@warpgogol/forge 5.3.3 → 6.0.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 (282) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/bin/cli.ts +7 -2
  3. package/dist/bin/cli.js +7 -2
  4. package/dist/bin/cli.js.map +1 -1
  5. package/dist/os/adr/adr.module.d.ts.map +1 -1
  6. package/dist/os/adr/adr.module.js +2 -0
  7. package/dist/os/adr/adr.module.js.map +1 -1
  8. package/dist/os/audit/audit.module.d.ts.map +1 -1
  9. package/dist/os/audit/audit.module.js +2 -0
  10. package/dist/os/audit/audit.module.js.map +1 -1
  11. package/dist/os/compass/compass.module.d.ts.map +1 -1
  12. package/dist/os/compass/compass.module.js +48 -16
  13. package/dist/os/compass/compass.module.js.map +1 -1
  14. package/dist/os/compass/handlers/compass-audit-handler.d.ts +2 -0
  15. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  16. package/dist/os/compass/handlers/compass-audit-handler.js +39 -9
  17. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  18. package/dist/os/compass/handlers/compass-docs-validate.d.ts +13 -0
  19. package/dist/os/compass/handlers/compass-docs-validate.d.ts.map +1 -0
  20. package/dist/os/compass/handlers/compass-docs-validate.js +326 -0
  21. package/dist/os/compass/handlers/compass-docs-validate.js.map +1 -0
  22. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  23. package/dist/os/compass/handlers/compass-inventory.js +5 -2
  24. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  25. package/dist/os/compass/handlers/summary-record.d.ts +17 -3
  26. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
  27. package/dist/os/compass/handlers/summary-record.js +107 -10
  28. package/dist/os/compass/handlers/summary-record.js.map +1 -1
  29. package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts +18 -0
  30. package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts.map +1 -0
  31. package/dist/os/compass/handlers/tests/forge-yaml-fixture.js +64 -0
  32. package/dist/os/compass/handlers/tests/forge-yaml-fixture.js.map +1 -0
  33. package/dist/os/compass/policy.d.ts +6 -1
  34. package/dist/os/compass/policy.d.ts.map +1 -1
  35. package/dist/os/compass/policy.js +8 -2
  36. package/dist/os/compass/policy.js.map +1 -1
  37. package/dist/os/core/core.module.d.ts.map +1 -1
  38. package/dist/os/core/core.module.js +124 -73
  39. package/dist/os/core/core.module.js.map +1 -1
  40. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  41. package/dist/os/exploration/exploration.module.js +3 -0
  42. package/dist/os/exploration/exploration.module.js.map +1 -1
  43. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  44. package/dist/os/mission/handlers/archive.js +1 -2
  45. package/dist/os/mission/handlers/archive.js.map +1 -1
  46. package/dist/os/naming/naming.module.d.ts.map +1 -1
  47. package/dist/os/naming/naming.module.js +9 -2
  48. package/dist/os/naming/naming.module.js.map +1 -1
  49. package/dist/os/notes/notes.module.d.ts.map +1 -1
  50. package/dist/os/notes/notes.module.js +17 -6
  51. package/dist/os/notes/notes.module.js.map +1 -1
  52. package/dist/os/plan/plan.module.d.ts.map +1 -1
  53. package/dist/os/plan/plan.module.js +2 -0
  54. package/dist/os/plan/plan.module.js.map +1 -1
  55. package/dist/os/plugin/plugin.module.d.ts.map +1 -1
  56. package/dist/os/plugin/plugin.module.js +9 -2
  57. package/dist/os/plugin/plugin.module.js.map +1 -1
  58. package/dist/os/program/program.module.d.ts.map +1 -1
  59. package/dist/os/program/program.module.js +19 -4
  60. package/dist/os/program/program.module.js.map +1 -1
  61. package/dist/os/queue/handlers/queue-validate.d.ts.map +1 -1
  62. package/dist/os/queue/handlers/queue-validate.js +154 -7
  63. package/dist/os/queue/handlers/queue-validate.js.map +1 -1
  64. package/dist/os/queue/manifest.d.ts +17 -1
  65. package/dist/os/queue/manifest.d.ts.map +1 -1
  66. package/dist/os/queue/manifest.js +127 -6
  67. package/dist/os/queue/manifest.js.map +1 -1
  68. package/dist/os/queue/queue.module.d.ts.map +1 -1
  69. package/dist/os/queue/queue.module.js +32 -4
  70. package/dist/os/queue/queue.module.js.map +1 -1
  71. package/dist/os/queue/types.d.ts +100 -1
  72. package/dist/os/queue/types.d.ts.map +1 -1
  73. package/dist/os/queue/types.js +44 -0
  74. package/dist/os/queue/types.js.map +1 -1
  75. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  76. package/dist/os/rfc/handlers/implement-stamp.js +28 -5
  77. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  78. package/dist/os/rfc/handlers/validate.js +1 -1
  79. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  80. package/dist/os/rfc/rfc.module.js +27 -3
  81. package/dist/os/rfc/rfc.module.js.map +1 -1
  82. package/dist/os/rfc/types.d.ts +11 -0
  83. package/dist/os/rfc/types.d.ts.map +1 -1
  84. package/dist/os/rfc/types.js +1 -0
  85. package/dist/os/rfc/types.js.map +1 -1
  86. package/dist/os/rfc/verification-evidence.d.ts +21 -0
  87. package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
  88. package/dist/os/rfc/verification-evidence.js +140 -23
  89. package/dist/os/rfc/verification-evidence.js.map +1 -1
  90. package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
  91. package/dist/os/rfc/verification-refresh.js +72 -37
  92. package/dist/os/rfc/verification-refresh.js.map +1 -1
  93. package/dist/os/session/handlers/save.d.ts.map +1 -1
  94. package/dist/os/session/handlers/save.js +46 -5
  95. package/dist/os/session/handlers/save.js.map +1 -1
  96. package/dist/os/session/session.module.d.ts.map +1 -1
  97. package/dist/os/session/session.module.js +5 -0
  98. package/dist/os/session/session.module.js.map +1 -1
  99. package/dist/os/spec/live-spec-merge.d.ts.map +1 -1
  100. package/dist/os/spec/live-spec-merge.js +55 -134
  101. package/dist/os/spec/live-spec-merge.js.map +1 -1
  102. package/dist/os/spec/live-spec-rebuild.d.ts +32 -0
  103. package/dist/os/spec/live-spec-rebuild.d.ts.map +1 -0
  104. package/dist/os/spec/live-spec-rebuild.js +272 -0
  105. package/dist/os/spec/live-spec-rebuild.js.map +1 -0
  106. package/dist/os/spec/live-spec-shared.d.ts +62 -0
  107. package/dist/os/spec/live-spec-shared.d.ts.map +1 -0
  108. package/dist/os/spec/live-spec-shared.js +315 -0
  109. package/dist/os/spec/live-spec-shared.js.map +1 -0
  110. package/dist/os/spec/live-spec-types.d.ts +17 -1
  111. package/dist/os/spec/live-spec-types.d.ts.map +1 -1
  112. package/dist/os/spec/live-spec-types.js +3 -0
  113. package/dist/os/spec/live-spec-types.js.map +1 -1
  114. package/dist/os/spec/live-spec-validate.d.ts.map +1 -1
  115. package/dist/os/spec/live-spec-validate.js +105 -2
  116. package/dist/os/spec/live-spec-validate.js.map +1 -1
  117. package/dist/os/spec/spec-materialize.d.ts +2 -0
  118. package/dist/os/spec/spec-materialize.d.ts.map +1 -1
  119. package/dist/os/spec/spec-materialize.js +45 -5
  120. package/dist/os/spec/spec-materialize.js.map +1 -1
  121. package/dist/os/spec/spec-schema.d.ts +19 -0
  122. package/dist/os/spec/spec-schema.d.ts.map +1 -1
  123. package/dist/os/spec/spec-schema.js +30 -0
  124. package/dist/os/spec/spec-schema.js.map +1 -1
  125. package/dist/os/spec/spec-status.d.ts +4 -0
  126. package/dist/os/spec/spec-status.d.ts.map +1 -1
  127. package/dist/os/spec/spec-status.js +19 -1
  128. package/dist/os/spec/spec-status.js.map +1 -1
  129. package/dist/os/spec/spec-validate.d.ts.map +1 -1
  130. package/dist/os/spec/spec-validate.js +55 -8
  131. package/dist/os/spec/spec-validate.js.map +1 -1
  132. package/dist/os/spec/spec.module.d.ts.map +1 -1
  133. package/dist/os/spec/spec.module.js +84 -8
  134. package/dist/os/spec/spec.module.js.map +1 -1
  135. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
  136. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +10 -4
  137. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
  138. package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
  139. package/dist/os/werkstatt/werkstatt.module.js +13 -4
  140. package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
  141. package/dist/os/workflow/workflow.module.d.ts.map +1 -1
  142. package/dist/os/workflow/workflow.module.js +13 -5
  143. package/dist/os/workflow/workflow.module.js.map +1 -1
  144. package/dist/src/cli-flags.d.ts.map +1 -1
  145. package/dist/src/cli-flags.js +25 -5
  146. package/dist/src/cli-flags.js.map +1 -1
  147. package/dist/src/config/forge-config.d.ts +24 -3
  148. package/dist/src/config/forge-config.d.ts.map +1 -1
  149. package/dist/src/config/forge-config.js +38 -7
  150. package/dist/src/config/forge-config.js.map +1 -1
  151. package/dist/src/onboarding/create.d.ts.map +1 -1
  152. package/dist/src/onboarding/create.js +26 -10
  153. package/dist/src/onboarding/create.js.map +1 -1
  154. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  155. package/dist/src/onboarding/doctor.js +49 -2
  156. package/dist/src/onboarding/doctor.js.map +1 -1
  157. package/dist/src/onboarding/init.d.ts.map +1 -1
  158. package/dist/src/onboarding/init.js +8 -3
  159. package/dist/src/onboarding/init.js.map +1 -1
  160. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  161. package/dist/src/onboarding/upgrade.js +24 -8
  162. package/dist/src/onboarding/upgrade.js.map +1 -1
  163. package/dist/src/pipeline-status.d.ts +14 -1
  164. package/dist/src/pipeline-status.d.ts.map +1 -1
  165. package/dist/src/pipeline-status.js +28 -8
  166. package/dist/src/pipeline-status.js.map +1 -1
  167. package/dist/src/types.d.ts +7 -1
  168. package/dist/src/types.d.ts.map +1 -1
  169. package/dist/src/types.js +6 -0
  170. package/dist/src/types.js.map +1 -1
  171. package/dist/src/utils/generated-marker.d.ts +8 -0
  172. package/dist/src/utils/generated-marker.d.ts.map +1 -1
  173. package/dist/src/utils/generated-marker.js +25 -0
  174. package/dist/src/utils/generated-marker.js.map +1 -1
  175. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  176. package/dist/src/validators/skill-validate.js +42 -15
  177. package/dist/src/validators/skill-validate.js.map +1 -1
  178. package/os/adr/adr.module.ts +2 -0
  179. package/os/audit/audit.module.ts +2 -0
  180. package/os/compass/compass.module.ts +50 -16
  181. package/os/compass/handlers/compass-audit-handler.ts +50 -9
  182. package/os/compass/handlers/compass-docs-validate.ts +359 -0
  183. package/os/compass/handlers/compass-inventory.ts +6 -3
  184. package/os/compass/handlers/summary-record.ts +118 -10
  185. package/os/compass/handlers/tests/compass-audit-record.test.ts +2 -1
  186. package/os/compass/handlers/tests/compass-audit-validate.test.ts +92 -3
  187. package/os/compass/handlers/tests/compass-docs-validate.test.ts +203 -0
  188. package/os/compass/handlers/tests/compass-ledger-scope.test.ts +2 -1
  189. package/os/compass/handlers/tests/compass-policy.test.ts +15 -18
  190. package/os/compass/handlers/tests/compass-v2-contract.test.ts +38 -0
  191. package/os/compass/handlers/tests/forge-yaml-fixture.ts +69 -0
  192. package/os/compass/handlers/tests/summary-record.test.ts +152 -0
  193. package/os/compass/policy.ts +8 -2
  194. package/os/core/core.module.ts +147 -75
  195. package/os/core/docs-archive.test.ts +136 -0
  196. package/os/exploration/exploration.module.ts +3 -0
  197. package/os/mission/handlers/archive.ts +1 -2
  198. package/os/naming/naming.module.ts +9 -2
  199. package/os/notes/notes.module.ts +17 -6
  200. package/os/plan/plan-0000-template.md +150 -0
  201. package/os/plan/plan.module.ts +2 -0
  202. package/os/plugin/plugin.module.ts +9 -2
  203. package/os/program/program.module.ts +19 -4
  204. package/os/queue/decision-ledger.test.ts +163 -0
  205. package/os/queue/handlers/queue-validate.ts +190 -8
  206. package/os/queue/manifest.ts +201 -7
  207. package/os/queue/queue-validate.test.ts +303 -0
  208. package/os/queue/queue.module.ts +32 -4
  209. package/os/queue/types.ts +56 -1
  210. package/os/rfc/handlers/implement-stamp.ts +35 -5
  211. package/os/rfc/handlers/validate.ts +1 -1
  212. package/os/rfc/rfc.module.ts +29 -3
  213. package/os/rfc/types.ts +17 -1
  214. package/os/rfc/verification-emit.test.ts +305 -0
  215. package/os/rfc/verification-evidence.ts +155 -24
  216. package/os/rfc/verification-refresh.test.ts +222 -1
  217. package/os/rfc/verification-refresh.ts +80 -38
  218. package/os/session/handlers/save.ts +41 -5
  219. package/os/session/session.module.ts +5 -0
  220. package/os/spec/live-spec-idempotency.pbt.test.ts +222 -0
  221. package/os/spec/live-spec-list-show-validate.test.ts +10 -6
  222. package/os/spec/live-spec-merge.test.ts +187 -7
  223. package/os/spec/live-spec-merge.ts +71 -155
  224. package/os/spec/live-spec-rebuild.test.ts +317 -0
  225. package/os/spec/live-spec-rebuild.ts +356 -0
  226. package/os/spec/live-spec-shared.ts +378 -0
  227. package/os/spec/live-spec-types.ts +21 -1
  228. package/os/spec/live-spec-validate.test.ts +317 -0
  229. package/os/spec/live-spec-validate.ts +106 -2
  230. package/os/spec/spec-materialize.test.ts +192 -0
  231. package/os/spec/spec-materialize.ts +48 -4
  232. package/os/spec/spec-schema.ts +49 -0
  233. package/os/spec/spec-status.ts +24 -0
  234. package/os/spec/spec-validate.test.ts +66 -0
  235. package/os/spec/spec-validate.ts +62 -8
  236. package/os/spec/spec.module.ts +85 -8
  237. package/os/werkstatt/handlers/werkstatt-operation-validate.ts +10 -4
  238. package/os/werkstatt/werkstatt.module.ts +13 -4
  239. package/os/workflow/workflow.module.ts +13 -5
  240. package/package.json +1 -1
  241. package/skills/_shared/fo-pipeline-conventions.md +126 -1
  242. package/skills/fo/fo-compass-annotate/SKILL.md +1 -1
  243. package/skills/fo/fo-doc-audit/SKILL.md +4 -4
  244. package/skills/fo/fo-explore/SKILL.md +2 -1
  245. package/skills/fo/fo-fix/SKILL.md +11 -3
  246. package/skills/fo/fo-handoff/SKILL.md +6 -8
  247. package/skills/fo/fo-idea-audit/SKILL.md +1 -1
  248. package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -2
  249. package/skills/fo/fo-idea-enhance/SKILL.md +23 -4
  250. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +86 -22
  251. package/skills/fo/fo-idea-implement/SKILL.md +57 -13
  252. package/skills/fo/fo-idea-plan/SKILL.md +28 -6
  253. package/skills/fo/fo-review/SKILL.md +69 -8
  254. package/skills/fo/fo-session-retro/SKILL.md +4 -3
  255. package/skills/fo/fo-session-save/SKILL.md +1 -1
  256. package/skills/fo/fo-step-commit/SKILL.md +2 -0
  257. package/skills/shared/grilling/SKILL.md +12 -0
  258. package/skills/shared/writing-great-skills/GLOSSARY.md +2 -0
  259. package/skills/shared/writing-great-skills/SKILL.md +2 -1
  260. package/src/cli-flags.ts +23 -5
  261. package/src/config/forge-config.ts +106 -57
  262. package/src/onboarding/create.ts +25 -9
  263. package/src/onboarding/doctor.ts +51 -2
  264. package/src/onboarding/init.ts +8 -3
  265. package/src/onboarding/upgrade.ts +36 -6
  266. package/src/pipeline-status.ts +32 -8
  267. package/src/tests/bindings-schema.test.ts +53 -1
  268. package/src/tests/cli-flags.test.ts +20 -0
  269. package/src/tests/cli-output.test.ts +13 -7
  270. package/src/tests/doctor-bindings.test.ts +7 -2
  271. package/src/tests/doctor-skills-unmanaged.test.ts +145 -0
  272. package/src/tests/fixtures/agents-generate-business-before.txt +7 -7
  273. package/src/tests/forge-config.test.ts +106 -2
  274. package/src/tests/implement-stamp.test.ts +38 -0
  275. package/src/tests/session-handlers.test.ts +33 -0
  276. package/src/tests/skill-validate.test.ts +180 -0
  277. package/src/tests/upgrade.test.ts +60 -0
  278. package/src/types.ts +13 -1
  279. package/src/utils/generated-marker.ts +28 -0
  280. package/src/validators/skill-validate.ts +43 -16
  281. package/skills/fo/fo-idea-implement/ADR-FLOW.md +0 -179
  282. package/skills/fo/fo-review/AXES.md +0 -70
@@ -20,9 +20,25 @@ triggerPhrases: ["plan the implementation for this RFC", "create implementation
20
20
  </non-goals>
21
21
  </MODULE_CONTRACT>
22
22
  <CHANGE_SUMMARY>
23
+ <item>RFC-1250: collect-mode contract — open questions and grilling emit to
24
+ the decision ledger; draft plan carries PENDING DECISION markers;
25
+ draft-to-accepted transition deferred to the resolution phase (window =
26
+ acceptance act).</item>
23
27
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
24
28
 
25
29
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
30
+ <item>RFC-1250: review wave — QUEUE-07 gates un-parked opens only, ledger binding checks, fail-closed loader
31
+
32
+ REVIEW-RFC-1250-01 findings: QUEUE-07 no longer fires on parked entries
33
+ (the park is the containment — a parked queue stays resumable and the
34
+ decision window arbitrates it); loader fails open only on ENOENT —
35
+ other read errors are QUEUE-01; ledger gains queue/id-stem binding
36
+ (QUEUE-02), Q-N uniqueness (QUEUE-05), and QUEUE-08 hygiene warnings
37
+ (missing answers, foreign doc ids); next excludes QUEUE-07-blocked
38
+ items; top-level decision totals added. Orchestrator pre-flight treats
39
+ QUEUE-07 as the window agenda — structural errors still stop the batch;
40
+ maturation skips parked/deferred items; uncovered imperative ask sites
41
+ gain collect riders (ADR code-trace, NC markers, audit-verdict guard).</item>
26
42
  </CHANGE_SUMMARY>
27
43
  -->
28
44
 
@@ -71,7 +87,11 @@ If all checks pass, proceed to step 0.3.
71
87
 
72
88
  #### 0.3. Transition draft → accepted
73
89
 
74
- If the RFC is `draft` or `reviewing` and has `enhancedAt` — the user's instruction to plan IS the architecture acceptance. Transition the RFC to `accepted`:
90
+ If the RFC is `draft` or `reviewing` and has `enhancedAt` — the user's instruction to plan IS the architecture acceptance. Transition the RFC to `accepted`.
91
+
92
+ **Collect mode exception:** inside an orchestrator-driven queue run the `draft → accepted` transition moves to the resolution phase — the answered decision window IS the acceptance act. In collect mode this skill persists the plan as a draft carrying `PENDING DECISION` markers and does NOT transition the RFC; the orchestrator's resolution phase finalizes (integrate answers, lift markers, transition + commit) after the window.
93
+
94
+ Standalone/interview-mode flow:
75
95
 
76
96
  1. Set `status: accepted`.
77
97
  2. Set `reviewers` — if the operator specified a reviewer at invocation, use that. Otherwise, read the default reviewer(s) from the `reviewers` field comment in `docs/rfcs/rfc-0000-template.md`. Set all listed default reviewers.
@@ -93,7 +113,7 @@ Then proceed to step 1.
93
113
  **Inherited acceptance.** If the RFC has a `specRef` frontmatter field pointing to a spec with `status: accepted`, the acceptance inheritance path applies:
94
114
 
95
115
  1. Check the audit report for this RFC — if the audit verdict is `approved`, the RFC MAY transition `draft → accepted` without a separate human acceptance ceremony. Record `reviewers` from the spec's `reviewers` field and note `via spec acceptance <spec-id>` in the commit message.
96
- 2. If the audit verdict is `needs-revision` or `rejected`, inheritance is void — a human decision is required. Do not transition; ask the operator.
116
+ 2. If the audit verdict is `needs-revision` or `rejected`, inheritance is void — a human decision is required. Do not transition; ask the operator. **Collect mode:** instead of asking, append an `open` ledger entry (`stage: plan`) recording the audit verdict and the inheritance question, leave a `> PENDING DECISION: Q-N` marker in the draft plan, and do not transition — the window arbitrates whether the RFC proceeds or returns to enhance.
97
117
  3. If the `specRef` points to a spec with `status: vendored` (not yet accepted), the RFC cannot progress past `draft` — V-SPEC-03 blocks it.
98
118
 
99
119
  ### 1. Read the RFC
@@ -125,13 +145,15 @@ Verify the RFC's claims about affected artifacts. Check:
125
145
 
126
146
  After exploring, identify decisions the RFC leaves open — ambiguities, trade-offs, unspecified boundaries, conflicting constraints. These are **decisions**, not facts: if a fact can be found by exploring the codebase, look it up instead of asking.
127
147
 
128
- Walk the user through each question **one at a time**. For each:
148
+ **Collect mode:** under an orchestrated run, never call `ask_user_question` — climb the self-resolution ladder (`_shared/fo-pipeline-conventions.md` §Self-resolution ladder); genuine trade-offs append to the queue's decision ledger as `open` entries (`stage: plan`) with recommended options, and `> PENDING DECISION: Q-N` markers land in the draft plan at the steps that depend on the answer.
149
+
150
+ Interview mode: walk the user through each question **one at a time**. For each:
129
151
 
130
152
  1. **Short context** — what the question is, why the plan needs it resolved, what changes depending on the answer.
131
153
  2. **Options** — list 2-4 concrete options, **recommended option first**. Mark it with "(recommended)". Each option is a short label plus one line explaining the trade-off.
132
154
  3. **Wait** — present the question and stop. Do not batch multiple questions; asking several at once is bewildering.
133
155
 
134
- Use the `ask_user_question` tool when available, with the recommended option as the first entry. Otherwise, present the question inline and wait for the answer.
156
+ Use the `ask_user_question` tool when available (interview mode only), with the recommended option as the first entry. Otherwise, present the question inline and wait for the answer.
135
157
 
136
158
  Typical questions that arise:
137
159
 
@@ -146,7 +168,7 @@ If exploration surfaces no open questions, skip this step and proceed directly t
146
168
 
147
169
  ### 4. Draft the plan
148
170
 
149
- Copy `docs/plans/plan-0000-template.md` and fill it, incorporating the user's answers from step 3. Each step must have a **completion criterion** — a checkable condition that tells the agent the step is done.
171
+ Copy `docs/plans/plan-0000-template.md` and fill it, incorporating the user's answers from step 3. Each step must have a **completion criterion** — a checkable condition that tells the agent the step is done. Keep the template's `## Falsified routes` ledger section — implementing skills append to it when an approach is abandoned after a real attempt (see `_shared/fo-pipeline-conventions.md` §Falsified-routes ledger).
150
172
 
151
173
  Step ordering follows the contract-first pattern:
152
174
 
@@ -168,7 +190,7 @@ Mark **human review points** on steps that:
168
190
 
169
191
  ### 5. Grill the plan
170
192
 
171
- Invoke the `/grilling` skill to stress-test the draft plan before persisting. This is **mandatory**, not optional — every plan goes through grilling.
193
+ Invoke the `/grilling` skill to stress-test the draft plan before persisting. This is **mandatory**, not optional — every plan goes through grilling. **Collect mode:** grilling runs in `emit` mode — questions land in the ledger (`stage: plan`) with recommended answers; no interview.
172
194
 
173
195
  The grilling checks:
174
196
 
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
9
9
  bindings:
10
10
  requires: [commands.validateRfc]
11
11
  optional: [paths.invariantsFile, paths.compassDocs]
12
- triggerPhrases: ["review this code diff", "check code against Forge standards", "fitness check on code changes"]
12
+ triggerPhrases: ["проверим всё ли сделали правильно", "проверь изменения", "review this session", "review this code diff", "check code against Forge standards"]
13
13
  ---
14
14
 
15
15
  <!--
@@ -20,9 +20,24 @@ triggerPhrases: ["review this code diff", "check code against Forge standards",
20
20
  </non-goals>
21
21
  </MODULE_CONTRACT>
22
22
  <CHANGE_SUMMARY>
23
+ <item>RFC-1250: soft-block arbitration appends to the queue decision ledger
24
+ (open / stage: review) under orchestrated runs.</item>
23
25
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
24
26
 
25
27
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
28
+ <item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
29
+ <item>RFC-1250: review wave — QUEUE-07 gates un-parked opens only, ledger binding checks, fail-closed loader
30
+
31
+ REVIEW-RFC-1250-01 findings: QUEUE-07 no longer fires on parked entries
32
+ (the park is the containment — a parked queue stays resumable and the
33
+ decision window arbitrates it); loader fails open only on ENOENT —
34
+ other read errors are QUEUE-01; ledger gains queue/id-stem binding
35
+ (QUEUE-02), Q-N uniqueness (QUEUE-05), and QUEUE-08 hygiene warnings
36
+ (missing answers, foreign doc ids); next excludes QUEUE-07-blocked
37
+ items; top-level decision totals added. Orchestrator pre-flight treats
38
+ QUEUE-07 as the window agenda — structural errors still stop the batch;
39
+ maturation skips parked/deferred items; uncovered imperative ask sites
40
+ gain collect riders (ADR code-trace, NC markers, audit-verdict guard).</item>
26
41
  </CHANGE_SUMMARY>
27
42
  -->
28
43
 
@@ -41,6 +56,25 @@ This skill reviews **code** — `.ts`, `.js`, `.tsx`, `.astro`, `.css`, `.json`,
41
56
  - For **RFCs, ADRs, architecture docs, or plans**, use `/fo-idea-audit` instead.
42
57
  - For **iterative fix-then-build-then-commit**, use `/fo-fix`.
43
58
 
59
+ ## Review modes: `inline` vs `independent`
60
+
61
+ `fo-review` accepts an `independent` flag. **Default: `true` when invoked from a pipeline orchestrator (`fo-idea-i-just-want-to-see-the-result`, `fo-idea-implement`), `false` for ad-hoc in-session review.**
62
+
63
+ In `independent` mode the reviewing pass executes in a **clean agent context** — a subagent dispatch where the platform provides one — carrying only artifacts:
64
+
65
+ - the diff range or file list to review;
66
+ - the rubric paths (this skill file, `_shared/fo-pipeline-conventions.md`);
67
+ - the anchor paths (AGENTS.md files, DNA invariants file, relevant specs);
68
+ - raw evidence (command output, failing logs, mechanical floor results).
69
+
70
+ **Never pass the executor's session narrative, self-assessment, or settled conclusions** — passing them defeats the isolation the mode exists for (veil-of-ignorance contract, shared with the falsified-routes blind-spot pass). The dispatched reviewer's prompt contains artifact paths and the rubric, not the executor's story.
71
+
72
+ Where the platform exposes no subagent primitive (or policy forbids dispatch), run an `isolated-inline` pass instead: re-derive conclusions only from the artifacts, deliberately ignoring the session's accumulated narrative, and record the fallback. **Never claim `subagent` isolation that did not happen** — the persisted report's `reviewer.isolation` field records the mode actually used (`subagent` | `isolated-inline` | `inline`), so independence is auditable rather than asserted.
73
+
74
+ An executor that narrows the reviewer's inputs — passing a self-authored summary instead of artifact paths — commits a scope-narrowing violation, itself reportable as a `soft-block` on the review process.
75
+
76
+ **Report persistence is the dispatcher's duty in `independent` mode.** A clean-context reviewer may be read-only and never writes files — it returns findings and verdict. The skill run that dispatched it performs steps 6–7 itself: it assembles the report, builds the YAML frontmatter (`reviewer.isolation` records the mode actually used), and writes the file to `docs/reviews/code/`. A persisted review report without the frontmatter block is a contract violation regardless of which side produced the prose.
77
+
44
78
  ## Process
45
79
 
46
80
  ### 1. Identify the diff
@@ -99,7 +133,7 @@ Read the context the diff claims to fit into:
99
133
 
100
134
  Do not read every file in the repo — only the standards relevant to the diff.
101
135
 
102
- ### 4. Run the seven review axes
136
+ ### 4. Run the eight review axes
103
137
 
104
138
  For each axis, check every item. An item either **passes**, **fails** (specific finding with evidence), or is **not applicable** (state why). Skip N/A items silently — do not pad the report.
105
139
 
@@ -177,6 +211,15 @@ If the invariants file is absent or the optional binding is unresolvable, state
177
211
  - **Migration path**: existing apps' path to compliance is documented.
178
212
  - **Security / privacy**: if the diff touches user data, PII, or external services, it addresses GDPR/privacy and secret management. No cookies (`document.cookie`, `Set-Cookie`). Client-side persistence is `localStorage` only; server-side is `unstorage`.
179
213
 
214
+ #### Axis H — Fracture inference
215
+
216
+ Will this output collapse at the next step? Judge the diff not only for what it is, but for whether the _process that produced it_ is honest:
217
+
218
+ - **Goal-closure authenticity** — claims of completion vs. verifiable evidence. A marked-done criterion whose checkable trace is absent or hand-waved is a fracture signal.
219
+ - **Ordering-constraint compliance** — skipped preconditions: plan steps executed out of order, dependencies implemented after their dependents, gates bypassed to reach a green run.
220
+ - **Unclosed-marking truthfulness** — deferred or open items actually declared as such; nothing silently dropped from the plan, todo list, or spec.
221
+ - **State-transmission completeness** — would a fresh agent recover this work without the conversation? Checkpoints, persisted reports, and committed artifacts carry the state — not session memory.
222
+
180
223
  ### 5. Check spec compliance
181
224
 
182
225
  If an original request, spec, PRD, issue, or brief is available (from commit messages, linked issues, or session context), build a gap table:
@@ -199,7 +242,7 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
199
242
  ```
200
243
  ## <Code Review in aiLanguage>: <diff range or file list>
201
244
 
202
- ### Verdict: <Approved | Needs revision | Rejected>
245
+ ### Verdict: <Approved | Needs revision | Rejected> (blockLevel: <pass | warning | soft-block | hard-block>)
203
246
 
204
247
  <2-3 sentence justification grounded in the most serious findings.>
205
248
 
@@ -228,6 +271,9 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
228
271
  ### Axis G — Blind spots
229
272
  <Findings or "No issues.">
230
273
 
274
+ ### Axis H — Fracture inference
275
+ <Findings or "No issues.">
276
+
231
277
  ### Spec compliance
232
278
 
233
279
  <Gap table or "No spec available — skipped.">
@@ -239,11 +285,22 @@ Present the findings in this structure in `aiLanguage`. **Translate all labels,
239
285
  3. <Hard question.>
240
286
  ```
241
287
 
242
- **Verdict criteria:**
288
+ **Verdict criteria (blocking model):**
289
+
290
+ Every verdict carries a `blockLevel` — the blocking semantics downstream pipeline skills act on. `verdict` is retained and **derived** from it for backward compatibility (`fo-fix` consumes `verdict` unchanged):
291
+
292
+ | `blockLevel` | `verdict` | Semantics |
293
+ | --- | --- | --- |
294
+ | `pass` | `approved` | Zero findings across all axes — no fracture signals |
295
+ | `warning` | `needs-revision` | Findings recorded as tracked observations; they must be answered, and unresolved warnings at T3 escalate to `soft-block` |
296
+ | `soft-block` | `needs-revision` + `escalation: operator` | Directional deviation or process violation — suspends the item for operator arbitration (queue mode: item parked, arbitration question appended to the decision ledger as `open`/`stage: review`/`parked: true`, batch continues) |
297
+ | `hard-block` | `rejected` | Fundamental flaw — fix, then **full** re-review (not a delta on the flagged point) before the item may proceed to stamping |
298
+
299
+ - **Approved (`pass`)** — zero findings across all eight axes. Any finding, no matter how minor or cosmetic, disqualifies Approved and forces Needs revision. The rationale: downstream agents treat Approved as a stop signal and stop reading the findings — so even a trivial finding left under Approved gets silently ignored. If there is anything to fix, the verdict must say so.
300
+ - **Needs revision (`warning` | `soft-block`)** — one or more findings on any axis, regardless of severity. A one-line cosmetic rename is enough (`warning`). Escalate to `soft-block` when the deviation is directional or the review process itself was compromised (e.g. narrowed inputs). The agent must not downgrade to Approved based on severity — a finding is a finding.
301
+ - **Rejected (`hard-block`)** — fundamental flaw: the diff contradicts a DNA invariant, introduces a backward compatibility layer, or bypasses the storage policy.
243
302
 
244
- - **Approved** — zero findings across all seven axes. Any finding, no matter how minor or cosmetic, disqualifies Approved and forces Needs revision. The rationale: downstream agents treat Approved as a stop signal and stop reading the findings — so even a trivial finding left under Approved gets silently ignored. If there is anything to fix, the verdict must say so.
245
- - **Needs revision** — one or more findings on any axis, regardless of severity. A one-line cosmetic rename is enough. The agent must not downgrade to Approved based on severity — a finding is a finding.
246
- - **Rejected** — fundamental flaw: the diff contradicts a DNA invariant, introduces a backward compatibility layer, or bypasses the storage policy.
303
+ The `blockLevel` → pipeline semantics (full re-review on `hard-block`, queue parking on `soft-block`, warning escalation at T3) are declared in `_shared/fo-pipeline-conventions.md` §Review blocking semantics.
247
304
 
248
305
  ### 7. Persist the review
249
306
 
@@ -265,8 +322,12 @@ reviewId: REVIEW-CODE-<YYYY-MM-DD>-<NN>
265
322
  date: YYYY-MM-DD
266
323
  reviewer:
267
324
  skill: fo-review
325
+ isolation: <subagent | isolated-inline | inline> # the isolation mode actually used
268
326
  model: <AI model identifier>
269
- verdict: <approved | needs-revision | rejected>
327
+ blockLevel: <pass | warning | soft-block | hard-block> # blocking semantics
328
+ verdict: <approved | needs-revision | rejected> # derived from blockLevel
329
+ escalation: <none | operator> # set when blockLevel = soft-block
330
+ observations: [] # tracked warnings carried to T3
270
331
  diffRange: <fixed-point>...HEAD
271
332
  filesReviewed:
272
333
  - <file path>
@@ -9,7 +9,7 @@ languagePolicy: ref(PREFERENCES.md)
9
9
  bindings:
10
10
  requires: []
11
11
  optional: [paths.invariantsFile]
12
- triggerPhrases: ["session retrospective", "triage session discoveries", "Завершаем эту сессию", "End session", "/session-end"]
12
+ triggerPhrases: ["завершаем", "протокол завершения", "Завершаем эту сессию", "session retrospective", "End session"]
13
13
  ---
14
14
 
15
15
  <!--
@@ -23,6 +23,7 @@ triggerPhrases: ["session retrospective", "triage session discoveries", "Зав
23
23
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
24
24
 
25
25
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
26
+ <item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
26
27
  </CHANGE_SUMMARY>
27
28
  -->
28
29
 
@@ -85,7 +86,7 @@ The agent reconstructs the current session's conversation from its context windo
85
86
  3. Reconstruct the conversation from context — include every user message and assistant response you can recall from the current session, in chronological order. This is a best-effort reconstruction: the agent's context window is the source, not an external export tool.
86
87
  4. **Redact sensitive information** — remove API keys, passwords, PII, and secret values before writing. Replace with `<redacted>`.
87
88
  5. **Truncate very long tool outputs** — if a tool call produced thousands of lines of output, summarize it as `<tool output truncated, N lines>` in the content field. Keep the tool call name and key results.
88
- 6. Write the file using `write_to_file` to `docs/sessions/.raw/<timestamp>-session.atif`.
89
+ 6. Write the file **atomically**: `write_to_file` to `docs/sessions/.raw/<timestamp>-session.atif.tmp`, then `mv` it to the same path without `.tmp` (rename is atomic). A parallel agent's `session.save` claims any `.atif` the moment it appears — this ordering guarantees it never sees a half-written transcript.
89
90
 
90
91
  ### 0c. Run session.save
91
92
 
@@ -450,7 +451,7 @@ If any operator insights were routed to `.agents/operator-profile.md`, offer the
450
451
 
451
452
  Present a concise summary in `aiLanguage`. **ALL labels, headings, column names, and prose MUST be translated to `aiLanguage`** — the template below is structural only. Only identifiers (file paths, skill names, RFC/ADR ids, commit hashes) stay untranslated. This is non-negotiable: an English summary when `aiLanguage` is `ru` is a violation of this skill's language contract.
452
453
 
453
- **Engineering Checkpoint (RFC-0884):** The closing block follows the Engineering Checkpoint protocol defined in `_shared/fo-session-summary.md`. The agent MUST:
454
+ **Engineering Checkpoint:** The closing block follows the Engineering Checkpoint protocol defined in `_shared/fo-session-summary.md`. The agent MUST:
454
455
 
455
456
  1. **Select mode** — analyze the session's changes. If the session changed architecture, runtime flow, state machines, persistence models, or public contracts, use **full mode** (6 sections). Otherwise, use **lightweight mode** (3 sections).
456
457
  2. **Diagram selection** (full mode only) — apply the diagram selection rules table from `_shared/fo-session-summary.md` to determine if a Mermaid diagram is warranted. If no structural change warrants a diagram, explicitly state "No diagram: this session did not change system structure..."
@@ -60,7 +60,7 @@ Enhance saved session transcripts with semantic annotations, summaries, and qual
60
60
 
61
61
  6. **Update the session file:**
62
62
  - Update frontmatter: `summary`, `decisions`, refined `types`, corrected metadata.
63
- - **Checkpoint fields (RFC-0884):** When the session produced substantial engineering work, populate the optional checkpoint frontmatter fields:
63
+ - **Checkpoint fields:** When the session produced substantial engineering work, populate the optional checkpoint frontmatter fields:
64
64
  - `checkpoint` — object with `before`, `change`, `after` (each 1-2 sentences describing state N, what was done, state N+1)
65
65
  - `systemDelta` — object with arrays: `changedContracts`, `changedSchemas`, `changedStateMachines`, `changedInvariants`, `changedPersistence`
66
66
  - `diagrams` — array of objects: `type` (flowchart/sequenceDiagram/stateDiagram-v2/erDiagram/none), `scope` (current-system/session-delta), `caption`, `mermaid` (Mermaid syntax or empty string)
@@ -10,6 +10,7 @@ concerns: code-mutation
10
10
  dependsOn: ['my-preferences']
11
11
  languagePolicy: ref(PREFERENCES.md)
12
12
  triggerPhrases:
13
+ - "закоммитим"
13
14
  - "commit after request"
14
15
  - "auto-commit changes"
15
16
  - "step commit"
@@ -26,6 +27,7 @@ triggerPhrases:
26
27
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
27
28
 
28
29
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
30
+ <item>RFC-1247: triggerPhrases vocabulary sync — mined operator phrasing applied to this skill's trigger set.</item>
29
31
  </CHANGE_SUMMARY>
30
32
  -->
31
33
 
@@ -22,11 +22,23 @@ knowledge:
22
22
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
23
23
 
24
24
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
25
+ <item>RFC-1250: two modes — interview (standalone, interactive) and emit
26
+ (orchestrated runs: questions land in the queue decision ledger with
27
+ recommended answers, no interview).</item>
25
28
  </CHANGE_SUMMARY>
26
29
  -->
27
30
 
28
31
  Before starting, read `PREFERENCES.md` at the repository root. If the file is missing or `aiLanguage` is unset, ask the operator once and create the file using the `my-preferences` skill semantics.
29
32
 
33
+ ## Modes
34
+
35
+ Grilling runs in one of two modes — the caller selects:
36
+
37
+ - **`interview`** (default — standalone, operator-invoked runs): the interactive behavior below, one question at a time.
38
+ - **`emit`** (inside an orchestrator-driven queue run — `fo-idea-i-just-want-to-see-the-result` queue mode): never ask the operator. Generate the same questions you would have asked, climb the self-resolution ladder (`_shared/fo-pipeline-conventions.md` §Self-resolution ladder), and append each surviving question to the queue's decision ledger `docs/queues/<id>.decisions.yaml` as an `open` entry (`id: Q-N`, `doc`, `stage`, `question`, `resolutionPath`, `options` with `recommended: true` on your recommended answer, `status: open`). Branching questions are written conditionally ("if Q-3 resolves to X, then…"). The pipeline's decision window consumes the emitted entries.
39
+
40
+ Mode trigger: `emit` activates only when the invoking skill passes a queue manifest / ledger path; otherwise `interview`.
41
+
30
42
  Read `learned-principles.md` (L2) at the start of each session to improve recommended answers. Apply only entries with `status: active`; skip entries with `status: stale`, `superseded`, or `archived`. Principles with `confirmations >= 3` may be applied autonomously — but re-evaluate if context changes.
31
43
 
32
44
  Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.
@@ -58,6 +58,8 @@ A **user-invoked** skill whose job is to point at your other user-invoked skills
58
58
 
59
59
  _Avoid_: dispatcher, menu, registry, index, router procedure
60
60
 
61
+ _Applied instance_: `fo-idea-i-just-want-to-see-the-result` is the forge pipeline's router skill — the operator's single front door. Its Preconditions carry an intent-routing table that maps non-pipeline intents (review, fix, session-end, commit, mission work, exploration) to their standing skills before document-id detection; pipeline intents flow through unchanged, and the escape hatches stay directly invocable.
62
+
61
63
  ### Granularity
62
64
 
63
65
  How finely you divide skills. Finer division spends one of the two loads: more **model-invoked** skills spend **context load** (more descriptions crowding the window and competing for attention); more **user-invoked** skills spend **cognitive load** (more for the human to remember and reach for). Two cuts guide the division. By **invocation**, split off a model-invoked skill where you have a distinct **leading word** to trigger it — a trigger word you actually use in your prompts. By **sequence**, split a run of **steps** where a step's **post-completion steps** need hiding, since isolating it in its own context clears what follows. Beware the reverse: merging sequences exposes each step's post-completion steps to what follows, inviting premature completion.
@@ -19,6 +19,7 @@ languagePolicy: ref(PREFERENCES.md)
19
19
  <item>RFC-1097: sweep — SKILL.md headers + classification fixes
20
20
 
21
21
  Sweep batch 1: add Compass v2 headers to 45 SKILL.md files (purpose derived from frontmatter description). Fix non-skill-markdown exclusion to check filename not workspace-relative path (packages/AGENTS.md escaped it). Add .coverage to ignoredDirs.</item>
22
+ <item>RFC-1247: close RFC-1247 review r2 — CHANGE_SUMMARY items on six touched skills, fo-handoff in AGENTS enumeration, glossary applied-instance pointer, recorded per-skill phrase split</item>
22
23
  </CHANGE_SUMMARY>
23
24
  -->
24
25
 
@@ -37,7 +38,7 @@ Two choices, trading different costs:
37
38
 
38
39
  Pick model-invocation only when the agent must reach the skill on its own, or another skill must. If it only ever fires by hand, make it user-invoked and pay no context load.
39
40
 
40
- When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each.
41
+ When user-invoked skills multiply past what you can remember, that piled-up cognitive load is cured by a **router skill**: one user-invoked skill that names the others and when to reach for each. (Applied instance: `fo-idea-i-just-want-to-see-the-result` — see GLOSSARY.md.)
41
42
 
42
43
  ## Writing the description
43
44
 
package/src/cli-flags.ts CHANGED
@@ -12,6 +12,10 @@ with `TypeError: targetId.toLowerCase is not a function`.</purpose>
12
12
  </MODULE_CONTRACT>
13
13
  <CHANGE_SUMMARY>
14
14
  <item>Standalone port of kernel argv resolution for the forge CLI (RFC-0260 lineage): strict KERNEL-FLAG-01/02/03 + KERNEL-ARG-01 diagnostics for schema-carrying commands, legacy heuristic parse (with KERNEL-ARG-01) for schema-less commands; repeated single-value string flags diagnose instead of silently promoting to an array that crashes handlers; indexOf-based inline-value split preserves values containing "=" that split("=", 2) silently truncated.</item>
15
+ <item>Session-retro 2026-10-08: string[] flags greedily consume consecutive
16
+ bare tokens until the next --flag (`--files a b` → ["a","b"]), matching the
17
+ kernel argv parser; bare positionals without a preceding string[] flag still
18
+ emit KERNEL-ARG-01.</item>
15
19
  </CHANGE_SUMMARY>
16
20
  */
17
21
 
@@ -227,11 +231,25 @@ function resolveStrict(
227
231
  continue;
228
232
  }
229
233
 
230
- const next = rawArgv[index + 1];
231
- if (typeof next === "string" && !next.startsWith("--")) {
232
- addFlagValue(flags, flagName, next);
233
- index += 1;
234
- continue;
234
+ // string[] flags consume every following bare token — mirrors the kernel's
235
+ // resolveCommandFlags: positional args are never valid (KERNEL-ARG-01),
236
+ // so `--files a b` unambiguously means the value list [a, b].
237
+ if (spec.kind === "string[]") {
238
+ let consumed = 0;
239
+ while (index + 1 < rawArgv.length && !rawArgv[index + 1]!.startsWith("--")) {
240
+ addFlagValue(flags, flagName, rawArgv[index + 1]!);
241
+ index += 1;
242
+ consumed += 1;
243
+ }
244
+ if (consumed > 0) continue;
245
+ // fall through to the missing-value diagnostic
246
+ } else {
247
+ const next = rawArgv[index + 1];
248
+ if (typeof next === "string" && !next.startsWith("--")) {
249
+ addFlagValue(flags, flagName, next);
250
+ index += 1;
251
+ continue;
252
+ }
235
253
  }
236
254
 
237
255
  diagnostics.push({
@@ -6,7 +6,6 @@
6
6
  </non-goals>
7
7
  </MODULE_CONTRACT>
8
8
  <CHANGE_SUMMARY>
9
- <item>RFC-0661: added optional knowledge.budgets binding for hot/warm layer character budget overrides.</item>
10
9
  <item>RFC-0662: added optional knowledge.retentionDays and knowledge.staleDays bindings for compaction overrides.</item>
11
10
  <item>RFC-0704: added optional independentVersionPackages field to forgeConfigSchema for packages with autonomous npm versions.</item>
12
11
  <item>RFC-1097: step 6 — compass.migrate codemod run
@@ -15,14 +14,15 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
15
14
  <item>RFC-1097: sweep — packages/forge + services clean
16
15
 
17
16
  Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PURPOSE-02), headers on mission/index + gen-upstreams, sanitizeItemText in summary.record (literal Compass tags corrupted history), excludedPaths for wrangler types, test-fixtures testPattern. forge+services now 0 diagnostics under --mode error.</item>
18
- <history>RFC-0391, RFC-0393, RFC-0537, RFC-0538, RFC-0539, RFC-0540, RFC-0543, RFC-0546, RFC-0639, RFC-0640, RFC-0643</history>
17
+ <item>RFC-1224: preserve operator forge.yaml content on upgrade, promote adrImplementStamp binding</item>
18
+ <history>RFC-0391, RFC-0393, RFC-0537, RFC-0538, RFC-0539, RFC-0540, RFC-0543, RFC-0546, RFC-0639, RFC-0640, RFC-0643, RFC-0661, RFC-1224</history>
19
19
  </CHANGE_SUMMARY>
20
20
  */
21
21
 
22
22
  import * as fs from "../utils/sync-fs.ts";
23
23
  import path from "node:path";
24
24
  import { z } from "zod";
25
- import { parse as parseYaml } from "yaml";
25
+ import { parse as parseYaml, parseDocument } from "yaml";
26
26
  import {
27
27
  TERMINOLOGY_DEFAULTS,
28
28
  compassPolicyOverridesSchema,
@@ -36,22 +36,27 @@ import { listStackProfiles, type StackProfile } from "../profiles/stack-profile.
36
36
 
37
37
  export const forgeBindingsSchema = z.object({
38
38
  schema: z.literal("forge/bindings@1"),
39
- commands: z.object({
40
- validateRfc: z.string().nullable().default(null),
41
- validateAdr: z.string().nullable().default(null),
42
- implementStamp: z.string().nullable().default(null),
43
- typecheck: z.string().nullable().default(null),
44
- test: z.string().nullable().default(null),
45
- scopedBuild: z.string().nullable().default(null),
46
- specValidate: z.string().nullable().default(null),
47
- sessionSave: z.string().nullable().default(null),
48
- // Semantic keys (RFC-0639) — domain-neutral, optional
49
- validate: z.string().nullable().default(null),
50
- produce: z.string().nullable().default(null),
51
- verify: z.string().nullable().default(null),
52
- preview: z.string().nullable().default(null),
53
- lint: z.string().nullable().default(null),
54
- }),
39
+ commands: z
40
+ .object({
41
+ validateRfc: z.string().nullable().default(null),
42
+ validateAdr: z.string().nullable().default(null),
43
+ implementStamp: z.string().nullable().default(null),
44
+ adrImplementStamp: z.string().nullable().default(null),
45
+ typecheck: z.string().nullable().default(null),
46
+ test: z.string().nullable().default(null),
47
+ scopedBuild: z.string().nullable().default(null),
48
+ specValidate: z.string().nullable().default(null),
49
+ sessionSave: z.string().nullable().default(null),
50
+ // Semantic keys (RFC-0639) — domain-neutral, optional
51
+ validate: z.string().nullable().default(null),
52
+ produce: z.string().nullable().default(null),
53
+ verify: z.string().nullable().default(null),
54
+ preview: z.string().nullable().default(null),
55
+ lint: z.string().nullable().default(null),
56
+ // RFC-1224: consumer-defined command keys (e.g. createRfc) stay in the
57
+ // parsed config so resolveBinding can resolve them.
58
+ })
59
+ .passthrough(),
55
60
  paths: z.object({
56
61
  invariantsFile: z.string().nullable().default(null),
57
62
  compassDocs: z.array(z.string()).default([]),
@@ -98,6 +103,7 @@ export interface ForgeBindings {
98
103
  validateRfc: string | null;
99
104
  validateAdr: string | null;
100
105
  implementStamp: string | null;
106
+ adrImplementStamp: string | null;
101
107
  typecheck: string | null;
102
108
  test: string | null;
103
109
  scopedBuild: string | null;
@@ -177,44 +183,50 @@ export interface ForgeMigrationAdapter {
177
183
  // Schema (forge/config@1)
178
184
  // ---------------------------------------------------------------------------
179
185
 
180
- export const forgeConfigSchema = z.object({
181
- schema: z.literal("forge/config@1"),
182
- project: z.object({
183
- name: z.string().min(1),
184
- stack: z.array(z.string()).default([]),
185
- packageManager: z.enum(["pnpm", "npm", "yarn", "bun", "none"]).default("pnpm"),
186
- // RFC-0640: optional domain field — absent means software-domain fallback
187
- domain: z.string().optional(),
188
- }),
189
- paths: z.object({
190
- rfcsDir: z.string().default("docs/rfcs"),
191
- adrsDir: z.string().default("docs/adrs"),
192
- plansDir: z.string().default("docs/plans"),
193
- auditsDir: z.string().default("docs/audits"),
194
- specsDir: z.string().default("docs/specs"),
195
- skillsDir: z.string().default(".agents/skills"),
196
- sessionsDir: z.string().default("docs/sessions"),
197
- }),
198
- /** Bindings contract (RFC-0393). Optional — absent means no bindings. */
199
- bindings: forgeBindingsSchema.optional(),
200
- /** Skill packs (RFC-0539). Optional — absent means no project-local packs. */
201
- skillPacks: z.array(forgeSkillPackSchema).optional(),
202
- /** Migration adapters (RFC-0546). Optional — absent means built-in adapters only. */
203
- migrationAdapters: z.array(forgeMigrationAdapterSchema).optional(),
204
- /** Forge sync metadata (RFC-0543). Optional — absent means never synced. */
205
- forge: z
206
- .object({
207
- syncedVersion: z.string().nullable().default(null),
208
- })
209
- .optional(),
210
- /** RFC-0643: profile id — when present, loadForgeConfig loads the corresponding profiles/<id>.yaml */
211
- // RFC-1118: accept the corrupted object form (whole StackProfile written by a
212
- // previous buggy serialize) so loadForgeConfig can recover the declared id —
213
- // a hard schema throw here would deadlock `forge upgrade`, the healing path.
214
- profile: z.union([z.string(), z.object({ id: z.string().min(1) }).passthrough()]).optional(),
215
- /** RFC-0704: packages with autonomous npm versions — ecosystem.commit skips platform bump when all staged files belong to these packages */
216
- independentVersionPackages: z.array(z.string()).optional(),
217
- });
186
+ export const forgeConfigSchema = z
187
+ .object({
188
+ schema: z.literal("forge/config@1"),
189
+ project: z.object({
190
+ name: z.string().min(1),
191
+ stack: z.array(z.string()).default([]),
192
+ packageManager: z.enum(["pnpm", "npm", "yarn", "bun", "none"]).default("pnpm"),
193
+ // RFC-0640: optional domain field — absent means software-domain fallback
194
+ domain: z.string().optional(),
195
+ /** RFC-1240: local consumer identity — absent means no consumer-aware spec filtering. */
196
+ consumer: z.string().optional(),
197
+ }),
198
+ paths: z.object({
199
+ rfcsDir: z.string().default("docs/rfcs"),
200
+ adrsDir: z.string().default("docs/adrs"),
201
+ plansDir: z.string().default("docs/plans"),
202
+ auditsDir: z.string().default("docs/audits"),
203
+ specsDir: z.string().default("docs/specs"),
204
+ skillsDir: z.string().default(".agents/skills"),
205
+ sessionsDir: z.string().default("docs/sessions"),
206
+ }),
207
+ /** Bindings contract (RFC-0393). Optional — absent means no bindings. */
208
+ bindings: forgeBindingsSchema.optional(),
209
+ /** Skill packs (RFC-0539). Optional — absent means no project-local packs. */
210
+ skillPacks: z.array(forgeSkillPackSchema).optional(),
211
+ /** Migration adapters (RFC-0546). Optional — absent means built-in adapters only. */
212
+ migrationAdapters: z.array(forgeMigrationAdapterSchema).optional(),
213
+ /** Forge sync metadata (RFC-0543). Optional — absent means never synced. */
214
+ forge: z
215
+ .object({
216
+ syncedVersion: z.string().nullable().default(null),
217
+ })
218
+ .optional(),
219
+ /** RFC-0643: profile id — when present, loadForgeConfig loads the corresponding profiles/<id>.yaml */
220
+ // RFC-1118: accept the corrupted object form (whole StackProfile written by a
221
+ // previous buggy serialize) so loadForgeConfig can recover the declared id —
222
+ // a hard schema throw here would deadlock `forge upgrade`, the healing path.
223
+ profile: z.union([z.string(), z.object({ id: z.string().min(1) }).passthrough()]).optional(),
224
+ /** RFC-0704: packages with autonomous npm versions — ecosystem.commit skips platform bump when all staged files belong to these packages */
225
+ independentVersionPackages: z.array(z.string()).optional(),
226
+ // RFC-1224: consumer-owned top-level sections (e.g. `plugins:`) stay in the
227
+ // parsed config so full-serialization writes do not silently drop them.
228
+ })
229
+ .passthrough();
218
230
 
219
231
  export interface ForgeConfig {
220
232
  schema: "forge/config@1";
@@ -224,6 +236,8 @@ export interface ForgeConfig {
224
236
  packageManager: "pnpm" | "npm" | "yarn" | "bun" | "none";
225
237
  /** RFC-0640: optional domain field — absent means software-domain fallback */
226
238
  domain?: string;
239
+ /** RFC-1240: local consumer identity — absent means no consumer-aware spec filtering */
240
+ consumer?: string;
227
241
  };
228
242
  paths: {
229
243
  rfcsDir: string;
@@ -268,6 +282,10 @@ export const FORGE_CLI_BINDING_DEFAULTS: ForgeCliBindingDefault[] = [
268
282
  key: "commands.implementStamp",
269
283
  template: "forge rfc.implement.stamp --id {id} --implementation-commit {commit}",
270
284
  },
285
+ {
286
+ key: "commands.adrImplementStamp",
287
+ template: "forge adr.implement.stamp --id {id} --implementation-commit {commit}",
288
+ },
271
289
  { key: "commands.specValidate", template: "forge spec.validate --spec={id} --json" },
272
290
  { key: "commands.sessionSave", template: "forge session.save --json" },
273
291
  ];
@@ -302,6 +320,7 @@ export function applyCliBindingDefaults(pm: string): ForgeBindings["commands"] {
302
320
  validateRfc: null,
303
321
  validateAdr: null,
304
322
  implementStamp: null,
323
+ adrImplementStamp: null,
305
324
  typecheck: null,
306
325
  test: null,
307
326
  scopedBuild: null,
@@ -471,6 +490,36 @@ export function serializeForgeConfig(config: ForgeConfig): Record<string, unknow
471
490
  return out;
472
491
  }
473
492
 
493
+ // ---------------------------------------------------------------------------
494
+ // YAML document patching — RFC-1224
495
+ // ---------------------------------------------------------------------------
496
+
497
+ /**
498
+ * A single targeted write into forge.yaml: a dotted key path expressed as
499
+ * segments plus the value to set. `applyForgeYamlPatches` creates missing
500
+ * intermediate maps and preserves comments/formatting elsewhere in the file.
501
+ */
502
+ export interface ForgeYamlPatch {
503
+ path: string[];
504
+ value: unknown;
505
+ }
506
+
507
+ /**
508
+ * Apply targeted patches to a forge.yaml document without rewriting it.
509
+ * Returns the patched YAML text, or null when the document cannot be parsed —
510
+ * callers should fall back to full serialization in that case.
511
+ */
512
+ export function applyForgeYamlPatches(rawYaml: string, patches: ForgeYamlPatch[]): string | null {
513
+ const doc = parseDocument(rawYaml);
514
+ if (doc.errors.length > 0) {
515
+ return null;
516
+ }
517
+ for (const patch of patches) {
518
+ doc.setIn(patch.path, patch.value);
519
+ }
520
+ return doc.toString();
521
+ }
522
+
474
523
  // ---------------------------------------------------------------------------
475
524
  // Forge root resolver — the single place that decides monorepo vs npm-installed
476
525
  // ---------------------------------------------------------------------------