@izkac/forgekit 0.3.12 → 0.3.14

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 (120) hide show
  1. package/bin/forge.mjs +119 -107
  2. package/bin/forgekit.mjs +83 -83
  3. package/bin/review.mjs +81 -81
  4. package/package.json +2 -1
  5. package/scripts/prepack.mjs +78 -78
  6. package/scripts/run-tests.mjs +50 -50
  7. package/src/adr.mjs +236 -236
  8. package/src/adr.test.mjs +170 -170
  9. package/src/change.mjs +327 -234
  10. package/src/change.test.mjs +145 -83
  11. package/src/cleanup-sessions.mjs +84 -84
  12. package/src/config.mjs +103 -103
  13. package/src/defer.mjs +75 -75
  14. package/src/doctor.mjs +350 -341
  15. package/src/doctor.test.mjs +114 -114
  16. package/src/fleet.test.mjs +50 -0
  17. package/src/init.mjs +680 -621
  18. package/src/install.mjs +815 -815
  19. package/src/install.test.mjs +180 -180
  20. package/src/integrity-check.mjs +60 -60
  21. package/src/integrity.mjs +688 -682
  22. package/src/integrity.test.mjs +612 -566
  23. package/src/lib/fleet.mjs +61 -4
  24. package/src/lib.mjs +160 -143
  25. package/src/lib.test.mjs +128 -0
  26. package/src/models.defaults.json +41 -41
  27. package/src/new-session.mjs +99 -99
  28. package/src/openspec-overlays/README.md +19 -19
  29. package/src/openspec-overlays/openspec-apply-change-footer.md +14 -14
  30. package/src/openspec-overlays/opsx-apply-completion-step.md +1 -1
  31. package/src/openspec-overlays/opsx-apply-implement-step.md +11 -11
  32. package/src/paths.mjs +92 -92
  33. package/src/plan-engine.mjs +321 -278
  34. package/src/plan-engine.test.mjs +447 -283
  35. package/src/preferences.defaults.json +78 -78
  36. package/src/preferences.mjs +438 -438
  37. package/src/preferences.test.mjs +174 -174
  38. package/src/record-evidence.mjs +204 -204
  39. package/src/repo-root.mjs +33 -0
  40. package/src/resolve-model.mjs +312 -312
  41. package/src/resolve-model.test.mjs +194 -194
  42. package/src/review/cli.test.mjs +117 -117
  43. package/src/review/export.mjs +172 -172
  44. package/src/review/export.test.mjs +197 -197
  45. package/src/review/fixtures/valid-review.json +42 -42
  46. package/src/review/lib.mjs +894 -894
  47. package/src/review/lib.test.mjs +266 -266
  48. package/src/review/schema.json +196 -196
  49. package/src/review/signals.test.mjs +62 -62
  50. package/src/score-cli.mjs +68 -68
  51. package/src/score.mjs +568 -568
  52. package/src/score.test.mjs +366 -366
  53. package/src/session-reminder.mjs +207 -207
  54. package/src/session-status.mjs +70 -70
  55. package/src/set-models.mjs +186 -186
  56. package/src/set-phase.mjs +205 -205
  57. package/src/set-prefs.mjs +294 -294
  58. package/src/specs-sync.mjs +232 -0
  59. package/src/specs-sync.test.mjs +114 -0
  60. package/src/spine.mjs +93 -93
  61. package/src/triage-prompt.mjs +175 -175
  62. package/src/triage-prompt.test.mjs +50 -50
  63. package/src/vendor-openspec-overlays.mjs +176 -176
  64. package/src/vendor-openspec-overlays.test.mjs +62 -62
  65. package/vendor/skills/archive-to-adr/SKILL.md +149 -149
  66. package/vendor/skills/forge/SKILL.md +136 -136
  67. package/vendor/skills/forge/docs/forge.md +650 -647
  68. package/vendor/skills/forge/phases/brainstorm.md +23 -23
  69. package/vendor/skills/forge/phases/finish.md +90 -87
  70. package/vendor/skills/forge/phases/implement.md +77 -77
  71. package/vendor/skills/forge/phases/plan-openspec.md +60 -60
  72. package/vendor/skills/forge/phases/plan-specs.md +163 -117
  73. package/vendor/skills/forge/phases/review.md +25 -25
  74. package/vendor/skills/forge/phases/verify.md +124 -124
  75. package/vendor/skills/forge/references/forge-layout.md +85 -85
  76. package/vendor/skills/forge/references/pace.md +115 -115
  77. package/vendor/skills/forge/references/plan-routing.md +52 -51
  78. package/vendor/skills/forge/references/runtime-integrity.md +232 -232
  79. package/vendor/skills/forge/references/substantial-work.md +37 -37
  80. package/vendor/skills/forge/references/test-evidence.md +30 -30
  81. package/vendor/skills/forge/references/test-strategy.md +68 -68
  82. package/vendor/skills/forge/skills/subagent-driven-development/SKILL.md +87 -87
  83. package/vendor/skills/forge/subagents/final-reviewer-prompt.md +56 -56
  84. package/vendor/skills/forge/subagents/implementer-prompt.md +38 -38
  85. package/vendor/skills/git-resolve-adr-conflict/SKILL.md +132 -132
  86. package/vendor/skills/thorough-code-review/SKILL.md +290 -290
  87. package/vendor/skills/thorough-code-review/examples.md +133 -133
  88. package/vendor/skills/thorough-code-review/reference/accepted-risks.md +26 -26
  89. package/vendor/skills/thorough-code-review/reference/lenses.md +96 -96
  90. package/vendor/skills/thorough-code-review/reference/phase1-scout.md +62 -62
  91. package/vendor/skills/thorough-code-review/reference/phase2-skeptic.md +105 -105
  92. package/vendor/skills/thorough-code-review/reference/report-schema.json +222 -222
  93. package/vendor/skills/thorough-code-review/reference/report-template.md +115 -115
  94. package/vendor/skills/thorough-code-review/reference/severity-rubric.md +49 -49
  95. package/vendor/skills/thorough-code-review/reference/signals-preflight.md +55 -55
  96. package/vendor/templates/adr/README.md +7 -7
  97. package/vendor/templates/adr/decisions.md +141 -141
  98. package/vendor/templates/adr/hooks/check-pending-adrs.mjs +74 -74
  99. package/vendor/templates/adr/hooks/check-pending-adrs.sh +3 -3
  100. package/vendor/templates/adr/hooks/openspec-archive-agent-message.mjs +52 -52
  101. package/vendor/templates/adr/hooks/openspec-archive-agent-message.sh +3 -3
  102. package/vendor/templates/project/claude/commands/forge-apply.md +75 -75
  103. package/vendor/templates/project/claude/commands/forge-brainstorm.md +7 -7
  104. package/vendor/templates/project/claude/commands/forge-build.md +17 -17
  105. package/vendor/templates/project/claude/commands/forge-plan.md +12 -12
  106. package/vendor/templates/project/claude/commands/forge-skip.md +14 -14
  107. package/vendor/templates/project/claude/commands/forge-status.md +16 -16
  108. package/vendor/templates/project/claude/commands/forge.md +16 -16
  109. package/vendor/templates/project/claude/hooks/forge-prompt-hook.mjs +73 -73
  110. package/vendor/templates/project/claude/hooks/forge-session-start.mjs +19 -19
  111. package/vendor/templates/project/claude/hooks/forge-triage-hook.mjs +77 -77
  112. package/vendor/templates/project/cursor/commands/forge-apply.md +75 -75
  113. package/vendor/templates/project/cursor/commands/forge-brainstorm.md +10 -10
  114. package/vendor/templates/project/cursor/commands/forge-build.md +17 -17
  115. package/vendor/templates/project/cursor/commands/forge-plan.md +15 -15
  116. package/vendor/templates/project/cursor/commands/forge-skip.md +14 -14
  117. package/vendor/templates/project/cursor/commands/forge-status.md +16 -16
  118. package/vendor/templates/project/cursor/commands/forge.md +16 -16
  119. package/vendor/templates/project/cursor/hooks/forge-session-start.mjs +30 -30
  120. package/vendor/templates/project/cursor/hooks/forge-session-start.sh +3 -3
@@ -1,232 +1,232 @@
1
- # Runtime integrity (hard rules)
2
-
3
- Forge verifies **outcomes of the system**, not only artifacts of work. These
4
- rules apply at every pace. Coordinators, implementers, and reviewers must not
5
- weaken them in briefs.
6
-
7
- ## 1. No stubs / no false success
8
-
9
- A handler that only logs, bumps progress, or marks a job/request `succeeded`
10
- without doing the domain work is **forbidden**.
11
-
12
- - If a job kind (or API path) is enqueueable / callable in production, it MUST
13
- run real domain logic, **or** fail closed with a clear error, **or** not be
14
- exposed at all.
15
- - Never authorize “stub OK”, “minimal poll loop only”, or “wire later” for a
16
- path this change claims.
17
-
18
- ## 2. Runtime owner required
19
-
20
- A capability requirement is **not** met by a library module alone.
21
-
22
- - For every REQ / capability this change implements, name the **production
23
- caller** (worker job kind, HTTP endpoint, CLI command, scheduled job, …).
24
- - Library-only = incomplete. Add a wiring task before marking the section done.
25
-
26
- ## 3. Tests must fail on a no-op
27
-
28
- Evidence that only asserts ceremony is invalid.
29
-
30
- | Invalid | Valid |
31
- | ------- | ----- |
32
- | Job status became `succeeded` | Fixture upload/run left the expected domain side effects |
33
- | Handler was called | Mongo/files/artifacts match the capability (or structured failure) |
34
- | Queue claim/lease works | Pairing/stats/proposals/exports exist as specified |
35
-
36
- If a test suite would still pass with a no-op handler, it does not prove the
37
- task.
38
-
39
- ## 4. Briefs may not narrow scope
40
-
41
- **Capability specs beat narrow task wording** when they conflict.
42
-
43
- - Coordinator briefs MUST NOT redefine done downward (e.g. authorize a stub
44
- when the spec requires real ETL).
45
- - To shrink scope: stop and ask the user. Do not silently checkbox around gaps.
46
- - Prefer `DONE_WITH_CONCERNS` / incomplete tasks over green checkboxes.
47
-
48
- ## 5. E2E means an executed product loop, not prose
49
-
50
- Before claiming the change complete:
51
-
52
- 1. Author the **closed product loop** as executable steps in `e2e.json`
53
- (`forge e2e init`), run it against the live entry points
54
- (`forge e2e run`), and get a **green run** — **or**
55
- 2. Leave an explicit **`BLOCKED`** list in `verify-evidence.md` — and do **not**
56
- mark the change complete / advance to `done`.
57
-
58
- **A single job slice is not platform E2E.** When the design has a
59
- producer/consumer split (analyze vs execute, proposals vs ratify, write vs
60
- read), the required E2E is the full loop:
61
-
62
- ```
63
- produce artifact → consumer reads it → decision/state change →
64
- next run's OUTPUT DIFFERS from the baseline
65
- ```
66
-
67
- Example: ingest→Parquet plus a thin run→`.sav` does **not** verify a
68
- governance loop; analyze→proposals→ratify→run-applies-decisions does.
69
-
70
- The mechanical gate requires a green, **current** `e2e-results.json` (its
71
- steps hash must match `e2e.json`) whenever the spine has real rows.
72
- Describing the loop in `verify-evidence.md` no longer satisfies the gate —
73
- prose cannot prove wiring. Each step is `{ name, cmd, expect?, timeoutMs? }`:
74
- exit code 0 required, `expect` (regex) matched against the output. Steps must
75
- assert **domain side effects** — a step list that would pass against a
76
- stubbed handler is invalid (rule 3 applies to e2e steps too).
77
-
78
- `e2e.json` may set `"notApplicable": "<reason>"` only when the loop cannot be
79
- driven by any command (e.g. requires a physical device). Reviewers police the
80
- reason; "no time" or "covered by unit tests" is a REJECT. Keep a short loop
81
- narrative under `## Product loop` in `verify-evidence.md` as reviewer context.
82
-
83
- **Project-level off switch (operator only).** `forge e2e disable "<reason>"`
84
- records `e2e.disabled` in `.forge/config.json` and the gate stops demanding
85
- executed runs project-wide (`forge e2e enable` restores it). This is the
86
- **human's** trade-off to make — an agent must NEVER run `forge e2e disable`,
87
- suggest it to dodge a red gate, or edit the config key. If the gate blocks
88
- you, fix the loop or ask the operator. When it is disabled, keep the
89
- `## Product loop` narrative in `verify-evidence.md` — with no executed run,
90
- prose is the only loop evidence the scorecard can grade.
91
-
92
- ### Keeping the loop cheap (cost policy)
93
-
94
- "Too complex to test" is usually a signal to test it, not to wave it through —
95
- a loop is complex exactly when the feature has many wiring seams, which is
96
- when wiring silently breaks. Never skip the loop for complexity; control its
97
- cost instead:
98
-
99
- - **Ask before building complex harness infrastructure — and only then.**
100
- The ask-line is infrastructure: a rig built from scratch, new
101
- servers/containers/services, third-party accounts or sandboxes (e.g. real
102
- payment checkout), device farms. That is a project, not a test — stop and
103
- ask the user. **Everything below that line never needs permission**: if a
104
- harness already exists (test server, isolated ports, scratch DB), author
105
- the loop; writing fixtures, seed data, helper scripts, or extra steps
106
- inside the existing rig is normal test work — just do it. Asking for
107
- fixture-level work is over-asking; skipping the loop because the rig is
108
- missing is under-testing — the ask is exactly the moment the operator can
109
- say "build it once" and make every future loop on the project cheap.
110
- - **A built harness is permanent project infrastructure — record it, reuse
111
- it.** When the operator approves building one: build it as committed
112
- project code (never session scratch), then record it:
113
-
114
- ```bash
115
- forge e2e harness --set "<what it is / where>" --start "<start command>" [--dir <path>]
116
- ```
117
-
118
- This lands in `.forge/config.json` (committed), and every later session
119
- sees it — `forge e2e init` and `forge e2e status` print the recorded
120
- harness. Check `forge e2e harness` before proposing to build or asking the
121
- operator; proposing a new rig while one is recorded is a REJECT.
122
- - **One executed loop per capability, not per assertion.** Push edge cases
123
- into unit tests; e2e proves the wiring exists.
124
- - **Set `timeoutMs` from the step count up front.** A 10-step loop is never a
125
- 30s test — a too-small budget fails at whatever line the clock runs out on,
126
- which reads as a phantom regression.
127
- - **Run it once, at the end, serially** — never alongside unit suites; load
128
- makes real assertions look flaky.
129
- - **Prefer a production/preview build over the dev server** when the loop
130
- drives a web app — compile-on-demand and dev-mode socket noise dominate the
131
- per-run cost and bury the actual assertion.
132
-
133
- ## 6. Job-kind closure
134
-
135
- Every job kind / entry point on the product surface (enums, API, UI) is, before
136
- the change can be complete, exactly one of:
137
-
138
- - **Wired end-to-end** (enqueueable + handled + domain side effects), or
139
- - **Deleted** from the enums / API / UI surface.
140
-
141
- “Fail closed for unsupported kind” is only a **temporary BLOCKED state**, never
142
- “change complete.” Schema fiction (kinds nobody handles or enqueues) is a
143
- verify failure.
144
-
145
- ## 7. Consumer–producer rule
146
-
147
- If a UI page, API response, or downstream job **reads** a collection, artifact,
148
- or field, verify must prove something in the **production path writes it**
149
- (fixture evidence), or the change is BLOCKED. Empty-forever queues that only
150
- tests can fill are a REJECT.
151
-
152
- ## 8. Deferrals are tracked debt, never checkboxes
153
-
154
- “Wiring in a later task/section” is only acceptable when registered:
155
-
156
- ```bash
157
- forge defer add --task <id> --reason "wiring lands in task <id>"
158
- forge defer resolve --task <id> # when the wiring task actually lands
159
- ```
160
-
161
- - Reviewers may only accept a deferral that names a **registered, still-open**
162
- task (`forge defer list`).
163
- - `forge phase done|finish` **refuses** while any deferral is unresolved.
164
- - An unregistered "later" in a brief or review is a REJECT.
165
-
166
- **Prose caveats don't survive — checkboxes and deferrals do.** Never tick a
167
- `tasks.md` box while a note says the work is unproven ("gate was never taken",
168
- "not yet verified", "should work"). Scorers, gates, and future sessions see
169
- the `[x]`, not the sentence above it. If a task is incomplete in any way, the
170
- box **stays open** or the gap becomes a `forge defer` entry — a ticked box
171
- documenting its own incompleteness is worse than an open one.
172
-
173
- ## Spine matrix (mechanical — `forge spine`)
174
-
175
- **Spine is mandatory for every Forge change** — not gated on pace, and not
176
- inferred from slug keywords (that miss is how hollow platforms shipped).
177
-
178
- At plan time (every change):
179
-
180
- ```bash
181
- forge spine init
182
- ```
183
-
184
- Then either:
185
-
186
- 1. **Fill rows** — one per capability/REQ cluster:
187
-
188
- | capability | library | runtimeOwner | writes | reads | uiConsumer | evidence |
189
-
190
- Every cell filled (`reads` / `uiConsumer` may be `"N/A"`); `evidence` points
191
- at the tier-2/E2E proof of the **wired** path. Library-only rows fail
192
- `forge spine check` — and `forge phase done` runs the same check.
193
-
194
- 2. **Or** set `"notApplicable": "<reason>"` for sync-only / docs-only work
195
- (e.g. `"sync HTTP only — no async producer/consumer"`). That is the honest
196
- opt-out; missing `spine.json` is not.
197
-
198
- An executed product loop (`forge e2e run`, green + current results) is
199
- required when the spine has real rows. Prefer `notApplicable` for sync-only
200
- changes instead of inventing a fake loop.
201
-
202
- ## Reviewer REJECT checklist (mandatory)
203
-
204
- REJECT the task (or final review → `NOT READY`) if any of:
205
-
206
- - Success path has no domain side effects required by the capability
207
- - Tests would pass with a no-op handler
208
- - API / UI can enqueue or trigger a kind the runtime cannot truly execute
209
- - UI / consumers depend on data nothing in the production path writes
210
- - Spec requirement has a library but no named runtime owner
211
- - Deferred wiring without a registered open deferral (`forge defer list`)
212
- - Spine row for this capability missing or library-only
213
- - E2E steps would pass against a stubbed handler (no domain side-effect
214
- assertions), or `e2e.json` opts out via `notApplicable` without a real reason
215
-
216
- ## Plan seam (every change)
217
-
218
- Before apply-ready:
219
-
220
- 1. `forge spine init` — **always**. Fill rows for each capability, or set
221
- `notApplicable` with a reason (sync-only / docs-only).
222
- 2. When the spine has real rows, `forge e2e init` — the acceptance **steps are
223
- a plan deliverable**: author (or task out) the `e2e.json` step list that
224
- drives the loop and asserts its side effects.
225
- 3. If the change involves workers, job queues, handlers, or cross-runtime
226
- calls, `tasks.md` MUST also include:
227
- - Explicit **wiring** tasks per job kind / entry point → domain pipeline
228
- - One **product-loop acceptance** task (last implement task, before
229
- verify) — its output is a green `forge e2e run`
230
-
231
- Missing spine = plan not ready. Keyword guesses about “jobs in scope” are not
232
- an excuse to skip the spine.
1
+ # Runtime integrity (hard rules)
2
+
3
+ Forge verifies **outcomes of the system**, not only artifacts of work. These
4
+ rules apply at every pace. Coordinators, implementers, and reviewers must not
5
+ weaken them in briefs.
6
+
7
+ ## 1. No stubs / no false success
8
+
9
+ A handler that only logs, bumps progress, or marks a job/request `succeeded`
10
+ without doing the domain work is **forbidden**.
11
+
12
+ - If a job kind (or API path) is enqueueable / callable in production, it MUST
13
+ run real domain logic, **or** fail closed with a clear error, **or** not be
14
+ exposed at all.
15
+ - Never authorize “stub OK”, “minimal poll loop only”, or “wire later” for a
16
+ path this change claims.
17
+
18
+ ## 2. Runtime owner required
19
+
20
+ A capability requirement is **not** met by a library module alone.
21
+
22
+ - For every REQ / capability this change implements, name the **production
23
+ caller** (worker job kind, HTTP endpoint, CLI command, scheduled job, …).
24
+ - Library-only = incomplete. Add a wiring task before marking the section done.
25
+
26
+ ## 3. Tests must fail on a no-op
27
+
28
+ Evidence that only asserts ceremony is invalid.
29
+
30
+ | Invalid | Valid |
31
+ | ------- | ----- |
32
+ | Job status became `succeeded` | Fixture upload/run left the expected domain side effects |
33
+ | Handler was called | Mongo/files/artifacts match the capability (or structured failure) |
34
+ | Queue claim/lease works | Pairing/stats/proposals/exports exist as specified |
35
+
36
+ If a test suite would still pass with a no-op handler, it does not prove the
37
+ task.
38
+
39
+ ## 4. Briefs may not narrow scope
40
+
41
+ **Capability specs beat narrow task wording** when they conflict.
42
+
43
+ - Coordinator briefs MUST NOT redefine done downward (e.g. authorize a stub
44
+ when the spec requires real ETL).
45
+ - To shrink scope: stop and ask the user. Do not silently checkbox around gaps.
46
+ - Prefer `DONE_WITH_CONCERNS` / incomplete tasks over green checkboxes.
47
+
48
+ ## 5. E2E means an executed product loop, not prose
49
+
50
+ Before claiming the change complete:
51
+
52
+ 1. Author the **closed product loop** as executable steps in `e2e.json`
53
+ (`forge e2e init`), run it against the live entry points
54
+ (`forge e2e run`), and get a **green run** — **or**
55
+ 2. Leave an explicit **`BLOCKED`** list in `verify-evidence.md` — and do **not**
56
+ mark the change complete / advance to `done`.
57
+
58
+ **A single job slice is not platform E2E.** When the design has a
59
+ producer/consumer split (analyze vs execute, proposals vs ratify, write vs
60
+ read), the required E2E is the full loop:
61
+
62
+ ```
63
+ produce artifact → consumer reads it → decision/state change →
64
+ next run's OUTPUT DIFFERS from the baseline
65
+ ```
66
+
67
+ Example: ingest→Parquet plus a thin run→`.sav` does **not** verify a
68
+ governance loop; analyze→proposals→ratify→run-applies-decisions does.
69
+
70
+ The mechanical gate requires a green, **current** `e2e-results.json` (its
71
+ steps hash must match `e2e.json`) whenever the spine has real rows.
72
+ Describing the loop in `verify-evidence.md` no longer satisfies the gate —
73
+ prose cannot prove wiring. Each step is `{ name, cmd, expect?, timeoutMs? }`:
74
+ exit code 0 required, `expect` (regex) matched against the output. Steps must
75
+ assert **domain side effects** — a step list that would pass against a
76
+ stubbed handler is invalid (rule 3 applies to e2e steps too).
77
+
78
+ `e2e.json` may set `"notApplicable": "<reason>"` only when the loop cannot be
79
+ driven by any command (e.g. requires a physical device). Reviewers police the
80
+ reason; "no time" or "covered by unit tests" is a REJECT. Keep a short loop
81
+ narrative under `## Product loop` in `verify-evidence.md` as reviewer context.
82
+
83
+ **Project-level off switch (operator only).** `forge e2e disable "<reason>"`
84
+ records `e2e.disabled` in `.forge/config.json` and the gate stops demanding
85
+ executed runs project-wide (`forge e2e enable` restores it). This is the
86
+ **human's** trade-off to make — an agent must NEVER run `forge e2e disable`,
87
+ suggest it to dodge a red gate, or edit the config key. If the gate blocks
88
+ you, fix the loop or ask the operator. When it is disabled, keep the
89
+ `## Product loop` narrative in `verify-evidence.md` — with no executed run,
90
+ prose is the only loop evidence the scorecard can grade.
91
+
92
+ ### Keeping the loop cheap (cost policy)
93
+
94
+ "Too complex to test" is usually a signal to test it, not to wave it through —
95
+ a loop is complex exactly when the feature has many wiring seams, which is
96
+ when wiring silently breaks. Never skip the loop for complexity; control its
97
+ cost instead:
98
+
99
+ - **Ask before building complex harness infrastructure — and only then.**
100
+ The ask-line is infrastructure: a rig built from scratch, new
101
+ servers/containers/services, third-party accounts or sandboxes (e.g. real
102
+ payment checkout), device farms. That is a project, not a test — stop and
103
+ ask the user. **Everything below that line never needs permission**: if a
104
+ harness already exists (test server, isolated ports, scratch DB), author
105
+ the loop; writing fixtures, seed data, helper scripts, or extra steps
106
+ inside the existing rig is normal test work — just do it. Asking for
107
+ fixture-level work is over-asking; skipping the loop because the rig is
108
+ missing is under-testing — the ask is exactly the moment the operator can
109
+ say "build it once" and make every future loop on the project cheap.
110
+ - **A built harness is permanent project infrastructure — record it, reuse
111
+ it.** When the operator approves building one: build it as committed
112
+ project code (never session scratch), then record it:
113
+
114
+ ```bash
115
+ forge e2e harness --set "<what it is / where>" --start "<start command>" [--dir <path>]
116
+ ```
117
+
118
+ This lands in `.forge/config.json` (committed), and every later session
119
+ sees it — `forge e2e init` and `forge e2e status` print the recorded
120
+ harness. Check `forge e2e harness` before proposing to build or asking the
121
+ operator; proposing a new rig while one is recorded is a REJECT.
122
+ - **One executed loop per capability, not per assertion.** Push edge cases
123
+ into unit tests; e2e proves the wiring exists.
124
+ - **Set `timeoutMs` from the step count up front.** A 10-step loop is never a
125
+ 30s test — a too-small budget fails at whatever line the clock runs out on,
126
+ which reads as a phantom regression.
127
+ - **Run it once, at the end, serially** — never alongside unit suites; load
128
+ makes real assertions look flaky.
129
+ - **Prefer a production/preview build over the dev server** when the loop
130
+ drives a web app — compile-on-demand and dev-mode socket noise dominate the
131
+ per-run cost and bury the actual assertion.
132
+
133
+ ## 6. Job-kind closure
134
+
135
+ Every job kind / entry point on the product surface (enums, API, UI) is, before
136
+ the change can be complete, exactly one of:
137
+
138
+ - **Wired end-to-end** (enqueueable + handled + domain side effects), or
139
+ - **Deleted** from the enums / API / UI surface.
140
+
141
+ “Fail closed for unsupported kind” is only a **temporary BLOCKED state**, never
142
+ “change complete.” Schema fiction (kinds nobody handles or enqueues) is a
143
+ verify failure.
144
+
145
+ ## 7. Consumer–producer rule
146
+
147
+ If a UI page, API response, or downstream job **reads** a collection, artifact,
148
+ or field, verify must prove something in the **production path writes it**
149
+ (fixture evidence), or the change is BLOCKED. Empty-forever queues that only
150
+ tests can fill are a REJECT.
151
+
152
+ ## 8. Deferrals are tracked debt, never checkboxes
153
+
154
+ “Wiring in a later task/section” is only acceptable when registered:
155
+
156
+ ```bash
157
+ forge defer add --task <id> --reason "wiring lands in task <id>"
158
+ forge defer resolve --task <id> # when the wiring task actually lands
159
+ ```
160
+
161
+ - Reviewers may only accept a deferral that names a **registered, still-open**
162
+ task (`forge defer list`).
163
+ - `forge phase done|finish` **refuses** while any deferral is unresolved.
164
+ - An unregistered "later" in a brief or review is a REJECT.
165
+
166
+ **Prose caveats don't survive — checkboxes and deferrals do.** Never tick a
167
+ `tasks.md` box while a note says the work is unproven ("gate was never taken",
168
+ "not yet verified", "should work"). Scorers, gates, and future sessions see
169
+ the `[x]`, not the sentence above it. If a task is incomplete in any way, the
170
+ box **stays open** or the gap becomes a `forge defer` entry — a ticked box
171
+ documenting its own incompleteness is worse than an open one.
172
+
173
+ ## Spine matrix (mechanical — `forge spine`)
174
+
175
+ **Spine is mandatory for every Forge change** — not gated on pace, and not
176
+ inferred from slug keywords (that miss is how hollow platforms shipped).
177
+
178
+ At plan time (every change):
179
+
180
+ ```bash
181
+ forge spine init
182
+ ```
183
+
184
+ Then either:
185
+
186
+ 1. **Fill rows** — one per capability/REQ cluster:
187
+
188
+ | capability | library | runtimeOwner | writes | reads | uiConsumer | evidence |
189
+
190
+ Every cell filled (`reads` / `uiConsumer` may be `"N/A"`); `evidence` points
191
+ at the tier-2/E2E proof of the **wired** path. Library-only rows fail
192
+ `forge spine check` — and `forge phase done` runs the same check.
193
+
194
+ 2. **Or** set `"notApplicable": "<reason>"` for sync-only / docs-only work
195
+ (e.g. `"sync HTTP only — no async producer/consumer"`). That is the honest
196
+ opt-out; missing `spine.json` is not.
197
+
198
+ An executed product loop (`forge e2e run`, green + current results) is
199
+ required when the spine has real rows. Prefer `notApplicable` for sync-only
200
+ changes instead of inventing a fake loop.
201
+
202
+ ## Reviewer REJECT checklist (mandatory)
203
+
204
+ REJECT the task (or final review → `NOT READY`) if any of:
205
+
206
+ - Success path has no domain side effects required by the capability
207
+ - Tests would pass with a no-op handler
208
+ - API / UI can enqueue or trigger a kind the runtime cannot truly execute
209
+ - UI / consumers depend on data nothing in the production path writes
210
+ - Spec requirement has a library but no named runtime owner
211
+ - Deferred wiring without a registered open deferral (`forge defer list`)
212
+ - Spine row for this capability missing or library-only
213
+ - E2E steps would pass against a stubbed handler (no domain side-effect
214
+ assertions), or `e2e.json` opts out via `notApplicable` without a real reason
215
+
216
+ ## Plan seam (every change)
217
+
218
+ Before apply-ready:
219
+
220
+ 1. `forge spine init` — **always**. Fill rows for each capability, or set
221
+ `notApplicable` with a reason (sync-only / docs-only).
222
+ 2. When the spine has real rows, `forge e2e init` — the acceptance **steps are
223
+ a plan deliverable**: author (or task out) the `e2e.json` step list that
224
+ drives the loop and asserts its side effects.
225
+ 3. If the change involves workers, job queues, handlers, or cross-runtime
226
+ calls, `tasks.md` MUST also include:
227
+ - Explicit **wiring** tasks per job kind / entry point → domain pipeline
228
+ - One **product-loop acceptance** task (last implement task, before
229
+ verify) — its output is a green `forge e2e run`
230
+
231
+ Missing spine = plan not ready. Keyword guesses about “jobs in scope” are not
232
+ an excuse to skip the spine.
@@ -1,37 +1,37 @@
1
- # Substantial work triage
2
-
3
- Run this check **before** implementation on every agent turn unless the user
4
- sent **`/forge:skip`**.
5
-
6
- **Forge = OpenSpec.** If work is substantial enough for Forge, it is substantial enough for a
7
- tracked OpenSpec change. Smaller work skips Forge entirely (direct execution).
8
-
9
- ## Enter Forge when ANY apply
10
-
11
- - New feature or behavior change
12
- - Bug fix that changes logic (not typo-only)
13
- - Multi-file or multi-workspace edit
14
- - Public API, Zod schema, OpenAPI, shared package export, or config schema change
15
- - Cross-package / cross-product impact (grep consumers)
16
- - User invokes `/forge` or any `/forge:*` command (except `/forge:skip`)
17
- - Work would likely produce an ADR or new `openspec/specs/` capability
18
-
19
- ## Skip Forge (execute directly) when ALL apply
20
-
21
- - Pure question, explanation, or read-only review
22
- - Typo, comment, formatting-only, or rename with zero behavior change
23
- - User explicitly sent **`/forge:skip`** for this task
24
-
25
- ## `/forge:skip` behaviour
26
-
27
- 1. If an active Forge session exists, run:
28
- ```bash
29
- forge phase skipped
30
- ```
31
- 2. Do **not** start brainstorm or plan for this task.
32
- 3. Proceed with the user's request under normal project rules.
33
-
34
- ## Ambiguous cases
35
-
36
- Ask one clarifying question: **would this produce an OpenSpec change?** If yes → Forge (OpenSpec).
37
- If no → execute directly. Skip requires explicit user opt-out (`/forge:skip`).
1
+ # Substantial work triage
2
+
3
+ Run this check **before** implementation on every agent turn unless the user
4
+ sent **`/forge:skip`**.
5
+
6
+ **Forge = OpenSpec.** If work is substantial enough for Forge, it is substantial enough for a
7
+ tracked OpenSpec change. Smaller work skips Forge entirely (direct execution).
8
+
9
+ ## Enter Forge when ANY apply
10
+
11
+ - New feature or behavior change
12
+ - Bug fix that changes logic (not typo-only)
13
+ - Multi-file or multi-workspace edit
14
+ - Public API, Zod schema, OpenAPI, shared package export, or config schema change
15
+ - Cross-package / cross-product impact (grep consumers)
16
+ - User invokes `/forge` or any `/forge:*` command (except `/forge:skip`)
17
+ - Work would likely produce an ADR or new `openspec/specs/` capability
18
+
19
+ ## Skip Forge (execute directly) when ALL apply
20
+
21
+ - Pure question, explanation, or read-only review
22
+ - Typo, comment, formatting-only, or rename with zero behavior change
23
+ - User explicitly sent **`/forge:skip`** for this task
24
+
25
+ ## `/forge:skip` behaviour
26
+
27
+ 1. If an active Forge session exists, run:
28
+ ```bash
29
+ forge phase skipped
30
+ ```
31
+ 2. Do **not** start brainstorm or plan for this task.
32
+ 3. Proceed with the user's request under normal project rules.
33
+
34
+ ## Ambiguous cases
35
+
36
+ Ask one clarifying question: **would this produce an OpenSpec change?** If yes → Forge (OpenSpec).
37
+ If no → execute directly. Skip requires explicit user opt-out (`/forge:skip`).
@@ -1,30 +1,30 @@
1
- # Per-task test evidence (tier 2)
2
-
3
- Each implement task records **tier 2** proof that subagents ran tests. See [test-strategy.md](./test-strategy.md) for all three tiers.
4
-
5
- The **coordinator** records this file after the implementer reports — use `forge evidence --task <nn>-<slug> --command "<cmd>" --exit <code> --summary "<text>"` (machine timestamp; refuses non-zero exit without `--allow-fail`) rather than hand-writing it. Verify **audits** these files — it does **not** re-run the same tier 2 commands. Verify runs **tier 3** (full workspace) once separately; see [../phases/verify.md](../phases/verify.md).
6
-
7
- ## Path
8
-
9
- `.forge/sessions/<session-id>/tasks/<nn>-<slug>/test-evidence.md`
10
-
11
- ## Template
12
-
13
- ```markdown
14
- # Test evidence — Task {nn}-{slug}
15
-
16
- - **Tier:** 2 (task-scoped — not full workspace unless noted)
17
- - **Command:** `npm test -- path/to/scoped.test.ts -- src/foo.test.ts`
18
- - **Exit code:** 0
19
- - **Summary:** 3/3 pass (or paste last ~20 lines of output)
20
- - **Run at:** 2026-06-05T15:04:22Z
21
- - **Recorded by:** implementer subagent (coordinator transcript)
22
- ```
23
-
24
- ## Rules
25
-
26
- - **Exit code must be `0`** before the task is marked complete.
27
- - **Default:** narrowest command — changed test file(s) + directly related tests. **Not** the full workspace suite.
28
- - **Full workspace at tier 2** only when the task changes shared contracts, cross-module integration, or the brief explicitly requires it. Note `Tier: 2 (full workspace — contract/integration)` in the file.
29
- - If the implementer re-ran tests after a fix, overwrite with the latest successful tier 2 run.
30
- - Verify **audits** tier 2 files and runs **tier 3** (full workspace) once — see [test-strategy.md](./test-strategy.md).
1
+ # Per-task test evidence (tier 2)
2
+
3
+ Each implement task records **tier 2** proof that subagents ran tests. See [test-strategy.md](./test-strategy.md) for all three tiers.
4
+
5
+ The **coordinator** records this file after the implementer reports — use `forge evidence --task <nn>-<slug> --command "<cmd>" --exit <code> --summary "<text>"` (machine timestamp; refuses non-zero exit without `--allow-fail`) rather than hand-writing it. Verify **audits** these files — it does **not** re-run the same tier 2 commands. Verify runs **tier 3** (full workspace) once separately; see [../phases/verify.md](../phases/verify.md).
6
+
7
+ ## Path
8
+
9
+ `.forge/sessions/<session-id>/tasks/<nn>-<slug>/test-evidence.md`
10
+
11
+ ## Template
12
+
13
+ ```markdown
14
+ # Test evidence — Task {nn}-{slug}
15
+
16
+ - **Tier:** 2 (task-scoped — not full workspace unless noted)
17
+ - **Command:** `npm test -- path/to/scoped.test.ts -- src/foo.test.ts`
18
+ - **Exit code:** 0
19
+ - **Summary:** 3/3 pass (or paste last ~20 lines of output)
20
+ - **Run at:** 2026-06-05T15:04:22Z
21
+ - **Recorded by:** implementer subagent (coordinator transcript)
22
+ ```
23
+
24
+ ## Rules
25
+
26
+ - **Exit code must be `0`** before the task is marked complete.
27
+ - **Default:** narrowest command — changed test file(s) + directly related tests. **Not** the full workspace suite.
28
+ - **Full workspace at tier 2** only when the task changes shared contracts, cross-module integration, or the brief explicitly requires it. Note `Tier: 2 (full workspace — contract/integration)` in the file.
29
+ - If the implementer re-ran tests after a fix, overwrite with the latest successful tier 2 run.
30
+ - Verify **audits** tier 2 files and runs **tier 3** (full workspace) once — see [test-strategy.md](./test-strategy.md).