Workflows nativos em .forgejo/workflows/ (ci, ci-pr, agent-pool, automerge, issue-transition, plan-issue, vercel-promote, archive), removendo .github/workflows e .github/actions. Runner Forgejo v13 com services Postgres por porta + DB_HOST via gateway do bridge. Libs de agente sobre o novo cliente forgejo-api.mjs (zero dependências, GITHUB_SERVER_URL/FORGEJO_API_URL), helpers de workflow plain-Node. pnpm issue corrigido (await em função sync) e validado ao vivo. Testes: forgejoApi.unit.spec.ts novo, pin do matrix do ci.yml atualizado. Closes #1 (parte 1 — docs/issues/pool seguem na parte 2)
78 lines
2.5 KiB
JavaScript
78 lines
2.5 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, issuesById, parseArgs, serializeFrontmatter } from './lib/agent-forgejo.mjs'
|
|
import { resolveRegisterStateLabel } from './lib/agent-plan-lifecycle.mjs'
|
|
import { forgejoApi as api } from './lib/forgejo-api.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 = (await 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 created = await api.createIssue({
|
|
title: `${flags.id} — ${flags.title}`,
|
|
body,
|
|
})
|
|
await api.setLabels(created.number, { add: labels })
|
|
const url = `https://git.solla.dev/fsolla/teqo/issues/${created.number}`
|
|
|
|
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}`)
|