teqo/scripts/agent-register.mjs
Cursor Agent d2cc1d2693
feat(ops): OPS17 — plan-issue blocked até plano em main
Register com --plan nasce blocked (não claimável); pnpm agent:ready
promove após o plano em main. Gate da skill plan-issue endurecido.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:06:14 +00:00

80 lines
2.4 KiB
JavaScript

/**
* `pnpm agent:register` — create a trackable issue (spec + prio + deps).
*
* pnpm agent:register -- --id B91 --title "Ações rápidas — X" \
* --prio P1 --depends B79 --kind feature --plan docs/plans/x.md [--body "..."]
*
* Body = frontmatter (id/depends/priority) + spec (linked plan + --body text).
* Starts life labeled `ready`, or `blocked` when `--blocked` / `--plan`
* (OPS17: plan-linked Issues are not claimable until the plan is on `main`
* and `pnpm agent:ready` promotes them).
*/
import { dieAgent, gh, issuesById, parseArgs, serializeFrontmatter } from './lib/agent-github.mjs'
import { resolveRegisterStateLabel } from './lib/agent-plan-lifecycle.mjs'
const die = dieAgent('register')
const { flags } = parseArgs(
process.argv.slice(2),
new Set(['id', 'title', 'prio', 'depends', 'kind', 'plan', 'body', 'labels', 'model']),
)
if (!flags.id || !flags.title)
die(
'Usage: pnpm agent:register -- --id <ID> --title <title> [--prio P2] [--depends A,B] [--kind feature] [--plan path] [--body text] [--labels extra,labels] [--model slug] [--blocked]',
)
const priority = /^P[0-3]$/.test(flags.prio ?? 'P2')
? (flags.prio ?? 'P2')
: die(`Invalid --prio "${flags.prio}" (P0..P3).`)
const depends = (flags.depends ?? '')
.split(',')
.map((v) => v.trim())
.filter(Boolean)
const existing = issuesById().get(flags.id)
if (existing)
die(`An issue with id ${flags.id} already exists: #${existing.number} — ${existing.title}`)
const body = serializeFrontmatter(
{
id: flags.id,
depends,
serializes: [],
priority,
...(flags.model ? { model: flags.model } : {}),
},
[flags.plan ? `Plano: [\`${flags.plan}\`](${flags.plan})` : null, flags.body ?? '']
.filter((chunk) => chunk !== null)
.join('\n\n'),
)
const stateLabel = resolveRegisterStateLabel({
hasPlan: Boolean(flags.plan),
explicitBlocked: Boolean(flags.blocked),
})
const labels = [
stateLabel,
`prio:${priority}`,
`kind:${flags.kind ?? 'feature'}`,
...(flags.labels ?? '')
.split(',')
.map((v) => v.trim())
.filter(Boolean),
]
const url = gh([
'issue',
'create',
'--title',
`${flags.id} — ${flags.title}`,
'--body',
body,
...labels.flatMap((label) => ['--label', label]),
])
const hint =
stateLabel === 'blocked' && flags.plan && !flags.blocked
? ' (blocked até plano em main — depois: pnpm agent:ready -- --issue <N>)'
: ''
console.log(`[agent:register] created ${url}${hint}`)