ll-skills 2.0.2 → 3.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.
Files changed (125) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +42 -20
  3. package/agents/ll-executor.md +2 -1
  4. package/agents/ll-verifier.md +1 -0
  5. package/assets/preamble.md +27 -39
  6. package/bin/install.js +4 -1
  7. package/hooks/ll-precompact.js +29 -1
  8. package/hooks/ll-skills-check-update.js +6 -6
  9. package/hooks/ll-state.js +30 -2
  10. package/package.json +3 -2
  11. package/scripts/evals/README.md +81 -0
  12. package/scripts/evals/cases/auto-dry-run/assert.sh +35 -0
  13. package/scripts/evals/cases/auto-dry-run/case.json +8 -0
  14. package/scripts/evals/cases/auto-dry-run/prompt.txt +1 -0
  15. package/scripts/evals/cases/auto-empty-repo/assert.sh +25 -0
  16. package/scripts/evals/cases/auto-empty-repo/case.json +8 -0
  17. package/scripts/evals/cases/auto-empty-repo/fixture/.gitkeep +0 -0
  18. package/scripts/evals/cases/auto-empty-repo/prompt.txt +1 -0
  19. package/scripts/evals/cases/decide-final-round/assert.sh +45 -0
  20. package/scripts/evals/cases/decide-final-round/case.json +8 -0
  21. package/scripts/evals/cases/decide-final-round/fixture/README.md +3 -0
  22. package/scripts/evals/cases/decide-final-round/prompt.txt +1 -0
  23. package/scripts/evals/cases/executor-block/assert.sh +33 -0
  24. package/scripts/evals/cases/executor-block/case.json +8 -0
  25. package/scripts/evals/cases/executor-block/prompt.txt +14 -0
  26. package/scripts/evals/cases/goal-autonomous/assert.sh +35 -0
  27. package/scripts/evals/cases/goal-autonomous/case.json +8 -0
  28. package/scripts/evals/cases/goal-autonomous/fixture/PLAN.md +42 -0
  29. package/scripts/evals/cases/goal-autonomous/fixture/PROGRESS.md +20 -0
  30. package/scripts/evals/cases/goal-autonomous/fixture/ROADMAP.md +29 -0
  31. package/scripts/evals/cases/goal-autonomous/fixture/package.json +8 -0
  32. package/scripts/evals/cases/goal-autonomous/fixture/src/money.js +6 -0
  33. package/scripts/evals/cases/goal-autonomous/fixture/test/reconcile.test.js +8 -0
  34. package/scripts/evals/cases/goal-autonomous/prompt.txt +1 -0
  35. package/scripts/evals/cases/implement-review-gate/assert.sh +37 -0
  36. package/scripts/evals/cases/implement-review-gate/case.json +8 -0
  37. package/scripts/evals/cases/implement-review-gate/prompt.txt +1 -0
  38. package/scripts/evals/cases/implement-stops-at-next/assert.sh +121 -0
  39. package/scripts/evals/cases/implement-stops-at-next/case.json +9 -0
  40. package/scripts/evals/cases/implement-stops-at-next/prompt.txt +1 -0
  41. package/scripts/evals/cases/preamble-no-ritual/assert.sh +17 -0
  42. package/scripts/evals/cases/preamble-no-ritual/case.json +8 -0
  43. package/scripts/evals/cases/preamble-no-ritual/fixture/README.md +3 -0
  44. package/scripts/evals/cases/preamble-no-ritual/fixture/src/a.ts +3 -0
  45. package/scripts/evals/cases/preamble-no-ritual/prompt.txt +1 -0
  46. package/scripts/evals/cases/router-no-skill/assert.sh +33 -0
  47. package/scripts/evals/cases/router-no-skill/case.json +8 -0
  48. package/scripts/evals/cases/router-no-skill/fixture/PLAN.md +21 -0
  49. package/scripts/evals/cases/router-no-skill/fixture/README.md +7 -0
  50. package/scripts/evals/cases/router-no-skill/fixture/decisions/README.md +3 -0
  51. package/scripts/evals/cases/router-no-skill/prompt.txt +1 -0
  52. package/scripts/evals/cases/router-small/assert.sh +21 -0
  53. package/scripts/evals/cases/router-small/case.json +8 -0
  54. package/scripts/evals/cases/router-small/fixture/README.md +17 -0
  55. package/scripts/evals/cases/router-small/prompt.txt +1 -0
  56. package/scripts/evals/cases/scout-no-plan/assert.sh +41 -0
  57. package/scripts/evals/cases/scout-no-plan/case.json +8 -0
  58. package/scripts/evals/cases/scout-no-plan/prompt.txt +8 -0
  59. package/scripts/evals/cases/verifier-weakened-test/assert.sh +19 -0
  60. package/scripts/evals/cases/verifier-weakened-test/case.json +8 -0
  61. package/scripts/evals/cases/verifier-weakened-test/prompt.txt +13 -0
  62. package/scripts/evals/cases/verifier-weakened-test/setup.sh +19 -0
  63. package/scripts/evals/fixtures/manual-contract/out.json +29 -0
  64. package/scripts/evals/fixtures/manual-contract/out.txt +5 -0
  65. package/scripts/evals/fixtures/manual-contract/with-skill.json +46 -0
  66. package/scripts/evals/fixtures/router-no-skill/fail.txt +5 -0
  67. package/scripts/evals/fixtures/router-no-skill/out.json +27 -0
  68. package/scripts/evals/fixtures/router-no-skill/pass.txt +4 -0
  69. package/scripts/evals/lib/assert.sh +107 -0
  70. package/scripts/evals/lib/extract.js +73 -0
  71. package/scripts/evals/run.sh +369 -0
  72. package/scripts/fixtures/auto-closed/PLAN.md +5 -0
  73. package/scripts/fixtures/auto-closed/PROGRESS.md +20 -0
  74. package/scripts/fixtures/auto-closed/ROADMAP.md +6 -0
  75. package/scripts/fixtures/auto-closed/docs/DELIVERY.md +3 -0
  76. package/scripts/fixtures/auto-decisions/decisions/DEC-0001-taken-alone.md +13 -0
  77. package/scripts/fixtures/auto-decisions/decisions/DEC-0002-owner.md +13 -0
  78. package/scripts/fixtures/auto-noroadmap/PLAN.md +20 -0
  79. package/scripts/fixtures/auto-noroadmap/PROGRESS.md +11 -0
  80. package/scripts/fixtures/auto-verify-next/PLAN.md +5 -0
  81. package/scripts/fixtures/auto-verify-next/PROGRESS.md +18 -0
  82. package/scripts/fixtures/auto-verify-next/ROADMAP.md +5 -0
  83. package/scripts/fixtures/auto-verify-next/phases/01/PLAN.md +6 -0
  84. package/scripts/fixtures/evals-auto/auto-dry-run/pass.txt +18 -0
  85. package/scripts/fixtures/evals-auto/auto-empty-repo/pass.txt +2 -0
  86. package/scripts/fixtures/evals-auto/goal-autonomous/pass.txt +29 -0
  87. package/scripts/fixtures/lint-bad/folded-description/SKILL.md +13 -0
  88. package/scripts/fixtures/lint-bad/jargon-in-questions/SKILL.md +36 -0
  89. package/scripts/fixtures/lint-bad/model-invocation-false/SKILL.md +10 -0
  90. package/scripts/fixtures/next-bad/skills/ll-bad/SKILL.md +30 -0
  91. package/scripts/fixtures/next-good/skills/ll-good/SKILL.md +26 -0
  92. package/scripts/fixtures/project/BACKLOG.md +6 -5
  93. package/scripts/fixtures/project/PROGRESS.md +4 -0
  94. package/scripts/lint-contract.cjs +495 -0
  95. package/scripts/lint-prompts.sh +443 -0
  96. package/scripts/ll-tools.js +497 -450
  97. package/scripts/smoke-test.sh +481 -4
  98. package/skills/ll-auto/SKILL.md +74 -0
  99. package/skills/ll-auto/references/run.md +75 -0
  100. package/skills/ll-auto/references/stages.md +66 -0
  101. package/skills/ll-auto/scripts/ll-auto.js +345 -0
  102. package/skills/ll-brainstorm/SKILL.md +14 -12
  103. package/skills/ll-brainstorm/references/decision-policy.md +22 -12
  104. package/skills/ll-close/SKILL.md +8 -7
  105. package/skills/ll-close/references/delivery.md +3 -1
  106. package/skills/ll-decide/SKILL.md +21 -19
  107. package/skills/ll-decide/references/decision-policy.md +22 -12
  108. package/skills/ll-decide/references/decision-room.md +5 -3
  109. package/skills/ll-decide/references/interview.md +29 -13
  110. package/skills/ll-decide/references/plan-skeleton.md +14 -14
  111. package/skills/ll-decide/references/premise-gate.md +34 -20
  112. package/skills/ll-goal/SKILL.md +22 -4
  113. package/skills/ll-goal/references/goal-template.md +57 -0
  114. package/skills/ll-implement/SKILL.md +25 -22
  115. package/skills/ll-implement/references/briefs.md +2 -1
  116. package/skills/ll-implement/references/decision-policy.md +22 -12
  117. package/skills/ll-implement/references/phase-conversation.md +20 -12
  118. package/skills/ll-implement/references/phase-plan.md +23 -0
  119. package/skills/ll-oncall/SKILL.md +3 -2
  120. package/skills/ll-refine/SKILL.md +3 -2
  121. package/skills/ll-research/SKILL.md +3 -2
  122. package/skills/ll-resume/SKILL.md +9 -4
  123. package/skills/ll-update/SKILL.md +6 -1
  124. package/skills/ll-verify/SKILL.md +2 -1
  125. package/skills/ll-verify/references/verifier-briefs.md +3 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,58 @@
2
2
 
3
3
  Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/). A skill `ll-update` lê este arquivo para mostrar o que mudou entre a versão instalada e a publicada.
4
4
 
5
+ ## [3.1.0] - 2026-09-11
6
+
7
+ ### Adicionado
8
+
9
+ - Passo `board-switch` no helper: troca o marcador de fase antes da primeira onda gravar, e `passes` recusa gravar quando o marcador é de outra fase — a onda 1 não escreve mais no lugar da fase anterior (F-1).
10
+ - Coluna `note` e condição executável (`` `cmd` exit N ``) nas linhas de backlog nascidas em `ll-implement`; o epílogo lista quem ainda não é parseável e a fase roda `backlog-reconcile` a seco antes de fechar, reescrevendo a linha na hora (F-2).
11
+ - Linha de progresso por onda no terminal durante uma fase (`onda i/M — M2, M3 rodando`), no despacho e no retorno de cada marco (F-4).
12
+ - Lint rule 9 (`lint-prompts.sh`): nenhuma pergunta ao dono ou linha de contagem carrega `band-1`, `[DEC-`, `[D-` ou `ASM-`; os casos de eval que esperavam a sessão "nomear o comando" (`router-research`, `router-execute`, `router-large-opener`) foram apagados e `router-no-skill` prova o contrário — um pedido comum é feito na hora mesmo num repositório com estado; os asserts de `decide-final-round` e `implement-stops-at-next` seguem a nova redação.
13
+ - Teto de tamanho do helper em 760 linhas / 36 000 bytes (`DEC-0016-helper-ceiling-760-36000.md`).
14
+ - `phase-stats --since <data>` passa a incluir o próprio dia informado (F-12).
15
+ - `ll-resume` grava a resposta a uma decisão `WAITING` no próprio arquivo da decisão.
16
+ - Linhas de memória fora do repositório (`ll-brainstorm`, `ll-close`) declaradas na tabela de entregáveis (F-10).
17
+ - Segunda rodada completa do laboratório: `lab/scenarios/notes-api.md` ganha os turnos 8–24 (fechamento por milestone, pesquisa, decisão sem perguntas com roadmap de quatro fases e uma decisão `WAITING`, meta autônoma, verificação externa, sabotagem seguida de reverificação, oncall, feedback em docx, refino, `ll-auto --pause-at/--resume`), `lab/README.md` ganha o protocolo de sessão isolada (`CLAUDE_CONFIG_DIR` próprio, diálogo de confiança pré-aceito, sondagem a cada 5 minutos) e `lab/rubric.md` ganha as métricas de progresso visível, integridade do board e caminhos percorridos.
18
+
19
+ ### Corrigido
20
+
21
+ - `ll-implement --no-talk` nunca pergunta: o item que só você decide vira decisão `WAITING` e congela só os marcos que dependem dele; o resto da fase roda (era o que `ll-auto` já assumia).
22
+ - Skill só por comando explícito: o preâmbulo global não redireciona mais nenhum pedido para uma skill, em nenhum repositório, tenha ele estado do ll-skills ou não — a sessão responde ou faz o que foi pedido, e só nomeia um comando quando o dono pergunta qual usar (feedback do dono, 2026-09-11).
23
+ - O gate de premissas do `ll-decide` manda no máximo quatro perguntas num bloco só, com cabeçalhos limpos (sem `[PG-n]`, sem `banda 1` na tela); a restrição inventada por cautela deixou de ser pergunta — vira assunção `ASM-n [revisable]` com gatilho de revisão, contada como assunção.
24
+ - Pergunta cujas opções só diferem em rigor de checagem não é mais feita — vira decisão por ausência (F-8).
25
+ - A sala de decisão (`OPTIONS.html`) é entregue por caminho de arquivo antes da primeira pergunta, sem publicar artefato e sem chamar outra skill (F-5, `DEC-0017-decision-room-file-not-published.md`).
26
+ - As telas e as perguntas ao dono não usam mais `banda 1`, `DEC-`, `ASM-`; a linha de contagem virou `perguntas N · decisões só suas em aberto K` (F-3, `DEC-0018-plain-question-headers.md`).
27
+ - As skills chamam o helper pelo comando, nunca leem o código dele na tela do dono (F-7).
28
+ - Script de aceitação comitado com caminho absoluto ou que mata processo alheio (`pkill`, `killall`) vira bloqueio do verificador em vez de uma ressalva (F-6).
29
+ - O primeiro turno de um pedido grande para no comando e num plano de até 5 linhas, sem escolher formato de id nem biblioteca de IO antes da hora (F-9).
30
+ - O laboratório aceita o diálogo de confiança da pasta antes do primeiro turno, num `CLAUDE_CONFIG_DIR` isolado — a primeira tentativa da rodada de 2026-09-11 tinha morrido nesse diálogo (F-11, `DEC-0019-lab-round-2-scope.md`).
31
+
32
+ ### Alterado
33
+
34
+ - `lab/rubric.md`: a lista de jargão troca `gate` por `regime` (a classe de roteamento já tem nome próprio no `CLAUDE.md`; nada em `lab/` deveria repeti-la na tela do dono).
35
+
36
+ ## [3.0.0] - 2026-09-10
37
+
38
+ ### Adicionado
39
+
40
+ - **`ll-auto`**: skill que roda o ciclo inteiro a partir do estado em disco — research, brainstorm, decide, fases, verificações, close — seguindo o `SKILL.md` de cada etapa em vigor, com as flags `"<objetivo>"`, `--research`, `--brainstorm`, `--interactive`, `--auto-decision`, `--pause-at <stage|N>`, `--from N`, `--to N`, `--only N`, `--verify all`, `--redo <stage>`, `--dry-run` e `--resume`; escreve `docs/AUTO.md` (objetivo, flags, roteiro, status por etapa) e lista no final toda decisão tomada sozinha, marcada `[decided by absence — revisable]`.
41
+ - Helper `skills/ll-auto/scripts/ll-auto.js` (Node puro, sem dependências, próprio da skill): `detect`, `roteiro`, `next-cmd`, `report`, `auto-md`.
42
+ - `--no-talk` em `ll-decide` e `ll-close`: nenhum bloco de pergunta é enviado; itens de faixa 2/3 tomam a recomendação como `ASM-n [decided by absence — revisable]`, itens de faixa 1 viram decisão `WAITING`.
43
+ - **`ll-goal --autonomous`**: modo que aponta o texto do `/goal` para `ll-auto --auto-decision` até a entrega inteira fechar, em vez de uma fase; sem a parte BUDGET, frontmatter com `mode: autonomous` em vez de `ceiling_usd`.
44
+ - Casos de eval `auto-dry-run` e `auto-empty-repo` (`scripts/evals/cases/`), a seção offline `evals-auto` do `scripts/smoke-test.sh` e uma repetição real de ambos via `scripts/evals/run.sh`.
45
+
46
+ ### Quebras
47
+
48
+ - As skills não são mais invocadas pelo modelo — todas com `disable-model-invocation: true`.
49
+ - Preâmbulo sem roteador de pedidos.
50
+ - Descrições das skills reescritas em uma linha.
51
+
52
+ ### Alterado
53
+
54
+ - Lint rule 1 e 3 do `lint-prompts.sh`.
55
+ - Casos de eval `router-*` e `preamble-no-ritual` passam a exigir o comando nomeado e nenhuma chamada da ferramenta Skill; helper `no_tool_use` em `scripts/evals/lib/assert.sh`.
56
+
5
57
  ## [2.0.2] - 2026-09-08
6
58
 
7
59
  ### Alterado
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # LL Skills
2
2
 
3
- Um ciclo de trabalho para [Claude Code](https://claude.com/claude-code): 11 skills, 4 agentes, 3 hooks e um helper que compartilham o mesmo estado em arquivos versionados do repositório. Um preâmbulo roteador instalado no seu `~/.claude/CLAUDE.md` classifica cada pedido antes de agir pedido pequeno continua pequeno, pedido grande cai na skill certa sem você digitar o nome dela. O produto real é a fase: `ll-implement` roda conversa, plano, revisão adversarial, ondas de execução com TDD, verificação de contexto limpo e epílogo em **uma** invocação, e escreve tudo em disco à medida que acontece, para que uma compactação não perca nada.
3
+ Um ciclo de trabalho para [Claude Code](https://claude.com/claude-code): 12 skills, 4 agentes, 3 hooks e dois helpers que compartilham o mesmo estado em arquivos versionados do repositório. Um preâmbulo instalado no seu `~/.claude/CLAUDE.md` carrega o bloco de regras da casa delegação, decisões, prova que vale para qualquer skill que você chamar. O produto real é a fase: `ll-implement` roda conversa, plano, revisão adversarial, ondas de execução com TDD, verificação de contexto limpo e epílogo em **uma** invocação, e escreve tudo em disco à medida que acontece, para que uma compactação não perca nada.
4
4
 
5
5
  ## Instalação
6
6
 
@@ -10,7 +10,7 @@ Requer [Node.js](https://nodejs.org) 18+ (o mesmo que o Claude Code já usa).
10
10
  npx ll-skills@latest
11
11
  ```
12
12
 
13
- Reinicie o Claude Code ao final. As skills são standalone — sem o prefixo `ll-skills:` — e podem ser chamadas pelo nome (`/ll-implement 3`) ou escolhidas pelo roteador do preâmbulo.
13
+ Reinicie o Claude Code ao final. As skills são standalone — sem o prefixo `ll-skills:` — e são chamadas pelo nome (`/ll-implement 3`).
14
14
 
15
15
  ```bash
16
16
  npx ll-skills@latest --local # instala em ./.claude, só para o projeto atual
@@ -25,8 +25,9 @@ O que a instalação **escreve** (em `$CLAUDE_CONFIG_DIR` ou `~/.claude`):
25
25
 
26
26
  | Caminho | Conteúdo |
27
27
  |---|---|
28
- | `skills/ll-*/` | as 11 skills, com `SKILL.md` e `references/` |
28
+ | `skills/ll-*/` | as 12 skills, com `SKILL.md` e `references/` |
29
29
  | `skills/ll-{implement,verify,close}/scripts/ll-tools.js` | cópia do helper, uma por skill que o usa |
30
+ | `skills/ll-auto/scripts/ll-auto.js` | o helper da própria skill, executável |
30
31
  | `agents/ll-{executor,scout,verifier,reviewer}.md` | os 4 agentes |
31
32
  | `hooks/ll-{skills-check-update,state,precompact}.js` | os 3 hooks, executáveis |
32
33
  | `settings.json` | duas entradas em `SessionStart` (`startup\|resume\|compact`) e uma em `PreCompact`; backup em `settings.json.ll-skills.bak` |
@@ -35,22 +36,9 @@ O que a instalação **escreve** (em `$CLAUDE_CONFIG_DIR` ou `~/.claude`):
35
36
 
36
37
  O que a instalação apenas **imprime**, e nunca escreve: a política sugerida de `settings.json` (`assets/settings.suggested.json` — deny list, `autoCompactWindow`, cache, modelos por papel) e o diagnóstico de sobras de instalações antigas. Reinstalar é idempotente; a primeira instalação 2.x poda as skills 1.x pelo manifesto.
37
38
 
38
- ## Como funciona
39
+ ## Como as skills são chamadas
39
40
 
40
- O preâmbulo classifica todo pedido por três critérios lacuna de intenção, irreversibilidade e pegada — e anuncia o regime em uma linha antes de agir.
41
-
42
- | Regime | Gatilho | O que acontece | Skill |
43
- |---|---|---|---|
44
- | SMALL | verbo + alvo endereçável, ≤25 palavras, ~3 chamadas | lê o alvo, faz, verifica com um número | nenhuma |
45
- | FIX | "não era isso", "quebrou", "não sobe" | após 2 tentativas iguais, para, junta evidência, diagnostica | nenhuma |
46
- | RESEARCH | "pesquise", "compare", "docs oficiais", restrição não validada | frentes paralelas + contra-evidência + checagem de citação | `ll-research` |
47
- | OPS | deploy, apply, cutover, credencial, IP, "avise a infra" | pré-flight de capacidades e verdade por outro caminho | `ll-oncall` |
48
- | LARGE | ideia nova, "plano", horas de máquina, cria um lugar | plano de ataque em 5 linhas, depois o contrato | `ll-decide` |
49
- | EXECUTE | "implementa", "continua", marco com `passes: false` | a fase inteira em uma invocação | `ll-implement` |
50
- | RESUME | 1º turno num repo com PROGRESS.md, "onde paramos" | briefing de ≤20 linhas, nada escrito | `ll-resume` |
51
- | REFINE | produto rodando + "melhorar", "fiel ao protótipo" | uma rodada fechada de refino | `ll-refine` |
52
-
53
- Uma palavra sua vence o classificador (`direto`, `pesquise`, `plano`, `implementa`, `fecha`, `status`). E a regra que amarra o conjunto: **uma skill nunca chama outra**. Cada uma termina num arquivo dentro do repositório e imprime `▶ Next — /clear, depois <comando>`; quem cola é você.
41
+ Uma skill roda quando você digita `/ll-<nome>`. A sessão nunca inicia uma skill sozinha: quando o pedido parece o trabalho de uma delas, ela responde com o comando exato para você colar e para aí. Uma skill por turno nenhuma chama outra. Cada uma termina num arquivo dentro do repositório e imprime `▶ Next — /clear, depois <comando>`; quem cola é você. `ll-auto` é a única exceção: o único lugar que segue as instruções de outra skill, e só quando você digita `/ll-auto`.
54
42
 
55
43
  ## Ciclo de um projeto
56
44
 
@@ -58,7 +46,7 @@ Uma vez por milestone, com a contagem de prompts seus por etapa:
58
46
 
59
47
  | Etapa | Prompts | Sai disso |
60
48
  |---|---|---|
61
- | ideia → roteador | 1 | plano de ataque em 5 linhas (LARGE) |
49
+ | ideia → `/ll-brainstorm` ou `/ll-research` | 1 | plano de ataque em 5 linhas (LARGE) |
62
50
  | `ll-brainstorm` | 0–1 | mapa A/B/C + bateria de ≤4 → `DECISIONS.md` / `OPENING.md` |
63
51
  | `ll-research` | 0–1 | `docs/research-<tema>/` com SUMMARY, evidências e fontes |
64
52
  | `ll-decide` | 1 + cliques | `PLAN.md`, `ROADMAP.md`, `decisions/`, `PROGRESS.md` vazio |
@@ -89,7 +77,7 @@ Entre fases, `/clear`: sessão nova custa menos e erra menos que compactação.
89
77
  | `ll-brainstorm` | "tenho uma ideia", "vamos discutir", antes de abrir uma fase | `phases/NN/DECISIONS.md` ou `docs/decide/OPENING.md` |
90
78
  | `ll-research` | "pesquise", "compare A e B", restrição não validada; `--market` para mercado e preço | `docs/research-<tema>/` (SUMMARY + evidências + fontes datadas) |
91
79
  | `ll-decide` | "escreve o plano", segunda tentativa, ou feedback externo em docx/pdf/xlsx | `PLAN.md` §0–§11, `ROADMAP.md`, `decisions/`, ou `docs/review-<data>.md` |
92
- | `ll-goal` | antes de uma noite sem ninguém olhando | `docs/GOAL.md` + o texto de 9 partes para `/goal` |
80
+ | `ll-goal` | antes de uma noite sem ninguém olhando; `ll-goal --autonomous ["<objetivo>"]` cobre a entrega inteira | `docs/GOAL.md` + o texto de 9 partes para `/goal`; no modo autônomo, o texto mantém `ll-auto --auto-decision` rodando até a entrega fechar |
93
81
  | `ll-implement` | "implementa a fase N", "continua" | a fase entregue, `phases/NN/PLAN.md`, PROGRESS carimbado |
94
82
  | `ll-verify` | "confere se terminou de verdade", contrato público, dinheiro, dado de cliente | `VERIFICATION.md` com ledger FRESH/STALE e dois selos |
95
83
  | `ll-close` | "fecha", "pode arquivar"; `--milestone` arquiva as fases | `docs/DELIVERY.md`, retrospectiva, ROADMAP colapsado |
@@ -97,6 +85,30 @@ Entre fases, `/clear`: sessão nova custa menos e erra menos que compactação.
97
85
  | `ll-refine` | produto rodando: "melhorar as telas", "fiel ao protótipo" | uma rodada registrada no PROGRESS; modo `visual` até o veredito FIEL |
98
86
  | `ll-oncall` | `claude -n <papel>`, "vigie a cada 1h", deploy/apply/cutover | bloco `## Federation`, `docs/REQUESTS.md`, pré-flight do deploy |
99
87
  | `ll-update` | "atualiza o ll-skills", ou o aviso da sessão | o pacote atualizado, com o changelog mostrado antes |
88
+ | `ll-auto` | `/ll-auto "<objetivo>" [flags]` | `docs/AUTO.md` e o ciclo inteiro |
89
+
90
+ ### Fluxo autônomo
91
+
92
+ `ll-auto` lê o estado em disco (`detect`), corta a lista de etapas com as flags (`roteiro`) e segue cada etapa lendo o `SKILL.md` dela — a única skill que faz isso, e só porque você digitou o comando.
93
+
94
+ | Flag | Efeito |
95
+ |---|---|
96
+ | `--research` | entra `research` no roteiro, se não estiver `done` |
97
+ | `--brainstorm` | entra `brainstorm` no roteiro, se não estiver `done` |
98
+ | `--interactive` | tira o `--no-talk` de `ll-brainstorm`/`ll-implement`: essas etapas falam com você |
99
+ | `--auto-decision` | resolve toda decisão de dono para a opção recomendada e segue |
100
+ | `--pause-at <stage\|N>` | para depois daquela etapa ou fase, com `▶ Next — /clear, then ll-auto --resume` |
101
+ | `--from N` / `--to N` / `--only N` | corta as fases por número (`--only N` corta o `close`) |
102
+ | `--verify all` | roda `ll-verify NN` depois de cada fase, mesmo sem o epílogo pedir |
103
+ | `--redo <stage>` | força uma etapa `done` de volta para `todo` |
104
+ | `--dry-run` | imprime a tabela do roteiro e para, antes de escrever `docs/AUTO.md` |
105
+ | `--resume` | retoma as flags gravadas em `docs/AUTO.md`, a partir da primeira linha que não é `done` |
106
+
107
+ Num repositório vazio (sem pesquisa, sem `OPENING.md`, sem `PLAN.md`) e sem objetivo, `ll-auto` não pergunta nada: imprime o comando que completa (`/ll-auto "<objetivo>" [--research] [--brainstorm]`) e para. Toda decisão de dono tomada sozinha ao longo do run (com `--auto-decision`) entra listada no fim, cada uma marcada `[decided by absence — revisable]`.
108
+
109
+ #### Para rodar sem parar
110
+
111
+ `ll-goal --autonomous` escreve o texto, você cola em `/goal <texto>`, e o loop do `/goal` reinicia `ll-auto --auto-decision` sempre que a sessão parar antes da entrega; decisões tomadas sozinhas ficam listadas no fim (`[decided by absence — revisable]`); só dinheiro, produção ou dados de cliente param a corrida.
100
112
 
101
113
  ## Agentes
102
114
 
@@ -132,6 +144,16 @@ Nenhum agente despacha subagente (profundidade 1) e nenhum pergunta ao dono: uma
132
144
  | `epilogue` | monta os dados do fim de fase e diz o próximo comando |
133
145
  | `phase-stats` | dias com trabalho, dias ociosos, commits por tipo, razão teste/feature |
134
146
 
147
+ `skills/ll-auto/scripts/ll-auto.js` é o helper próprio da skill `ll-auto` — Node puro, sem dependências, nunca uma cópia de `ll-tools.js`.
148
+
149
+ | Comando | O que faz |
150
+ |---|---|
151
+ | `detect` | lê o estado em disco e devolve a tabela de etapas (`research` … `close`) com status `todo`/`half`/`done` |
152
+ | `roteiro` | corta a tabela do `detect` pelas flags e devolve a lista ordenada de etapas a rodar |
153
+ | `next-cmd` | lê o comando da última linha `▶ Next` de um arquivo |
154
+ | `report` | lista os `decisions/*.md` marcados `[decided by absence — revisable]` |
155
+ | `auto-md` | monta o corpo de `docs/AUTO.md` (objetivo, flags, roteiro, decisões, log) |
156
+
135
157
  ## Arquivos de estado no repositório
136
158
 
137
159
  ```
@@ -22,6 +22,7 @@ You execute one milestone of a phase plan. You do not plan, do not decide and do
22
22
  2. The project's `CLAUDE.md`.
23
23
  3. The `### M<n>` blocks of previous waves in `PROGRESS.md`: what was built before you and what they left in `not_verified:`.
24
24
  4. Every file in your milestone's `read_first:`, and the section of `phases/NN/CODE-CONTEXT.md` the brief names.
25
+ 5. The brief itself, field by field: MILESTONE, PLAN, CONTEXT, FILES, WAVE (your wave and the milestones running in parallel — their files are not yours), TDD, ACCEPTANCE, MODEL, DEC RESERVED (the only ids you may cite in `questions:`), INPUTS (paths that already exist), DO NOT, RETURN.
25
26
 
26
27
  Nothing else. One Read per file; do not re-read a range already in context. Grep before Read on files over 2,000 lines.
27
28
 
@@ -89,7 +90,7 @@ commits: <sha7> test(M<n>): <msg> · <sha7> feat(M<n>): <msg>
89
90
  commands: <acceptance command> → "<last output line>" · <other command> → "<last line>"
90
91
  deviations: none | <rule applied> — <what> (<file:line>)
91
92
  questions: none | <decision requested> — <the option you would take and why>
92
- backlog: none | <deviation|stub|test-not-run|debt|domain-question> · <what> · `<closing command>` exit 0
93
+ backlog: none | <type> · <what> · `<cmd>` exit 0 · note: <prose>
93
94
  not_verified: <what this milestone does not prove; one item per line, or none>
94
95
  ```
95
96
 
@@ -50,6 +50,7 @@ Levels for a phase criterion: exists (the file) → substantive (not a stub: no
50
50
  - `git diff <range> -- <test files>`: an assertion loosened, a test skipped, deleted or made unconditional without a `DEC-` id in the commit or in `decisions/` → `BLOCKS: process`.
51
51
  - each milestone with `tdd: yes`: `git log` shows `test(M<n>)` before `feat(M<n>)`; missing or inverted → `BLOCKS: process`.
52
52
  - files a milestone's block names that do not exist in HEAD, or commits it lists that git does not have → `BLOCKS: report`.
53
+ - a committed script under `phases/` or `scripts/` with an absolute home path, `pkill -f` or `killall` → `BLOCKS: process` (a disconfirmation about a committed artifact is a BLOCK, not a reservation).
53
54
 
54
55
  ## The 8 plan questions (mode plan)
55
56
 
@@ -1,36 +1,21 @@
1
1
  <!-- ll-skills:preamble v1 -->
2
2
  # ll-skills — how this session works
3
3
 
4
- ## Route every request before acting
5
- Classify every request by three criteria — intent gap (does it say what it wants, or only what
6
- hurts?), irreversibility (leaves the repo, costs money, touches prod?) and footprint (one file, one
7
- service, one system?) — and state the regime and the reason in one line before doing anything.
8
- - SMALL: verb + addressable target, ≤25 words, fits in ~3 tool calls → read the target, do what is
9
- authorized, verify with a number, label provenance; no skill, no file, no subagent.
10
- - FIX: "não era isso", "quebrou", "não sobe" → after 2 failed attempts of the same kind, stop, write
11
- what was ruled out, gather evidence, present diagnosis + one question with options; fix AND root cause.
12
- - RESEARCH: "pesquise", "compare", "docs oficiais", unvalidated restriction → `ll-research`.
13
- - OPS: deploy, apply, cutover, credential, IP, "avise a infra" → `ll-oncall` (ops mode).
14
- - LARGE: new idea, "plano", hours of machine time, the request creates a place (folder, repo) →
15
- 5-line plan of attack, then `ll-decide project`, or `ll-research <topic>` first when intent is missing.
16
- - EXECUTE: `phases/NN/PLAN.md` has a milestone with `passes: false`, or "implementa" / "continua" /
17
- "roda a fase N" → `ll-implement N`.
18
- - RESUME: first turn in a repo with PROGRESS.md; "status", "onde estamos", "o que tenho pra decidir" → `ll-resume`.
19
- - REFINE: product running + "melhorar"; external feedback (docx, pdf, sheet); "fiel ao protótipo" →
20
- `ll-refine`, or `ll-decide feedback`.
21
- One word from the owner beats the classifier: direto → SMALL; pesquise → RESEARCH; plano → LARGE;
22
- goal → `ll-goal N`; implementa / continua → EXECUTE; fecha → `ll-close`; status → RESUME; a skill
23
- named as a suffix of the request also counts. Never change regime silently: when small turns large (bigger
24
- root cause, operational pain, chained deliveries, a new place), say so in one line and offer once.
25
- Never in SMALL: spec, plan, PROGRESS, VERIFICATION, premortem, interview, a subagent for what fits in
26
- 3 calls, questions about implementation, two questions in a row, automatic commits.
27
-
28
4
  ## Skills
29
- A skill never invokes another skill and never decides the owner's next request; `ll-implement` covers one
30
- phase per invocation. Every skill ends in a repository file and prints "▶ Next `/clear` then `<command>`" for
31
- the owner to paste; that line ends the turn, no tool call follows it. State lives at the repo root (`PLAN.md`,
32
- `PROGRESS.md`, `phases/`, `decisions/`), never in a subfolder, written as it happens. Reply to the owner in
33
- Portuguese, in their words (marco, onda, gate, contexto limpo, fiel); every file is English. Short answer, long proof.
5
+ A skill runs only when the owner types `/ll-<name>`. The session never starts one on its own, never runs one on the
6
+ owner's behalf, never calls the Skill tool on an ll skill and never redirects a request to a skill: whatever the owner
7
+ asks is answered or done as asked, in any repository, whether or not `PLAN.md`, `PROGRESS.md`, `phases/` or
8
+ `decisions/` exist. A command is named only when the owner asks which command to use. `ll-auto` is the single place
9
+ that follows another skill's instructions, and only while the owner invoked `/ll-auto`.
10
+ A request that is a verb plus an addressable target and fits in about three tool calls gets the work itself, not a
11
+ ritual: read the target, do what is authorized, verify with a number, label provenance; no spec, no plan, no PROGRESS
12
+ entry, no VERIFICATION, no premortem, no interview, no subagent, no automatic commit, no two questions in a row. When
13
+ a small request turns out to be large (a bigger root cause, a chained delivery, a new folder or repo), say so in one
14
+ line. A skill never invokes another skill and never decides the owner's next request; `ll-implement` covers one phase
15
+ per invocation. Every skill ends in a repository file and prints "▶ Next — /clear, then <command>" for the owner to
16
+ paste; that line ends the turn, no tool call follows it. State lives at the repo root (`PLAN.md`, `PROGRESS.md`,
17
+ `phases/`, `decisions/`), never in a subfolder, written as it happens. Reply to the owner in Portuguese, in their
18
+ words (marco, onda, gate, contexto limpo, fiel); every file is English. Short answer, long proof.
34
19
 
35
20
  ## Delegation
36
21
  The session orchestrates; subagents execute, verify, scout and review, never orchestrate; depth 1 — an
@@ -45,19 +30,20 @@ unbiased judge and design; haiku never executes or verifies. The reviewer is nev
45
30
  executor. The per-role profile lives in PLAN.md §7 and is read every wave.
46
31
 
47
32
  ## Decisions
48
- Band 1 — ask, never decide alone: money above the round's ceiling; irreversible outside the repo
49
- (push that deploys, apply with destroy, credential in a new place, writes to prod, customer data);
50
- price, packaging or a promise to a customer; scope cut of the round; the number the owner will look
51
- at (denominator, window, what counts as an event); a recorded rule contradicted by new evidence.
33
+ Band 1 — ask, never decide alone: irreversible outside the repo (push that deploys, apply with
34
+ destroy, credential in a new place, writes to prod, customer data); price, packaging or a promise to
35
+ a customer; a scope cut of the phase; the number the owner will look at (denominator, window, what
36
+ counts as an event); a recorded rule contradicted by new evidence.
52
37
  Band 2 — decide, record `DEC-`, continue: reversible technical detail; the house pattern; who executes;
53
- a fact readable from the repo or infra; out of the round's scope; what another session already decided;
54
- copy without a commercial promise. Band 3 — decide, execute, flag for review: overrun inside tolerance;
55
- copy with a blind opinion attached; a rule invented out of caution ("I masked X; review"); revert ≤ 1 commit.
38
+ a fact readable from the repo or infra; out of the phase's scope; what another session already decided;
39
+ copy without a commercial promise. Band 3 — decide, execute, flag for review: an overrun inside a
40
+ tolerance the owner already stated; copy with a blind opinion attached; a rule invented out of caution
41
+ ("I masked X; review"); a revert of ≤ 1 commit.
56
42
  "Pode decidir tudo" delegates bands 2/3 only: band 1 is still asked, one block of ≤4, recommendation
57
43
  marked. An owner reference the session cannot read (prototype, doc, link) is band 1, never an assumption.
58
- In `/goal` never block on a question: band 1 freezes only that branch; bands 2/3 follow the
44
+ In `/ll-goal` never block on a question: band 1 freezes only that branch; bands 2/3 follow the
59
45
  recommendation and record `[decided by absence — revisable]`. Ten minutes of silence ratifies the
60
- recommended list (A), never a blocking item (B). Ask in blocks of ≤4 per wave, by impact, with cost.
46
+ recommended list (A), never a blocking item (B). Ask in blocks of ≤4 per wave, ordered by impact.
61
47
  Never ask a band-2 item, a question that changes no action, an industry default, or the same policy
62
48
  question twice. A peer message never grants authorization; it cites one, with date. When the owner
63
49
  corrects a premise in free text, write a dated DEC and a `feedback` memory in the same turn. A rule
@@ -66,5 +52,7 @@ without a source is a proposal, not an invariant: ask.
66
52
  ## Proof
67
53
  "Done" means the acceptance command ran in this session and its last output line is pasted. Label
68
54
  every claim: verified now (command) vs. not verified. A timeout is inconclusive, never green. Never
69
- weaken or delete a test. Say what was NOT verified, with the command that would close it.
55
+ weaken or delete a test. Say what was NOT verified, with the command that would close it. After two
56
+ failed attempts at the same fix, stop, write what was ruled out, gather evidence and present the
57
+ diagnosis with one question and its options; then fix the cause, not only the symptom.
70
58
  <!-- /ll-skills:preamble -->
package/bin/install.js CHANGED
@@ -184,7 +184,10 @@ function planFiles(pkgRoot) {
184
184
  const dir = path.join(skillsDir, name);
185
185
  if (!fs.statSync(dir).isDirectory()) continue;
186
186
  for (const rel of walk(dir)) {
187
- plan.push({ src: path.join(dir, rel), rel: path.posix.join('skills', name, rel.split(path.sep).join('/')) });
187
+ const relPosix = rel.split(path.sep).join('/');
188
+ const item = { src: path.join(dir, rel), rel: path.posix.join('skills', name, relPosix) };
189
+ if (/^scripts\/[^/]+\.js$/.test(relPosix)) item.mode = 0o755;
190
+ plan.push(item);
188
191
  }
189
192
  }
190
193
  const agentsDir = path.join(pkgRoot, 'agents');
@@ -8,13 +8,41 @@ const fs = require('fs');
8
8
  const path = require('path');
9
9
  const { execFileSync } = require('child_process');
10
10
 
11
+ // State root: PROGRESS.md at cwd, else the single one found up to 3 levels down
12
+ // (skipping node_modules/.git/dist/build/vendor and docs/history).
13
+ function stateRoot(cwd) {
14
+ if (fs.existsSync(path.join(cwd, 'PROGRESS.md'))) return cwd;
15
+ const skip = new Set(['node_modules', '.git', 'dist', 'build', 'vendor', 'fixtures', 'fixture', 'test', 'tests']);
16
+ const found = [];
17
+ const walk = (dir, depth) => {
18
+ if (depth > 3 || found.length > 1) return;
19
+ let ents;
20
+ try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
21
+ for (const e of ents) {
22
+ if (!e.isDirectory() || skip.has(e.name)) continue;
23
+ const sub = path.join(dir, e.name);
24
+ if (path.relative(cwd, sub) === path.join('docs', 'history')) continue;
25
+ if (fs.existsSync(path.join(sub, 'PROGRESS.md'))) found.push(sub); else walk(sub, depth + 1);
26
+ }
27
+ };
28
+ walk(cwd, 1);
29
+ if (found.length > 1) {
30
+ // several candidates: keep those with an ll-state block, then the most recently written
31
+ const stamp = (d) => { try { return fs.statSync(path.join(d, 'PROGRESS.md')).mtimeMs; } catch { return 0; } };
32
+ const withState = found.filter((d) => { try { return /<!--\s*ll-state\s*-->/.test(fs.readFileSync(path.join(d, 'PROGRESS.md'), 'utf8')); } catch { return false; } });
33
+ const pool = withState.length ? withState : found;
34
+ return pool.sort((a, b) => stamp(b) - stamp(a))[0];
35
+ }
36
+ return found.length === 1 ? found[0] : cwd;
37
+ }
38
+
11
39
  function main() {
12
40
  let input = {};
13
41
  try { input = JSON.parse(fs.readFileSync(0, 'utf8')); } catch { input = {}; }
14
42
  const cwd = typeof input.cwd === 'string' && input.cwd ? input.cwd : process.cwd();
15
43
  const trigger = typeof input.trigger === 'string' && input.trigger ? input.trigger : 'auto';
16
44
 
17
- const file = path.join(cwd, 'PROGRESS.md');
45
+ const file = path.join(stateRoot(cwd), 'PROGRESS.md');
18
46
  let body;
19
47
  try { body = fs.readFileSync(file, 'utf8'); } catch { return; }
20
48
 
@@ -4,8 +4,8 @@
4
4
  // Hook SessionStart do ll-skills. Instalado em <configDir>/hooks/ pelo bin/install.js.
5
5
  //
6
6
  // Modo leitor (sem argumentos, foreground, sem rede):
7
- // o cache da execução anterior e, se houver versão mais nova registrada para a
8
- // versão instalada agora, emite um systemMessage curto. Depois dispara o modo worker
7
+ // reads the cache of the previous run and, when a newer version is recorded for the
8
+ // version installed now, emits a short systemMessage. Then it starts the worker mode
9
9
  // em background e sai.
10
10
  //
11
11
  // Modo worker (--worker, background, com rede):
@@ -13,8 +13,8 @@
13
13
  // está no registro e a instalação veio de `npx github:`, cai para `git ls-remote` e
14
14
  // compara o SHA. Regrava o cache.
15
15
  //
16
- // Regra de ouro: nunca atrasar o início da sessão, nada em stderr, nada fora do
17
- // próprio cache. Qualquer falha termina em silêncio com exit 0.
16
+ // Golden rule: never delay the session start, nothing on stderr, nothing outside
17
+ // its own cache. Any failure ends silently with exit 0.
18
18
 
19
19
  const fs = require('fs');
20
20
  const path = require('path');
@@ -111,7 +111,7 @@ function worker(installed) {
111
111
  return;
112
112
  }
113
113
 
114
- // Pacote ainda não publicado: referência remota confiável se a instalação veio do GitHub.
114
+ // Package not published yet: a remote reference is reliable only when installed from GitHub.
115
115
  const info = readJson(path.join(STATE_DIR, 'install.json'));
116
116
  if (info && info.source === 'github' && info.sha) {
117
117
  const remote = gitRemoteSha();
@@ -152,6 +152,6 @@ function main() {
152
152
  try {
153
153
  main();
154
154
  } catch {
155
- /* silêncio */
155
+ /* silence */
156
156
  }
157
157
  process.exit(0);
package/hooks/ll-state.js CHANGED
@@ -64,7 +64,7 @@ function parseStateBlockLite(bl) {
64
64
  if (!line.trim() || /^\s*#/.test(line)) continue;
65
65
  let m = /^phase:\s*(.*)$/.exec(line);
66
66
  if (m) { st.phase = String(llScalar(m[1])); inM = false; continue; }
67
- if (/^milestones:\s*$/.test(line)) { inM = true; continue; }
67
+ if (/^milestones:\s*(\{\s*\})?$/.test(line)) { inM = true; continue; }
68
68
  m = /^(\s*)(M\d+|G-\d+):\s*\{(.*)\}\s*$/.exec(line);
69
69
  if (m && inM) {
70
70
  st.milestones[m[2]] = llScalar('{' + m[3] + '}');
@@ -144,10 +144,38 @@ function build(cwd, source) {
144
144
  return out.slice(0, MAX_LINES - 2).concat(['', board.text]);
145
145
  }
146
146
 
147
+ // State root: PROGRESS.md at cwd, else the single one found up to 3 levels down
148
+ // (skipping node_modules/.git/dist/build/vendor and docs/history).
149
+ function stateRoot(cwd) {
150
+ if (fs.existsSync(path.join(cwd, 'PROGRESS.md'))) return cwd;
151
+ const skip = new Set(['node_modules', '.git', 'dist', 'build', 'vendor', 'fixtures', 'fixture', 'test', 'tests']);
152
+ const found = [];
153
+ const walk = (dir, depth) => {
154
+ if (depth > 3 || found.length > 1) return;
155
+ let ents;
156
+ try { ents = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
157
+ for (const e of ents) {
158
+ if (!e.isDirectory() || skip.has(e.name)) continue;
159
+ const sub = path.join(dir, e.name);
160
+ if (path.relative(cwd, sub) === path.join('docs', 'history')) continue;
161
+ if (fs.existsSync(path.join(sub, 'PROGRESS.md'))) found.push(sub); else walk(sub, depth + 1);
162
+ }
163
+ };
164
+ walk(cwd, 1);
165
+ if (found.length > 1) {
166
+ // several candidates: keep those with an ll-state block, then the most recently written
167
+ const stamp = (d) => { try { return fs.statSync(path.join(d, 'PROGRESS.md')).mtimeMs; } catch { return 0; } };
168
+ const withState = found.filter((d) => { try { return /<!--\s*ll-state\s*-->/.test(fs.readFileSync(path.join(d, 'PROGRESS.md'), 'utf8')); } catch { return false; } });
169
+ const pool = withState.length ? withState : found;
170
+ return pool.sort((a, b) => stamp(b) - stamp(a))[0];
171
+ }
172
+ return found.length === 1 ? found[0] : cwd;
173
+ }
174
+
147
175
  function main() {
148
176
  const input = readStdin();
149
177
  const cwd = typeof input.cwd === 'string' && input.cwd ? input.cwd : process.cwd();
150
- const lines = build(cwd, input.source);
178
+ const lines = build(stateRoot(cwd), input.source);
151
179
  if (!lines || !lines.length) return;
152
180
  process.stdout.write(JSON.stringify({
153
181
  hookSpecificOutput: { hookEventName: 'SessionStart', additionalContext: lines.join('\n').trim() },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ll-skills",
3
- "version": "2.0.2",
4
- "description": "Evidence-driven development pipeline for Claude Code: router preamble, 11 skills (brainstorm, research, decide, goal, implement, verify, close, resume, refine, oncall, update), 4 agents, 3 hooks and a state helper",
3
+ "version": "3.1.0",
4
+ "description": "Evidence-driven development pipeline for Claude Code: router preamble, 12 skills (auto, brainstorm, research, decide, goal, implement, verify, close, resume, refine, oncall, update), 4 agents, 3 hooks and a state helper",
5
5
  "bin": {
6
6
  "ll-skills": "bin/install.js"
7
7
  },
@@ -16,6 +16,7 @@
16
16
  "README.md"
17
17
  ],
18
18
  "scripts": {
19
+ "lint": "bash scripts/lint-prompts.sh && node scripts/lint-contract.cjs",
19
20
  "test": "bash scripts/smoke-test.sh"
20
21
  },
21
22
  "engines": {
@@ -0,0 +1,81 @@
1
+ # Behavioural evals
2
+
3
+ `smoke-test.sh` checks what the files say. These cases check what a session *does* with them: each
4
+ installs the package into a throwaway `CLAUDE_CONFIG_DIR`, runs `claude -p` against a throwaway
5
+ copy of a fixture repository, and scores the answer and the work tree with a shell assert.
6
+
7
+ bash scripts/evals/run.sh --dry-run --all # print the commands, call nothing
8
+ bash scripts/evals/run.sh --case router-small --reps 1 # one case, one rep
9
+ bash scripts/evals/run.sh --all # twelve cases, three reps
10
+
11
+ `--all` | `--case <id>` (repeatable) | `--reps N` (default 3) | `--model <id>` | `--dry-run`.
12
+ Exit 0 when every selected case passed in at least `min_pass` reps (`case.json`, capped at the
13
+ reps actually run, so `--reps 1` means 1 of 1).
14
+
15
+ ## Cost
16
+
17
+ Router cases are 1–8 turns and cost cents. The six agent and skill cases run 30–40 turns: dollars
18
+ per rep, tens of dollars for `--all --reps 3` — a skill that fans out subagents costs about a dollar
19
+ per turn-block, so keep routing caps low. Dry run first, then one cheap case.
20
+
21
+ ## Autonomous cases
22
+
23
+ `auto-dry-run`, `auto-empty-repo` and `goal-autonomous` run the unattended path end to end: ≤ 12
24
+ turns and cost cents, like the router cases. The prompt is the slash command exactly as the owner
25
+ types it (`/ll-auto --dry-run`, `/ll-auto`, `/ll-goal --autonomous "Deliver phases 07 and 08"`),
26
+ which `claude -p` expands; there is no agent, no fan-out. `goal-autonomous` scores the pasted `/goal`
27
+ text (`ll-auto --auto-decision`, ≤ 4000 chars) and the committed `docs/GOAL.md` (`mode: autonomous`,
28
+ `phase: all`). Their assert scripts are proven offline, without calling `claude -p`, by `npm test`
29
+ (section `evals-auto` in `scripts/smoke-test.sh`) against the fixed answers under
30
+ `scripts/fixtures/evals-auto/<case>/pass.txt`.
31
+
32
+ `max_turns` is a budget, not a measurement: the `num_turns` the result reports counts the skill's `!`
33
+ preprocessor Bash calls together with the model's own tool calls, and a run has ended `success` with
34
+ `num_turns 7` under `--max-turns 4`. Pin each cap above the highest count real reps show (`case.json`
35
+ `note`), so the cap only ever cuts a run that really went long.
36
+
37
+ ## Router cases
38
+
39
+ A skill runs only when the owner types it, so these cases score what the session does with a plain
40
+ request — never which command it names back.
41
+
42
+ | case | prompt | what it scores |
43
+ |---|---|---|
44
+ | `router-small` | `conta as linhas de README.md` | the answer itself: nothing written, no ritual, no Skill call |
45
+ | `router-no-skill` | a research request in a repo that carries `PLAN.md` and `decisions/` | the research itself: no command handed back, no `▶ Next`, no Skill call, nothing created |
46
+ | `preamble-no-ritual` | a one-line typo fix | no spec, no plan, no `PROGRESS.md`, no subagent |
47
+
48
+ A case that exercises a skill types the slash command in its `prompt.txt` (`/ll-implement 7`,
49
+ `/ll-decide project …`): a skill is never started from prose, so a prose prompt would score the
50
+ plain answer, not the skill.
51
+
52
+ ## Cases proven offline
53
+
54
+ The `router-no-skill` (research delivered, no command handed back), `decide-final-round`
55
+ (decision-room path before the first question, count line in plain words) and
56
+ `implement-stops-at-next` (wave line before the epilogue, helper never read) asserts are proven
57
+ without calling `claude -p` by `npm test` (section `evals-auto`), against the captures and answers
58
+ under `fixtures/router-no-skill/` — `out.json`, a compliant `pass.txt` and a `fail.txt` that only
59
+ hands a command back — and the inline captures the smoke test builds.
60
+
61
+ ## Results — outside the repo
62
+
63
+ Each run writes `$LL_EVAL_RESULTS/<YYYY-MM-DD-HHMM>/` (default `~/.claude/ll-skills-evals`, outside the repo): `RESULTS.md`,
64
+ `summary.json`, the installer log and, per rep, `out.json`, `out.txt`, `assert.log`. Work trees
65
+ live under `mktemp -d` outside the repo — so the session under test never discovers this project's
66
+ own `.claude/` or `CLAUDE.md` — and are kept; `RESULTS.md` prints their path.
67
+
68
+ ## Add a case
69
+
70
+ `cases/<id>/`: `case.json` (`max_turns`, `history`, `min_pass`, `agent`, `permission_mode`,
71
+ optional `reuse`), `prompt.txt` (`{{WORK}}` becomes the work tree's absolute path), optional
72
+ `fixture/` (else `scripts/fixtures/project`), optional `setup.sh <workdir>`, and
73
+ `assert.sh <workdir> <out.json> <out.txt>` sourcing `lib/assert.sh`.
74
+
75
+ ## Environment
76
+
77
+ `env -u CLAUDECODE`, `--strict-mcp-config`, `--permission-mode bypassPermissions` by default.
78
+ `--max-turns` works but is absent from `claude --help`. `--verbose` is required: without it
79
+ `--output-format json` prints only the `result` object, and the regime line — stated in the *first*
80
+ assistant message, before any tool call — cannot be read. A fresh `CLAUDE_CONFIG_DIR` has no auth:
81
+ `run.sh` symlinks `~/.claude/.credentials.json` into it (a copy goes stale on token refresh).
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env bash
2
+ # --dry-run: the stage table and the roteiro are printed, nothing is written, no skill starts.
3
+ . "$(cd "$(dirname "${BASH_SOURCE[0]}")/../../lib" && pwd)/assert.sh"
4
+
5
+ WORK="$1"; OUT_JSON="$2"; OUT_TXT="$3"
6
+
7
+ # The roteiro of the shared fixture, tolerant to a table or a numbered list:
8
+ # each stage and its command on one line.
9
+ contains "$OUT_TXT" 'phase-07.*ll-implement 0?7' 'the roteiro carries the phase-07 row with ll-implement 07'
10
+ contains "$OUT_TXT" 'phase-08.*ll-implement 0?8' 'the roteiro carries the phase-08 row with ll-implement 08'
11
+ contains "$OUT_TXT" 'close.*ll-close' 'the roteiro carries the close row with ll-close'
12
+
13
+ # CA-04: the stage table from detect is printed too, decide already done.
14
+ contains "$OUT_TXT" 'decide.*done' 'the stage table is printed with decide: done'
15
+
16
+ no_path "$WORK/docs/AUTO.md" 'docs/AUTO.md was not written: the dry run stopped before opening the run'
17
+
18
+ # The capture files are the harness's, not the run's: a real rep keeps them under
19
+ # the results dir, the offline check hands them inside the scratch work tree.
20
+ dirty="$(git -C "$WORK" status --porcelain | while IFS= read -r line; do
21
+ path="${line#???}"
22
+ [ "$WORK/$path" = "$OUT_JSON" ] || [ "$path" = "$OUT_JSON" ] && continue
23
+ [ "$WORK/$path" = "$OUT_TXT" ] || [ "$path" = "$OUT_TXT" ] && continue
24
+ printf '%s\n' "$line"
25
+ done)"
26
+ if [ -z "$dirty" ]; then
27
+ ok 'git status --porcelain is empty: nothing was written'
28
+ else
29
+ fail "the working tree was changed: $(printf '%s' "$dirty" | tr '\n' ' ')"
30
+ fi
31
+
32
+ no_tool_use "$OUT_JSON" Skill 'no Skill tool call anywhere in the capture'
33
+ no_tool_use "$OUT_JSON" AskUserQuestion 'no AskUserQuestion tool call anywhere in the capture'
34
+
35
+ finish
@@ -0,0 +1,8 @@
1
+ {
2
+ "max_turns": 6,
3
+ "history": false,
4
+ "min_pass": 1,
5
+ "agent": null,
6
+ "permission_mode": "bypassPermissions",
7
+ "note": "Proves the --dry-run stop of ll-auto: the stage table and the roteiro are printed, docs/AUTO.md is not written and no skill is started. bypassPermissions so the helper's Bash runs unattended. Shared fixture: scripts/fixtures/project (phase-07 half, phase-08 planned)."
8
+ }
@@ -0,0 +1 @@
1
+ /ll-auto --dry-run