@jamie-tam/forge 6.0.0 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +77 -59
  2. package/agents/dreamer.md +10 -7
  3. package/agents/gotcha-hunter.md +1 -1
  4. package/agents/prototype-codifier.md +2 -2
  5. package/commands/{forge.md → discover.md} +13 -9
  6. package/commands/dream.md +71 -0
  7. package/commands/feature.md +57 -10
  8. package/commands/{evolve.md → forge-evolve.md} +3 -3
  9. package/commands/greenfield.md +5 -5
  10. package/commands/note.md +64 -0
  11. package/commands/{task-force.md → parallel.md} +15 -15
  12. package/commands/resume.md +2 -2
  13. package/commands/setup.md +18 -17
  14. package/commands/status.md +2 -2
  15. package/commands/wrap.md +130 -0
  16. package/dist/__tests__/hooks.test.js +334 -0
  17. package/dist/__tests__/init.test.js +110 -0
  18. package/dist/__tests__/work-manifest.test.js +48 -14
  19. package/dist/cli.js +0 -0
  20. package/dist/hooks.js +88 -6
  21. package/dist/init.js +39 -1
  22. package/dist/uninstall.js +11 -5
  23. package/dist/work-manifest.js +63 -24
  24. package/hooks/config/gate-requirements.json +1 -1
  25. package/hooks/hooks.json +14 -1
  26. package/hooks/scripts/gate-enforcer.sh +51 -6
  27. package/hooks/scripts/pre-compact.sh +120 -55
  28. package/hooks/scripts/session-start.sh +43 -4
  29. package/hooks/scripts/telemetry.sh +32 -2
  30. package/hooks/templates/CLAUDE.md.template +6 -3
  31. package/package.json +1 -1
  32. package/references/common/phases.md +8 -6
  33. package/references/common/skill-authoring.md +1 -1
  34. package/rules/common/forge-system.md +64 -6
  35. package/rules/common/quality-gates.md +2 -0
  36. package/skills/build-prototype/SKILL.md +4 -4
  37. package/skills/build-tdd/SKILL.md +14 -0
  38. package/skills/concept-slides/SKILL.md +11 -11
  39. package/skills/deliver-deploy/SKILL.md +10 -1
  40. package/skills/harden/SKILL.md +22 -8
  41. package/skills/iterate-prototype/SKILL.md +22 -0
  42. package/skills/quality-test-execution/SKILL.md +26 -1
  43. package/skills/quality-test-plan/SKILL.md +21 -1
  44. package/skills/support-debug/SKILL.md +1 -1
  45. package/skills/support-dream/SKILL.md +8 -7
  46. package/skills/support-gotcha/SKILL.md +3 -3
  47. package/skills/{support-task-force → support-parallel}/SKILL.md +22 -22
  48. package/skills/{support-task-force → support-parallel}/references/dispatch-pattern.md +10 -10
  49. package/skills/{support-task-force → support-parallel}/references/synthesis-template.md +10 -10
  50. package/skills/support-skill-validator/SKILL.md +5 -5
  51. package/skills/support-skill-validator/references/validation-checks.md +1 -1
  52. package/skills/support-system-guide/SKILL.md +4 -3
  53. package/skills/support-wiki-lint/scripts/lint.mjs +52 -0
  54. package/templates/README.md +1 -1
  55. package/templates/aiwiki/CLAUDE.md.template +48 -22
  56. package/templates/aiwiki/schemas/session.md +134 -49
  57. package/templates/manifests/bugfix.yaml +1 -1
  58. package/templates/manifests/feature.yaml +1 -1
  59. package/templates/manifests/greenfield.yaml +1 -1
  60. package/templates/manifests/hotfix.yaml +1 -1
  61. package/templates/manifests/refactor.yaml +1 -1
  62. package/templates/manifests/v5/SCHEMA.md +14 -17
  63. package/templates/manifests/v5/feature.yaml +1 -1
  64. package/templates/manifests/v6/SCHEMA.md +14 -10
  65. package/commands/abort.md +0 -25
  66. package/dist/__tests__/active-manifest.test.js +0 -272
  67. package/dist/__tests__/gate-check.test.js +0 -384
  68. package/dist/active-manifest.js +0 -229
  69. package/dist/gate-check.js +0 -326
@@ -63,6 +63,31 @@ Now that the test plan is parsed and files are verified, run the Codex consent f
63
63
  - **Takeover:** Dispatch Codex with the test plan to execute tests and produce the results report. Claude reviews test quality and coverage.
64
64
  - **Verify** or **Skip / Codex unavailable:** Proceed with the steps below. The Codex Verify note in Step 9 will dispatch Codex to review test quality (Verify only).
65
65
 
66
+ ### Step 1.6: Oracle Coverage Check
67
+
68
+ Before any test runs, verify that every oracle in `aiwiki/oracles/` for this work item is mapped to a test in the plan. Oracles are the Phase 5 (harden) contract — production code must reproduce the prototype's verified behavior. This is the load-bearing closure of the mock-pass / real-break wiring gap; running tests without checking oracle coverage re-creates the gap.
69
+
70
+ 1. Enumerate `aiwiki/oracles/*.md`. Filter to oracles whose `prototype_path` is within this work item's scope (typically `pocs/{name}-prototype/`).
71
+ 2. For each in-scope oracle, find the matching test ID(s) in the test plan's "Map Oracles to Tests" table (produced by `quality-test-plan` Step 2.3).
72
+ 3. **If any in-scope oracle is unmapped, halt:**
73
+
74
+ ```
75
+ ORACLE COVERAGE FAILURE:
76
+ Unmapped oracle: aiwiki/oracles/auth-login-success.md
77
+ Type: interaction
78
+ prototype_path: pocs/myapp-prototype/src/auth/Login.tsx
79
+ No test in test-plan.md cites this oracle.
80
+
81
+ Cannot execute the test plan. Mock-heavy tests pass while real integration
82
+ breaks (the wiring gap) — the chain closes only when every oracle has a
83
+ test. Resolve by:
84
+ (a) Returning to quality-test-plan and adding a test that satisfies the
85
+ oracle, OR
86
+ (b) Re-running harden if the oracle is stale or out of scope.
87
+ ```
88
+
89
+ 4. **Skip condition:** If no oracles exist for this work item (the test plan recorded "No oracles in scope" in Step 2.3, or `aiwiki/oracles/` is empty for the scope), record "No oracles in scope" in the results and proceed. The check is non-blocking when oracle capture wasn't part of the lifecycle.
90
+
66
91
  ### Step 2: External Service Availability Check
67
92
 
68
93
  Before executing any tests, determine which external services are available for real testing.
@@ -393,7 +418,7 @@ Do not execute only unit tests and declare success. All test types from the plan
393
418
 
394
419
  | Field | Value |
395
420
  |---|---|
396
- | **Requires** | Test plan (`.forge/work/{type}/{name}/test-plan.md`) + implementation code (from `build-tdd`) + architecture artifacts (`.forge/work/{type}/{name}/architecture/api-contract.md` for external service verification) |
421
+ | **Requires** | Test plan (`.forge/work/{type}/{name}/test-plan.md`) + implementation code (from `build-tdd`) + architecture artifacts (`.forge/work/{type}/{name}/architecture/api-contract.md` for external service verification) + oracle pages (`aiwiki/oracles/*.md` from harden Step 2.5) when codify ran |
397
422
  | **Produces** | `.forge/work/{type}/{name}/test-results.md` |
398
423
  | **Feeds into** | `deliver-deploy` (via quality gate -- zero failures required) |
399
424
  | **Updates manifest** | `artifacts.test-results: test-results.md`, `phases.quality.test-execution: { status: complete, gate-passed: true }` |
@@ -96,6 +96,26 @@ Create a traceability matrix:
96
96
 
97
97
  **Rule:** Every acceptance criterion MUST have at least one test. If a criterion has no test, the plan is incomplete.
98
98
 
99
+ ### Step 2.3: Map Oracles to Tests
100
+
101
+ If `aiwiki/oracles/` contains oracle pages for slices in this work item, every in-scope oracle MUST appear in the traceability matrix with at least one mapped test. Oracles are the prototype-derived behavioral contract from Phase 5 (harden); production code is not "tested" if oracles are unverified. This is the load-bearing closure of the mock-pass / real-break wiring gap (Flux/REACH dogfood signal).
102
+
103
+ For each `aiwiki/oracles/{slug}.md` whose `prototype_path` is within this work item's scope (typically `pocs/{name}-prototype/`):
104
+
105
+ ```markdown
106
+ | Oracle | Type | Setup → Trigger → Assertions cite | Mapped tests |
107
+ |---|---|---|---|
108
+ | `auth-login-success` | interaction | `pocs/myapp-prototype/src/auth/Login.tsx:42` | IT-003, E2E-001 |
109
+ | `dashboard-renders-empty-state` | render | `pocs/myapp-prototype/src/Dashboard.tsx:18` | IT-005 |
110
+ | `checkout-applies-discount-code` | golden-trace | `pocs/myapp-prototype/src/checkout/apply.ts:67` | IT-012, CONTRACT-004 |
111
+ ```
112
+
113
+ **Rule:** Every in-scope oracle MUST have at least one test that exercises its `Setup → Trigger → Assertions`. Unmapped oracles fail this step — either add tests to cover them, or surface to the user that harden's oracle capture missed a slice.
114
+
115
+ The mapped test SHOULD be an integration or E2E test (oracles describe boundary behavior; unit tests with mocks at the boundary don't satisfy them). A pure-unit test mapping is acceptable only when the oracle is itself a unit-level invariant (rare).
116
+
117
+ **Skip condition:** If `phase_plan.codify: skipped` for this work item or `aiwiki/oracles/` is empty for the work scope, record "No oracles in scope" in the plan and proceed. The check is non-blocking when oracle capture wasn't part of the lifecycle (e.g. trivial bugfix routed past harden).
118
+
99
119
  ### Step 2.5: Map User Journeys to E2E Scenarios
100
120
 
101
121
  If the requirements document includes a User Journeys section, create a business flow traceability table. Every journey MUST map to an E2E test scenario. Gaps are flagged before test execution.
@@ -237,7 +257,7 @@ If the critic identifies coverage gaps or missing scenarios, address them before
237
257
 
238
258
  | Field | Value |
239
259
  |---|---|
240
- | **Requires** | Implementation code (from `build-tdd`), architecture artifacts (`.forge/work/{type}/{name}/architecture/`), requirements (`.forge/work/{type}/{name}/requirements.md`) |
260
+ | **Requires** | Implementation code (from `build-tdd`), architecture artifacts (`.forge/work/{type}/{name}/architecture/`), requirements (`.forge/work/{type}/{name}/requirements.md`), oracle pages (`aiwiki/oracles/*.md` from harden Step 2.5) when codify ran |
241
261
  | **Produces** | `.forge/work/{type}/{name}/test-plan.md` |
242
262
  | **Feeds into** | `quality-test-execution` (test plan drives execution) |
243
263
  | **Updates manifest** | `artifacts.test-plan: test-plan.md` |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: support-debug
3
- description: "Use when encountering any bug, test failure, error, crash, or unexpected behavior — enforces systematic root cause investigation."
3
+ description: "Use when a bug, test failure, error, crash, or unexpected behavior needs systematic investigation triggered by phrases like 'debug this', 'why is X failing', 'trace this error', 'figure out what's wrong', 'investigate the failure', 'this is broken', 'help me debug'. Enforces a four-phase process (fact-check → root-cause investigation → hypothesis testing → implementation) with a 3-fix threshold that stops the random-fix spiral. Skip when the user is asking a design or architecture question (not a failure to investigate), when the failure is a known limitation already documented, or when the work is prototype iteration where the lightweight feedback loop in iterate-prototype is the right shape."
4
4
  ---
5
5
 
6
6
  # Support: Debug
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: support-dream
3
- description: "Use when the user asks to 'consolidate the wiki', 'clean up aiwiki', 'merge duplicate notes', 'prune stale gotchas', or when /evolve runs maintenance. Also auto-fires on phase-close or when context approaches compaction (~85%). Merges aiwiki duplicates, resolves contradictions, refreshes the session index. Output goes to aiwiki/proposed/ for user review — input is never modified."
3
+ description: "Use when the user asks to 'consolidate the wiki', 'clean up aiwiki', 'merge duplicate notes', 'prune stale gotchas', or when /forge-evolve runs maintenance. Auto-fires via /dream slash command (manual), hooks/scripts/pre-compact.sh (PreCompact, ~85% context — writes a 'Status: unconsumed' Checkpoints entry to aiwiki/sessions/{date}-{session_id}.md that the post-compact agent acts on), and phase-close skills (iterate-prototype Step 9, harden Step 4, feature.md Step 8.5 per-slice, deliver-deploy Phase 5.4 retrospective) which dispatch this skill after writing their respective artifacts.{phase}.locked_at. Merges aiwiki duplicates, resolves contradictions, refines the active session file. Output goes to aiwiki/proposed/ for user review — input is never modified."
4
4
  ---
5
5
 
6
6
  # Support: Dream (Wiki Consolidation)
@@ -22,7 +22,7 @@ Three triggers, distinct intents:
22
22
  | Trigger | Intent | Scope |
23
23
  |---|---|---|
24
24
  | **Phase close** (Phase 4 (iterate) lock, Phase 5 (codify) lock, Phase 6 (production-build) per-slice close, Phase 7 (deliver) retrospective) | Promote phase outputs into curated wiki state | Subfolders touched by the phase |
25
- | **PreCompact hook fire** (~85% context utilization) | Consolidate session signal into durable form before lossy compaction | `aiwiki/sessions/{current}` + `aiwiki/raw/` + recently-touched typed pages |
25
+ | **PreCompact hook fire** (~85% context utilization) | Consolidate signal into durable form before lossy compaction | `aiwiki/raw/` + recently-touched typed pages. Also refines the active session file (`aiwiki/sessions/{date}-{session_id_short}.md`) — pre-compact creates it lazily on first fire; dream consolidates its `## Checkpoints` event log if it grows beyond ~10 entries. |
26
26
  | **Manual `/dream`** | User-driven cleanup (after major refactor, branch merge, accumulated noise) | User-specified |
27
27
 
28
28
  **Do NOT skip when:**
@@ -55,14 +55,15 @@ Fired by phase-close hooks (after user emits the phase-lock signal):
55
55
 
56
56
  ### PreCompact trigger
57
57
 
58
- Fired by forge's existing pre-compact hook (~85% context):
58
+ Fired indirectly via the pre-compact hook (`hooks/scripts/pre-compact.sh`). The hook itself cannot dispatch a subagent — instead it writes a `**Dream directive (unconsumed)**` block to the active session file's `## Checkpoints` section. The post-compact agent reads the session file, finds the unconsumed directive, and invokes this skill.
59
59
 
60
- 1. Hook calls skill with scope `[aiwiki/sessions/{current}, aiwiki/raw/, recently-touched-typed-pages]`
61
- 2. **Sync prerequisite** — session checkpoint hook has already updated `aiwiki/sessions/{current}.md` with all events. Dream IMPROVES this file; does not produce its existence.
60
+ 1. Skill is invoked by the post-compact agent acting on the directive. Scope from directive: `aiwiki/raw/` + recently-touched typed pages, plus the active session file itself (`aiwiki/sessions/{date}-{session_id_short}.md`).
61
+ 2. **Session file is always present at PreCompact time** — pre-compact.sh creates it lazily on first fire and appends the checkpoint. Dream refines the session file's `## Checkpoints` section if it has grown unwieldy (>10 entries) and may pre-populate the index sections (`## Files touched`, etc.) from git diff and aiwiki writes, leaving `/wrap` to finalize.
62
62
  3. Dispatches `dreamer` subagent
63
63
  4. Output to `aiwiki/proposed/{dream_id}/`
64
64
  5. LINT runs on proposed output
65
- 6. Native compaction proceeds (does not wait for user review — the consolidated session file is already on disk)
65
+ 6. Native compaction does not wait for user review — the consolidated raw/typed pages and session-file proposal are already on disk
66
+ 7. **Mark the directive consumed** — after dispatch returns, the agent changes the originating entry's header from `**Dream directive (unconsumed):**` to `**Dream directive (consumed at {ISO-timestamp}):**`. Header-flip is what `session-start.sh` counts. Appending a separate "Status: consumed" line leaves the original unconsumed-marked header in place and the next session-start will still surface it as a HARD-INTERRUPT (dogfood-validated 2026-05-18).
66
67
 
67
68
  ### Manual /dream trigger
68
69
 
@@ -176,7 +177,7 @@ This skill operates the dream side; the user-facing CLI is separate but document
176
177
  | Mistake | Fix |
177
178
  |---|---|
178
179
  | Modifying `aiwiki/` directly during consolidation | All writes go to `aiwiki/proposed/{dream_id}/`; the swap is the user's action |
179
- | Writing to `aiwiki/sessions/{current}.md` to "create" the file | Session checkpoint hook creates the file; dream only refines an existing file |
180
+ | Writing a new file in `aiwiki/sessions/` instead of refining the active session file | The active session file is `aiwiki/sessions/{date}-{session_id_short}.md` created by pre-compact, /wrap, /dream, or harden. Dream refines that file in place (via the proposed-output path); it does not produce a separate sessions file. |
180
181
  | Running dream when there's no signal to consolidate | Skip the dream entirely; record nothing |
181
182
  | Skipping LINT on proposed output | LINT MUST run; lint warnings go into the manifest, surface during review |
182
183
  | Promoting raw entries without reading the target schema | Read `aiwiki/schemas/{type}.md` first; the raw entry must satisfy required sections + frontmatter |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: support-gotcha
3
- description: "Use when a subtle bug, surprising behavior, or hard-won lesson is uncovered that could recur records it as a typed wiki page for future prevention."
3
+ description: "Use when a reproducible failure mode, hard-won lesson, or surprising behavior with a concrete trigger emerges and is worth preventing next time — triggered by phrases like 'record this gotcha', 'save this lesson', 'capture this finding', 'we should remember this', 'this is a gotcha', 'log this for future', or automatically after support-debug closes a non-trivial bug. Writes a typed page to aiwiki/gotchas/{date}-{slug}.md with reproduction steps, root cause, and concrete fix; promotes to a rule when the same pattern recurs (N=3). Skip for speculation or half-formed thoughts (use /note for those); skip if the failure mode is not reproducible — a gotcha needs a concrete trigger, not a vibe."
4
4
  ---
5
5
 
6
6
  # Support: Gotcha
@@ -43,7 +43,7 @@ Every bug fixed, every failed approach, every "I wish I'd known that earlier" mo
43
43
  | **Requires** | Concrete lesson: what broke, why, how to prevent |
44
44
  | **Produces** | Gotcha page in `aiwiki/gotchas/{YYYY-MM-DD}-{slug}.md` (project) or `~/.claude/gotchas/{YYYY-MM-DD}-{slug}.md` (global) |
45
45
  | **Schema** | `aiwiki/schemas/gotcha.md` — LINT validates frontmatter + sections on write |
46
- | **Feeds into** | Future sessions (prevention), `gotcha-hunter` agent (surfaces relevant entries to reviewers), `/evolve` (skill improvement) |
46
+ | **Feeds into** | Future sessions (prevention), `gotcha-hunter` agent (surfaces relevant entries to reviewers), `/forge-evolve` (skill improvement) |
47
47
 
48
48
  ### Storage tiers
49
49
 
@@ -234,7 +234,7 @@ When no pending promotions exist, `gotcha-hunter` (separate agent) reads `aiwiki
234
234
  | `gotcha-hunter` (agent) | Reads `aiwiki/gotchas/` and surfaces diff-relevant entries to reviewers; never writes |
235
235
  | `support-wiki-lint` | Validates frontmatter + sections on every write |
236
236
  | `support-dream` | At phase-close / PreCompact: consolidates raw entries, may merge similar gotchas, prunes retired entries (writes proposals to `aiwiki/proposed/{dream_id}/` for user review) |
237
- | `/evolve` command | Reads gotchas to identify skill improvement opportunities |
237
+ | `/forge-evolve` command | Reads gotchas to identify skill improvement opportunities |
238
238
 
239
239
  ## Quick reference
240
240
 
@@ -1,28 +1,28 @@
1
1
  ---
2
- name: support-task-force
3
- description: "Use when the user prompts a punch list of independent tasks (numbered or bulleted, ≥3 items) OR explicitly invokes /task-force. Classifies each task by type, assembles the right specialist team per task, dispatches all in parallel, aggregates results. Phase-aware: light teams during prototype phases (fast iteration), full crew during harden/production (no shortcuts). Optional Codex adversarial pairing when consent is on. REFUSES command-shaped work — routes feature/bugfix/refactor items to their owning commands instead."
2
+ name: support-parallel
3
+ description: "Use when the user prompts a punch list of independent tasks (numbered or bulleted, ≥3 items) OR explicitly invokes /parallel. Classifies each task by type, assembles the right specialist team per task, dispatches all in parallel, aggregates results. Phase-aware: light teams during prototype phases (fast iteration), full crew during harden/production (no shortcuts). Optional Codex adversarial pairing when consent is on. REFUSES command-shaped work — routes feature/bugfix/refactor items to their owning commands instead."
4
4
  ---
5
5
 
6
- # Task Force
6
+ # Parallel
7
7
 
8
8
  ## Overview
9
9
 
10
10
  Users don't always invoke `/feature` or `/bugfix`. The daily reality is a paste-in punch list: "do these 10 things: 1. update README; 2. explore option X; 3. add a test for Y; 4. ...". Doing those in series in one context window is slow, conflict-prone, and skips the Codex second-opinion that catches real bugs.
11
11
 
12
- This skill assembles a **task-force per item** — a specialist team sized for the task's type and the project's current phase — and dispatches them in parallel. Each task-force has a Claude reviewer/builder paired with a Codex sibling (when the task is non-trivial). The skill REFUSES to swallow command-shaped work; items that look like features/bugfixes/refactors get routed to their owning commands.
12
+ This skill assembles a **team per item** — sized for the task's type and the project's current phase — and dispatches them in parallel. Each team has a Claude reviewer/builder paired with a Codex sibling (when the task is non-trivial). The skill REFUSES to swallow command-shaped work; items that look like features/bugfixes/refactors get routed to their owning commands.
13
13
 
14
14
  **Core principle:** match team size to task complexity AND to the project's current phase. Prototype phases iterate fast with light teams. Production phases demand the full crew.
15
15
 
16
- **Announce at start:** "I'm using support-task-force to dispatch N task-forces in parallel — M routed to commands, K running in light mode, L running in full mode." If `!max` / `--full-power` detected: "...running in `!max` mode — production teams enforced regardless of phase."
16
+ **Announce at start:** "I'm using support-parallel to dispatch N teams in parallel — M routed to commands, K running in light mode, L running in full mode." If `!max` / `--full-power` detected: "...running in `!max` mode — production teams enforced regardless of phase."
17
17
 
18
18
  ## When to Use
19
19
 
20
20
  Fire when **any** of:
21
- - User types `/task-force` explicitly
21
+ - User types `/parallel` explicitly
22
22
  - User prompt contains a numbered list (`1. xxx 2. xxx 3. xxx`) with ≥3 items
23
23
  - User prompt contains a bulleted list (`- xxx / - xxx / - xxx`) with ≥3 items AND items look like work-tasks (not casual mentions)
24
24
 
25
- Confirm with user before dispatching if auto-detected (one-line: "Detected a 5-item task list; dispatching task-forces — say 'no' to cancel").
25
+ Confirm with user before dispatching if auto-detected (one-line: "Detected a 5-item task list; dispatching teams — say 'no' to cancel").
26
26
 
27
27
  Do NOT use for:
28
28
  - A single task (use the appropriate command or skill directly)
@@ -33,7 +33,7 @@ Do NOT use for:
33
33
 
34
34
  ### Step 0: Codex consent (per `protocols/codex.md`)
35
35
 
36
- Run the Codex consent flow ONCE for the whole task-force run. The choice (Verify / Takeover / Skip / Never) propagates to every per-task dispatch. Record in `.forge/task-force/{run-id}/codex.yaml`.
36
+ Run the Codex consent flow ONCE for the whole parallel run. The choice (Verify / Takeover / Skip / Never) propagates to every per-task dispatch. Record in `.forge/parallel/{run-id}/codex.yaml`.
37
37
 
38
38
  ### Step 1: Detect repo phase (or honor full-power override)
39
39
 
@@ -100,7 +100,7 @@ For each task, apply this classifier in order — first match wins:
100
100
  | ≥4 subsystems touched OR ≥3 verbs combined | **complex** |
101
101
  | Anything else | **ambiguous** (ask user) |
102
102
 
103
- Command-shaped items get **routed out** — they do NOT get a task-force. Surface them to the user with: "Item X looks like a `/feature` — running it as a forge command instead. The remaining items continue as task-forces." User can override.
103
+ Command-shaped items get **routed out** — they do NOT get a team. Surface them to the user with: "Item X looks like a `/feature` — running it as a forge command instead. The remaining items continue as teams." User can override.
104
104
 
105
105
  ### Step 4: Assemble team per task
106
106
 
@@ -136,20 +136,20 @@ Apply both the **task type** AND the **phase mode**:
136
136
 
137
137
  Ask the user: "Is this a prototype or production task list?" Then proceed with the matching template.
138
138
 
139
- ### Step 5: Dispatch all task-forces in parallel
139
+ ### Step 5: Dispatch all teams in parallel
140
140
 
141
141
  For each non-routed task:
142
142
  1. Compose the prompt: include the task text, the detected type, phase mode, the team composition.
143
143
  2. Fire each agent in the team as a background subagent (`run_in_background: true`).
144
144
  3. For tasks whose team includes "dispatch X skill", spawn ONE agent that invokes that skill (the skill handles its own internal multi-agent chain).
145
- 4. Tag each agent with `task-force/{run-id}/{task-n}/{role}` for telemetry.
145
+ 4. Tag each agent with `parallel/{run-id}/{task-n}/{role}` for telemetry.
146
146
 
147
147
  Batched dispatch ceiling: 20-25 agents per `<function_calls>` block. For 10 tasks × 4 agents = 40 agents, plan 2 dispatch rounds.
148
148
 
149
149
  ### Step 6: Accumulate
150
150
 
151
151
  Background notifications arrive asynchronously:
152
- - Save each agent's result to `.forge/task-force/{run-id}/task-{n}/{role}.md`
152
+ - Save each agent's result to `.forge/parallel/{run-id}/task-{n}/{role}.md`
153
153
  - Maintain a per-task status line: `Task 3 of 10: 2 of 3 agents complete (1 pending)`
154
154
  - DO NOT narrate every individual agent completion to the user — batch updates every ≥3 returns
155
155
 
@@ -161,14 +161,14 @@ When all agents for a task return, synthesize:
161
161
  - If only one returned (other failed/timeout) → mark `complete-single-source`, flag for user attention
162
162
  - If both failed → mark `failed`, recommend retry or single-task fallback
163
163
 
164
- Per-task output goes to `.forge/task-force/{run-id}/task-{n}/verdict.md`.
164
+ Per-task output goes to `.forge/parallel/{run-id}/task-{n}/verdict.md`.
165
165
 
166
166
  ### Step 8: Run summary
167
167
 
168
168
  After all tasks finish (or hit batch limit), produce one consolidated report:
169
169
 
170
170
  ```
171
- Task-Force Run {run-id} — {N} tasks, {M} routed to commands
171
+ Parallel Run {run-id} — {N} tasks, {M} routed to commands
172
172
 
173
173
  | # | Task | Type | Team size | Status | Conflicts |
174
174
  |---|------|------|-----------|--------|-----------|
@@ -186,7 +186,7 @@ Followups:
186
186
  - Run /feature for item 4 when ready
187
187
  ```
188
188
 
189
- Write the summary to `.forge/task-force/{run-id}/run-summary.md` and surface to user.
189
+ Write the summary to `.forge/parallel/{run-id}/run-summary.md` and surface to user.
190
190
 
191
191
  ### Step 9: Stop
192
192
 
@@ -197,8 +197,8 @@ This skill does ONE run per invocation. If the user wants to iterate on findings
197
197
  | Field | Value |
198
198
  |---|---|
199
199
  | Requires | A user-provided task list (parsed in Step 2); optionally an active manifest for phase detection |
200
- | Produces | `.forge/task-force/{run-id}/codex.yaml`, `.forge/task-force/{run-id}/tasks.yaml` (classification), `.forge/task-force/{run-id}/task-{n}/{role}.md` per agent, `.forge/task-force/{run-id}/task-{n}/verdict.md` per task, `.forge/task-force/{run-id}/run-summary.md` |
201
- | Updates manifest | If a feature/bugfix manifest is active, append `phases.{phase}.task-force-runs: [{run-id}]`. Otherwise no manifest update — task-force runs are not phase-gated. |
200
+ | Produces | `.forge/parallel/{run-id}/codex.yaml`, `.forge/parallel/{run-id}/tasks.yaml` (classification), `.forge/parallel/{run-id}/task-{n}/{role}.md` per agent, `.forge/parallel/{run-id}/task-{n}/verdict.md` per task, `.forge/parallel/{run-id}/run-summary.md` |
201
+ | Updates manifest | If a feature/bugfix manifest is active, append `phases.{phase}.parallel-runs: [{run-id}]`. Otherwise no manifest update — parallel runs are not phase-gated. |
202
202
  | Feeds into | `/feature`, `/bugfix`, `/refactor` (for routed items); `support-gotcha` (for recurring patterns surfaced across tasks) |
203
203
 
204
204
  ## Agent Dispatch
@@ -224,11 +224,11 @@ Raw agents it dispatches directly:
224
224
  | Step | Skill / Command | Why |
225
225
  |---|---|---|
226
226
  | Pre-dispatch consent | `protocols/codex.md` | Codex pairing requires consent ONCE per run |
227
- | Task routing-out | `/feature`, `/bugfix`, `/refactor`, `/greenfield`, `/hotfix` | Command-shaped items must use commands, not task-forces |
227
+ | Task routing-out | `/feature`, `/bugfix`, `/refactor`, `/greenfield`, `/hotfix` | Command-shaped items must use commands, not teams |
228
228
  | Per-task dev | `quality-code-review` skill | Production dev tasks get the full review chain |
229
229
  | Per-task debug | `support-debug` skill | Debug tasks get tracer + gotcha-hunter |
230
230
  | Per-task security | `quality-security-audit` skill | Security tasks get the OWASP-aware audit chain |
231
- | Post-run gotcha | `support-gotcha` | Patterns surfaced across multiple task-forces deserve a recorded lesson |
231
+ | Post-run gotcha | `support-gotcha` | Patterns surfaced across multiple teams deserve a recorded lesson |
232
232
 
233
233
  ## Red Flags
234
234
 
@@ -239,12 +239,12 @@ Raw agents it dispatches directly:
239
239
  | Codex consent skipped silently | Means no second-opinion across the whole run — for production-mode tasks this is a regression |
240
240
  | 0 conflicts across all tasks | Either every task was trivial OR Claude+Codex are echoing each other; sample-check |
241
241
  | Complex tasks in prototype mode | Probably should be a /feature; warn user before proceeding |
242
- | Run-id directories never get cleaned | Add a periodic prune; aiwiki/dream or /evolve should handle it |
242
+ | Run-id directories never get cleaned | Add a periodic prune; aiwiki/dream or /forge-evolve should handle it |
243
243
  | Soft cap warning ignored repeatedly | User has misframed work — recommend splitting into milestones |
244
244
 
245
245
  ## Anti-Patterns
246
246
 
247
- **Swallowing command-shaped work.** If the user types "add a payment feature, then audit security, then ship", DO NOT run a task-force — that's three workflows pretending to be three tasks. Route them: `/feature` → `quality-security-audit` → `/feature` deploy phase. Task-force is for items that DON'T fit a workflow.
247
+ **Swallowing command-shaped work.** If the user types "add a payment feature, then audit security, then ship", DO NOT dispatch a parallel run — that's three workflows pretending to be three tasks. Route them: `/feature` → `quality-security-audit` → `/feature` deploy phase. `/parallel` is for items that DON'T fit a workflow.
248
248
 
249
249
  **Phase-blind sizing.** Spawning the full crew on a Phase-4 prototype task wastes tokens AND violates the prototype-throwaway principle. Always read phase first.
250
250
 
@@ -252,7 +252,7 @@ Raw agents it dispatches directly:
252
252
 
253
253
  **Ignoring divergent verdicts.** Claude+Codex disagreement is a SIGNAL, not noise. Surface it. Let the user adjudicate.
254
254
 
255
- **Letting `.forge/task-force/` grow forever.** Each run leaves a directory. Add to `support-dream` consolidation scope, or document a cleanup pattern.
255
+ **Letting `.forge/parallel/` grow forever.** Each run leaves a directory. Add to `support-dream` consolidation scope, or document a cleanup pattern.
256
256
 
257
257
  **Auto-dispatching without confirmation when auto-detected.** Numbered lists in user prose aren't always task lists (could be a survey of options, a sequence diagram, etc.). Confirm before firing 40 agents.
258
258
 
@@ -1,4 +1,4 @@
1
- # Task-Force Dispatch Pattern
1
+ # Parallel Dispatch Pattern
2
2
 
3
3
  Operational recipes for spawning per-task Claude+Codex teams.
4
4
 
@@ -101,7 +101,7 @@ complex → architect + tracer + builder + dispatch quality-code-review + spe
101
101
  ## Per-agent prompt template
102
102
 
103
103
  ```
104
- You are agent {role} in task-force task {n} of {N}, run-id {run-id}.
104
+ You are agent {role} in parallel-run task {n} of {N}, run-id {run-id}.
105
105
 
106
106
  Task type: {dev|research|debug|docs|review|security|quick|complex}
107
107
  Phase mode: {prototype|production}
@@ -120,10 +120,10 @@ Your scope: {paths, subsystem, or "whole repo"}
120
120
 
121
121
  OUTPUT:
122
122
  - Result of doing the task (code diffs, findings, document, etc.)
123
- - One-line verdict for the task-force aggregator: PASS / CONCERNS / FAIL
124
- - Hand off any followups by writing them to .forge/task-force/{run-id}/task-{n}/followups.md
123
+ - One-line verdict for the parallel-run aggregator: PASS / CONCERNS / FAIL
124
+ - Hand off any followups by writing them to .forge/parallel/{run-id}/task-{n}/followups.md
125
125
 
126
- Cap your output at {N} words. Save artifacts under .forge/task-force/{run-id}/task-{n}/{role}.{ext}.
126
+ Cap your output at {N} words. Save artifacts under .forge/parallel/{run-id}/task-{n}/{role}.{ext}.
127
127
  ```
128
128
 
129
129
  ## Batched dispatch ceiling
@@ -155,7 +155,7 @@ else:
155
155
  | Codex sandbox can't write | "operation blocked in sandbox" | Codex outputs uncommitted; Claude commits or main session commits |
156
156
  | Two agents touch same file | Edit tool conflict | Partition more aggressively |
157
157
  | Classifier picks command-shaped but rest heterogeneous | Some routed, some not | Surface routing decisions, continue with remainder |
158
- | User cancels mid-run | Receives interrupt | Mark in-flight tasks abandoned; preserve completed outputs |
158
+ | User cancels mid-run | Receives interrupt | Stop in-flight tasks; preserve completed outputs |
159
159
 
160
160
  ## Sizing examples
161
161
 
@@ -172,7 +172,7 @@ else:
172
172
 
173
173
  ## Cleanup
174
174
 
175
- `.forge/task-force/{run-id}/` accumulates per-run. Prune via:
176
- - `/evolve` (include task-force cleanup as a step)
177
- - Manual: `find .forge/task-force -maxdepth 1 -mtime +30 -exec rm -rf {} +`
178
- - `support-dream` could consolidate task-force runs into aiwiki summary entries before prune
175
+ `.forge/parallel/{run-id}/` accumulates per-run. Prune via:
176
+ - `/forge-evolve` (include parallel-run cleanup as a step)
177
+ - Manual: `find .forge/parallel -maxdepth 1 -mtime +30 -exec rm -rf {} +`
178
+ - `support-dream` could consolidate parallel runs into aiwiki summary entries before prune
@@ -1,4 +1,4 @@
1
- # Task-Force Output Templates
1
+ # Parallel Run Output Templates
2
2
 
3
3
  Use these for per-task verdicts (Step 7) and run summaries (Step 8).
4
4
 
@@ -31,20 +31,20 @@ Use these for per-task verdicts (Step 7) and run summaries (Step 8).
31
31
 
32
32
  ## Artifacts
33
33
 
34
- - `.forge/task-force/{run-id}/task-{n}/builder.md`
35
- - `.forge/task-force/{run-id}/task-{n}/code-reviewer-claude.md`
36
- - `.forge/task-force/{run-id}/task-{n}/code-reviewer-codex.md`
37
- - `.forge/task-force/{run-id}/task-{n}/followups.md` (if any)
34
+ - `.forge/parallel/{run-id}/task-{n}/builder.md`
35
+ - `.forge/parallel/{run-id}/task-{n}/code-reviewer-claude.md`
36
+ - `.forge/parallel/{run-id}/task-{n}/code-reviewer-codex.md`
37
+ - `.forge/parallel/{run-id}/task-{n}/followups.md` (if any)
38
38
 
39
39
  ## Followups (if any)
40
40
 
41
- - <item> — owner: <user | next task-force run | /evolve>
41
+ - <item> — owner: <user | next parallel run | /forge-evolve>
42
42
  ```
43
43
 
44
44
  ## Run summary
45
45
 
46
46
  ```markdown
47
- # Task-Force Run {run-id}
47
+ # Parallel Run {run-id}
48
48
 
49
49
  **Started:** {ISO-8601}
50
50
  **Completed:** {ISO-8601}
@@ -95,9 +95,9 @@ Use these for per-task verdicts (Step 7) and run summaries (Step 8).
95
95
 
96
96
  ## Next steps
97
97
 
98
- If divergence > 30%, sample-check a few task-force outputs — your classifier or team-assembly might be miscalibrated.
98
+ If divergence > 30%, sample-check a few team outputs — your classifier or team-assembly might be miscalibrated.
99
99
 
100
- If all tasks PASSED with no divergence, run a `/evolve` to consider whether patterns recurred enough to warrant capturing as a gotcha or rule.
100
+ If all tasks PASSED with no divergence, run a `/forge-evolve` to consider whether patterns recurred enough to warrant capturing as a gotcha or rule.
101
101
  ```
102
102
 
103
103
  ## Severity / verdict definitions
@@ -123,4 +123,4 @@ After run summary, if any task is `complete-divergent` AND the divergence is ove
123
123
  - Debug task with divergent verdicts → `support-debug` skill standalone
124
124
  - Research task with divergent verdicts → user adjudication required
125
125
 
126
- Task-force is for parallel speed. When agreement breaks down, the right tool is depth, not parallelism.
126
+ `/parallel` is for parallel speed. When agreement breaks down, the right tool is depth, not parallelism.
@@ -16,7 +16,7 @@ As the forge harness grows -- skills added, rules promoted from gotchas, command
16
16
  | Trigger | Validation Scope | Performance Target |
17
17
  |---|---|---|
18
18
  | `/validate` command | Full scan (all 5 checks) | Under 30 seconds |
19
- | `/evolve` modifies a skill | Pre-apply check (modified skill vs all others) | Under 10 seconds |
19
+ | `/forge-evolve` modifies a skill | Pre-apply check (modified skill vs all others) | Under 10 seconds |
20
20
  | Session start | Lightweight I/O graph check only | Under 3 seconds |
21
21
  | Manual request | Full scan or targeted check | Depends on scope |
22
22
  | After gotcha promotion | Promoted rule vs existing rules and skills | Under 10 seconds |
@@ -32,7 +32,7 @@ As the forge harness grows -- skills added, rules promoted from gotchas, command
32
32
  |---|---|
33
33
  | **Requires** | All `SKILL.md` files + all `rules/*.md` files + all `commands/*.md` files |
34
34
  | **Produces** | Validation report (structured, actionable) |
35
- | **Feeds into** | `/evolve` command (fix contradictions before applying changes) |
35
+ | **Feeds into** | `/forge-evolve` command (fix contradictions before applying changes) |
36
36
  | **Updates** | Nothing directly -- produces a report for human/AI action |
37
37
 
38
38
  ### Input Files
@@ -127,9 +127,9 @@ No blocking errors. System is consistent.
127
127
  Warnings should be reviewed when convenient.
128
128
  ```
129
129
 
130
- ### /evolve Command (Pre-Apply Check)
130
+ ### /forge-evolve Command (Pre-Apply Check)
131
131
 
132
- Before `/evolve` applies any skill modification:
132
+ Before `/forge-evolve` applies any skill modification:
133
133
 
134
134
  1. Receive the proposed change
135
135
  2. Apply the change to a temporary copy
@@ -139,7 +139,7 @@ Before `/evolve` applies any skill modification:
139
139
  6. If clean: ALLOW the change
140
140
 
141
141
  ```
142
- /evolve proposes modifying build-tdd...
142
+ /forge-evolve proposes modifying build-tdd...
143
143
 
144
144
  Pre-apply validation:
145
145
  [PASS] No directive conflicts
@@ -267,7 +267,7 @@ Only escalate to WARNING/ERROR when you can name the downstream skill that fails
267
267
  ```
268
268
  DRIFT:
269
269
 
270
- [ERROR] D-001: New Contradiction After /evolve
270
+ [ERROR] D-001: New Contradiction After /forge-evolve
271
271
  Modified: support-debug (added "ALWAYS verify with context7 before debugging")
272
272
  Conflicts with: rules/common/verification.md ("verify when UNCERTAIN, not always")
273
273
  Analysis: New directive is stricter than existing rule.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: support-system-guide
3
- description: "Use when the user opens a fresh session, asks 'what should I run', 'where do I start', 'which command for X', 'is this a /feature or /greenfield', or describes intent without naming a command. Routes them to the right command (/feature, /greenfield, /task-force, /harden, etc.) and explains the phase model. Skip if the user has already invoked a specific command."
3
+ description: "Use when the user opens a fresh session, asks 'what should I run', 'where do I start', 'which command for X', 'is this a /feature or /greenfield', or describes intent without naming a command. Routes them to the right command (/feature, /greenfield, /parallel, /harden, etc.) and explains the phase model. Skip if the user has already invoked a specific command."
4
4
  ---
5
5
 
6
6
  <EXTREMELY-IMPORTANT>
@@ -71,13 +71,14 @@ When the user describes what they want to do, route them to the correct command.
71
71
 
72
72
  | User Intent | Command | What It Does |
73
73
  |---|---|---|
74
- | "What does this project have?" / "Show me forge" / "What can I run?" | `/forge` | One-screen discovery — installed capabilities, active work, suggested next |
74
+ | "What does this project have?" / "Show me forge" / "What can I run?" | `/discover` | One-screen discovery — installed capabilities, active work, suggested next |
75
+ | "Capture this thought" / "Note this for later" / "Save this research" | `/note <text>` | Append to `aiwiki/raw/{date}.md` — for Phase 1-2 research, ad-hoc brainstorm, anything not yet a typed page |
75
76
  | "Add a feature" / "Implement X" / "Build Y" | `/feature` | Full lifecycle: discover -> plan -> build -> quality -> deliver |
76
77
  | "New project" / "Start from scratch" / "Greenfield" | `/greenfield` | Scaffold + full lifecycle for a new project |
77
78
  | "Fix this bug" / "Something is broken" / "Error when..." | `/bugfix` | Debug -> fix -> test -> PR |
78
79
  | "Clean up" / "Refactor" / "Improve code quality" | `/refactor` | Analyze -> refactor -> review -> PR |
79
80
  | "Production is down" / "Emergency fix" / "Critical bug" | `/hotfix` | Emergency: debug -> fix -> test -> deploy (expedited gates) |
80
- | "Improve the skills" / "Update a skill" / "System enhancement" | `/evolve` | Self-improvement: review skills, propose changes, validate |
81
+ | "Improve the skills" / "Update a skill" / "System enhancement" | `/forge-evolve` | Self-improvement: review skills, propose changes, validate |
81
82
  | "Check consistency" / "Validate skills" / "Run validator" | `/validate` | Validate all skills/rules for contradictions and gaps |
82
83
 
83
84
  ### Command vs. Direct Skill Use
@@ -23,8 +23,23 @@ const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
23
23
  const CITATION_HASHED_RE = /([\w./@~-]+\.\w+):(\d+)@([0-9a-f]{7})\b/g;
24
24
  const CITATION_BARE_RE = /([\w./@~-]+\.\w+):(\d+)(?!@?[0-9a-f]{7})\b/g;
25
25
  const ACK_STALE_RE = /\/\/\s*ack-stale\s*:|#\s*ack-stale\s*:/;
26
+ const ACK_SECRET_RE = /\back-secret\s*:/;
26
27
  const SECTION_RE = /^##\s+(.+?)\s*$/gm;
27
28
 
29
+ // Possible-secret patterns. Advisory only — emitted as warnings, not errors.
30
+ // Lint hook is non-blocking (`hooks/scripts/wiki-lint.sh` returns continue:true
31
+ // unconditionally), so these never block a write — they surface on stderr so
32
+ // the next edit can address them. False positives are downgraded to info if
33
+ // the same line carries an `ack-secret: <reason>` annotation.
34
+ const SECRET_PATTERNS = [
35
+ { name: 'aws_access_key', re: /AKIA[0-9A-Z]{16}/g },
36
+ { name: 'private_key_block', re: /-----BEGIN (?:[A-Z ]+ )?PRIVATE KEY-----/g },
37
+ { name: 'password_assignment', re: /\b(?:password|passwd|pwd)\s*[=:]\s*['"][^'"\s$][^'"\s]{3,}['"]/gi },
38
+ { name: 'api_key_assignment', re: /\b(?:api[_-]?key|apikey|secret[_-]?key|access[_-]?token|bearer[_-]?token)\s*[=:]\s*['"][^'"\s$][^'"\s]{7,}['"]/gi },
39
+ { name: 'jwt_token', re: /\beyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g },
40
+ { name: 'url_credentials', re: /\b[a-z][a-z0-9+.-]*:\/\/[^\s/:@]+:[^\s/@]+@/gi },
41
+ ];
42
+
28
43
  // ---- Minimal YAML parser ---------------------------------------------------
29
44
  // Handles only what our schema + frontmatter files use:
30
45
  // - Top-level mapping
@@ -389,6 +404,43 @@ export function lint({ file, schemasDir, root }) {
389
404
  fs.writeFileSync(absFile, newContent, 'utf8');
390
405
  }
391
406
 
407
+ // Secrets scan — advisory only, never an error. The wiki-lint hook is
408
+ // non-blocking; these warnings surface on stderr so the next edit can
409
+ // address them. Scan the FINAL post-backfill content (after citation hash
410
+ // updates). Skip lines annotated with `ack-secret: <reason>`.
411
+ const finalContent = updates.length > 0
412
+ ? `---\n${modifiedFm}\n---\n${modifiedBody}`
413
+ : original;
414
+ const finalLines = finalContent.split('\n');
415
+ const finalLineOffsets = computeLineOffsets(finalContent);
416
+ for (const { name, re } of SECRET_PATTERNS) {
417
+ re.lastIndex = 0;
418
+ let m;
419
+ while ((m = re.exec(finalContent)) !== null) {
420
+ const matchOffset = m.index;
421
+ // Find the line number (1-based).
422
+ let lineNum = 1;
423
+ for (let i = 0; i < finalLineOffsets.length; i++) {
424
+ if (finalLineOffsets[i] > matchOffset) break;
425
+ lineNum = i + 1;
426
+ }
427
+ const lineText = finalLines[lineNum - 1] || '';
428
+ const ackedOnSameLine = ACK_SECRET_RE.test(lineText);
429
+ const finding = {
430
+ kind: 'possible_secret',
431
+ type: name,
432
+ line: lineNum,
433
+ preview: m[0].slice(0, 40),
434
+ message: `Possible ${name} on line ${lineNum} (preview: ${m[0].slice(0, 40)}). If this is an intentional example or test fixture, add an \`ack-secret: <reason>\` annotation on the same line to downgrade to info.`,
435
+ };
436
+ if (ackedOnSameLine) {
437
+ warnings.push({ ...finding, kind: 'possible_secret_acked' });
438
+ } else {
439
+ warnings.push(finding);
440
+ }
441
+ }
442
+ }
443
+
392
444
  return {
393
445
  ok: errors.length === 0,
394
446
  file,
@@ -12,7 +12,7 @@ Installed into the target project by `npx @jamie-tam/forge init` (or kept in-syn
12
12
 
13
13
  ## Legacy
14
14
 
15
- Kept on-disk so older manifests still parse and so `/evolve` can migrate them forward. Not installed into new projects.
15
+ Kept on-disk so older manifests still parse and so `/forge-evolve` can migrate them forward. Not installed into new projects.
16
16
 
17
17
  - **`manifests/v5/`** — v5 schema (`SCHEMA.md` plus a `feature.yaml` reference). v5 manifests still parse against the v6 reader (see `manifests/v6/SCHEMA.md` §4). v4 manifests also still parse but no template is retained — the reader synthesizes the missing fields.
18
18