@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
@@ -15,14 +15,18 @@ entries from all RFCs, and builds a bidirectional trace matrix.
15
15
  </CHANGE_SUMMARY>
16
16
  */
17
17
 
18
- import { readFile } from "node:fs/promises";
19
18
  import { join } from "node:path";
19
+ import { ambientIo, resolveIo } from "../../src/utils/io.ts";
20
20
 
21
21
  import { writeFileAtomic } from "../../src/utils/fs-atomic.ts";
22
22
  import { buildGeneratedHeader } from "../../src/utils/generated-marker.ts";
23
23
  import { stringify as yamlStringify } from "yaml";
24
24
  import { listRfcFiles, readAndParseRfc } from "./frontmatter-io.ts";
25
25
  import { RFC_DIR } from "./types.ts";
26
+
27
+ // Ambient default for helper fns without a context param — handlers override
28
+ // with `const io = resolveIo(context.io)` inside their own scope.
29
+ const io = ambientIo;
26
30
  import type {
27
31
  Diagnostic,
28
32
  ForgeCommandInput,
@@ -56,7 +60,7 @@ export interface DnaTraceResult {
56
60
  async function parseDnaRegistry(workspaceRoot: string): Promise<Set<string>> {
57
61
  const ids = new Set<string>();
58
62
  try {
59
- const src = await readFile(join(workspaceRoot, DNA_REGISTRY_PATH), "utf-8");
63
+ const src = await io.readFile(join(workspaceRoot, DNA_REGISTRY_PATH));
60
64
  for (const m of src.matchAll(DNA_HEADING_RE)) {
61
65
  ids.add(`DNA-${m[1]}`);
62
66
  }
@@ -186,6 +190,7 @@ export async function runRfcDnaTraceValidate(
186
190
  input: ForgeCommandInput,
187
191
  context: ForgeRuntimeContext,
188
192
  ): Promise<ForgeCommandResult<DnaTraceResult>> {
193
+ const _io = resolveIo(context.io);
189
194
  const { workspaceRoot, logger, outputFormat } = context;
190
195
  const dnaFilter = input.flags["dna"] as string | undefined;
191
196
 
@@ -241,6 +246,7 @@ export async function runRfcDnaTraceGenerate(
241
246
  _input: ForgeCommandInput,
242
247
  context: ForgeRuntimeContext,
243
248
  ): Promise<ForgeCommandResult<DnaTraceResult>> {
249
+ const _io = resolveIo(context.io);
244
250
  const { workspaceRoot, logger, outputFormat } = context;
245
251
 
246
252
  const { entries, diagnostics, registryIds } = await buildDnaTrace(workspaceRoot);
@@ -22,7 +22,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
22
22
  </CHANGE_SUMMARY>
23
23
  */
24
24
 
25
- import fs from "node:fs/promises";
25
+ import { ambientIo as fs } from "../../src/utils/io.ts";
26
26
  import path from "node:path";
27
27
  import YAML from "yaml";
28
28
 
@@ -47,13 +47,13 @@ export async function listRfcFiles(rfcDirPath: string): Promise<string[]> {
47
47
 
48
48
  async function scanDir(dirPath: string, relativePrefix: string): Promise<void> {
49
49
  try {
50
- const entries = await fs.readdir(dirPath, { withFileTypes: true });
50
+ const entries = await fs.readdir(dirPath);
51
51
  for (const entry of entries) {
52
52
  const relativePath = relativePrefix ? `${relativePrefix}/${entry.name}` : entry.name;
53
- if (entry.isDirectory()) {
53
+ if (entry.isDirectory) {
54
54
  await scanDir(path.join(dirPath, entry.name), relativePath);
55
55
  } else if (
56
- entry.isFile() &&
56
+ entry.isFile &&
57
57
  entry.name.endsWith(".md") &&
58
58
  !entry.name.startsWith("rfc-0000") &&
59
59
  !entry.name.endsWith(".generated.md") &&
@@ -84,7 +84,7 @@ export async function readAndParseRfc(
84
84
  ): Promise<ReadAndParseRfcResult | undefined> {
85
85
  try {
86
86
  const filePath = path.join(rfcDirPath, fileName);
87
- const content = await fs.readFile(filePath, "utf-8");
87
+ const content = await fs.readFile(filePath);
88
88
  return { fileName, parsed: parseRfcFile(content) };
89
89
  } catch (e) {
90
90
  if (e instanceof Error) {
@@ -22,7 +22,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
22
22
  </CHANGE_SUMMARY>
23
23
  */
24
24
 
25
- import fs from "node:fs/promises";
25
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
26
26
  import path from "node:path";
27
27
  import { stringify as yamlStringify } from "yaml";
28
28
  import { listRfcFiles, readAndParseRfc } from "../frontmatter-io.ts";
@@ -137,7 +137,9 @@ export async function runRfcArchive(
137
137
  }
138
138
 
139
139
  try {
140
- await fs.access(targetPath);
140
+ await fs.exists(targetPath).then((ok) => {
141
+ if (!ok) throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
142
+ });
141
143
  skipped.push({ id, file: relFile, reason: "destination exists" });
142
144
  continue;
143
145
  } catch {
@@ -145,7 +147,7 @@ export async function runRfcArchive(
145
147
  }
146
148
 
147
149
  if (!dryRun) {
148
- await fs.mkdir(targetDir, { recursive: true });
150
+ await fs.mkdir(targetDir);
149
151
  try {
150
152
  await fs.rename(path.join(rfcDirPath, fileName), targetPath);
151
153
  } catch (err) {
@@ -184,7 +186,9 @@ export async function runRfcArchive(
184
186
  }
185
187
 
186
188
  try {
187
- await fs.access(targetPath);
189
+ await fs.exists(targetPath).then((ok) => {
190
+ if (!ok) throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
191
+ });
188
192
  skipped.push({ id, file: relFile, reason: "destination exists" });
189
193
  continue;
190
194
  } catch {
@@ -269,7 +273,7 @@ export async function runRfcArchive(
269
273
  count: entries.length,
270
274
  entries,
271
275
  };
272
- await fs.writeFile(path.join(workspaceRoot, outRel), `${yamlStringify(payload)}`, "utf-8");
276
+ await fs.writeFile(path.join(workspaceRoot, outRel), `${yamlStringify(payload)}`);
273
277
  indexRefreshed = true;
274
278
  if (outputFormat === "pretty") {
275
279
  logger.info(`rfc.archive: refreshed ${outRel} (${entries.length} entries)`);
@@ -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
 
16
16
  import { listRfcFiles, readAndParseRfc } from "../frontmatter-io.ts";
@@ -117,7 +117,7 @@ async function loadFeatureKeysForApps(
117
117
  "features.ts",
118
118
  );
119
119
  try {
120
- const source = await fs.readFile(featuresPath, "utf-8");
120
+ const source = await fs.readFile(featuresPath);
121
121
  result.set(siteName, extractDefinedFeatureKeysFromSource(source));
122
122
  } catch {
123
123
  // features.ts not found for this app — skip
@@ -165,7 +165,9 @@ export async function runRfcCheck(
165
165
  if (!isLiteralFsPath(declaredPath)) continue;
166
166
  const absPath = path.join(workspaceRoot, declaredPath);
167
167
  try {
168
- await fs.access(absPath);
168
+ await fs.exists(absPath).then((ok) => {
169
+ if (!ok) throw Object.assign(new Error("ENOENT"), { code: "ENOENT" });
170
+ });
169
171
  } catch {
170
172
  violations.push({
171
173
  rfcId,
@@ -25,8 +25,9 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
25
25
  </CHANGE_SUMMARY>
26
26
  */
27
27
 
28
- import { execFile } from "node:child_process";
29
- import { readFile, unlink, mkdir } from "node:fs/promises";
28
+ import { execFile, writeFileSync } from "../../../src/utils/sync-fs.ts";
29
+ import { ambientIo, resolveIo } from "../../../src/utils/io.ts";
30
+
30
31
  import { join, dirname } from "node:path";
31
32
 
32
33
  import { writeFileAtomic } from "../../../src/utils/fs-atomic.ts";
@@ -43,6 +44,10 @@ import { evaluateAcceptanceCriteria } from "./validate-rules.ts";
43
44
  import { toIsoDate } from "./shared.ts";
44
45
  import { RFC_DIR, RFC_METADATA_CUTOFF, RFC_PROBE_BINDING_CUTOFF } from "../types.ts";
45
46
  import type { RfcStatus, RfcImplementStampViolation, RfcImplementStampResult } from "../types.ts";
47
+
48
+ // Ambient default for helper fns without a context param — handlers override
49
+ // with `const io = resolveIo(context.io)` inside their own scope.
50
+ const io = ambientIo;
46
51
  import type {
47
52
  ForgeCommandInput,
48
53
  ForgeCommandResult,
@@ -162,16 +167,15 @@ async function acquireRfcLock(
162
167
  ): Promise<{ acquired: boolean; lockPath: string }> {
163
168
  const lockPath = lockFilePath(workspaceRoot, rfcId);
164
169
  const lockDir = dirname(lockPath);
165
- await mkdir(lockDir, { recursive: true });
170
+ await io.mkdir(lockDir);
166
171
 
167
172
  // Atomic lock acquisition via O_EXCL file creation
168
- const { open } = await import("node:fs/promises");
169
173
  try {
170
- const handle = await open(lockPath, "wx");
171
- await handle.writeFile(
174
+ writeFileSync(
175
+ lockPath,
172
176
  JSON.stringify({ pid: process.pid, acquiredAt: new Date().toISOString() }),
177
+ { flag: "wx" },
173
178
  );
174
- await handle.close();
175
179
  return { acquired: true, lockPath };
176
180
  } catch {
177
181
  return { acquired: false, lockPath };
@@ -180,7 +184,7 @@ async function acquireRfcLock(
180
184
 
181
185
  async function releaseRfcLock(lockPath: string): Promise<void> {
182
186
  try {
183
- await unlink(lockPath);
187
+ await io.rm(lockPath);
184
188
  } catch {
185
189
  // Lock file already removed — safe
186
190
  }
@@ -195,7 +199,7 @@ async function checkExistingEvidence(
195
199
  const slug = rfcId.toLowerCase();
196
200
  const evidencePath = join(workspaceRoot, VERIFICATION_DIR, `${slug}.generated.yaml`);
197
201
  try {
198
- const content = await readFile(evidencePath, "utf-8");
202
+ const content = await io.readFile(evidencePath);
199
203
  const evidence = yamlParse(content) as { overall?: string };
200
204
  return { exists: true, overall: String(evidence.overall ?? "") };
201
205
  } catch {
@@ -239,6 +243,7 @@ export async function runRfcImplementStamp(
239
243
  input: ForgeCommandInput,
240
244
  context: ForgeRuntimeContext,
241
245
  ): Promise<ForgeCommandResult<RfcImplementStampResult>> {
246
+ const io = resolveIo(context.io);
242
247
  const { workspaceRoot, logger, outputFormat, dryRun } = context;
243
248
  const rfcDirPath = join(workspaceRoot, RFC_DIR);
244
249
 
@@ -437,7 +442,7 @@ export async function runRfcImplementStamp(
437
442
  try {
438
443
  // ── Atomic mutation ──────────────────────────────────────────────────────
439
444
  const rfcFilePath = join(rfcDirPath, targetFile);
440
- const rfcSource = await readFile(rfcFilePath, "utf-8");
445
+ const rfcSource = await io.readFile(rfcFilePath);
441
446
 
442
447
  const today = toIsoDate(new Date());
443
448
  const stampedAt = new Date().toISOString();
@@ -16,7 +16,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
16
16
  </CHANGE_SUMMARY>
17
17
  */
18
18
 
19
- import fs from "node:fs/promises";
19
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
20
20
  import path from "node:path";
21
21
  import { parse as yamlParse, stringify as yamlStringify } from "yaml";
22
22
 
@@ -78,7 +78,7 @@ export async function runRfcIndexGenerate(
78
78
  count: entries.length,
79
79
  entries,
80
80
  };
81
- await fs.writeFile(path.join(workspaceRoot, outRel), `${yamlStringify(payload)}`, "utf-8");
81
+ await fs.writeFile(path.join(workspaceRoot, outRel), `${yamlStringify(payload)}`);
82
82
  written = outRel;
83
83
  }
84
84
 
@@ -166,7 +166,7 @@ export async function runRfcIndexValidate(
166
166
  // RFC-IDX-01: missing index file
167
167
  let indexContent: string;
168
168
  try {
169
- indexContent = await fs.readFile(indexPath, "utf-8");
169
+ indexContent = await fs.readFile(indexPath);
170
170
  } catch {
171
171
  violations.push({
172
172
  rule: "RFC-IDX-01",
@@ -18,8 +18,8 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
18
18
  </CHANGE_SUMMARY>
19
19
  */
20
20
 
21
- import { readFile } from "node:fs/promises";
22
21
  import path from "node:path";
22
+ import { ambientIo, resolveIo } from "../../../src/utils/io.ts";
23
23
  import { parse as yamlParse } from "yaml";
24
24
 
25
25
  import type { CommandRegistry } from "../../../src/types.ts";
@@ -42,10 +42,14 @@ import type {
42
42
  import { RFC_DIR, RFC_METADATA_CUTOFF } from "../types.ts";
43
43
  import { commandBuckets } from "./shared.ts";
44
44
 
45
+ // Ambient default for helper fns without a context param — handlers override
46
+ // with `const io = resolveIo(context.io)` inside their own scope.
47
+ const io = ambientIo;
48
+
45
49
  async function loadManifestCommandNames(workspaceRoot: string): Promise<Set<string>> {
46
50
  const manifestPath = path.join(workspaceRoot, "docs", "command-manifest.generated.yaml");
47
51
  try {
48
- const raw = await readFile(manifestPath, "utf-8");
52
+ const raw = await io.readFile(manifestPath);
49
53
  const manifest = yamlParse(raw) as { commands?: Array<{ name: string }> };
50
54
  return new Set((manifest.commands ?? []).map((c) => c.name));
51
55
  } catch {
@@ -195,6 +199,7 @@ export async function runRfcCommandLifecycleValidate(
195
199
  input: ForgeCommandInput,
196
200
  context: ForgeRuntimeContext,
197
201
  ): Promise<ForgeCommandResult<RfcCommandLifecycleValidationResult>> {
202
+ const _io = resolveIo(context.io);
198
203
  const { workspaceRoot, logger, outputFormat } = context;
199
204
  const rfcDirPath = path.join(workspaceRoot, RFC_DIR);
200
205
  const targetId = input.flags["id"] as string | undefined;
@@ -19,7 +19,8 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
19
19
  </CHANGE_SUMMARY>
20
20
  */
21
21
 
22
- import fs from "node:fs/promises";
22
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
23
+ import { writeFileSync } from "../../../src/utils/sync-fs.ts";
23
24
  import path from "node:path";
24
25
  import { toKebabCase } from "../../../src/utils/string-utils.ts";
25
26
  import { listRfcFiles, readAndParseRfc } from "../frontmatter-io.ts";
@@ -190,7 +191,7 @@ export async function runRfcCreate(
190
191
  const templatePath = resolveRfcTemplate(workspaceRoot);
191
192
  let templateContent: string;
192
193
  try {
193
- templateContent = await fs.readFile(templatePath, "utf-8");
194
+ templateContent = await fs.readFile(templatePath);
194
195
  } catch {
195
196
  throw new Error(`RFC template not found at ${templatePath}.`);
196
197
  }
@@ -250,14 +251,14 @@ export async function runRfcCreate(
250
251
  const claimPath = path.join(rfcDirPath, `${nextSlug}.claim`);
251
252
 
252
253
  try {
253
- await fs.writeFile(claimPath, `${process.pid}\n`, { flag: "wx" });
254
+ writeFileSync(claimPath, `${process.pid}\n`, { flag: "wx" });
254
255
  } catch (err) {
255
256
  if ((err as NodeJS.ErrnoException).code === "EEXIST") {
256
257
  // Stale claim (crashed create) → reclaim and retry the same id.
257
258
  // Live claim → another create holds this id — move to the next.
258
259
  const st = await fs.stat(claimPath).catch(() => null);
259
260
  if (st && Date.now() - st.mtimeMs > CLAIM_STALE_MS) {
260
- await fs.rm(claimPath, { force: true });
261
+ await fs.rm(claimPath);
261
262
  } else {
262
263
  candidate++;
263
264
  }
@@ -283,11 +284,11 @@ export async function runRfcCreate(
283
284
  content = content.replace(/^# RFC-0000: .+$/m, `# ${nextId}: ${title}`);
284
285
 
285
286
  const targetPath = path.join(rfcDirPath, fileName);
286
- await fs.writeFile(targetPath, content, { flag: "wx" });
287
+ writeFileSync(targetPath, content, { flag: "wx" });
287
288
  relativeFile = path.join(RFC_DIR, fileName);
288
289
  allocated = true;
289
290
  } finally {
290
- await fs.rm(claimPath, { force: true });
291
+ await fs.rm(claimPath);
291
292
  }
292
293
  if (allocated) break;
293
294
  }
@@ -10,8 +10,8 @@
10
10
  </CHANGE_SUMMARY>
11
11
  */
12
12
 
13
- import fs from "node:fs/promises";
14
- import { existsSync } from "node:fs";
13
+ import { ambientIo as fs } from "../../../src/utils/io.ts";
14
+ import { existsSync } from "../../../src/utils/sync-fs.ts";
15
15
  import path from "node:path";
16
16
  import { fileURLToPath } from "node:url";
17
17
 
@@ -38,7 +38,7 @@ export async function loadInvariantIds(
38
38
  const re = new RegExp(`^##\\s+${prefix}-(\\d+)\\b`, "gm");
39
39
  for (const rel of relPaths) {
40
40
  try {
41
- const src = await fs.readFile(path.join(workspaceRoot, rel), "utf-8");
41
+ const src = await fs.readFile(path.join(workspaceRoot, rel));
42
42
  for (const m of src.matchAll(re)) ids.add(parseInt(m[1]!, 10));
43
43
  } catch {
44
44
  // Doc not present at this path — try the next candidate.
@@ -20,8 +20,8 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
20
20
  </CHANGE_SUMMARY>
21
21
  */
22
22
 
23
- import { readFile } from "node:fs/promises";
24
23
  import { join, basename } from "node:path";
24
+ import { ambientIo, resolveIo } from "../../../src/utils/io.ts";
25
25
 
26
26
  import { toKebabCase } from "../../../src/utils/string-utils.ts";
27
27
  import { writeFileAtomic } from "../../../src/utils/fs-atomic.ts";
@@ -37,12 +37,16 @@ import type {
37
37
  } from "../../../src/types.ts";
38
38
  import { toIsoDate } from "./shared.ts";
39
39
 
40
+ // Ambient default for helper fns without a context param — handlers override
41
+ // with `const io = resolveIo(context.io)` inside their own scope.
42
+ const io = ambientIo;
43
+
40
44
  const DNA_REGISTRY_PATH = "docs/architecture-dna.md";
41
45
  const DNA_HEADING_RE = /^##\s+DNA-(\d+)\b/gm;
42
46
 
43
47
  async function validateDnaIds(workspaceRoot: string, ids: string[]): Promise<string[]> {
44
48
  const errors: string[] = [];
45
- const registrySrc = await readFile(join(workspaceRoot, DNA_REGISTRY_PATH), "utf-8");
49
+ const registrySrc = await io.readFile(join(workspaceRoot, DNA_REGISTRY_PATH));
46
50
  const knownDna = new Set<string>();
47
51
  for (const m of registrySrc.matchAll(DNA_HEADING_RE)) {
48
52
  knownDna.add(`DNA-${m[1]}`);
@@ -68,6 +72,7 @@ export async function runRfcSupersedePropose(
68
72
  input: ForgeCommandInput,
69
73
  context: ForgeRuntimeContext,
70
74
  ): Promise<ForgeCommandResult<RfcSupersedeProposeResult>> {
75
+ const io = resolveIo(context.io);
71
76
  const { workspaceRoot, logger, outputFormat } = context;
72
77
  const rfcDirPath = join(workspaceRoot, RFC_DIR);
73
78
 
@@ -147,7 +152,7 @@ export async function runRfcSupersedePropose(
147
152
  const templatePath = resolveRfcTemplate(workspaceRoot);
148
153
  let templateContent: string;
149
154
  try {
150
- templateContent = await readFile(templatePath, "utf-8");
155
+ templateContent = await io.readFile(templatePath);
151
156
  } catch {
152
157
  throw new Error(`RFC template not found at ${templatePath}.`);
153
158
  }
@@ -168,7 +168,10 @@ describe("V-38: document readiness completeness (RFC-1006)", () => {
168
168
  const body = BASE_BODY.replace(
169
169
  "DOCUMENT_READINESS_HERE",
170
170
  "## Document readiness\n\n- [ ] DR-1: alternatives listed",
171
- ).replace("ACCEPTANCE_HERE", "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)");
171
+ ).replace(
172
+ "ACCEPTANCE_HERE",
173
+ "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)",
174
+ );
172
175
  const parsed = makeParsed("accepted", body);
173
176
  const violations = await runValidate(parsed);
174
177
  const v38 = filterRule(violations, "V-38");
@@ -180,7 +183,10 @@ describe("V-38: document readiness completeness (RFC-1006)", () => {
180
183
  const body = BASE_BODY.replace(
181
184
  "DOCUMENT_READINESS_HERE",
182
185
  "## Document readiness\n\n- [x] DR-1: alternatives listed (evidence: file: test.md:1)",
183
- ).replace("ACCEPTANCE_HERE", "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)");
186
+ ).replace(
187
+ "ACCEPTANCE_HERE",
188
+ "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)",
189
+ );
184
190
  const parsed = makeParsed("accepted", body);
185
191
  const violations = await runValidate(parsed);
186
192
  const v38 = filterRule(violations, "V-38");
@@ -191,7 +197,10 @@ describe("V-38: document readiness completeness (RFC-1006)", () => {
191
197
  const body = BASE_BODY.replace(
192
198
  "DOCUMENT_READINESS_HERE",
193
199
  "## Document readiness\n\n- [ ] DR-1: alternatives listed",
194
- ).replace("ACCEPTANCE_HERE", "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)");
200
+ ).replace(
201
+ "ACCEPTANCE_HERE",
202
+ "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)",
203
+ );
195
204
  const parsed = makeParsed("accepted", body, { createdAt: "2026-08-01" });
196
205
  const violations = await runValidate(parsed);
197
206
  const v38 = filterRule(violations, "V-38");
@@ -202,7 +211,10 @@ describe("V-38: document readiness completeness (RFC-1006)", () => {
202
211
  const body = BASE_BODY.replace(
203
212
  "DOCUMENT_READINESS_HERE",
204
213
  "## Document readiness\n\n- [ ] DR-1: alternatives listed",
205
- ).replace("ACCEPTANCE_HERE", "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)");
214
+ ).replace(
215
+ "ACCEPTANCE_HERE",
216
+ "- [x] AC-1: test (evidence: test.ts:1)\n- [x] AC-2: test2 (evidence: test.ts:2)\n- [x] AC-3: test3 (evidence: test.ts:3)",
217
+ );
206
218
  const parsed = makeParsed("draft", body);
207
219
  const violations = await runValidate(parsed);
208
220
  const v38 = filterRule(violations, "V-38");
@@ -470,8 +482,8 @@ describe("Pre-cutoff exemption (RFC-1006)", () => {
470
482
  );
471
483
  const parsed = makeParsed("accepted", body, { createdAt: "2026-08-01" });
472
484
  const violations = await runValidate(parsed);
473
- const newRules = violations.filter(
474
- (v) => ["V-38", "V-39", "V-40", "V-41", "V-42"].includes(v.rule),
485
+ const newRules = violations.filter((v) =>
486
+ ["V-38", "V-39", "V-40", "V-41", "V-42"].includes(v.rule),
475
487
  );
476
488
  expect(newRules).toHaveLength(0);
477
489
  });
@@ -20,8 +20,9 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
20
20
  */
21
21
 
22
22
  import path from "node:path";
23
- import { readFile, stat } from "node:fs/promises";
24
- import { execFile } from "node:child_process";
23
+ import { ambientIo } from "../../../src/utils/io.ts";
24
+
25
+ import { execFile } from "../../../src/utils/sync-fs.ts";
25
26
 
26
27
  import { parse as yamlParse } from "yaml";
27
28
  import { validateAcceptanceShape } from "../acceptance.ts";
@@ -43,6 +44,10 @@ import {
43
44
  import type { ProbeCoverageReport, AcceptanceProbe } from "../types.ts";
44
45
  import { DNA_DOCS, AP_DOCS } from "./shared.ts";
45
46
 
47
+ // Ambient default for helper fns without a context param — handlers override
48
+ // with `const io = resolveIo(context.io)` inside their own scope.
49
+ const io = ambientIo;
50
+
46
51
  const DNA_DOC = DNA_DOCS[0]!;
47
52
  const AP_DOC = AP_DOCS[0]!;
48
53
 
@@ -831,7 +836,7 @@ export async function validateSingleRfc(
831
836
  } else if (evidence.startsWith("test:")) {
832
837
  const testPath = evidence.slice("test:".length).trim();
833
838
  try {
834
- await stat(path.join(workspaceRoot, testPath));
839
+ await io.stat(path.join(workspaceRoot, testPath));
835
840
  } catch {
836
841
  addViolation(
837
842
  rfcId,
@@ -844,7 +849,7 @@ export async function validateSingleRfc(
844
849
  const lastColon = evidence.lastIndexOf(":");
845
850
  const filePath = evidence.slice(0, lastColon).trim();
846
851
  try {
847
- await stat(path.join(workspaceRoot, filePath));
852
+ await io.stat(path.join(workspaceRoot, filePath));
848
853
  } catch {
849
854
  addViolation(
850
855
  rfcId,
@@ -1110,7 +1115,7 @@ export async function validateSingleRfc(
1110
1115
  let evidenceOk = false;
1111
1116
  let evidenceOverall = "";
1112
1117
  try {
1113
- const evidenceContent = await readFile(evidenceAbsPath, "utf-8");
1118
+ const evidenceContent = await io.readFile(evidenceAbsPath);
1114
1119
  const evidence = yamlParse(evidenceContent) as { overall?: string };
1115
1120
  evidenceOverall = String(evidence.overall ?? "");
1116
1121
  evidenceOk = evidenceOverall === "pass";
@@ -0,0 +1,71 @@
1
+ /*
2
+ <MODULE_CONTRACT>
3
+ <purpose>Unit tests for runRfcValidate flag handling — the --id guard that
4
+ rejects non-string values before file scanning.</purpose>
5
+ <non-goals>
6
+ <item>Do not duplicate validate-rules coverage — V-rule behavior lives in validate-rules*.test.ts.</item>
7
+ </non-goals>
8
+ </MODULE_CONTRACT>
9
+ <CHANGE_SUMMARY>
10
+ <item>Initial test — non-string --id (boolean/array from unvalidated flag input) throws a clear flag error instead of TypeError in rfcFileMatchesId.</item>
11
+ </CHANGE_SUMMARY>
12
+ */
13
+
14
+ import { test, expect, describe } from "vitest";
15
+ import { mkdtempSync, rmSync } from "node:fs";
16
+ import { join } from "node:path";
17
+ import { tmpdir } from "node:os";
18
+ import { runRfcValidate } from "./validate.ts";
19
+ import type {
20
+ ForgeCommandInput,
21
+ ForgeFlagValue,
22
+ ForgeRuntimeContext,
23
+ } from "../../../src/types.ts";
24
+
25
+ function makeContext(workspaceRoot: string): ForgeRuntimeContext {
26
+ return {
27
+ workspaceRoot,
28
+ logger: {
29
+ info: () => {},
30
+ success: () => {},
31
+ warn: () => {},
32
+ error: () => {},
33
+ section: () => {},
34
+ },
35
+ dryRun: false,
36
+ outputFormat: "json",
37
+ };
38
+ }
39
+
40
+ describe("runRfcValidate --id flag guard", () => {
41
+ test.each([
42
+ ["boolean true", true],
43
+ ["string array", ["rfc-0001", "rfc-0002"]],
44
+ ])("non-string --id (%s) throws a clear error", async (_label, id) => {
45
+ const dir = mkdtempSync(join(tmpdir(), "rfc-validate-id-"));
46
+ try {
47
+ const input: ForgeCommandInput = {
48
+ argv: [],
49
+ flags: { id: id as ForgeFlagValue },
50
+ };
51
+ await expect(runRfcValidate(input, makeContext(dir))).rejects.toThrow(
52
+ 'Flag "--id" for command "rfc.validate" requires a single string value.',
53
+ );
54
+ } finally {
55
+ rmSync(dir, { recursive: true, force: true });
56
+ }
57
+ });
58
+
59
+ test("missing --id runs the all-files path without throwing the guard", async () => {
60
+ const dir = mkdtempSync(join(tmpdir(), "rfc-validate-noid-"));
61
+ try {
62
+ const result = await runRfcValidate(
63
+ { argv: [], flags: {} },
64
+ makeContext(dir),
65
+ );
66
+ expect(result.data?.status).toBe("pass");
67
+ } finally {
68
+ rmSync(dir, { recursive: true, force: true });
69
+ }
70
+ });
71
+ });
@@ -13,6 +13,7 @@ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten
13
13
  <item>RFC-1097: sweep — werkstatt-engine clean
14
14
 
15
15
  Sweep batch 4: 73 Compass headers on headerless engine files (certification, component-runtime, isolation, evolution, testing), real KEY_DECISIONS on 75 files (kernel, cache, dht, swim, gitmesh, runtime), ~80 purpose expansions (CONTRACT-02/PURPOSE-02), non-goals on 13 CONTRACT-03 files, CS-07 history literal fix repo-wide (253 files). Policy: .template.ts/.template.astro excludedPaths. werkstatt-engine now 0 diagnostics.</item>
16
+ <item>Guard --id against non-string values (boolean/array from unvalidated flag input) — throws a clear flag error instead of TypeError in rfcFileMatchesId.</item>
16
17
  </CHANGE_SUMMARY>
17
18
  */
18
19
 
@@ -48,7 +49,11 @@ export async function runRfcValidate(
48
49
  const { workspaceRoot, logger, outputFormat } = context;
49
50
  const rfcDirPath = path.join(workspaceRoot, RFC_DIR);
50
51
 
51
- const targetId = input.flags["id"] as string | undefined;
52
+ const rawId = input.flags["id"];
53
+ if (rawId !== undefined && typeof rawId !== "string") {
54
+ throw new Error(`Flag "--id" for command "rfc.validate" requires a single string value.`);
55
+ }
56
+ const targetId = rawId as string | undefined;
52
57
 
53
58
  const allFiles = await listRfcFiles(rfcDirPath);
54
59
  const filesToValidate = targetId
@@ -77,7 +77,9 @@ describe("rfc.create — RFC-1138 concurrent id allocation", () => {
77
77
  const ids = results.map((r) => (r.data as { id: string }).id);
78
78
  expect(new Set(ids).size).toBe(5);
79
79
 
80
- const files = (await fs.readdir(rfcDir)).filter((f) => f.startsWith("rfc-") && f !== "rfc-0000-template.md");
80
+ const files = (await fs.readdir(rfcDir)).filter(
81
+ (f) => f.startsWith("rfc-") && f !== "rfc-0000-template.md",
82
+ );
81
83
  expect(files).toHaveLength(5);
82
84
  });
83
85
 
@@ -94,7 +96,11 @@ describe("rfc.create — RFC-1138 concurrent id allocation", () => {
94
96
  test("AC-5: pre-existing highest id is respected after a collision", async () => {
95
97
  // Seed rfc-0001 so the first create takes 0002; a file racing in at 0002
96
98
  // forces the retry path to land on 0003.
97
- await fs.writeFile(path.join(rfcDir, "rfc-0001-seeded.md"), "---\nid: RFC-0001\n---\n", "utf-8");
99
+ await fs.writeFile(
100
+ path.join(rfcDir, "rfc-0001-seeded.md"),
101
+ "---\nid: RFC-0001\n---\n",
102
+ "utf-8",
103
+ );
98
104
  const winner = runRfcCreate(makeInput("Winner"), makeContext(tmpDir));
99
105
  // Interleave a manual claim at the id the scan will compute.
100
106
  const claim = (async () => {
@@ -111,7 +117,9 @@ describe("rfc.create — RFC-1138 concurrent id allocation", () => {
111
117
  const id = (result.data as { id: string }).id;
112
118
  // Either the create won 0002 (interloper lost the wx race) or it retried to 0003.
113
119
  expect(["RFC-0002", "RFC-0003"]).toContain(id);
114
- const files = (await fs.readdir(rfcDir)).filter((f) => f.startsWith("rfc-") && f !== "rfc-0000-template.md");
120
+ const files = (await fs.readdir(rfcDir)).filter(
121
+ (f) => f.startsWith("rfc-") && f !== "rfc-0000-template.md",
122
+ );
115
123
  // Seeded + interloper (if it won) + create output — never a silent overwrite.
116
124
  expect(files.length).toBeGreaterThanOrEqual(2);
117
125
  });