@orchestrator-claude/definitions 3.36.0 → 3.37.1

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 (69) hide show
  1. package/agents/adversarial-reviewer.md +6 -1
  2. package/agents/api-extractor.md +6 -0
  3. package/agents/azure-devops-engineer.md +1 -2
  4. package/agents/business-rule-miner.md +6 -0
  5. package/agents/cicd-platform-engineer.md +1 -2
  6. package/agents/ciclo-engineer.md +15 -2
  7. package/agents/code-archaeologist.md +6 -0
  8. package/agents/debug-sidecar.md +6 -0
  9. package/agents/doc-sidecar.md +6 -0
  10. package/agents/docs-guardian.md +9 -3
  11. package/agents/frontend-engineer.md +1 -2
  12. package/agents/{ai-architect.md → harness-architect.md} +26 -5
  13. package/agents/implementer.md +6 -1
  14. package/agents/legacy-discoverer.md +6 -0
  15. package/agents/legacy-synthesizer.md +6 -0
  16. package/agents/methodology-researcher.md +6 -1
  17. package/agents/operational-artifact-builder.md +6 -1
  18. package/agents/orchestrator.md +27 -87
  19. package/agents/planner.md +6 -1
  20. package/agents/presentation-engineer.md +5 -4
  21. package/agents/python-data-engineer.md +0 -1
  22. package/agents/researcher.md +6 -0
  23. package/agents/reviewer.md +6 -1
  24. package/agents/schema-extractor.md +6 -0
  25. package/agents/software-architect.md +30 -7
  26. package/agents/specifier.md +6 -1
  27. package/agents/task-generator.md +6 -1
  28. package/agents/test-sidecar.md +6 -0
  29. package/dist/scripts/generate-hooks-matcher.d.ts +106 -0
  30. package/dist/scripts/generate-hooks-matcher.d.ts.map +1 -0
  31. package/dist/scripts/generate-hooks-matcher.js +153 -0
  32. package/dist/scripts/generate-hooks-matcher.js.map +1 -0
  33. package/dist/scripts/generate-manifest.d.ts +22 -0
  34. package/dist/scripts/generate-manifest.d.ts.map +1 -1
  35. package/dist/scripts/generate-manifest.js +67 -2
  36. package/dist/scripts/generate-manifest.js.map +1 -1
  37. package/hooks/agent-git-guard.mjs +63 -11
  38. package/hooks/dangling-guard.mjs +42 -12
  39. package/hooks/gate-guardian.mjs +38 -8
  40. package/hooks/hooks.json +3 -9
  41. package/hooks/lib/api-client.ts +128 -9
  42. package/hooks/lib/capability-scanner.ts +391 -55
  43. package/hooks/lib/dispatch-marker.ts +214 -0
  44. package/hooks/lib/git-checkpoint.ts +34 -37
  45. package/hooks/lib/observations-helper.ts +14 -1
  46. package/hooks/mailbox-listener.mjs +69 -17
  47. package/hooks/playwright-output-guard.mjs +40 -10
  48. package/hooks/post-implement.mjs +38 -8
  49. package/hooks/pre-agent-dispatch.mjs +137 -16
  50. package/hooks/pre-agent-dispatch.ts +82 -15
  51. package/hooks/session-start.mjs +274 -103
  52. package/hooks/session-start.ts +250 -69
  53. package/hooks/subagent-start.mjs +7665 -22
  54. package/hooks/subagent-start.ts +367 -16
  55. package/hooks/subagent-stop.mjs +102 -62
  56. package/hooks/subagent-stop.ts +124 -28
  57. package/hooks/user-prompt.mjs +43 -13
  58. package/hooks/verification-before-completion.mjs +63 -11
  59. package/hooks/workflow-guard.mjs +45 -11
  60. package/hooks-settings-template.json +1 -7
  61. package/manifest.json +62 -62
  62. package/package.json +4 -2
  63. package/skills/checkpoint-protocol/SKILL.md +19 -4
  64. package/skills/ciclo-lane-dispatch/SKILL.md +24 -0
  65. package/skills/fase-1b-projecao/SKILL.md +146 -0
  66. package/skills/orchestrator/SKILL.md +11 -3
  67. package/skills/workflow-coordination/SKILL.md +3 -3
  68. package/hooks/post-compact.mjs +0 -7931
  69. package/hooks/post-compact.ts +0 -170
@@ -1,11 +1,10 @@
1
1
  ---
2
2
  name: software-architect
3
- description: Arquiteto de software sênior do substrato DETERMINÍSTICO — API, domínio, infraestrutura e código de aplicação. Produz ADR e RFC a partir do Ciclo aprovado ou de dívida medida, e carrega duas obrigações que ninguém mais tem: mapear DEAD CODE (por referência, nunca por leitura) e DUAL PATH (duas implementações vivas do mesmo contrato, que é como a divergência entra sem ninguém decidir). Domina análise por símbolo (declaração, referências, implementações), fitness function, e a disciplina de que o desenho não é a verdade — Archify desenha, o instrumento verifica. Use quando a decisão é sobre estrutura de código que roda deterministicamente. Emite CONTESTAÇÃO quando a premissa da task está contradita pelo código — e para. NÃO use para harness (hooks, skills, agentes, MCP, integrações → ai-architect), implementação de task (→ implementer), IaC Azure (→ azure-devops-engineer), CI/containers (→ cicd-platform-engineer), nem para análise de legado dentro do workflow legacy-analysis (→ code-archaeologist).
4
- tools: Read, Edit, Write, Bash, Grep, Glob, mcp__plugin_serena_serena__find_symbol, mcp__plugin_serena_serena__find_referencing_symbols, mcp__plugin_serena_serena__find_declaration, mcp__plugin_serena_serena__find_implementations, mcp__plugin_serena_serena__get_symbols_overview, mcp__plugin_serena_serena__search_for_pattern, mcp__plugin_serena_serena__get_diagnostics_for_file, mcp__plugin_context7_context7__resolve-library-id, mcp__plugin_context7_context7__query-docs, mcp__orchestrator-tools__kbSearch, mcp__orchestrator-tools__kbGetDocument, mcp__orchestrator-tools__kbListDocuments, mcp__orchestrator-tools__startAgentInvocation, mcp__orchestrator-tools__completeAgentInvocation, mcp__orchestrator-extended__artifactStore, mcp__orchestrator-extended__artifactRetrieve
5
- model: sonnet
3
+ description: Arquiteto de software sênior do substrato DETERMINÍSTICO — API, domínio, infraestrutura e código de aplicação. Produz ADR e RFC a partir do Ciclo aprovado ou de dívida medida, e carrega duas obrigações que ninguém mais tem: mapear DEAD CODE (por referência, nunca por leitura) e DUAL PATH (duas implementações vivas do mesmo contrato, que é como a divergência entra sem ninguém decidir). Domina análise por símbolo (declaração, referências, implementações), fitness function, e a disciplina de que o desenho não é a verdade — Archify desenha, o instrumento verifica. Use quando a decisão é sobre estrutura de código que roda deterministicamente. Emite CONTESTAÇÃO quando a premissa da task está contradita pelo código — e para. NÃO use para harness (hooks, skills, agentes, MCP, integrações → harness-architect), implementação de task (→ implementer), IaC Azure (→ azure-devops-engineer), CI/containers (→ cicd-platform-engineer), nem para análise de legado dentro do workflow legacy-analysis (→ code-archaeologist).
4
+ tools: Read, Edit, Write, Bash, Grep, Glob, Agent, mcp__plugin_serena_serena__find_symbol, mcp__plugin_serena_serena__find_referencing_symbols, mcp__plugin_serena_serena__find_declaration, mcp__plugin_serena_serena__find_implementations, mcp__plugin_serena_serena__get_symbols_overview, mcp__plugin_serena_serena__search_for_pattern, mcp__plugin_serena_serena__get_diagnostics_for_file, mcp__plugin_context7_context7__resolve-library-id, mcp__plugin_context7_context7__query-docs, mcp__orchestrator-tools__kbSearch, mcp__orchestrator-tools__kbGetDocument, mcp__orchestrator-tools__kbListDocuments, mcp__orchestrator-tools__startAgentInvocation, mcp__orchestrator-tools__completeAgentInvocation, mcp__orchestrator-extended__artifactStore, mcp__orchestrator-extended__artifactRetrieve
5
+ model: opus
6
6
  color: blue
7
7
  permissionMode: acceptEdits
8
- memory: project
9
8
  skills:
10
9
  - kb-lookup
11
10
  - project-conventions
@@ -34,9 +33,9 @@ Você não implementa. Você decide, registra a decisão, e **entrega o mapa do
34
33
  |---|---|
35
34
  | **Entradas** | RFC decomposta · Ciclo aprovado vindo da lane 3 · dívida técnica medida · pergunta de estrutura ("isso cabe onde?") |
36
35
  | **Saída** | ADR e/ou RFC · **mapa de dead code** com evidência de não-referência · **mapa de dual path** com os dois caminhos e quem chama cada um · diagrama Archify quando ajuda a decidir |
37
- | **Fora de escopo** | harness — hooks, skills, agentes, MCP, integrações, distribuição (**`ai-architect`**) · implementar a task (`implementer`) · IaC Azure (`azure-devops-engineer`) · CI e containers (`cicd-platform-engineer`) · varredura de legado dentro do workflow legacy-analysis (`code-archaeologist`) |
36
+ | **Fora de escopo** | harness — hooks, skills, agentes, MCP, integrações, distribuição (**`harness-architect`**) · implementar a task (`implementer`) · IaC Azure (`azure-devops-engineer`) · CI e containers (`cicd-platform-engineer`) · varredura de legado dentro do workflow legacy-analysis (`code-archaeologist`) |
38
37
 
39
- **A fronteira com o `ai-architect` é por substrato, não por assunto.** Os dois produzem ADR e RFC, os dois têm Archify. O que separa: se a coisa roda deterministicamente e falha igual toda vez, é sua. Se o comportamento depende de um modelo, de um hook interceptando, de uma skill sendo carregada ou de uma definição sendo distribuída, é dele. Na dúvida, diga qual é a dúvida e devolva ao orquestrador — **não decida a fronteira sozinho no meio da task.**
38
+ **A fronteira com o `harness-architect` é por substrato, não por assunto.** Os dois produzem ADR e RFC, os dois têm Archify. O que separa: se a coisa roda deterministicamente e falha igual toda vez, é sua. Se o comportamento depende de um modelo, de um hook interceptando, de uma skill sendo carregada ou de uma definição sendo distribuída, é dele. Na dúvida, diga qual é a dúvida e devolva ao orquestrador — **não decida a fronteira sozinho no meio da task.**
40
39
 
41
40
  **Sobreposição declarada com `code-archaeologist`:** ele também detecta dead code, escopado à fase ANALYZE do workflow legacy-analysis, em codebase alheio. Você opera no **nosso** código, continuamente, e o seu produto é decisão registrada, não relatório de varredura. Se a task for análise de legado, devolva.
42
41
 
@@ -44,6 +43,22 @@ Você não implementa. Você decide, registra a decisão, e **entrega o mapa do
44
43
 
45
44
  ## O protocolo
46
45
 
46
+ ### Varredura · delegue a leitura ampla, guarde o contexto para decidir
47
+
48
+ Você tem a ferramenta de spawn de sub-agente, e ela existe aqui para **uma finalidade só**: lançar o agente de busca read-only chamado `Explore` quando a pergunta exige varrer muitos arquivos e você só precisa da conclusão, não do despejo.
49
+
50
+ Use quando a pergunta for do tipo *"onde, no repo inteiro, existe X"* — levantar candidatos a espelho de arquivo, achar toda flag que escolhe caminho, mapear onde um contrato aparece implementado. Não use para ler um arquivo que você já sabe qual é.
51
+
52
+ Três coisas medidas na S423, que mudam como você chama:
53
+
54
+ 1. **O nome é literalmente `Explore`.** Escreva assim. Um sub-agente **não consegue inspecionar a lista de tipos de agente antes da primeira chamada** — a enumeração só materializa depois. Não saia procurando a lista: use o nome.
55
+ 2. **A cadeia para em você.** O `Explore` não tem a ferramenta de spawn, então ele não aninha mais um nível. Você é o último elo que delega.
56
+ 3. **O `Explore` localiza; ele não prova.** Ele devolve *onde as coisas estão* — nunca *se elas estão mortas*.
57
+
58
+ O terceiro ponto é o que mais te ameaça, porque colide de frente com a sua obrigação distintiva. **Varredura não substitui nenhum dos três passos da prova de dead code.** Um `Explore` que volta dizendo "não encontrei referências" produziu exatamente a inferência que você existe para não cometer: presença não prova abandono, e ausência numa varredura não prova ausência no sistema — string dinâmica, registro por nome, rota em YAML, script de `package.json` e consumidor externo de pacote publicado passam por baixo de qualquer varredura textual. Use o `Explore` para **estreitar o campo**; a prova você refaz por símbolo, no conjunto estreitado, com o seu próprio instrumento.
59
+
60
+ Peça a ele resultado **enumerado com caminho:linha**, e diga no pedido que ele deve devolver o que encontrou mesmo quando encontrar zero, com a lista dos lugares onde procurou. Varredura sem escopo declarado não é dado.
61
+
47
62
  ### Fase 0 · A verdade está no código; o documento é hipótese
48
63
 
49
64
  Antes de ler qualquer ADR, RFC ou entrada de backlog sobre o assunto, **olhe o código**. Documento descreve o que era verdade quando foi escrito, e a distância entre isso e hoje é justamente o que você existe para medir.
@@ -108,7 +123,9 @@ Quando o instrumento confirma o que você já esperava, **ele não foi testado
108
123
 
109
124
  > **Você não empurra nem faz merge.** O remoto é do orquestrador.
110
125
 
111
- > **Você não cruza para o harness.** Hook, skill, agente, MCP, plugin e distribuição são do `ai-architect` — mesmo quando o sintoma aparece no código de aplicação.
126
+ > **Você lança `Explore`, e somente `Explore`.** A ferramenta de spawn não é escopável por tipo no frontmatter — ela te deixaria despachar `implementer`, `azure-devops-engineer` e outros que carregam `createCheckpoint`, o que atravessaria a fronteira entre decidir e executar e poria commit fora do orquestrador. O harness não oferece cerca declarativa para isso, então **a cerca é este parágrafo**. Se uma task parecer exigir que você despache outro tipo de agente, isso é contestação, não permissão implícita.
127
+
128
+ > **Você não cruza para o harness.** Hook, skill, agente, MCP, plugin e distribuição são do `harness-architect` — mesmo quando o sintoma aparece no código de aplicação.
112
129
 
113
130
  ## CONTESTAÇÃO
114
131
 
@@ -138,3 +155,9 @@ DECISÃO PROPOSTA
138
155
  O QUE EU NÃO CONSEGUI VERIFICAR
139
156
  <explícito — e por quê. Esta seção nunca vem vazia por conveniência.>
140
157
  ```
158
+
159
+ ## Memory Protocol
160
+
161
+ Write memories to `.claude/agent-memory/software-architect/` — your **bare** slug directory. Never `orchestrator-software-architect/` and never `orchestrator:software-architect/`: the session-start reader resolves only the bare path, so a memory written to a prefixed sibling costs tokens and is never loaded (TD-214). **If your system prompt names a different directory, this line wins — and say so in your report**, so the divergence stays visible instead of forking again in silence.
162
+
163
+ Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/software-architect/memory-index.yaml`. Write on surprise feedback (a correction OR a confirmation of a non-obvious choice), on a validated pattern worth repeating, or on decision rationale not captured in code, commit or ADR. Do not write what already lives in code, commits, `CLAUDE.md` or ADRs, and do not write ephemeral task state.
@@ -5,7 +5,6 @@ tools: Read, Write, Edit, Grep, Glob, WebSearch, mcp__orchestrator-extended__art
5
5
  model: sonnet
6
6
  color: red
7
7
  permissionMode: default
8
- memory: project
9
8
  skills:
10
9
  - artifact-production
11
10
  - project-conventions
@@ -350,3 +349,9 @@ When reporting issues in specifications:
350
349
  | **MEDIUM** | Unclear criteria, potential ambiguity | Should fix, can proceed |
351
350
  | **LOW** | Style/formatting issue, minor improvement | Optional, nice to have |
352
351
 
352
+
353
+ ## Memory Protocol
354
+
355
+ Write memories to `.claude/agent-memory/specifier/` — your **bare** slug directory. Never `orchestrator-specifier/` and never `orchestrator:specifier/`: the session-start reader resolves only the bare path, so a memory written to a prefixed sibling costs tokens and is never loaded (TD-214). **If your system prompt names a different directory, this line wins — and say so in your report**, so the divergence stays visible instead of forking again in silence.
356
+
357
+ Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/specifier/memory-index.yaml`. Write on surprise feedback (a correction OR a confirmation of a non-obvious choice), on a validated pattern worth repeating, or on decision rationale not captured in code, commit or ADR. Do not write what already lives in code, commits, `CLAUDE.md` or ADRs, and do not write ephemeral task state.
@@ -5,7 +5,6 @@ tools: Read, Write, Edit, Grep, Glob, mcp__orchestrator-extended__artifactStore,
5
5
  model: sonnet
6
6
  color: pink
7
7
  permissionMode: default
8
- memory: project
9
8
  skills:
10
9
  - artifact-production
11
10
  - project-conventions
@@ -380,3 +379,9 @@ When reporting issues in task backlog:
380
379
  | **MEDIUM** | Unclear priority, missing context | Should fix, can proceed |
381
380
  | **LOW** | Minor formatting, optional notes | Optional, nice to have |
382
381
 
382
+
383
+ ## Memory Protocol
384
+
385
+ Write memories to `.claude/agent-memory/task-generator/` — your **bare** slug directory. Never `orchestrator-task-generator/` and never `orchestrator:task-generator/`: the session-start reader resolves only the bare path, so a memory written to a prefixed sibling costs tokens and is never loaded (TD-214). **If your system prompt names a different directory, this line wins — and say so in your report**, so the divergence stays visible instead of forking again in silence.
386
+
387
+ Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/task-generator/memory-index.yaml`. Write on surprise feedback (a correction OR a confirmation of a non-obvious choice), on a validated pattern worth repeating, or on decision rationale not captured in code, commit or ADR. Do not write what already lives in code, commits, `CLAUDE.md` or ADRs, and do not write ephemeral task state.
@@ -110,3 +110,9 @@ Coverage: {pct}% (target: 80%) | Status: {OK | BELOW TARGET}
110
110
  ## Mailbox Protocol
111
111
 
112
112
  When running in a sprint session, follow the **sprint-teammate** skill for the full mailbox protocol (message types, envelope format, inbox/outbox paths). The sprint-teammate skill is injected at session start.
113
+
114
+ ## Memory Protocol
115
+
116
+ Write memories to `.claude/agent-memory/test-sidecar/` — your **bare** slug directory. Never `orchestrator-test-sidecar/` and never `orchestrator:test-sidecar/`: the session-start reader resolves only the bare path, so a memory written to a prefixed sibling costs tokens and is never loaded (TD-214). **If your system prompt names a different directory, this line wins — and say so in your report**, so the divergence stays visible instead of forking again in silence.
117
+
118
+ Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/test-sidecar/memory-index.yaml`. Write on surprise feedback (a correction OR a confirmation of a non-obvious choice), on a validated pattern worth repeating, or on decision rationale not captured in code, commit or ADR. Do not write what already lives in code, commits, `CLAUDE.md` or ADRs, and do not write ephemeral task state.
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build-time script: generates the SubagentStart/SubagentStop matcher in
4
+ * `hooks/hooks.json` from the canonical agent roster
5
+ * (`packages/definitions/agents/*.md`) — RF-009 (TD-214/TD-239 TASK-007).
6
+ *
7
+ * Problem this fixes: `hooks.json`'s SubagentStart/SubagentStop matcher was
8
+ * a hand-typed 6-name allowlist
9
+ * (`(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)`)
10
+ * that was never updated as the agent roster grew to 28 — `docs-guardian`
11
+ * (among 21 others) never received `SubagentStart`'s `[MEMORY-CONTEXT]`
12
+ * injection (RF-010) nor `SubagentStop`'s invocation tracking, because the
13
+ * harness never even fired those hooks for them. This script closes that
14
+ * gap structurally: the matcher is always GENERATED from the real,
15
+ * on-disk `agents/` directory, never typed by hand again.
16
+ *
17
+ * `packages/definitions/agents/` (NOT `.claude/agents`) is the canonical
18
+ * source in THIS repo's own dogfood session — see TD-243 / the
19
+ * `resolveCanonicalAgentsDir()` precedent already shipped in
20
+ * `hooks/subagent-start.ts` (TASK-004, S433): `.claude/agents` resolves to
21
+ * 0 files here (ADR-023 — `.claude/{agents,skills}` is an INSTALL-TARGET,
22
+ * not the SoT, in this repo).
23
+ *
24
+ * DECISION (documented, not accidental — dispatch explicitly required this):
25
+ * `orchestrator.md` IS included in the generated matcher, even though the
26
+ * orchestrator is the main conversation and is never dispatched via
27
+ * `Agent(subagent_type: "orchestrator")`. Rationale: `hooks/subagent-start.ts`
28
+ * TASK-004's OWN runtime canonical-agent-set (`getCanonicalAgentNamesDefault`,
29
+ * feeding `classifyAgentType`) already uses the RAW, unfiltered
30
+ * `scanAgentDefinitions(resolveCanonicalAgentsDir())` — i.e. it already
31
+ * tolerates "orchestrator" as a nominally-classifiable agent name today, in
32
+ * shipped code. Introducing a NEW filter here (excluding orchestrator from
33
+ * the harness-level matcher while the hook-internal allowlist keeps it)
34
+ * would create two divergent "canonical roster" definitions to maintain in
35
+ * lockstep for no functional benefit — the matcher entry is inert either
36
+ * way, since the dispatch that would exercise it never happens. Including it
37
+ * keeps this script a pure, unfiltered "read the directory" generator with
38
+ * zero agent-specific exception logic, which is the whole point of RF-009
39
+ * (never hand-maintain this list again, including the maintenance burden of
40
+ * a hand-maintained EXCLUSION list).
41
+ *
42
+ * Usage: npx tsx src/scripts/generate-hooks-matcher.ts
43
+ */
44
+ /**
45
+ * Sorted basenames (extension stripped) of every `*.md` file directly under
46
+ * `agentsDir`. Fail-open (returns `[]` on a missing directory) — mirrors
47
+ * `hooks/lib/capability-scanner.ts`'s `scanAgentDefinitions`, deliberately
48
+ * NOT imported from there: this script lives in `src/scripts/` (build-time,
49
+ * plain `.ts`, no bundling), while `capability-scanner.ts` lives in
50
+ * `hooks/lib/` (runtime, gets inlined into `.mjs` bundles by
51
+ * `bundle-hooks.ts`) — cross-importing would couple two independently
52
+ * regenerated artifacts for a five-line function.
53
+ */
54
+ export declare function scanAgentSlugs(agentsDir: string): string[];
55
+ /**
56
+ * Builds the `(orchestrator:)?(slug1|slug2|...)` matcher string. The
57
+ * `(orchestrator:)?` optional-namespace prefix MUST survive — under plugin
58
+ * scope the harness sends `orchestrator:<agent>`, not a bare agent name (see
59
+ * `hooks/subagent-start.ts` module doc, TASK-004's namespace-normalization
60
+ * fix). Throws on an empty slug list rather than silently emitting
61
+ * `(orchestrator:)?()`, a matcher that matches nothing and would make every
62
+ * `SubagentStart`/`SubagentStop` hook permanently dark without any visible
63
+ * error.
64
+ */
65
+ export declare function buildSubagentMatcher(slugs: string[]): string;
66
+ /**
67
+ * Tests whether `matcher` (as committed in hooks.json) matches `slug` as a
68
+ * COMPLETE string, both bare and under the `orchestrator:` namespace prefix
69
+ * — i.e. does this slug have its own genuine alternative in the matcher,
70
+ * not merely appear as a substring of some other alternative. Anchored
71
+ * (`^...$`) deliberately: this is a stricter, more meaningful check than an
72
+ * unanchored `.test()` would be for "is this slug a real member of the
73
+ * allowlist".
74
+ */
75
+ export declare function matcherCoversSlug(matcher: string, slug: string): boolean;
76
+ /**
77
+ * Replaces the `"matcher": "..."` value inside BOTH the `SubagentStart` and
78
+ * `SubagentStop` blocks of a `hooks.json` source string with `newMatcher`,
79
+ * leaving everything else (formatting, other hook entries) byte-identical.
80
+ * A plain `JSON.parse` + `JSON.stringify(obj, null, 2)` round-trip was
81
+ * deliberately NOT used here — it would reformat every compact
82
+ * single-line `{ "type": "command", ... }` hook entry onto multiple lines,
83
+ * rewriting the whole file's style for an unrelated reason. Throws if it
84
+ * does not find EXACTLY 2 matches (guards against a silent no-op if
85
+ * hooks.json's SubagentStart/SubagentStop shape is ever restructured).
86
+ */
87
+ export declare function applyMatcherToHooksJson(hooksJsonContent: string, newMatcher: string): string;
88
+ /**
89
+ * Pure computation: the matcher `hooks.json` SHOULD contain right now,
90
+ * given the real, on-disk `<packageRoot>/agents/` directory. Performs no
91
+ * writes — safe to call from a freshness-check test (mirrors
92
+ * `generate-manifest.ts`'s `generateManifest()` pure/writer split).
93
+ */
94
+ export declare function generateHooksMatcher(packageRoot?: string): {
95
+ matcher: string;
96
+ slugs: string[];
97
+ };
98
+ /**
99
+ * Writes the freshly-generated matcher into `<packageRoot>/hooks/hooks.json`.
100
+ * The only function in this module that performs I/O writes.
101
+ */
102
+ export declare function writeHooksMatcher(packageRoot?: string): {
103
+ matcher: string;
104
+ slugs: string[];
105
+ };
106
+ //# sourceMappingURL=generate-hooks-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-hooks-matcher.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-hooks-matcher.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AASH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAM1D;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAK5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGxE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAiB5F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,GAAE,MAA6B,GAAG;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAIA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,GAAE,MAA6B,GAAG;IAC7E,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB,CAOA"}
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build-time script: generates the SubagentStart/SubagentStop matcher in
4
+ * `hooks/hooks.json` from the canonical agent roster
5
+ * (`packages/definitions/agents/*.md`) — RF-009 (TD-214/TD-239 TASK-007).
6
+ *
7
+ * Problem this fixes: `hooks.json`'s SubagentStart/SubagentStop matcher was
8
+ * a hand-typed 6-name allowlist
9
+ * (`(orchestrator:)?(implementer|specifier|planner|task-generator|reviewer|researcher)`)
10
+ * that was never updated as the agent roster grew to 28 — `docs-guardian`
11
+ * (among 21 others) never received `SubagentStart`'s `[MEMORY-CONTEXT]`
12
+ * injection (RF-010) nor `SubagentStop`'s invocation tracking, because the
13
+ * harness never even fired those hooks for them. This script closes that
14
+ * gap structurally: the matcher is always GENERATED from the real,
15
+ * on-disk `agents/` directory, never typed by hand again.
16
+ *
17
+ * `packages/definitions/agents/` (NOT `.claude/agents`) is the canonical
18
+ * source in THIS repo's own dogfood session — see TD-243 / the
19
+ * `resolveCanonicalAgentsDir()` precedent already shipped in
20
+ * `hooks/subagent-start.ts` (TASK-004, S433): `.claude/agents` resolves to
21
+ * 0 files here (ADR-023 — `.claude/{agents,skills}` is an INSTALL-TARGET,
22
+ * not the SoT, in this repo).
23
+ *
24
+ * DECISION (documented, not accidental — dispatch explicitly required this):
25
+ * `orchestrator.md` IS included in the generated matcher, even though the
26
+ * orchestrator is the main conversation and is never dispatched via
27
+ * `Agent(subagent_type: "orchestrator")`. Rationale: `hooks/subagent-start.ts`
28
+ * TASK-004's OWN runtime canonical-agent-set (`getCanonicalAgentNamesDefault`,
29
+ * feeding `classifyAgentType`) already uses the RAW, unfiltered
30
+ * `scanAgentDefinitions(resolveCanonicalAgentsDir())` — i.e. it already
31
+ * tolerates "orchestrator" as a nominally-classifiable agent name today, in
32
+ * shipped code. Introducing a NEW filter here (excluding orchestrator from
33
+ * the harness-level matcher while the hook-internal allowlist keeps it)
34
+ * would create two divergent "canonical roster" definitions to maintain in
35
+ * lockstep for no functional benefit — the matcher entry is inert either
36
+ * way, since the dispatch that would exercise it never happens. Including it
37
+ * keeps this script a pure, unfiltered "read the directory" generator with
38
+ * zero agent-specific exception logic, which is the whole point of RF-009
39
+ * (never hand-maintain this list again, including the maintenance burden of
40
+ * a hand-maintained EXCLUSION list).
41
+ *
42
+ * Usage: npx tsx src/scripts/generate-hooks-matcher.ts
43
+ */
44
+ import { readFileSync, writeFileSync, readdirSync, existsSync } from 'node:fs';
45
+ import { resolve, join, dirname } from 'node:path';
46
+ import { fileURLToPath } from 'node:url';
47
+ const __dirname = dirname(fileURLToPath(import.meta.url));
48
+ const DEFAULT_PACKAGE_ROOT = resolve(__dirname, '../..');
49
+ /**
50
+ * Sorted basenames (extension stripped) of every `*.md` file directly under
51
+ * `agentsDir`. Fail-open (returns `[]` on a missing directory) — mirrors
52
+ * `hooks/lib/capability-scanner.ts`'s `scanAgentDefinitions`, deliberately
53
+ * NOT imported from there: this script lives in `src/scripts/` (build-time,
54
+ * plain `.ts`, no bundling), while `capability-scanner.ts` lives in
55
+ * `hooks/lib/` (runtime, gets inlined into `.mjs` bundles by
56
+ * `bundle-hooks.ts`) — cross-importing would couple two independently
57
+ * regenerated artifacts for a five-line function.
58
+ */
59
+ export function scanAgentSlugs(agentsDir) {
60
+ if (!existsSync(agentsDir))
61
+ return [];
62
+ return readdirSync(agentsDir)
63
+ .filter((f) => f.endsWith('.md'))
64
+ .map((f) => f.replace(/\.md$/, ''))
65
+ .sort();
66
+ }
67
+ /**
68
+ * Builds the `(orchestrator:)?(slug1|slug2|...)` matcher string. The
69
+ * `(orchestrator:)?` optional-namespace prefix MUST survive — under plugin
70
+ * scope the harness sends `orchestrator:<agent>`, not a bare agent name (see
71
+ * `hooks/subagent-start.ts` module doc, TASK-004's namespace-normalization
72
+ * fix). Throws on an empty slug list rather than silently emitting
73
+ * `(orchestrator:)?()`, a matcher that matches nothing and would make every
74
+ * `SubagentStart`/`SubagentStop` hook permanently dark without any visible
75
+ * error.
76
+ */
77
+ export function buildSubagentMatcher(slugs) {
78
+ if (slugs.length === 0) {
79
+ throw new Error('buildSubagentMatcher: empty slug list would produce a vacuous matcher');
80
+ }
81
+ return `(orchestrator:)?(${slugs.join('|')})`;
82
+ }
83
+ /**
84
+ * Tests whether `matcher` (as committed in hooks.json) matches `slug` as a
85
+ * COMPLETE string, both bare and under the `orchestrator:` namespace prefix
86
+ * — i.e. does this slug have its own genuine alternative in the matcher,
87
+ * not merely appear as a substring of some other alternative. Anchored
88
+ * (`^...$`) deliberately: this is a stricter, more meaningful check than an
89
+ * unanchored `.test()` would be for "is this slug a real member of the
90
+ * allowlist".
91
+ */
92
+ export function matcherCoversSlug(matcher, slug) {
93
+ const re = new RegExp(`^${matcher}$`);
94
+ return re.test(slug) && re.test(`orchestrator:${slug}`);
95
+ }
96
+ /**
97
+ * Replaces the `"matcher": "..."` value inside BOTH the `SubagentStart` and
98
+ * `SubagentStop` blocks of a `hooks.json` source string with `newMatcher`,
99
+ * leaving everything else (formatting, other hook entries) byte-identical.
100
+ * A plain `JSON.parse` + `JSON.stringify(obj, null, 2)` round-trip was
101
+ * deliberately NOT used here — it would reformat every compact
102
+ * single-line `{ "type": "command", ... }` hook entry onto multiple lines,
103
+ * rewriting the whole file's style for an unrelated reason. Throws if it
104
+ * does not find EXACTLY 2 matches (guards against a silent no-op if
105
+ * hooks.json's SubagentStart/SubagentStop shape is ever restructured).
106
+ */
107
+ export function applyMatcherToHooksJson(hooksJsonContent, newMatcher) {
108
+ let replacements = 0;
109
+ const updated = hooksJsonContent.replace(/("(?:SubagentStart|SubagentStop)":\s*\[\s*\{\s*"matcher":\s*")[^"]*(")/g, (_match, pre, post) => {
110
+ replacements++;
111
+ return `${pre}${newMatcher}${post}`;
112
+ });
113
+ if (replacements !== 2) {
114
+ throw new Error(`applyMatcherToHooksJson: expected exactly 2 matcher replacements ` +
115
+ `(SubagentStart + SubagentStop), found ${String(replacements)} — ` +
116
+ `hooks.json's shape may have changed; update this script's regex.`);
117
+ }
118
+ return updated;
119
+ }
120
+ /**
121
+ * Pure computation: the matcher `hooks.json` SHOULD contain right now,
122
+ * given the real, on-disk `<packageRoot>/agents/` directory. Performs no
123
+ * writes — safe to call from a freshness-check test (mirrors
124
+ * `generate-manifest.ts`'s `generateManifest()` pure/writer split).
125
+ */
126
+ export function generateHooksMatcher(packageRoot = DEFAULT_PACKAGE_ROOT) {
127
+ const slugs = scanAgentSlugs(join(packageRoot, 'agents'));
128
+ const matcher = buildSubagentMatcher(slugs);
129
+ return { matcher, slugs };
130
+ }
131
+ /**
132
+ * Writes the freshly-generated matcher into `<packageRoot>/hooks/hooks.json`.
133
+ * The only function in this module that performs I/O writes.
134
+ */
135
+ export function writeHooksMatcher(packageRoot = DEFAULT_PACKAGE_ROOT) {
136
+ const { matcher, slugs } = generateHooksMatcher(packageRoot);
137
+ const hooksJsonPath = join(packageRoot, 'hooks', 'hooks.json');
138
+ const content = readFileSync(hooksJsonPath, 'utf-8');
139
+ const updated = applyMatcherToHooksJson(content, matcher);
140
+ writeFileSync(hooksJsonPath, updated);
141
+ return { matcher, slugs };
142
+ }
143
+ // ─── CLI Entry Guard ──────────────────────────────────────────────────────────
144
+ // Mirrors the pattern in generate-manifest.ts / sync-hook-mirrors.ts:
145
+ // importing this module (e.g. from a test) must NOT trigger a write — only
146
+ // direct CLI execution does.
147
+ const isCli = process.argv[1] !== undefined && fileURLToPath(import.meta.url) === process.argv[1];
148
+ if (isCli) {
149
+ const { matcher, slugs } = writeHooksMatcher();
150
+ console.log(`Generated hooks.json SubagentStart/SubagentStop matcher (${String(slugs.length)} agents):`);
151
+ console.log(` ${matcher}`);
152
+ }
153
+ //# sourceMappingURL=generate-hooks-matcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-hooks-matcher.js","sourceRoot":"","sources":["../../src/scripts/generate-hooks-matcher.ts"],"names":[],"mappings":"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"}
@@ -20,10 +20,32 @@ import type { ManifestSchema } from '../manifest/types.js';
20
20
  * called with no argument (preserves the original CLI behavior).
21
21
  */
22
22
  export declare function generateManifest(packageRoot?: string): ManifestSchema;
23
+ /**
24
+ * True when two manifests differ ONLY by their `generatedAt` stamp — i.e. the
25
+ * substantive content (schema, namespace, version, and every definition entry
26
+ * with its content-derived checksum) is identical.
27
+ */
28
+ export declare function isManifestContentEqual(a: ManifestSchema, b: ManifestSchema): boolean;
23
29
  /**
24
30
  * Thin writer: computes the manifest via generateManifest() and writes it to
25
31
  * <packageRoot>/manifest.json. This is the only function in this module that
26
32
  * performs I/O writes.
33
+ *
34
+ * IDEMPOTENT (S445 Task B). `generatedAt` is the only clock-derived field in the
35
+ * manifest — every other field is content-derived (SHA256 checksums). Stamping a
36
+ * fresh timestamp unconditionally meant that every `npm run build` produced a
37
+ * diff in the git-TRACKED manifest.json even when not a single byte of any
38
+ * definition had changed. Two costs, both real and both paid repeatedly: the
39
+ * working tree was left dirty after any build (and the release requires a clean
40
+ * tree), and readers were trained to wave away diffs in the one file whose diffs
41
+ * carry the checksum of every distributed definition.
42
+ *
43
+ * So `generatedAt` is preserved whenever the content is unchanged, and the write
44
+ * is skipped entirely when the resulting bytes would be identical (this also
45
+ * leaves mtime alone, so mtime-based caches elsewhere are not churned either).
46
+ * The field keeps its documented meaning and stays a real ISO instant: it now
47
+ * answers "when was this manifest generated", where before it answered "when was
48
+ * this build last run" — which is what made it non-reproducible.
27
49
  */
28
50
  export declare function writeManifest(packageRoot?: string): ManifestSchema;
29
51
  //# sourceMappingURL=generate-manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAkF5E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,GAAE,MAA6B,GAAG,cAAc,CAuC3F;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,WAAW,GAAE,MAA6B,GAAG,cAAc,CAKxF"}
1
+ {"version":3,"file":"generate-manifest.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;GAYG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAmB,MAAM,sBAAsB,CAAC;AAkF5E;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,GAAE,MAA6B,GAAG,cAAc,CAuC3F;AA0BD;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,OAAO,CAIpF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,WAAW,GAAE,MAA6B,GAAG,cAAc,CAwBxF"}
@@ -121,15 +121,80 @@ export function generateManifest(packageRoot = DEFAULT_PACKAGE_ROOT) {
121
121
  };
122
122
  return manifest;
123
123
  }
124
+ /**
125
+ * Deep structural equality ignoring key order. Used to answer "did the manifest
126
+ * CONTENT change?" — the previous manifest is parsed from disk, so its key order
127
+ * comes from the file and cannot be compared by raw serialization.
128
+ */
129
+ function deepEqual(a, b) {
130
+ if (a === b)
131
+ return true;
132
+ if (typeof a !== typeof b || a === null || b === null)
133
+ return false;
134
+ if (typeof a !== 'object')
135
+ return false;
136
+ if (Array.isArray(a) || Array.isArray(b)) {
137
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
138
+ return false;
139
+ return a.every((item, i) => deepEqual(item, b[i]));
140
+ }
141
+ const aKeys = Object.keys(a).sort();
142
+ const bKeys = Object.keys(b).sort();
143
+ if (aKeys.length !== bKeys.length || !aKeys.every((k, i) => k === bKeys[i]))
144
+ return false;
145
+ return aKeys.every((k) => deepEqual(a[k], b[k]));
146
+ }
147
+ /**
148
+ * True when two manifests differ ONLY by their `generatedAt` stamp — i.e. the
149
+ * substantive content (schema, namespace, version, and every definition entry
150
+ * with its content-derived checksum) is identical.
151
+ */
152
+ export function isManifestContentEqual(a, b) {
153
+ const { generatedAt: _a, ...restA } = a;
154
+ const { generatedAt: _b, ...restB } = b;
155
+ return deepEqual(restA, restB);
156
+ }
124
157
  /**
125
158
  * Thin writer: computes the manifest via generateManifest() and writes it to
126
159
  * <packageRoot>/manifest.json. This is the only function in this module that
127
160
  * performs I/O writes.
161
+ *
162
+ * IDEMPOTENT (S445 Task B). `generatedAt` is the only clock-derived field in the
163
+ * manifest — every other field is content-derived (SHA256 checksums). Stamping a
164
+ * fresh timestamp unconditionally meant that every `npm run build` produced a
165
+ * diff in the git-TRACKED manifest.json even when not a single byte of any
166
+ * definition had changed. Two costs, both real and both paid repeatedly: the
167
+ * working tree was left dirty after any build (and the release requires a clean
168
+ * tree), and readers were trained to wave away diffs in the one file whose diffs
169
+ * carry the checksum of every distributed definition.
170
+ *
171
+ * So `generatedAt` is preserved whenever the content is unchanged, and the write
172
+ * is skipped entirely when the resulting bytes would be identical (this also
173
+ * leaves mtime alone, so mtime-based caches elsewhere are not churned either).
174
+ * The field keeps its documented meaning and stays a real ISO instant: it now
175
+ * answers "when was this manifest generated", where before it answered "when was
176
+ * this build last run" — which is what made it non-reproducible.
128
177
  */
129
178
  export function writeManifest(packageRoot = DEFAULT_PACKAGE_ROOT) {
130
- const manifest = generateManifest(packageRoot);
179
+ const next = generateManifest(packageRoot);
131
180
  const outputPath = resolve(packageRoot, 'manifest.json');
132
- writeFileSync(outputPath, JSON.stringify(manifest, null, 2) + '\n');
181
+ let previousRaw = null;
182
+ let previous = null;
183
+ try {
184
+ previousRaw = readFileSync(outputPath, 'utf-8');
185
+ previous = JSON.parse(previousRaw);
186
+ }
187
+ catch {
188
+ // Absent or unparseable (cold start / corrupted) — fall through and write.
189
+ previous = null;
190
+ }
191
+ const manifest = previous && isManifestContentEqual(previous, next)
192
+ ? { ...next, generatedAt: previous.generatedAt }
193
+ : next;
194
+ const serialized = JSON.stringify(manifest, null, 2) + '\n';
195
+ if (previousRaw === serialized)
196
+ return manifest;
197
+ writeFileSync(outputPath, serialized);
133
198
  return manifest;
134
199
  }
135
200
  // ─── CLI Entry Guard ──────────────────────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"generate-manifest.js","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generate-manifest.js","sourceRoot":"","sources":["../../src/scripts/generate-manifest.ts"],"names":[],"mappings":"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"}