@brunosps00/dev-workflow 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -0
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +104 -0
- package/README.md +6 -4
- package/lib/build-plugin.js +4 -1
- package/lib/constants.js +4 -2
- package/lib/validate.js +21 -0
- package/package.json +1 -1
- package/scaffold/en/commands/dw-brainstorm.md +12 -8
- package/scaffold/en/commands/dw-bugfix.md +4 -2
- package/scaffold/en/commands/dw-plan.md +2 -2
- package/scaffold/en/commands/dw-refactor.md +1 -0
- package/scaffold/en/commands/dw-review.md +33 -2
- package/scaffold/en/commands/dw-run.md +1 -0
- package/scaffold/en/commands/dw-triage.md +220 -0
- package/scaffold/en/templates/idea-onepager.md +28 -0
- package/scaffold/en/templates/task-template.md +1 -0
- package/scaffold/en/templates/tasks-template.md +9 -8
- package/scaffold/en/templates/triage-needs-info-template.md +23 -0
- package/scaffold/en/templates/triage-out-of-scope-template.md +36 -0
- package/scaffold/en/templates/triage-record-template.md +88 -0
- package/scaffold/pt-br/commands/dw-autopilot.md +81 -81
- package/scaffold/pt-br/commands/dw-brainstorm.md +12 -9
- package/scaffold/pt-br/commands/dw-bugfix.md +4 -2
- package/scaffold/pt-br/commands/dw-claude-run.md +19 -19
- package/scaffold/pt-br/commands/dw-codex-run.md +19 -19
- package/scaffold/pt-br/commands/dw-context-budget.md +10 -10
- package/scaffold/pt-br/commands/dw-copilot-run.md +20 -20
- package/scaffold/pt-br/commands/dw-dockerize.md +102 -102
- package/scaffold/pt-br/commands/dw-find-skills.md +52 -52
- package/scaffold/pt-br/commands/dw-goal.md +41 -41
- package/scaffold/pt-br/commands/dw-harness-audit.md +11 -11
- package/scaffold/pt-br/commands/dw-intel.md +70 -70
- package/scaffold/pt-br/commands/dw-learn.md +24 -24
- package/scaffold/pt-br/commands/dw-new-project.md +88 -88
- package/scaffold/pt-br/commands/dw-open-design.md +53 -53
- package/scaffold/pt-br/commands/dw-opportunities.md +45 -45
- package/scaffold/pt-br/commands/dw-pause.md +39 -39
- package/scaffold/pt-br/commands/dw-plan.md +2 -2
- package/scaffold/pt-br/commands/dw-refactor.md +31 -30
- package/scaffold/pt-br/commands/dw-resume.md +22 -22
- package/scaffold/pt-br/commands/dw-review.md +33 -2
- package/scaffold/pt-br/commands/dw-run.md +1 -0
- package/scaffold/pt-br/commands/dw-skill-health.md +10 -10
- package/scaffold/pt-br/commands/dw-subtask-complete.md +4 -4
- package/scaffold/pt-br/commands/dw-subtask-start.md +4 -4
- package/scaffold/pt-br/commands/dw-triage.md +220 -0
- package/scaffold/pt-br/templates/bugfix-summary-template.md +20 -20
- package/scaffold/pt-br/templates/concerns-template.md +20 -20
- package/scaffold/pt-br/templates/idea-onepager.md +28 -0
- package/scaffold/pt-br/templates/project-onepager.md +32 -32
- package/scaffold/pt-br/templates/state-template.md +13 -13
- package/scaffold/pt-br/templates/task-template.md +1 -0
- package/scaffold/pt-br/templates/tasks-template.md +9 -8
- package/scaffold/pt-br/templates/triage-needs-info-template.md +23 -0
- package/scaffold/pt-br/templates/triage-out-of-scope-template.md +36 -0
- package/scaffold/pt-br/templates/triage-record-template.md +88 -0
- package/scaffold/scripts/hooks/git-guardrails.mjs +41 -24
- package/scaffold/skills/dw-debug-protocol/SKILL.md +2 -0
- package/scaffold/skills/dw-debug-protocol/references/six-step-triage.md +60 -1
- package/scaffold/skills/dw-execute-phase/references/wave-coordination.md +14 -14
- package/scaffold/skills/dw-grilling/SKILL.md +17 -7
- package/scaffold/skills/dw-grilling/references/decision-tree.md +30 -7
- package/scaffold/skills/dw-simplification/references/deep-modules.md +50 -0
- package/scaffold/skills/dw-testing-discipline/SKILL.md +3 -1
- package/scaffold/skills/dw-testing-discipline/references/tdd-loop.md +83 -0
|
@@ -4,51 +4,51 @@ last_paused: ""
|
|
|
4
4
|
last_resumed: ""
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Estado da
|
|
7
|
+
# Estado da Sessão
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Memória de trabalho entre sessões. Índice leve do que está em andamento, do que foi decidido, do que ficou parado. Atualizado por `/dw-pause` (consolida) e lido por `/dw-resume` (orienta).
|
|
10
10
|
|
|
11
|
-
Diferente do `MEMORY.md` por-PRD (
|
|
11
|
+
Diferente do `MEMORY.md` por-PRD (memória de workflow para uma feature) ou dos ADRs (decisões arquiteturais duráveis), este arquivo vive no nível do projeto e sobrevive entre PRDs, branches e sessões. Edite livremente entre pausas.
|
|
12
12
|
|
|
13
13
|
## Open Loops (Pontas Soltas)
|
|
14
14
|
|
|
15
|
-
O que
|
|
15
|
+
O que está em andamento — trabalho começado mas não terminado. Cada entrada: label curto + path/alvo + próxima ação concreta.
|
|
16
16
|
|
|
17
17
|
- _nenhum_
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Decisões
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Decisões transversais que ainda não viraram ADR (porque não justificam um, ou porque a formalização foi adiada). Formato: `YYYY-MM-DD — decisao — contexto (1 linha)`.
|
|
22
22
|
|
|
23
23
|
- _nenhuma_
|
|
24
24
|
|
|
25
25
|
## Bloqueios
|
|
26
26
|
|
|
27
|
-
O que
|
|
27
|
+
O que está impedindo o avanço. Externo (esperando alguém), interno (lacuna de conhecimento) ou técnico (tooling quebrado). Cada entrada: label curto + o que está bloqueado + dono / condição de desbloqueio.
|
|
28
28
|
|
|
29
29
|
- _nenhum_
|
|
30
30
|
|
|
31
31
|
## Todos
|
|
32
32
|
|
|
33
|
-
Pequenos follow-ups que
|
|
33
|
+
Pequenos follow-ups que não justificam um PRD ou task. Uma linha cada. Limpe conforme forem feitos ou migrados para um PRD.
|
|
34
34
|
|
|
35
35
|
- _nenhum_
|
|
36
36
|
|
|
37
37
|
## Ideias Adiadas
|
|
38
38
|
|
|
39
|
-
Ideias consideradas mas parqueadas. Capture para
|
|
39
|
+
Ideias consideradas mas parqueadas. Capture para não perder; revisite quando o escopo mudar. Cada entrada: ideia + motivo do park + trigger de revisita (se conhecido).
|
|
40
40
|
|
|
41
41
|
- _nenhuma_
|
|
42
42
|
|
|
43
|
-
##
|
|
43
|
+
## Lições
|
|
44
44
|
|
|
45
|
-
Pequenas
|
|
45
|
+
Pequenas lições aprendidas no trabalho recente — padrões que funcionaram, pegadinhas, "da próxima vez eu...". Não são arquiteturais (essas vão para ADRs); são operacionais.
|
|
46
46
|
|
|
47
47
|
- _nenhuma_
|
|
48
48
|
|
|
49
|
-
##
|
|
49
|
+
## Preferências
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Convenções acordadas durante o trabalho que afetam como o agent deve se comportar dali em diante. Exemplos: "sempre rodar `pnpm typecheck` antes do commit", "preferir named exports a default exports em utils".
|
|
52
52
|
|
|
53
53
|
- _nenhuma_
|
|
54
54
|
|
|
@@ -19,19 +19,20 @@ feat/prd-[nome-funcionalidade]
|
|
|
19
19
|
|
|
20
20
|
## Tarefas
|
|
21
21
|
|
|
22
|
-
| Task | Descrição | RFs | Status | Commit |
|
|
23
|
-
|
|
24
|
-
| 1.0 | [Título] | RF-1.1, RF-1.2 | Pendente | — |
|
|
25
|
-
| 2.0 | [Título] | RF-2.1 | Pendente | — |
|
|
26
|
-
| 3.0 | [Título] | RF-3.1, RF-3.2 | Pendente | — |
|
|
22
|
+
| Task | Descrição | Depends on | RFs | Status | Commit |
|
|
23
|
+
|------|-----------|------------|-----|--------|--------|
|
|
24
|
+
| 1.0 | [Título] | none | RF-1.1, RF-1.2 | Pendente | — |
|
|
25
|
+
| 2.0 | [Título] | 1.0 | RF-2.1 | Pendente | — |
|
|
26
|
+
| 3.0 | [Título] | 1.0, 2.0 | RF-3.1, RF-3.2 | Pendente | — |
|
|
27
27
|
|
|
28
28
|
`Commit` guarda o SHA curto escrito de volta pelo `/dw-run` quando a task fecha (passo 6). É o que torna o diff da task localizável depois — deixe `—` até a task commitar.
|
|
29
|
+
`Depends on` é o grafo de dependência consumido pelo `/dw-run`; escreva `none` quando uma task não tiver dependência.
|
|
29
30
|
|
|
30
31
|
## Progresso
|
|
31
32
|
|
|
32
|
-
- [ ] 1.0 Título da Tarefa Principal
|
|
33
|
-
- [ ] 2.0 Título da Tarefa Principal
|
|
34
|
-
- [ ] 3.0 Título da Tarefa Principal
|
|
33
|
+
- [ ] 1.0 Título da Tarefa Principal Depends on: none
|
|
34
|
+
- [ ] 2.0 Título da Tarefa Principal Depends on: 1.0
|
|
35
|
+
- [ ] 3.0 Título da Tarefa Principal Depends on: 1.0, 2.0
|
|
35
36
|
|
|
36
37
|
## Workflow
|
|
37
38
|
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Needs Info: <título>
|
|
2
|
+
|
|
3
|
+
## Perguntas Bloqueantes
|
|
4
|
+
|
|
5
|
+
- [ ] <pergunta 1>
|
|
6
|
+
- [ ] <pergunta 2>
|
|
7
|
+
- [ ] <pergunta 3>
|
|
8
|
+
|
|
9
|
+
## Por Que Isto Bloqueia a Triagem
|
|
10
|
+
|
|
11
|
+
<Explique por que a informação ausente impede confiança na categoria/estado ou na verificação.>
|
|
12
|
+
|
|
13
|
+
## Resposta do Autor
|
|
14
|
+
|
|
15
|
+
<Cole ou resuma a resposta do autor. Quando o autor responder, mova o estado de triagem de `needs-info` para `needs-triage` e rode novamente a etapa de recomendação.>
|
|
16
|
+
|
|
17
|
+
## Evidência Solicitada
|
|
18
|
+
|
|
19
|
+
- Passos de reprodução:
|
|
20
|
+
- Comportamento esperado vs atual:
|
|
21
|
+
- Ambiente ou massa de teste:
|
|
22
|
+
- PR diff ou branch/ref:
|
|
23
|
+
- Screenshots/logs/traces:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: out-of-scope
|
|
3
|
+
schema_version: "1.0"
|
|
4
|
+
concept: "<concept-slug>"
|
|
5
|
+
created_at: "YYYY-MM-DD"
|
|
6
|
+
updated_at: "YYYY-MM-DD"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Fora de Escopo: <Nome do Conceito>
|
|
10
|
+
|
|
11
|
+
## Decisão
|
|
12
|
+
|
|
13
|
+
Rejeitado em YYYY-MM-DD.
|
|
14
|
+
|
|
15
|
+
## Motivo
|
|
16
|
+
|
|
17
|
+
<Registre o motivo durável. Não escreva apenas "wontfix"; explique a fronteira de produto, técnica, operacional ou de política.>
|
|
18
|
+
|
|
19
|
+
## Aplica-se A
|
|
20
|
+
|
|
21
|
+
- <Formulação de domínio dos pedidos que esta decisão cobre>
|
|
22
|
+
- <Redações alternativas conhecidas que mapeiam para o mesmo conceito>
|
|
23
|
+
|
|
24
|
+
## Evidência
|
|
25
|
+
|
|
26
|
+
- Registro de triagem: `.dw/triage/NNN-<slug>.md`
|
|
27
|
+
- Busca no codebase:
|
|
28
|
+
- Decisões anteriores:
|
|
29
|
+
|
|
30
|
+
## Condições de Reabertura
|
|
31
|
+
|
|
32
|
+
<O que precisaria mudar para este conceito ser reconsiderado?>
|
|
33
|
+
|
|
34
|
+
## Histórico
|
|
35
|
+
|
|
36
|
+
- YYYY-MM-DD — rejected — <actor> — <reason>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: triage-record
|
|
3
|
+
schema_version: "1.0"
|
|
4
|
+
id: "NNN-<slug>"
|
|
5
|
+
category: "bug | enhancement"
|
|
6
|
+
state: "needs-triage | needs-info | ready-for-work | needs-human | wontfix"
|
|
7
|
+
created_at: "YYYY-MM-DD"
|
|
8
|
+
updated_at: "YYYY-MM-DD"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Triagem: <título>
|
|
12
|
+
|
|
13
|
+
## Fonte
|
|
14
|
+
|
|
15
|
+
| Campo | Valor |
|
|
16
|
+
|-------|-------|
|
|
17
|
+
| Tipo de Fonte | paste / file / github-issue / github-pr / other |
|
|
18
|
+
| Referência da Fonte | <caminho, URL, número de issue, número de PR, ou marcador de sessão colada> |
|
|
19
|
+
| Autor | <nome ou desconhecido> |
|
|
20
|
+
| Reportado em | <data ou desconhecida> |
|
|
21
|
+
| Recuperado por | local / gh / pasted / owner-provided |
|
|
22
|
+
|
|
23
|
+
## Resumo de Intake
|
|
24
|
+
|
|
25
|
+
<Resumo curto do pedido em linguagem de domínio.>
|
|
26
|
+
|
|
27
|
+
## Classificação
|
|
28
|
+
|
|
29
|
+
| Campo | Valor |
|
|
30
|
+
|-------|-------|
|
|
31
|
+
| Categoria | bug / enhancement |
|
|
32
|
+
| Estado | needs-triage / needs-info / ready-for-work / needs-human / wontfix |
|
|
33
|
+
| Conceito de Domínio | <slug do conceito e nome humano> |
|
|
34
|
+
| Motivo do Desfecho | <por que este estado foi escolhido> |
|
|
35
|
+
|
|
36
|
+
## Checks do Codebase
|
|
37
|
+
|
|
38
|
+
### Busca de Redundância
|
|
39
|
+
|
|
40
|
+
| Área Pesquisada | Query / Conceito | Resultado |
|
|
41
|
+
|-----------------|------------------|-----------|
|
|
42
|
+
| `.dw/domain/**` | <concept> | <match / no match / missing> |
|
|
43
|
+
| `.dw/spec/**` | <concept> | <match / no match / missing> |
|
|
44
|
+
| `.dw/bugfixes/**` | <concept> | <match / no match / missing> |
|
|
45
|
+
| `.dw/rules/**` | <concept> | <match / no match / missing> |
|
|
46
|
+
| Código / testes / docs | <concept> | <match / no match> |
|
|
47
|
+
|
|
48
|
+
### Busca de Rejeição Anterior
|
|
49
|
+
|
|
50
|
+
| Registro | Similaridade | Decisão |
|
|
51
|
+
|----------|--------------|---------|
|
|
52
|
+
| `.dw/out-of-scope/<concept>.md` | <por que é similar> | aplica / não aplica / reaberta |
|
|
53
|
+
|
|
54
|
+
## Verificação
|
|
55
|
+
|
|
56
|
+
| Campo | Valor |
|
|
57
|
+
|-------|-------|
|
|
58
|
+
| Status da Verificação | confirmed / failed-to-reproduce / insufficient-detail |
|
|
59
|
+
| Método de Verificação | passos de reprodução / revisão do diff do PR / testes relevantes / check de inventário de produto |
|
|
60
|
+
| Comandos Rodados | <comandos ou n/a> |
|
|
61
|
+
| Arquivos Inspecionados | <caminhos> |
|
|
62
|
+
| Evidência | <o que foi observado> |
|
|
63
|
+
|
|
64
|
+
## Needs Info
|
|
65
|
+
|
|
66
|
+
<!-- Se o estado for needs-info, cole aqui o corpo de triage-needs-info-template.md. Caso contrário, escreva "n/a". -->
|
|
67
|
+
|
|
68
|
+
n/a
|
|
69
|
+
|
|
70
|
+
## Roteamento
|
|
71
|
+
|
|
72
|
+
| Condição | Rota |
|
|
73
|
+
|----------|------|
|
|
74
|
+
| ready-for-work + bug | `/dw-bugfix` |
|
|
75
|
+
| ready-for-work + enhancement | `/dw-plan prd` |
|
|
76
|
+
| pedido malformado | `/dw-brainstorm --mode=grill` |
|
|
77
|
+
| needs-human | ação do dono |
|
|
78
|
+
| wontfix | sem trabalho downstream |
|
|
79
|
+
|
|
80
|
+
Rota selecionada: <rota ou n/a>
|
|
81
|
+
|
|
82
|
+
## Link Out-of-Scope
|
|
83
|
+
|
|
84
|
+
<Se rejeitado, linke `.dw/out-of-scope/<concept>.md`. Se já implementado, linke a implementação e declare que nenhum registro out-of-scope foi escrito.>
|
|
85
|
+
|
|
86
|
+
## Histórico
|
|
87
|
+
|
|
88
|
+
- YYYY-MM-DD — needs-triage -> <state> — <actor> — <reason>
|
|
@@ -14,13 +14,17 @@
|
|
|
14
14
|
* error allows the command, so a hook bug never blocks the user.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
import path from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
export const DANGEROUS = [
|
|
18
21
|
{ re: /\bgit\s+push\b[^\n|&;]*(--force\b|--force-with-lease\b|\s-f\b)/, why: 'force push rewrites remote history' },
|
|
19
22
|
{ re: /\bgit\s+push\b[^\n|&;]*(--delete\b|\s-d\b|\s:\S)/, why: 'deletes a remote branch' },
|
|
20
23
|
{ re: /\bgit\s+reset\b[^\n|&;]*--hard\b/, why: 'hard reset discards uncommitted work and rewrites the branch' },
|
|
21
24
|
{ re: /\bgit\s+clean\b[^\n|&;]*-[a-z]*f/, why: 'git clean -f permanently deletes untracked files' },
|
|
22
25
|
{ re: /\bgit\s+branch\b[^\n|&;]*\s-D\b/, why: 'force-deletes a branch that may be unmerged' },
|
|
23
26
|
{ re: /\bgit\s+checkout\b[^\n|&;]*\s(--\s+\.|\.\s*$)/, why: 'discards all local changes in the working tree' },
|
|
27
|
+
{ re: /\bgit\s+restore\b[^\n|&;]*\s(--\s+)?\.(?=\s*(?:$|[|&;]))/, why: 'discards all local changes in the working tree' },
|
|
24
28
|
];
|
|
25
29
|
|
|
26
30
|
function readStdin() {
|
|
@@ -38,42 +42,55 @@ function allow() {
|
|
|
38
42
|
process.exit(0);
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
function
|
|
42
|
-
process.stdout.write(
|
|
43
|
-
JSON.stringify({
|
|
44
|
-
hookSpecificOutput: {
|
|
45
|
-
hookEventName: 'PreToolUse',
|
|
46
|
-
permissionDecision: 'deny',
|
|
47
|
-
permissionDecisionReason: reason,
|
|
48
|
-
},
|
|
49
|
-
}) + '\n',
|
|
50
|
-
);
|
|
51
|
-
process.exit(0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function main() {
|
|
45
|
+
export function evaluatePayload(input) {
|
|
55
46
|
let payload;
|
|
56
47
|
try {
|
|
57
|
-
payload = JSON.parse(
|
|
48
|
+
payload = JSON.parse(input);
|
|
58
49
|
} catch {
|
|
59
|
-
return
|
|
50
|
+
return null; // fail open
|
|
60
51
|
}
|
|
61
52
|
|
|
62
53
|
const command = payload && payload.tool_input && typeof payload.tool_input.command === 'string'
|
|
63
54
|
? payload.tool_input.command
|
|
64
55
|
: '';
|
|
65
|
-
if (!command) return
|
|
56
|
+
if (!command) return null;
|
|
66
57
|
|
|
67
58
|
for (const rule of DANGEROUS) {
|
|
68
59
|
if (rule.re.test(command)) {
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
return {
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: 'PreToolUse',
|
|
63
|
+
permissionDecision: 'deny',
|
|
64
|
+
permissionDecisionReason:
|
|
65
|
+
`Blocked by dev-workflow git guardrails: ${rule.why}. ` +
|
|
66
|
+
`If this is intentional, run it yourself outside the agent, or adjust .claude/settings.json hooks.`,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
73
69
|
}
|
|
74
70
|
}
|
|
75
71
|
|
|
76
|
-
return
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function deny(reason) {
|
|
76
|
+
process.stdout.write(
|
|
77
|
+
JSON.stringify({
|
|
78
|
+
hookSpecificOutput: {
|
|
79
|
+
hookEventName: 'PreToolUse',
|
|
80
|
+
permissionDecision: 'deny',
|
|
81
|
+
permissionDecisionReason: reason,
|
|
82
|
+
},
|
|
83
|
+
}) + '\n',
|
|
84
|
+
);
|
|
85
|
+
process.exit(0);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function main() {
|
|
89
|
+
const result = evaluatePayload(await readStdin());
|
|
90
|
+
if (!result) return allow();
|
|
91
|
+
return deny(result.hookSpecificOutput.permissionDecisionReason);
|
|
77
92
|
}
|
|
78
93
|
|
|
79
|
-
|
|
94
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
95
|
+
main().catch(() => allow());
|
|
96
|
+
}
|
|
@@ -32,6 +32,8 @@ See `references/stop-the-line.md` for when this rule bends.
|
|
|
32
32
|
|
|
33
33
|
Without a deterministic reproduction, you cannot know whether your "fix" worked. The reproduction is the hypothesis test. Even a flaky bug needs a *reproducible-enough* test (e.g., "fails 8/10 runs") before fixing.
|
|
34
34
|
|
|
35
|
+
For non-trivial bugs, or after a first fix fails, Step 1 must establish the red-capable feedback loop contract in `references/six-step-triage.md` before theorizing: one loop, deterministic enough, fast, agent-runnable, and observed red. If the loop needs human action, use the HITL template there instead of continuing blind.
|
|
36
|
+
|
|
35
37
|
If you cannot reproduce: see `references/non-reproducible-strategy.md`. Don't fix on guess.
|
|
36
38
|
|
|
37
39
|
### 3. Find the root cause, not the nearest cause
|
|
@@ -14,12 +14,71 @@ Six discrete steps. Each has a specific output. Don't move to the next without f
|
|
|
14
14
|
- From a log line → find the surrounding context (request ID, user ID, timestamp); reconstruct the scenario.
|
|
15
15
|
- Write a failing test FIRST when the bug is in pure logic. The test commits the bug to record before you fix it.
|
|
16
16
|
|
|
17
|
+
### Feedback loop contract
|
|
18
|
+
|
|
19
|
+
For a non-trivial bug, or whenever the first attempted fix did not work, do not theorize before you have a feedback loop. A good loop is:
|
|
20
|
+
|
|
21
|
+
- **Single:** one command or one executable artifact, not a hand-managed sequence.
|
|
22
|
+
- **Deterministic:** produces the same result often enough to trust the signal.
|
|
23
|
+
- **Fast:** runs quickly enough that you can use it repeatedly while narrowing the cause.
|
|
24
|
+
- **Agent-runnable:** executable by the agent without hidden credentials, private hardware, or unrecorded manual state.
|
|
25
|
+
- **Red-capable:** proven to fail now, with the failure already observed and saved. "It should fail" is not enough.
|
|
26
|
+
|
|
27
|
+
Small obvious bugs are exempt from the full checklist when the reproduction is already a single clear command or click path and the fix is truly surgical. The exemption ends immediately if the first fix fails or the bug touches multiple layers.
|
|
28
|
+
|
|
29
|
+
### Loop repertoire
|
|
30
|
+
|
|
31
|
+
Pick the smallest loop that can show the bug:
|
|
32
|
+
|
|
33
|
+
| Loop type | Use when |
|
|
34
|
+
|-----------|----------|
|
|
35
|
+
| Focused test | The bug fits an existing unit, integration, contract, or E2E suite |
|
|
36
|
+
| `curl` / HTTP client | The bug is an API request/response behavior |
|
|
37
|
+
| CLI command | The symptom is triggered by a command-line entry point |
|
|
38
|
+
| Headless browser | The bug depends on browser rendering, routing, storage, or user events |
|
|
39
|
+
| Trace replay | You have a captured request/session/fixture that can be replayed |
|
|
40
|
+
| Dedicated harness | The production entry point is too slow or noisy, but a public seam can be exercised directly |
|
|
41
|
+
| Fuzz or repeat runner | The bug is input-sensitive or low-frequency but locally amplifiable |
|
|
42
|
+
| `git bisect` | A known-good revision exists and the regression window matters |
|
|
43
|
+
| Differential test | A new path should match an old implementation, another service, or a reference output |
|
|
44
|
+
|
|
45
|
+
### HITL loop template
|
|
46
|
+
|
|
47
|
+
Use this when the loop cannot be run by the agent because it needs credentials, private data, hardware, or a human click. Do not continue in the dark; ask for the missing artifact or access.
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
## Human-in-the-loop reproduction needed
|
|
51
|
+
|
|
52
|
+
I cannot run the feedback loop myself because: <credential / hardware / private data / manual action>.
|
|
53
|
+
|
|
54
|
+
Please provide one of:
|
|
55
|
+
- A single command I can run locally or in CI.
|
|
56
|
+
- A sanitized fixture, trace, screenshot sequence, or log bundle.
|
|
57
|
+
- Temporary access or exact manual steps you will run.
|
|
58
|
+
|
|
59
|
+
What I already tried:
|
|
60
|
+
- <attempt 1 + result>
|
|
61
|
+
- <attempt 2 + result>
|
|
62
|
+
|
|
63
|
+
Once provided, I will first confirm the loop is red-capable before proposing the fix.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### After the loop is red-capable
|
|
67
|
+
|
|
68
|
+
Only after the failing loop is observed:
|
|
69
|
+
|
|
70
|
+
1. Minimize the case by removing one variable at a time.
|
|
71
|
+
2. List 3-5 falsifiable hypotheses and rank them before testing any one.
|
|
72
|
+
3. Instrument one variable at a time, with removable log prefixes such as `[DW-DEBUG:<slug>]`, so cleanup is mechanical.
|
|
73
|
+
4. Keep the regression test on the right public seam; do not lock the test to internals.
|
|
74
|
+
5. Remove temporary instrumentation before final verification.
|
|
75
|
+
|
|
17
76
|
**Common pitfall:** "It happens sometimes." This is not a reproduction. Either:
|
|
18
77
|
- Find a deterministic trigger (often there's a state precondition you missed), OR
|
|
19
78
|
- Quantify the rate (8/10 runs) and treat the test as flaky-but-progress.
|
|
20
79
|
- See `non-reproducible-strategy.md` for state/timing/env-dependent cases.
|
|
21
80
|
|
|
22
|
-
**Done when:** You have a one-line command
|
|
81
|
+
**Done when:** You have a one-line command, executable script, or short click path for a trivial UI bug that produces the bug ≥80% of the time. For non-trivial bugs, the loop also satisfies the feedback loop contract above, or the HITL blocker is recorded with explicit artifact/access requested from the user.
|
|
23
82
|
|
|
24
83
|
## Step 2 — Localize
|
|
25
84
|
|
|
@@ -4,7 +4,7 @@ Tasks within a phase have dependencies. Some can run in parallel; others must wa
|
|
|
4
4
|
|
|
5
5
|
## Wave computation
|
|
6
6
|
|
|
7
|
-
Input: `tasks.md` with each task carrying a `Depends on:` field (none, or comma-separated task
|
|
7
|
+
Input: `tasks.md` with each task carrying a `Depends on:` field (none, or comma-separated task IDs).
|
|
8
8
|
|
|
9
9
|
Algorithm: topological sort.
|
|
10
10
|
|
|
@@ -13,25 +13,25 @@ Algorithm: topological sort.
|
|
|
13
13
|
3. Wave assignment:
|
|
14
14
|
- Wave 1 = tasks with zero dependencies
|
|
15
15
|
- Wave N = tasks whose all dependencies are in waves 1..N-1
|
|
16
|
-
4. Output: ordered list of waves, each wave a list of task
|
|
16
|
+
4. Output: ordered list of waves, each wave a list of task IDs.
|
|
17
17
|
|
|
18
18
|
## Example
|
|
19
19
|
|
|
20
20
|
```
|
|
21
21
|
tasks.md:
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
22
|
+
- 1.0 Create user schema Depends on: none
|
|
23
|
+
- 2.0 Create user model Depends on: 1.0
|
|
24
|
+
- 3.0 Create order schema Depends on: none
|
|
25
|
+
- 4.0 Wire auth middleware Depends on: 2.0
|
|
26
|
+
- 5.0 Add login endpoint Depends on: 4.0
|
|
27
|
+
- 6.0 Add order endpoint Depends on: 2.0, 3.0
|
|
28
|
+
- 7.0 Wire validation rules Depends on: 4.0, 6.0
|
|
29
29
|
|
|
30
30
|
Computed waves:
|
|
31
|
-
Wave 1: [
|
|
32
|
-
Wave 2: [
|
|
33
|
-
Wave 3: [
|
|
34
|
-
Wave 4: [
|
|
31
|
+
Wave 1: [1.0, 3.0] (no deps; can run in parallel)
|
|
32
|
+
Wave 2: [2.0] (depends on 1.0)
|
|
33
|
+
Wave 3: [4.0, 6.0] (depend on wave 2)
|
|
34
|
+
Wave 4: [5.0, 7.0] (depend on wave 3)
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
## Parallel execution within a wave
|
|
@@ -73,7 +73,7 @@ Each wave is a checkpoint:
|
|
|
73
73
|
|
|
74
74
|
## Order within a wave
|
|
75
75
|
|
|
76
|
-
Within a wave, order doesn't matter logically (no deps between same-wave tasks). But for **commit history readability**, the executor should commit in numeric order of task
|
|
76
|
+
Within a wave, order doesn't matter logically (no deps between same-wave tasks). But for **commit history readability**, the executor should commit in numeric order of task ID (1.0 commit before 2.0 even if both are wave 1). The parallel subagent results may arrive out of order; the executor collects and commits sequentially.
|
|
77
77
|
|
|
78
78
|
This means: subagents return their changes (files written, but NOT committed). The executor commits them in numeric order.
|
|
79
79
|
|
|
@@ -36,17 +36,23 @@ vocabulary and the calling command for the idea one-pager / PRD.
|
|
|
36
36
|
until every dependency branch is resolved, glossary/code contradictions are closed, no blocking decision
|
|
37
37
|
remains, AND the user explicitly confirms. Otherwise persist a draft/paused state and stop.
|
|
38
38
|
|
|
39
|
-
## Before the first question — build the decision tree
|
|
39
|
+
## Before the first question — resume or build the decision tree
|
|
40
40
|
|
|
41
|
-
Inspect
|
|
42
|
-
its
|
|
41
|
+
Inspect the active one-pager/PRD first. If it already has a `### Decision Map`, read it before reconstructing:
|
|
42
|
+
load its nodes, `Depends on:` fields, states, explicit **Frontier**, and `#### Decision Fog`; do not re-ask a
|
|
43
|
+
node already marked `resolved`. Continue from the Frontier when it exists. Only rebuild from scratch when no
|
|
44
|
+
durable map exists or the map is malformed.
|
|
45
|
+
|
|
46
|
+
When no resumable map exists, inspect project facts and open questions, then order them by dependency (never ask
|
|
47
|
+
a downstream decision before its blocker is resolved):
|
|
43
48
|
|
|
44
49
|
1. Read what already exists: `.dw/rules/`, `.dw/intel/` (via `/dw-intel` when present), `.dw/constitution.md`,
|
|
45
50
|
`.dw/domain/**` (glossary / context-map), current PRDs/TechSpecs, recent git activity.
|
|
46
51
|
2. Extract the open decisions the plan/PRD implies. Fold in vocabulary tension surfaced by `dw-domain-modeling`
|
|
47
52
|
(fuzzy or overloaded terms are decisions too).
|
|
48
|
-
3. Order them into a **dependency tree**: a node that constrains others comes first. Record it
|
|
49
|
-
(or `/dw-plan`) can resume. Full method + the shared-understanding gate:
|
|
53
|
+
3. Order them into a **dependency tree**: a node that constrains others comes first. Record it in `### Decision
|
|
54
|
+
Map` so a later turn (or `/dw-plan`) can resume. Full method + the shared-understanding gate:
|
|
55
|
+
`references/decision-tree.md`.
|
|
50
56
|
|
|
51
57
|
## The loop
|
|
52
58
|
|
|
@@ -59,6 +65,9 @@ For each unresolved node, in dependency order:
|
|
|
59
65
|
`dw-domain-modeling`; the caller persists to the one-pager/PRD). ADR creation still needs a separate explicit
|
|
60
66
|
approval — never auto-create one.
|
|
61
67
|
5. **Re-walk** the tree: the answer may unlock or reshape downstream nodes.
|
|
68
|
+
6. **Persist the map** after each resolved answer when writes are authorized: update node state, `Depends on:`,
|
|
69
|
+
explicit **Frontier**, and `Decision Fog` without duplicating the decision outcome already recorded in
|
|
70
|
+
**Resolved Decisions**.
|
|
62
71
|
|
|
63
72
|
When the tree is exhausted and contradictions are closed, present the shared-understanding summary and ask the
|
|
64
73
|
user to confirm. Only then is the session `aligned`.
|
|
@@ -90,8 +99,9 @@ what you *would* persist.
|
|
|
90
99
|
- **Scope:** the artifact under grill (one-pager / PRD / TechSpec), the decision tree size, and how many nodes
|
|
91
100
|
are resolved vs open.
|
|
92
101
|
- **Evidence:** the facts discovered from repo/rules/intel/docs (with sources) that were used instead of asking.
|
|
93
|
-
- **Artifacts:**
|
|
94
|
-
authorized `.dw/domain/**` / one-pager / PRD updates (with
|
|
102
|
+
- **Artifacts:** Decision Map (nodes, `Depends on:`, state, Frontier, Decision Fog), resolved decisions with the
|
|
103
|
+
recommended answer and the user's choice, and any authorized `.dw/domain/**` / one-pager / PRD updates (with
|
|
104
|
+
paths).
|
|
95
105
|
- **Decisions:** each resolved decision, the alternative rejected, and why.
|
|
96
106
|
- **Risks:** open decisions, unclosed glossary/code contradictions, and any decision made without full evidence.
|
|
97
107
|
- **Next Step:** either "user to confirm shared understanding" (with the remaining nodes) or "aligned — hand off
|
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
Grill is not a flat questionnaire. It is a walk down a **dependency-ordered decision tree**, so an upstream
|
|
4
4
|
decision is never asked after the downstream decision it constrains.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Resume or build the tree (before the first question)
|
|
7
|
+
|
|
8
|
+
Before rebuilding a tree, read the active one-pager/PRD for an existing `### Decision Map`. If present and
|
|
9
|
+
well-formed, resume from it instead of deriving the same tree again. Load the node IDs, `Depends on:` fields,
|
|
10
|
+
states, explicit **Frontier**, and `#### Decision Fog`; do not re-ask a node already marked `resolved`.
|
|
11
|
+
|
|
12
|
+
If there is no durable map yet:
|
|
7
13
|
|
|
8
14
|
1. **Gather open decisions.** Read the plan/PRD and the project's durable facts (`.dw/rules/`, `.dw/intel/` via
|
|
9
15
|
`/dw-intel`, `.dw/constitution.md`, `.dw/domain/**`, current PRDs/TechSpecs, recent git activity). List every
|
|
@@ -16,14 +22,31 @@ decision is never asked after the downstream decision it constrains.
|
|
|
16
22
|
4. **Topologically order.** Ask parents before children. Independent branches can be walked in any order, but
|
|
17
23
|
within a branch always resolve the blocker first.
|
|
18
24
|
|
|
19
|
-
Record the tree
|
|
20
|
-
exactly where it stopped.
|
|
25
|
+
Record the tree in the active artifact's `### Decision Map` so this session, a later Grill session, or a later
|
|
26
|
+
`/dw-plan` handoff can resume exactly where it stopped.
|
|
27
|
+
|
|
28
|
+
## Durable Decision Map contract
|
|
29
|
+
|
|
30
|
+
- Keep one row per decision node with a stable ID (`D1`, `D2`, ...), a short node label, `State`, `Depends on:`,
|
|
31
|
+
`Frontier?`, and structural notes.
|
|
32
|
+
- Use the same dependency field shape as task plans: `Depends on: none` or `Depends on: D1, D2`. This keeps
|
|
33
|
+
dependency parsing consistent across durable artifacts.
|
|
34
|
+
- Allowed `State` values are `resolved`, `open-ready`, and `open-blocked`.
|
|
35
|
+
- Maintain an explicit `**Frontier:**` line listing all `open-ready` node IDs, or `none`. The next session reads
|
|
36
|
+
this line directly; it must not need to manually recompute the graph to know what can be asked next.
|
|
37
|
+
- Keep `#### Decision Fog` for known unresolved areas that are not yet crisp enough to phrase as a decision
|
|
38
|
+
node. Each item is one line and graduates into a real node once it becomes decidable.
|
|
39
|
+
|
|
40
|
+
Do not duplicate the content of `### Resolved Decisions` in the map. The map records structure and resume state;
|
|
41
|
+
`Resolved Decisions` records the recommended answer, user's choice, rejected alternative, and evidence.
|
|
21
42
|
|
|
22
43
|
## Walk the tree
|
|
23
44
|
|
|
24
45
|
Resolve nodes in dependency order using the per-turn contract (`interview-loop.md`). After each answer, **re-walk
|
|
25
|
-
the tree
|
|
26
|
-
new node, inserted in dependency order — not asked
|
|
46
|
+
the tree** and persist the updated map when writes are authorized: a resolved parent may add, remove, or reshape
|
|
47
|
+
child nodes. New tension discovered mid-walk becomes a new node, inserted in dependency order — not asked
|
|
48
|
+
immediately if a blocker is still open. If a newly discovered uncertainty is real but still too vague to phrase
|
|
49
|
+
as a decision, add it to `Decision Fog` instead of pretending the tree is complete.
|
|
27
50
|
|
|
28
51
|
## The shared-understanding gate
|
|
29
52
|
|
|
@@ -44,8 +67,8 @@ terms, and the remaining (non-blocking) decisions with their owners.
|
|
|
44
67
|
If the gate is not met — blocking decision open, contradiction unclosed, or the user not yet confirming — **do
|
|
45
68
|
not** declare alignment. Persist a draft/paused state:
|
|
46
69
|
|
|
47
|
-
- Keep the one-pager (or PRD) at its draft/paused status with
|
|
48
|
-
remaining open nodes recorded (the caller performs the write, only if authorized).
|
|
70
|
+
- Keep the one-pager (or PRD) at its draft/paused status with `### Decision Map`, resolved decisions, the
|
|
71
|
+
explicit Frontier, and remaining open nodes recorded (the caller performs the write, only if authorized).
|
|
49
72
|
- Return `FINDINGS` with the open nodes as the Next Step, so the next turn resumes the same tree.
|
|
50
73
|
|
|
51
74
|
## Handoff to /dw-plan
|