mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
OPS108 — Modo autônomo por flag --auto nas skills plan-issue e work-issue
This commit is contained in:
parent
a164961344
commit
46f659147d
7 changed files with 192 additions and 1 deletions
|
|
@ -122,6 +122,17 @@ Antes de criar Issues:
|
|||
|
||||
**Pare e espere.** Itere até confirmação explícita do lote.
|
||||
|
||||
## Modo autônomo (`--auto`)
|
||||
|
||||
Opt-out da pausa por invocação. Detecta-se em `$ARGUMENTS`: `/plan-issue --auto ...` (a flag vive dentro do prompt, junto dos demais argumentos; sem parser dedicado).
|
||||
|
||||
- **Sem a flag (ou flag desconhecida):** o Passo 4 GATE vale idêntico — pare e espere confirmação explícita. Nada no tracker antes do gate.
|
||||
- **Com a flag:** o Passo 4 vira apresentação-sem-pausa (o overview continua obrigatório, mas no resumo final, não como pedido de confirmação); o Passo 5 (registro) segue direto: `pnpm agent:register` por plano aprovado pelo próprio agente, PR `Related #N`, `pnpm agent:ready`.
|
||||
- **Pode auto-aprovar:** conteúdo e fatiamento dos planos, prioridade, dependências, abordagem de intenção, cortes de escopo já previstos na skill e os literais de dados que o próprio plano recomenda (registrados como assumidos).
|
||||
- **Continua parando (vale mesmo com a flag):** Consent/LGPD fail-closed, migração de schema, contrato de URL público, shapes públicos, produção/aprovação humana; divergência material de produto → o item **não é registrado** e fica fora do lote até decisão humana, reportado no resumo final.
|
||||
- **Não confundir:** `--auto` aqui é flag da skill dentro do prompt; o `--auto` do CLI opencode (auto-aprovar permissões de ferramenta) é outro conceito.
|
||||
- **Convivência:** `agent-work-issue` continua sendo o contrato do pool dormente; este modo é opt-in da sessão humana. Consolidação futura é item à parte.
|
||||
|
||||
## Passo 5 — Registro (sub-agente registrador)
|
||||
|
||||
Após confirmação, dispatche o sub-agente registrador com:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ disable-model-invocation: true
|
|||
|
||||
Executa uma Issue já claimada de ponta a ponta com supervisão humana. A sessão nasce no contrato: Issue claimada, worktree correto, branch correta.
|
||||
|
||||
**Proibido:** DB de prod; merge sem CI green; editar outras Issues `in-progress`; pular a pausa do impl plan; Draft / sem auto-merge.
|
||||
**Proibido:** DB de prod; merge sem CI green; editar outras Issues `in-progress`; pular a pausa do impl plan (exceto com `--auto`, ver §Modo autônomo); Draft / sem auto-merge.
|
||||
|
||||
## Decomposição em sub-agentes
|
||||
|
||||
|
|
@ -133,6 +133,17 @@ Apresente no chat:
|
|||
|
||||
Divergência material de produto → pare, pergunte ao humano.
|
||||
|
||||
## Modo autônomo (`--auto`)
|
||||
|
||||
Opt-out da pausa por invocação. Detecta-se em `$ARGUMENTS`: `/work-issue --issue <N> --auto` (a flag vive dentro do prompt, junto do `--issue <N>` do contrato OPS33; sem parser dedicado).
|
||||
|
||||
- **Sem a flag (ou flag desconhecida):** o Passo 3c GATE vale idêntico — apresente o plano, pare e aguarde confirmação explícita. Proibido pular a pausa.
|
||||
- **Com a flag:** o impl plan do Passo 3b nasce marcado `aprovado` pelo próprio agente; o Passo 3c vira apresentação-no-chat-sem-espera (abordagem + rejeitadas + fases + riscos continuam obrigatórios no chat e no arquivo) e a execução (Passo 4) segue direto até o PR.
|
||||
- **Pode auto-aprovar:** abordagem técnica, cortes de escopo já previstos na skill e os literais de dados que o próprio plano recomenda (registrados como assumidos).
|
||||
- **Continua parando (vale mesmo com a flag):** Consent/LGPD fail-closed, migração de schema, contrato de URL público, shapes públicos, produção/aprovação humana, merge sem CI green, DB de prod; divergência material de produto → pare, comente na Issue e flipe para `blocked` (precedente do fluxo autônomo). O claim continua contrato do ambiente: este modo nunca claima Issue.
|
||||
- **Não confundir:** `--auto` aqui é flag da skill dentro do prompt; o `--auto` do CLI opencode (auto-aprovar permissões de ferramenta) é outro conceito.
|
||||
- **Convivência:** `agent-work-issue` continua sendo o contrato do pool dormente; este modo é opt-in da sessão humana. Consolidação futura é item à parte.
|
||||
|
||||
## Passo 4 — Executar
|
||||
|
||||
`SwitchMode` → `agent`. Siga `execution-pipeline.md`:
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ description: Transforma ideias humanas em Issues GitHub + planos de intenção e
|
|||
|
||||
Carregue a skill `plan-issue` (ferramenta de skills, nome exato) e siga o fluxo dela de ponta a ponta. A fonte canônica é `.agents/skills/plan-issue/SKILL.md` — não a transcreva nem recrie o fluxo.
|
||||
|
||||
Uso: /plan-issue [--auto] [...ideias]. Com `--auto`, a skill dispensa a pausa do GATE e segue até o registro; sem ela, o fluxo supervisionado atual vale.
|
||||
|
||||
$ARGUMENTS
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ description: Executa uma Issue já claimada de ponta a ponta com supervisão hum
|
|||
|
||||
Carregue a skill `work-issue` (ferramenta de skills, nome exato) e siga o fluxo dela de ponta a ponta. A fonte canônica é `.agents/skills/work-issue/SKILL.md` — não a transcreva nem recrie o fluxo.
|
||||
|
||||
Uso: /work-issue --issue <N> [--auto]. Com `--auto`, a skill marca o impl plan como aprovado e executa até o PR sem pausa; sem ela, a pausa do GATE vale.
|
||||
|
||||
$ARGUMENTS
|
||||
|
|
|
|||
1
docs/changelog/2026-09-15-ops108.md
Normal file
1
docs/changelog/2026-09-15-ops108.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
**OPS108 — Modo autônomo por flag nas skills plan-issue e work-issue (2026-09-15):** as duas skills ganham opt-out da pausa por invocação via flag única `--auto` (dentro do prompt, ex. `/work-issue --issue 1018 --auto`); sem a flag, os GATEs atuais valem idênticos. Com a flag, `plan-issue` registra sem confirmação (divergência material → item fora do lote) e `work-issue` marca o impl plan como aprovado e executa até o PR (divergência → `blocked`, nunca claima). A flag nunca atravessa os invariantes duros (Consent/LGPD fail-closed, migração de schema, URL público, shapes públicos, produção, CI green). Os dois comandos viram a flag numa linha de uso sem ganhar lógica (guard OPS25 intacto); o texto desambigua do `--auto` do CLI opencode. Testes: novo `skillsAutoFlag.unit.spec.ts` (8 testes pinando flag, fail-safe, lista dura e contrato thin-wrapper); suite unit 3075 verde, lint/typecheck/format limpos.
|
||||
92
docs/plans/ops108-modo-autonomo-por-flag-impl.md
Normal file
92
docs/plans/ops108-modo-autonomo-por-flag-impl.md
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
# Impl: OPS108 — Modo autônomo por flag nas skills plan-issue e work-issue
|
||||
|
||||
Status: aprovado
|
||||
Atualizado em: 2026-09-15
|
||||
Issue: #1018
|
||||
Intenção: docs/plans/ops108-modo-autonomo-por-flag.md
|
||||
Appetite restante: herdado (~0,5–1 dia eng; só texto de skills/comandos + teste unit)
|
||||
|
||||
## Leitura da intenção
|
||||
|
||||
- **Outcome:** com `--auto`, `plan-issue` vai do overview ao registro e `work-issue` vai do impl plan ao PR **sem** pausa de confirmação; sem a flag, os GATEs atuais permanecem idênticos.
|
||||
- **O que NÃO negociar:** a pausa continua default (opt-in por invocação); a flag nunca atravessa os invariantes duros (Consent/LGPD fail-closed, migração de schema, contrato de URL público, shapes públicos, aprovação humana de produção); divergência material de produto continua parando (work-issue → `blocked`; plan-issue → item fora do lote); claim continua contrato do ambiente (`work-issue --auto` nunca claima); sem CI green não mergea; comandos continuam wrappers finos (guard OPS25).
|
||||
- **O que reavaliar:** a hipótese de direção ("a flag viaja no texto já repassado hoje") está correta — `$ARGUMENTS` já carrega `--issue <N>` por convenção de prompt, sem parser; `--auto` segue o mesmo caminho. Confirmado: `scripts/lib/worktree.mjs:207-232` monta `--prompt "/work-issue --issue N"` (a flag da skill vive **dentro** da string do prompt, não no argv do CLI).
|
||||
|
||||
## Abordagem recomendada
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["/plan-issue --auto ou /work-issue --issue N --auto"] --> B["skill detecta --auto em $ARGUMENTS"]
|
||||
B -->|"sem flag"| C["GATE atual idêntico (pausa)"]
|
||||
B -->|"com flag"| D["auto-aprova recomendação própria, segue até registro/PR"]
|
||||
D --> E["parada dura? → para e reporta (blocked/fora do lote)"]
|
||||
```
|
||||
|
||||
**Opções consideradas:** A | B | C (por decisão abaixo)
|
||||
**Recomendação:** semântica espelhada mínima em cada `SKILL.md` + uma linha de descobribilidade em cada comando + spec unit que pina o novo texto.
|
||||
**Rejeitadas:** ver cada decisão.
|
||||
|
||||
### Decisões de engenharia
|
||||
|
||||
**D1 — Onde vive a semântica da flag.**
|
||||
Opções: A) bloco compartilhado novo referenciado pelas duas skills · B) seção dedicada espelhada em cada `SKILL.md` · C) só nos comandos.
|
||||
Recomendação: B — cada skill é dona do próprio GATE (`plan-issue` Passo 4, `work-issue` Passo 3c), e skills são fonte canônica autocontida (sub-agentes recebem contexto mínimo); ~15 linhas espelhadas, cada uma redigida na voz do próprio GATE.
|
||||
Alternativas rejeitadas: A porque um include cross-skill cria indireção e acoplamento para um texto curto que precisa ser lido inline no momento do gate; C porque comandos são proibidos de transcrever fluxo (guard OPS25 — `opencodeCommands.unit.spec.ts`).
|
||||
|
||||
**D2 — Como os comandos expõem `--auto` sem ganhar lógica.**
|
||||
Opções: A) só no `description` do frontmatter · B) uma linha de uso no corpo, mantendo `$ARGUMENTS` + ponteiro canônico · C) nada nos comandos.
|
||||
Recomendação: B — ex. `Uso: /work-issue --issue <N> [--auto]` + frase de uma linha ("`--auto` dispensa a pausa do GATE; sem ela, o fluxo supervisionado atual vale"). O corpo continua sem transcrever o fluxo.
|
||||
Alternativas rejeitadas: A porque `description` é curta (TUI) e não comporta semântica nem desambiguação; C porque a flag ficaria indescobrível no prompt `/`.
|
||||
|
||||
**D3 — Desambiguação `--auto` da skill vs `--auto` do CLI opencode.**
|
||||
Opções: A) nota explícita de uma frase em cada skill (e eco curto nos comandos) · B) renomear a flag (ex. `--autonomous`) · C) ignorar a colisão.
|
||||
Recomendação: A — a intenção já decidiu `--auto` (gate 2026-09-15); o texto diz: "`--auto` aqui é flag da skill dentro do prompt (ex. `/work-issue --issue 1018 --auto`); não confundir com `--auto` do CLI opencode (auto-aprovar permissões de ferramenta, ex. `launch opencode … --auto --prompt …` em `scripts/lib/worktree.mjs:218`)".
|
||||
Alternativas rejeitadas: B porque reabre decisão de produto fechada e quebra a simetria `--issue`/`--auto` no mesmo canal (`$ARGUMENTS`); C porque a colisão é real e já pinada em teste (`worktree.unit.spec.ts:164-277`) — silêncio geraria invocações erradas.
|
||||
|
||||
**D4 — Questões em aberto da intenção (assumidos).**
|
||||
Opções (divergência no `plan-issue` autônomo): A) não registra, reporta no resumo · B) registra `blocked`.
|
||||
Recomendação: A — preserva "nada no tracker antes do gate"; o item volta barato quando o humano decidir.
|
||||
Opções (`work-issue --auto` vs `agent-work-issue`): A) separados neste item · B) consolidar.
|
||||
Recomendação: A — contratos diferentes (sessão humana opt-in vs pool dormente); convivência documentada numa frase em cada skill; consolidação é item futuro.
|
||||
|
||||
### Componentes / mudanças
|
||||
|
||||
- **`plan-issue/SKILL.md`** (`.agents/skills/plan-issue/SKILL.md`): nova seção "Modo autônomo (`--auto`)": detecção em `$ARGUMENTS`; Passo 4 GATE vira apresentação-sem-pausa (overview continua obrigatório no resumo); registro segue Passo 5 sem confirmação; lista fechada do que pode auto-aprovar vs parada dura (cópia das listas da intenção); divergência material → item fora do lote + resumo final; fail-safe ("flag ausente/desconhecida → GATE idêntico"); nota de desambiguação CLI; frase de convivência com `agent-work-issue`.
|
||||
- **`work-issue/SKILL.md`** (`.agents/skills/work-issue/SKILL.md`): nova seção "Modo autônomo (`--auto`)": parsing em Passo 1 (`--auto` em `$ARGUMENTS`, ex. `/work-issue --issue 1018 --auto`); Passo 3b marca impl plan `aprovado` sem pausa; Passo 3c vira apresentação-no-chat-sem-espera; "Proibido" ganha exceção explícita ("pular a pausa do impl plan" continua proibido, exceto com `--auto` — todo o resto do Proibido intocado, inclusive nunca claimar); mesmas listas fechadas; divergência → `blocked` (precedente `agent-work-issue`); fail-safe; desambiguação CLI.
|
||||
- **Comandos** (`.opencode/commands/plan-issue.md`, `work-issue.md`): +1 linha de uso com `[--auto]` + 1 frase (dispensa a pausa; aponta a skill como canônica). `$ARGUMENTS`, `` `nome` ``, ponteiro canônico e frontmatter `description` sem `model:` preservados — guard existente continua verde.
|
||||
- **Migration:** sem migration (só markdown).
|
||||
- **Access / Consent:** N/A (sem superfície de dados); as listas de parada dura citam Consent fail-closed sem tocá-lo.
|
||||
- **UI:** Impeccable A — sem UI, sem rascunho.
|
||||
- **Testes:** novo `tests/unit/skillsAutoFlag.unit.spec.ts` pinando o contrato textual: cada `SKILL.md` contém `--auto` + menção de parada dura (Consent/LGPD, migração, URL público, produção) + frase fail-safe ("sem a flag"); cada comando contém `--auto` + `$ARGUMENTS` + ponteiro canônico. Guard `opencodeCommands.unit.spec.ts` existente deve continuar verde sem edição (se exigir ajuste, o ajuste é no comando, não no guard).
|
||||
|
||||
### Dados → forma (se aplicável)
|
||||
|
||||
N/A — sem superfície de dados (intenção: "Dados: N/A").
|
||||
|
||||
## Fases verificáveis
|
||||
|
||||
1. **Tracer / texto+teste** (quota: quase todo o appetite) — editar 2 `SKILL.md` + 2 comandos + criar `skillsAutoFlag.unit.spec.ts`; rodar `pnpm vitest run tests/unit/skillsAutoFlag.unit.spec.ts tests/unit/opencodeCommands.unit.spec.ts`; depois `pnpm gate:fast`.
|
||||
2. **UI** — N/A (Impeccable A).
|
||||
3. **Gates** — `pnpm gate:fast` na iteração; entrega com `pnpm push` (não `git push` nu). E2E: nenhum (sem superfície de produto; skill-docs não entram no `E2E_AFFECTED_MANIFEST`). Int: nenhum (sem DB).
|
||||
|
||||
## Rabbit holes / Não escopo (engenharia)
|
||||
|
||||
- Renomear a flag ou ler `--auto` do argv do CLI (a flag mora no prompt `$ARGUMENTS`, não no argv — `worktree.mjs:218` é outro `--auto`).
|
||||
- Lógica nos comandos (quebra OPS25) ou skill gêmea "autônoma" (twin = drift; intenção corta).
|
||||
- Puxar claim/pool/launch de worktree para a skill (contrato do ambiente; `worktree.mjs:207-232` intocado).
|
||||
- Tocar `agent-work-issue`, `AGENT-OPS.md`, `engineering-audit` ou `E2E_AFFECTED_MANIFEST` (fora do escopo fechado: 2 skills + 2 comandos + 1 spec).
|
||||
- Quoting: exemplos com aspas no prompt passam por xargs no launch — manter exemplos simples, sem aspas aninhadas.
|
||||
|
||||
## Riscos e mitigação
|
||||
|
||||
- **Colisão mental `--auto` skill vs CLI** → mitigado pela nota de desambiguação (D3) + exemplo canônico `/work-issue --issue 1018 --auto` nos dois lugares.
|
||||
- **Bypass acidental de invariante** → mitigado pelas listas fechadas duplicadas (auto-aprovável vs parada dura) + fail-safe + spec que pina a menção de parada dura.
|
||||
- **Drift com `agent-work-issue`** → mitigado pela frase de convivência (D4-A); sem edição no contrato do pool.
|
||||
- **Sub-agente escritor indisponível** (falhou 2x nesta sessão com erro transitório do provider) → mitigado: plano escrito inline pelo agente principal a partir dos findings do explorador + leitura direta dos arquivos; registrar no resumo.
|
||||
|
||||
## Aceite de engenharia
|
||||
|
||||
- [ ] Aceite de produto da intenção ainda coberto (flag opt-out só da pausa; listas fechadas; fail-safe; claim/CI/produção intocados)
|
||||
- [ ] Invariantes AGENTS/engineering-standards (edit the owner, don't twin; comandos finos; copy pt-BR / identificadores em inglês)
|
||||
- [ ] Testes de domínio previstos (unit textual do contrato; sem access/write paths — sem unit/int de domínio)
|
||||
- [ ] Self-score decision-quality: 5/5 (caras com rejeitadas: D1–D4; cabe no appetite; rabbit holes nomeados; depth check: zero módulo novo, reuso dos donos; outcome da intenção intacto)
|
||||
72
tests/unit/skillsAutoFlag.unit.spec.ts
Normal file
72
tests/unit/skillsAutoFlag.unit.spec.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
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`,
|
||||
)
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue