@warpgogol/forge 4.2.4 → 5.1.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 (363) hide show
  1. package/AGENTS.md +14 -6
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +8 -8
  4. package/README.uk.md +5 -5
  5. package/dist/os/adr/handlers/list-create.d.ts.map +1 -1
  6. package/dist/os/adr/handlers/list-create.js +4 -1
  7. package/dist/os/adr/handlers/list-create.js.map +1 -1
  8. package/dist/os/adr/handlers/validate.d.ts.map +1 -1
  9. package/dist/os/adr/handlers/validate.js +6 -1
  10. package/dist/os/adr/handlers/validate.js.map +1 -1
  11. package/dist/os/adr/types.d.ts.map +1 -1
  12. package/dist/os/adr/types.js +7 -3
  13. package/dist/os/adr/types.js.map +1 -1
  14. package/dist/os/compass/compass.module.d.ts.map +1 -1
  15. package/dist/os/compass/compass.module.js +76 -10
  16. package/dist/os/compass/compass.module.js.map +1 -1
  17. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  18. package/dist/os/compass/handlers/compass-audit-handler.js +7 -3
  19. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  20. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts +1 -9
  21. package/dist/os/compass/handlers/compass-change-summary-handler.d.ts.map +1 -1
  22. package/dist/os/compass/handlers/compass-change-summary-handler.js +44 -186
  23. package/dist/os/compass/handlers/compass-change-summary-handler.js.map +1 -1
  24. package/dist/os/compass/handlers/compass-inventory-handler.d.ts +2 -0
  25. package/dist/os/compass/handlers/compass-inventory-handler.d.ts.map +1 -1
  26. package/dist/os/compass/handlers/compass-inventory-handler.js +24 -12
  27. package/dist/os/compass/handlers/compass-inventory-handler.js.map +1 -1
  28. package/dist/os/compass/handlers/compass-inventory.d.ts +7 -5
  29. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  30. package/dist/os/compass/handlers/compass-inventory.js +84 -241
  31. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  32. package/dist/os/compass/handlers/compass-migrate-handler.d.ts +4 -0
  33. package/dist/os/compass/handlers/compass-migrate-handler.d.ts.map +1 -0
  34. package/dist/os/compass/handlers/compass-migrate-handler.js +100 -0
  35. package/dist/os/compass/handlers/compass-migrate-handler.js.map +1 -0
  36. package/dist/os/compass/handlers/compass-migrate.d.ts +34 -0
  37. package/dist/os/compass/handlers/compass-migrate.d.ts.map +1 -0
  38. package/dist/os/compass/handlers/compass-migrate.js +273 -0
  39. package/dist/os/compass/handlers/compass-migrate.js.map +1 -0
  40. package/dist/os/compass/handlers/resolve-scan-root.d.ts.map +1 -1
  41. package/dist/os/compass/handlers/resolve-scan-root.js +15 -8
  42. package/dist/os/compass/handlers/resolve-scan-root.js.map +1 -1
  43. package/dist/os/compass/handlers/summary-record.d.ts +46 -0
  44. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -0
  45. package/dist/os/compass/handlers/summary-record.js +233 -0
  46. package/dist/os/compass/handlers/summary-record.js.map +1 -0
  47. package/dist/os/compass/index.d.ts +4 -1
  48. package/dist/os/compass/index.d.ts.map +1 -1
  49. package/dist/os/compass/index.js +9 -1
  50. package/dist/os/compass/index.js.map +1 -1
  51. package/dist/os/compass/policy.d.ts +65 -0
  52. package/dist/os/compass/policy.d.ts.map +1 -0
  53. package/dist/os/compass/policy.js +241 -0
  54. package/dist/os/compass/policy.js.map +1 -0
  55. package/dist/os/core/core.module.d.ts.map +1 -1
  56. package/dist/os/core/core.module.js +11 -23
  57. package/dist/os/core/core.module.js.map +1 -1
  58. package/dist/os/core/handlers/forge-autonomy-validate.d.ts.map +1 -1
  59. package/dist/os/core/handlers/forge-autonomy-validate.js +7 -1
  60. package/dist/os/core/handlers/forge-autonomy-validate.js.map +1 -1
  61. package/dist/os/core/handlers/package-health.d.ts.map +1 -1
  62. package/dist/os/core/handlers/package-health.js +6 -1
  63. package/dist/os/core/handlers/package-health.js.map +1 -1
  64. package/dist/os/core/handlers/pinned-check.d.ts.map +1 -1
  65. package/dist/os/core/handlers/pinned-check.js +6 -1
  66. package/dist/os/core/handlers/pinned-check.js.map +1 -1
  67. package/dist/os/core/handlers/pinned-validate.d.ts.map +1 -1
  68. package/dist/os/core/handlers/pinned-validate.js +6 -1
  69. package/dist/os/core/handlers/pinned-validate.js.map +1 -1
  70. package/dist/os/core/handlers/validate.d.ts.map +1 -1
  71. package/dist/os/core/handlers/validate.js +6 -1
  72. package/dist/os/core/handlers/validate.js.map +1 -1
  73. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  74. package/dist/os/exploration/exploration.module.js +6 -4
  75. package/dist/os/exploration/exploration.module.js.map +1 -1
  76. package/dist/os/exploration/handlers/list.d.ts.map +1 -1
  77. package/dist/os/exploration/handlers/list.js +4 -1
  78. package/dist/os/exploration/handlers/list.js.map +1 -1
  79. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  80. package/dist/os/mission/handlers/archive.js +7 -3
  81. package/dist/os/mission/handlers/archive.js.map +1 -1
  82. package/dist/os/mission/index.d.ts.map +1 -1
  83. package/dist/os/mission/index.js +13 -0
  84. package/dist/os/mission/index.js.map +1 -1
  85. package/dist/os/notes/index.d.ts.map +1 -1
  86. package/dist/os/notes/index.js +7 -1
  87. package/dist/os/notes/index.js.map +1 -1
  88. package/dist/os/rfc/frontmatter-io.d.ts.map +1 -1
  89. package/dist/os/rfc/frontmatter-io.js +6 -1
  90. package/dist/os/rfc/frontmatter-io.js.map +1 -1
  91. package/dist/os/rfc/handlers/archive.d.ts.map +1 -1
  92. package/dist/os/rfc/handlers/archive.js +6 -1
  93. package/dist/os/rfc/handlers/archive.js.map +1 -1
  94. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  95. package/dist/os/rfc/handlers/implement-stamp.js +7 -3
  96. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  97. package/dist/os/rfc/handlers/index-graph.d.ts.map +1 -1
  98. package/dist/os/rfc/handlers/index-graph.js +6 -1
  99. package/dist/os/rfc/handlers/index-graph.js.map +1 -1
  100. package/dist/os/rfc/handlers/lifecycle.d.ts.map +1 -1
  101. package/dist/os/rfc/handlers/lifecycle.js +6 -1
  102. package/dist/os/rfc/handlers/lifecycle.js.map +1 -1
  103. package/dist/os/rfc/handlers/list-create.d.ts.map +1 -1
  104. package/dist/os/rfc/handlers/list-create.js +6 -1
  105. package/dist/os/rfc/handlers/list-create.js.map +1 -1
  106. package/dist/os/rfc/handlers/pipeline-status.d.ts.map +1 -1
  107. package/dist/os/rfc/handlers/pipeline-status.js +6 -1
  108. package/dist/os/rfc/handlers/pipeline-status.js.map +1 -1
  109. package/dist/os/rfc/handlers/supersede-propose.d.ts.map +1 -1
  110. package/dist/os/rfc/handlers/supersede-propose.js +6 -1
  111. package/dist/os/rfc/handlers/supersede-propose.js.map +1 -1
  112. package/dist/os/rfc/handlers/validate-rules.d.ts.map +1 -1
  113. package/dist/os/rfc/handlers/validate-rules.js +7 -3
  114. package/dist/os/rfc/handlers/validate-rules.js.map +1 -1
  115. package/dist/os/rfc/handlers/validate.d.ts.map +1 -1
  116. package/dist/os/rfc/handlers/validate.js +6 -1
  117. package/dist/os/rfc/handlers/validate.js.map +1 -1
  118. package/dist/os/rfc/index.d.ts.map +1 -1
  119. package/dist/os/rfc/index.js +6 -1
  120. package/dist/os/rfc/index.js.map +1 -1
  121. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  122. package/dist/os/rfc/rfc.module.js +6 -1
  123. package/dist/os/rfc/rfc.module.js.map +1 -1
  124. package/dist/os/rfc/types.d.ts +7 -4
  125. package/dist/os/rfc/types.d.ts.map +1 -1
  126. package/dist/os/rfc/types.js +7 -4
  127. package/dist/os/rfc/types.js.map +1 -1
  128. package/dist/os/session/handlers/save.d.ts.map +1 -1
  129. package/dist/os/session/handlers/save.js +6 -1
  130. package/dist/os/session/handlers/save.js.map +1 -1
  131. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.d.ts.map +1 -1
  132. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js +6 -1
  133. package/dist/os/werkstatt/handlers/werkstatt-lock-recover.js.map +1 -1
  134. package/dist/os/werkstatt/handlers/workspace-deps.js +3 -3
  135. package/dist/os/werkstatt/handlers/workspace-deps.js.map +1 -1
  136. package/dist/os/workflow/index.d.ts.map +1 -1
  137. package/dist/os/workflow/index.js +6 -1
  138. package/dist/os/workflow/index.js.map +1 -1
  139. package/dist/src/config/forge-config.d.ts +62 -4
  140. package/dist/src/config/forge-config.d.ts.map +1 -1
  141. package/dist/src/config/forge-config.js +35 -19
  142. package/dist/src/config/forge-config.js.map +1 -1
  143. package/dist/src/forge-module.d.ts.map +1 -1
  144. package/dist/src/forge-module.js +6 -1
  145. package/dist/src/forge-module.js.map +1 -1
  146. package/dist/src/index.d.ts.map +1 -1
  147. package/dist/src/index.js +10 -2
  148. package/dist/src/index.js.map +1 -1
  149. package/dist/src/migration-adapters/git-utils.d.ts.map +1 -1
  150. package/dist/src/migration-adapters/git-utils.js +6 -2
  151. package/dist/src/migration-adapters/git-utils.js.map +1 -1
  152. package/dist/src/migration-adapters/ignored-files.d.ts.map +1 -1
  153. package/dist/src/migration-adapters/ignored-files.js +6 -1
  154. package/dist/src/migration-adapters/ignored-files.js.map +1 -1
  155. package/dist/src/migration-adapters/index.d.ts.map +1 -1
  156. package/dist/src/migration-adapters/index.js +4 -1
  157. package/dist/src/migration-adapters/index.js.map +1 -1
  158. package/dist/src/migration-adapters/types.d.ts.map +1 -1
  159. package/dist/src/migration-adapters/types.js +6 -2
  160. package/dist/src/migration-adapters/types.js.map +1 -1
  161. package/dist/src/onboarding/agents-generate.d.ts.map +1 -1
  162. package/dist/src/onboarding/agents-generate.js +18 -14
  163. package/dist/src/onboarding/agents-generate.js.map +1 -1
  164. package/dist/src/onboarding/create.d.ts.map +1 -1
  165. package/dist/src/onboarding/create.js +7 -6
  166. package/dist/src/onboarding/create.js.map +1 -1
  167. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  168. package/dist/src/onboarding/doctor.js +7 -13
  169. package/dist/src/onboarding/doctor.js.map +1 -1
  170. package/dist/src/onboarding/init.d.ts.map +1 -1
  171. package/dist/src/onboarding/init.js +7 -12
  172. package/dist/src/onboarding/init.js.map +1 -1
  173. package/dist/src/onboarding/invariant-engine.d.ts.map +1 -1
  174. package/dist/src/onboarding/invariant-engine.js +7 -2
  175. package/dist/src/onboarding/invariant-engine.js.map +1 -1
  176. package/dist/src/onboarding/nested-agents-generate.d.ts.map +1 -1
  177. package/dist/src/onboarding/nested-agents-generate.js +7 -2
  178. package/dist/src/onboarding/nested-agents-generate.js.map +1 -1
  179. package/dist/src/onboarding/nested-agents-templates.d.ts.map +1 -1
  180. package/dist/src/onboarding/nested-agents-templates.js +11 -3
  181. package/dist/src/onboarding/nested-agents-templates.js.map +1 -1
  182. package/dist/src/onboarding/scaffold-project.d.ts.map +1 -1
  183. package/dist/src/onboarding/scaffold-project.js +6 -1
  184. package/dist/src/onboarding/scaffold-project.js.map +1 -1
  185. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  186. package/dist/src/onboarding/upgrade.js +7 -3
  187. package/dist/src/onboarding/upgrade.js.map +1 -1
  188. package/dist/src/profiles/profile-schema.d.ts +54 -4
  189. package/dist/src/profiles/profile-schema.d.ts.map +1 -1
  190. package/dist/src/profiles/profile-schema.js +34 -14
  191. package/dist/src/profiles/profile-schema.js.map +1 -1
  192. package/dist/src/profiles/stack-profile.d.ts +24 -0
  193. package/dist/src/profiles/stack-profile.d.ts.map +1 -1
  194. package/dist/src/profiles/stack-profile.js +7 -3
  195. package/dist/src/profiles/stack-profile.js.map +1 -1
  196. package/dist/src/registry.d.ts.map +1 -1
  197. package/dist/src/registry.js +7 -9
  198. package/dist/src/registry.js.map +1 -1
  199. package/dist/src/types.d.ts.map +1 -1
  200. package/dist/src/types.js +6 -1
  201. package/dist/src/types.js.map +1 -1
  202. package/dist/src/utils/fs-atomic.d.ts.map +1 -1
  203. package/dist/src/utils/fs-atomic.js +13 -1
  204. package/dist/src/utils/fs-atomic.js.map +1 -1
  205. package/dist/src/utils/fs-idempotent.d.ts.map +1 -1
  206. package/dist/src/utils/fs-idempotent.js +13 -0
  207. package/dist/src/utils/fs-idempotent.js.map +1 -1
  208. package/dist/src/utils/fs-trash-sync.d.ts.map +1 -1
  209. package/dist/src/utils/fs-trash-sync.js +13 -1
  210. package/dist/src/utils/fs-trash-sync.js.map +1 -1
  211. package/dist/src/utils/fs-trash.d.ts.map +1 -1
  212. package/dist/src/utils/fs-trash.js +13 -1
  213. package/dist/src/utils/fs-trash.js.map +1 -1
  214. package/dist/src/utils/fs.d.ts.map +1 -1
  215. package/dist/src/utils/fs.js +14 -3
  216. package/dist/src/utils/fs.js.map +1 -1
  217. package/dist/src/utils/hash.d.ts.map +1 -1
  218. package/dist/src/utils/hash.js +12 -1
  219. package/dist/src/utils/hash.js.map +1 -1
  220. package/dist/src/utils/index.d.ts.map +1 -1
  221. package/dist/src/utils/index.js +13 -2
  222. package/dist/src/utils/index.js.map +1 -1
  223. package/dist/src/utils/string-utils.d.ts.map +1 -1
  224. package/dist/src/utils/string-utils.js +12 -1
  225. package/dist/src/utils/string-utils.js.map +1 -1
  226. package/dist/src/validators/port-validate.js +1 -1
  227. package/dist/src/validators/port-validate.js.map +1 -1
  228. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  229. package/dist/src/validators/skill-validate.js +7 -8
  230. package/dist/src/validators/skill-validate.js.map +1 -1
  231. package/docs/getting-started.md +1 -1
  232. package/docs/reference/forge-yaml.md +38 -9
  233. package/docs/reference/profiles.md +8 -8
  234. package/os/adr/handlers/list-create.ts +4 -1
  235. package/os/adr/handlers/validate.ts +6 -1
  236. package/os/adr/types.ts +7 -3
  237. package/os/compass/compass.module.ts +79 -13
  238. package/os/compass/handlers/compass-audit-handler.ts +22 -3
  239. package/os/compass/handlers/compass-change-summary-handler.ts +55 -227
  240. package/os/compass/handlers/compass-inventory-handler.ts +30 -12
  241. package/os/compass/handlers/compass-inventory.ts +103 -240
  242. package/os/compass/handlers/compass-migrate-handler.ts +122 -0
  243. package/os/compass/handlers/compass-migrate.ts +361 -0
  244. package/os/compass/handlers/resolve-scan-root-package.test.ts +70 -0
  245. package/os/compass/handlers/resolve-scan-root.ts +15 -8
  246. package/os/compass/handlers/summary-record.ts +313 -0
  247. package/os/compass/handlers/tests/compass-migrate.test.ts +291 -0
  248. package/os/compass/handlers/tests/compass-policy.test.ts +249 -0
  249. package/os/compass/handlers/tests/compass-v2-contract.test.ts +9 -9
  250. package/os/compass/handlers/tests/summary-record.test.ts +224 -0
  251. package/os/compass/index.ts +23 -5
  252. package/os/compass/policy.ts +350 -0
  253. package/os/core/core.module.ts +11 -23
  254. package/os/core/handlers/forge-autonomy-validate.ts +7 -1
  255. package/os/core/handlers/package-health.ts +6 -1
  256. package/os/core/handlers/pinned-check.ts +6 -1
  257. package/os/core/handlers/pinned-validate.ts +6 -1
  258. package/os/core/handlers/validate.ts +6 -1
  259. package/os/exploration/exploration.module.ts +72 -71
  260. package/os/exploration/handlers/list.ts +4 -1
  261. package/os/mission/handlers/archive.ts +7 -3
  262. package/os/mission/index.ts +14 -0
  263. package/os/notes/index.ts +7 -1
  264. package/os/rfc/frontmatter-io.ts +6 -1
  265. package/os/rfc/handlers/archive.ts +6 -1
  266. package/os/rfc/handlers/implement-stamp.ts +7 -3
  267. package/os/rfc/handlers/index-graph.ts +6 -1
  268. package/os/rfc/handlers/lifecycle.ts +6 -1
  269. package/os/rfc/handlers/list-create.ts +6 -1
  270. package/os/rfc/handlers/pipeline-status.ts +6 -1
  271. package/os/rfc/handlers/supersede-propose.ts +6 -1
  272. package/os/rfc/handlers/validate-rules.ts +7 -3
  273. package/os/rfc/handlers/validate.ts +6 -1
  274. package/os/rfc/index.ts +6 -1
  275. package/os/rfc/rfc.module.ts +6 -1
  276. package/os/rfc/types.ts +7 -4
  277. package/os/session/handlers/save.ts +6 -1
  278. package/os/werkstatt/handlers/werkstatt-lock-recover.ts +6 -1
  279. package/os/werkstatt/handlers/workspace-deps.ts +3 -3
  280. package/os/workflow/index.ts +6 -1
  281. package/package.json +1 -1
  282. package/profiles/{godot-csharp.yaml → godot-game.yaml} +2 -2
  283. package/profiles/{knowledge-typescript-turborepo.yaml → knowledge.yaml} +1 -1
  284. package/profiles/{phaser-turborepo.yaml → phaser-game.yaml} +2 -2
  285. package/profiles/{typescript-turborepo.yaml → typescript.yaml} +2 -2
  286. package/skills/fo/fo-add-tests/SKILL.md +14 -0
  287. package/skills/fo/fo-architecture/SKILL.md +14 -0
  288. package/skills/fo/fo-compass-annotate/SKILL.md +14 -0
  289. package/skills/fo/fo-design-summit/SKILL.md +14 -0
  290. package/skills/fo/fo-doc-audit/SKILL.md +14 -0
  291. package/skills/fo/fo-explore/SKILL.md +14 -0
  292. package/skills/fo/fo-extract-dna/SKILL.md +14 -0
  293. package/skills/fo/fo-fix/SKILL.md +14 -0
  294. package/skills/fo/fo-handoff/SKILL.md +14 -0
  295. package/skills/fo/fo-harvest/SKILL.md +14 -0
  296. package/skills/fo/fo-idea/SKILL.md +14 -0
  297. package/skills/fo/fo-idea-audit/SKILL.md +14 -0
  298. package/skills/fo/fo-idea-create-adr/SKILL.md +14 -0
  299. package/skills/fo/fo-idea-create-rfc/SKILL.md +14 -0
  300. package/skills/fo/fo-idea-enhance/SKILL.md +14 -0
  301. package/skills/fo/fo-idea-i-just-want-to-see-the-plan/SKILL.md +14 -0
  302. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +14 -0
  303. package/skills/fo/fo-idea-implement/SKILL.md +14 -0
  304. package/skills/fo/fo-idea-plan/SKILL.md +14 -0
  305. package/skills/fo/fo-idea-status/SKILL.md +14 -0
  306. package/skills/fo/fo-knowledge-distill/SKILL.md +14 -0
  307. package/skills/fo/fo-memory-sync/SKILL.md +14 -0
  308. package/skills/fo/fo-qa/SKILL.md +14 -0
  309. package/skills/fo/fo-review/SKILL.md +14 -0
  310. package/skills/fo/fo-session-retro/SKILL.md +14 -0
  311. package/skills/fo/fo-session-save/SKILL.md +14 -0
  312. package/skills/fo/fo-spec-ingest/SKILL.md +14 -0
  313. package/skills/fo/fo-step-commit/SKILL.md +14 -0
  314. package/skills/fo/fo-triage/SKILL.md +14 -0
  315. package/skills/meta/forge-bootstrap/SKILL.md +14 -0
  316. package/skills/meta/port-to-forge/SKILL.md +14 -0
  317. package/skills/meta/skill-create/SKILL.md +14 -0
  318. package/skills/shared/grilling/SKILL.md +14 -0
  319. package/skills/shared/my-preferences/SKILL.md +14 -0
  320. package/skills/shared/windows-ai-tooling/SKILL.md +14 -0
  321. package/skills/shared/writing-great-skills/SKILL.md +14 -0
  322. package/src/config/forge-config.ts +40 -23
  323. package/src/forge-module.ts +6 -1
  324. package/src/index.ts +10 -2
  325. package/src/migration-adapters/git-utils.ts +6 -2
  326. package/src/migration-adapters/ignored-files.ts +6 -1
  327. package/src/migration-adapters/index.ts +4 -1
  328. package/src/migration-adapters/types.ts +6 -2
  329. package/src/onboarding/agents-generate.ts +23 -14
  330. package/src/onboarding/create.ts +7 -6
  331. package/src/onboarding/doctor.ts +7 -13
  332. package/src/onboarding/init.ts +7 -12
  333. package/src/onboarding/invariant-engine.ts +7 -2
  334. package/src/onboarding/nested-agents-generate.ts +7 -2
  335. package/src/onboarding/nested-agents-templates.ts +11 -3
  336. package/src/onboarding/scaffold-project.ts +6 -1
  337. package/src/onboarding/upgrade.ts +7 -3
  338. package/src/profiles/profile-schema.ts +42 -18
  339. package/src/profiles/stack-profile.ts +7 -3
  340. package/src/registry.ts +7 -9
  341. package/src/tests/agents-generate-domain.test.ts +3 -3
  342. package/src/tests/agents-generate.test.ts +2 -2
  343. package/src/tests/create.test.ts +4 -4
  344. package/src/tests/forge-autonomy-validate.test.ts +1 -1
  345. package/src/tests/package-files.test.ts +53 -1
  346. package/src/tests/profile-schema.test.ts +4 -4
  347. package/src/tests/scaffold-project.test.ts +3 -3
  348. package/src/tests/stack-profile.test.ts +12 -12
  349. package/src/types.ts +6 -1
  350. package/src/utils/fs-atomic.ts +13 -1
  351. package/src/utils/fs-idempotent.ts +13 -0
  352. package/src/utils/fs-trash-sync.ts +13 -1
  353. package/src/utils/fs-trash.ts +13 -1
  354. package/src/utils/fs.ts +14 -3
  355. package/src/utils/hash.ts +12 -1
  356. package/src/utils/index.ts +13 -2
  357. package/src/utils/string-utils.ts +12 -1
  358. package/src/validators/port-validate.ts +1 -1
  359. package/src/validators/skill-validate.ts +7 -8
  360. package/skills/shared/extension-e2e-mitm/SKILL.md +0 -53
  361. package/skills/shared/extension-e2e-mitm/fixture-proxy.ts +0 -113
  362. package/src/types/werkstatt-engine-shims.d.ts +0 -1416
  363. package/src/types/werkstatt-shared-shims.d.ts +0 -5686
@@ -9,6 +9,10 @@
9
9
  <item>RFC-0374: initial forgeCompassModule registering 12 compass commands.</item>
10
10
  <item>RFC-0538: renamed compass.changesummary.tidy to compass.summary.trim, removed compass.annotate, compass.clear, compass.markup.migrate, compass.invariant.add.</item>
11
11
  <item>RFC-0556: removed dynamic import of @warpgogol/site-kernel-checks, all handlers now inlined in forge/os/compass/handlers/.</item>
12
+ <item>RFC-1095: compass.summary.record, trim repair rewrite, commit integration</item>
13
+ <item>RFC-1097: steps 1-4 — compass.migrate codemod
14
+
15
+ Add the v1 to v2 Compass header codemod: migrateFile pure transform (collapse, strip, seed, reorder, purpose-flag actions), migrateWorkspace walker, runCompassMigrate handler with dirty-tree refusal and --force/--files/--dry-run flags, module registration, and 15 unit tests.</item>
12
16
  </CHANGE_SUMMARY>
13
17
  */
14
18
 
@@ -21,10 +25,9 @@ import {
21
25
  runCompassAuditBaseline,
22
26
  runCompassAuditValidate,
23
27
  } from "./handlers/compass-audit-handler.ts";
24
- import {
25
- runCompassChangeSummaryValidate,
26
- runCompassSummaryTrim,
27
- } from "./handlers/compass-change-summary-handler.ts";
28
+ import { runCompassSummaryTrim } from "./handlers/compass-change-summary-handler.ts";
29
+ import { runCompassSummaryRecord } from "./handlers/summary-record.ts";
30
+ import { runCompassMigrate } from "./handlers/compass-migrate-handler.ts";
28
31
 
29
32
  const compassScanFlags = {
30
33
  packages: {
@@ -33,7 +36,7 @@ const compassScanFlags = {
33
36
  },
34
37
  package: {
35
38
  kind: "string",
36
- description: "With --packages, scan one package by directory/name.",
39
+ description: "Scan one package by directory/name (implies --packages).",
37
40
  },
38
41
  workpiece: {
39
42
  kind: "string",
@@ -85,25 +88,47 @@ export const forgeCompassModule: ForgeModule = {
85
88
  execute: runCompassValidation,
86
89
  },
87
90
  {
88
- name: "compass.changesummary.validate",
89
- contract: "compass",
90
- rules: [],
91
+ name: "compass.summary.record",
91
92
  description:
92
- "Validate CHANGE_SUMMARY blocks for boilerplate items and over-cap unprotected items (RFC-0349).",
93
+ "Append a governance-referencing item to each target file's CHANGE_SUMMARY and collapse the 5-item window into <history> (RFC-1095). Invoked by commit commands when a commit carries an RFC/ADR reference.",
93
94
  scope: "workspace",
95
+ mutatesState: true,
94
96
  supportsAllSites: true,
95
- flags: { ...compassScanFlags, mode: compassModeFlag },
97
+ writes: [
98
+ "apps/**/*.{astro,ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
99
+ "packages/**/*.{astro,ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
100
+ "services/**/*.{ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
101
+ ],
96
102
  reads: [
97
103
  "packages/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
98
104
  "apps/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
99
105
  "services/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
100
106
  ],
101
- execute: runCompassChangeSummaryValidate,
107
+ cacheable: false,
108
+ flags: {
109
+ ...compassScanFlags,
110
+ id: {
111
+ kind: "string",
112
+ required: true,
113
+ description: "Governance ID to record (e.g. RFC-1095, ADR-0042).",
114
+ },
115
+ files: {
116
+ kind: "string[]",
117
+ description:
118
+ "Target files (repo-relative, or workpiece-relative with --workpiece). Commit integrations pass the commit's changed-file set.",
119
+ },
120
+ text: {
121
+ kind: "string",
122
+ description:
123
+ "Item description. Default: commit subject minus conventional prefix; bare ID outside commit context.",
124
+ },
125
+ },
126
+ execute: runCompassSummaryRecord,
102
127
  },
103
128
  {
104
129
  name: "compass.summary.trim",
105
130
  description:
106
- "Deterministically trim CHANGE_SUMMARY blocks: remove boilerplate, cap total items to 30, preserve protected items (RFC-0538).",
131
+ "Repair CHANGE_SUMMARY blocks to the v2 shape: collapse described items past 5 into <history>, remove ID-less items, normalize <history> (RFC-1095).",
107
132
  scope: "workspace",
108
133
  mutatesState: true,
109
134
  supportsAllSites: true,
@@ -118,9 +143,50 @@ export const forgeCompassModule: ForgeModule = {
118
143
  "services/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
119
144
  ],
120
145
  cacheable: false,
121
- flags: { ...compassScanFlags },
146
+ flags: {
147
+ ...compassScanFlags,
148
+ mode: {
149
+ kind: "string",
150
+ description: "Repair mode: repair (default, only mode — reserved for future modes).",
151
+ },
152
+ },
122
153
  execute: runCompassSummaryTrim,
123
154
  },
155
+ {
156
+ name: "compass.migrate",
157
+ description:
158
+ "Rewrite authored file headers to the Compass v2 shape (RFC-1097): collapse CHANGE_SUMMARY into <history>, strip forbidden v1 blocks, seed KEY_DECISIONS from @ai-invariant comments, reorder blocks canonically. Refuses a dirty git tree unless --force.",
159
+ scope: "workspace",
160
+ mutatesState: true,
161
+ supportsAllSites: true,
162
+ writes: [
163
+ "apps/**/*.{astro,ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
164
+ "packages/**/*.{astro,ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
165
+ "services/**/*.{ts,tsx,js,mjs,css,cs,tscn,tres,gd,md}",
166
+ ],
167
+ reads: [
168
+ "packages/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
169
+ "apps/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
170
+ "services/**/*.{ts,tsx,astro,js,mjs,css,cs,tscn,tres,gd,md}",
171
+ ],
172
+ cacheable: false,
173
+ flags: {
174
+ ...compassScanFlags,
175
+ files: {
176
+ kind: "string[]",
177
+ description: "Explicit root-relative file list — bypasses scan-root filtering entirely.",
178
+ },
179
+ "dry-run": {
180
+ kind: "boolean",
181
+ description: "Print the action manifest without writing any file.",
182
+ },
183
+ force: {
184
+ kind: "boolean",
185
+ description: "Override the dirty-tree refusal.",
186
+ },
187
+ },
188
+ execute: runCompassMigrate,
189
+ },
124
190
  {
125
191
  name: "compass.audit.plan",
126
192
  description:
@@ -21,6 +21,7 @@ import { resolve, relative } from "node:path";
21
21
  import { execFile } from "node:child_process";
22
22
  import { promisify } from "node:util";
23
23
  import { createCompassInventoryEntries } from "./compass-inventory.ts";
24
+ import { resolveCompassPolicy } from "../policy.ts";
24
25
  import { resolveCompassScanRoot } from "./resolve-scan-root.ts";
25
26
  import { getRevisionByPath } from "./git-revision.ts";
26
27
  import type { CompassInventoryEntry } from "./compass-inventory.ts";
@@ -139,7 +140,13 @@ export async function runCompassAuditPlan(
139
140
  }>
140
141
  > {
141
142
  const scanRoot = resolveCompassScanRoot(input, context);
142
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
143
+ const policy = resolveCompassPolicy(context.workspaceRoot, context.forgeRoot);
144
+ const entries = await createCompassInventoryEntries(
145
+ context.workspaceRoot,
146
+ input,
147
+ scanRoot,
148
+ policy,
149
+ );
143
150
  const authored = getAuthoredEntries(entries);
144
151
  const ledger = await loadLedger(context.workspaceRoot);
145
152
 
@@ -283,7 +290,13 @@ export async function runCompassAuditBaseline(
283
290
  }>
284
291
  > {
285
292
  const scanRoot = resolveCompassScanRoot(input, context);
286
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
293
+ const policy = resolveCompassPolicy(context.workspaceRoot, context.forgeRoot);
294
+ const entries = await createCompassInventoryEntries(
295
+ context.workspaceRoot,
296
+ input,
297
+ scanRoot,
298
+ policy,
299
+ );
287
300
  const authored = getAuthoredEntries(entries);
288
301
  const ledger = await loadLedger(context.workspaceRoot);
289
302
 
@@ -347,7 +360,13 @@ export async function runCompassAuditValidate(
347
360
  > {
348
361
  const strict = input.flags["strict"] === true;
349
362
  const scanRoot = resolveCompassScanRoot(input, context);
350
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
363
+ const policy = resolveCompassPolicy(context.workspaceRoot, context.forgeRoot);
364
+ const entries = await createCompassInventoryEntries(
365
+ context.workspaceRoot,
366
+ input,
367
+ scanRoot,
368
+ policy,
369
+ );
351
370
  const authored = getAuthoredEntries(entries);
352
371
  const ledger = await loadLedger(context.workspaceRoot);
353
372
 
@@ -1,228 +1,74 @@
1
1
  /*
2
2
  <MODULE_CONTRACT>
3
- <purpose>CHANGE_SUMMARY classification, validation, and deterministic tidy logic
4
- per RFC-0349. Moved from @warpgogol/site-kernel-checks to @warpgogol/forge for full
5
- autonomous mode (RFC-0556). Provides compass.changesummary.validate and compass.summary.trim.</purpose>
3
+ <purpose>CHANGE_SUMMARY v2 repair logic per RFC-1095. Moved from
4
+ @warpgogol/site-kernel-checks to @warpgogol/forge for full autonomous mode
5
+ (RFC-0556). Provides compass.summary.trim --mode repair.</purpose>
6
6
  <non-goals>
7
7
  <item>Do not audit truthfulness of CHANGE_SUMMARY items against code — that is RFC-0352.</item>
8
- <item>Do not delete protected (RFC/code-referencing) items under any circumstance.</item>
9
- <item>Do not use an LLM — classification and tidy are purely deterministic.</item>
8
+ <item>Do not use an LLM — repair is purely deterministic.</item>
9
+ <item>Do not classify items — under the v2 contract every item carries a governance ID; ID-less items are removed, not classified.</item>
10
10
  </non-goals>
11
11
  </MODULE_CONTRACT>
12
12
  <CHANGE_SUMMARY>
13
- <item>RFC-0349: initial implementation of classifyChangeSummaryItem, compass.changesummary.validate, and compass.changesummary.tidy.</item>
14
13
  <item>RFC-0538: renamed compass.changesummary.tidy to compass.summary.trim, raised cap from 3 unprotected to 30 total items, aligned validate cap to 30 total.</item>
15
14
  <item>RFC-0556: moved from @warpgogol/site-kernel-checks to @warpgogol/forge for autonomous mode.</item>
16
15
  <item>RFC-1094: --mode flag; mode-aware COMPASS-CS-05/06/07 diagnostics via shared evaluateV2Rules; PROTECTED_RE now aliases GOVERNANCE_ID_RE.</item>
16
+ <item>RFC-1095: rewrote trim as v2 repair (collapse >5 described items into history, remove ID-less items, normalize history); removed compass.changesummary.validate and the classify machinery (classifyChangeSummaryItem, PROTECTED_RE, BOILERPLATE_RE).</item>
17
+ <item>RFC-1095: compass.summary.record, trim repair rewrite, commit integration</item>
18
+ <history>RFC-0349</history>
17
19
  </CHANGE_SUMMARY>
18
20
  */
19
21
 
20
22
  import { resolve } from "node:path";
21
23
  import { readFile } from "node:fs/promises";
22
- import {
23
- createCompassInventoryEntries,
24
- evaluateV2Rules,
25
- getEntrySource,
26
- resolveCompassMode,
27
- GOVERNANCE_ID_RE,
28
- } from "./compass-inventory.ts";
24
+ import { createCompassInventoryEntries } from "./compass-inventory.ts";
25
+ import { resolveCompassPolicy } from "../policy.ts";
29
26
  import { resolveCompassScanRoot } from "./resolve-scan-root.ts";
30
27
  import { writeFileIfChanged } from "../../../src/utils/fs-idempotent.ts";
28
+ import {
29
+ buildChangeSummaryBlock,
30
+ CHANGE_SUMMARY_WINDOW,
31
+ mergeHistoryIds,
32
+ parseChangeSummary,
33
+ } from "./summary-record.ts";
31
34
  import type {
32
- Diagnostic,
33
35
  ForgeCommandInput,
34
36
  ForgeCommandResult,
35
37
  ForgeRuntimeContext,
36
38
  } from "../../../src/types.ts";
37
39
 
38
- const PROTECTED_RE = GOVERNANCE_ID_RE;
39
- const BOILERPLATE_RE =
40
- /^(Wave\s+\d|Backfill\b|Annotate Compass|Annotation revision|Initial creation|Compass scaffolding|Created as part of|Enhance .* with Compass)/i;
41
-
42
- export type ChangeSummaryItemClass = "protected" | "boilerplate" | "unprotected";
40
+ const CHANGE_SUMMARY_BLOCK_RE = /<CHANGE_SUMMARY>[\s\S]*?<\/CHANGE_SUMMARY>/;
43
41
 
44
- export function classifyChangeSummaryItem(text: string): ChangeSummaryItemClass {
45
- if (PROTECTED_RE.test(text)) return "protected";
46
- if (BOILERPLATE_RE.test(text.trim())) return "boilerplate";
47
- return "unprotected";
48
- }
49
-
50
- function extractChangeSummaryBlock(source: string): string | null {
51
- const match = source.match(/<CHANGE_SUMMARY>[\s\S]*?<\/CHANGE_SUMMARY>/);
52
- return match?.[0] ?? null;
53
- }
54
-
55
- function extractItems(block: string): string[] {
56
- const items: string[] = [];
57
- const re = /<item>([\s\S]*?)<\/item>/g;
58
- let m: RegExpExecArray | null;
59
- while ((m = re.exec(block)) !== null) {
60
- items.push(m[1]!.trim());
61
- }
62
- return items;
63
- }
64
-
65
- function getLineCommentPrefix(filePath: string): string | null {
66
- if (filePath.endsWith(".gd")) return "# ";
67
- if (filePath.endsWith(".tscn") || filePath.endsWith(".tres")) return "; ";
68
- return null;
69
- }
70
-
71
- function rebuildChangeSummaryBlock(items: string[], filePath: string): string {
72
- const prefix = getLineCommentPrefix(filePath);
73
- const lines = ["<CHANGE_SUMMARY>"];
74
- for (const item of items) {
75
- lines.push(` <item>${item}</item>`);
76
- }
77
- lines.push("</CHANGE_SUMMARY>");
78
- if (prefix) {
79
- return lines.map((line, i) => (i === 0 ? line : prefix + line)).join("\n");
80
- }
81
- return lines.join("\n");
82
- }
83
-
84
- function replaceChangeSummaryBlock(source: string, newBlock: string): string {
85
- return source.replace(/<CHANGE_SUMMARY>[\s\S]*?<\/CHANGE_SUMMARY>/, newBlock);
86
- }
87
-
88
- const MAX_TOTAL_ITEMS = 30;
89
-
90
- export async function runCompassChangeSummaryValidate(
42
+ export async function runCompassSummaryTrim(
91
43
  input: ForgeCommandInput,
92
44
  context: ForgeRuntimeContext,
93
45
  ): Promise<
94
46
  ForgeCommandResult<{
95
47
  command: string;
96
- status: "pass" | "fail";
97
- diagnostics: Diagnostic[];
98
- checkedFiles: number;
48
+ status: "ok";
49
+ files: Array<{ path: string; removed: string[]; kept: number }>;
99
50
  }>
100
51
  > {
101
- const scanRoot = resolveCompassScanRoot(input, context);
102
- let mode: ReturnType<typeof resolveCompassMode>;
103
- try {
104
- mode = resolveCompassMode(input);
105
- } catch {
52
+ const mode = input.flags["mode"];
53
+ if (mode !== undefined && mode !== "repair") {
106
54
  context.logger.error(
107
- `[compass.changesummary.validate] invalid --mode value: ${String(input.flags["mode"])} (expected warning|error)`,
55
+ `[compass.summary.trim] invalid --mode value: ${String(mode)} (expected "repair")`,
108
56
  );
109
57
  return { exitCode: 1, summary: "invalid --mode value" };
110
58
  }
111
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
112
-
113
- const diagnostics: Diagnostic[] = [];
114
- let checkedFiles = 0;
115
-
116
- // RFC-1094: v2 CS rules (CS-05/06/07) are mode-aware; v1 rules (CS-01/02)
117
- // stay at error severity in both modes until the sibling lifecycle RFC lands.
118
- const v2Severity = mode === "error" ? "error" : "warning";
119
-
120
- for (const entry of entries) {
121
- if (entry.authoringStatus !== "authored" || entry.requiredScaffolding === "none") {
122
- continue;
123
- }
124
-
125
- checkedFiles++;
126
-
127
- const absPath = resolve(context.workspaceRoot, entry.path);
128
- const source = getEntrySource(entry) ?? (await readFile(absPath, "utf8"));
129
-
130
- for (const v2 of evaluateV2Rules(entry, source)) {
131
- if (!v2.ruleId.startsWith("COMPASS-CS-")) {
132
- continue;
133
- }
134
- diagnostics.push({
135
- ruleId: v2.ruleId,
136
- severity: v2Severity,
137
- file: entry.path,
138
- message: v2.message,
139
- fixHint: v2.fix,
140
- });
141
- }
142
-
143
- if (!entry.hasChangeSummary) {
144
- continue;
145
- }
146
-
147
- const block = extractChangeSummaryBlock(source);
148
- if (!block) continue;
149
-
150
- const items = extractItems(block);
151
- let hasBoilerplate = false;
152
- let totalItems = 0;
153
-
154
- for (const item of items) {
155
- const cls = classifyChangeSummaryItem(item);
156
- if (cls === "boilerplate") {
157
- hasBoilerplate = true;
158
- }
159
- totalItems++;
160
- }
161
-
162
- if (hasBoilerplate) {
163
- diagnostics.push({
164
- ruleId: "COMPASS-CS-01",
165
- severity: "error",
166
- file: entry.path,
167
- message: "CHANGE_SUMMARY contains a boilerplate item",
168
- fixHint: "fix: run compass.summary.trim",
169
- });
170
- }
171
-
172
- if (totalItems > MAX_TOTAL_ITEMS) {
173
- diagnostics.push({
174
- ruleId: "COMPASS-CS-02",
175
- severity: "error",
176
- file: entry.path,
177
- message: `CHANGE_SUMMARY has ${totalItems} total items (cap is ${MAX_TOTAL_ITEMS})`,
178
- fixHint: `fix: run compass.summary.trim (cap is ${MAX_TOTAL_ITEMS} total items)`,
179
- });
180
- }
181
- }
182
-
183
- const failed = diagnostics.some((d) => d.severity === "error");
184
-
185
- for (const d of diagnostics) {
186
- const log = `[compass.changesummary.validate] ${d.ruleId}: ${d.file}: ${d.message}`;
187
- if (d.severity === "error") {
188
- context.logger.error(log);
189
- } else {
190
- context.logger.warn(log);
191
- }
192
- }
193
-
194
- return {
195
- data: {
196
- command: "compass.changesummary.validate",
197
- status: failed ? "fail" : "pass",
198
- diagnostics,
199
- checkedFiles,
200
- },
201
- exitCode: failed ? 1 : 0,
202
- summary: failed
203
- ? undefined
204
- : `[compass.changesummary.validate] OK (${checkedFiles} authored files checked)`,
205
- };
206
- }
207
-
208
- const TRIM_FALLBACK_ITEM = "Tidied by compass.summary.trim; see git history for prior entries.";
209
59
 
210
- export async function runCompassSummaryTrim(
211
- input: ForgeCommandInput,
212
- context: ForgeRuntimeContext,
213
- ): Promise<
214
- ForgeCommandResult<{
215
- command: string;
216
- status: "ok";
217
- files: Array<{ path: string; removed: string[]; kept: number }>;
218
- }>
219
- > {
220
60
  if (context.dryRun) {
221
61
  context.logger.info(`[compass.summary.trim] dry-run active — will not apply changes`);
222
62
  }
223
63
 
224
64
  const scanRoot = resolveCompassScanRoot(input, context);
225
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
65
+ const policy = resolveCompassPolicy(context.workspaceRoot, context.forgeRoot);
66
+ const entries = await createCompassInventoryEntries(
67
+ context.workspaceRoot,
68
+ input,
69
+ scanRoot,
70
+ policy,
71
+ );
226
72
 
227
73
  const results: Array<{ path: string; removed: string[]; kept: number }> = [];
228
74
 
@@ -237,58 +83,40 @@ export async function runCompassSummaryTrim(
237
83
 
238
84
  const absPath = resolve(context.workspaceRoot, entry.path);
239
85
  const source = await readFile(absPath, "utf8");
240
- const block = extractChangeSummaryBlock(source);
241
- if (!block) continue;
86
+ const blockMatch = source.match(CHANGE_SUMMARY_BLOCK_RE);
87
+ if (!blockMatch) continue;
242
88
 
243
- const items = extractItems(block);
244
- const keptItems: string[] = [];
89
+ const { items, historyIds } = parseChangeSummary(blockMatch[0]);
245
90
  const removedItems: string[] = [];
246
91
 
247
- const unprotectedItems: Array<{ index: number; text: string }> = [];
248
-
249
- for (let i = 0; i < items.length; i++) {
250
- const text = items[i]!;
251
- const cls = classifyChangeSummaryItem(text);
252
-
253
- if (cls === "protected") {
254
- keptItems.push(text);
255
- } else if (cls === "boilerplate") {
256
- removedItems.push(text);
92
+ // v2 repair: drop ID-less items, collapse described items past the window.
93
+ const idItems: string[] = [];
94
+ for (const item of items) {
95
+ if (policy.idPatternPrefix.test(item)) {
96
+ idItems.push(item);
257
97
  } else {
258
- unprotectedItems.push({ index: i, text });
98
+ removedItems.push(item);
259
99
  }
260
100
  }
261
101
 
262
- const protectedCount = keptItems.length;
263
- const maxUnprotectedToKeep = Math.max(0, MAX_TOTAL_ITEMS - protectedCount);
264
- const unprotectedToKeep = unprotectedItems.slice(-maxUnprotectedToKeep);
265
- const unprotectedToRemove = unprotectedItems.slice(0, -maxUnprotectedToKeep);
266
-
267
- for (const item of unprotectedToRemove) {
268
- removedItems.push(item.text);
269
- }
270
-
271
- const keepSet = new Set<string>();
272
- for (const item of unprotectedToKeep) {
273
- keepSet.add(item.text);
102
+ const collapsedIds: string[] = [];
103
+ while (idItems.length > CHANGE_SUMMARY_WINDOW) {
104
+ const oldest = idItems.shift()!;
105
+ const idMatch = oldest.match(policy.idPatternPrefix);
106
+ if (idMatch) collapsedIds.push(idMatch[0]);
107
+ removedItems.push(oldest);
274
108
  }
275
109
 
276
- const finalItems: string[] = [];
277
- const protectedTexts = new Set(keptItems);
278
- const unprotectedTexts = new Set(unprotectedToKeep.map((u) => u.text));
110
+ const nextHistory = mergeHistoryIds(historyIds, collapsedIds, policy);
111
+ const historyChanged =
112
+ nextHistory.length !== historyIds.length || nextHistory.some((id, i) => id !== historyIds[i]);
279
113
 
280
- for (const originalItem of items) {
281
- if (protectedTexts.has(originalItem) || unprotectedTexts.has(originalItem)) {
282
- finalItems.push(originalItem);
283
- }
284
- }
285
-
286
- if (finalItems.length === 0) {
287
- finalItems.push(TRIM_FALLBACK_ITEM);
114
+ if (removedItems.length === 0 && !historyChanged) {
115
+ continue;
288
116
  }
289
117
 
290
- const newBlock = rebuildChangeSummaryBlock(finalItems, entry.path);
291
- const transformed = replaceChangeSummaryBlock(source, newBlock);
118
+ const newBlock = buildChangeSummaryBlock(idItems, nextHistory, entry.path);
119
+ const transformed = source.replace(CHANGE_SUMMARY_BLOCK_RE, newBlock);
292
120
 
293
121
  if (transformed === source) {
294
122
  continue;
@@ -299,13 +127,13 @@ export async function runCompassSummaryTrim(
299
127
  }
300
128
 
301
129
  context.logger.info(
302
- `[compass.summary.trim] trimmed: ${entry.path} (removed ${removedItems.length}, kept ${finalItems.length})`,
130
+ `[compass.summary.trim] repaired: ${entry.path} (removed ${removedItems.length}, kept ${idItems.length})`,
303
131
  );
304
132
 
305
133
  results.push({
306
134
  path: entry.path,
307
135
  removed: removedItems,
308
- kept: finalItems.length,
136
+ kept: idItems.length,
309
137
  });
310
138
  }
311
139
 
@@ -319,7 +147,7 @@ export async function runCompassSummaryTrim(
319
147
  summary: `[compass.summary.trim] files=${results.length}, removed=${results.reduce((sum, r) => sum + r.removed.length, 0)}`,
320
148
  nextSteps: [
321
149
  {
322
- action: `Commit the trimmed headers: pnpm exec forge run ecosystem.commit`,
150
+ action: `Commit the repaired headers: pnpm exec forge run ecosystem.commit`,
323
151
  kind: "optional",
324
152
  },
325
153
  ],
@@ -12,12 +12,16 @@ contract block specs alongside built-in MODULE_CONTRACT and CHANGE_SUMMARY check
12
12
  </non-goals>
13
13
  </MODULE_CONTRACT>
14
14
  <CHANGE_SUMMARY>
15
- <item>RFC-0348: v2 two-block contract — XML output updated, compass.validate emits COMPASS-* diagnostics, summary uses standard-required-files.</item>
16
- <item>RFC-0350: added COMPASS-TODO-01 diagnostic for unfilled Compass TODO sentinels.</item>
17
- <item>RFC-0556: moved from @warpgogol/site-kernel-checks to @warpgogol/forge for autonomous mode.</item>
18
- <item>Game extensions: added COMPASS-SYNTAX-01 diagnostic validating comment syntax per file type (.gd needs # prefix, .tscn/.tres need ; prefix, .ts/.cs need block comment).</item>
19
15
  <item>RFC-0943: added COMPASS-PLUGIN-01/02/03 diagnostics for pack-declared contract block specs from forge.plugin.yaml extensionPoints.</item>
20
16
  <item>RFC-1094: --mode warning|error on compass.validate; mode-aware v2 diagnostics (KD/ORDER/PURPOSE) with severity field; inventory data.entries now carries full entries and XML gains v2 fields.</item>
17
+ <item>RFC-1095: summary-record unit tests, commit integration tests, CS rules into compass.validate</item>
18
+ <item>RFC-1097: step 6 — compass.migrate codemod run
19
+
20
+ Mechanical v1 to v2 header migration across the workspace: 942 files rewritten — CHANGE_SUMMARY windows collapsed into history, forbidden v1 blocks stripped, KEY_DECISIONS seeded from @ai-invariant comments (5 files) or TODO placeholders (103 files), blocks reordered to canonical order.</item>
21
+ <item>RFC-1097: sweep — packages/forge + services clean
22
+
23
+ Sweep batch 2: real KEY_DECISIONS on 10 files, expanded purposes (CONTRACT-02/PURPOSE-02), headers on mission/index + gen-upstreams, sanitizeItemText in summary.record (literal Compass tags corrupted history), excludedPaths for wrangler types, test-fixtures testPattern. forge+services now 0 diagnostics under --mode error.</item>
24
+ <history>RFC-0348, RFC-0350, RFC-0556</history>
21
25
  </CHANGE_SUMMARY>
22
26
  */
23
27
 
@@ -31,6 +35,7 @@ import {
31
35
  type CompassInventoryEntry,
32
36
  } from "./compass-inventory.ts";
33
37
  import { resolveCompassScanRoot } from "./resolve-scan-root.ts";
38
+ import { resolveCompassPolicy, type CompassPolicySource } from "../policy.ts";
34
39
  import { writeFileIfChanged } from "../../../src/utils/fs-idempotent.ts";
35
40
  import { loadForgeConfig } from "../../../src/config/forge-config.ts";
36
41
  import {
@@ -259,10 +264,12 @@ export async function runCompassInventory(
259
264
  entries: CompassInventoryEntry[];
260
265
  outputPath: string;
261
266
  summary: CompassInventorySummary;
267
+ policySource: CompassPolicySource;
262
268
  }>
263
269
  > {
264
270
  const scanRoot = resolveCompassScanRoot(input, context) ?? context.workspaceRoot;
265
- const entries = await createCompassInventoryEntries(scanRoot, input);
271
+ const policy = resolveCompassPolicy(scanRoot, context.forgeRoot);
272
+ const entries = await createCompassInventoryEntries(scanRoot, input, undefined, policy);
266
273
  const summary = summarizeInventory(entries);
267
274
 
268
275
  context.logger.info(
@@ -274,7 +281,7 @@ export async function runCompassInventory(
274
281
  `[compass.inventory] dry-run active — skipped writing ${INVENTORY_OUTPUT_PATH}`,
275
282
  );
276
283
  return {
277
- data: { entries, outputPath: INVENTORY_OUTPUT_PATH, summary },
284
+ data: { entries, outputPath: INVENTORY_OUTPUT_PATH, summary, policySource: policy.source },
278
285
  summary: `[compass.inventory] previewed ${INVENTORY_OUTPUT_PATH}`,
279
286
  nextSteps: [
280
287
  {
@@ -290,7 +297,7 @@ export async function runCompassInventory(
290
297
  await writeFileIfChanged(outputPath, xml);
291
298
 
292
299
  return {
293
- data: { entries, outputPath, summary },
300
+ data: { entries, outputPath, summary, policySource: policy.source },
294
301
  summary: `[compass.inventory] ${context.dryRun ? "previewed" : "wrote"} ${INVENTORY_OUTPUT_PATH}`,
295
302
  nextSteps: context.dryRun
296
303
  ? [
@@ -335,7 +342,13 @@ export async function runCompassValidation(
335
342
  );
336
343
  return { exitCode: 1, summary: "invalid --mode value" };
337
344
  }
338
- const entries = await createCompassInventoryEntries(context.workspaceRoot, input, scanRoot);
345
+ const policy = resolveCompassPolicy(context.workspaceRoot, context.forgeRoot);
346
+ const entries = await createCompassInventoryEntries(
347
+ context.workspaceRoot,
348
+ input,
349
+ scanRoot,
350
+ policy,
351
+ );
339
352
  const summary = summarizeInventory(entries);
340
353
  const failures = entries.filter(
341
354
  (entry) =>
@@ -355,9 +368,14 @@ export async function runCompassValidation(
355
368
 
356
369
  // RFC-1094: v2 rules are mode-aware — warnings in `warning` mode (default
357
370
  // during the migration window), errors in `error` mode. Owned subset:
358
- // COMPASS-KD-*, COMPASS-ORDER-01, COMPASS-PURPOSE-*. CS-* rules are emitted
359
- // by compass.changesummary.validate.
360
- const V2_VALIDATE_RULE_PREFIXES = ["COMPASS-KD-", "COMPASS-ORDER-", "COMPASS-PURPOSE-"];
371
+ // COMPASS-KD-*, COMPASS-ORDER-01, COMPASS-PURPOSE-*, COMPASS-CS-*.
372
+ // RFC-1095: CS-* rules moved here — compass.changesummary.validate is removed.
373
+ const V2_VALIDATE_RULE_PREFIXES = [
374
+ "COMPASS-KD-",
375
+ "COMPASS-ORDER-",
376
+ "COMPASS-PURPOSE-",
377
+ "COMPASS-CS-",
378
+ ];
361
379
  const v2Severity = mode === "error" ? "error" : "warning";
362
380
  const authoredEntries = entries.filter(
363
381
  (entry) => entry.authoringStatus === "authored" && entry.requiredScaffolding !== "none",
@@ -365,7 +383,7 @@ export async function runCompassValidation(
365
383
  for (const entry of authoredEntries) {
366
384
  const absPath = resolve(context.workspaceRoot, entry.path);
367
385
  const source = getEntrySource(entry) ?? (await readFile(absPath, "utf8"));
368
- for (const v2 of evaluateV2Rules(entry, source)) {
386
+ for (const v2 of evaluateV2Rules(entry, source, policy)) {
369
387
  if (!V2_VALIDATE_RULE_PREFIXES.some((prefix) => v2.ruleId.startsWith(prefix))) {
370
388
  continue;
371
389
  }