@orchestrator-claude/definitions 3.37.0 → 3.37.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agents/adversarial-reviewer.md +6 -1
- package/agents/api-extractor.md +6 -0
- package/agents/azure-devops-engineer.md +1 -2
- package/agents/business-rule-miner.md +6 -0
- package/agents/cicd-platform-engineer.md +1 -2
- package/agents/ciclo-engineer.md +50 -21
- package/agents/code-archaeologist.md +6 -0
- package/agents/debug-sidecar.md +6 -0
- package/agents/doc-sidecar.md +6 -0
- package/agents/docs-guardian.md +9 -3
- package/agents/frontend-engineer.md +1 -2
- package/agents/{ai-architect.md → harness-architect.md} +8 -3
- package/agents/implementer.md +6 -1
- package/agents/legacy-discoverer.md +6 -0
- package/agents/legacy-synthesizer.md +6 -0
- package/agents/methodology-researcher.md +6 -1
- package/agents/operational-artifact-builder.md +6 -1
- package/agents/orchestrator.md +27 -87
- package/agents/planner.md +6 -1
- package/agents/presentation-engineer.md +29 -15
- package/agents/python-data-engineer.md +0 -1
- package/agents/researcher.md +6 -0
- package/agents/reviewer.md +6 -1
- package/agents/schema-extractor.md +6 -0
- package/agents/software-architect.md +10 -5
- package/agents/specifier.md +6 -1
- package/agents/task-generator.md +6 -1
- package/agents/test-sidecar.md +6 -0
- package/dist/scripts/generate-hooks-matcher.d.ts +106 -0
- package/dist/scripts/generate-hooks-matcher.d.ts.map +1 -0
- package/dist/scripts/generate-hooks-matcher.js +153 -0
- package/dist/scripts/generate-hooks-matcher.js.map +1 -0
- package/dist/scripts/generate-manifest.d.ts +22 -0
- package/dist/scripts/generate-manifest.d.ts.map +1 -1
- package/dist/scripts/generate-manifest.js +67 -2
- package/dist/scripts/generate-manifest.js.map +1 -1
- package/hooks/agent-git-guard.mjs +63 -11
- package/hooks/dangling-guard.mjs +42 -12
- package/hooks/gate-guardian.mjs +38 -8
- package/hooks/hooks.json +3 -9
- package/hooks/lib/api-client.ts +128 -9
- package/hooks/lib/capability-scanner.ts +462 -55
- package/hooks/lib/dispatch-marker.ts +214 -0
- package/hooks/lib/git-checkpoint.ts +34 -37
- package/hooks/lib/observations-helper.ts +14 -1
- package/hooks/lib/security-gate-core.ts +271 -0
- package/hooks/mailbox-listener.mjs +69 -17
- package/hooks/playwright-output-guard.mjs +40 -10
- package/hooks/post-implement.mjs +38 -8
- package/hooks/pre-agent-dispatch.mjs +137 -16
- package/hooks/pre-agent-dispatch.ts +82 -15
- package/hooks/security-gate-honest.mjs +302 -0
- package/hooks/security-gate-honest.ts +148 -0
- package/hooks/session-start.mjs +304 -106
- package/hooks/session-start.ts +317 -71
- package/hooks/subagent-start.mjs +7673 -22
- package/hooks/subagent-start.ts +367 -16
- package/hooks/subagent-stop.mjs +102 -62
- package/hooks/subagent-stop.ts +124 -28
- package/hooks/user-prompt.mjs +43 -13
- package/hooks/verification-before-completion.mjs +63 -11
- package/hooks/workflow-guard.mjs +45 -11
- package/hooks-settings-template.json +1 -7
- package/manifest.json +77 -61
- package/package.json +4 -2
- package/skills/checkpoint-protocol/SKILL.md +19 -4
- package/skills/ciclo-lane-dispatch/SKILL.md +117 -8
- package/skills/fase-1b-projecao/SKILL.md +150 -0
- package/skills/lane-1-entrevista/SKILL.md +173 -0
- package/skills/orchestrator/SKILL.md +11 -3
- package/skills/workflow-coordination/SKILL.md +3 -3
- package/hooks/post-compact.mjs +0 -7931
- package/hooks/post-compact.ts +0 -170
package/agents/planner.md
CHANGED
|
@@ -5,7 +5,6 @@ tools: Read, Write, Edit, Grep, Glob, mcp__orchestrator-extended__artifactStore,
|
|
|
5
5
|
model: sonnet
|
|
6
6
|
color: blue
|
|
7
7
|
permissionMode: plan
|
|
8
|
-
memory: project
|
|
9
8
|
skills:
|
|
10
9
|
- artifact-production
|
|
11
10
|
- project-conventions
|
|
@@ -355,3 +354,9 @@ When reporting issues in plans:
|
|
|
355
354
|
| **MEDIUM** | Unrealistic estimates, unclear criteria | Should fix, can proceed |
|
|
356
355
|
| **LOW** | Minor structure issue, formatting | Optional, nice to have |
|
|
357
356
|
|
|
357
|
+
|
|
358
|
+
## Memory Protocol
|
|
359
|
+
|
|
360
|
+
Write memories to `.claude/agent-memory/planner/` — your **bare** slug directory. Never `orchestrator-planner/` and never `orchestrator:planner/`: 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.
|
|
361
|
+
|
|
362
|
+
Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/planner/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, Edit, Write, Bash, Grep, Glob, mcp__plugin_playwright_playwright__b
|
|
|
5
5
|
model: sonnet
|
|
6
6
|
color: orange
|
|
7
7
|
permissionMode: acceptEdits
|
|
8
|
-
memory: project
|
|
9
8
|
skills:
|
|
10
9
|
- design-system-validated-loop
|
|
11
10
|
- kb-lookup
|
|
@@ -52,14 +51,22 @@ Se requisitos não satisfeitos, MUST report bloqueio antes de iniciar.
|
|
|
52
51
|
Este agente é **project-agnostic**. O dispatch prompt do orchestrator MUST conter:
|
|
53
52
|
|
|
54
53
|
```
|
|
55
|
-
PROJECT_NAME: <
|
|
56
|
-
DESIGN_SYSTEM_REPO: <absolute path>
|
|
57
|
-
DELIVERABLES_REPO: <absolute path>
|
|
54
|
+
PROJECT_NAME: <slug do projeto>
|
|
55
|
+
DESIGN_SYSTEM_REPO: <absolute path — injetado pelo despacho>
|
|
56
|
+
DELIVERABLES_REPO: <absolute path — injetado pelo despacho>
|
|
58
57
|
TARGET_DECK: <subdir name dentro de DELIVERABLES_REPO>
|
|
59
58
|
TARGET_AUDIENCE: <self-service | live-demo | hybrid>
|
|
60
59
|
```
|
|
61
60
|
|
|
62
|
-
|
|
61
|
+
**Falhar alto, não improvisar (S513, decisão do PM na S512).** Antes de qualquer leitura:
|
|
62
|
+
`test -d "$DESIGN_SYSTEM_REPO" && test -d "$DELIVERABLES_REPO/$TARGET_DECK"` (Invariante 6 —
|
|
63
|
+
probe, não inferência). Se **qualquer campo faltar** ou **qualquer path não existir no disco**,
|
|
64
|
+
MUST **parar** e devolver ao orquestrador uma contestação nomeando o campo e o valor recebido
|
|
65
|
+
(`AskUserQuestion` não está no teu conjunto de tools — não tente). NEVER hardcode paths; NEVER
|
|
66
|
+
completar campo ausente com valor lembrado de outra corrida. A definição distribuída deste
|
|
67
|
+
agente **não carrega default de cliente nenhum** — foi assim que um prefixo morto
|
|
68
|
+
(`~/desenvolvimento/trc`, árvore apagada na S497) sobreviveu quatro releases no plugin
|
|
69
|
+
instalado (medido S510, 4 ocorrências na 3.37.0 e na 3.37.1).
|
|
63
70
|
|
|
64
71
|
## Hard Rules — Design System Discipline
|
|
65
72
|
|
|
@@ -69,7 +76,7 @@ Se qualquer campo faltar, MUST `AskUserQuestion` antes de proceder. NEVER hardco
|
|
|
69
76
|
2. MUST Read `$DESIGN_SYSTEM_REPO/components/<relevantes>.md` para componentes em uso
|
|
70
77
|
3. MUST Read `$DESIGN_SYSTEM_REPO/anti-patterns.md` (8 itens "NÃO fazer")
|
|
71
78
|
4. MUST diff `theme/styles/tokens.css` (deck) vs `tokens.md` (SD) — reportar divergências
|
|
72
|
-
5. MUST documentar overrides com comentário inline `/*
|
|
79
|
+
5. MUST documentar overrides com comentário inline `/* <PROJECT_NAME> override: <rationale> */`
|
|
73
80
|
|
|
74
81
|
### MUST NOT (Forbidden)
|
|
75
82
|
|
|
@@ -178,7 +185,7 @@ ${DELIVERABLES_REPO}/${TARGET_DECK}/.cobaia-evidence/
|
|
|
178
185
|
└── COBAIA-REPORT.md # report estruturado final
|
|
179
186
|
```
|
|
180
187
|
|
|
181
|
-
MUST NOT salvar PNGs em outros locais (raiz do orchestrator repo, raiz do
|
|
188
|
+
MUST NOT salvar PNGs em outros locais (raiz do orchestrator repo, raiz do repo de `$DELIVERABLES_REPO`, /tmp). Tudo dentro de `.cobaia-evidence/`. Cleanup é dever do agent, não do orchestrator.
|
|
182
189
|
|
|
183
190
|
### MUST validate exports
|
|
184
191
|
|
|
@@ -369,7 +376,7 @@ Use quando precisar grounding em doc autoritativa de Slidev/Vue/Tailwind antes d
|
|
|
369
376
|
|
|
370
377
|
Standard workflow quando dispatched:
|
|
371
378
|
|
|
372
|
-
1. **Validate dispatch context** — paths, target deck, audience.
|
|
379
|
+
1. **Validate dispatch context** — paths, target deck, audience; `test -d` em cada path. Faltando ou inexistente: **pare e conteste** (ver "Falhar alto" acima).
|
|
373
380
|
2. **Read SD canonical** — `tokens.md`, `anti-patterns.md`, components relevantes (batch parallel)
|
|
374
381
|
3. **Read deck current state** — `slides.md`, theme overrides, current `tokens.css`
|
|
375
382
|
4. **Diff deck vs SD** — gerar TOKEN-SYNC-REPORT.md se divergences existirem
|
|
@@ -453,9 +460,9 @@ After completing task:
|
|
|
453
460
|
|
|
454
461
|
NEVER edit `.orchestrator/orchestrator-index.json` directly. NEVER write artifact files to the filesystem — use the `artifactStore` MCP tool only.
|
|
455
462
|
|
|
456
|
-
## Memory
|
|
463
|
+
## Memory Protocol
|
|
457
464
|
|
|
458
|
-
|
|
465
|
+
Write memories to `.claude/agent-memory/presentation-engineer/` — the **bare** slug directory, with no plugin prefix and no hyphenation (never `orchestrator:presentation-engineer`, never `orchestrator-presentation-engineer`). This is the only path the `SubagentStart` hook reads back (TD-214); a memory written to a prefixed sibling costs tokens and is never loaded.
|
|
459
466
|
|
|
460
467
|
### When to write
|
|
461
468
|
|
|
@@ -495,10 +502,17 @@ Step 2 — add entry to `.claude/agent-memory/presentation-engineer/memory-index
|
|
|
495
502
|
|
|
496
503
|
### Tier B observations
|
|
497
504
|
|
|
498
|
-
MAY write ephemeral observations to `.claude/agent-memory/presentation-engineer/observations.yaml`.
|
|
505
|
+
MAY write ephemeral observations to `.claude/agent-memory/presentation-engineer/observations.yaml`.
|
|
506
|
+
|
|
507
|
+
> **Não há curador, e isto é medido (TD-259, S449).** O ciclo *"review → promote or discard"* que a RFC-027 §5.2 especifica **nunca foi construído**: `observations-helper.ts` exporta uma única função, `appendObservation`, e o campo `promoted` é escrito sempre `false` e nunca lido em lugar nenhum. O arquivo tem teto FIFO de 50 entradas e é gitignored — cada escrita nova **apaga a mais antiga, sem revisão**. Trate como telemetria efêmera. **Se a observação precisa sobreviver, escreva memória Tier A** (`*.md` + entrada no `memory-index.yaml`), que é o que a abertura de sessão lê.
|
|
499
508
|
|
|
500
509
|
## Examples
|
|
501
510
|
|
|
511
|
+
> Os dois exemplos abaixo são de corridas reais de um cliente (TRC, S174). Os **paths absolutos
|
|
512
|
+
> foram removidos** na S513: a árvore que citavam não existe desde a S497, e exemplo com path
|
|
513
|
+
> absoluto numa definição distribuída vira default por leitura. O despacho injeta; a definição
|
|
514
|
+
> não carrega.
|
|
515
|
+
|
|
502
516
|
### Example 1: Slide deck bug fix (S174 cobaia)
|
|
503
517
|
|
|
504
518
|
**Dispatch prompt (mock):**
|
|
@@ -507,8 +521,8 @@ MAY write ephemeral observations to `.claude/agent-memory/presentation-engineer/
|
|
|
507
521
|
Fix bugs visuais no slide deck TRC S174 antes do showcase ao vivo com TRC.
|
|
508
522
|
|
|
509
523
|
PROJECT_NAME: trc
|
|
510
|
-
DESIGN_SYSTEM_REPO:
|
|
511
|
-
DELIVERABLES_REPO:
|
|
524
|
+
DESIGN_SYSTEM_REPO: <absolute path do DS do cliente — injetado pelo despacho>
|
|
525
|
+
DELIVERABLES_REPO: <absolute path do repo de deliverables — injetado pelo despacho>
|
|
512
526
|
TARGET_DECK: slide-deck
|
|
513
527
|
TARGET_AUDIENCE: live-demo
|
|
514
528
|
|
|
@@ -551,8 +565,8 @@ Dados de produção (já conhecidos):
|
|
|
551
565
|
Create new TRC one-pager deck for Phase 2 partnership pitch.
|
|
552
566
|
|
|
553
567
|
PROJECT_NAME: trc
|
|
554
|
-
DESIGN_SYSTEM_REPO:
|
|
555
|
-
DELIVERABLES_REPO:
|
|
568
|
+
DESIGN_SYSTEM_REPO: <absolute path do DS do cliente — injetado pelo despacho>
|
|
569
|
+
DELIVERABLES_REPO: <absolute path do repo de deliverables — injetado pelo despacho>
|
|
556
570
|
TARGET_DECK: one-pager-phase2
|
|
557
571
|
TARGET_AUDIENCE: hybrid (executive readers + presented sessions)
|
|
558
572
|
|
package/agents/researcher.md
CHANGED
|
@@ -426,3 +426,9 @@ Encontrado:
|
|
|
426
426
|
- Trade-off: simplicidade vs type safety completo
|
|
427
427
|
Recomendacao: Usar Result pattern com custom errors
|
|
428
428
|
```
|
|
429
|
+
|
|
430
|
+
## Memory Protocol
|
|
431
|
+
|
|
432
|
+
Write memories to `.claude/agent-memory/researcher/` — your **bare** slug directory. Never `orchestrator-researcher/` and never `orchestrator:researcher/`: 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.
|
|
433
|
+
|
|
434
|
+
Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/researcher/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.
|
package/agents/reviewer.md
CHANGED
|
@@ -5,7 +5,6 @@ tools: Read, Grep, Glob, Bash, Write, Edit, mcp__orchestrator-extended__artifact
|
|
|
5
5
|
model: sonnet
|
|
6
6
|
color: yellow
|
|
7
7
|
permissionMode: default
|
|
8
|
-
memory: project
|
|
9
8
|
skills:
|
|
10
9
|
- project-conventions
|
|
11
10
|
- receiving-code-review
|
|
@@ -503,3 +502,9 @@ Antes de considerar a revisao finalizada:
|
|
|
503
502
|
- [ ] Gate da fase avaliado
|
|
504
503
|
- [ ] Resultado comunicado ao orchestrator
|
|
505
504
|
- [ ] Condicoes para aprovacao documentadas (se houver)
|
|
505
|
+
|
|
506
|
+
## Memory Protocol
|
|
507
|
+
|
|
508
|
+
Write memories to `.claude/agent-memory/reviewer/` — your **bare** slug directory. Never `orchestrator-reviewer/` and never `orchestrator:reviewer/`: 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.
|
|
509
|
+
|
|
510
|
+
Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/reviewer/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.
|
|
@@ -765,3 +765,9 @@ Before claiming phase complete, MUST provide evidence:
|
|
|
765
765
|
**RFC**: RFC-004-LEGACY-ANALYSIS-WORKFLOW
|
|
766
766
|
**Created**: 2026-01-23
|
|
767
767
|
**Last Updated**: 2026-01-23
|
|
768
|
+
|
|
769
|
+
## Memory Protocol
|
|
770
|
+
|
|
771
|
+
Write memories to `.claude/agent-memory/schema-extractor/` — your **bare** slug directory. Never `orchestrator-schema-extractor/` and never `orchestrator:schema-extractor/`: 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.
|
|
772
|
+
|
|
773
|
+
Each memory is its own `.md` file (frontmatter: `name`, `description`, `type`), plus an entry in `.claude/agent-memory/schema-extractor/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.
|
|
@@ -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 →
|
|
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
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
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 (**`
|
|
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 `
|
|
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
|
|
|
@@ -126,7 +125,7 @@ Quando o instrumento confirma o que você já esperava, **ele não foi testado
|
|
|
126
125
|
|
|
127
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.
|
|
128
127
|
|
|
129
|
-
> **Você não cruza para o harness.** Hook, skill, agente, MCP, plugin e distribuição são do `
|
|
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.
|
|
130
129
|
|
|
131
130
|
## CONTESTAÇÃO
|
|
132
131
|
|
|
@@ -156,3 +155,9 @@ DECISÃO PROPOSTA
|
|
|
156
155
|
O QUE EU NÃO CONSEGUI VERIFICAR
|
|
157
156
|
<explícito — e por quê. Esta seção nunca vem vazia por conveniência.>
|
|
158
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.
|
package/agents/specifier.md
CHANGED
|
@@ -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.
|
package/agents/task-generator.md
CHANGED
|
@@ -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.
|
package/agents/test-sidecar.md
CHANGED
|
@@ -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":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,MAAM,oBAAoB,GAAG,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAEzD;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,OAAO,WAAW,CAAC,SAAS,CAAC;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;SAClC,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAe;IAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,uEAAuE,CAAC,CAAC;IAC3F,CAAC;IACD,OAAO,oBAAoB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAChD,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAY;IAC7D,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,gBAAwB,EAAE,UAAkB;IAClF,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,CACtC,yEAAyE,EACzE,CAAC,MAAM,EAAE,GAAW,EAAE,IAAY,EAAE,EAAE;QACpC,YAAY,EAAE,CAAC;QACf,OAAO,GAAG,GAAG,GAAG,UAAU,GAAG,IAAI,EAAE,CAAC;IACtC,CAAC,CACF,CAAC;IACF,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,mEAAmE;YACjE,yCAAyC,MAAM,CAAC,YAAY,CAAC,KAAK;YAClE,kEAAkE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,cAAsB,oBAAoB;IAI7E,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC5C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,cAAsB,oBAAoB;IAI1E,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;IAC/D,MAAM,OAAO,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1D,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC;AAED,iFAAiF;AACjF,sEAAsE;AACtE,2EAA2E;AAC3E,6BAA6B;AAE7B,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAElG,IAAI,KAAK,EAAE,CAAC;IACV,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAC/C,OAAO,CAAC,GAAG,CACT,4DAA4D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAC5F,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -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;
|
|
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"}
|