@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
@@ -21,8 +21,8 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
21
21
  </CHANGE_SUMMARY>
22
22
  */
23
23
 
24
- import fs from "node:fs/promises";
25
- import { exec } from "node:child_process";
24
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
25
+ import { exec } from "../../../src/utils/sync-fs.ts";
26
26
  import { promisify } from "node:util";
27
27
  import path from "node:path";
28
28
  import type {
@@ -141,7 +141,7 @@ async function appendAuditLog(
141
141
  ): Promise<void> {
142
142
  const logPath = path.join(repoRoot, AUDIT_LOG_PATH);
143
143
  const line = JSON.stringify(entry) + "\n";
144
- await fs.appendFile(logPath, line, "utf8");
144
+ await fs.appendFile(logPath, line);
145
145
  }
146
146
 
147
147
  export async function runPinnedValidate(
@@ -11,7 +11,7 @@
11
11
  </CHANGE_SUMMARY>
12
12
  */
13
13
 
14
- import fs from "node:fs";
14
+ import * as fs from "../../../src/utils/sync-fs.ts";
15
15
  import path from "node:path";
16
16
  import { parse as parseYaml } from "yaml";
17
17
  import { resolveForgeRoot } from "../../../src/config/forge-config.ts";
@@ -13,7 +13,7 @@
13
13
  </CHANGE_SUMMARY>
14
14
  */
15
15
 
16
- import fs from "node:fs";
16
+ import * as fs from "../../../src/utils/sync-fs.ts";
17
17
  import path from "node:path";
18
18
  import type {
19
19
  ForgeCommandInput,
@@ -14,8 +14,8 @@
14
14
  </CHANGE_SUMMARY>
15
15
  */
16
16
 
17
- import { readFile, copyFile, mkdir, stat } from "node:fs/promises";
18
17
  import { join, basename } from "node:path";
18
+ import { ambientIo, resolveIo } from "../../../src/utils/io.ts";
19
19
  import { createHash } from "node:crypto";
20
20
  import type {
21
21
  ForgeCommandInput,
@@ -27,6 +27,10 @@ import { loadWorkspaceDeps } from "../../werkstatt/handlers/workspace-deps.ts";
27
27
  import { writeFileIfChanged } from "../../../src/utils/fs-idempotent.ts";
28
28
  import type { ProfileRelease } from "../../../src/profiles/profile-schema.ts";
29
29
 
30
+ // Ambient default for helper fns without a context param — handlers override
31
+ // with `const io = resolveIo(context.io)` inside their own scope.
32
+ const io = ambientIo;
33
+
30
34
  export interface ReleaseManifest {
31
35
  schemaVersion: string;
32
36
  releaseId: string;
@@ -58,7 +62,7 @@ function generateReleaseId(profileId: string, shortHash: string): string {
58
62
 
59
63
  async function readVersionFromPackageJson(workspaceRoot: string): Promise<string> {
60
64
  try {
61
- const raw = await readFile(join(workspaceRoot, "package.json"), "utf8");
65
+ const raw = await io.readFile(join(workspaceRoot, "package.json"));
62
66
  const pkg = JSON.parse(raw) as { version?: string };
63
67
  return pkg.version ?? "0.0.0";
64
68
  } catch {
@@ -79,7 +83,7 @@ async function findBuiltArtifacts(
79
83
  if (!isGlob) {
80
84
  const fullPath = join(workspaceRoot, produceOutput);
81
85
  try {
82
- const _s = await stat(fullPath);
86
+ const _s = await io.stat(fullPath);
83
87
  return [fullPath];
84
88
  } catch {
85
89
  return [];
@@ -110,6 +114,7 @@ export async function runReleasePrepare(
110
114
  input: ForgeCommandInput,
111
115
  context: ForgeRuntimeContext,
112
116
  ): Promise<ForgeCommandResult<ForgeReleasePrepareResult>> {
117
+ const io = resolveIo(context.io);
113
118
  const { workspaceRoot, logger } = context;
114
119
  const { dryRun, profileIdOverride } = resolveLifecycleFlags(input, context);
115
120
 
@@ -212,7 +217,7 @@ export async function runReleasePrepare(
212
217
  if (!dryRun) {
213
218
  const { byteHashFile } = await loadWorkspaceDeps();
214
219
  hash = await byteHashFile(builtFile);
215
- const stats = await stat(builtFile);
220
+ const stats = await io.stat(builtFile);
216
221
  size = stats.size;
217
222
  allHashes += hash;
218
223
  }
@@ -268,12 +273,12 @@ export async function runReleasePrepare(
268
273
  };
269
274
  }
270
275
 
271
- await mkdir(releaseDir, { recursive: true });
276
+ await io.mkdir(releaseDir);
272
277
 
273
278
  for (const a of manifestArtifacts) {
274
279
  const srcPath = join(workspaceRoot, a.path);
275
280
  const dstPath = join(releaseDir, basename(a.path));
276
- await copyFile(srcPath, dstPath);
281
+ await io.copyFile(srcPath, dstPath);
277
282
  }
278
283
 
279
284
  const manifestPath = join(releaseDir, releaseConfig.manifestName);
@@ -14,8 +14,8 @@
14
14
  </CHANGE_SUMMARY>
15
15
  */
16
16
 
17
- import { readFile, copyFile, mkdir } from "node:fs/promises";
18
17
  import { join, basename } from "node:path";
18
+ import { resolveIo } from "../../../src/utils/io.ts";
19
19
  import type {
20
20
  ForgeCommandInput,
21
21
  ForgeCommandResult,
@@ -46,6 +46,7 @@ export async function runReleasePublish(
46
46
  input: ForgeCommandInput,
47
47
  context: ForgeRuntimeContext,
48
48
  ): Promise<ForgeCommandResult<ForgeReleasePublishResult>> {
49
+ const io = resolveIo(context.io);
49
50
  const { workspaceRoot, logger } = context;
50
51
  const { dryRun, profileIdOverride } = resolveLifecycleFlags(input, context);
51
52
 
@@ -87,7 +88,7 @@ export async function runReleasePublish(
87
88
 
88
89
  let manifest: ReleaseManifest;
89
90
  try {
90
- const raw = await readFile(manifestPath, "utf8");
91
+ const raw = await io.readFile(manifestPath);
91
92
  manifest = JSON.parse(raw) as ReleaseManifest;
92
93
  } catch {
93
94
  return {
@@ -155,15 +156,14 @@ export async function runReleasePublish(
155
156
 
156
157
  if (target === "local") {
157
158
  const publishedDir = join(releaseDir, "published");
158
- await mkdir(publishedDir, { recursive: true });
159
+ await io.mkdir(publishedDir);
159
160
  for (const f of filesToPublish) {
160
161
  const dst = join(publishedDir, basename(f));
161
- await copyFile(f, dst);
162
+ await io.copyFile(f, dst);
162
163
  publishedFiles.push({ path: f, targetPath: dst });
163
164
  }
164
165
  } else if (target === "r2" || target === "s3") {
165
166
  const { S3Client, PutObjectCommand } = await import("@aws-sdk/client-s3");
166
- const { readFile: fsReadFile } = await import("node:fs/promises");
167
167
 
168
168
  const endpoint =
169
169
  target === "r2"
@@ -185,7 +185,7 @@ export async function runReleasePublish(
185
185
 
186
186
  for (const f of filesToPublish) {
187
187
  const key = prefix ? `${prefix}/${basename(f)}` : basename(f);
188
- const body = await fsReadFile(f);
188
+ const body = await io.readFile(f);
189
189
  await client.send(
190
190
  new PutObjectCommand({
191
191
  Bucket: bucket,
@@ -18,7 +18,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
18
18
  </CHANGE_SUMMARY>
19
19
  */
20
20
 
21
- import { exec } from "node:child_process";
21
+ import { exec } from "../../../src/utils/sync-fs.ts";
22
22
  import { promisify } from "node:util";
23
23
  import type {
24
24
  ForgeCommandInput,
@@ -74,6 +74,7 @@ export async function createForgeExplorationModule(): Promise<ForgeModule> {
74
74
  scope: "workspace",
75
75
  mutatesState: true,
76
76
  writes: ["docs/explorations/*.md"],
77
+ generates: [],
77
78
  reads: ["docs/explorations/*.md"],
78
79
  cacheable: false,
79
80
  flags: {
@@ -13,7 +13,7 @@ their YAML frontmatter without validating the shape.
13
13
  </CHANGE_SUMMARY>
14
14
  */
15
15
 
16
- import fs from "node:fs/promises";
16
+ import { ambientIo as fs } from "../../src/utils/io.ts";
17
17
  import path from "node:path";
18
18
  import YAML from "yaml";
19
19
  import { EXPLORATION_DIR } from "./types.ts";
@@ -38,9 +38,9 @@ export async function listExplorationFiles(explorationsDirPath: string): Promise
38
38
  const results: string[] = [];
39
39
 
40
40
  try {
41
- const entries = await fs.readdir(explorationsDirPath, { withFileTypes: true });
41
+ const entries = await fs.readdir(explorationsDirPath);
42
42
  for (const entry of entries) {
43
- if (entry.isFile() && entry.name.endsWith(".md") && entry.name !== "README.md") {
43
+ if (entry.isFile && entry.name.endsWith(".md") && entry.name !== "README.md") {
44
44
  results.push(entry.name);
45
45
  }
46
46
  }
@@ -57,7 +57,7 @@ export async function readAndParseExplorationNote(
57
57
  ): Promise<{ fileName: string; parsed: ParsedExplorationNote } | undefined> {
58
58
  try {
59
59
  const filePath = path.join(explorationsDirPath, fileName);
60
- const content = await fs.readFile(filePath, "utf-8");
60
+ const content = await fs.readFile(filePath);
61
61
  return { fileName, parsed: parseExplorationFile(content) };
62
62
  } catch {
63
63
  return undefined;
@@ -10,7 +10,7 @@
10
10
  </CHANGE_SUMMARY>
11
11
  */
12
12
 
13
- import fs from "node:fs/promises";
13
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
14
14
  import path from "node:path";
15
15
  import type {
16
16
  ForgeCommandInput,
@@ -110,7 +110,7 @@ export async function runExplorationArchive(
110
110
  related,
111
111
  };
112
112
  const updatedContent = serializeExplorationNote(updatedFrontmatter, result.parsed.body);
113
- await fs.writeFile(filePath, updatedContent, "utf-8");
113
+ await fs.writeFile(filePath, updatedContent);
114
114
  }
115
115
  if (outputFormat === "pretty") {
116
116
  logger.info(`Exploration note ${slug} is already archived (no-op).`);
@@ -136,7 +136,7 @@ export async function runExplorationArchive(
136
136
  };
137
137
 
138
138
  const updatedContent = serializeExplorationNote(updatedFrontmatter, result.parsed.body);
139
- await fs.writeFile(filePath, updatedContent, "utf-8");
139
+ await fs.writeFile(filePath, updatedContent);
140
140
 
141
141
  if (outputFormat === "pretty") {
142
142
  logger.success(`Archived exploration note: ${slug} (${previousStatus} → archived)`);
@@ -318,8 +318,14 @@ describe("mission.archive", () => {
318
318
  });
319
319
 
320
320
  test("RFC-0801: service folders deleted before move", async () => {
321
- await writeMissionManifest(missionsDir, "test-m014", "closed");
321
+ // Mission carries a releaseId — already released, so the deferred-release
322
+ // guard does not apply and all service folders are cleaned.
322
323
  const missionDir = path.join(missionsDir, "test-m014");
324
+ await fs.mkdir(missionDir, { recursive: true });
325
+ await fs.writeFile(
326
+ path.join(missionDir, "mission.yaml"),
327
+ `missionId: test-m014\nstate: closed\nreleaseId: test-r000014\n`,
328
+ );
323
329
  const workpieceDir = path.join(missionDir, "workpiece");
324
330
  await fs.mkdir(workpieceDir, { recursive: true });
325
331
 
@@ -341,6 +347,37 @@ describe("mission.archive", () => {
341
347
  }
342
348
  });
343
349
 
350
+ test("deferred-release guard: closed mission without releaseId → node_modules preserved", async () => {
351
+ await writeMissionManifest(missionsDir, "test-m014b", "closed");
352
+ const missionDir = path.join(missionsDir, "test-m014b");
353
+ const workpieceDir = path.join(missionDir, "workpiece");
354
+ await fs.mkdir(workpieceDir, { recursive: true });
355
+
356
+ for (const folder of ["node_modules", "dist", ".astro"]) {
357
+ const folderPath = path.join(workpieceDir, folder);
358
+ await fs.mkdir(folderPath, { recursive: true });
359
+ await fs.writeFile(path.join(folderPath, "dummy.txt"), `content of ${folder}\n`);
360
+ }
361
+
362
+ const data = unwrap(await runMissionArchive(makeInput(), makeContext(tmpDir)));
363
+
364
+ expect(data.moved).toHaveLength(1);
365
+ const archivedWorkpiece = path.join(
366
+ missionsDir,
367
+ "archive",
368
+ "closed",
369
+ "test-m014b",
370
+ "workpiece",
371
+ );
372
+ // node_modules preserved so release.prepare can still run on the archived
373
+ // workpiece — archived dirs fall outside the pnpm-workspace glob.
374
+ expect(existsSync(path.join(archivedWorkpiece, "node_modules"))).toBe(true);
375
+ expect(existsSync(path.join(archivedWorkpiece, "node_modules", "dummy.txt"))).toBe(true);
376
+ // Other service folders still cleaned.
377
+ expect(existsSync(path.join(archivedWorkpiece, "dist"))).toBe(false);
378
+ expect(existsSync(path.join(archivedWorkpiece, ".astro"))).toBe(false);
379
+ });
380
+
344
381
  test("RFC-0801: mission without workpiece — cleanup skipped gracefully", async () => {
345
382
  await writeMissionManifest(missionsDir, "test-m015", "closed");
346
383
  // No workpiece/ directory created — simulates aborted mission
@@ -22,14 +22,15 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
22
22
 
23
23
  Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PURPOSE-02), headers on mission/index + gen-upstreams, sanitizeItemText in summary.record (literal Compass tags corrupted history), excludedPaths for wrangler types, test-fixtures testPattern. forge+services now 0 diagnostics under --mode error.</item>
24
24
  <item>RFC-1138: pipeline hygiene — module-scoped exempt entries, archive gitignore guard, dns upsert to deploy phases, promote auto-sync, rfc.create claim protocol, siteHasRuntime filter</item>
25
+ <item>warpgogol-m000175 fo-fix: deferred-release guard — closed missions without releaseId keep workpiece node_modules on archive (archived dirs fall outside the pnpm-workspace glob, so deps cannot be reinstalled in place and release.prepare would fail on WORKPIECE-IMPORTS-01); released missions still get full service-folder cleanup.</item>
25
26
  <history>RFC-0573, RFC-0733, RFC-0801</history>
26
27
  </CHANGE_SUMMARY>
27
28
  */
28
29
 
29
- import fs from "node:fs/promises";
30
- import { existsSync } from "node:fs";
30
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
31
+ import { existsSync, lstatSync } from "../../../src/utils/sync-fs.ts";
31
32
  import path from "node:path";
32
- import { execSync } from "node:child_process";
33
+ import { execSync } from "../../../src/utils/sync-fs.ts";
33
34
  import { parse as parseYaml } from "yaml";
34
35
  import type {
35
36
  ForgeCommandInput,
@@ -56,12 +57,16 @@ const SERVICE_FOLDERS = [
56
57
  ".turbo",
57
58
  ] as const;
58
59
 
59
- async function cleanServiceFolders(workpieceDir: string): Promise<string[]> {
60
+ async function cleanServiceFolders(
61
+ workpieceDir: string,
62
+ keep: readonly string[] = [],
63
+ ): Promise<string[]> {
60
64
  const removed: string[] = [];
61
65
  for (const folder of SERVICE_FOLDERS) {
66
+ if (keep.includes(folder)) continue;
62
67
  const target = path.join(workpieceDir, folder);
63
68
  if (existsSync(target)) {
64
- await fs.rm(target, { recursive: true, force: true });
69
+ await fs.rm(target);
65
70
  removed.push(folder);
66
71
  }
67
72
  }
@@ -76,7 +81,7 @@ function isCacheEntry(name: string): boolean {
76
81
  async function readMissionReleaseId(missionDir: string): Promise<string | null> {
77
82
  const manifestPath = path.join(missionDir, "mission.yaml");
78
83
  try {
79
- const raw = await fs.readFile(manifestPath, "utf8");
84
+ const raw = await fs.readFile(manifestPath);
80
85
  const parsed = parseYaml(raw) as Record<string, unknown>;
81
86
  const releaseId = parsed?.releaseId;
82
87
  if (typeof releaseId === "string" && releaseId.trim()) return releaseId.trim();
@@ -89,7 +94,7 @@ async function readMissionReleaseId(missionDir: string): Promise<string | null>
89
94
  async function readMissionState(missionDir: string): Promise<string | null> {
90
95
  const manifestPath = path.join(missionDir, "mission.yaml");
91
96
  try {
92
- const raw = await fs.readFile(manifestPath, "utf8");
97
+ const raw = await fs.readFile(manifestPath);
93
98
  const parsed = parseYaml(raw) as Record<string, unknown>;
94
99
  const state = parsed?.state;
95
100
  if (typeof state === "string") return state.trim();
@@ -106,7 +111,7 @@ async function readMissionState(missionDir: string): Promise<string | null> {
106
111
  const workpieceDir = path.join(missionDir, "workpiece");
107
112
  if (existsSync(workpieceDir)) {
108
113
  const entries = await fs.readdir(workpieceDir);
109
- const nonCacheEntries = entries.filter((e) => !isCacheEntry(e));
114
+ const nonCacheEntries = entries.filter((e) => !isCacheEntry(e.name));
110
115
  if (nonCacheEntries.length === 0) {
111
116
  return "closed";
112
117
  }
@@ -125,17 +130,17 @@ async function isOrphanedRemnant(missionDir: string): Promise<boolean> {
125
130
  if (!existsSync(workpieceDir)) return true;
126
131
 
127
132
  const entries = await fs.readdir(workpieceDir);
128
- const nonCacheEntries = entries.filter((e) => !isCacheEntry(e));
133
+ const nonCacheEntries = entries.filter((e) => !isCacheEntry(e.name));
129
134
  return nonCacheEntries.length === 0;
130
135
  }
131
136
 
132
137
  // RFC-0982: Check if a mission directory has non-cache content (source files,
133
138
  // configs, etc.) that warrants manual inspection rather than auto-cleanup.
134
139
  async function hasNonCacheContent(missionDir: string): Promise<boolean> {
135
- const entries = await fs.readdir(missionDir, { withFileTypes: true });
140
+ const entries = await fs.readdir(missionDir);
136
141
  for (const entry of entries) {
137
142
  if (entry.name === "workpiece") continue;
138
- if (entry.isDirectory() && isCacheEntry(entry.name)) {
143
+ if (entry.isDirectory && isCacheEntry(entry.name)) {
139
144
  continue;
140
145
  }
141
146
  // Any file or non-cache directory at mission root is content
@@ -146,7 +151,7 @@ async function hasNonCacheContent(missionDir: string): Promise<boolean> {
146
151
  const workpieceDir = path.join(missionDir, "workpiece");
147
152
  if (existsSync(workpieceDir)) {
148
153
  const wpEntries = await fs.readdir(workpieceDir);
149
- const nonCacheEntries = wpEntries.filter((e) => !isCacheEntry(e));
154
+ const nonCacheEntries = wpEntries.filter((e) => !isCacheEntry(e.name));
150
155
  if (nonCacheEntries.length > 0) return true;
151
156
  }
152
157
 
@@ -176,7 +181,7 @@ async function moveMissionDir(
176
181
 
177
182
  if (!dryRun) {
178
183
  if (targetParentDir) {
179
- await fs.mkdir(targetParentDir, { recursive: true });
184
+ await fs.mkdir(targetParentDir);
180
185
  }
181
186
 
182
187
  // RFC-0801: Clean service folders from workpiece before move.
@@ -185,11 +190,27 @@ async function moveMissionDir(
185
190
  // Aborted missions may not have a workpiece/ directory — skip gracefully.
186
191
  const workpieceDir = path.join(sourcePath, "workpiece");
187
192
  if (existsSync(workpieceDir)) {
193
+ // Deferred-release guard: a closed mission without a releaseId still
194
+ // needs release.prepare (ADR-0085 closed-workpiece rebuild path), and
195
+ // archived dirs fall outside the pnpm-workspace `missions/*/workpiece`
196
+ // glob — node_modules cannot be reinstalled in place. Keep it so the
197
+ // archived workpiece stays release-ready.
198
+ const keepFolders =
199
+ direction === "into-archive" &&
200
+ state === "closed" &&
201
+ !(await readMissionReleaseId(sourcePath))
202
+ ? ["node_modules"]
203
+ : [];
188
204
  try {
189
- const removed = await cleanServiceFolders(workpieceDir);
205
+ const removed = await cleanServiceFolders(workpieceDir, keepFolders);
190
206
  if (removed.length > 0 && logger) {
191
207
  logger.info(` cleaned service folders: ${removed.join(", ")}`);
192
208
  }
209
+ if (keepFolders.length > 0 && logger) {
210
+ logger.info(
211
+ " kept node_modules — mission has no releaseId; release.prepare can still run on the archived workpiece",
212
+ );
213
+ }
193
214
  } catch (cleanupErr) {
194
215
  // Non-fatal: log warning and continue with move
195
216
  if (logger) {
@@ -271,14 +292,17 @@ export async function runMissionArchive(
271
292
  }
272
293
 
273
294
  // Phase 1: Scan missions/ for terminal-state missions to move into archive
274
- const rootEntries = await fs.readdir(missionsPath, { withFileTypes: true });
295
+ const rootEntries = await fs.readdir(missionsPath);
275
296
 
276
297
  // Stale symlink cleanup: IDEs or file watchers may recreate symlinks to
277
298
  // archived mission directories after mission.archive has moved them.
278
299
  // These symlinks break pnpm workspace resolution and mission number derivation.
279
300
  // Trash them before they can cause downstream issues.
280
301
  for (const e of rootEntries) {
281
- if (e.isSymbolicLink() && e.name !== ARCHIVE_DIR_NAME) {
302
+ if (
303
+ lstatSync(path.join(missionsPath, e.name)).isSymbolicLink() &&
304
+ e.name !== ARCHIVE_DIR_NAME
305
+ ) {
282
306
  const symlinkPath = path.join(missionsPath, e.name);
283
307
  const sourceRel = `${MISSIONS_DIR}/${e.name}`;
284
308
  if (!dryRun) {
@@ -296,7 +320,12 @@ export async function runMissionArchive(
296
320
  }
297
321
 
298
322
  const rootDirs = rootEntries
299
- .filter((e) => e.isDirectory() && !e.isSymbolicLink() && e.name !== ARCHIVE_DIR_NAME)
323
+ .filter(
324
+ (e) =>
325
+ e.isDirectory &&
326
+ !lstatSync(path.join(missionsPath, e.name)).isSymbolicLink() &&
327
+ e.name !== ARCHIVE_DIR_NAME,
328
+ )
300
329
  .map((e) => e.name);
301
330
 
302
331
  for (const missionId of rootDirs) {
@@ -356,12 +385,14 @@ export async function runMissionArchive(
356
385
 
357
386
  // Warn when archiving a closed mission without a release — operator likely
358
387
  // forgot to run release.prepare before archiving. Non-blocking: some missions
359
- // (e.g. aborted, content-only) legitimately have no release.
388
+ // (e.g. aborted, content-only) legitimately have no release. The workpiece
389
+ // node_modules are preserved in this case so the archived mission stays
390
+ // release-ready (see deferred-release guard in moveMissionDir).
360
391
  if (state === "closed" && !dryRun) {
361
392
  const releaseId = await readMissionReleaseId(missionDir);
362
393
  if (!releaseId && outputFormat === "pretty") {
363
394
  logger.warn(
364
- ` ⚠ ${missionId}: closed mission has no releaseId — run release.prepare before archiving if this mission needs deployment`,
395
+ ` ⚠ ${missionId}: closed mission has no releaseId — keeping workpiece node_modules so release.prepare can still run on the archived workpiece`,
365
396
  );
366
397
  }
367
398
  }
@@ -410,13 +441,13 @@ export async function runMissionArchive(
410
441
  // Phase 2: Scan missions/archive/<state>/ for non-terminal missions to move back
411
442
  const archivePath = path.join(missionsPath, ARCHIVE_DIR_NAME);
412
443
  if (existsSync(archivePath)) {
413
- const stateDirs = await fs.readdir(archivePath, { withFileTypes: true });
414
- const stateDirNames = stateDirs.filter((e) => e.isDirectory()).map((e) => e.name);
444
+ const stateDirs = await fs.readdir(archivePath);
445
+ const stateDirNames = stateDirs.filter((e) => e.isDirectory).map((e) => e.name);
415
446
 
416
447
  for (const stateDirName of stateDirNames) {
417
448
  const stateDirPath = path.join(archivePath, stateDirName);
418
- const archivedMissions = await fs.readdir(stateDirPath, { withFileTypes: true });
419
- const archivedDirNames = archivedMissions.filter((e) => e.isDirectory()).map((e) => e.name);
449
+ const archivedMissions = await fs.readdir(stateDirPath);
450
+ const archivedDirNames = archivedMissions.filter((e) => e.isDirectory).map((e) => e.name);
420
451
 
421
452
  for (const missionId of archivedDirNames) {
422
453
  const archivedMissionDir = path.join(stateDirPath, missionId);
@@ -14,47 +14,46 @@
14
14
  import type { ForgeModule } from "../../src/forge-module.ts";
15
15
 
16
16
  export async function createForgeMissionModule(): Promise<ForgeModule> {
17
- const { runMissionArchive } = await import("./handlers/archive.ts");
17
+ const { runMissionArchive } = await import("./handlers/archive.ts");
18
18
  return {
19
- name: "forge-mission",
20
- version: "0.1.0",
21
- runtime: "autonomous",
19
+ name: "forge-mission",
20
+ version: "0.1.0",
21
+ runtime: "autonomous",
22
22
  declarations: [],
23
- commands: [
24
- {
25
- name: "mission.archive",
26
- description:
27
- "Move terminal-state mission directories (state: closed or aborted in " +
28
- "mission.yaml) into missions/archive/<state>/<missionId>/ subdirectories. " +
29
- "Bidirectional: moves open missions found in archive subdirectories back " +
30
- "to missions/. Use --dry-run to preview. Use --status to filter to a " +
31
- "single terminal status (closed, aborted). " +
32
- "Prefer the docs.archive umbrella command unless you need to archive only missions.",
33
- scope: "workspace",
34
- mutatesState: true,
35
- writes: ["missions/*", "missions/archive/**"],
36
- reads: ["missions/**"],
37
- cacheable: false,
38
- flags: {
39
- "dry-run": {
40
- kind: "boolean",
41
- description: "Preview what would be moved without touching the filesystem.",
42
- },
43
- status: {
44
- kind: "string",
45
- description: "Filter to a single terminal status (closed, aborted).",
46
- },
47
- "clean-orphans": {
48
- kind: "boolean",
49
- description:
50
- "Trash orphaned directories (no mission.yaml, only cache files) instead of archiving them.",
23
+ commands: [
24
+ {
25
+ name: "mission.archive",
26
+ description:
27
+ "Move terminal-state mission directories (state: closed or aborted in " +
28
+ "mission.yaml) into missions/archive/<state>/<missionId>/ subdirectories. " +
29
+ "Bidirectional: moves open missions found in archive subdirectories back " +
30
+ "to missions/. Use --dry-run to preview. Use --status to filter to a " +
31
+ "single terminal status (closed, aborted). " +
32
+ "Prefer the docs.archive umbrella command unless you need to archive only missions.",
33
+ scope: "workspace",
34
+ mutatesState: true,
35
+ writes: ["missions/*", "missions/archive/**"],
36
+ generates: [],
37
+ reads: ["missions/**"],
38
+ cacheable: false,
39
+ flags: {
40
+ "dry-run": {
41
+ kind: "boolean",
42
+ description: "Preview what would be moved without touching the filesystem.",
43
+ },
44
+ status: {
45
+ kind: "string",
46
+ description: "Filter to a single terminal status (closed, aborted).",
47
+ },
48
+ "clean-orphans": {
49
+ kind: "boolean",
50
+ description:
51
+ "Trash orphaned directories (no mission.yaml, only cache files) instead of archiving them.",
52
+ },
51
53
  },
54
+ execute: runMissionArchive,
52
55
  },
53
- execute: runMissionArchive,
54
- }
55
- ],
56
- pipelines: [
57
-
58
- ]};
56
+ ],
57
+ pipelines: [],
58
+ };
59
59
  }
60
- ;
@@ -13,9 +13,14 @@ uses kebab-case (lowercase letters, digits, hyphens only), with documented exemp
13
13
  */
14
14
 
15
15
  import { basename, join, relative } from "node:path";
16
- import { readFile } from "node:fs/promises";
17
- import { readdirSync, type Dirent } from "node:fs";
16
+ import { ambientIo, resolveIo } from "../../src/utils/io.ts";
17
+
18
+ import { readdirSync, type Dirent } from "../../src/utils/sync-fs.ts";
18
19
  import { collectFiles } from "../../src/utils/fs.ts";
20
+
21
+ // Ambient default for helper fns without a context param — handlers override
22
+ // with `const io = resolveIo(context.io)` inside their own scope.
23
+ const io = ambientIo;
19
24
  import type {
20
25
  ForgeCommandInput,
21
26
  ForgeCommandResult,
@@ -168,7 +173,7 @@ function hasNamingViolation(fileName: string): boolean {
168
173
  async function readSimpleIgnorePatterns(filePath: string): Promise<Set<string>> {
169
174
  const patterns = new Set<string>();
170
175
  try {
171
- const content = await readFile(filePath, "utf8");
176
+ const content = await io.readFile(filePath);
172
177
  for (const rawLine of content.split("\n")) {
173
178
  const line = rawLine.trim();
174
179
  if (!line || line.startsWith("#")) continue;
@@ -270,6 +275,7 @@ export async function runNamingConventionLint(
270
275
  unknownTopLevelDirs?: string[];
271
276
  }>
272
277
  > {
278
+ const _io = resolveIo(context.io);
273
279
  const workspaceRoot = context.workspaceRoot;
274
280
  const includeIgnored = input.flags["include-ignored"] === true;
275
281