@warpgogol/forge 5.2.3 → 5.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (584) hide show
  1. package/AGENTS.md +34 -2
  2. package/README.md +1 -1
  3. package/README.uk.md +8 -8
  4. package/bin/cli.ts +1 -0
  5. package/dist/bin/cli.js +1 -0
  6. package/dist/bin/cli.js.map +1 -1
  7. package/dist/os/adr/adr.module.d.ts.map +1 -1
  8. package/dist/os/adr/adr.module.js +8 -3
  9. package/dist/os/adr/adr.module.js.map +1 -1
  10. package/dist/os/adr/frontmatter-io.js +5 -5
  11. package/dist/os/adr/frontmatter-io.js.map +1 -1
  12. package/dist/os/adr/handlers/archive.d.ts.map +1 -1
  13. package/dist/os/adr/handlers/archive.js +10 -4
  14. package/dist/os/adr/handlers/archive.js.map +1 -1
  15. package/dist/os/adr/handlers/implement-stamp.d.ts.map +1 -1
  16. package/dist/os/adr/handlers/implement-stamp.js +10 -9
  17. package/dist/os/adr/handlers/implement-stamp.js.map +1 -1
  18. package/dist/os/adr/handlers/list-create.js +5 -5
  19. package/dist/os/adr/handlers/list-create.js.map +1 -1
  20. package/dist/os/adr/handlers/validate.js +1 -1
  21. package/dist/os/adr/handlers/validate.js.map +1 -1
  22. package/dist/os/audit/audit.module.js +3 -3
  23. package/dist/os/audit/audit.module.js.map +1 -1
  24. package/dist/os/audit/frontmatter-io.js +5 -5
  25. package/dist/os/audit/frontmatter-io.js.map +1 -1
  26. package/dist/os/audit/handlers/archive.d.ts.map +1 -1
  27. package/dist/os/audit/handlers/archive.js +10 -4
  28. package/dist/os/audit/handlers/archive.js.map +1 -1
  29. package/dist/os/compass/compass.module.d.ts.map +1 -1
  30. package/dist/os/compass/compass.module.js +17 -1
  31. package/dist/os/compass/compass.module.js.map +1 -1
  32. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  33. package/dist/os/compass/handlers/compass-audit-handler.js +12 -5
  34. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  35. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
  36. package/dist/os/compass/handlers/compass-change-summary-handler.js +3 -2
  37. package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
  38. package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
  39. package/dist/os/compass/handlers/compass-inventory-handler.js +6 -4
  40. package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
  41. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  42. package/dist/os/compass/handlers/compass-inventory.js +10 -8
  43. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  44. package/dist/os/compass/handlers/compass-migrate-handler.js +1 -1
  45. package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -1
  46. package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -1
  47. package/dist/os/compass/handlers/compass-migrate.js +6 -3
  48. package/dist/os/compass/handlers/compass-migrate.js.map +1 -1
  49. package/dist/os/compass/handlers/git-revision.d.ts.map +1 -1
  50. package/dist/os/compass/handlers/git-revision.js +9 -6
  51. package/dist/os/compass/handlers/git-revision.js.map +1 -1
  52. package/dist/os/compass/handlers/resolve-scan-root.js +1 -1
  53. package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
  54. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
  55. package/dist/os/compass/handlers/summary-record.js +8 -4
  56. package/dist/os/compass/handlers/summary-record.js.map +1 -1
  57. package/dist/os/core/core.module.d.ts.map +1 -1
  58. package/dist/os/core/core.module.js +57 -4
  59. package/dist/os/core/core.module.js.map +1 -1
  60. package/dist/os/core/handlers/assets-helpers.d.ts.map +1 -1
  61. package/dist/os/core/handlers/assets-helpers.js +6 -3
  62. package/dist/os/core/handlers/assets-helpers.js.map +1 -1
  63. package/dist/os/core/handlers/build.js +1 -1
  64. package/dist/os/core/handlers/build.js.map +1 -1
  65. package/dist/os/core/handlers/determinism-check.d.ts.map +1 -1
  66. package/dist/os/core/handlers/determinism-check.js +10 -6
  67. package/dist/os/core/handlers/determinism-check.js.map +1 -1
  68. package/dist/os/core/handlers/dev.js +1 -1
  69. package/dist/os/core/handlers/dev.js.map +1 -1
  70. package/dist/os/core/handlers/file-size-lint.d.ts.map +1 -1
  71. package/dist/os/core/handlers/file-size-lint.js +11 -7
  72. package/dist/os/core/handlers/file-size-lint.js.map +1 -1
  73. package/dist/os/core/handlers/forge-autonomy-validate.d.ts.map +1 -1
  74. package/dist/os/core/handlers/forge-autonomy-validate.js +9 -5
  75. package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
  76. package/dist/os/core/handlers/knowledge-compact.js +1 -1
  77. package/dist/os/core/handlers/knowledge-compact.js.map +1 -1
  78. package/dist/os/core/handlers/package-health.js +1 -1
  79. package/dist/os/core/handlers/package-health.js.map +1 -1
  80. package/dist/os/core/handlers/pinned-check.js +2 -2
  81. package/dist/os/core/handlers/pinned-check.js.map +1 -1
  82. package/dist/os/core/handlers/pinned-init.d.ts.map +1 -1
  83. package/dist/os/core/handlers/pinned-init.js +9 -8
  84. package/dist/os/core/handlers/pinned-init.js.map +1 -1
  85. package/dist/os/core/handlers/pinned-validate.js +3 -3
  86. package/dist/os/core/handlers/pinned-validate.js.map +1 -1
  87. package/dist/os/core/handlers/profile-resolve.js +1 -1
  88. package/dist/os/core/handlers/profile-resolve.js.map +1 -1
  89. package/dist/os/core/handlers/public-surface.js +1 -1
  90. package/dist/os/core/handlers/public-surface.js.map +1 -1
  91. package/dist/os/core/handlers/release-prepare.d.ts.map +1 -1
  92. package/dist/os/core/handlers/release-prepare.js +10 -6
  93. package/dist/os/core/handlers/release-prepare.js.map +1 -1
  94. package/dist/os/core/handlers/release-publish.js +6 -6
  95. package/dist/os/core/handlers/release-publish.js.map +1 -1
  96. package/dist/os/core/handlers/validate.js +1 -1
  97. package/dist/os/core/handlers/validate.js.map +1 -1
  98. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  99. package/dist/os/exploration/exploration.module.js +1 -0
  100. package/dist/os/exploration/exploration.module.js.map +1 -1
  101. package/dist/os/exploration/frontmatter-io.js +4 -4
  102. package/dist/os/exploration/frontmatter-io.js.map +1 -1
  103. package/dist/os/exploration/handlers/archive.js +3 -3
  104. package/dist/os/exploration/handlers/archive.js.map +1 -1
  105. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  106. package/dist/os/mission/handlers/archive.js +22 -19
  107. package/dist/os/mission/handlers/archive.js.map +1 -1
  108. package/dist/os/mission/mission.module.js +3 -3
  109. package/dist/os/mission/mission.module.js.map +1 -1
  110. package/dist/os/naming/naming-convention.d.ts.map +1 -1
  111. package/dist/os/naming/naming-convention.js +7 -3
  112. package/dist/os/naming/naming-convention.js.map +1 -1
  113. package/dist/os/naming/naming.module.d.ts.map +1 -1
  114. package/dist/os/naming/naming.module.js +4 -3
  115. package/dist/os/naming/naming.module.js.map +1 -1
  116. package/dist/os/notes/notes.module.d.ts.map +1 -1
  117. package/dist/os/notes/notes.module.js +6 -3
  118. package/dist/os/notes/notes.module.js.map +1 -1
  119. package/dist/os/plan/frontmatter-io.js +5 -5
  120. package/dist/os/plan/frontmatter-io.js.map +1 -1
  121. package/dist/os/plan/handlers/archive.d.ts.map +1 -1
  122. package/dist/os/plan/handlers/archive.js +10 -4
  123. package/dist/os/plan/handlers/archive.js.map +1 -1
  124. package/dist/os/plan/plan.module.js +3 -3
  125. package/dist/os/plan/plan.module.js.map +1 -1
  126. package/dist/os/plugin/plugin.module.d.ts.map +1 -1
  127. package/dist/os/plugin/plugin.module.js +6 -3
  128. package/dist/os/plugin/plugin.module.js.map +1 -1
  129. package/dist/os/program/discovery.js +2 -2
  130. package/dist/os/program/discovery.js.map +1 -1
  131. package/dist/os/program/handlers/complete.js +1 -1
  132. package/dist/os/program/handlers/complete.js.map +1 -1
  133. package/dist/os/program/handlers/lease.js +1 -1
  134. package/dist/os/program/handlers/lease.js.map +1 -1
  135. package/dist/os/program/handlers/seal.js +1 -1
  136. package/dist/os/program/handlers/seal.js.map +1 -1
  137. package/dist/os/program/lease.js +1 -1
  138. package/dist/os/program/lease.js.map +1 -1
  139. package/dist/os/program/program.module.d.ts.map +1 -1
  140. package/dist/os/program/program.module.js +9 -3
  141. package/dist/os/program/program.module.js.map +1 -1
  142. package/dist/os/queue/index.js +1 -1
  143. package/dist/os/queue/manifest.d.ts.map +1 -1
  144. package/dist/os/queue/manifest.js +4 -8
  145. package/dist/os/queue/manifest.js.map +1 -1
  146. package/dist/os/rfc/acceptance.d.ts.map +1 -1
  147. package/dist/os/rfc/acceptance.js +10 -6
  148. package/dist/os/rfc/acceptance.js.map +1 -1
  149. package/dist/os/rfc/decision-log.d.ts.map +1 -1
  150. package/dist/os/rfc/decision-log.js +4 -3
  151. package/dist/os/rfc/decision-log.js.map +1 -1
  152. package/dist/os/rfc/dna-trace.d.ts.map +1 -1
  153. package/dist/os/rfc/dna-trace.js +7 -2
  154. package/dist/os/rfc/dna-trace.js.map +1 -1
  155. package/dist/os/rfc/frontmatter-io.js +5 -5
  156. package/dist/os/rfc/frontmatter-io.js.map +1 -1
  157. package/dist/os/rfc/handlers/archive.d.ts.map +1 -1
  158. package/dist/os/rfc/handlers/archive.js +11 -5
  159. package/dist/os/rfc/handlers/archive.js.map +1 -1
  160. package/dist/os/rfc/handlers/check.d.ts.map +1 -1
  161. package/dist/os/rfc/handlers/check.js +6 -3
  162. package/dist/os/rfc/handlers/check.js.map +1 -1
  163. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  164. package/dist/os/rfc/handlers/implement-stamp.js +11 -10
  165. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  166. package/dist/os/rfc/handlers/index-graph.js +3 -3
  167. package/dist/os/rfc/handlers/index-graph.js.map +1 -1
  168. package/dist/os/rfc/handlers/lifecycle.d.ts.map +1 -1
  169. package/dist/os/rfc/handlers/lifecycle.js +6 -2
  170. package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
  171. package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
  172. package/dist/os/rfc/handlers/list-create.js +7 -6
  173. package/dist/os/rfc/handlers/list-create.js.map +1 -1
  174. package/dist/os/rfc/handlers/shared.js +3 -3
  175. package/dist/os/rfc/handlers/shared.js.map +1 -1
  176. package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
  177. package/dist/os/rfc/handlers/supersede-propose.js +7 -3
  178. package/dist/os/rfc/handlers/supersede-propose.js.map +1 -1
  179. package/dist/os/rfc/handlers/validate-rules.d.ts.map +1 -1
  180. package/dist/os/rfc/handlers/validate-rules.js +8 -5
  181. package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
  182. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  183. package/dist/os/rfc/rfc.module.js +44 -4
  184. package/dist/os/rfc/rfc.module.js.map +1 -1
  185. package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
  186. package/dist/os/rfc/verification-evidence.js +9 -5
  187. package/dist/os/rfc/verification-evidence.js.map +1 -1
  188. package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
  189. package/dist/os/rfc/verification-refresh.js +4 -3
  190. package/dist/os/rfc/verification-refresh.js.map +1 -1
  191. package/dist/os/session/frontmatter-io.js +12 -12
  192. package/dist/os/session/frontmatter-io.js.map +1 -1
  193. package/dist/os/session/handlers/archive.d.ts.map +1 -1
  194. package/dist/os/session/handlers/archive.js +10 -4
  195. package/dist/os/session/handlers/archive.js.map +1 -1
  196. package/dist/os/session/handlers/metrics-aggregate.d.ts.map +1 -1
  197. package/dist/os/session/handlers/metrics-aggregate.js +9 -5
  198. package/dist/os/session/handlers/metrics-aggregate.js.map +1 -1
  199. package/dist/os/session/handlers/metrics-rfc.d.ts.map +1 -1
  200. package/dist/os/session/handlers/metrics-rfc.js +11 -8
  201. package/dist/os/session/handlers/metrics-rfc.js.map +1 -1
  202. package/dist/os/session/handlers/metrics-session.d.ts.map +1 -1
  203. package/dist/os/session/handlers/metrics-session.js +6 -3
  204. package/dist/os/session/handlers/metrics-session.js.map +1 -1
  205. package/dist/os/session/handlers/save.d.ts.map +1 -1
  206. package/dist/os/session/handlers/save.js +14 -8
  207. package/dist/os/session/handlers/save.js.map +1 -1
  208. package/dist/os/session/session.module.d.ts.map +1 -1
  209. package/dist/os/session/session.module.js +6 -0
  210. package/dist/os/session/session.module.js.map +1 -1
  211. package/dist/os/spec/live-spec-list.js +4 -4
  212. package/dist/os/spec/live-spec-list.js.map +1 -1
  213. package/dist/os/spec/live-spec-merge.js +5 -5
  214. package/dist/os/spec/live-spec-merge.js.map +1 -1
  215. package/dist/os/spec/live-spec-show.js +3 -3
  216. package/dist/os/spec/live-spec-show.js.map +1 -1
  217. package/dist/os/spec/live-spec-validate.js +4 -4
  218. package/dist/os/spec/live-spec-validate.js.map +1 -1
  219. package/dist/os/spec/spec-materialize.js +9 -9
  220. package/dist/os/spec/spec-materialize.js.map +1 -1
  221. package/dist/os/spec/spec-status.js +9 -9
  222. package/dist/os/spec/spec-status.js.map +1 -1
  223. package/dist/os/spec/spec-validate.js +7 -7
  224. package/dist/os/spec/spec-validate.js.map +1 -1
  225. package/dist/os/spec/spec.module.d.ts.map +1 -1
  226. package/dist/os/spec/spec.module.js +8 -0
  227. package/dist/os/spec/spec.module.js.map +1 -1
  228. package/dist/os/werkstatt/handlers/lock.js +16 -16
  229. package/dist/os/werkstatt/handlers/lock.js.map +1 -1
  230. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +3 -3
  231. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
  232. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
  233. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +3 -2
  234. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
  235. package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
  236. package/dist/os/werkstatt/werkstatt.module.js +6 -2
  237. package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
  238. package/dist/os/workflow/handlers.d.ts.map +1 -1
  239. package/dist/os/workflow/handlers.js +8 -5
  240. package/dist/os/workflow/handlers.js.map +1 -1
  241. package/dist/os/workflow/workflow.module.d.ts.map +1 -1
  242. package/dist/os/workflow/workflow.module.js +6 -3
  243. package/dist/os/workflow/workflow.module.js.map +1 -1
  244. package/dist/src/compass/contract-registry.js +1 -1
  245. package/dist/src/compass/contract-registry.js.map +1 -1
  246. package/dist/src/config/forge-config.d.ts +10 -1
  247. package/dist/src/config/forge-config.d.ts.map +1 -1
  248. package/dist/src/config/forge-config.js +8 -1
  249. package/dist/src/config/forge-config.js.map +1 -1
  250. package/dist/src/knowledge/budgets.js +1 -1
  251. package/dist/src/knowledge/budgets.js.map +1 -1
  252. package/dist/src/knowledge/compact.js +1 -1
  253. package/dist/src/knowledge/compact.js.map +1 -1
  254. package/dist/src/knowledge/parse.js +1 -1
  255. package/dist/src/knowledge/parse.js.map +1 -1
  256. package/dist/src/knowledge/sync.d.ts.map +1 -1
  257. package/dist/src/knowledge/sync.js +3 -5
  258. package/dist/src/knowledge/sync.js.map +1 -1
  259. package/dist/src/migration-adapters/git-utils.js +2 -2
  260. package/dist/src/migration-adapters/git-utils.js.map +1 -1
  261. package/dist/src/migration-adapters/ignored-files.js +2 -2
  262. package/dist/src/migration-adapters/ignored-files.js.map +1 -1
  263. package/dist/src/migration-adapters/node-typescript-pnpm/index.js +1 -1
  264. package/dist/src/migration-adapters/node-typescript-pnpm/index.js.map +1 -1
  265. package/dist/src/migration-adapters/phaser-pnpm/index.js +1 -1
  266. package/dist/src/migration-adapters/phaser-pnpm/index.js.map +1 -1
  267. package/dist/src/onboarding/agents-generate.d.ts +2 -0
  268. package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
  269. package/dist/src/onboarding/agents-generate.js +73 -48
  270. package/dist/src/onboarding/agents-generate.js.map +1 -1
  271. package/dist/src/onboarding/create.d.ts.map +1 -1
  272. package/dist/src/onboarding/create.js +10 -10
  273. package/dist/src/onboarding/create.js.map +1 -1
  274. package/dist/src/onboarding/doctor.d.ts +6 -0
  275. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  276. package/dist/src/onboarding/doctor.js +179 -61
  277. package/dist/src/onboarding/doctor.js.map +1 -1
  278. package/dist/src/onboarding/init.d.ts.map +1 -1
  279. package/dist/src/onboarding/init.js +30 -1
  280. package/dist/src/onboarding/init.js.map +1 -1
  281. package/dist/src/onboarding/invariant-engine.js +1 -1
  282. package/dist/src/onboarding/invariant-engine.js.map +1 -1
  283. package/dist/src/onboarding/memory-compact.d.ts +22 -0
  284. package/dist/src/onboarding/memory-compact.d.ts.map +1 -0
  285. package/dist/src/onboarding/memory-compact.js +148 -0
  286. package/dist/src/onboarding/memory-compact.js.map +1 -0
  287. package/dist/src/onboarding/memory-scaffold.d.ts +1 -0
  288. package/dist/src/onboarding/memory-scaffold.d.ts.map +1 -1
  289. package/dist/src/onboarding/memory-scaffold.js +2 -2
  290. package/dist/src/onboarding/memory-scaffold.js.map +1 -1
  291. package/dist/src/onboarding/nested-agents-generate.d.ts +4 -1
  292. package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
  293. package/dist/src/onboarding/nested-agents-generate.js +35 -6
  294. package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
  295. package/dist/src/onboarding/nested-agents-templates.d.ts.map +1 -1
  296. package/dist/src/onboarding/nested-agents-templates.js +8 -12
  297. package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
  298. package/dist/src/onboarding/npm-token-check.js +2 -2
  299. package/dist/src/onboarding/npm-token-check.js.map +1 -1
  300. package/dist/src/onboarding/prettierignore.d.ts +29 -0
  301. package/dist/src/onboarding/prettierignore.d.ts.map +1 -0
  302. package/dist/src/onboarding/prettierignore.js +231 -0
  303. package/dist/src/onboarding/prettierignore.js.map +1 -0
  304. package/dist/src/onboarding/profile-validate.d.ts.map +1 -1
  305. package/dist/src/onboarding/profile-validate.js +5 -4
  306. package/dist/src/onboarding/profile-validate.js.map +1 -1
  307. package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
  308. package/dist/src/onboarding/scaffold-project.js +35 -27
  309. package/dist/src/onboarding/scaffold-project.js.map +1 -1
  310. package/dist/src/onboarding/scaffold.js +1 -1
  311. package/dist/src/onboarding/scaffold.js.map +1 -1
  312. package/dist/src/onboarding/skill-markers.d.ts +27 -0
  313. package/dist/src/onboarding/skill-markers.d.ts.map +1 -0
  314. package/dist/src/onboarding/skill-markers.js +131 -0
  315. package/dist/src/onboarding/skill-markers.js.map +1 -0
  316. package/dist/src/onboarding/upgrade.d.ts +10 -0
  317. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  318. package/dist/src/onboarding/upgrade.js +215 -74
  319. package/dist/src/onboarding/upgrade.js.map +1 -1
  320. package/dist/src/onboarding/workspace-discovery.d.ts +1 -1
  321. package/dist/src/onboarding/workspace-discovery.d.ts.map +1 -1
  322. package/dist/src/onboarding/workspace-discovery.js +15 -3
  323. package/dist/src/onboarding/workspace-discovery.js.map +1 -1
  324. package/dist/src/pipeline-status.d.ts +6 -5
  325. package/dist/src/pipeline-status.d.ts.map +1 -1
  326. package/dist/src/pipeline-status.js +24 -19
  327. package/dist/src/pipeline-status.js.map +1 -1
  328. package/dist/src/profiles/stack-profile.js +1 -1
  329. package/dist/src/profiles/stack-profile.js.map +1 -1
  330. package/dist/src/registry.d.ts +1 -1
  331. package/dist/src/registry.d.ts.map +1 -1
  332. package/dist/src/registry.js +3 -3
  333. package/dist/src/registry.js.map +1 -1
  334. package/dist/src/skill-schema.d.ts +1 -1
  335. package/dist/src/skill-schema.d.ts.map +1 -1
  336. package/dist/src/skill-schema.js +4 -1
  337. package/dist/src/skill-schema.js.map +1 -1
  338. package/dist/src/types.d.ts +116 -0
  339. package/dist/src/types.d.ts.map +1 -1
  340. package/dist/src/utils/editable-region.d.ts +46 -0
  341. package/dist/src/utils/editable-region.d.ts.map +1 -0
  342. package/dist/src/utils/editable-region.js +125 -0
  343. package/dist/src/utils/editable-region.js.map +1 -0
  344. package/dist/src/utils/fs-idempotent.d.ts +2 -1
  345. package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
  346. package/dist/src/utils/fs-idempotent.js +11 -7
  347. package/dist/src/utils/fs-idempotent.js.map +1 -1
  348. package/dist/src/utils/generated-marker.d.ts +17 -0
  349. package/dist/src/utils/generated-marker.d.ts.map +1 -1
  350. package/dist/src/utils/generated-marker.js +29 -1
  351. package/dist/src/utils/generated-marker.js.map +1 -1
  352. package/dist/src/utils/index.d.ts +3 -1
  353. package/dist/src/utils/index.d.ts.map +1 -1
  354. package/dist/src/utils/index.js +3 -1
  355. package/dist/src/utils/index.js.map +1 -1
  356. package/dist/src/utils/io.d.ts +9 -0
  357. package/dist/src/utils/io.d.ts.map +1 -0
  358. package/dist/src/utils/io.js +130 -0
  359. package/dist/src/utils/io.js.map +1 -0
  360. package/dist/src/utils/markdown-table.d.ts +21 -0
  361. package/dist/src/utils/markdown-table.d.ts.map +1 -0
  362. package/dist/src/utils/markdown-table.js +116 -0
  363. package/dist/src/utils/markdown-table.js.map +1 -0
  364. package/dist/src/utils/sync-fs.d.ts +5 -0
  365. package/dist/src/utils/sync-fs.d.ts.map +1 -0
  366. package/dist/src/utils/sync-fs.js +26 -0
  367. package/dist/src/utils/sync-fs.js.map +1 -0
  368. package/dist/src/validators/note-frontmatter-validate.js +1 -1
  369. package/dist/src/validators/note-frontmatter-validate.js.map +1 -1
  370. package/dist/src/validators/note-link-validate.js +1 -1
  371. package/dist/src/validators/note-link-validate.js.map +1 -1
  372. package/dist/src/validators/note-orphan-detect.js +1 -1
  373. package/dist/src/validators/note-orphan-detect.js.map +1 -1
  374. package/dist/src/validators/port-validate.js +1 -1
  375. package/dist/src/validators/port-validate.js.map +1 -1
  376. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  377. package/dist/src/validators/skill-validate.js +34 -13
  378. package/dist/src/validators/skill-validate.js.map +1 -1
  379. package/docs/reference/forge-yaml.md +12 -0
  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 -9
  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 +58 -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.ts +27 -19
  421. package/os/mission/mission.module.ts +38 -39
  422. package/os/naming/naming-convention.ts +9 -3
  423. package/os/naming/naming.module.ts +25 -25
  424. package/os/notes/notes.module.ts +87 -85
  425. package/os/plan/frontmatter-io.ts +5 -5
  426. package/os/plan/handlers/archive.ts +8 -4
  427. package/os/plan/plan.module.ts +33 -34
  428. package/os/plugin/plugin.module.ts +8 -6
  429. package/os/program/discovery.ts +2 -2
  430. package/os/program/handlers/complete.ts +1 -1
  431. package/os/program/handlers/lease.ts +1 -1
  432. package/os/program/handlers/seal.ts +1 -1
  433. package/os/program/lease.ts +1 -1
  434. package/os/program/program.module.ts +198 -193
  435. package/os/queue/index.ts +1 -1
  436. package/os/queue/manifest.ts +10 -9
  437. package/os/queue/queue-validate.test.ts +6 -15
  438. package/os/rfc/acceptance.ts +12 -6
  439. package/os/rfc/decision-log.ts +4 -3
  440. package/os/rfc/dna-trace.ts +8 -2
  441. package/os/rfc/frontmatter-io.ts +5 -5
  442. package/os/rfc/handlers/archive.ts +9 -5
  443. package/os/rfc/handlers/check.ts +5 -3
  444. package/os/rfc/handlers/implement-stamp.ts +15 -10
  445. package/os/rfc/handlers/index-graph.ts +3 -3
  446. package/os/rfc/handlers/lifecycle.ts +7 -2
  447. package/os/rfc/handlers/list-create.ts +7 -6
  448. package/os/rfc/handlers/shared.ts +3 -3
  449. package/os/rfc/handlers/supersede-propose.ts +8 -3
  450. package/os/rfc/handlers/validate-rules-rfc1006.test.ts +18 -6
  451. package/os/rfc/handlers/validate-rules.ts +10 -5
  452. package/os/rfc/rfc-create-concurrent.test.ts +11 -3
  453. package/os/rfc/rfc.module.ts +413 -374
  454. package/os/rfc/verification-evidence.ts +11 -5
  455. package/os/rfc/verification-refresh.ts +4 -3
  456. package/os/session/frontmatter-io.ts +14 -14
  457. package/os/session/handlers/archive.ts +8 -4
  458. package/os/session/handlers/metrics-aggregate.ts +34 -13
  459. package/os/session/handlers/metrics-rfc.ts +13 -8
  460. package/os/session/handlers/metrics-session.ts +7 -3
  461. package/os/session/handlers/save.ts +12 -8
  462. package/os/session/session.module.ts +6 -0
  463. package/os/spec/live-spec-list.ts +4 -4
  464. package/os/spec/live-spec-merge.ts +5 -5
  465. package/os/spec/live-spec-show.ts +3 -3
  466. package/os/spec/live-spec-validate.ts +4 -4
  467. package/os/spec/spec-materialize.ts +9 -9
  468. package/os/spec/spec-status.ts +9 -9
  469. package/os/spec/spec-validate.ts +7 -7
  470. package/os/spec/spec.module.ts +8 -0
  471. package/os/werkstatt/handlers/lock.ts +16 -16
  472. package/os/werkstatt/handlers/werkstatt-lock-recover.ts +3 -3
  473. package/os/werkstatt/handlers/werkstatt-operation-validate.ts +4 -2
  474. package/os/werkstatt/werkstatt.module.ts +8 -5
  475. package/os/workflow/handlers.ts +7 -5
  476. package/os/workflow/workflow.module.ts +45 -44
  477. package/package.json +1 -1
  478. package/profiles/forge-shell.yaml +3 -0
  479. package/profiles/godot-game.yaml +3 -0
  480. package/profiles/phaser-game.yaml +3 -0
  481. package/profiles/site-workshop.yaml +567 -564
  482. package/skills/fo/fo-add-tests/SKILL.md +2 -2
  483. package/skills/fo/fo-architecture/SKILL.md +2 -2
  484. package/skills/fo/fo-compass-annotate/SKILL.md +2 -2
  485. package/skills/fo/fo-design-summit/SKILL.md +2 -2
  486. package/skills/fo/fo-doc-audit/SKILL.md +2 -2
  487. package/skills/fo/fo-explore/SKILL.md +2 -2
  488. package/skills/fo/fo-extract-dna/SKILL.md +2 -2
  489. package/skills/fo/fo-fix/SKILL.md +2 -2
  490. package/skills/fo/fo-handoff/SKILL.md +2 -2
  491. package/skills/fo/fo-harvest/SKILL.md +2 -2
  492. package/skills/fo/fo-idea/SKILL.md +2 -2
  493. package/skills/fo/fo-idea-audit/SKILL.md +2 -2
  494. package/skills/fo/fo-idea-create-adr/SKILL.md +3 -3
  495. package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -3
  496. package/skills/fo/fo-idea-enhance/SKILL.md +2 -2
  497. package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +2 -2
  498. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +1 -1
  499. package/skills/fo/fo-idea-implement/SKILL.md +2 -2
  500. package/skills/fo/fo-idea-plan/SKILL.md +2 -2
  501. package/skills/fo/fo-idea-status/SKILL.md +2 -2
  502. package/skills/fo/fo-knowledge-distill/SKILL.md +2 -2
  503. package/skills/fo/fo-memory-sync/SKILL.md +2 -2
  504. package/skills/fo/fo-qa/SKILL.md +2 -2
  505. package/skills/fo/fo-review/SKILL.md +2 -2
  506. package/skills/fo/fo-session-retro/SKILL.md +2 -2
  507. package/skills/fo/fo-session-save/SKILL.md +2 -2
  508. package/skills/fo/fo-spec-ingest/SKILL.md +2 -2
  509. package/skills/fo/fo-step-commit/SKILL.md +1 -1
  510. package/skills/fo/fo-triage/SKILL.md +2 -2
  511. package/skills/meta/forge-bootstrap/SKILL.md +1 -1
  512. package/skills/meta/port-to-forge/SKILL.md +1 -1
  513. package/skills/meta/skill-create/SKILL.md +1 -1
  514. package/skills/shared/grilling/SKILL.md +1 -1
  515. package/skills/shared/grilling/learned-principles.archive.md +17 -0
  516. package/skills/shared/grilling/learned-principles.md +0 -1
  517. package/skills/shared/knowledge/learned-principles.md +6 -0
  518. package/skills/shared/my-preferences/SKILL.md +1 -1
  519. package/skills/shared/windows-ai-tooling/SKILL.md +1 -1
  520. package/skills/shared/writing-great-skills/SKILL.md +1 -1
  521. package/src/compass/contract-registry.ts +1 -1
  522. package/src/config/forge-config.ts +12 -1
  523. package/src/knowledge/__tests__/sync.test.ts +2 -7
  524. package/src/knowledge/budgets.ts +1 -1
  525. package/src/knowledge/compact.ts +1 -1
  526. package/src/knowledge/parse.ts +1 -1
  527. package/src/knowledge/sync.ts +3 -5
  528. package/src/migration-adapters/git-utils.ts +2 -2
  529. package/src/migration-adapters/ignored-files.ts +2 -2
  530. package/src/migration-adapters/node-typescript-pnpm/index.ts +1 -1
  531. package/src/migration-adapters/phaser-pnpm/index.ts +1 -1
  532. package/src/onboarding/agents-generate.ts +91 -50
  533. package/src/onboarding/create.ts +10 -10
  534. package/src/onboarding/doctor.ts +199 -59
  535. package/src/onboarding/init.ts +38 -1
  536. package/src/onboarding/invariant-engine.ts +1 -1
  537. package/src/onboarding/memory-compact.ts +189 -0
  538. package/src/onboarding/memory-scaffold.ts +2 -2
  539. package/src/onboarding/nested-agents-generate.ts +50 -5
  540. package/src/onboarding/nested-agents-templates.ts +19 -13
  541. package/src/onboarding/npm-token-check.ts +2 -2
  542. package/src/onboarding/prettierignore.ts +263 -0
  543. package/src/onboarding/profile-validate.ts +5 -4
  544. package/src/onboarding/scaffold-project.ts +38 -27
  545. package/src/onboarding/scaffold.ts +1 -1
  546. package/src/onboarding/skill-markers.ts +162 -0
  547. package/src/onboarding/templates/behavioral-layer-core.md +2 -4
  548. package/src/onboarding/upgrade.ts +285 -89
  549. package/src/onboarding/workspace-discovery.ts +16 -2
  550. package/src/pipeline-status.test.ts +1 -4
  551. package/src/pipeline-status.ts +30 -13
  552. package/src/profiles/stack-profile.ts +1 -1
  553. package/src/registry.ts +4 -4
  554. package/src/skill-schema.ts +4 -1
  555. package/src/tests/acceptance-probe-kinds.test.ts +5 -15
  556. package/src/tests/agents-generate.test.ts +32 -7
  557. package/src/tests/contract-registry.test.ts +12 -6
  558. package/src/tests/doctor-dist-freshness.test.ts +110 -0
  559. package/src/tests/doctor-fix.test.ts +142 -0
  560. package/src/tests/doctor-nested-agents.test.ts +160 -0
  561. package/src/tests/editable-generated-region.test.ts +231 -0
  562. package/src/tests/file-size-lint.test.ts +8 -12
  563. package/src/tests/fixtures/agents-generate-business-before.txt +54 -54
  564. package/src/tests/markdown-table.test.ts +107 -0
  565. package/src/tests/memory-compact.test.ts +143 -0
  566. package/src/tests/prettierignore-manage.test.ts +134 -0
  567. package/src/tests/skill-agents-sync.test.ts +168 -0
  568. package/src/tests/skill-sync-marker.test.ts +134 -0
  569. package/src/tests/skill-validate.test.ts +12 -5
  570. package/src/tests/upgrade.test.ts +87 -41
  571. package/src/tests/workspace-discovery.test.ts +28 -0
  572. package/src/types.ts +123 -0
  573. package/src/utils/editable-region.ts +156 -0
  574. package/src/utils/fs-idempotent.ts +12 -6
  575. package/src/utils/generated-marker.ts +36 -2
  576. package/src/utils/index.ts +17 -0
  577. package/src/utils/io.ts +143 -0
  578. package/src/utils/markdown-table.ts +121 -0
  579. package/src/utils/sync-fs.ts +43 -0
  580. package/src/validators/note-frontmatter-validate.ts +1 -1
  581. package/src/validators/note-link-validate.ts +1 -1
  582. package/src/validators/note-orphan-detect.ts +1 -1
  583. package/src/validators/port-validate.ts +1 -1
  584. package/src/validators/skill-validate.ts +38 -13
@@ -21,8 +21,10 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
21
21
  </CHANGE_SUMMARY>
22
22
  */
23
23
 
24
- import { readFile, readdir, stat } from "node:fs/promises";
25
- import { readFileSync, existsSync } from "node:fs";
24
+ import type { WorkspaceIO } from "../types.ts";
25
+ import { resolveIo } from "../utils/io.ts";
26
+ import { hasEditableGeneratedMarker, mergeEditableGenerated } from "../utils/index.ts";
27
+ import { readFileSync, existsSync } from "../utils/sync-fs.ts";
26
28
  import { join, relative, dirname, resolve } from "node:path";
27
29
  import { parse as parseYaml } from "yaml";
28
30
  import { forgePluginManifestSchema } from "../plugin/forge-plugin-manifest.ts";
@@ -35,7 +37,7 @@ import { resolveForgeRoot, loadForgeConfig, resolveBinding, resolveTerminology,
35
37
  import { FORGE_SKILLS, discoverPackSkills } from "../registry.ts";
36
38
  import { discoverWorkspaces } from "./workspace-discovery.ts";
37
39
  import { buildNestedAgentsMd, selectNestedTemplate } from "./nested-agents-templates.ts";
38
- import { readPackageInfo } from "./nested-agents-generate.ts";
40
+ import { readPackageInfo, generateNestedAgentsMd } from "./nested-agents-generate.ts";
39
41
  import { listStackProfiles, type StackProfile } from "../profiles/stack-profile.ts";
40
42
  import { resolveAllTerminology } from "../profiles/terminology-utils.ts";
41
43
  import { TERMINOLOGY_DEFAULTS } from "../profiles/profile-schema.ts";
@@ -47,14 +49,21 @@ import type { ParsedKnowledgeFile } from "../knowledge/index.ts";
47
49
  import { computeLayerBudgets, resolveKnowledgeBudgets, DEFAULT_KNOWLEDGE_BUDGETS } from "../knowledge/budgets.ts";
48
50
  import { detectDuplicatePrinciples } from "../knowledge/index.ts";
49
51
  import type { DuplicatePair } from "../knowledge/index.ts";
50
- import { checkMemoryLayerHealth } from "./memory-scaffold.ts";
52
+ import { checkMemoryLayerHealth, resolveMemoryBudget } from "./memory-scaffold.ts";
53
+ import { compactMemoryMd } from "./memory-compact.ts";
51
54
  import { checkInvariants } from "./invariant-engine.ts";
52
55
  import type { InvariantViolation } from "./invariant-engine.ts";
53
56
  import { checkNpmToken, workshopNeedsWarpgogolToken } from "./npm-token-check.ts";
54
- import { execSync } from "node:child_process";
55
- import fs from "node:fs";
57
+ import { execSync } from "../utils/sync-fs.ts";
58
+ import * as fs from "../utils/sync-fs.ts";
56
59
  import type { ProfilePrerequisite } from "../profiles/profile-schema.ts";
57
60
 
61
+ interface DoctorFixResult {
62
+ check: string;
63
+ action: "fixed" | "skipped" | "failed";
64
+ detail: string;
65
+ }
66
+
58
67
  interface DoctorCheck {
59
68
  name: string;
60
69
  status: "pass" | "fail" | "warn";
@@ -80,13 +89,8 @@ interface BindingNotice {
80
89
  suggestion: string;
81
90
  }
82
91
 
83
- async function pathExists(target: string): Promise<boolean> {
84
- try {
85
- await stat(target);
86
- return true;
87
- } catch {
88
- return false;
89
- }
92
+ async function pathExists(target: string, io: WorkspaceIO): Promise<boolean> {
93
+ return io.exists(target);
90
94
  }
91
95
 
92
96
  const FORBIDDEN_IMPORT_PATTERN =
@@ -95,19 +99,20 @@ const FORBIDDEN_IMPORT_PATTERN =
95
99
  async function scanForForbiddenImports(
96
100
  dir: string,
97
101
  workspaceRoot: string,
102
+ io: WorkspaceIO,
98
103
  ): Promise<ForbiddenImport[]> {
99
104
  const violations: ForbiddenImport[] = [];
100
- const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
105
+ const entries = await io.readdir(dir).catch(() => []);
101
106
 
102
107
  for (const entry of entries) {
103
108
  const fullPath = join(dir, entry.name);
104
109
 
105
- if (entry.isDirectory()) {
110
+ if (entry.isDirectory) {
106
111
  if (entry.name === "node_modules" || entry.name === "tests") continue;
107
- const sub = await scanForForbiddenImports(fullPath, workspaceRoot);
112
+ const sub = await scanForForbiddenImports(fullPath, workspaceRoot, io);
108
113
  violations.push(...sub);
109
114
  } else if (entry.name.endsWith(".ts")) {
110
- const content = await readFile(fullPath, "utf8").catch(() => "");
115
+ const content = await io.readFile(fullPath).catch(() => "");
111
116
  let match: RegExpExecArray | null;
112
117
  const pattern = new RegExp(FORBIDDEN_IMPORT_PATTERN.source, "g");
113
118
  while ((match = pattern.exec(content)) !== null) {
@@ -144,7 +149,7 @@ const BINDING_COMMAND_KEYS = [
144
149
  "commands.sessionSave",
145
150
  ];
146
151
 
147
- async function validateBindings(workspaceRoot: string): Promise<BindingValidation> {
152
+ async function validateBindings(workspaceRoot: string, io: WorkspaceIO): Promise<BindingValidation> {
148
153
  const result: BindingValidation = { resolved: [], absent: [], invalid: [], notices: [] };
149
154
 
150
155
  let config;
@@ -163,7 +168,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
163
168
  if (value === null) {
164
169
  result.absent.push(key);
165
170
  } else if (typeof value === "string") {
166
- const exists = await pathExists(join(workspaceRoot, value));
171
+ const exists = await pathExists(join(workspaceRoot, value), io);
167
172
  if (exists) {
168
173
  result.resolved.push(key);
169
174
  } else {
@@ -175,7 +180,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
175
180
  const compassDocs = resolveBinding(config, "paths.compassDocs");
176
181
  if (Array.isArray(compassDocs) && compassDocs.length > 0) {
177
182
  for (const docPath of compassDocs) {
178
- const exists = await pathExists(join(workspaceRoot, docPath));
183
+ const exists = await pathExists(join(workspaceRoot, docPath), io);
179
184
  if (exists) {
180
185
  result.resolved.push(`paths.compassDocs[${docPath}]`);
181
186
  } else {
@@ -219,6 +224,7 @@ async function validateBindings(workspaceRoot: string): Promise<BindingValidatio
219
224
  async function checkStaleKnowledgeFiles(
220
225
  workspaceRoot: string,
221
226
  forgeRoot: string,
227
+ io: WorkspaceIO,
222
228
  ): Promise<DoctorCheck> {
223
229
  const stale: string[] = [];
224
230
 
@@ -240,8 +246,8 @@ async function checkStaleKnowledgeFiles(
240
246
  const srcPath = join(skillSrcDir, kf);
241
247
  const destPath = join(agentsSkillsDir, skill.name, kf);
242
248
 
243
- const srcExists = await pathExists(srcPath);
244
- const destExists = await pathExists(destPath);
249
+ const srcExists = await pathExists(srcPath, io);
250
+ const destExists = await pathExists(destPath, io);
245
251
 
246
252
  if (srcExists && destExists) {
247
253
  // Append-only contract: local copies legitimately accumulate entries.
@@ -272,8 +278,8 @@ async function checkStaleKnowledgeFiles(
272
278
  const srcPath = join(skillSrcDir, kf);
273
279
  const destPath = join(agentsSkillsDir, skill.name, kf);
274
280
 
275
- const srcExists = await pathExists(srcPath);
276
- const destExists = await pathExists(destPath);
281
+ const srcExists = await pathExists(srcPath, io);
282
+ const destExists = await pathExists(destPath, io);
277
283
 
278
284
  if (srcExists && destExists) {
279
285
  const plan = planKnowledgeSync(srcPath, destPath);
@@ -635,7 +641,7 @@ function checkSharedKnowledgeFile(
635
641
  // Independent version packages diagnostics (RFC-0704)
636
642
  // ---------------------------------------------------------------------------
637
643
 
638
- async function checkIndependentVersionPackages(workspaceRoot: string): Promise<DoctorCheck> {
644
+ async function checkIndependentVersionPackages(workspaceRoot: string, io: WorkspaceIO): Promise<DoctorCheck> {
639
645
  let config;
640
646
  try {
641
647
  config = loadForgeConfig(workspaceRoot);
@@ -651,8 +657,8 @@ async function checkIndependentVersionPackages(workspaceRoot: string): Promise<D
651
657
  let validCount = 0;
652
658
 
653
659
  for (const pkgPath of config.independentVersionPackages) {
654
- const dirExists = await pathExists(join(workspaceRoot, pkgPath));
655
- const pkgJsonExists = await pathExists(join(workspaceRoot, pkgPath, "package.json"));
660
+ const dirExists = await pathExists(join(workspaceRoot, pkgPath), io);
661
+ const pkgJsonExists = await pathExists(join(workspaceRoot, pkgPath, "package.json"), io);
656
662
  if (!dirExists) {
657
663
  issues.push(`path '${pkgPath}' does not exist`);
658
664
  } else if (!pkgJsonExists) {
@@ -681,7 +687,7 @@ async function checkIndependentVersionPackages(workspaceRoot: string): Promise<D
681
687
  // Pack skill diagnostics (RFC-0539)
682
688
  // ---------------------------------------------------------------------------
683
689
 
684
- async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
690
+ async function checkPackSkills(workspaceRoot: string, io: WorkspaceIO): Promise<DoctorCheck> {
685
691
  let config;
686
692
  try {
687
693
  config = loadForgeConfig(workspaceRoot);
@@ -713,7 +719,7 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
713
719
  }
714
720
  dirs.add(pack.dir);
715
721
 
716
- const packDirExists = await pathExists(join(workspaceRoot, pack.dir));
722
+ const packDirExists = await pathExists(join(workspaceRoot, pack.dir), io);
717
723
  if (!packDirExists) {
718
724
  issues.push(`pack dir '${pack.dir}' does not exist`);
719
725
  }
@@ -732,12 +738,12 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
732
738
  const srcPath = join(workspaceRoot, skill.dir, skill.path);
733
739
  const destPath = join(agentsSkillsDir, skill.name, "SKILL.md");
734
740
 
735
- const srcExists = await pathExists(srcPath);
736
- const destExists = await pathExists(destPath);
741
+ const srcExists = await pathExists(srcPath, io);
742
+ const destExists = await pathExists(destPath, io);
737
743
 
738
744
  if (srcExists && destExists) {
739
- const srcContent = await readFile(srcPath, "utf8").catch(() => "");
740
- const destContent = await readFile(destPath, "utf8").catch(() => "");
745
+ const srcContent = await io.readFile(srcPath).catch(() => "");
746
+ const destContent = await io.readFile(destPath).catch(() => "");
741
747
  if (srcContent !== destContent) {
742
748
  issues.push(`stale copy of '${skill.name}'`);
743
749
  }
@@ -760,7 +766,7 @@ async function checkPackSkills(workspaceRoot: string): Promise<DoctorCheck> {
760
766
  // Pack manifest diagnostics (RFC-0941)
761
767
  // ---------------------------------------------------------------------------
762
768
 
763
- async function checkPackManifests(workspaceRoot: string): Promise<DoctorCheck> {
769
+ async function checkPackManifests(workspaceRoot: string, _io: WorkspaceIO): Promise<DoctorCheck> {
764
770
  let config;
765
771
  try {
766
772
  config = loadForgeConfig(workspaceRoot);
@@ -813,7 +819,8 @@ async function checkPackManifests(workspaceRoot: string): Promise<DoctorCheck> {
813
819
 
814
820
  async function checkNestedAgentsMd(
815
821
  workspaceRoot: string,
816
- workspaceTypes?: ProfileWorkspaceType[],
822
+ workspaceTypes: ProfileWorkspaceType[] | undefined,
823
+ io: WorkspaceIO,
817
824
  ): Promise<DoctorCheck> {
818
825
  let config;
819
826
  try {
@@ -826,7 +833,11 @@ async function checkNestedAgentsMd(
826
833
  };
827
834
  }
828
835
 
829
- const workspaces = discoverWorkspaces(workspaceRoot, workspaceTypes);
836
+ const workspaces = discoverWorkspaces(
837
+ workspaceRoot,
838
+ workspaceTypes,
839
+ config.bindings?.workspaces?.skipDirs,
840
+ );
830
841
 
831
842
  if (workspaces.length === 0) {
832
843
  return {
@@ -840,6 +851,7 @@ async function checkNestedAgentsMd(
840
851
  let missing = 0;
841
852
  let stale = 0;
842
853
  let handwritten = 0;
854
+ let unmapped = 0;
843
855
 
844
856
  for (const ws of workspaces) {
845
857
  if (!ws.hasAgentsMd) {
@@ -852,7 +864,7 @@ async function checkNestedAgentsMd(
852
864
  handwritten++;
853
865
  const suggestions: string[] = [];
854
866
  try {
855
- const content = await readFile(join(workspaceRoot, ws.path, "AGENTS.md"), "utf8");
867
+ const content = await io.readFile(join(workspaceRoot, ws.path, "AGENTS.md"));
856
868
  if (!content.includes("AGENTS.md")) {
857
869
  suggestions.push("reference root AGENTS.md");
858
870
  }
@@ -874,8 +886,19 @@ async function checkNestedAgentsMd(
874
886
  const terminology = resolveAllTerminology(config, profile);
875
887
  const wsType = workspaceTypes?.find((wt) => wt.id === ws.type);
876
888
  const expected = selectNestedTemplate(wsType, profile, terminology, fallback);
877
- const actual = await readFile(join(workspaceRoot, ws.path, "AGENTS.md"), "utf8");
878
- if (expected !== actual) {
889
+ const actual = await io.readFile(join(workspaceRoot, ws.path, "AGENTS.md"));
890
+ // RFC-1153: boundary-aware staleness — merge(expected, actual) compares
891
+ // only the generated head; content below the forge:custom boundary (or
892
+ // the canonical footer fallback) is preserved, not drift. Files bearing
893
+ // the restrictive GENERATED marker are generator-owned (RFC-0081) — any
894
+ // divergence is plain staleness, never unmapped-customization.
895
+ const merged = mergeEditableGenerated(expected, actual, `${ws.path}/AGENTS.md`);
896
+ if (merged === null && hasEditableGeneratedMarker(actual)) {
897
+ unmapped++;
898
+ issues.push(
899
+ `${ws.path}/AGENTS.md has custom content but no resolvable boundary — add <!-- forge:custom --> manually`,
900
+ );
901
+ } else if (merged === null || merged !== actual.replace(/\r\n/g, "\n")) {
879
902
  stale++;
880
903
  issues.push(`${ws.path}/AGENTS.md stale — run 'forge agents generate'`);
881
904
  }
@@ -895,11 +918,12 @@ async function checkNestedAgentsMd(
895
918
  const parts: string[] = [];
896
919
  if (missing > 0) parts.push(`${missing} missing`);
897
920
  if (stale > 0) parts.push(`${stale} stale`);
921
+ if (unmapped > 0) parts.push(`${unmapped} unmapped-customization`);
898
922
  if (handwritten > 0) parts.push(`${handwritten} hand-written`);
899
923
 
900
924
  return {
901
925
  name: "nested-AGENTS.md",
902
- status: stale > 0 ? "warn" : "pass",
926
+ status: stale > 0 || unmapped > 0 ? "warn" : "pass",
903
927
  message: `${parts.join(", ")} — ${issues.slice(0, 3).join("; ")}${issues.length > 3 ? ` (+${issues.length - 3} more)` : ""}`,
904
928
  };
905
929
  }
@@ -1209,13 +1233,15 @@ function checkPrerequisites(prerequisites: ProfilePrerequisite[]): DoctorCheck {
1209
1233
  export async function runDoctor(
1210
1234
  input: ForgeCommandInput,
1211
1235
  context: ForgeRuntimeContext,
1212
- ): Promise<ForgeCommandResult<{ command: string; checks: DoctorCheck[]; allPass: boolean; forbiddenImports: ForbiddenImport[]; bindings: BindingValidation; domain?: DomainReport }>> {
1213
- const { workspaceRoot, logger, outputFormat } = context;
1236
+ ): Promise<ForgeCommandResult<{ command: string; checks: DoctorCheck[]; allPass: boolean; forbiddenImports: ForbiddenImport[]; bindings: BindingValidation; domain?: DomainReport; fixes?: DoctorFixResult[] }>> {
1237
+ const { workspaceRoot, logger, outputFormat, dryRun } = context;
1238
+ const fio = resolveIo(context.io);
1214
1239
  const strict = input.flags["strict"] === true;
1240
+ const fix = input.flags["fix"] === true;
1215
1241
  const checks: DoctorCheck[] = [];
1216
1242
 
1217
1243
  // Check forge.yaml
1218
- const forgeYamlExists = await pathExists(join(workspaceRoot, "forge.yaml"));
1244
+ const forgeYamlExists = await pathExists(join(workspaceRoot, "forge.yaml"), fio);
1219
1245
  checks.push({
1220
1246
  name: "forge.yaml",
1221
1247
  status: forgeYamlExists ? "pass" : "warn",
@@ -1225,7 +1251,7 @@ export async function runDoctor(
1225
1251
  });
1226
1252
 
1227
1253
  // Check AGENTS.md
1228
- const agentsMdExists = await pathExists(join(workspaceRoot, "AGENTS.md"));
1254
+ const agentsMdExists = await pathExists(join(workspaceRoot, "AGENTS.md"), fio);
1229
1255
  checks.push({
1230
1256
  name: "AGENTS.md",
1231
1257
  status: agentsMdExists ? "pass" : "warn",
@@ -1235,7 +1261,7 @@ export async function runDoctor(
1235
1261
  });
1236
1262
 
1237
1263
  // Check PREFERENCES.md
1238
- const preferencesExists = await pathExists(join(workspaceRoot, "PREFERENCES.md"));
1264
+ const preferencesExists = await pathExists(join(workspaceRoot, "PREFERENCES.md"), fio);
1239
1265
  checks.push({
1240
1266
  name: "PREFERENCES.md",
1241
1267
  status: preferencesExists ? "pass" : "warn",
@@ -1245,7 +1271,7 @@ export async function runDoctor(
1245
1271
  });
1246
1272
 
1247
1273
  // Check .agents/skills/
1248
- const skillsDirExists = await pathExists(join(workspaceRoot, ".agents", "skills"));
1274
+ const skillsDirExists = await pathExists(join(workspaceRoot, ".agents", "skills"), fio);
1249
1275
  checks.push({
1250
1276
  name: ".agents/skills/",
1251
1277
  status: skillsDirExists ? "pass" : "fail",
@@ -1255,7 +1281,7 @@ export async function runDoctor(
1255
1281
  });
1256
1282
 
1257
1283
  // Check docs/rfcs/
1258
- const rfcsDirExists = await pathExists(join(workspaceRoot, "docs", "rfcs"));
1284
+ const rfcsDirExists = await pathExists(join(workspaceRoot, "docs", "rfcs"), fio);
1259
1285
  checks.push({
1260
1286
  name: "docs/rfcs/",
1261
1287
  status: rfcsDirExists ? "pass" : "warn",
@@ -1265,7 +1291,7 @@ export async function runDoctor(
1265
1291
  });
1266
1292
 
1267
1293
  // Check docs/adrs/
1268
- const adrsDirExists = await pathExists(join(workspaceRoot, "docs", "adrs"));
1294
+ const adrsDirExists = await pathExists(join(workspaceRoot, "docs", "adrs"), fio);
1269
1295
  checks.push({
1270
1296
  name: "docs/adrs/",
1271
1297
  status: adrsDirExists ? "pass" : "warn",
@@ -1374,7 +1400,7 @@ export async function runDoctor(
1374
1400
  : `${invalidProfiles.length} profile(s) invalid (advisory): ${invalidProfiles.map((p) => p.id).join(", ")}`,
1375
1401
  });
1376
1402
 
1377
- const forbiddenImports = await scanForForbiddenImports(forgeRoot, workspaceRoot);
1403
+ const forbiddenImports = await scanForForbiddenImports(forgeRoot, workspaceRoot, fio);
1378
1404
  checks.push({
1379
1405
  name: "autonomy-guard",
1380
1406
  status: forbiddenImports.length === 0 ? "pass" : "fail",
@@ -1385,7 +1411,7 @@ export async function runDoctor(
1385
1411
  });
1386
1412
 
1387
1413
  // Check bindings contract (RFC-0393)
1388
- const bindingsResult = await validateBindings(workspaceRoot);
1414
+ const bindingsResult = await validateBindings(workspaceRoot, fio);
1389
1415
  checks.push({
1390
1416
  name: "bindings",
1391
1417
  status: bindingsResult.invalid.length === 0 ? "pass" : "fail",
@@ -1396,7 +1422,7 @@ export async function runDoctor(
1396
1422
  });
1397
1423
 
1398
1424
  // Check stale knowledge files (RFC-0524, RFC-0539)
1399
- const staleCheck = await checkStaleKnowledgeFiles(workspaceRoot, forgeRoot);
1425
+ const staleCheck = await checkStaleKnowledgeFiles(workspaceRoot, forgeRoot, fio);
1400
1426
  checks.push(staleCheck);
1401
1427
 
1402
1428
  // RFC-0660: Check legacy sections in knowledge files
@@ -1418,16 +1444,19 @@ export async function runDoctor(
1418
1444
  // RFC-0664: Check memory layer health (budget, gitignore coverage, leak risk)
1419
1445
  checks.push(checkMemoryLayer(workspaceRoot));
1420
1446
 
1447
+ // RFC-1151: Check dist freshness — stale dist/ silently shadows src/ in source checkouts
1448
+ checks.push(checkDistFreshness(forgeRoot));
1449
+
1421
1450
  // RFC-0539: Check pack skills — stale/missing copies and config validation
1422
- const packCheck = await checkPackSkills(workspaceRoot);
1451
+ const packCheck = await checkPackSkills(workspaceRoot, fio);
1423
1452
  checks.push(packCheck);
1424
1453
 
1425
1454
  // RFC-0941: Check pack manifests — forge.plugin.yaml existence and validity
1426
- const packManifestCheck = await checkPackManifests(workspaceRoot);
1455
+ const packManifestCheck = await checkPackManifests(workspaceRoot, fio);
1427
1456
  checks.push(packManifestCheck);
1428
1457
 
1429
1458
  // RFC-0704: Check independent version packages — paths must exist and contain package.json
1430
- const independentCheck = await checkIndependentVersionPackages(workspaceRoot);
1459
+ const independentCheck = await checkIndependentVersionPackages(workspaceRoot, fio);
1431
1460
  checks.push(independentCheck);
1432
1461
 
1433
1462
  // RFC-0611: Check nested AGENTS.md — missing, stale, hand-written
@@ -1435,8 +1464,8 @@ export async function runDoctor(
1435
1464
  // RFC-0640 fix: previously gated by isSoftwareDomain, which skipped the check
1436
1465
  // entirely for non-software domains. Now runs for all domains — profile-driven
1437
1466
  // wsTypes replace hardcoded detection when present.
1467
+ let wsTypes: ProfileWorkspaceType[] | undefined;
1438
1468
  {
1439
- let wsTypes: ProfileWorkspaceType[] | undefined;
1440
1469
  try {
1441
1470
  const config = loadForgeConfig(workspaceRoot);
1442
1471
  // RFC-0643: prefer config.profile (loaded by loadForgeConfig)
@@ -1455,7 +1484,7 @@ export async function runDoctor(
1455
1484
  } catch {
1456
1485
  // profiles not loadable
1457
1486
  }
1458
- const nestedCheck = await checkNestedAgentsMd(workspaceRoot, wsTypes);
1487
+ const nestedCheck = await checkNestedAgentsMd(workspaceRoot, wsTypes, fio);
1459
1488
  checks.push(nestedCheck);
1460
1489
  }
1461
1490
 
@@ -1472,6 +1501,15 @@ export async function runDoctor(
1472
1501
  const allPass = finalChecks.every((c) => c.status === "pass");
1473
1502
  const hasFails = finalChecks.some((c) => c.status === "fail");
1474
1503
 
1504
+ // RFC-1151: --fix applies registered safe remediations for warn/fail checks
1505
+ const fixes: DoctorFixResult[] = [];
1506
+ if (fix) {
1507
+ for (const check of finalChecks) {
1508
+ if (check.status === "pass") continue;
1509
+ fixes.push(await applyDoctorRemediation(check, workspaceRoot, wsTypes, dryRun === true, fio));
1510
+ }
1511
+ }
1512
+
1475
1513
  if (outputFormat === "pretty") {
1476
1514
  logger.section(`Forge Doctor — ${workspaceRoot}`);
1477
1515
  for (const check of finalChecks) {
@@ -1479,6 +1517,10 @@ export async function runDoctor(
1479
1517
  const fn = check.status === "pass" ? logger.success : check.status === "warn" ? logger.warn : logger.error;
1480
1518
  fn(`${icon} ${check.name}: ${check.message}`);
1481
1519
  }
1520
+ for (const f of fixes) {
1521
+ const fn = f.action === "fixed" ? logger.success : f.action === "failed" ? logger.error : logger.info;
1522
+ fn(` fix ${f.check}: ${f.action} — ${f.detail}`);
1523
+ }
1482
1524
  if (allPass) {
1483
1525
  logger.success("All checks passed — forge is properly configured.");
1484
1526
  } else if (hasFails) {
@@ -1488,11 +1530,109 @@ export async function runDoctor(
1488
1530
  }
1489
1531
  }
1490
1532
 
1533
+ const fixFailed = fixes.some((f) => f.action === "failed");
1534
+
1491
1535
  return {
1492
- data: { command: "forge.doctor", checks: finalChecks, allPass, forbiddenImports, bindings: bindingsResult, domain: domainReport },
1493
- exitCode: hasFails ? 1 : 0,
1536
+ data: { command: "forge.doctor", checks: finalChecks, allPass, forbiddenImports, bindings: bindingsResult, domain: domainReport, ...(fix ? { fixes } : {}) },
1537
+ exitCode: hasFails || fixFailed ? 1 : 0,
1494
1538
  summary: allPass
1495
1539
  ? "forge.doctor: all checks passed"
1496
- : `forge.doctor: ${finalChecks.filter((c) => c.status === "fail").length} fail(s), ${finalChecks.filter((c) => c.status === "warn").length} warn(s)`,
1540
+ : `forge.doctor: ${finalChecks.filter((c) => c.status === "fail").length} fail(s), ${finalChecks.filter((c) => c.status === "warn").length} warn(s)${fix ? `, ${fixes.filter((f) => f.action === "fixed").length} fixed` : ""}`,
1497
1541
  };
1498
1542
  }
1543
+
1544
+ // RFC-1151: dist-freshness — a stale dist/ silently shadows src/ because
1545
+ // bin/cli.js prefers dist when present. Warn-only; rebuild is a pnpm script,
1546
+ // not forge's call. Pass (skip) when src/ or dist/ is absent — npm consumers
1547
+ // ship dist-only, so this activates only in source checkouts.
1548
+ function checkDistFreshness(forgeRoot: string): DoctorCheck {
1549
+ const srcDir = join(forgeRoot, "src");
1550
+ const distDir = join(forgeRoot, "dist");
1551
+ if (!fs.existsSync(srcDir) || !fs.existsSync(distDir)) {
1552
+ return {
1553
+ name: "dist-freshness",
1554
+ status: "pass",
1555
+ message: "no src+dist pair — not a source checkout",
1556
+ };
1557
+ }
1558
+ const newestSrc = newestMtime(srcDir);
1559
+ const distMtime = fs.statSync(distDir).mtimeMs;
1560
+ if (newestSrc > distMtime) {
1561
+ return {
1562
+ name: "dist-freshness",
1563
+ status: "warn",
1564
+ message: `dist/ older than newest src/ file — run 'pnpm run build' in ${forgeRoot}`,
1565
+ };
1566
+ }
1567
+ return { name: "dist-freshness", status: "pass", message: "dist/ is fresh" };
1568
+ }
1569
+
1570
+ function newestMtime(dir: string): number {
1571
+ let newest = 0;
1572
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true, recursive: true })) {
1573
+ if (!entry.isFile()) continue;
1574
+ const m = fs.statSync(join(entry.parentPath, entry.name)).mtimeMs;
1575
+ if (m > newest) newest = m;
1576
+ }
1577
+ return newest;
1578
+ }
1579
+
1580
+ // RFC-1151: remediation dispatch — check name → safe fix action.
1581
+ // Remediations reuse existing generators; hand-written files are never touched
1582
+ // (generated-marker edit guard inside generateNestedAgentsMd).
1583
+ async function applyDoctorRemediation(
1584
+ check: DoctorCheck,
1585
+ workspaceRoot: string,
1586
+ workspaceTypes: ProfileWorkspaceType[] | undefined,
1587
+ dryRun: boolean,
1588
+ io: WorkspaceIO,
1589
+ ): Promise<DoctorFixResult> {
1590
+ switch (check.name) {
1591
+ case "nested-AGENTS.md": {
1592
+ try {
1593
+ const config = loadForgeConfig(workspaceRoot);
1594
+ const res = await generateNestedAgentsMd(workspaceRoot, config, dryRun, workspaceTypes, io);
1595
+ return {
1596
+ check: check.name,
1597
+ action: res.generated.length > 0 ? "fixed" : "skipped",
1598
+ detail: `${res.generated.length} file(s) ${dryRun ? "would be " : ""}regenerated, ${res.skipped.length} skipped`,
1599
+ };
1600
+ } catch (err) {
1601
+ return { check: check.name, action: "failed", detail: (err as Error).message };
1602
+ }
1603
+ }
1604
+ case "memory-layer": {
1605
+ try {
1606
+ const memoryPath = join(workspaceRoot, ".agents", "memory", "MEMORY.md");
1607
+ if (!(await io.exists(memoryPath))) {
1608
+ return { check: check.name, action: "skipped", detail: "MEMORY.md absent" };
1609
+ }
1610
+ const content = await io.readFile(memoryPath);
1611
+ const budget = resolveMemoryBudget(workspaceRoot);
1612
+ const { lines, removedLines, fitsBudget } = compactMemoryMd(content, budget);
1613
+ if (!fitsBudget) {
1614
+ return {
1615
+ check: check.name,
1616
+ action: "failed",
1617
+ detail: "still over budget after Environment notes truncation — manual editorial compaction required",
1618
+ };
1619
+ }
1620
+ if (removedLines.length === 0) {
1621
+ return { check: check.name, action: "skipped", detail: "within budget" };
1622
+ }
1623
+ if (!dryRun) {
1624
+ await io.writeFile(memoryPath, lines.join("\n"));
1625
+ }
1626
+ return {
1627
+ check: check.name,
1628
+ action: "fixed",
1629
+ detail: `${dryRun ? "would remove" : "removed"} ${removedLines.length} bullet(s)`,
1630
+ };
1631
+ } catch (err) {
1632
+ return { check: check.name, action: "failed", detail: (err as Error).message };
1633
+ }
1634
+ }
1635
+ default:
1636
+ return { check: check.name, action: "skipped", detail: "no-remediation" };
1637
+ }
1638
+ }
@@ -20,11 +20,13 @@ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PU
20
20
  </CHANGE_SUMMARY>
21
21
  */
22
22
 
23
- import fs from "node:fs";
23
+ import * as fs from "../utils/sync-fs.ts";
24
24
  import path from "node:path";
25
25
  import { stringify as stringifyYaml, parse as parseYaml } from "yaml";
26
26
  import { FORGE_SKILLS, discoverPackSkills } from "../registry.ts";
27
27
  import { syncKnowledgeFile } from "../knowledge/index.ts";
28
+ import { writeSkillMarkerSync } from "./skill-markers.ts";
29
+ import { planPrettierignoreSync, applyPrettierignoreSync } from "./prettierignore.ts";
28
30
  import { defaultForgeConfig, loadForgeConfig, resolveForgeRoot, type ForgeConfig } from "../config/forge-config.ts";
29
31
  import { listStackProfiles, detectStack } from "../profiles/stack-profile.ts";
30
32
 
@@ -280,6 +282,11 @@ export function runInit(
280
282
  fs.writeFileSync(destPath, content, "utf8");
281
283
  created.push(`${config.paths.skillsDir}/${skillName}/SKILL.md`);
282
284
 
285
+ // RFC-1154: marker manifest lists SKILL.md + knowledge files whose content
286
+ // is purely forge's (copied/unchanged); merged/skipped files carry consumer
287
+ // entries and stay out of the manifest so prune never deletes them.
288
+ const markerFiles = ["SKILL.md"];
289
+
283
290
  // RFC-0524: sync declared knowledge files
284
291
  const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
285
292
  if (fmMatch) {
@@ -298,6 +305,9 @@ export function runInit(
298
305
  if (syncResult.action === "copied" || syncResult.action === "merged") {
299
306
  created.push(`${config.paths.skillsDir}/${skillName}/${kf}`);
300
307
  }
308
+ if (syncResult.action === "copied" || syncResult.action === "unchanged") {
309
+ markerFiles.push(kf);
310
+ }
301
311
  } else {
302
312
  errors.push(`Knowledge file '${kf}' declared in ${skillName} but not found in source`);
303
313
  }
@@ -307,6 +317,7 @@ export function runInit(
307
317
  // Frontmatter parse error — SKILL-01 will catch this in validation
308
318
  }
309
319
  }
320
+ writeSkillMarkerSync(destDir, markerFiles);
310
321
  }
311
322
 
312
323
  // RFC-0539: Copy declared pack skills to .agents/skills/<name>/ for IDE discovery
@@ -352,6 +363,9 @@ export function runInit(
352
363
  fs.writeFileSync(destPath, content, "utf8");
353
364
  created.push(`${config.paths.skillsDir}/${skillName}/SKILL.md`);
354
365
 
366
+ // RFC-1154: same marker rule as forge skills.
367
+ const markerFiles = ["SKILL.md"];
368
+
355
369
  // RFC-0524: sync declared knowledge files for pack skills
356
370
  const fmMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
357
371
  if (fmMatch) {
@@ -370,6 +384,9 @@ export function runInit(
370
384
  if (syncResult.action === "copied" || syncResult.action === "merged") {
371
385
  created.push(`${config.paths.skillsDir}/${skillName}/${kf}`);
372
386
  }
387
+ if (syncResult.action === "copied" || syncResult.action === "unchanged") {
388
+ markerFiles.push(kf);
389
+ }
373
390
  } else {
374
391
  errors.push(`Knowledge file '${kf}' declared in ${skillName} but not found in source`);
375
392
  }
@@ -379,6 +396,7 @@ export function runInit(
379
396
  // Frontmatter parse error — SKILL-01 will catch this in validation
380
397
  }
381
398
  }
399
+ writeSkillMarkerSync(destDir, markerFiles);
382
400
  }
383
401
 
384
402
  // RFC-0663: Sync shared knowledge layer to .agents/skills/shared-knowledge/
@@ -391,6 +409,25 @@ export function runInit(
391
409
  if (syncResult.action === "copied" || syncResult.action === "merged") {
392
410
  created.push(`${config.paths.skillsDir}/shared-knowledge/learned-principles.md`);
393
411
  }
412
+ // RFC-1154: marker lists the file only when its content is purely forge's.
413
+ writeSkillMarkerSync(
414
+ sharedKnowledgeDestDir,
415
+ syncResult.action === "copied" || syncResult.action === "unchanged"
416
+ ? ["learned-principles.md"]
417
+ : [],
418
+ );
419
+ }
420
+
421
+ // RFC-1154: reconcile the forge-managed .prettierignore block (prettier
422
+ // consumers only; additive + idempotent, no-op otherwise). Non-fatal —
423
+ // a prettierignore write failure must not fail init.
424
+ try {
425
+ applyPrettierignoreSync(
426
+ workspaceRoot,
427
+ planPrettierignoreSync(workspaceRoot, config.paths.skillsDir),
428
+ );
429
+ } catch (err) {
430
+ errors.push(`.prettierignore reconcile failed: ${(err as Error).message}`);
394
431
  }
395
432
 
396
433
  // 4. Create docs directories from config paths
@@ -20,7 +20,7 @@ Sweep batch 4: 73 Compass headers on headerless engine files (certification, com
20
20
  </CHANGE_SUMMARY>
21
21
  */
22
22
 
23
- import fs from "node:fs";
23
+ import * as fs from "../utils/sync-fs.ts";
24
24
  import path from "node:path";
25
25
  import { parse as parseYaml } from "yaml";
26
26
  import type { StackProfile } from "../profiles/stack-profile.ts";