@warpgogol/forge 5.2.4 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (590) hide show
  1. package/README.md +1 -1
  2. package/README.uk.md +8 -8
  3. package/bin/cli.ts +25 -33
  4. package/dist/bin/cli.js +21 -32
  5. package/dist/bin/cli.js.map +1 -1
  6. package/dist/os/adr/adr.module.d.ts.map +1 -1
  7. package/dist/os/adr/adr.module.js +8 -3
  8. package/dist/os/adr/adr.module.js.map +1 -1
  9. package/dist/os/adr/frontmatter-io.js +5 -5
  10. package/dist/os/adr/frontmatter-io.js.map +1 -1
  11. package/dist/os/adr/handlers/archive.d.ts.map +1 -1
  12. package/dist/os/adr/handlers/archive.js +10 -4
  13. package/dist/os/adr/handlers/archive.js.map +1 -1
  14. package/dist/os/adr/handlers/implement-stamp.d.ts.map +1 -1
  15. package/dist/os/adr/handlers/implement-stamp.js +10 -10
  16. package/dist/os/adr/handlers/implement-stamp.js.map +1 -1
  17. package/dist/os/adr/handlers/list-create.js +5 -5
  18. package/dist/os/adr/handlers/list-create.js.map +1 -1
  19. package/dist/os/adr/handlers/validate.js +1 -1
  20. package/dist/os/adr/handlers/validate.js.map +1 -1
  21. package/dist/os/audit/audit.module.js +3 -3
  22. package/dist/os/audit/audit.module.js.map +1 -1
  23. package/dist/os/audit/frontmatter-io.js +5 -5
  24. package/dist/os/audit/frontmatter-io.js.map +1 -1
  25. package/dist/os/audit/handlers/archive.d.ts.map +1 -1
  26. package/dist/os/audit/handlers/archive.js +10 -4
  27. package/dist/os/audit/handlers/archive.js.map +1 -1
  28. package/dist/os/compass/compass.module.d.ts.map +1 -1
  29. package/dist/os/compass/compass.module.js +17 -1
  30. package/dist/os/compass/compass.module.js.map +1 -1
  31. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  32. package/dist/os/compass/handlers/compass-audit-handler.js +12 -5
  33. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  34. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
  35. package/dist/os/compass/handlers/compass-change-summary-handler.js +3 -2
  36. package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
  37. package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
  38. package/dist/os/compass/handlers/compass-inventory-handler.js +6 -4
  39. package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
  40. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  41. package/dist/os/compass/handlers/compass-inventory.js +10 -8
  42. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  43. package/dist/os/compass/handlers/compass-migrate-handler.js +1 -1
  44. package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -1
  45. package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -1
  46. package/dist/os/compass/handlers/compass-migrate.js +6 -3
  47. package/dist/os/compass/handlers/compass-migrate.js.map +1 -1
  48. package/dist/os/compass/handlers/git-revision.d.ts.map +1 -1
  49. package/dist/os/compass/handlers/git-revision.js +9 -6
  50. package/dist/os/compass/handlers/git-revision.js.map +1 -1
  51. package/dist/os/compass/handlers/resolve-scan-root.js +1 -1
  52. package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
  53. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
  54. package/dist/os/compass/handlers/summary-record.js +8 -4
  55. package/dist/os/compass/handlers/summary-record.js.map +1 -1
  56. package/dist/os/core/core.module.d.ts.map +1 -1
  57. package/dist/os/core/core.module.js +43 -4
  58. package/dist/os/core/core.module.js.map +1 -1
  59. package/dist/os/core/handlers/assets-helpers.d.ts.map +1 -1
  60. package/dist/os/core/handlers/assets-helpers.js +6 -3
  61. package/dist/os/core/handlers/assets-helpers.js.map +1 -1
  62. package/dist/os/core/handlers/build.js +1 -1
  63. package/dist/os/core/handlers/build.js.map +1 -1
  64. package/dist/os/core/handlers/determinism-check.d.ts.map +1 -1
  65. package/dist/os/core/handlers/determinism-check.js +10 -6
  66. package/dist/os/core/handlers/determinism-check.js.map +1 -1
  67. package/dist/os/core/handlers/dev.js +1 -1
  68. package/dist/os/core/handlers/dev.js.map +1 -1
  69. package/dist/os/core/handlers/file-size-lint.d.ts.map +1 -1
  70. package/dist/os/core/handlers/file-size-lint.js +11 -7
  71. package/dist/os/core/handlers/file-size-lint.js.map +1 -1
  72. package/dist/os/core/handlers/forge-autonomy-validate.d.ts.map +1 -1
  73. package/dist/os/core/handlers/forge-autonomy-validate.js +9 -5
  74. package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
  75. package/dist/os/core/handlers/knowledge-compact.js +1 -1
  76. package/dist/os/core/handlers/knowledge-compact.js.map +1 -1
  77. package/dist/os/core/handlers/package-health.js +1 -1
  78. package/dist/os/core/handlers/package-health.js.map +1 -1
  79. package/dist/os/core/handlers/pinned-check.js +2 -2
  80. package/dist/os/core/handlers/pinned-check.js.map +1 -1
  81. package/dist/os/core/handlers/pinned-init.d.ts.map +1 -1
  82. package/dist/os/core/handlers/pinned-init.js +9 -8
  83. package/dist/os/core/handlers/pinned-init.js.map +1 -1
  84. package/dist/os/core/handlers/pinned-validate.js +3 -3
  85. package/dist/os/core/handlers/pinned-validate.js.map +1 -1
  86. package/dist/os/core/handlers/profile-resolve.js +1 -1
  87. package/dist/os/core/handlers/profile-resolve.js.map +1 -1
  88. package/dist/os/core/handlers/public-surface.js +1 -1
  89. package/dist/os/core/handlers/public-surface.js.map +1 -1
  90. package/dist/os/core/handlers/release-prepare.d.ts.map +1 -1
  91. package/dist/os/core/handlers/release-prepare.js +10 -6
  92. package/dist/os/core/handlers/release-prepare.js.map +1 -1
  93. package/dist/os/core/handlers/release-publish.js +6 -6
  94. package/dist/os/core/handlers/release-publish.js.map +1 -1
  95. package/dist/os/core/handlers/validate.js +1 -1
  96. package/dist/os/core/handlers/validate.js.map +1 -1
  97. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  98. package/dist/os/exploration/exploration.module.js +1 -0
  99. package/dist/os/exploration/exploration.module.js.map +1 -1
  100. package/dist/os/exploration/frontmatter-io.js +4 -4
  101. package/dist/os/exploration/frontmatter-io.js.map +1 -1
  102. package/dist/os/exploration/handlers/archive.js +3 -3
  103. package/dist/os/exploration/handlers/archive.js.map +1 -1
  104. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  105. package/dist/os/mission/handlers/archive.js +44 -23
  106. package/dist/os/mission/handlers/archive.js.map +1 -1
  107. package/dist/os/mission/mission.module.js +3 -3
  108. package/dist/os/mission/mission.module.js.map +1 -1
  109. package/dist/os/naming/naming-convention.d.ts.map +1 -1
  110. package/dist/os/naming/naming-convention.js +7 -3
  111. package/dist/os/naming/naming-convention.js.map +1 -1
  112. package/dist/os/naming/naming.module.d.ts.map +1 -1
  113. package/dist/os/naming/naming.module.js +4 -3
  114. package/dist/os/naming/naming.module.js.map +1 -1
  115. package/dist/os/notes/notes.module.d.ts.map +1 -1
  116. package/dist/os/notes/notes.module.js +6 -3
  117. package/dist/os/notes/notes.module.js.map +1 -1
  118. package/dist/os/plan/frontmatter-io.js +5 -5
  119. package/dist/os/plan/frontmatter-io.js.map +1 -1
  120. package/dist/os/plan/handlers/archive.d.ts.map +1 -1
  121. package/dist/os/plan/handlers/archive.js +10 -4
  122. package/dist/os/plan/handlers/archive.js.map +1 -1
  123. package/dist/os/plan/plan.module.js +3 -3
  124. package/dist/os/plan/plan.module.js.map +1 -1
  125. package/dist/os/plugin/plugin.module.d.ts.map +1 -1
  126. package/dist/os/plugin/plugin.module.js +6 -3
  127. package/dist/os/plugin/plugin.module.js.map +1 -1
  128. package/dist/os/program/discovery.js +2 -2
  129. package/dist/os/program/discovery.js.map +1 -1
  130. package/dist/os/program/handlers/complete.js +1 -1
  131. package/dist/os/program/handlers/complete.js.map +1 -1
  132. package/dist/os/program/handlers/lease.js +1 -1
  133. package/dist/os/program/handlers/lease.js.map +1 -1
  134. package/dist/os/program/handlers/seal.js +1 -1
  135. package/dist/os/program/handlers/seal.js.map +1 -1
  136. package/dist/os/program/lease.js +1 -1
  137. package/dist/os/program/lease.js.map +1 -1
  138. package/dist/os/program/program.module.d.ts.map +1 -1
  139. package/dist/os/program/program.module.js +9 -3
  140. package/dist/os/program/program.module.js.map +1 -1
  141. package/dist/os/queue/index.js +1 -1
  142. package/dist/os/queue/manifest.d.ts.map +1 -1
  143. package/dist/os/queue/manifest.js +4 -8
  144. package/dist/os/queue/manifest.js.map +1 -1
  145. package/dist/os/rfc/acceptance.d.ts.map +1 -1
  146. package/dist/os/rfc/acceptance.js +10 -6
  147. package/dist/os/rfc/acceptance.js.map +1 -1
  148. package/dist/os/rfc/decision-log.d.ts.map +1 -1
  149. package/dist/os/rfc/decision-log.js +4 -3
  150. package/dist/os/rfc/decision-log.js.map +1 -1
  151. package/dist/os/rfc/dna-trace.d.ts.map +1 -1
  152. package/dist/os/rfc/dna-trace.js +7 -2
  153. package/dist/os/rfc/dna-trace.js.map +1 -1
  154. package/dist/os/rfc/frontmatter-io.js +5 -5
  155. package/dist/os/rfc/frontmatter-io.js.map +1 -1
  156. package/dist/os/rfc/handlers/archive.d.ts.map +1 -1
  157. package/dist/os/rfc/handlers/archive.js +11 -5
  158. package/dist/os/rfc/handlers/archive.js.map +1 -1
  159. package/dist/os/rfc/handlers/check.d.ts.map +1 -1
  160. package/dist/os/rfc/handlers/check.js +6 -3
  161. package/dist/os/rfc/handlers/check.js.map +1 -1
  162. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  163. package/dist/os/rfc/handlers/implement-stamp.js +11 -10
  164. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  165. package/dist/os/rfc/handlers/index-graph.js +3 -3
  166. package/dist/os/rfc/handlers/index-graph.js.map +1 -1
  167. package/dist/os/rfc/handlers/lifecycle.d.ts.map +1 -1
  168. package/dist/os/rfc/handlers/lifecycle.js +6 -2
  169. package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
  170. package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
  171. package/dist/os/rfc/handlers/list-create.js +7 -6
  172. package/dist/os/rfc/handlers/list-create.js.map +1 -1
  173. package/dist/os/rfc/handlers/shared.js +3 -3
  174. package/dist/os/rfc/handlers/shared.js.map +1 -1
  175. package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
  176. package/dist/os/rfc/handlers/supersede-propose.js +7 -3
  177. package/dist/os/rfc/handlers/supersede-propose.js.map +1 -1
  178. package/dist/os/rfc/handlers/validate-rules.d.ts.map +1 -1
  179. package/dist/os/rfc/handlers/validate-rules.js +8 -5
  180. package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
  181. package/dist/os/rfc/handlers/validate.d.ts.map +1 -1
  182. package/dist/os/rfc/handlers/validate.js +6 -1
  183. package/dist/os/rfc/handlers/validate.js.map +1 -1
  184. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  185. package/dist/os/rfc/rfc.module.js +44 -4
  186. package/dist/os/rfc/rfc.module.js.map +1 -1
  187. package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
  188. package/dist/os/rfc/verification-evidence.js +9 -5
  189. package/dist/os/rfc/verification-evidence.js.map +1 -1
  190. package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
  191. package/dist/os/rfc/verification-refresh.js +4 -3
  192. package/dist/os/rfc/verification-refresh.js.map +1 -1
  193. package/dist/os/session/frontmatter-io.js +12 -12
  194. package/dist/os/session/frontmatter-io.js.map +1 -1
  195. package/dist/os/session/handlers/archive.d.ts.map +1 -1
  196. package/dist/os/session/handlers/archive.js +10 -4
  197. package/dist/os/session/handlers/archive.js.map +1 -1
  198. package/dist/os/session/handlers/metrics-aggregate.d.ts.map +1 -1
  199. package/dist/os/session/handlers/metrics-aggregate.js +9 -5
  200. package/dist/os/session/handlers/metrics-aggregate.js.map +1 -1
  201. package/dist/os/session/handlers/metrics-rfc.d.ts.map +1 -1
  202. package/dist/os/session/handlers/metrics-rfc.js +11 -8
  203. package/dist/os/session/handlers/metrics-rfc.js.map +1 -1
  204. package/dist/os/session/handlers/metrics-session.d.ts.map +1 -1
  205. package/dist/os/session/handlers/metrics-session.js +6 -3
  206. package/dist/os/session/handlers/metrics-session.js.map +1 -1
  207. package/dist/os/session/handlers/save.d.ts.map +1 -1
  208. package/dist/os/session/handlers/save.js +14 -8
  209. package/dist/os/session/handlers/save.js.map +1 -1
  210. package/dist/os/session/session.module.d.ts.map +1 -1
  211. package/dist/os/session/session.module.js +6 -0
  212. package/dist/os/session/session.module.js.map +1 -1
  213. package/dist/os/spec/live-spec-list.js +4 -4
  214. package/dist/os/spec/live-spec-list.js.map +1 -1
  215. package/dist/os/spec/live-spec-merge.js +5 -5
  216. package/dist/os/spec/live-spec-merge.js.map +1 -1
  217. package/dist/os/spec/live-spec-show.js +3 -3
  218. package/dist/os/spec/live-spec-show.js.map +1 -1
  219. package/dist/os/spec/live-spec-validate.js +4 -4
  220. package/dist/os/spec/live-spec-validate.js.map +1 -1
  221. package/dist/os/spec/spec-materialize.js +9 -9
  222. package/dist/os/spec/spec-materialize.js.map +1 -1
  223. package/dist/os/spec/spec-status.js +9 -9
  224. package/dist/os/spec/spec-status.js.map +1 -1
  225. package/dist/os/spec/spec-validate.js +7 -7
  226. package/dist/os/spec/spec-validate.js.map +1 -1
  227. package/dist/os/spec/spec.module.d.ts.map +1 -1
  228. package/dist/os/spec/spec.module.js +8 -0
  229. package/dist/os/spec/spec.module.js.map +1 -1
  230. package/dist/os/werkstatt/handlers/lock.js +16 -16
  231. package/dist/os/werkstatt/handlers/lock.js.map +1 -1
  232. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +3 -3
  233. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
  234. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
  235. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +3 -2
  236. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
  237. package/dist/os/werkstatt/handlers/workspace-deps.d.ts.map +1 -1
  238. package/dist/os/werkstatt/handlers/workspace-deps.js +0 -1
  239. package/dist/os/werkstatt/handlers/workspace-deps.js.map +1 -1
  240. package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
  241. package/dist/os/werkstatt/werkstatt.module.js +6 -2
  242. package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
  243. package/dist/os/workflow/handlers.d.ts.map +1 -1
  244. package/dist/os/workflow/handlers.js +8 -5
  245. package/dist/os/workflow/handlers.js.map +1 -1
  246. package/dist/os/workflow/workflow.module.d.ts.map +1 -1
  247. package/dist/os/workflow/workflow.module.js +6 -3
  248. package/dist/os/workflow/workflow.module.js.map +1 -1
  249. package/dist/src/cli-flags.d.ts +28 -0
  250. package/dist/src/cli-flags.d.ts.map +1 -0
  251. package/dist/src/cli-flags.js +232 -0
  252. package/dist/src/cli-flags.js.map +1 -0
  253. package/dist/src/compass/contract-registry.js +1 -1
  254. package/dist/src/compass/contract-registry.js.map +1 -1
  255. package/dist/src/config/forge-config.d.ts +1 -1
  256. package/dist/src/config/forge-config.js +1 -1
  257. package/dist/src/config/forge-config.js.map +1 -1
  258. package/dist/src/knowledge/budgets.js +1 -1
  259. package/dist/src/knowledge/budgets.js.map +1 -1
  260. package/dist/src/knowledge/compact.js +1 -1
  261. package/dist/src/knowledge/compact.js.map +1 -1
  262. package/dist/src/knowledge/parse.js +1 -1
  263. package/dist/src/knowledge/parse.js.map +1 -1
  264. package/dist/src/knowledge/sync.d.ts.map +1 -1
  265. package/dist/src/knowledge/sync.js +3 -5
  266. package/dist/src/knowledge/sync.js.map +1 -1
  267. package/dist/src/migration-adapters/git-utils.js +2 -2
  268. package/dist/src/migration-adapters/git-utils.js.map +1 -1
  269. package/dist/src/migration-adapters/ignored-files.js +2 -2
  270. package/dist/src/migration-adapters/ignored-files.js.map +1 -1
  271. package/dist/src/migration-adapters/node-typescript-pnpm/index.js +1 -1
  272. package/dist/src/migration-adapters/node-typescript-pnpm/index.js.map +1 -1
  273. package/dist/src/migration-adapters/phaser-pnpm/index.js +1 -1
  274. package/dist/src/migration-adapters/phaser-pnpm/index.js.map +1 -1
  275. package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
  276. package/dist/src/onboarding/agents-generate.js +76 -34
  277. package/dist/src/onboarding/agents-generate.js.map +1 -1
  278. package/dist/src/onboarding/create.d.ts.map +1 -1
  279. package/dist/src/onboarding/create.js +10 -10
  280. package/dist/src/onboarding/create.js.map +1 -1
  281. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  282. package/dist/src/onboarding/doctor.js +68 -59
  283. package/dist/src/onboarding/doctor.js.map +1 -1
  284. package/dist/src/onboarding/init.d.ts.map +1 -1
  285. package/dist/src/onboarding/init.js +30 -1
  286. package/dist/src/onboarding/init.js.map +1 -1
  287. package/dist/src/onboarding/invariant-engine.js +1 -1
  288. package/dist/src/onboarding/invariant-engine.js.map +1 -1
  289. package/dist/src/onboarding/memory-compact.d.ts.map +1 -1
  290. package/dist/src/onboarding/memory-compact.js +5 -4
  291. package/dist/src/onboarding/memory-compact.js.map +1 -1
  292. package/dist/src/onboarding/memory-scaffold.js +1 -1
  293. package/dist/src/onboarding/memory-scaffold.js.map +1 -1
  294. package/dist/src/onboarding/nested-agents-generate.d.ts +4 -1
  295. package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
  296. package/dist/src/onboarding/nested-agents-generate.js +34 -5
  297. package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
  298. package/dist/src/onboarding/nested-agents-templates.d.ts.map +1 -1
  299. package/dist/src/onboarding/nested-agents-templates.js +8 -12
  300. package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
  301. package/dist/src/onboarding/npm-token-check.js +2 -2
  302. package/dist/src/onboarding/npm-token-check.js.map +1 -1
  303. package/dist/src/onboarding/prettierignore.d.ts +29 -0
  304. package/dist/src/onboarding/prettierignore.d.ts.map +1 -0
  305. package/dist/src/onboarding/prettierignore.js +231 -0
  306. package/dist/src/onboarding/prettierignore.js.map +1 -0
  307. package/dist/src/onboarding/profile-validate.d.ts.map +1 -1
  308. package/dist/src/onboarding/profile-validate.js +5 -4
  309. package/dist/src/onboarding/profile-validate.js.map +1 -1
  310. package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
  311. package/dist/src/onboarding/scaffold-project.js +35 -27
  312. package/dist/src/onboarding/scaffold-project.js.map +1 -1
  313. package/dist/src/onboarding/scaffold.js +1 -1
  314. package/dist/src/onboarding/scaffold.js.map +1 -1
  315. package/dist/src/onboarding/skill-markers.d.ts +27 -0
  316. package/dist/src/onboarding/skill-markers.d.ts.map +1 -0
  317. package/dist/src/onboarding/skill-markers.js +131 -0
  318. package/dist/src/onboarding/skill-markers.js.map +1 -0
  319. package/dist/src/onboarding/upgrade.d.ts +10 -0
  320. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  321. package/dist/src/onboarding/upgrade.js +215 -74
  322. package/dist/src/onboarding/upgrade.js.map +1 -1
  323. package/dist/src/onboarding/workspace-discovery.js +1 -1
  324. package/dist/src/onboarding/workspace-discovery.js.map +1 -1
  325. package/dist/src/pipeline-status.d.ts +6 -5
  326. package/dist/src/pipeline-status.d.ts.map +1 -1
  327. package/dist/src/pipeline-status.js +24 -19
  328. package/dist/src/pipeline-status.js.map +1 -1
  329. package/dist/src/profiles/stack-profile.js +1 -1
  330. package/dist/src/profiles/stack-profile.js.map +1 -1
  331. package/dist/src/registry.d.ts +1 -1
  332. package/dist/src/registry.d.ts.map +1 -1
  333. package/dist/src/registry.js +3 -3
  334. package/dist/src/registry.js.map +1 -1
  335. package/dist/src/skill-schema.d.ts +1 -1
  336. package/dist/src/skill-schema.d.ts.map +1 -1
  337. package/dist/src/skill-schema.js +4 -1
  338. package/dist/src/skill-schema.js.map +1 -1
  339. package/dist/src/types.d.ts +116 -0
  340. package/dist/src/types.d.ts.map +1 -1
  341. package/dist/src/utils/editable-region.d.ts +46 -0
  342. package/dist/src/utils/editable-region.d.ts.map +1 -0
  343. package/dist/src/utils/editable-region.js +125 -0
  344. package/dist/src/utils/editable-region.js.map +1 -0
  345. package/dist/src/utils/fs-idempotent.d.ts +2 -1
  346. package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
  347. package/dist/src/utils/fs-idempotent.js +11 -7
  348. package/dist/src/utils/fs-idempotent.js.map +1 -1
  349. package/dist/src/utils/generated-marker.d.ts +17 -0
  350. package/dist/src/utils/generated-marker.d.ts.map +1 -1
  351. package/dist/src/utils/generated-marker.js +29 -1
  352. package/dist/src/utils/generated-marker.js.map +1 -1
  353. package/dist/src/utils/index.d.ts +3 -1
  354. package/dist/src/utils/index.d.ts.map +1 -1
  355. package/dist/src/utils/index.js +3 -1
  356. package/dist/src/utils/index.js.map +1 -1
  357. package/dist/src/utils/io.d.ts +9 -0
  358. package/dist/src/utils/io.d.ts.map +1 -0
  359. package/dist/src/utils/io.js +130 -0
  360. package/dist/src/utils/io.js.map +1 -0
  361. package/dist/src/utils/markdown-table.d.ts +21 -0
  362. package/dist/src/utils/markdown-table.d.ts.map +1 -0
  363. package/dist/src/utils/markdown-table.js +116 -0
  364. package/dist/src/utils/markdown-table.js.map +1 -0
  365. package/dist/src/utils/sync-fs.d.ts +5 -0
  366. package/dist/src/utils/sync-fs.d.ts.map +1 -0
  367. package/dist/src/utils/sync-fs.js +26 -0
  368. package/dist/src/utils/sync-fs.js.map +1 -0
  369. package/dist/src/validators/note-frontmatter-validate.js +1 -1
  370. package/dist/src/validators/note-frontmatter-validate.js.map +1 -1
  371. package/dist/src/validators/note-link-validate.js +1 -1
  372. package/dist/src/validators/note-link-validate.js.map +1 -1
  373. package/dist/src/validators/note-orphan-detect.js +1 -1
  374. package/dist/src/validators/note-orphan-detect.js.map +1 -1
  375. package/dist/src/validators/port-validate.js +1 -1
  376. package/dist/src/validators/port-validate.js.map +1 -1
  377. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  378. package/dist/src/validators/skill-validate.js +34 -13
  379. package/dist/src/validators/skill-validate.js.map +1 -1
  380. package/os/adr/adr.module.ts +136 -132
  381. package/os/adr/frontmatter-io.ts +5 -5
  382. package/os/adr/handlers/archive.ts +8 -4
  383. package/os/adr/handlers/implement-stamp.ts +14 -10
  384. package/os/adr/handlers/list-create.ts +5 -5
  385. package/os/adr/handlers/validate.ts +1 -1
  386. package/os/audit/audit.module.ts +33 -34
  387. package/os/audit/frontmatter-io.ts +5 -5
  388. package/os/audit/handlers/archive.ts +8 -4
  389. package/os/compass/compass.module.ts +17 -1
  390. package/os/compass/handlers/compass-audit-handler.ts +13 -5
  391. package/os/compass/handlers/compass-change-summary-handler.ts +4 -2
  392. package/os/compass/handlers/compass-inventory-handler.ts +7 -4
  393. package/os/compass/handlers/compass-inventory.ts +11 -8
  394. package/os/compass/handlers/compass-migrate-handler.ts +1 -1
  395. package/os/compass/handlers/compass-migrate.ts +7 -3
  396. package/os/compass/handlers/git-revision.ts +11 -6
  397. package/os/compass/handlers/resolve-scan-root.ts +1 -1
  398. package/os/compass/handlers/summary-record.ts +10 -4
  399. package/os/compass/handlers/tests/compass-audit-plan.test.ts +2 -1
  400. package/os/core/core.module.ts +43 -4
  401. package/os/core/handlers/assets-helpers.ts +7 -3
  402. package/os/core/handlers/build.ts +1 -1
  403. package/os/core/handlers/determinism-check.ts +12 -6
  404. package/os/core/handlers/dev.ts +1 -1
  405. package/os/core/handlers/file-size-lint.ts +16 -9
  406. package/os/core/handlers/forge-autonomy-validate.ts +10 -5
  407. package/os/core/handlers/knowledge-compact.ts +1 -1
  408. package/os/core/handlers/package-health.ts +1 -1
  409. package/os/core/handlers/pinned-check.ts +2 -2
  410. package/os/core/handlers/pinned-init.ts +9 -8
  411. package/os/core/handlers/pinned-validate.ts +3 -3
  412. package/os/core/handlers/profile-resolve.ts +1 -1
  413. package/os/core/handlers/public-surface.ts +1 -1
  414. package/os/core/handlers/release-prepare.ts +11 -6
  415. package/os/core/handlers/release-publish.ts +6 -6
  416. package/os/core/handlers/validate.ts +1 -1
  417. package/os/exploration/exploration.module.ts +1 -0
  418. package/os/exploration/frontmatter-io.ts +4 -4
  419. package/os/exploration/handlers/archive.ts +3 -3
  420. package/os/mission/handlers/archive.test.ts +38 -1
  421. package/os/mission/handlers/archive.ts +54 -23
  422. package/os/mission/mission.module.ts +38 -39
  423. package/os/naming/naming-convention.ts +9 -3
  424. package/os/naming/naming.module.ts +25 -25
  425. package/os/notes/notes.module.ts +87 -85
  426. package/os/plan/frontmatter-io.ts +5 -5
  427. package/os/plan/handlers/archive.ts +8 -4
  428. package/os/plan/plan.module.ts +33 -34
  429. package/os/plugin/plugin.module.ts +8 -6
  430. package/os/program/discovery.ts +2 -2
  431. package/os/program/handlers/complete.ts +1 -1
  432. package/os/program/handlers/lease.ts +1 -1
  433. package/os/program/handlers/seal.ts +1 -1
  434. package/os/program/lease.ts +1 -1
  435. package/os/program/program.module.ts +198 -193
  436. package/os/queue/index.ts +1 -1
  437. package/os/queue/manifest.ts +10 -9
  438. package/os/queue/queue-validate.test.ts +6 -15
  439. package/os/rfc/acceptance.ts +12 -6
  440. package/os/rfc/decision-log.ts +4 -3
  441. package/os/rfc/dna-trace.ts +8 -2
  442. package/os/rfc/frontmatter-io.ts +5 -5
  443. package/os/rfc/handlers/archive.ts +9 -5
  444. package/os/rfc/handlers/check.ts +5 -3
  445. package/os/rfc/handlers/implement-stamp.ts +15 -10
  446. package/os/rfc/handlers/index-graph.ts +3 -3
  447. package/os/rfc/handlers/lifecycle.ts +7 -2
  448. package/os/rfc/handlers/list-create.ts +7 -6
  449. package/os/rfc/handlers/shared.ts +3 -3
  450. package/os/rfc/handlers/supersede-propose.ts +8 -3
  451. package/os/rfc/handlers/validate-rules-rfc1006.test.ts +18 -6
  452. package/os/rfc/handlers/validate-rules.ts +10 -5
  453. package/os/rfc/handlers/validate.test.ts +71 -0
  454. package/os/rfc/handlers/validate.ts +6 -1
  455. package/os/rfc/rfc-create-concurrent.test.ts +11 -3
  456. package/os/rfc/rfc.module.ts +413 -374
  457. package/os/rfc/verification-evidence.ts +11 -5
  458. package/os/rfc/verification-refresh.ts +4 -3
  459. package/os/session/frontmatter-io.ts +14 -14
  460. package/os/session/handlers/archive.ts +8 -4
  461. package/os/session/handlers/metrics-aggregate.ts +34 -13
  462. package/os/session/handlers/metrics-rfc.ts +13 -8
  463. package/os/session/handlers/metrics-session.ts +7 -3
  464. package/os/session/handlers/save.ts +12 -8
  465. package/os/session/session.module.ts +6 -0
  466. package/os/spec/live-spec-list.ts +4 -4
  467. package/os/spec/live-spec-merge.ts +5 -5
  468. package/os/spec/live-spec-show.ts +3 -3
  469. package/os/spec/live-spec-validate.ts +4 -4
  470. package/os/spec/spec-materialize.ts +9 -9
  471. package/os/spec/spec-status.ts +9 -9
  472. package/os/spec/spec-validate.ts +7 -7
  473. package/os/spec/spec.module.ts +8 -0
  474. package/os/werkstatt/handlers/lock.ts +16 -16
  475. package/os/werkstatt/handlers/werkstatt-lock-recover.ts +3 -3
  476. package/os/werkstatt/handlers/werkstatt-operation-validate.ts +4 -2
  477. package/os/werkstatt/handlers/workspace-deps.ts +0 -1
  478. package/os/werkstatt/werkstatt.module.ts +8 -5
  479. package/os/workflow/handlers.ts +7 -5
  480. package/os/workflow/workflow.module.ts +45 -44
  481. package/package.json +1 -1
  482. package/profiles/forge-shell.yaml +1 -1
  483. package/profiles/godot-game.yaml +1 -1
  484. package/profiles/knowledge.yaml +1 -1
  485. package/profiles/phaser-game.yaml +1 -1
  486. package/profiles/site-workshop.yaml +1 -1
  487. package/profiles/typescript.yaml +1 -1
  488. package/skills/fo/fo-add-tests/SKILL.md +2 -2
  489. package/skills/fo/fo-architecture/SKILL.md +2 -2
  490. package/skills/fo/fo-compass-annotate/SKILL.md +2 -2
  491. package/skills/fo/fo-design-summit/SKILL.md +2 -2
  492. package/skills/fo/fo-doc-audit/SKILL.md +2 -2
  493. package/skills/fo/fo-explore/SKILL.md +2 -2
  494. package/skills/fo/fo-extract-dna/SKILL.md +2 -2
  495. package/skills/fo/fo-fix/SKILL.md +2 -2
  496. package/skills/fo/fo-handoff/SKILL.md +2 -2
  497. package/skills/fo/fo-harvest/SKILL.md +2 -2
  498. package/skills/fo/fo-idea/SKILL.md +2 -2
  499. package/skills/fo/fo-idea-audit/SKILL.md +2 -2
  500. package/skills/fo/fo-idea-create-adr/SKILL.md +3 -3
  501. package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -3
  502. package/skills/fo/fo-idea-enhance/SKILL.md +2 -2
  503. package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +2 -2
  504. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +1 -1
  505. package/skills/fo/fo-idea-implement/SKILL.md +2 -2
  506. package/skills/fo/fo-idea-plan/SKILL.md +2 -2
  507. package/skills/fo/fo-idea-status/SKILL.md +2 -2
  508. package/skills/fo/fo-knowledge-distill/SKILL.md +2 -2
  509. package/skills/fo/fo-memory-sync/SKILL.md +2 -2
  510. package/skills/fo/fo-qa/SKILL.md +2 -2
  511. package/skills/fo/fo-review/SKILL.md +2 -2
  512. package/skills/fo/fo-session-retro/SKILL.md +2 -2
  513. package/skills/fo/fo-session-save/SKILL.md +2 -2
  514. package/skills/fo/fo-spec-ingest/SKILL.md +2 -2
  515. package/skills/fo/fo-step-commit/SKILL.md +1 -1
  516. package/skills/fo/fo-triage/SKILL.md +2 -2
  517. package/skills/meta/forge-bootstrap/SKILL.md +1 -1
  518. package/skills/meta/port-to-forge/SKILL.md +1 -1
  519. package/skills/meta/skill-create/SKILL.md +1 -1
  520. package/skills/shared/grilling/SKILL.md +1 -1
  521. package/skills/shared/grilling/learned-principles.archive.md +17 -0
  522. package/skills/shared/grilling/learned-principles.md +0 -1
  523. package/skills/shared/knowledge/learned-principles.md +6 -0
  524. package/skills/shared/my-preferences/SKILL.md +1 -1
  525. package/skills/shared/windows-ai-tooling/SKILL.md +1 -1
  526. package/skills/shared/writing-great-skills/SKILL.md +1 -1
  527. package/src/cli-flags.ts +285 -0
  528. package/src/compass/contract-registry.ts +1 -1
  529. package/src/config/forge-config.ts +1 -1
  530. package/src/knowledge/__tests__/sync.test.ts +2 -7
  531. package/src/knowledge/budgets.ts +1 -1
  532. package/src/knowledge/compact.ts +1 -1
  533. package/src/knowledge/parse.ts +1 -1
  534. package/src/knowledge/sync.ts +3 -5
  535. package/src/migration-adapters/git-utils.ts +2 -2
  536. package/src/migration-adapters/ignored-files.ts +2 -2
  537. package/src/migration-adapters/node-typescript-pnpm/index.ts +1 -1
  538. package/src/migration-adapters/phaser-pnpm/index.ts +1 -1
  539. package/src/onboarding/agents-generate.ts +92 -36
  540. package/src/onboarding/create.ts +10 -10
  541. package/src/onboarding/doctor.ts +70 -55
  542. package/src/onboarding/init.ts +38 -1
  543. package/src/onboarding/invariant-engine.ts +1 -1
  544. package/src/onboarding/memory-compact.ts +5 -4
  545. package/src/onboarding/memory-scaffold.ts +1 -1
  546. package/src/onboarding/nested-agents-generate.ts +45 -4
  547. package/src/onboarding/nested-agents-templates.ts +19 -13
  548. package/src/onboarding/npm-token-check.ts +2 -2
  549. package/src/onboarding/prettierignore.ts +263 -0
  550. package/src/onboarding/profile-validate.ts +5 -4
  551. package/src/onboarding/scaffold-project.ts +38 -27
  552. package/src/onboarding/scaffold.ts +1 -1
  553. package/src/onboarding/skill-markers.ts +162 -0
  554. package/src/onboarding/templates/behavioral-layer-core.md +2 -4
  555. package/src/onboarding/upgrade.ts +285 -89
  556. package/src/onboarding/workspace-discovery.ts +1 -1
  557. package/src/pipeline-status.test.ts +1 -4
  558. package/src/pipeline-status.ts +30 -13
  559. package/src/profiles/stack-profile.ts +1 -1
  560. package/src/registry.ts +4 -4
  561. package/src/skill-schema.ts +4 -1
  562. package/src/tests/acceptance-probe-kinds.test.ts +5 -15
  563. package/src/tests/agents-generate.test.ts +28 -5
  564. package/src/tests/cli-flags.test.ts +169 -0
  565. package/src/tests/contract-registry.test.ts +12 -6
  566. package/src/tests/doctor-fix.test.ts +1 -4
  567. package/src/tests/doctor-nested-agents.test.ts +53 -1
  568. package/src/tests/editable-generated-region.test.ts +231 -0
  569. package/src/tests/file-size-lint.test.ts +8 -12
  570. package/src/tests/fixtures/agents-generate-business-before.txt +85 -56
  571. package/src/tests/markdown-table.test.ts +107 -0
  572. package/src/tests/prettierignore-manage.test.ts +134 -0
  573. package/src/tests/skill-agents-sync.test.ts +168 -0
  574. package/src/tests/skill-sync-marker.test.ts +134 -0
  575. package/src/tests/skill-validate.test.ts +12 -5
  576. package/src/tests/upgrade.test.ts +87 -41
  577. package/src/types.ts +123 -0
  578. package/src/utils/editable-region.ts +156 -0
  579. package/src/utils/fs-idempotent.ts +12 -6
  580. package/src/utils/generated-marker.ts +36 -2
  581. package/src/utils/index.ts +17 -0
  582. package/src/utils/io.ts +143 -0
  583. package/src/utils/markdown-table.ts +121 -0
  584. package/src/utils/sync-fs.ts +43 -0
  585. package/src/validators/note-frontmatter-validate.ts +1 -1
  586. package/src/validators/note-link-validate.ts +1 -1
  587. package/src/validators/note-orphan-detect.ts +1 -1
  588. package/src/validators/port-validate.ts +1 -1
  589. package/src/validators/skill-validate.ts +38 -13
  590. package/AGENTS.md +0 -502
package/AGENTS.md DELETED
@@ -1,502 +0,0 @@
1
- # @warpgogol/forge Agent Guide
2
-
3
- Portable governance skills and command modules extracted from the engine (RFC-0374) (RFC-0374).
4
-
5
- ## Architecture
6
-
7
- - `src/` — portable, no kernel imports. Contains skill schema, registry, validators, onboarding handlers, config module, canonical types, and utilities.
8
- - `os/` — ForgeModule registrations. RFC-0556: `os/compass/` and `os/werkstatt/` are fully autonomous — all command handlers are inlined in `os/*/handlers/` and no longer dynamically import `@warpgogol/*` packages. Other `os/` modules may still use dynamic imports where kernel integration is needed. RFC-0940: all `os/*.module.ts` files declare a required `runtime` field (`"autonomous"` or `"werkstatt-adapter"`). Only `os/werkstatt/` may import `@warpgogol/werkstatt-engine` — all other `os/` directories are autonomous. ADR-0019: `@warpgogol/werkstatt-shared` is no longer a dependency — `scanDirectoryForImports` is inlined in `os/core/handlers/forge-autonomy-validate.ts`. `forge.autonomy.validate` enforces FORGE-AUTONOMY-01. Type-only imports (`import type`) are exempt. 2026-09-22: the `@warpgogol/werkstatt-engine` devDependency was removed from `package.json` to break the turbo-reported forge↔engine package cycle — `os/werkstatt/handlers/workspace-deps.ts` now bridges fingerprinting via `@warpgogol/werkstatt-shared/fingerprint` (canonical home since RFC-1104). Do not re-add an engine dependency; new bridge needs go through `werkstatt-shared` subpaths.
9
- - `bin/` — CLI entrypoint (`forge` command) for autonomous usage without `@warpgogol/werkstatt-engine`. **New `os/` modules MUST be registered manually in `bin/cli.ts` `buildRegistry()`** — the standalone CLI has no module auto-discovery. A module exported via `package.json` and wired in `tools/kernel.config.ts` profiles is still invisible to `forge <cmd>` until added to the registry array. Discovered 2026-09-16: `forge-adr` (and 6 other modules) existed in source but were unreachable via the CLI.
10
- - `skills/` — forge-managed skill definitions (29 fo skills + 5 shared + 3 meta = 37 skills). Project-declared skill packs (RFC-0539) live outside forge and are discovered via `discoverPackSkills` from `forge.yaml` `skillPacks` config.
11
-
12
- ## RFC-0855 program control-plane boundary
13
-
14
- Packet 000 will add the portable `forge/program@1` control plane under `os/program/` as specified by accepted RFC-0856 and its committed implementation plan. Do not implement it, register commands, or alter packet state before packet 000 is sealed. The module validates and writes governance artifacts only: it never executes packet work, commits, materializes decisions without a preparation lease, deploys, or imports `@warpgogol/werkstatt-engine`. Keep it cross-platform, deny unknown fields and unsafe paths, store only lease-token digests, and preserve packet 000 as the sole irreversible bootstrap.
15
-
16
- ## OS modules
17
-
18
- | Module | Commands | Source |
19
- | --- | --- | --- |
20
- | `forgeCoreModule` | `create`, `doctor`, `upgrade`, `forge.agents.generate`, `scaffold`, `port.scaffold`, `skill.validate`, `skill.list`, `port.validate`, `profile.validate`, `dev`, `build`, `validate`, `pinned.validate`, `pinned.init`, `package.health`, `docs.archive`, `forge.autonomy.validate`, `forge.public-surface.validate`, `file.size.lint` | `os/core/` |
21
- | `forgeRfcModule` | `rfc.list`, `rfc.validate`, `rfc.create`, `rfc.verification.emit`, `rfc.verification.refresh`, etc. | `os/rfc/` |
22
- | `forgeWorkflowModule` | `workflow.lint`, `workflow.list`, `workflow.amend.list` | `os/workflow/` |
23
- | `forgeNamingModule` | `naming.convention.lint` | `os/naming/` |
24
- | `forgeCompassModule` | `compass.inventory`, `compass.validate`, `compass.summary.record`, `compass.summary.trim`, etc. (8 commands). All compass commands accept `--workpiece <path>` for scoping to a mission workpiece directory (RFC-0617). `compass.summary.record` appends governance-ID items to `CHANGE_SUMMARY` at commit time (RFC-1095). | `os/compass/` |
25
- | `forgeWerkstattModule` | `werkstatt.lock.status`, `werkstatt.lock.recover`, `werkstatt.operation.validate` | `os/werkstatt/` |
26
- | `forgeSpecModule` | `spec.validate`, `spec.status`, `spec.materialize`, `spec.live.merge`, `spec.live.list`, `spec.live.show`, `spec.live.validate` | `os/spec/` |
27
- | `forgeAdrModule` | `adr.list`, `adr.create`, `adr.validate`, `adr.archive`, `adr.implement.stamp` | `os/adr/` |
28
- | `forgePlanModule` | `plan.archive` | `os/plan/` |
29
- | `forgeAuditModule` | `audit.archive` | `os/audit/` |
30
- | `forgeSessionModule` | `session.save`, `session.archive`, `session.validate`, `session.list`, `metrics.aggregate` | `os/session/` |
31
- | `forgeMissionModule` | `mission.archive` | `os/mission/` |
32
- | `forgeExplorationModule` | `exploration.list`, `exploration.show`, `exploration.archive` | `os/exploration/` |
33
- | `forgeNotesModule` | `note.link.validate`, `note.frontmatter.validate`, `note.orphan.detect` | `os/notes/` |
34
- | `forgeProgramModule` | `program.packet.validate`, `program.packet.seal`, `program.packet.lease`, `program.packet.complete` | `os/program/` |
35
- | `forgePluginModule` | `forge.plugin.validate`, `forge.plugin.discover` | `os/plugin/` |
36
- | `forgeQueueModule` | `queue.validate` — validates `docs/queues/*.yaml` manifests and reports derived per-item pipeline status (RFC-1140). Shared resolver lives in `src/pipeline-status.ts`. | `os/queue/` |
37
-
38
- ## RFC-1053: Skill effectiveness metrics
39
-
40
- `metrics.aggregate` (RFC-1053) queries and aggregates per-skill effectiveness metrics from `docs/metrics/` YAML files. Metrics are generated at two integration points:
41
-
42
- - `rfc.implement.stamp` — generates `docs/metrics/rfcs/<rfc-id>.metrics.yaml` after successful stamp (non-fatal on failure).
43
- - `session.save` — generates `docs/metrics/sessions/<session-id>.metrics.yaml` from parsed ATIF messages (non-fatal on failure).
44
-
45
- Both generators are best-effort: metrics failures log a warning and never block the primary operation. Agents MUST NOT manually edit `docs/metrics/` files — they are generated artifacts produced by `rfc.implement.stamp` and `session.save`.
46
-
47
- ## Compass contract extension points (RFC-0943)
48
-
49
- Skill packs MAY declare additional Compass contract blocks beyond the built-in `MODULE_CONTRACT`, `KEY_DECISIONS`, and `CHANGE_SUMMARY` (v2, RFC-1094) via `forge.plugin.yaml` `extensionPoints.compass.contract.blocks[]`. Each block spec is declarative data:
50
-
51
- - `blockId` — kebab-case identifier (e.g. `api-contract`). The marker in source files is the uppercased, underscore-separated form (e.g. `<API_CONTRACT>`).
52
- - `requiredFor` — glob patterns matching files that must carry this block (e.g. `["packages/my-pack/**/*.ts"]`).
53
- - `requiredTags` — optional array of `{ name, minWords? }` tags that must appear inside the block.
54
-
55
- `compass.validate` loads block specs from all declared skill packs via `loadContractRegistry` and emits `COMPASS-PLUGIN-01` (missing block), `COMPASS-PLUGIN-02` (missing required tag), and `COMPASS-PLUGIN-03` (tag below minWords) diagnostics. Duplicate `blockId` across packs is rejected with `COMPASS-PLUGIN-DUP-01`. The `FORBIDDEN_PATTERNS` negative list stays hardcoded in `compass-inventory.ts` and is not extensible by packs.
56
-
57
- ## Compass policy externalization (RFC-1096)
58
-
59
- All Compass policy values — scan roots, file extensions, ignored dirs/prefixes, test patterns, high-risk globs, layer/risk rules, workspace-kind map, exclusion globs, governance-ID and boilerplate regexes — are resolved by `resolveCompassPolicy` in `os/compass/policy.ts` from three layers: generic defaults → stack profile `compass:` section → consumer `forge.yaml` `bindings.compass`. Agents MUST NOT add stack- or consumer-specific literals (paths, extensions, regexes) to `os/compass/**` — they belong in `profiles/*.yaml` or the consumer's `forge.yaml`. Union keys merge with `!`-subtraction; `scanRoots`, `idPattern`, `purposeBoilerplatePatterns`, `layerRules`, `workspaceKinds` replace wholesale. `idPattern` must match the `ABC-123` probe or resolution throws `CompassPolicyConfigError`. See `docs/reference/forge-yaml.md` `bindings.compass` for the key reference.
60
-
61
- Exclusion, layer, and risk globs match `relativePathWithinWorkspace`, not the repo-root-relative path. For leaf-workspace scans (`--workpiece`, `--site`, or a cwd-resolved site) it is computed relative to `scanRoot` (the workpiece/site dir); for `--packages`, `--package`, and default `scanRoots` it is repo-relative with the workspace-kind prefix stripped via `getWorkspaceRelativeSegments`. Author exclusion globs (e.g. `public/_video/**`) against the workspace-relative form — a repo-relative glob silently fails to match leaf scans. See `createCompassInventoryEntries` in `os/compass/handlers/compass-inventory.ts`.
62
-
63
- ## Commit and config loading rules
64
-
65
- - **Verify `ecosystem.commit` output.** `ecosystem.commit` commits whatever is in the git index (staged files). If another agent staged files before your call, those files will be included in your commit instead of your own. After every `ecosystem.commit`, run `git show --stat HEAD` to verify the correct files were committed. If wrong files were committed, the missing files remain untracked/unstaged and must be committed separately.
66
- - **Wrap `loadForgeConfig` in try/catch in handlers that run in test workspaces.** `loadForgeConfig` throws when `forge.yaml` does not exist at the workspace root. Handlers that may be called from test workspaces without a `forge.yaml` (e.g. `runCompassValidation`) must guard the call with try/catch and skip pack-dependent logic when config is unavailable.
67
- - **`listStackProfiles` returns `[]` for a missing `profiles/` dir — it does not throw.** Distinguishing "catalog unavailable" from "catalog present but empty/unknown id" requires an explicit `existsSync` on the profiles directory. Discovered during RFC-1118: without the check, an unreadable catalog produced a spurious "unknown profile id" fail instead of "catalog-unavailable" warn.
68
- - **Fail-closed recovery of corrupted config fields requires the Zod schema to accept the corrupted shape.** Strict validation runs before any recovery logic — a schema that rejects the corrupted form makes recovery unreachable. Widen the field schema (e.g. `z.union([string, object])`), recover in `loadForgeConfig`, and heal on the next `serializeForgeConfig` write. Discovered during RFC-1118.
69
- - **Register new top-level directories in `NAMING_CONVENTION_IGNORED_TOP_LEVEL`.** When a new top-level directory appears in the repo (e.g. `.adr-locks`, `.devin`, `.forge`, `.rfc-locks`, `patches`, `storage`), add it to `NAMING_CONVENTION_IGNORED_TOP_LEVEL` in `os/naming/naming-convention.ts`. Otherwise `naming.convention.lint` reports "unknown top-level directory" errors.
70
- - **Add tool-generated/imported/historical dirs to `NAMING_CONVENTION_EXEMPT_DIRS`.** Directories containing tool-generated files (e.g. `docs/performance` with timestamp-based names), imported specification documents (e.g. `docs/specs` with `01-PBP-System-Specification.md`), and archived RFCs (e.g. `docs/rfcs/archive`) should be added to `NAMING_CONVENTION_EXEMPT_DIRS` in `os/naming/naming-convention.ts` to avoid false-positive kebab-case violations on files whose naming is controlled by external tools or conventions.
71
- - **Use `%s` not `%B` for git log delimiter parsing.** When parsing `git log --format` output with `\x1f`-delimited fields, use `%s` (subject only) instead of `%B` (full body). `%B` includes newlines which break the per-line `split("\x1f")` parsing, causing all entries to be silently skipped. Discovered during RFC-1053 `metrics-rfc.ts` implementation.
72
- - **`writeFileAtomic` does not create parent directories.** `src/utils/fs-atomic.ts` writes the temp file directly — a missing parent dir fails with ENOENT. Always `mkdir(dirname, { recursive: true })` before calling it for paths whose parent may not exist (e.g. `docs/` in a fresh workspace). Discovered during RFC-1139: `saveLedger` crashed on `docs/compass-audit-ledger.generated.yaml` in a test fixture without `docs/`.
73
- - **Chicken-and-egg with self-referential acceptance probes.** When an RFC's acceptance probe checks for a file that is created by `rfc.implement.stamp` itself (e.g. `docs/metrics/rfcs/<rfc-id>.metrics.yaml`), `rfc.verification.emit` will always report "fail" before stamping because the file doesn't exist yet. Solution: generate the file manually first (e.g. via a node script calling the generator function), re-emit evidence, then stamp. The stamp's `RFC-IMP-06` check requires evidence to be "pass" before proceeding. Discovered during RFC-1053 stamping.
74
- - **Check `batch:` frontmatter before creating sibling RFCs.** When an RFC references sibling RFCs (e.g. "the sibling lifecycle RFC"), grep `docs/rfcs/` for the shared `batch:` field first — the batch may already be fully drafted. Creating a new RFC for an already-drafted sibling produces duplicates. Discovered during RFC-1094 retro: RFC-1095/1096/1097 existed as drafts before the operator asked to "write the needed RFCs".
75
- - **Mark forward references to unimplemented commands.** When documentation (skill templates, AGENTS.md, RFCs) references a command that does not exist yet — e.g. a sibling-RFC command like `compass.migrate` — mark it explicitly as `(sibling RFC, not yet implemented)`. Bare references make agents try to run non-existent commands. Discovered during RFC-1094.
76
- - **Compass test fixtures must not embed literal contract blocks or banned literals.** `compass.summary.record` rewrites `<CHANGE_SUMMARY>` blocks found in a file's header region at commit time — a literal block inside a test file gets self-rewritten (this broke `compass-v2-contract.test.ts`). Build tags via concatenation (`"<" + "CHANGE_SUMMARY>"`) and construct banned literals dynamically so AC-4-style source scans do not flag the test file itself. Discovered during RFC-1096.
77
- - **Keep consumer/stack literals out of commit messages for `os/compass` files.** `compass.summary.record` embeds the commit message verbatim into `<CHANGE_SUMMARY>` items — a message like "werkstatt-engine clean" lands the banned literal `werkstatt` inside `os/compass/**` sources and trips the AC-4 banned-literal scan (`compass-policy.test.ts`). Use generic package names in commit messages ("engine package clean") for commits that touch `os/compass` files. Discovered during RFC-1097 sweep.
78
- - **AC evidence annotations must be bare file paths without em-dash suffixes.** `rfc.validate` (V-27) requires `(evidence: <file:line>)` or `(evidence: test: <path>)` annotations. The evidence parser treats everything after the prefix as a literal file path — adding descriptive text after an em-dash (e.g. `(evidence: test: packages/forge/src/tests/public-surface.test.ts — SURFACE-02 tests)`) causes "evidence references a file that does not exist" errors. Keep evidence annotations to `evidence: file: <path>` or `evidence: test: <path>` only. Discovered during RFC-1080 stamping.
79
- - **`compass.validate` is workspace-scoped — in mission pipelines it scans `packages/*`, not just the workpiece.** `execute-pipeline` injects `--site` for workspace-scoped commands, but `resolveCompassScanRoot` still resolves the platform scan root (`scanRoots`/`packages/`) — so platform compass debt blocks site missions even when the workpiece itself is clean. To scan only the workpiece, run `compass.validate --workpiece <path>` directly. When a mission fails on compass errors in `packages/*`, fix the platform files — the workpiece is not the problem. Discovered during warpgogol-m000142: 170 platform violations blocked a 1-file workpiece mission.
80
- - **`COMPASS-PURPOSE-02` requires a whole-word token match.** `deriveFileTokens` produces filename-stem segments, exported-symbol words, and (for generic stems like `index`/`helpers`) the parent directory name. The `<purpose>` text must contain at least one token as a standalone lowercase word — a camelCase symbol does not satisfy its own segments (`AuditService` does not satisfy `audit`). Write the token as a separate word in the purpose sentence. See `compass-inventory.ts` `deriveFileTokens` + the PURPOSE-02 check.
81
-
82
- ## Program packet control plane (RFC-0856)
83
-
84
- The program packet control plane governs sequential packet execution under `forge/program@1`. It validates boundaries; it does not execute implementation commands or commit on behalf of agents.
85
-
86
- - **Program Steward** and **Packet Executor** are distinct roles. A Steward seals packets, recovers stale leases, and validates completions. An Executor holds the lease and implements the packet. The same actor MUST NOT be both Steward and Executor for the same packet.
87
- - **Manual state edits are forbidden.** Packet state transitions (`draft` → `sealed` → `active` → `completed`) must go through the registered commands. Self-sealing (a packet's Executor calling `seal` or `complete` for their own packet) is rejected.
88
- - **Lease tokens are opaque and untracked.** Raw lease tokens exist only in memory and the command response. Only the SHA-256 hash is persisted in `.forge/program-leases/` (gitignored). Tokens never appear in tracked artifacts, logs, or completion reports.
89
- - **Normative source hashes are exact-byte.** `normativeSources` in a packet record SHA-256 digests of the exact file bytes at seal time. Reordered YAML or reformatted JSON that changes byte content will fail validation, even if the parsed structure is semantically identical.
90
- - **Bootstrap packet 000 is irreversible.** The `--bootstrap` flag on `program.packet.complete` is valid only for the first packet (no predecessor, program state `preparing`). It transitions the program to `executing`. There is no second bootstrap path.
91
- - **Path validation is traversal-safe.** `allowedFiles` and `forbiddenFiles` use lexical path normalization that resolves `..` segments before glob matching, preventing directory traversal escapes.
92
-
93
- ## Archive convention
94
-
95
- When archiving terminal artifacts, prefer the `docs.archive` umbrella command over individual `rfc.archive`, `adr.archive`, `plan.archive`, `audit.archive`, `session.archive`, `mission.archive` commands. The umbrella command runs all six in sequence and prevents leaving audits/plans/sessions/missions unarchived when the operator's intent is to clean up all terminal artifacts. Use individual commands only when the operator explicitly asks for a single domain (e.g. "archive only RFCs").
96
-
97
- - **RFC-0711: `docs.archive` post-loop `spec.live.merge` step.** After archiving, `docs.archive` scans implemented RFCs with a `liveSpec` frontmatter field and calls `spec.live.merge` for each, creating or updating living feature specs under `docs/specs/live/<domain>.md`. Rejected RFCs with `liveSpec` are skipped. Merge failures are non-fatal — the archive step still completes. Use `--dry-run` to preview merges without writing. Expect `docs/specs/live/*.md` modifications in the same dirty tree as archive moves — commit them together.
98
-
99
- - **`rfc.validate --root <file>` does NOT scope validation to a single file.** It validates ALL RFCs in the repo regardless of the `--root` flag. To check specific RFCs, use `--json` with `2>/dev/null` (log lines go to stderr) and filter the `data.violations[]` array by `rfcId`. Discovered during RFC-1035–1038 gap analysis.
100
- - **`rfc.archive` does NOT accept `--id`.** It archives ALL terminal-status RFCs at once. Available flags: `--dry-run` (preview), `--status <status>` (filter by status). Use `--dry-run` first to verify which files will move. Discovered during RFC-1038 archiving.
101
- - **Post-rename cleanup for `fs.rename` on watched directories:** When an archive handler uses `fs.rename` to move a directory that an IDE or file watcher is tracking (e.g. mission workpiece with an open `.astro/` cache), the watcher may recreate stale cache at the source path after the rename completes. Always add a post-rename cleanup check using `trashPath` from `utils/fs-trash.ts`: `if (existsSync(sourcePath)) { await trashPath(sourcePath); }` after the `fs.rename` call. See `os/mission/handlers/archive.ts` `moveMissionDir` for the reference implementation.
102
-
103
- ## Pinned-files protection (RFC-0733)
104
-
105
- The pinned-files protection system prevents accidental deletion, move, or modification of foundational files (templates, configs, structural directories). It is opt-in — protection is active only when `.forge/pinned.yaml` exists.
106
-
107
- - **`forge pinned.init`** creates `.forge/pinned.yaml` with default foundation entries, installs a pre-commit hook, adds `.forge/pinned-audit.log` to `.gitignore`, and optionally generates a CI workflow (`--ci`). Re-running merges defaults with existing entries — operator-removed default entries are re-added, but custom entries are never overwritten or removed.
108
- - **`forge pinned.validate`** checks the working tree against the manifest. In `staged` mode (default), it checks `git diff --cached`; in `ci` mode (`--mode ci`), it checks the last-commit diff. Violations for `delete` and `move` operations are always blocked; `modify` is blocked only for `freeze` mode entries (not `protect`).
109
- - **Override:** Use `--allow-pinned-override <path>` for an audited escape hatch. Each override is logged to `.forge/pinned-audit.log` (append-only, gitignored) with timestamp, path, mode, and reason. The `FORGE_PINNED_OVERRIDE` env var (comma-separated paths) is also read by `pinned.validate` — this allows the pre-commit hook to support overrides without changing the hook script: `FORGE_PINNED_OVERRIDE=docs/rfcs/rfc-0076.md git commit`.
110
- - **Manifest integrity:** `pinned.validate` compares the current manifest against the last-committed version. If entries have been removed, it reports `PINNED_MANIFEST_TAMPERED`.
111
- - **Archive pre-check:** All 6 archive handlers (`rfc.archive`, `adr.archive`, `plan.archive`, `audit.archive`, `session.archive`, `mission.archive`) load the pinned manifest once per invocation and skip pinned files/directories with a warning instead of moving them. When the manifest is missing, archive handlers behave as before (protection inactive). **Intra-directory moves are exempted:** if both source and destination are within the same pinned directory (e.g. `docs/rfcs/rfc-0076.md` → `docs/rfcs/archive/implemented/rfc-0076.md`), the move is allowed — the file hasn't left the protected directory.
112
- - **`.forge/` directory:** The `.forge/` directory is a forge-specific convention for project-local governance files. It sits alongside `forge.yaml` and contains `pinned.yaml` (manifest) and `pinned-audit.log` (override audit trail).
113
-
114
- ## Agent-safety scripts in profiles (RFC-1019)
115
-
116
- All Forge stack profiles include portable agent-safety scripts as embedded file content blocks. These scripts protect AI agents from destructive git operations and enforce session-end protocol.
117
-
118
- - **`scripts/git-guard.sh`** — shell function intercepting `git stash`, `git reset --hard`, `git checkout --`, `git checkout -f`, `git switch -f`, `git clean -f`, `git restore`. Override: `ALLOW_DESTRUCTIVE_GIT=1`. Uses `FORGE_GIT_GUARD` marker (not `WERKSTATT_GIT_GUARD`).
119
- - **`scripts/setup-git-guards.sh`** — auto-detects shell (zsh → `~/.zshenv`, bash → `~/.bashrc`) and installs git-guard.sh source line. Supports `install`, `--verify`, `--remove` modes.
120
- - **`scripts/clean-stale-stashes.sh`** — detects and optionally drops stale git stash entries. Report mode (`--drop` to clean, `--drop-all` for all).
121
- - **`scripts/check-clean-trees.sh`** — universal dirty-tree checker. Finds all `.git` directories up to 3 levels deep and checks each for dirty state.
122
- - **`hooks/pre-user-prompt.sh`** — session-end protocol enforcement + stale-stash detection + git-guard verification. Requires `jq`. Exits with code 2 on session-end trigger phrases to inject protocol instructions.
123
- - **`hooks/pre-user-prompt-wrapper.mjs`** — Node.js cross-platform wrapper called by `.windsurf/hooks.json`. Detects bash availability, prints one-time warning if bash not found (Windows without Git Bash), then delegates to `hooks/pre-user-prompt.sh`.
124
- - **`.windsurf/hooks.json`** — Windsurf hook registration for `pre_user_prompt`, calls `node $ROOT_WORKSPACE_PATH/hooks/pre-user-prompt-wrapper.mjs`.
125
- - **PREFERENCES.md** generated by `forge init` includes `formOfAddress` field and operational rules: plan confirmation vs implementation, skill invocation tracking, commit granularity, session-end protocol.
126
-
127
- ## Skills
128
-
129
- Skills live in `skills/` and are synced to `.agents/skills/` by `create`. Each skill has a `SKILL.md` with standardized frontmatter (name, description, category, concerns, dependsOn).
130
-
131
- - **When editing a skill in `packages/forge/skills/`**, the synced copy in `.agents/skills/<name>/SKILL.md` MUST also be committed in the same session — `create` is not run automatically after manual edits. Stale `.agents/skills/` copies cause `doctor` to report drift.
132
- - **Canonical sync path is flat**: `.agents/skills/<name>/SKILL.md` (e.g. `.agents/skills/fo-idea-implement/SKILL.md`). Both `create` (`init.ts`) and `upgrade` (`upgrade.ts`) sync to this flat path. A nested `.agents/skills/fo/<name>/SKILL.md` path is NOT created or maintained by forge — it is a stale artifact if present and should be removed.
133
- - **`FORGE_SKILLS[].path` is relative to the forge package root** and already includes the `skills/` prefix — resolve via `path.join(forgeRoot, skill.path)` (see `init.ts`). Never join a `skillsRoot` with `skill.path`: that produces a doubled `skills/skills/` prefix and silently finds nothing.
134
- - **When renumbering steps in SKILL.md files** (inserting or removing a numbered step), grep for hard-coded step numbers across all `.md` files in the repo. Cross-references to `fo-idea-implement` step numbers exist in `PREFERENCES.md`, `fo-doc-audit/SKILL.md`, and `fo-session-retro/SKILL.md` — these break silently when steps shift. Always update all cross-references in the same commit.
135
-
136
- The `concerns` field uses a four-level taxonomy (RFC-0523): `read-only` (no file modifications), `document-only` (modifies `.md` files only), `content-mutation` (modifies content `.md`/`.yaml` but not executable code), `code-mutation` (modifies `.ts`/`.astro` code). `skill.validate` enforces this via SKILL-12.
137
-
138
- The optional `knowledge` field (RFC-0524) declares cumulative knowledge files as an array of file names relative to the SKILL.md directory (e.g. `knowledge: [qa-log.md, learned-principles.md]`). `skill.validate` enforces SKILL-13: declared knowledge files must exist. `create` syncs them to `.agents/skills/`. `doctor` detects stale copies. See `writing-great-skills` § Cumulative knowledge pattern for the three-layer reference pattern, entry format, and mutation contract. RFC-0660 adds SKILL-19 (entry schema validity) and SKILL-20 (identifier uniqueness) for structured knowledge entries, and `doctor` reports legacy-section counts. RFC-0661 adds SKILL-21 (hot/warm layer character budget warnings — warnings only, never build gates) and `doctor` reports budget summaries with headroom %.
139
-
140
- ### Validator return-type refactoring
141
-
142
- When refactoring a validator's return type (e.g. from `Violation[]` to `{ errors, warnings }`), update **all** return points and call sites in the same commit. TypeScript catches missing fields in return objects, but does not catch semantic errors like warnings accidentally left in the violations array. After refactoring, search for all `return` statements and all call sites that destructure the result, and verify each one handles both `errors` and `warnings` correctly.
143
-
144
- ### Skill packs (RFC-0539)
145
-
146
- Project-declared skill packs allow projects to manage their own skills under a project-specific prefix, separate from forge's portable `fo-` skills. Packs are declared in `forge.yaml` under `skillPacks`:
147
-
148
- ```yaml
149
- skillPacks:
150
- - prefix: wg
151
- dir: packages/warpgogol-skills/skills
152
- ```
153
-
154
- - `create` syncs pack skills alongside forge skills into `.agents/skills/`.
155
- - `skill.validate` validates pack skills with SKILL-01..13 plus SKILL-14 (pack skill name must start with pack prefix), SKILL-15 (non-forge skill may not use `fo-` prefix), and SKILL-17 (no platform RFC/ADR ids or platform names).
156
- - SKILL-07 enforces asymmetric dependency direction: pack skills may depend on forge skills, but forge skills may not depend on pack skills (breaks portability).
157
- - `skill.list` includes pack skills with `pack:<prefix>` annotation.
158
- - `doctor` checks for stale/missing pack skill copies and validates `skillPacks` config (unique prefixes, unique dirs, no `fo` prefix, dir exists).
159
- - **RFC-0552:** `create` (via `runInit`) and `upgrade` (via `syncPackSkills`) detect pack skills whose name conflicts with a Forge skill name. Conflicting pack skills are skipped (not copied to `.agents/skills/`) and reported in `skippedSkills` on `InitResult` and `UpgradeResult`. The `forge-bootstrap` skill reports skipped skills to the operator during onboarding. The `forge-bootstrap` skill also runs `git init` for greenfield projects without a `.git` directory and commits synced skills to git.
160
-
161
- ## Import rules
162
-
163
- - `src/` must NOT import from `@warpgogol/werkstatt-engine` or any kernel package.
164
- - `os/compass/` and `os/werkstatt/` are fully autonomous (RFC-0556) — all handlers are inlined in `os/*/handlers/` and must NOT import from `@warpgogol/*` packages.
165
- - Other `os/` modules MAY dynamically import `@warpgogol/*` packages where kernel integration is needed.
166
- - Apps import forge modules from `@warpgogol/forge` (the package entrypoint re-exports all OS modules).
167
- - **MUST** use `hasGeneratedMarker()` from `utils/index.ts` for detecting generated file markers — never use raw `content.includes("GENERATED")` which is fragile and breaks if the marker format changes.
168
- - **Compass shared flags:** New flags for compass commands MUST be added to the shared `compassScanFlags` object in `os/compass/compass.module.ts`, not to individual command definitions. The `compassScanFlags` object is spread into all compass commands that use `flags: { ...compassScanFlags }`, ensuring the flag is available consistently across the command family. Per-command flags that are unique to one command may be defined inline.
169
- - **CLI flags must be wired to behavior.** Every flag declared in a command registration MUST affect the command's output or behavior — not just be read and stored. A flag that is read but never used is dead code and a contract violation. When adding a flag, implement its behavioral effect in the same commit. Verify by searching for the flag variable name in the handler function body.
170
- - **Profile-driven workspace detection is domain-neutral.** `workspaceTypes` from a stack profile must replace hardcoded workspace detection for ALL domains, not just software. Do NOT gate `checkNestedAgentsMd` or `discoverWorkspaces` by `isSoftwareDomain` — that silently skips the check for non-software domains (game, creative, etc.). When `workspaceTypes` is present, it fully replaces hardcoded detection; when absent, hardcoded detection is the fallback for all domains.
171
- - **`command-registered` probes MUST fall back to command manifest.** The `command-registered` probe in `os/rfc/acceptance.ts` uses `commandRegistry?.listCommands()`, which only sees workspace-scoped commands (forge modules). App-scoped commands from `werkstatt-site/checks` are invisible to the workspace-level registry. Always include a `loadManifestCommandNames(workspaceRoot)` fallback, matching the pattern already used in `os/rfc/handlers/lifecycle.ts`. Without this, `rfc.acceptance.run` and `rfc.verification.emit` will falsely report app-scoped commands as "not registered".
172
-
173
- ## RFC frontmatter: commands.changed (RFC-CMD-03)
174
-
175
- The `commands.changed` field in RFC frontmatter must only list **registered CLI commands** (e.g. `compass.audit.baseline`, `mission.materialize`), not internal functions or handlers (e.g. `acquireLock`, `releaseLock`). `rfc.validate` enforces this via RFC-CMD-03: every entry in `commands.changed` must match a live command in the registry. Internal functions that are not registered as CLI commands must not appear in `commands.changed` — use `packagesImpacted` to indicate which packages were modified. The registry checked is the **werkstatt kernel registry**, not the standalone `forge` CLI — a command that works via `forge <cmd>` may still be unregistered in the kernel (e.g. `profile.validate` resolves to a different site-level command under `werkstatt run`). Verify registration via `werkstatt run <cmd>` or `docs/command-manifest.generated.yaml` before listing.
176
-
177
- ## RFC frontmatter: YAML backtick quoting
178
-
179
- YAML plain scalar values that **start with a backtick** (`` ` ``) must be double-quoted. Backtick is a reserved character in YAML plain scalars — the parser fails with "Plain value cannot start with reserved character `" and `rfc.implement.stamp`reports "Could not parse target RFC" (RFC-IMP-01). This commonly affects`successSignals`, `nonGoals`, and other list items in RFC frontmatter that reference code identifiers in backticks. Always quote such strings: `` - "`doctor`reports domain information" `` instead of `` -`doctor` reports domain information ``.
180
-
181
- **Agent action:** After creating an RFC with `rfc.create`, scan the generated `successSignals` and `nonGoals` sections for unquoted backtick entries. Fix them immediately before committing. This prevents a recurring pattern where `ecosystem.manifest.generate` and `rfc.implement.stamp` fail on RFCs created with backtick-heavy frontmatter.
182
-
183
- **Diagnostic:** If `rfc.implement.stamp` fails with `Could not parse target RFC` (RFC-IMP-01), the RFC frontmatter has a YAML syntax error — not a missing file. Check for unquoted backtick values first.
184
-
185
- ## RFC command lifecycle validation (RFC-CMD-02)
186
-
187
- `getLiveCommands` in `os/rfc/handlers/lifecycle.ts` always merges `commandRegistry.listCommands()` with `docs/command-manifest.generated.yaml`. This is necessary because lazy-loaded modules (e.g. `leitstand`) are not loaded when `rfc.validate` runs, so their commands are absent from the registry but present in the manifest. Never change this to a fallback-only pattern (using manifest only when registry is empty) — that produces false-positive `RFC-CMD-02` violations for commands from lazy-loaded modules.
188
-
189
- **After registering new commands in `tools/kernel.config.ts`, always run `command.manifest.generate` before `rfc.implement.stamp` AND before `rfc.verification.emit`.** Without this, `docs/command-manifest.generated.yaml` is stale and `rfc.validate` fails with RFC-CMD-02 ("implemented RFC lists X under commands.added, but no live command is registered"). The manifest is the source of truth for lazy-loaded command discovery. The `command-registered` acceptance probe in `rfc.verification.emit` resolves commands via `getLiveCommands` (registry + manifest merge) — a newly registered command missing from the manifest fails the probe with "not registered" even though `werkstatt run <cmd>` works. Discovered during RFC-1097 stamping.
190
-
191
- **The same manifest regen is mandatory for commands added inside an existing module's `commands[]` array** (e.g. `os/core/core.module.ts`) — no `kernel.config.ts` change is needed for those, but the probe still resolves via the manifest. Also rebuild `packages/forge/dist` (`pnpm run build`) when the standalone `forge` CLI or a dist-loading consumer must see the new command — `bin/cli.js` prefers `dist/` when present, and a stale dist silently shadows `src/` (the `dist-freshness` doctor check, RFC-1151, warns on exactly this). Discovered during RFC-1151: `memory.compact` failed the `command-registered` probe until the manifest was regenerated.
192
-
193
- ## RFC status transitions: rfc.implement.stamp is exclusive (V-16)
194
-
195
- `rfc.implement.stamp` is the **exclusive atomic path** for accepted → implemented transitions. It atomically sets `status: implemented`, `implementedAt`, and `updatedAt` together. **NEVER** manually edit RFC frontmatter to set `implementedAt` or change `status` to `implemented` — this bypasses the atomic guarantee and risks leaving `status` and `implementedAt` out of sync. V-16 enforces this as an error: `status: accepted/draft` with `implementedAt` set, or `status: implemented` with empty `implementedAt`, both fail `rfc.validate`. After implementing an RFC, run `rfc.implement.stamp --id RFC-XXXX` to stamp it (auto-detects the implementation commit via `git log --grep` when `--implementation-commit` is omitted, RFC-0756; pass `--implementation-commit <sha>` to override). **`--implementation-commit` takes a git SHA, not the version printed by `ecosystem.commit`** — passing `6.316.121` fails RFC-IMP-03 ("not reachable from HEAD"). Resolve the SHA via `git log --oneline --grep="<message>"`. Discovered during RFC-1139 stamping.
196
-
197
- ## RFC acceptance criteria: evidence annotation (RFC-IMP-02)
198
-
199
- `rfc.implement.stamp` enforces RFC-IMP-02: every checked acceptance criterion (`- [x]`) MUST have an inline `(evidence: ...)` annotation. Parenthetical references without the `evidence:` keyword (e.g. `(promote.ts, 13 tests)`) do NOT satisfy the rule — the stamp fails with "checked criteria lack inline (evidence: ...) annotation". Always format as: `- [x] <criterion text> (evidence: <file paths, commands, or test counts>)`. Commit the annotated criteria before running `rfc.implement.stamp`.
200
-
201
- ## RFC acceptance probes: criterion binding and coverage (RFC-0997)
202
-
203
- RFC-0997 binds acceptance probes to criteria via the `criterion: "AC-N"` field and adds three validation rules for post-cutoff RFCs (createdAt >= `2026-09-01`):
204
-
205
- - **V-35**: every probe SHALL declare `criterion` referencing an existing `AC-N` id. Missing, malformed, or dangling `criterion` is a blocking error.
206
- - **V-36**: every top-level checklist line (`- [ ]` / `- [x]`) in `## Acceptance criteria` SHALL start with a unique `AC-N:` identifier. Duplicate or missing identifiers are blocking errors.
207
- - **V-37**: checked criteria evidence SHALL resolve — `probe:AC-N` must reference a criterion with at least one bound probe; `test:<path>` and `<path>:<line>` must reference an existing file. **Evidence annotations MUST NOT contain em-dashes (—) or nested quotes** — the V-37 parser breaks on `test: path — "description"` and reports the file as non-existent. **The `<path>` token MUST be the file path only — no AC-N suffixes, no descriptions, no extra text after the path.** The parser treats everything after `test:` until end-of-parenthesis as the file path; `test: packages/forge/os/rfc/file.test.ts AC-1` is reported as non-existent because the parser looks for a file named `packages/forge/os/rfc/file.test.ts AC-1`. Use simple `(evidence: test:packages/forge/src/tests/file.test.ts)` without em-dashes, nested quotes, or AC-N suffixes. Discovered during RFC-0998 and RFC-0999.
208
- - **RFC-IMP-08**: `rfc.implement.stamp` blocks stamping for post-cutoff RFCs of kind `architecture`, `contract`, or `command` that declare zero acceptance probes. Policy and deprecation kinds are exempt.
209
- - **Coverage report**: `rfc.validate --json` and `rfc.acceptance.run` emit a non-blocking `coverage` block per post-cutoff RFC with `totalCriteria`, `probeBackedCriteria`, `coverageRatio`, `uncoveredCriteria`, `unboundProbes`.
210
- - **`file-contains` probe `pattern` is RegExp, not literal.** The `file-contains` acceptance probe compiles its `pattern` field via `new RegExp(pattern, "m")`. Parentheses, brackets, dots, and other regex metacharacters MUST be escaped (e.g. `\\(RFC-1023\\)` not `(RFC-1023)`). Unescaped parentheses silently fail to match and produce false "pattern not found" results. Discovered during RFC-1023 verification.
211
- - **YAML escape sequences in `file-contains` probe patterns.** When a `pattern` field contains regex escapes like `\\*`, double-quoted YAML strings produce a YAML parse error ("Invalid escape sequence \\*"). Use single-quoted YAML strings for patterns containing backslash escapes: `pattern: '1 \\* 1024'` instead of `pattern: "1 \\* 1024"`. Single-quoted YAML treats backslashes literally. Discovered during RFC-1091 stamping.
212
- - **`file-contains` probe must match source code, not computed values.** When a probe checks for a numeric constant, the pattern must match the literal source expression (e.g. `1 \\* 1024 \\* 1024 \\* 1024`), not the computed result (e.g. `1073741824`). The probe runs `new RegExp(pattern).test(fileContent)` against source text — it cannot evaluate expressions. Discovered during RFC-1091 AC-9 probe.
213
-
214
- ## RFC criteria content rules: phase separation, reject checklist, criterion versioning (RFC-1006)
215
-
216
- RFC-1006 adds five validation rules for post-cutoff RFCs and ADRs (createdAt >= `2026-09-03`):
217
-
218
- - **V-38**: `accepted`/`implemented` RFCs with unchecked `DR-N` items in `## Document readiness` section are blocking errors. Document readiness criteria (`DR-N`) are separated from system conformance criteria (`AC-N`).
219
- - **V-39**: acceptance criteria containing `SHALL ... and ...` joining two verb phrases are non-atomic — split into separate criteria.
220
- - **V-40**: acceptance criteria containing unbounded quantity triggers (`fast`, `scalable`, `low latency`, etc.) are blocking errors — state a specific number.
221
- - **V-41**: acceptance criteria containing weasel verbs (`handle gracefully`, `robust`, `works correctly`, etc.) are blocking errors — replace with a specific observable behavior.
222
- - **V-42**: malformed criterion supersession annotations (`> Superseded AC-N (YYYY-MM-DD): <reason>`) are blocking errors. Superseded criteria are excluded from the unchecked count.
223
-
224
- V-39..V-41 also apply to post-cutoff `implemented` ADRs via `adr.validate`. Pre-cutoff RFCs and ADRs are exempt. The reject checklist is conservative — it uses closed trigger lists, not semantic analysis. See `packages/forge/skills/fo/fo-idea-create-rfc/acceptance-criteria-standard.md` for the canonical authoring guide.
225
-
226
- - **Section extractors in `validate-rules.ts` MUST call `stripFencedCodeBlocks(body)` before regex-matching markdown sections.** RFC documents contain fenced code blocks with example headings and checklists. Without stripping, extractors like `extractDocumentReadinessSection` and `extractAcceptanceCriteriaSection` match headings inside code blocks, producing false-positive validation errors (e.g. V-38 reporting unchecked criteria from a code block example). The `stripFencedCodeBlocks` helper removes all ` ```...``` ` blocks before extraction. Any new section extractor added to `validate-rules.ts` must follow this pattern.
227
-
228
- ## Re-entrant werkstatt locks (RFC-0616)
229
-
230
- `acquireLock` and `releaseLock` in `os/werkstatt/handlers/lock.ts` are re-entrant by PID. When the same process re-acquires a lock it already holds, `acquireLock` increments the `depth` counter instead of throwing. `releaseLock` decrements `depth` and only deletes the lock file when `depth` reaches `1` or is `undefined`. The `depth` field is `.optional()` in `werkstattLockSchema` — old lock files without `depth` parse successfully and are treated as `depth=1` via `?? 1` fallbacks. Agents MUST NOT assume `acquireLock` always throws on an existing lock file — it only throws when a **different** live process holds the lock.
231
-
232
- ## forge.yaml (RFC-0391)
233
-
234
- `forge.yaml` is the machine-readable project configuration file at the project root. It records project name, stack, package manager, and docs paths. `create` creates it; `doctor` checks for it; `forge.agents.generate` reads it to produce `AGENTS.md`.
235
-
236
- - **MUST NOT** run `forge.agents.generate` against this monorepo's root `AGENTS.md` — it is hand-written and carries no generated marker; the edit guard enforces this, do not bypass it.
237
- - **MUST NOT** re-add any `@warpgogol/*` import to `packages/forge` source — `doctor` autonomy guard will fail.
238
- - **MUST NOT** hand-edit a generated `AGENTS.md` in bootstrapped projects — edit `forge.yaml` and regenerate.
239
- - **MUST NOT** delete or "fix" an unresolvable `profile:` field to silence `doctor` (RFC-1118). The `profile-id-known` check fails when the declared id is absent from the installed `@warpgogol/forge` catalog — the remedy is `forge upgrade` (config ahead of pinned forge) or correcting the id, never removing the field. Re-serialization preserves the declared id verbatim; `forge init`/`create` never overwrite an existing `profile:` with a detection result.
240
-
241
- ## Stack profiles (RFC-0392)
242
-
243
- Stack profiles are YAML documents under `profiles/` describing a supported stack (detection markers, workspace layout, install steps, baseline files). `scaffold` creates a working pnpm + Turborepo monorepo from a chosen profile in an empty directory. The migration-adapter registry (RFC-0546) detects the stack of an existing project during `forge-bootstrap` transplant mode.
244
-
245
- - **MUST NOT** scaffold into a non-empty directory — no `--force` flag.
246
- - **MUST NOT** add stack profiles for stacks forge cannot scaffold end-to-end.
247
- - **MUST** reference all template files in `profiles/<profile>-templates/` from the profile YAML (`workspaceTypes[].agentsMdTemplate` or `firstWorkspace.files`) or document them in the `agentsMdTemplate` file. Unreferenced template files are orphan artifacts that operators cannot discover.
248
- - Shipped profiles: `typescript`, `phaser-game`, `godot-game`, `knowledge`, `forge-shell` (minimal — default for `create`), `site-workshop` (per-client Werkstatt workshops, RFC-1125).
249
- - **`site-workshop` token-onboarding contract (RFC-1125):** the profile scaffolds a Werkstatt workshop that installs private `@warpgogol/*` packages. `forge create` runs a non-interactive npm-token probe (`npm-token-check.ts`) **before** `pnpm install` — it fails fast with a fixHint when the token cannot fetch `@warpgogol/werkstatt-engine` (`.npmrc` `_authToken` or `NPM_TOKEN` env honored; never a `--npm-token` flag). `forge.doctor` re-runs the same probe post-install. The profile never scaffolds `systems-cache/` inside the workshop root — it is a sibling directory created on demand by `sternsystem.register`. `sternsystem.register` blocks until `werkstatt.identity.json` and a signing key exist (run `identity.bootstrap` first). `werkstatt.platform.update` bumps `@warpgogol/*` deps and reports `pinnedPlatform` drift.
250
- - **MUST** include a `.github/workflows/ci.yml` template in every stack profile's `workspace.files` list. The CI template MUST include `concurrency` (cancel superseded PR runs), `permissions: contents: read` at workflow level, `timeout-minutes` per job, `env: TZ: UTC` per job, `actions/checkout@v5`, and `actions/setup-node@v5` with Node 24. New projects inherit reliable CI from the scaffold — operators should not need to hand-write CI from scratch.
251
-
252
- ### Domain fields (RFC-0638)
253
-
254
- The `forge/stack-profile@1` schema includes six optional domain-neutral fields that allow a profile to declare its domain model. All fields are optional — existing profiles without them parse and function identically.
255
-
256
- - **`domain`** — string identifying the project domain (e.g. `software`, `game`, `book`, `music`, `illustration`). Used for profile detection and doctor output.
257
- - **`terminology`** — map of universal concept keys to domain-specific terms (e.g. `artifact: "game"`). Open vocabulary; universal keys have built-in defaults exported as `TERMINOLOGY_DEFAULTS`. Missing keys fall back to the default term.
258
- - **`artifacts`** — array of artifact definitions (id, extensions, produce/validate commands, determinism properties). Used by `doctor` for domain-specific health checks in follow-up RFCs.
259
- - **`workspaceTypes`** — array of workspace type definitions (id, detection markers, associated skills, AGENTS.md template). Used by `forge.agents.generate` for per-domain workspace detection in follow-up RFCs.
260
- - **`invariants`** — array of domain-specific invariant definitions (id matching `^[A-Z]+-\d+$`, rule text, severity). Schema only — enforcement is deferred to follow-up RFCs.
261
- - **`register`** — string selecting the default behavioral register (`business` or `creative`). Used by `create` as a one-time default for new projects; existing `PREFERENCES.md` is never overwritten.
262
-
263
- Types and schemas are exported from `@warpgogol/forge`: `StackProfileDomainFields`, `ProfileArtifact`, `ProfileWorkspaceType`, `ProfileInvariant`, `stackProfileDomainFieldsSchema`, `UNIVERSAL_TERMINOLOGY_KEYS`, `TERMINOLOGY_DEFAULTS`.
264
-
265
- ### Domain-aware commands (RFC-0640)
266
-
267
- The following commands are domain-aware — they read domain fields from the stack profile and `forge.yaml` to adapt their behavior:
268
-
269
- - **`profile.validate`** — validates profile YAML files under `packages/forge/profiles/` against the `forge/stack-profile@1` schema (including RFC-0638 domain fields). Supports `--id <profile-id>` to validate a single profile. Returns exit 1 if any profile is invalid.
270
- - **`create`** — reads `domain`, `terminology`, `register`, and artifact-derived semantic bindings from the selected profile and writes them into `forge.yaml` (domain, terminology, bindings.commands) and `PREFERENCES.md` (register). When the profile has no domain fields, behavior is unchanged (software-domain fallback).
271
- - **`doctor`** — reports domain info (domain, source, register, terminology, invariant count) as a `domain-info` check. Enforces profile invariants via the invariant engine as a `domain-invariants` check (RFC-0675) — invariants with a `check` declaration are actively verified (`filename-pattern`, `file-contains`, `file-not-contains`, `attribute-pattern`); invariants without `check` remain advisory. The `attribute-pattern` check kind (RFC-0694) validates attribute values on elements matching a tag selector — requires `elements` (array) and `attribute` fields (schema-enforced via `.refine()`). Reports `fail` for error-severity violations, `warn` for warning-severity. The `--strict` flag elevates `warn` to `fail` for `domain-invariants` and `profile-validate` checks. `--json` includes `invariantViolations` array in the `domain-invariants` check. Runs `profile.validate` as an advisory `profile-validate` check (warn status on failure, not gating — shipped profiles are forge-internal). Nested AGENTS.md check runs for all domains — profile-driven workspace types replace hardcoded detection when present. Domain is resolved via a three-tier chain: `forge.yaml` `project.domain` → stack profile `domain` → default `software`.
272
- - **`forge.agents.generate`** — loads `workspaceTypes[]` from the matching stack profile and passes them to `discoverWorkspaces` for profile-driven workspace type detection. When the profile has no `workspaceTypes`, falls back to hardcoded detection (astro.config → app, Dockerfile → service, else package).
273
-
274
- ### Per-domain AGENTS.md templates (RFC-0643)
275
-
276
- `forge.agents.generate` uses profile terminology and register to produce domain-appropriate AGENTS.md files. When no profile is loaded (or the profile has no domain fields), output is identical to the pre-RFC-0643 implementation — no regression for existing software-domain projects.
277
-
278
- - **Root AGENTS.md templates**: Static prose (header, project section, paths section, conventions) is extracted to template files at `src/onboarding/templates/root-agents-business.md` and `root-agents-creative.md`. `selectRootTemplate(register)` returns the appropriate template. Dynamic sections (skills table, capabilities, behavioral layer) remain inline and are inserted at the `{{dynamicSections}}` marker.
279
- - **Nested AGENTS.md templates**: `selectNestedTemplate(workspaceType, profile, terminology, fallback)` reads `workspaceTypes[].agentsMdTemplate` from the profile. Template paths are relative to `packages/forge/profiles/`. Absolute paths and parent-directory traversal (`..`) are rejected with a silent fallback to the hardcoded template.
280
- - **Terminology substitution**: `substituteTemplate(content, terminology)` replaces `{{terminology.key}}` placeholders with resolved values. Runs on the final assembled content (after dynamic sections are appended), so the behavioral layer's fixed policy text also receives terminology substitution. Unknown keys resolve to the key name itself — no error.
281
- - **`{{terminology.key}}` placeholder syntax**: AGENTS.md templates use `{{terminology.key}}` (double-brace), not `ref(bindings.terminology.key)` (skill syntax). The two are documented separately.
282
- - **`details` field in `--json` output**: `AgentsGenerateResult` includes an optional `details` array with per-file metadata: `{ path, domain?, register?, workspaceType? }`. The `generated` field remains `string[]` for backward compatibility.
283
- - **`profile` field in `forge.yaml`**: `create` writes `profile: <id>` to `forge.yaml`. `loadForgeConfig` loads the corresponding `profiles/<id>.yaml` and attaches it as `config.profile` (a `StackProfile` object). The profile object is stripped before serialization — `forge.yaml` stores the profile id (string), not the full profile.
284
- - **Template comments MUST NOT use literal `{{placeholder}}` syntax**: `replaceProjectPlaceholders()` runs on the entire template content, including HTML comments. A comment like `<!-- inserted at {{dynamicSections}} -->` will have the placeholder replaced with the full dynamic sections content, breaking the comment and inflating the output. Use plain text names (e.g. `dynamicSections marker`) in comments instead of `{{...}}` syntax.
285
- - **All template content MUST be external files, not inline `lines.push()` string arrays.** Fixed prose and policy text in forge generators (e.g. `agents-generate.ts`, `nested-agents-templates.ts`) must live in `.md` template files under `src/onboarding/templates/` or `profiles/`, loaded via `fs.readFileSync` with placeholder substitution. Inline `lines.push("### Section heading")` patterns for fixed text are a contract violation — they embed template content in source code, making it harder to review and maintain. Dynamic, data-driven content (tables generated from registry data, conditional sections from config) remains inline.
286
- - **Template files read at runtime via `fs.readFileSync` MUST be listed in `package.json` `files` array.** TypeScript compilation (`tsc`) does not copy `.md` template files to `dist/`. Without an explicit `files` entry, template files exist on disk in development but are missing from the published npm package — the generator silently falls back to empty content. The test `src/tests/package-files.test.ts` guards this: it verifies that `src/onboarding/templates/` is in the `files` array and that all expected template files exist and are readable.
287
- - **Profile object stripping before YAML serialization**: `loadForgeConfig` attaches a full `StackProfile` object to `config.profile`. Before serializing the config back to YAML (e.g. in `create` post-processing), the profile object MUST be stripped back to its string id. Otherwise `forge.yaml` contains an object instead of a string and fails schema validation on re-read.
288
- - **Profile invariant `rule` fields containing colons MUST be double-quoted.** YAML plain scalars with colons (e.g. `rule: mode attribute must be one of: sequence, fixed, contain, fit`) cause "Nested mappings are not allowed in compact mappings" parsing errors. Always quote rule fields that contain colons: `rule: "mode attribute must be one of: sequence, fixed, contain, fit"`. This also applies to any other YAML string field in profile YAML that may contain colons.
289
-
290
- ## Bindings contract (RFC-0393)
291
-
292
- The `bindings` section in `forge.yaml` de-hardcodes project-specific values from fo-skills. Skills reference bindings by key (e.g. `ref(forge.yaml bindings.commands.validateRfc)`) instead of hardcoding commands, paths, or terminology.
293
-
294
- - `forgeBindingsSchema` + `resolveBinding(config, key, placeholders?)` are exported from `@warpgogol/forge`.
295
- - `doctor` validates bindings: checks path existence, reports resolved/absent/invalid, and emits `defaultable-binding-null` notices for forge-CLI-backed bindings that are null (RFC-0540).
296
- - `create` writes forge-CLI-backed defaults for commands forge provides (`validateRfc`, `validateAdr`, `implementStamp`, `specValidate`) and null for stack-dependent commands (`typecheck`, `test`, `scopedBuild`). The package manager from `forge.yaml` determines the runner prefix (`pnpm exec`, `npx`, `yarn exec`, `bunx`).
297
- - `skill.validate` enforces SKILL-11: canonical skill bodies must not contain hardcoded `pnpm exec werkstatt run` or `docs/architecture-dna.md` in instruction lines (code blocks and `run:` directives). Supports `<!-- skill-lint-disable SKILL-11 -->` escape hatch.
298
- - `skill.validate` enforces SKILL-17: skill files must not contain specific platform RFC/ADR ids (`RFC-\d{4}`, `ADR-\d{4}`) or platform names ("Warpgogol", "Warpgogol", "WarpGogol"). Generic "RFC"/"ADR" terms, generic placeholder ids (`RFC-XXXX`), file paths (`adr-0000-template.md`), and binding key names (`validateRfc`) are allowed. The `@warpgogol/forge` npm package name is excluded from the platform name check. Supports `<!-- skill-lint-disable SKILL-17 -->` escape hatch.
299
- - `skill.validate` enforces SKILL-18: canonical forge skill bodies must not reference software-specific binding keys (`bindings.commands.typecheck`, `bindings.commands.scopedBuild`, `bindings.commands.test`) in instruction lines (code blocks and `run:` directives). Skills must reference semantic keys (`bindings.commands.validate`, `bindings.commands.produce`, `bindings.commands.verify`) instead. Supports `<!-- skill-lint-disable SKILL-18 -->` escape hatch. Applies to forge skills only, not pack skills.
300
- - Skills declare binding requirements in frontmatter: `bindings: { requires: [...], optional: [...] }`.
301
- - Degradation contract: required binding unresolvable → skill refuses to start; optional binding absent → step skipped with `Degraded:` line in report.
302
- - **RFC-0609: Binding templates must use flag format.** CLI binding templates in `FORGE_CLI_BINDING_DEFAULTS` and `forge.yaml` must use `--id {id}` (flag format), not `{id}` (positional). For example: `forge rfc.validate --id {id} --json`, not `forge rfc.validate {id} --json`. This applies to `validateRfc`, `validateAdr`, and any future binding that passes an identifier to a command.
303
-
304
- ### Semantic command keys (RFC-0639)
305
-
306
- The `forge/bindings@1` schema includes five optional semantic command keys that work across all domains. These coexist with the software-specific keys (`typecheck`, `test`, `scopedBuild`) — they do not replace them.
307
-
308
- - **`commands.validate`** — domain-neutral validation command (replaces `typecheck` for non-software domains).
309
- - **`commands.produce`** — domain-neutral artifact production command (replaces `scopedBuild`).
310
- - **`commands.verify`** — domain-neutral verification command (replaces `test`).
311
- - **`commands.preview`** — domain-neutral preview command (e.g. dev server, live preview).
312
- - **`commands.lint`** — domain-neutral linting command.
313
-
314
- All semantic keys are optional with `null` defaults. `applyCliBindingDefaults` initializes them with `null` (they are stack-dependent, not CLI-backed). `doctor` does **not** validate semantic keys — they are opt-in per-domain, so reporting them as `absent` for projects that intentionally leave them `null` would be noise. Skills reference them via `ref(bindings.commands.produce)` etc.
315
-
316
- ### Terminology resolution (RFC-0639)
317
-
318
- The `terminology` field in `forge/bindings@1` is non-optional with a `{}` default (changed from `.optional()` in RFC-0639). `resolveTerminology(config, terminology, key)` resolves a terminology key using a three-tier chain:
319
-
320
- 1. **Tier 1 — bindings override**: `config.bindings.terminology[key]` (per-project).
321
- 2. **Tier 2 — caller-provided**: the `terminology` parameter (typically `profile.terminology` from RFC-0638).
322
- 3. **Tier 3 — universal default**: `TERMINOLOGY_DEFAULTS` from `@warpgogol/forge` (re-exported from `profile-schema.ts`).
323
-
324
- If the key is not found in any tier, the key itself is returned. The `terminology` parameter is `Record<string, string> | undefined` — a separate parameter, not embedded in `StackProfile` — so the function works whether or not RFC-0638 profile terminology is available.
325
-
326
- `resolveTerminology` is exported from `@warpgogol/forge` and `@warpgogol/forge/config`.
327
-
328
- ## Output contract (RFC-0542)
329
-
330
- Every forge CLI command's output ends with a **Next steps** block in pretty mode and a `nextSteps` array in `--json` mode. Each entry is `{ action: string, kind: "required" | "optional" }`.
331
-
332
- - `renderNextSteps`, `renderIdeRecommendation`, and `generateHelp` are pure functions in `src/cli-output.ts` — importable by `bin/cli.ts` and unit tests.
333
- - `create` prints an IDE recommendation (Windsurf tested, alternatives without guarantee) after the Next steps block in pretty mode.
334
- - All forge CLI natural-language output is English regardless of `PREFERENCES.md` — `aiLanguage` governs agent chat, not the forge binary.
335
- - `printHelp` is generated from the registry via `generateHelp` — no hand-maintained command list. `--help <command>` prints per-command flags and description.
336
- - `ForgeNextStep` type and `nextSteps?` field are on `ForgeCommandResult` directly (cross-cutting), not inside command-specific `data`.
337
- - Lifecycle commands (`create`, `scaffold`, `doctor`, `port.scaffold`) MUST populate `nextSteps`. Pass-state validators MAY leave the array empty.
338
- - Future commands (`create`, `upgrade`) MUST conform to the `nextSteps` contract from day one.
339
- - Skill reports (agent chat output) use the operator's `aiLanguage` and contain zero CLI commands, guides, or format references in user-facing text. The system hides all complexity from the operator. CLI output remains English per RFC-0542; only the skill (agent chat) uses `aiLanguage`. The `forge-bootstrap` welcoming report is the canonical example of this contract.
340
-
341
- ## Silent upgrade trigger (RFC-0554)
342
-
343
- The `forge-bootstrap` skill step 0 silently checks `forge.syncedVersion` against the installed `@warpgogol/forge` version. If they differ, it runs `forge upgrade --update-npm` invisibly — the operator is never informed about migration, version numbers, or upgrade mechanics. The npm update is skipped automatically in monorepo environments (where `packages/forge/` exists). The `upgrade` CLI command remains available for manual sync (with or without `--update-npm`). This is not a dual-path: it is a single upgrade mechanism (`runUpgrade`) with two entry points (CLI and `forge-bootstrap`).
344
-
345
- ## Core behavioral layer (RFC-0548)
346
-
347
- `forge.agents.generate` now includes a **Core behavioral layer** section in generated `AGENTS.md` files. This section is wrapped in `<!-- forge:begin behavioral-layer -->` / `<!-- forge:end behavioral-layer -->` markers and contains:
348
-
349
- - **Intent-to-skill routing table** — generated from `triggers` fields in fo-skill frontmatter. Each row maps natural-language trigger phrases to the corresponding skill.
350
- - **Fixed policy text** for 20 core behavioral areas: auto-grilling, auto-session-save, auto-review, context awareness, creator-facing communication, adaptive learning, proactive guidance, live operator feedback, register parameter, pushback policy, external capabilities (MCP), safety net, invisible quality, first creation moment, creative health, sharing and feedback, cultural awareness, indirect teaching, ownership, and commit policy (RFC-0551).
351
- - **Conditional extended behavioral layer** (RFC-0549) — included only when the register is `creative` (read from `PREFERENCES.md` `register` field). Contains ten sections: personal connection, creative memory, emotional rhythm (questions not declarations), gentle accountability, creative partnership, visual thinking, audience empathy, creative companion (companion mode, `saveCompanionSessions` flag, pull-only inspiration feed), creative confidence (outcome-based praise, never refuse creative direction), and always-next-step (RFC-0551, supersedes the "at most one per session" anticipatory suggestion limit). Content is loaded from `src/onboarding/templates/behavioral-layer-extended.md`.
352
-
353
- `create` auto-runs `forge.agents.generate` after `forge.init`, so newly created projects get the behavioral layer from day one. If generation fails, a warning is logged but the create command continues.
354
-
355
- The `triggers` field in skill frontmatter is validated by SKILL-16: optional array of 1-5 natural-language strings (each 5-100 characters), only allowed on fo-category skills. Pack skills may not declare triggers.
356
-
357
- ## Nested AGENTS.md generation (RFC-0611)
358
-
359
- `forge.agents.generate` also generates nested `AGENTS.md` files for workspace directories (directories containing `package.json`). Workspace type is auto-detected by content markers:
360
-
361
- - **app** — directory with `astro.config.*`
362
- - **service** — directory with `Dockerfile` or `service.config.yaml`
363
- - **package** — directory with `package.json` only
364
- - Precedence: app > service > package
365
-
366
- Workspace-type detection rules are defined in RFC-0611. Agents MUST NOT add new detection rules without an amending RFC.
367
-
368
- The edit guard skips hand-written nested `AGENTS.md` files (no generated marker) and reports them in the `skipped` array. Generated files (with marker) are regenerated if content differs. `upgrade` also runs nested generation after skill sync. `doctor` checks for missing, stale (in-memory comparison), and hand-written improvement opportunities.
369
-
370
- `forge.agents.generate` supports `dryRun` mode (RFC-0601 pattern): it renders content in memory without writing to disk, returning `renderedFiles` in the result. This is used by `doctor` for staleness detection.
371
-
372
- - **Doctor stale check MUST use the same rendering pipeline as `forge agents generate`.** The stale check in `checkNestedAgentsMd` (`src/onboarding/doctor.ts`) must call `readPackageInfo` → `buildNestedAgentsMd(ws, config, packageInfo)` → `selectNestedTemplate(wsType, profile, terminology, fallback)` — exactly matching `generateNestedAgentsMd` in `src/onboarding/nested-agents-generate.ts`. Any divergence (missing `packageInfo`, missing `selectNestedTemplate`, missing `resolveAllTerminology`) causes false-positive stale reports for all generated nested `AGENTS.md` files. When modifying either function, verify the other stays in sync.
373
-
374
- ## Extended behavioral layer (RFC-0549)
375
-
376
- The extended behavioral layer is conditionally included in generated `AGENTS.md` files when the operator's register is `creative`. It adds ten behavioral policies additive to the core layer:
377
-
378
- 1. **Personal connection** — operator name at key moments, project story, deep purpose as compass.
379
- 2. **Creative memory** — unimplemented ideas, aesthetic preferences, creative influences.
380
- 3. **Emotional rhythm** — session mood via questions (not declarations), return after break, progress celebration.
381
- 4. **Gentle accountability** — unfinished intentions, deep purpose checks.
382
- 5. **Creative partnership** — sounding board (2-3 alternatives), creative constraints, anticipatory suggestions.
383
- 6. **Visual thinking** — visual previews, visual diffs, milestone gallery, voice consistency, tone matching.
384
- 7. **Audience empathy** — audience perspective, first-visitor test, emotional memory, project narrative.
385
- 8. **Creative companion** — companion mode (`saveCompanionSessions` flag), creative blocks, inspiration feed (pull-only MVP, `inspirationFeed: on|off`).
386
- 9. **Creative confidence** — outcome-based praise (not effort-based), gentle purpose-drift pushback (never refuse creative direction).
387
- 10. **Always-next-step** (RFC-0551) — the agent MUST always propose a concrete next step after any pause point. Supersedes the "at most one anticipatory suggestion per session" limit from Creative partnership (section 5).
388
-
389
- Three surrogate-relationship mitigations: questions instead of declarations, outcome-based praise, and 90-day entry expiry for emotional observations in `operator-profile.md`.
390
-
391
- `fo-session-retro` routes extended-layer insights to `operator-profile.md` with Zugangsstufen tags: emotional rhythm → `[Vertraulich]` with 90-day expiry, aesthetic preferences → `[Öffentlich]`.
392
-
393
- ## RFC commands frontmatter (RFC-CMD-01..03)
394
-
395
- When an RFC transitions to `implemented`, `rfc.validate` enforces command lifecycle rules against the `commands:` frontmatter:
396
-
397
- - **RFC-CMD-01:** A live command listed under `commands.proposed` but not `commands.added` is a violation. For implemented RFCs, newly created commands MUST be in `commands.added`, not `commands.proposed`. `commands.proposed` is only valid for RFCs in `draft` or `accepted` status.
398
- - **RFC-CMD-03:** Every entry under `commands.changed` MUST be a registered live command (present in `docs/command-manifest.generated.yaml`). Pipeline names (e.g. `build.prepare`, `SITES_BUILD_PREPARE_PIPELINE`) are NOT registered commands — they MUST NOT be listed under `commands.changed`. If an RFC modifies a pipeline array, that is not a command registration change.
399
-
400
- ## Spec vendoring (RFC-0394..0397)
401
-
402
- External specification packages are vendored as immutable snapshots under `docs/specs/<spec-id>/` with an integrity manifest and `forge-spec.yaml` projection.
403
-
404
- - `forgeSpecModule` (in `os/spec/`) registers `spec.validate`, `spec.status`, `spec.materialize`, `spec.live.merge`, `spec.live.list`, `spec.live.show`, `spec.live.validate`.
405
- - `spec.validate` enforces SPEC-01..07: integrity, schema, cycles, references, waves, duplicates, materializedAs.
406
- - `spec.materialize` scaffolds RFC files for front nodes with `specRef` traceability and writes `materializedAs` back to `forge-spec.yaml`.
407
- - `spec.status` projects per-node states, blockers, and progress.
408
- - Spec amendments (`docs/specs/<id>/amendments/amd-NNN-*.md`) are the only correction channel — snapshot files are never modified.
409
-
410
- ### Living feature specs (RFC-0711)
411
-
412
- Living feature specs are mutable markdown documents under `docs/specs/live/<domain>.md` that reflect the current specification of a feature or module. Unlike vendored spec snapshots (DNA-55), living specs evolve through delta merges from archived RFCs.
413
-
414
- - `spec.live.merge --id <RFC-XXXX>` extracts headings from the RFC's `## Design` section and merges them into the corresponding living spec. All-or-nothing: aborts on any heading conflict without writing. Use `--dry-run` to preview.
415
- - `spec.live.list` lists all living specs with domain, title, lastMergedRfc, and history count.
416
- - `spec.live.show --domain <name>` reads and returns a single living spec.
417
- - `spec.live.validate` validates all living specs with rules V-LS-01..05 (frontmatter, domain/filename match, archived RFC references, history integrity, duplicate domains).
418
- - `docs.archive` automatically calls `spec.live.merge` for implemented RFCs with `liveSpec` frontmatter field after archiving. Rejected RFCs with `liveSpec` are skipped.
419
-
420
- ## NPM publish workflow
421
-
422
- To publish a new version of `@warpgogol/forge` to NPM:
423
-
424
- 1. Bump `version` in `packages/forge/package.json` (semver: minor for new skills/features, patch for fixes).
425
- 2. Bump `forge.syncedVersion` in `forge.yaml` to match.
426
- 3. Run `pnpm --filter @warpgogol/forge publish --access public --no-git-checks` — publishes to `@warpgogol/forge` on npmjs.org.
427
- 4. Commit version bumps: `git add packages/forge/package.json forge.yaml && git commit -m "release: @warpgogol/forge@<version>"`.
428
-
429
- The `prepublishOnly` script runs `clean → build → publish-check → strip-workspace-deps` automatically. **`strip-workspace-deps.mjs`** removes `@warpgogol/*` `workspace:*` dependencies from `package.json` before publish — these packages are not on npm and would make the published package uninstallable. The `postpublish` script restores the original `package.json` via `git checkout -- ./package.json`.
430
-
431
- **Do NOT use `npm publish`** — it fails during `prepublishOnly` because `tsc` cannot resolve workspace dependencies (`@warpgogol/werkstatt-site/share/fs`, `@warpgogol/werkstatt-engine/fingerprint`) outside the pnpm workspace context. `pnpm publish` handles workspace dependencies correctly.
432
-
433
- **Workspace deps must use dynamic imports.** `@warpgogol/*` packages that are not published to npm MUST be imported via dynamic `import()` (see `os/core/handlers/workspace-deps.ts`), never static `import`. Static imports would fail at runtime when forge is installed standalone from npm. The `workspace-deps.ts` helper caches the dynamic import and throws a clear error message if the packages are missing.
434
-
435
- ### `.npmrc` token precedence
436
-
437
- When publishing `@warpgogol/forge`, npm resolves the auth token from `.npmrc` files in precedence order: `packages/forge/.npmrc` (project) > `werkstatt/.npmrc` (workspace root) > `~/.npmrc` (user). A stale token in `packages/forge/.npmrc` silently overrides valid tokens in the other files. npm returns `404 Not Found` (not `403 Forbidden`) on PUT when the token lacks publish permissions — this is a deliberate npm security behavior that masks auth failures as missing resources. When rotating npm tokens, update ALL `.npmrc` files that contain a token, starting with `packages/forge/.npmrc`. All three files are gitignored.
438
-
439
- ### repo-extract operational notes
440
-
441
- - **Extract destination**: `repo-extract` writes the standalone repo to `<werkstatt-parent>/packages/<destName>` (e.g. `../packages/forge`) when `projectDir` starts with `packages/` and no `destBase`/`--dest` override is set. When a push fails, reconcile in that directory.
442
- - **Diverged remote export**: if `git push` is rejected because the remote has an export commit the local repo lacks, the remote commit is an older export snapshot fully superseded by the local one. Resolve with `git merge -s ours origin/main` + push — records the remote commit in history while keeping the newer export tree. Do NOT rebase (hundreds of `.coverage/` conflicts) or force-push.
443
- - **Post-ship version sync is automatic**: after a successful extract+push, repo-extract commits `chore: forge version sync X → Y (post-ship)` back to the monorepo (one commit per file: `package.json`, `forge.yaml`). Do not manually `ecosystem.commit` the version bump afterward — verify with `git log` instead.
444
-
445
- ## Git command patterns in forge handlers
446
-
447
- - **`git log --oneline` output includes a hash prefix** — the format is `<hash> <message>`, not `<message>`. When matching commit message patterns in `--oneline` output, do NOT anchor the regex to `^implement:` or `^feat:` — the line starts with the hash. Use a non-anchored pattern like `implement:\s+RFC-\d{4}\b` instead. Discovered during RFC-0625 V-32 implementation where `^implement:` failed to match `--oneline` output.
448
- - **`execGit` helper pattern** — multiple forge handlers (`implement-stamp.ts`, `verification-evidence.ts`, `validate-rules.ts`, `validate.ts`) each define their own `execGit`/`execGitLog` helper wrapping `execFile("git", ...)`. These are candidates for extraction into a shared `os/utils/git.ts` utility.
449
-
450
- ## CLI invocation and test fixtures
451
-
452
- - **Running forge CLI commands on the workspace root** — `pnpm --filter @warpgogol/forge exec forge <command>` runs from the package directory (`packages/forge/`), where `forge.yaml` is not found. To run forge commands against the workspace root (e.g. `doctor`, `rfc.validate`, `upgrade`), use `node packages/forge/bin/cli.js <command>` from the workspace root instead.
453
- - **Golden fixture for `agents-generate`** — when adding or modifying sections in `agents-generate.ts`, the golden fixture `src/tests/fixtures/agents-generate-business-before.txt` MUST be updated to match the new generated output. The test `agents-generate-domain.test.ts` compares generated content against this fixture with `expect(content).toBe(goldenFixture)` — a mismatch fails the test.
454
- - **SKILL-17 brand pattern must be case-sensitive** — the brand regex in `skill-validate.ts` uses a `@`-lookbehind to allow `@warpgogol/<pkg>` npm-scope references in skill instruction lines. Making the regex case-insensitive (`/gi`) defeats the lookbehind and false-flags every `@warpgogol` import as a brand violation. Keep the regex case-sensitive (`/g` only) so the `@`-scope allowance works correctly.
455
- - **`vi.resetModules()` before `vi.doMock()` for Node builtins** — when mocking Node built-in modules (e.g. `node:child_process`) in vitest, `vi.resetModules()` MUST be called BEFORE `vi.doMock()`. Without `resetModules()` first, the module cache retains the original module and the mock is not applied on re-import via dynamic `import()`. After the test, call `vi.doUnmock()` and `vi.resetModules()` to restore. Discovered during `upgrade.test.ts` `--update-npm` mock testing.
456
- - **Mock `execSync` for scaffold tests** — `runScaffoldProject` calls `execSync` to run `pnpm add` install commands, which fail in test environments without network access. Mock `node:child_process` with `vi.mock("node:child_process", async (importActual) => { const actual = await importActual(); return { ...actual, execSync: vi.fn(() => Buffer.from("mocked")) }; })` and use dynamic `await import("../onboarding/scaffold-project.ts")` after the mock. Use `vi.importActual` to preserve `execFile` (used by `promisify(execFile)` in forge/os/compass).
457
- - **`runDoctor` profile resolution in tests** — `runDoctor` calls `resolveForgeRoot(workspaceRoot)` which searches for `packages/forge/` relative to the workspace root. In temp-directory tests, the forge package is not found, so profile-dependent checks (prerequisites, invariants) are silently skipped. Either pass `forgeRoot` in the `ForgeRuntimeContext` (preferred), or create a minimal `packages/forge/profiles/<id>.yaml` inside the temp directory.
458
-
459
- ## RFC frontmatter: versionBump for prose-only policy RFCs
460
-
461
- Prose-only policy RFCs (skill-text-only, no code/command/contract changes) MUST set `versionBump: none`, not `patch`. The `patch` value over-reports the SemVer impact — there is no runtime or API surface change. This was a recurring audit finding across RFC-0669, RFC-0670, RFC-0671, RFC-0672, and RFC-0673 (5 consecutive RFCs). Set `versionBump: none` at creation time for `kind: policy` RFCs that only modify `.md` skill files.
462
-
463
- ## RFC frontmatter: file system responsibilities table
464
-
465
- Skill-text-only RFCs MUST include `packages/forge/AGENTS.md` in the file system responsibilities table with the note "No change needed — documents skill infrastructure, not individual skill behavior." This preempts a recurring audit finding (5 consecutive RFCs). The `packages/forge/AGENTS.md` file documents skill infrastructure (sync paths, validator rules, import constraints), not individual skill behavior — so it never needs updating when a skill's text changes.
466
-
467
- ## rfc.create title reuse
468
-
469
- `rfc.create` may reuse the title from a previous invocation in the same session. After creating an RFC, always verify the generated filename matches the intended title before populating content. If the filename is wrong, delete the file and re-run `rfc.create` with the correct `--title`. Do not rename the file — the RFC ID is assigned by the command and must not be manually changed.
470
-
471
- ## rfc.archive scope and bulk frontmatter edits
472
-
473
- - **`rfc.archive` moves files only from `docs/rfcs/` root into `archive/`** — it does NOT re-sort between archive subdirectories. An RFC whose status changes to `superseded` while already inside `archive/implemented/` stays there; the validator does not enforce the subdirectory. Discovered during the 2026-09-22 validation cleanup (16 RFCs transitioned to superseded in place).
474
- - **Bulk frontmatter edits must handle both empty-field forms.** YAML serializes unset fields as both `closedAt:` (empty) and `closedAt: null` — a regex matching only `^closedAt:\s*$` misses the `null` variant. Match `^closedAt:\s*(null)?\s*$` when filling fields mechanically. Similarly, acceptance probe commands appear both quoted (`command: "site-kernel run ..."`) and unquoted (`command: site-kernel run ...`) — rewrite patterns must cover both.
475
-
476
- ## Profile-driven RFC conventions
477
-
478
- All profile-driven RFCs (RFC-0674 onwards) MUST follow these conventions:
479
-
480
- - **CLI flags**: every proposed command MUST support `--dry-run`, `--json`, and `--profile` flags. These are the standard Forge lifecycle flags.
481
- - **Schema extensions**: all new profile schema fields MUST be optional (`z.optional()`) — existing profiles must continue to validate without changes.
482
- - **No domain-specific logic in Forge core**: all behavior is driven by profile YAML declarations. Forge source must not import domain-specific packages or hardcode domain-specific rules.
483
- - **File system responsibilities table**: every profile-driven RFC MUST list `packages/forge/src/profiles/profile-schema.ts` and `packages/forge/os/core/core.module.ts` in the table.
484
-
485
- ## Workflow file placement
486
-
487
- Workflow files MUST live only in `.agents/workflows/`. Do NOT duplicate workflow files in `.windsurf/workflows/` — `.windsurf/workflows/` is IDE-specific config that does not ship to new projects via `create`. `.agents/workflows/` is the single source of truth for workflow definitions.
488
-
489
- ## Workflow files vs skill content
490
-
491
- IDE-specific workflow files (`.windsurf/workflows/`, `.devin/workflows/`) MUST NOT duplicate skill content. Skills (`packages/forge/skills/`) are the portable unit — they ship to every new project via `create`. Workflow files are IDE-specific triggers that reference skills by name; they should not contain the protocol itself. If a workflow file grows beyond a trigger phrase + skill reference, move the content into the skill's `SKILL.md`.
492
-
493
- ## Kernel command handler pattern: pure function + thin handler
494
-
495
- When a kernel command's logic needs to be called from two contexts — (1) a pipeline step via `KernelRuntimeContext` and (2) directly from another package without kernel types — split into a pure function + thin kernel handler.
496
-
497
- - **Pure function**: `ensureThing(workspaceRoot: string, logger: { info: (msg: string) => void }): Promise<Result>` — no kernel types, callable from any package.
498
- - **Thin kernel handler**: `runThing(input: KernelCommandInput, context: KernelRuntimeContext): Promise<KernelCommandResult<Result>>` — calls the pure function, wraps result in `KernelCommandResult`, catches errors → `exitCode: 1`.
499
-
500
- This avoids the fragile alternative of calling a kernel handler with synthetic `input`/`context` from non-kernel code. The pure function is the reusable unit; the handler is the pipeline/CLI adapter.
501
-
502
- **Custom result types:** When a kernel command returns a custom data type (not `CheckResult`), you cannot use `failResult`/`passResult` from result helpers — they return `KernelCommandResult<CheckResult>`, not your type. Build the `KernelCommandResult` manually: `{ data: result, exitCode: 0, summary: "ok" }` for success, `{ data: { ...nulls }, exitCode: 1, summary: msg }` for error.