teqo/tests/unit/agentPlanLifecycle.unit.spec.ts
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

89 lines
2.5 KiB
TypeScript

// @vitest-environment node
import { describe, expect, it } from 'vitest'
import {
canPromotePlanIssue,
resolveRegisterStateLabel,
} from '../../scripts/lib/agent-plan-lifecycle.mjs'
type TestIssue = {
number: number
title: string
body: string
state: string
labels: Array<{ name: string }>
}
const issue = (over: Partial<TestIssue> = {}): TestIssue => ({
number: 1,
title: 'Issue de teste',
body: 'Plano: [`docs/plans/x.md`](docs/plans/x.md)',
state: 'OPEN',
labels: [{ name: 'blocked' }, { name: 'prio:P2' }],
...over,
})
describe('resolveRegisterStateLabel', () => {
it('keeps chores without a plan as ready', () => {
expect(resolveRegisterStateLabel({ hasPlan: false })).toBe('ready')
})
it('starts plan-linked issues as blocked (OPS17)', () => {
expect(resolveRegisterStateLabel({ hasPlan: true })).toBe('blocked')
})
it('honors explicit --blocked even without a plan', () => {
expect(resolveRegisterStateLabel({ hasPlan: false, explicitBlocked: true })).toBe('blocked')
})
it('stays blocked when both --plan and --blocked are set', () => {
expect(resolveRegisterStateLabel({ hasPlan: true, explicitBlocked: true })).toBe('blocked')
})
})
describe('canPromotePlanIssue', () => {
it('accepts an open blocked issue with a docs/plans/ link', () => {
expect(canPromotePlanIssue(issue())).toEqual({ ok: true })
})
it('rejects closed issues', () => {
expect(canPromotePlanIssue(issue({ state: 'CLOSED' }))).toEqual({
ok: false,
reason: 'not-open',
})
})
it('rejects issues that are not blocked', () => {
expect(canPromotePlanIssue(issue({ labels: [{ name: 'ready' }] }))).toEqual({
ok: false,
reason: 'not-blocked',
})
})
it.each(['in-progress', 'done', 'in-prod'])(
'rejects when %s coexists with blocked',
(stateLabel) => {
expect(
canPromotePlanIssue(issue({ labels: [{ name: 'blocked' }, { name: stateLabel }] })),
).toEqual({ ok: false, reason: 'state-label' })
},
)
it('rejects human-gated blocked issues even when they link a plan', () => {
expect(
canPromotePlanIssue(
issue({
labels: [{ name: 'blocked' }, { name: 'needs:consent' }],
}),
),
).toEqual({ ok: false, reason: 'needs-human' })
})
it('rejects blocked issues without a plan link (product block, not awaiting plan)', () => {
expect(canPromotePlanIssue(issue({ body: 'bloqueio jurídico' }))).toEqual({
ok: false,
reason: 'no-plan-link',
})
})
})