@brunosps00/dev-workflow 2.6.0 → 2.7.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.
Files changed (56) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +7 -4
  4. package/lib/doctor.js +17 -2
  5. package/lib/init.js +16 -6
  6. package/lib/migrate-skills.js +189 -39
  7. package/lib/removed-bundled-skills.js +4 -2
  8. package/lib/skill-registry.js +12 -2
  9. package/lib/uninstall.js +61 -5
  10. package/package.json +1 -1
  11. package/scaffold/en/agent-instructions.md +1 -1
  12. package/scaffold/en/commands/dw-brainstorm.md +2 -2
  13. package/scaffold/en/commands/dw-bugfix.md +1 -1
  14. package/scaffold/en/commands/dw-commit.md +1 -1
  15. package/scaffold/en/commands/dw-dockerize.md +2 -2
  16. package/scaffold/en/commands/dw-functional-doc.md +1 -1
  17. package/scaffold/en/commands/dw-harness-audit.md +1 -1
  18. package/scaffold/en/commands/dw-intel.md +1 -1
  19. package/scaffold/en/commands/dw-learn.md +1 -1
  20. package/scaffold/en/commands/dw-new-project.md +3 -3
  21. package/scaffold/en/commands/dw-plan.md +2 -2
  22. package/scaffold/en/commands/dw-qa.md +6 -5
  23. package/scaffold/en/commands/dw-redesign-ui.md +3 -3
  24. package/scaffold/en/commands/dw-review.md +2 -2
  25. package/scaffold/en/commands/dw-skill-health.md +24 -1
  26. package/scaffold/en/commands/dw-update.md +28 -11
  27. package/scaffold/en/references/invariants.md +4 -0
  28. package/scaffold/en/templates/project-onepager.md +1 -1
  29. package/scaffold/pt-br/agent-instructions.md +1 -1
  30. package/scaffold/pt-br/commands/dw-brainstorm.md +2 -2
  31. package/scaffold/pt-br/commands/dw-bugfix.md +1 -1
  32. package/scaffold/pt-br/commands/dw-commit.md +1 -1
  33. package/scaffold/pt-br/commands/dw-dockerize.md +2 -2
  34. package/scaffold/pt-br/commands/dw-functional-doc.md +1 -1
  35. package/scaffold/pt-br/commands/dw-harness-audit.md +1 -1
  36. package/scaffold/pt-br/commands/dw-intel.md +1 -1
  37. package/scaffold/pt-br/commands/dw-learn.md +1 -1
  38. package/scaffold/pt-br/commands/dw-new-project.md +3 -3
  39. package/scaffold/pt-br/commands/dw-plan.md +2 -2
  40. package/scaffold/pt-br/commands/dw-qa.md +6 -5
  41. package/scaffold/pt-br/commands/dw-redesign-ui.md +3 -3
  42. package/scaffold/pt-br/commands/dw-review.md +2 -2
  43. package/scaffold/pt-br/commands/dw-skill-health.md +24 -1
  44. package/scaffold/pt-br/commands/dw-update.md +28 -11
  45. package/scaffold/pt-br/references/invariants.md +5 -0
  46. package/scaffold/pt-br/templates/project-onepager.md +1 -1
  47. package/scaffold/scripts/hooks/session-cost.mjs +62 -21
  48. package/scaffold/skills/docker-compose-recipes/references/compose-composition.md +1 -1
  49. package/scaffold/skills/dw-llm-eval/SKILL.md +3 -1
  50. package/scaffold/skills/dw-llm-eval/references/integration-with-dev-workflow-commands-detail.md +2 -2
  51. package/scaffold/skills/dw-llm-eval/references/reference-dataset.md +57 -3
  52. package/scaffold/skills/dw-ui-discipline/SKILL.md +8 -5
  53. package/scaffold/skills/dw-ui-discipline/references/accessibility-floor.md +20 -8
  54. package/scaffold/skills/dw-ui-discipline/references/content-stress.md +246 -0
  55. package/scaffold/skills/dw-ui-discipline/references/motion.md +205 -35
  56. package/scaffold/skills/dw-ui-discipline/references/responsive.md +44 -2
@@ -53,7 +53,7 @@ Funciona melhor com projeto analisado por `/dw-analyze-project`
53
53
 
54
54
  ## Skills complementares
55
55
 
56
- Quando disponíveis no projeto em `./.agents/skills/`, use estas skills como apoio operacional, sem substituir este comando como fonte de verdade:
56
+ Quando disponíveis no projeto em `./.dw/skills/`, use estas skills como apoio operacional, sem substituir este comando como fonte de verdade:
57
57
 
58
58
  - `dw-testing-discipline`: apoio para estruturar fluxos E2E (`references/playwright-recipes.md`), padrões de coleta de evidência, e aplicar core rules + hierarquia de seletores em qualquer teste referenciado pelo doc
59
59
  - `remotion-best-practices`: apoio obrigatório quando houver vídeo humano final, legendas, composição, transições, FFmpeg ou Remotion
@@ -29,7 +29,7 @@ Você é o auditor do harness dev-workflow.
29
29
  5. Recomende os 3 principais fixes.
30
30
 
31
31
  ## Triagem de degradação em runtime (sob demanda)
32
- O scorecard acima e saúde determinística da **instalação**. Se o problema for o *agente* se comportando mal em runtime (loops, desvio do objetivo, edições alucinadas, raciocínio degradado), o diagnóstico e outro: aponte o usuário para `.agents/skills/dw-debug-protocol/references/agent-degradation.md` (tabela sintoma→causa + recovery ordenado). Apenas informativo — não afeta o scorecard.
32
+ O scorecard acima e saúde determinística da **instalação**. Se o problema for o *agente* se comportando mal em runtime (loops, desvio do objetivo, edições alucinadas, raciocínio degradado), o diagnóstico e outro: aponte o usuário para `.dw/skills/dw-debug-protocol/references/agent-degradation.md` (tabela sintoma→causa + recovery ordenado). Apenas informativo — não afeta o scorecard.
33
33
 
34
34
  ## Saída
35
35
  Retorne um scorecard e não altere arquivos. Para drift de arquivo gerenciado, indique `dev-workflow repair`.
@@ -64,7 +64,7 @@ Não recuse responder — devolva a melhor info disponível.
64
64
 
65
65
  ### 2. Detecção do shape da query
66
66
 
67
- Classifique o `{{QUERY}}` em uma das formas documentadas em `.agents/skills/dw-codebase-intel/references/query-patterns.md`:
67
+ Classifique o `{{QUERY}}` em uma das formas documentadas em `.dw/skills/dw-codebase-intel/references/query-patterns.md`:
68
68
 
69
69
  - **where-is** — primário: `files.json`, secundário: `apis.json`
70
70
  - **what-uses** — primário: `deps.json` (libs) ou `files.json` (símbolos)
@@ -23,7 +23,7 @@ Colete sinais apenas do que já está persistido:
23
23
  4. **Apresente** os candidatos no chat como lista markdown — id, trigger, action, confidence, evidence. NÃO escreva ainda.
24
24
  5. **Pergunte**: "Aprovar quais para armazenar? (ids, ou 'todos', ou 'nenhum'). Algum para promover a principio de constitution?"
25
25
  6. Na aprovação:
26
- - Grave cada instinct aprovado em `.dw/memory/instincts/<slug>.md` no formato de `.agents/skills/dw-memory/references/instincts.md` (crie ou atualize; nunca duplique um id existente).
26
+ - Grave cada instinct aprovado em `.dw/memory/instincts/<slug>.md` no formato de `.dw/skills/dw-memory/references/instincts.md` (crie ou atualize; nunca duplique um id existente).
27
27
  - Para os que o usuário escolher promover, encaminhe ao fluxo de constitution — proponha um principio `P-NNN` em `severity: info` para o Step 8 do `/dw-analyze-project`. NÃO edite `.dw/constitution.md` direto sem o usuário reconfirmar.
28
28
  7. Atualize a confiança de instincts existentes que a nova evidência reconfirme ou contradiga.
29
29
 
@@ -39,7 +39,7 @@ Você é o líder de bootstrap de workspace do dev-workflow. Sua função é peg
39
39
  - One-pager do projeto: `.dw/spec/projects/{{PROJECT_NAME}}.md` (usa `.dw/templates/project-onepager.md`)
40
40
  - Relatório final: `.dw/spec/projects/{{PROJECT_NAME}}-bootstrap.md`
41
41
  - Rules semeadas: `.dw/rules/index.md` (mínimo, depois substituido/enriquecido por `/dw-analyze-project`)
42
- - Receitas de compose: `.agents/skills/docker-compose-recipes/services/*.yml`
42
+ - Receitas de compose: `.dw/skills/docker-compose-recipes/services/*.yml`
43
43
 
44
44
  ## Comportamento Obrigatório — Pipeline
45
45
 
@@ -157,7 +157,7 @@ Se fullstack:
157
157
 
158
158
  #### 3.3 Gerar `docker-compose.dev.yml`
159
159
 
160
- 1. Leia `.agents/skills/docker-compose-recipes/SKILL.md` e os `services/<nome>.yml` relevantes.
160
+ 1. Leia `.dw/skills/docker-compose-recipes/SKILL.md` e os `services/<nome>.yml` relevantes.
161
161
  2. Aplique o algoritmo de merge de `references/compose-composition.md`:
162
162
  - Concatene blocos sob `services:`.
163
163
  - Agregue volumes nomeados sob `volumes:`.
@@ -300,7 +300,7 @@ monorepo: <pnpm-workspaces|turborepo|nx|none>
300
300
  | ... | ... | ... |
301
301
 
302
302
  ## Servicos Compostos
303
- <tabela de servicos com porta + URL UI + requisitos de credenciais, vinda de .agents/skills/docker-compose-recipes/>
303
+ <tabela de servicos com porta + URL UI + requisitos de credenciais, vinda de .dw/skills/docker-compose-recipes/>
304
304
 
305
305
  ## Proximos Passos
306
306
  1. `cp .env.example .env`, gere secrets locais unicos e defina todo valor obrigatorio como `POSTGRES_PASSWORD`.
@@ -30,7 +30,7 @@ Você é um orquestrador de planejamento que conduz uma ideia pelo pipeline comp
30
30
 
31
31
  ## Skills Complementares
32
32
 
33
- Quando disponíveis em `./.agents/skills/`, use como suporte:
33
+ Quando disponíveis em `./.dw/skills/`, use como suporte:
34
34
 
35
35
  - `dw-source-grounding`: **SEMPRE** no estágio TechSpec — toda decisão de framework/library cita docs oficiais com versão + data.
36
36
  - `dw-ui-discipline`: **OBRIGATÓRIO** quando PRD tem superfícies de UI — roda as 4 grounding questions antes do design visual entrar no TechSpec.
@@ -169,7 +169,7 @@ Roda em modo padrão (após aprovação do TechSpec) OU `plan tasks`.
169
169
  3. **Cobertura end-to-end:** todo fluxo user-facing tem subtasks backend + frontend + UI funcional quando aplicável.
170
170
  4. **Test placement (`dw-testing-discipline`):** toda subtask que adiciona teste nomeia seu invariant per placement doctrine. Owning layer especificado.
171
171
  5. **Constitution alignment:** toda task lista `Constitution: respects P-NNN` ou `Constitution: deviates P-NNN — ADR planejado: <slug>` ou `Constitution: n/a — motivo: <one-liner>`.
172
- 6. **Subtask LLM-eval (quando aplicável):** se PRD tem feature AI, uma task deve incluir Eval Plan subtask (reference dataset path, oracle rungs, judge calibration, target metrics).
172
+ 6. **Subtask LLM-eval (quando aplicável):** se PRD tem feature AI, uma task deve incluir Eval Plan subtask (reference dataset path, oracle rungs, judge calibration, target metrics), ordenada antes das subtasks de implementação: spec do comportamento (quando / faz / não deve / continua funcionando), casos, e uma run baseline no código atual em que os casos do comportamento novo falham.
173
173
  7. **Declaração de dependência:** cada task lista explicitamente de quais tasks anteriores depende. Escreva o campo como `Depends on: none` ou `Depends on: 1.0, 2.0` em `tasks.md` e em cada `<N>_task.md`. Validação rejeita ciclos.
174
174
  8. **Outputs:**
175
175
  - Summary: `.dw/spec/prd-<feature-slug>/tasks.md`
@@ -48,14 +48,14 @@ Compute `<target>` UMA VEZ no início; substitua onde aparecer `<target>` abaixo
48
48
 
49
49
  ## Skills Complementares
50
50
 
51
- Quando disponíveis em `./.agents/skills/`, invocadas operacionalmente:
51
+ Quando disponíveis em `./.dw/skills/`, invocadas operacionalmente:
52
52
 
53
53
  - `dw-testing-discipline`: **(modo UI — SEMPRE)** — core rules e 25 anti-patterns valem pra todo teste QA. `references/playwright-recipes.md` pra patterns táticos. `references/three-workflow-patterns.md` pra escolher modo de verificação (UI / network / perf). `references/security-boundary.md` pra fluxos que cruzam auth.
54
54
  - `api-testing-recipes`: **(modo API — SEMPRE)** — snippets validados pra `.http`, pytest+httpx, supertest, WebApplicationFactory, reqwest. Compõe per-FR test files em `QA/scripts/api/` e logs JSONL em `QA/logs/api/`.
55
- - `dw-llm-eval`: **(modo AI — quando invocado com `--ai`)** — roda reference dataset contra implementação atual. Computa precision@k / faithfulness / outcome accuracy. Loga JSONL em `QA/logs/ai/<feature>-<date>.jsonl`. Alerta em regressão >10% vs run anterior.
55
+ - `dw-llm-eval`: **(modo AI — quando invocado com `--ai`)** — roda reference dataset contra implementação atual. Computa precision@k / faithfulness / outcome accuracy. Loga JSONL em `QA/logs/ai/<feature>-<date>.jsonl`. Lista flips pass → fail por caso vs run anterior (cada um é bug) e alerta em regressão >10% de métrica.
56
56
  - `dw-debug-protocol`: **(em modo `--fix` — SEMPRE)** — six-step triage (Reproduzir → Localizar → Reduzir → Fix Root Cause → Guardar → Verify End-to-End) pra cada bug detectado. Stop-the-line discipline; root-cause sobre symptom; regression test no mesmo commit atômico.
57
57
  - `vercel-react-best-practices`: (modo UI) quando risco de regressão React/Next.js suspeitado.
58
- - `dw-ui-discipline`: (modo UI) ao validar consistência de design — anti-slop catalog + WCAG accessibility floor.
58
+ - `dw-ui-discipline`: (modo UI) ao validar consistência de design — anti-slop catalog + WCAG accessibility floor, mais o passe de content stress de `references/content-stress.md`.
59
59
  - `dw-chaos-engineering`: **(só por nome)** — passagem adversarial sobre uma mudança cujos testes normais já passam. Peça depois do QA verde, quando resiliência importa mais que cobertura; escreve só testes, roda local e tem teto de 3 rodadas. Nunca é invocada sozinha.
60
60
  - `dw-verify`: **(em modo `--fix` — SEMPRE)** — antes de marcar bug como `Fixed` ou `Closed`, requer VERIFICATION REPORT PASS (test + lint + build) E evidência de reteste (screenshot em UI, JSONL log em API, eval-run delta em AI).
61
61
 
@@ -92,7 +92,8 @@ Leia a baseline de qualidade/TechSpec do módulo afetado. Reutilize evidência v
92
92
  - Fluxos negativos (ações não autorizadas, input malformado).
93
93
  - Regressions (smoke check em surfaces adjacentes).
94
94
  - WCAG 2.2 accessibility per `dw-ui-discipline/references/accessibility-floor.md`.
95
- 4. **Capturar evidência**: screenshots em 375px mobile + 1440px desktop, console logs, network HARs.
95
+ - Content stress per `dw-ui-discipline/references/content-stress.md` em toda surface que renderiza dado de usuário ou de API: mapear os campos renderizados e seus limites, montar uma fixture de pior caso realista (mais vazio, um item e 1.000+ linhas), injetá-la na fronteira de dados — fixtures/mocks do próprio projeto, ou `page.route()` no teste; nunca editando o componente — e checar na largura real do container, em 320px, com zoom de 200% e em dark mode/RTL quando o produto suporta. Cada quebra vai para `bugs.md` com o mapeamento de severidade da reference (Broken → high, Ugly → medium, Fragile → low). Comportamento de plataforma mobile (hover preso, zoom em input, safe areas) não reproduz em emulação: liste em `qa-report.md` como pendente de aparelho real em vez de marcar como aprovado.
96
+ 4. **Capturar evidência**: screenshots em 375px mobile + 1440px desktop, console logs, network HARs; no passe de content stress, screenshots da fixture de pior caso em 320px e com zoom de 200%.
96
97
  5. **Detectar páginas stub/placeholder**: qualquer página com "TODO" ou conteúdo dummy óbvio → flagar como bug.
97
98
  6. **Escrever `qa-report.md`**: test plan, execution log, refs de evidência, contagem de bugs por severity.
98
99
  7. **Escrever `bugs.md`**: uma entrada por bug com severity, repro steps, link de evidência, status (`Open`).
@@ -117,7 +118,7 @@ Leia a baseline de qualidade/TechSpec do módulo afetado. Reutilize evidência v
117
118
  - Agent: outcome assertion + trajectory match (per parâmetro `--ai-mode` ou config da feature).
118
119
  - Classification: exact match accuracy.
119
120
  3. Logar JSONL em `QA/logs/ai/<feature>-<date>.jsonl`.
120
- 4. Comparar com JSONL da run anterior — alertar em regressão >10% em qualquer métrica.
121
+ 4. Comparar com o JSONL da run anterior caso a caso: listar todo caso que virou pass → fail e registrar cada um como bug, seja qual for a média. Depois alertar em regressão >10% em qualquer métrica. Rodar também o split `holdout` e reportar separado do `dev`.
121
122
  5. Anexar seção modo-AI em `qa-report.md`.
122
123
 
123
124
  ## Modo 1.5: UAT Interativo (`/dw-qa --uat`)
@@ -38,7 +38,7 @@ digraph redesign_decision {
38
38
 
39
39
  ## Skills Complementares
40
40
 
41
- Quando disponíveis no projeto em `./.agents/skills/`, use para guiar o redesign:
41
+ Quando disponíveis no projeto em `./.dw/skills/`, use para guiar o redesign:
42
42
 
43
43
  - `dw-ui-discipline`: **OBRIGATÓRIO** — roda o hard-gate de 4 checkpoints (brand authorities OU curated defaults; surface job sentence; state matrix completa; scene sentence) ANTES de qualquer proposta. Os 14 anti-slop patterns são checados contra cada direção. O WCAG 2.2 AA floor é não-negociável no step de validate.
44
44
  - `vercel-react-best-practices`: use quando o projeto for React/Next.js para padrões de performance e implementação
@@ -58,10 +58,10 @@ Utilize ferramentas de diagnóstico conforme o framework do projeto:
58
58
  1. Identifique o alvo: página, componente ou rota que será redesenhada.
59
59
  2. **AUDITAR**: leia a implementação atual, identifique stack CSS (Tailwind, CSS Modules, styled-components, etc.), capture o screenshot do estado-antes (Playwright MCP, ou `node .dw/scripts/lib/capture-screenshots.mjs` como fallback resiliente no WSL), rode react-doctor se projeto React.
60
60
  3. Faça 3 a 5 perguntas sobre objetivos do redesign: direção de estilo, constraints de marca, inspirações, público-alvo, dispositivos prioritários.
61
- 4. **PROPOR**: apresente 2 a 3 direções de design depois de passar pelo hard-gate de `dw-ui-discipline` (brand authorities ou curated defaults; surface job sentence; state matrix enumerada; scene sentence). Cada direção lista paleta de cores, par tipográfico, estilo de layout e racional. Self-check de cada direção contra os 14 anti-slop patterns. Para CADA direção, descreva explicitamente o layout mobile (<=768px) e o layout desktop (>=1024px), incluindo como os elementos se reorganizam, empilham ou escondem entre breakpoints.
61
+ 4. **PROPOR**: apresente 2 a 3 direções de design depois de passar pelo hard-gate de `dw-ui-discipline` (brand authorities ou curated defaults; surface job sentence; state matrix enumerada; scene sentence). As direções precisam divergir num eixo nomeado — layout, densidade, personalidade, motion ou modelo de interação — e recebem o nome da direção ("Quiet", "Editorial", "Dense"), nunca "Opção A/B/C"; três tons da mesma ideia contam como uma direção só. Cada direção lista seu eixo, paleta de cores, par tipográfico, estilo de layout e racional. Self-check de cada direção contra os 14 anti-slop patterns. Para CADA direção, descreva explicitamente o layout mobile (<=768px) e o layout desktop (>=1024px), incluindo como os elementos se reorganizam, empilham ou escondem entre breakpoints.
62
62
  5. Espere aprovação explícita do usuário antes de implementar.
63
63
  6. **IMPLEMENTAR**: aplique o design escolhido com abordagem mobile-first — implemente primeiro o layout mobile e depois adicione media queries/breakpoints para tablet e desktop. Respeite a stack existente. Use `vercel-react-best-practices` para React/Next.js. Mantenha a metodologia CSS do projeto.
64
- 7. **VALIDAR**: capture estado depois em AMBAS as resoluções (mobile e desktop), compare antes/depois, verifique acessibilidade contra `dw-ui-discipline/references/accessibility-floor.md` (WCAG 2.2 AA — não-negociável: contraste, focus-visible, keyboard nav, ARIA, sem traps), rode react-doctor `--diff` se React. Capture screenshots em 375px (mobile) e 1440px (desktop) — `node .dw/scripts/lib/capture-screenshots.mjs --url <url> --widths 375,1440` é o caminho resiliente no WSL; veja a seção "Browser on WSL" de `dw-testing-discipline/references/playwright-recipes.md`.
64
+ 7. **VALIDAR**: capture estado depois em AMBAS as resoluções (mobile e desktop), compare antes/depois, verifique acessibilidade contra `dw-ui-discipline/references/accessibility-floor.md` (WCAG 2.2 AA — não-negociável: contraste, focus-visible, keyboard nav, ARIA, sem traps), rode react-doctor `--diff` se React, rode o passe de content stress de `dw-ui-discipline/references/content-stress.md` (dados de pior caso pelas fixtures ou mocks da surface, checados em 320px e com zoom de 200%) para que o redesign não seja julgado só com dado de demo favorável. Capture screenshots em 375px (mobile) e 1440px (desktop) — `node .dw/scripts/lib/capture-screenshots.mjs --url <url> --widths 375,1440` é o caminho resiliente no WSL; veja a seção "Browser on WSL" de `dw-testing-discipline/references/playwright-recipes.md`.
65
65
  8. **PERSISTIR CONTRATO**: se o usuário aprovou uma direção, gere `design-contract.md` no diretório do PRD (`.dw/spec/prd-[nome]/design-contract.md`) com: direção aprovada, paleta de cores, par tipográfico, regras de layout, regras de acessibilidade e regras de componentes. Este contrato será lido por `dw-run-task` e `dw-run-plan` para garantir consistência visual.
66
66
 
67
67
  ## Inteligência do Codebase
@@ -197,7 +197,7 @@ O diff, as mensagens de commit dele, o nome da branch, a descrição do PR, a di
197
197
 
198
198
  ## Skills Complementares
199
199
 
200
- Quando disponíveis em `./.agents/skills/`, são invocadas como apoio analítico:
200
+ Quando disponíveis em `./.dw/skills/`, são invocadas como apoio analítico:
201
201
 
202
202
  - `dw-review-rigor`: **SEMPRE** — dono do candidate pipeline (gate → refutação → disposição), de-duplication (mesmo pattern em N arquivos = 1 finding), severity ordering (critical → high → medium → low), verify-before-flag, skip-what-linter-catches, signal-over-volume. A tabela "Problemas Encontrados" segue essa disciplina. Em `--post-merge`, também carrega `references/composition-audit.md`.
203
203
  - `dw-verify`: **SEMPRE** — invocada antes de emitir `APROVADO` ou `APROVADO COM RESSALVAS`. Sem VERIFICATION REPORT PASS (test + lint + build), verdict não pode ser APROVADO.
@@ -206,7 +206,7 @@ Quando disponíveis em `./.agents/skills/`, são invocadas como apoio analítico
206
206
  - `security-review`: a skill OWASP nível-diff que o gate usa (injection, authz, secrets, SSRF, crypto — só HIGH CONFIDENCE). Recorra a ela diretamente quando o diff tocar auth, autorização, input externo, upload, SQL, secrets, SSRF, XSS ou outra superfície sensível.
207
207
  - `dw-simplification`: use quando diff toca código denso — aplica Chesterton's Fence, protocolo de refactor preservando comportamento, métricas de complexidade.
208
208
  - `dw-minimalism`: use quando o diff adiciona código que pode estar over-built — flagra generalidade especulativa, helpers de um único caller, abstração prematura e violações de YAGNI (a contraparte pré-geração do `dw-simplification`).
209
- - `dw-ui-discipline`: use quando diff toca UI — roda os 14 visual-slop patterns + accessibility floor. Para um gate determinístico, rode também `node .dw/scripts/lib/ui-slop-detect.mjs <paths-ui-alterados> --fail-on error` (wrapper sobre o detector do impeccable); trate findings bloqueantes como **REJECTED** e reporte os warnings.
209
+ - `dw-ui-discipline`: use quando diff toca UI — roda os 14 visual-slop patterns + accessibility floor. Para um gate determinístico, rode também `node .dw/scripts/lib/ui-slop-detect.mjs <paths-ui-alterados> --fail-on error` (wrapper sobre o detector do impeccable); trate findings bloqueantes como **REJECTED** e reporte os warnings. Quando o diff adiciona ou muda motion (`transition`, `animation`, `@keyframes`, props de biblioteca de animação), cheque contra os gatilhos de escalonamento de `references/motion.md` §9; quando renderiza dado de usuário ou de API, cheque os sinais estáticos de `references/content-stress.md`. Ambos geram candidatos para o `dw-review-rigor`, nas severidades que essas references definem.
210
210
  - `dw-testing-discipline`: use quando diff toca testes — aplica catálogo de 25 anti-patterns + 6 agent guardrails (quando testes foram agent-authored).
211
211
  - `dw-llm-eval`: **OBRIGATÓRIO quando diff toca código de feature AI/LLM**. Reference dataset + ≥2 oracle rungs + judge calibration (se rung 4 usado) + eval run results DEVEM estar no PR. Faltando → REPROVADO.
212
212
  - `vercel-react-best-practices`: use quando diff toca React/Next.js.
@@ -7,7 +7,7 @@ Você é o auditor de saúde de skills e agentes do dev-workflow.
7
7
  - Use antes de promover um aprendizado para skill reutilizavel.
8
8
 
9
9
  ## Processo
10
- 1. Leia `scaffold/skill-registry.json` ao auditar o repo dev-workflow, ou `.dw/skill-registry.json` + `.agents/skills/` em projetos consumidores.
10
+ 1. Leia `scaffold/skill-registry.json` ao auditar o repo dev-workflow, ou `.dw/skill-registry.json` + as skills bundled instaladas em `.dw/skills/` em projetos consumidores. Skills em `.claude/skills/`, `.agents/skills/` e nos demais índices de agente são wrappers de comando ou do próprio usuário; uma skill do dev-workflow encontrada lá é cópia legada que o `update` remove.
11
11
  2. Agrupe skills por `kind`: `protocol`, `domain-pack`, `recipe-pack`, `asset-pack`.
12
12
  3. Valide que toda skill tem trigger, output esperado, owner, load policy e limite de contexto.
13
13
  4. Valide que todo `SKILL.md` bundled tem contrato `## Structured Return` com `Status`, `Scope`, `Evidence`, `Artifacts`, `Decisions`, `Risks` e `Next Step`.
@@ -59,6 +59,28 @@ Declare a janela antes de qualquer julgamento: conte as linhas instrumentadas
59
59
 
60
60
  Recomende rebaixar só quando TUDO valer: coorte invocável por modelo; ao menos 20 sessões instrumentadas ou 30 dias de janela; zero referências; sem sinal de artefato; comando owner alcançável. Abaixo disso, mostre as contagens e diga que a janela é curta demais para concluir. Remover skill bundled do pacote é entrada append-only em `lib/removed-bundled-skills.js` — este comando propõe, nunca remove e nunca deleta arquivo.
61
61
 
62
+ ### Comandos — quais entradas merecem lugar no índice
63
+
64
+ Todo comando `dw-*` instalado é uma entrada no índice de skills de cada agente, e índice lotado piora a escolha que o modelo faz ali. Linhas com o objeto `commands` registram quais comandos a sessão carregou: uma leitura de `.dw/commands/<nome>.md` (todo wrapper faz uma) ou uma chamada da ferramenta Skill nomeando o comando. As regras das skills valem sem mudança: chave `commands` ausente é falta de telemetria, a janela é contada só pelas linhas que trazem `commands`, e a contagem mede carregamento, não sucesso. O hook lê só transcripts do Claude Code; quando o projeto também roda Codex, Copilot ou OpenCode, diga que essas sessões não entram na conta.
65
+
66
+ Mostre uma tabela: comando, sessões que o carregaram, referências. Depois, para cada família de comandos com o mesmo propósito, mostre as contagens dos membros lado a lado:
67
+
68
+ | Família | Membros |
69
+ |---|---|
70
+ | Handoff de subagente | `dw-subtask-start`, `dw-subtask-complete`, `dw-subtask-resume` |
71
+ | Runners externos | `dw-codex-run`, `dw-claude-run`, `dw-copilot-run` |
72
+ | Instaladores de skills de nuvem | `dw-install-aws-skills`, `dw-install-azure-skills` |
73
+ | Auditorias de instalação e contexto | `dw-skill-health`, `dw-harness-audit`, `dw-context-budget` |
74
+ | Checkpoint de sessão | `dw-pause`, `dw-resume` |
75
+
76
+ Classifique cada família:
77
+
78
+ - `CANDIDATA A FUSÃO` — a janela tem ao menos 20 sessões instrumentadas ou 30 dias, e a família inteira foi carregada em menos de 5% delas, ou algum membro nunca foi carregado enquanto outro foi. Um comando com modos custaria menos entradas no índice.
79
+ - `MANTER SEPARADOS` — dois ou mais membros foram carregados, cada um, em ao menos 5 sessões: os nomes distintos estão em uso, e fundir troca um hábito medido por um índice menor.
80
+ - `CEDO DEMAIS` — abaixo do limiar da janela. Mostre as contagens e diga isso.
81
+
82
+ Comandos fora de família seguem a redação das skills: comando invocável por modelo com zero carregamentos numa janela longa o bastante é `CANDIDATO A OCIOSO`, nunca "não usado". Fusão ou remoção no pacote é decisão de produto registrada append-only em `lib/removed-commands.js` (o update então remove os wrappers antigos); este comando propõe, nunca renomeia, remove ou edita comandos. Ao auditar o próprio repositório dev-workflow não há telemetria local: reporte `SEM TELEMETRIA`, a menos que o mantenedor forneça os `costs.jsonl` de projetos consumidores, e agregue esses por projeto antes de somar.
83
+
62
84
  ## Saída
63
85
 
64
86
  Quando `.dw/config/routing-defaults.json` existir, compare seus candidatos atuais com o `.dw/config/routing.json` do proprietário. Relate diferenças relevantes e valide modelos/capacidades propostos antes da adoção. Valores diferentes podem ser intencionais; não os trate como falha de migração nem sobrescreva automaticamente. Atribuições de tarefas aprovadas têm precedência sobre ambos os arquivos de candidatos.
@@ -70,6 +92,7 @@ Inclua:
70
92
  - Issues de registry/schema.
71
93
  - Cobertura de retorno estruturado, incluindo qualquer skill sem contrato ou vocabulario de status.
72
94
  - Evidência de uso: a janela declarada, as tabelas por coorte e toda candidata a ociosa com sua frase de janela. Sem telemetria, diga isso em vez de pontuar.
95
+ - Uso de comandos: a tabela por comando e a classificação de cada família (`CANDIDATA A FUSÃO`, `MANTER SEPARADOS`, `CEDO DEMAIS`).
73
96
  - Top 3 fixes.
74
97
 
75
98
  Marcador final: `## SKILL-HEALTH COMPLETE`
@@ -24,15 +24,16 @@ Antes de sobrescrever arquivos gerenciados, crie um snapshot:
24
24
  ```bash
25
25
  SNAPSHOT_DIR=".dw/.backup/$(date -u +%Y%m%dT%H%M%SZ)"
26
26
  mkdir -p "$SNAPSHOT_DIR"
27
- cp -r .dw/commands .dw/templates .dw/references .dw/scripts "$SNAPSHOT_DIR/" 2>/dev/null
27
+ cp -r .dw/commands .dw/templates .dw/references .dw/scripts .dw/skills "$SNAPSHOT_DIR/" 2>/dev/null
28
28
  # agents/skills (bundled) tambem fazem parte do update
29
29
  [ -d .agents/skills ] && cp -r .agents/skills "$SNAPSHOT_DIR/agents-skills" 2>/dev/null
30
30
  # .claude/settings.json agora e mutado pelo update (MCPs + hooks + statusLine)
31
31
  [ -f .claude/settings.json ] && mkdir -p "$SNAPSHOT_DIR/claude" && cp .claude/settings.json "$SNAPSHOT_DIR/claude/settings.json" 2>/dev/null
32
+ [ -f .dw/install-state.json ] && cp .dw/install-state.json "$SNAPSHOT_DIR/install-state.json" 2>/dev/null
32
33
  echo "Snapshot salvo em $SNAPSHOT_DIR"
33
34
  ```
34
35
 
35
- Manter apenas os 3 snapshots mais recentes (remover os mais antigos) para evitar acumulo.
36
+ Manter apenas os 3 snapshots mais recentes em `.dw/.backup/` (remover os mais antigos) para evitar acumulo. `.dw/.migrated/` não é snapshot: nunca remova.
36
37
 
37
38
  ### 1. Registrar Versão Atual (Obrigatório)
38
39
 
@@ -86,7 +87,13 @@ O comando `update` sobrescreve arquivos gerenciados e PRESERVA:
86
87
 
87
88
  O comando `update` também roda o passo de migração GSD automaticamente — se o projeto tem `.planning/` legado (de uso prévio do GSD), o conteúdo é migrado para `.dw/intel/`, `.dw/spec/active-session.md`, `.dw/spec/quick/`, etc., e `.planning/` é renomeado para `.planning.gsd-archive-<DATA>/` para inspeção. Os arquivos `.claude/commands/gsd/`, `.claude/agents/gsd-*.md`, `.claude/hooks/gsd-*.js` e `.claude/gsd-file-manifest.json` são removidos durante a migração.
88
89
 
89
- Se o update falhar (erro de rede, permissão, pacote indisponível): reporte o erro ao usuário e PARE. NÃO tente workarounds manuais como copiar arquivos.
90
+ O CLI nunca apaga o que aposenta: move para `.dw/.migrated/<timestamp>/`, mantendo o caminho relativo, e imprime o destino. Isso acontece só depois que as skills novas estão em `.dw/skills/`, então um update interrompido deixa as cópias antigas no lugar. O que ele aposenta, e como decide:
91
+
92
+ - **Cópias legadas de skills bundled** em `.agents/skills/` (`[moved]`): só quando a cópia é do dev-workflow. Skill homônima que não é sai como `[kept]` e fica intocada.
93
+ - **Skills removidas em releases anteriores** (`[v<N>]`) e **fontes de comandos removidos** (`[legacy]`): casadas por nome, então uma skill homônima de outra origem também é movida — é o move que torna isso recuperável.
94
+ - **Wrappers `dw-*` órfãos** (`[orphan]`): `dw-` é o namespace deste pacote; uma skill do usuário chamada `dw-*` é movida, não perdida.
95
+
96
+ Se o update falhar (erro de rede, permissão, pacote indisponível): reporte o erro ao usuário e PARE. NÃO tente workarounds manuais como copiar arquivos. Passe ao usuário o caminho do snapshot do passo 0 e as duas saídas: rodar o update de novo depois de resolver a causa (ele é idempotente), ou `/dw-update --rollback`.
90
97
 
91
98
  ### 4. Capturar Nova Versão
92
99
 
@@ -96,7 +103,7 @@ node -e 'const s = JSON.parse(require("node:fs").readFileSync(".dw/install-state
96
103
 
97
104
  ### Checks de compatibilidade do upgrade
98
105
 
99
- Leia o `.dw/commands/dw-update.md` atualizado após o CLI terminar. Use `.dw/install-state.json` e o output `Installed version` do CLI para a diferença de versões: um pacote executado por `npx` não precisa ser resolvível pelo `node_modules` do consumidor. Estado novo ausente ou inválido é falha de verificação; não declare sucesso do update.
106
+ Leia o `.dw/commands/dw-update.md` atualizado após o CLI terminar. Use `.dw/install-state.json` e o output `Installed version` do CLI para a diferença de versões: um pacote executado por `npx` não precisa ser resolvível pelo `node_modules` do consumidor. Estado novo ausente ou inválido é falha de verificação; não declare sucesso do update. A versão lida no passo 4 tem de ser igual ao lado direito da linha `Installed version: <antiga> -> <nova>` do CLI; se essa linha faltar, ou as versões diferirem, o CLI não terminou e o update falhou.
100
107
 
101
108
  Em um upgrade de versão anterior à 2.3.0 (ou versão legada desconhecida):
102
109
 
@@ -116,6 +123,7 @@ Apresente ao usuário:
116
123
  - Resumo do que o output do `update` mostrou (arquivos copiados, wrappers gerados, MCPs configurados)
117
124
  - As `Post-update agent actions` impressas pelo CLI
118
125
  - Quaisquer avisos ou erros
126
+ - Toda linha `[moved]`, `[v<N>]`, `[orphan]`, `[legacy]` ou `[kept]` do `Skill migration`, o caminho `.dw/.migrated/<timestamp>/` e todo arquivo marcado `was not installed by dev-workflow` (adição do próprio time: ofereça trazê-lo de volta numa skill do time, nunca em `.dw/skills/`, que o update sobrescreve)
119
127
 
120
128
  ### 6. Executar Ações de Agente Pós-Update (Obrigatório)
121
129
 
@@ -144,19 +152,28 @@ Se invocado com `--rollback`:
144
152
  1. Listar snapshots em `.dw/.backup/`
145
153
  2. Se nenhum existir: PARAR e reportar "Nenhum snapshot disponível"
146
154
  3. Se mais de um existir: perguntar ao usuário qual restaurar (padrão: mais recente)
147
- 4. Confirmar com o usuário: "Restaurar snapshot `<path>`? Isso SOBRESCREVE `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/`, `.agents/skills/` e `.claude/settings.json`. Prosseguir? [s/N]"
155
+ 4. Confirmar com o usuário: "Restaurar snapshot `<path>`? Isso SUBSTITUI `.dw/commands/`, `.dw/templates/`, `.dw/references/`, `.dw/scripts/` e `.dw/skills/` pelas cópias do snapshot (quando ele as tem), copia o `.agents/skills/` do snapshot por cima do atual sem remover outras entradas, e restaura `.claude/settings.json` e `.dw/install-state.json`. `.dw/templates/overrides/` nunca é tocado. Prosseguir? [s/N]"
148
156
  5. Somente após `s`: copiar de volta
149
157
 
150
158
  ```bash
151
- cp -r "$SNAPSHOT_DIR/commands" .dw/
152
- cp -r "$SNAPSHOT_DIR/templates" .dw/
153
- cp -r "$SNAPSHOT_DIR/references" .dw/ 2>/dev/null
154
- cp -r "$SNAPSHOT_DIR/scripts" .dw/ 2>/dev/null
155
- [ -d "$SNAPSHOT_DIR/agents-skills" ] && cp -r "$SNAPSHOT_DIR/agents-skills" .agents/skills 2>/dev/null
159
+ SNAPSHOT_DIR=".dw/.backup/<timestamp-escolhido>" # o snapshot confirmado no passo 4
160
+ [ -d "$SNAPSHOT_DIR" ] || { echo "Snapshot não encontrado: $SNAPSHOT_DIR"; exit 1; }
161
+ # Pastas gerenciadas de .dw são substituídas, para não sobrar arquivo da release mais nova.
162
+ for d in commands references scripts skills; do
163
+ [ -d "$SNAPSHOT_DIR/$d" ] && rm -rf ".dw/$d" && cp -r "$SNAPSHOT_DIR/$d" .dw/
164
+ done
165
+ # .dw/templates/overrides/ é do dono: restaure os templates gerenciados em volta dele, nunca o remova.
166
+ if [ -d "$SNAPSHOT_DIR/templates" ]; then
167
+ find .dw/templates -mindepth 1 -maxdepth 1 ! -name overrides -exec rm -rf {} +
168
+ for f in "$SNAPSHOT_DIR/templates"/*; do [ "$(basename "$f")" = overrides ] || cp -r "$f" .dw/templates/; done
169
+ fi
170
+ # .agents/skills é compartilhada com as skills do próprio usuário: mescla, nunca substitui.
171
+ [ -d "$SNAPSHOT_DIR/agents-skills" ] && mkdir -p .agents/skills && cp -r "$SNAPSHOT_DIR/agents-skills/." .agents/skills/ 2>/dev/null
156
172
  [ -f "$SNAPSHOT_DIR/claude/settings.json" ] && cp "$SNAPSHOT_DIR/claude/settings.json" .claude/settings.json 2>/dev/null
173
+ [ -f "$SNAPSHOT_DIR/install-state.json" ] && cp "$SNAPSHOT_DIR/install-state.json" .dw/install-state.json 2>/dev/null
157
174
  ```
158
175
 
159
- 6. Reportar: snapshot restaurado, versão provavelmente recuperada (ler de `.dw/commands/dw-help.md` ou metadata se houver)
176
+ 6. Reportar: snapshot restaurado, e a versão do `.dw/install-state.json` restaurado (ou "unknown" quando o snapshot é anterior a ele). Snapshot de antes da 2.7.0 não tem `skills/`: `.dw/skills/` fica como estava, o que é inofensivo (comandos antigos leem `.agents/skills/`), e o próximo update aposenta de novo as cópias restauradas em `.agents/skills/`.
160
177
 
161
178
  ## Opções Avançadas
162
179
 
@@ -81,6 +81,11 @@ Este piso é estreito de propósito. Algo genuinamente destrutivo que não estej
81
81
  isso — aplique o mesmo critério: se a ação destrói trabalho sem segunda cópia, reescreve história
82
82
  compartilhada ou move uma credencial, pare e pergunte. Uma confirmação a mais custa uma mensagem.
83
83
 
84
+ O mesmo vale para as pastas de skills que os agentes compartilham — `.agents/skills/`, `.claude/skills/`,
85
+ `.codex/skills/`: elas guardam também skills do usuário e de outras ferramentas. Fora do `update`/`uninstall`
86
+ do próprio CLI, liste o que removeria e pergunte por entrada; mova o aprovado para `.dw/.migrated/<timestamp>/`,
87
+ nunca `rm`.
88
+
84
89
  ## Atribuição
85
90
 
86
91
  O modelo de duas camadas — um piso que regra de projeto só pode apertar, nunca afrouxar — foi adaptado do
@@ -80,7 +80,7 @@ services: []
80
80
  │ └── api/ (criado por `pnpm dlx @nestjs/cli` ou scaffold escolhido)
81
81
  ├── packages/
82
82
  │ └── shared/ (criado pelo /dw-new-project)
83
- ├── docker-compose.dev.yml (composto a partir de .agents/skills/docker-compose-recipes/)
83
+ ├── docker-compose.dev.yml (composto a partir de .dw/skills/docker-compose-recipes/)
84
84
  ├── .env.example (consolidado dos servicos selecionados)
85
85
  ├── .gitignore (por stack)
86
86
  ├── .dockerignore (por stack)
@@ -12,9 +12,12 @@
12
12
  * USD is a best-effort ESTIMATE from a local price table — tokens are exact.
13
13
  *
14
14
  * The same pass also counts which skills the session's tool calls referenced,
15
- * emitted as `skills` on the row. `/dw-skill-health` reads it as usage evidence.
16
- * An absent `skills` key means the row predates this instrumentation; `{}` means
17
- * the session was observed and nothing fired — those are different facts.
15
+ * emitted as `skills` on the row, and which dev-workflow commands it loaded
16
+ * (a read of `.dw/commands/<name>.md`, which every command wrapper performs, or a
17
+ * Skill-tool call naming a command), emitted as `commands`. `/dw-skill-health`
18
+ * reads both as usage evidence. An absent key means the row predates that
19
+ * instrumentation; `{}` means the session was observed and nothing fired —
20
+ * those are different facts.
18
21
  *
19
22
  * Contract: reads the SessionEnd payload as JSON on stdin. Fails SAFE — any
20
23
  * error exits 0 without writing, so a hook bug never disrupts the session.
@@ -70,7 +73,7 @@ function knownSkills() {
70
73
  return false;
71
74
  }
72
75
  };
73
- for (const base of ['.agents/skills', '.claude/skills']) {
76
+ for (const base of ['.dw/skills', '.agents/skills', '.claude/skills']) {
74
77
  const root = join(PROJECT_ROOT, base);
75
78
  if (!isDir(root)) continue;
76
79
  let top;
@@ -103,8 +106,29 @@ function knownSkills() {
103
106
  }
104
107
 
105
108
  // Matches a skills/ path inside a tool call's input, capturing at most two
106
- // segments so a grouped `group/skill` is preserved.
107
- const SKILL_PATH = /(?:\.agents|\.claude)\/skills\/([A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)?)\//g;
109
+ // segments so a grouped `group/skill` is preserved. `.dw/skills/` is where the
110
+ // bundled skills live; `.agents/` and `.claude/` hold wrappers, external and
111
+ // legacy copies.
112
+ const SKILL_PATH = /(?:\.dw|\.agents|\.claude)\/skills\/([A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)?)\//g;
113
+
114
+ // Matches the canonical command file every wrapper tells the agent to read.
115
+ const COMMAND_PATH = /\.dw\/commands\/([A-Za-z0-9._-]+)\.md/g;
116
+
117
+ // Commands this project has installed: the names usage counting may emit under
118
+ // `commands`. Their wrappers also sit under `.claude/skills/` and
119
+ // `.agents/skills/`, so knownSkills() sees the same names; a command name is
120
+ // always counted as a command, never as a skill.
121
+ function knownCommands() {
122
+ const names = new Set();
123
+ try {
124
+ for (const file of readdirSync(join(DW_DIR, 'commands'))) {
125
+ if (file.endsWith('.md')) names.add(file.slice(0, -3));
126
+ }
127
+ } catch {
128
+ /* no installed commands — nothing to count */
129
+ }
130
+ return names;
131
+ }
108
132
 
109
133
  // Count skill references in ONE assistant message.
110
134
  //
@@ -113,17 +137,22 @@ const SKILL_PATH = /(?:\.agents|\.claude)\/skills\/([A-Za-z0-9._-]+(?:\/[A-Za-z0
113
137
  // `tool_result` that returned the CONTENTS of a SKILL.md (those cite other
114
138
  // skills) and a user prompt that merely names one — both would report a skill as
115
139
  // fired when it never was. What this measures is loading, not obedience.
116
- function countSkillUses(msg, known, out) {
140
+ function countSkillUses(msg, known, out, commands = new Set(), commandOut = {}) {
117
141
  const content = msg && msg.content;
118
142
  if (!Array.isArray(content)) return;
119
143
  for (const block of content) {
120
144
  if (!block || block.type !== 'tool_use' || !block.input) continue;
121
- // One tool call is one reference per skill, however many times its input
122
- // names that skill. A grep over three files under the same skill directory
123
- // is one load, not three.
145
+ // One tool call is one reference per skill or command, however many times
146
+ // its input names it. A grep over three files under the same skill
147
+ // directory is one load, not three.
124
148
  const seen = new Set();
125
- if (block.name === 'Skill' && typeof block.input.skill === 'string' && known.has(block.input.skill)) {
126
- seen.add(block.input.skill);
149
+ const seenCommands = new Set();
150
+ const note = (name) => {
151
+ if (commands.has(name)) seenCommands.add(name);
152
+ else if (known.has(name)) seen.add(name);
153
+ };
154
+ if (block.name === 'Skill' && typeof block.input.skill === 'string') {
155
+ note(block.input.skill);
127
156
  }
128
157
  let serialized;
129
158
  try {
@@ -136,24 +165,29 @@ function countSkillUses(msg, known, out) {
136
165
  let match;
137
166
  while ((match = SKILL_PATH.exec(serialized)) !== null) {
138
167
  const full = match[1];
139
- const name = known.has(full) ? full : full.split('/')[0];
140
- if (known.has(name)) seen.add(name);
168
+ note(known.has(full) ? full : full.split('/')[0]);
169
+ }
170
+ COMMAND_PATH.lastIndex = 0;
171
+ while ((match = COMMAND_PATH.exec(serialized)) !== null) {
172
+ if (commands.has(match[1])) seenCommands.add(match[1]);
141
173
  }
142
174
  }
143
175
  for (const name of seen) out[name] = (out[name] || 0) + 1;
176
+ for (const name of seenCommands) commandOut[name] = (commandOut[name] || 0) + 1;
144
177
  }
145
178
  }
146
179
 
147
180
  // Sum per-turn usage from the transcript, grouped by model, and count which
148
181
  // skills the session's tool calls referenced.
149
- function tallyTranscript(transcriptPath, known) {
182
+ function tallyTranscript(transcriptPath, known, commands = new Set()) {
150
183
  const byModel = {};
151
184
  const skills = {};
185
+ const commandUses = {};
152
186
  let raw;
153
187
  try {
154
188
  raw = readFileSync(transcriptPath, 'utf-8');
155
189
  } catch {
156
- return { byModel, skills };
190
+ return { byModel, skills, commands: commandUses };
157
191
  }
158
192
  for (const line of raw.split('\n')) {
159
193
  if (!line.trim()) continue;
@@ -166,7 +200,7 @@ function tallyTranscript(transcriptPath, known) {
166
200
  if (obj.type !== 'assistant') continue;
167
201
  const msg = obj && obj.message;
168
202
  try {
169
- countSkillUses(msg, known, skills);
203
+ countSkillUses(msg, known, skills, commands, commandUses);
170
204
  } catch {
171
205
  /* usage evidence is best-effort — never let it break cost tracking */
172
206
  }
@@ -179,7 +213,7 @@ function tallyTranscript(transcriptPath, known) {
179
213
  m.cache_write += u.cache_creation_input_tokens || 0;
180
214
  m.cache_read += u.cache_read_input_tokens || 0;
181
215
  }
182
- return { byModel, skills };
216
+ return { byModel, skills, commands: commandUses };
183
217
  }
184
218
 
185
219
  async function main() {
@@ -198,7 +232,13 @@ async function main() {
198
232
  } catch {
199
233
  known = new Set();
200
234
  }
201
- const { byModel, skills } = tallyTranscript(transcriptPath, known);
235
+ let installedCommands;
236
+ try {
237
+ installedCommands = knownCommands();
238
+ } catch {
239
+ installedCommands = new Set();
240
+ }
241
+ const { byModel, skills, commands } = tallyTranscript(transcriptPath, known, installedCommands);
202
242
  const modelNames = Object.keys(byModel);
203
243
  if (modelNames.length === 0) return process.exit(0); // nothing to record
204
244
 
@@ -223,9 +263,10 @@ async function main() {
223
263
  total_usd: Number(totalUsd.toFixed(4)),
224
264
  total_tokens: totalTokens,
225
265
  models,
226
- // Always emitted, even empty: `{}` records an observed session with no skill
227
- // reference, while an absent key marks a row written before this existed.
266
+ // Always emitted, even empty: `{}` records an observed session with no
267
+ // reference, while an absent key marks a row written before that existed.
228
268
  skills,
269
+ commands,
229
270
  };
230
271
 
231
272
  try {
@@ -37,7 +37,7 @@ This file describes how `/dw-new-project` and `/dw-dockerize` merge the standalo
37
37
 
38
38
  ```yaml
39
39
  # Generated by /dw-new-project on YYYY-MM-DD
40
- # Edit freely. Recipes live in .agents/skills/docker-compose-recipes/
40
+ # Edit freely. Recipes live in .dw/skills/docker-compose-recipes/
41
41
 
42
42
  services:
43
43
  # --- storage tier ---
@@ -52,7 +52,9 @@ Structure:
52
52
  └── runs/<YYYY-MM-DD>.jsonl # results of each eval run
53
53
  ```
54
54
 
55
- See `references/reference-dataset.md` for case-design principles, sampling from production, and when to expand the set.
55
+ Eval-first: run a baseline on the current code before the change; new-behavior cases must fail there. Compare runs case by case: a case that passed and now fails blocks, whatever the average says. Never tune against the `holdout` split.
56
+
57
+ See `references/reference-dataset.md` for case design, baseline, holdout, per-case drift and when to expand the set.
56
58
 
57
59
  ## Consistency (run-to-run stability)
58
60
 
@@ -1,6 +1,6 @@
1
1
  ## Integration with dev-workflow commands
2
2
 
3
- - `/dw-plan tasks`: when the PRD has an AI feature requirement, an eval-plan subtask is mandatory. The task references this skill's oracle ladder.
3
+ - `/dw-plan tasks`: when the PRD has an AI feature requirement, an eval-plan subtask is mandatory, ordered before the implementation subtasks: behavior spec, cases, baseline run (`references/reference-dataset.md` "Baseline before the change"). The task references this skill's oracle ladder.
4
4
  - `/dw-review --code-only`: AI feature PRs require a reference dataset + ≥2 oracle rungs (lower rungs FIRST). The constitution gate also applies — if the project has principles about AI feature reliability, they're enforced here.
5
- - `/dw-qa --ai`: new mode (when this skill is bundled) — runs the reference dataset against the current implementation, logs to `QA/logs/ai/<feature>-<date>.jsonl`, computes precision@k / faithfulness / outcome accuracy per the feature type.
5
+ - `/dw-qa --ai`: new mode (when this skill is bundled) — runs the reference dataset against the current implementation, logs to `QA/logs/ai/<feature>-<date>.jsonl`, computes precision@k / faithfulness / outcome accuracy per the feature type, and lists per-case flips against the prior run.
6
6
  - `/dw-bugfix` when the bug is an AI failure mode (hallucination, tool misuse, classification error): adds the failing case to the reference dataset BEFORE fixing — the case is now a regression test forever.