teqo-backup/tests/unit/skillsAutoFlag.unit.spec.ts

72 lines
3.3 KiB
TypeScript

import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
import { describe, expect, it } from 'vitest'
// OPS108: pins the `--auto` autonomous-mode contract of the plan-issue and
// work-issue skills (and their thin command wrappers). The flag lives inside
// the prompt ($ARGUMENTS), not in the opencode CLI argv — the specs below pin
// the fail-safe wording (no flag = current supervised flow) and the hard-stop
// list that the flag can never cross.
const repoRoot = process.cwd()
const skills = ['plan-issue', 'work-issue'] as const
function readSkill(name: (typeof skills)[number]): string {
return readFileSync(resolve(repoRoot, `.agents/skills/${name}/SKILL.md`), 'utf8')
}
describe.each(skills)('skill /%s documents the --auto autonomous mode', (name) => {
it('declares the flag, the fail-safe and the CLI disambiguation', () => {
const content = readSkill(name)
expect(content, 'skill must declare the --auto flag').toContain('--auto')
expect(content, 'skill must name the autonomous-mode section').toContain('Modo autônomo')
expect(content, 'skill must state the no-flag fail-safe').toContain('Sem a flag')
expect(content, 'skill must disambiguate from the opencode CLI flag').toContain('Não confundir')
expect(content, 'disambiguation must name the opencode CLI').toContain('CLI opencode')
})
it('pins the hard-stop list the flag can never cross', () => {
const content = readSkill(name)
expect(content, 'hard-stop must cite Consent/LGPD').toContain('Consent/LGPD')
expect(content, 'hard-stop must cite schema migration').toContain('migração de schema')
expect(content, 'hard-stop must cite the public URL contract').toContain('URL público')
expect(content, 'hard-stop must cite production').toContain('produção')
})
})
describe('work-issue --auto keeps the environment contract', () => {
it('self-approves the impl plan but never claims and flips divergence to blocked', () => {
const content = readSkill('work-issue')
expect(content, 'autonomous impl plan must be self-approved').toContain('aprovado')
expect(content, 'autonomous mode must never claim an issue').toContain('nunca claima')
expect(content, 'material divergence must flip to blocked').toContain('blocked')
})
})
describe('plan-issue --auto keeps the tracker gate', () => {
it('skips only the pause and leaves diverged items unregistered', () => {
const content = readSkill('plan-issue')
expect(content, 'diverged items must stay unregistered').toContain('não é registrado')
expect(content, 'nothing hits the tracker before the gate').toContain(
'Nada no tracker antes do gate',
)
})
})
describe.each(skills)('command /%s advertises --auto without gaining logic', (name) => {
it('mentions --auto while keeping the thin-wrapper contract', () => {
const content = readFileSync(resolve(repoRoot, `.opencode/commands/${name}.md`), 'utf8')
expect(content, 'command must advertise the --auto flag').toContain('--auto')
expect(content, 'command must pass arguments through').toContain('$ARGUMENTS')
expect(content, 'command must reference the skill by exact name').toContain(`\`${name}\``)
expect(content, 'command must point at the canonical skill file').toContain(
`.agents/skills/${name}/SKILL.md`,
)
})
})