@warpgogol/forge 5.3.3 → 6.0.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 (282) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/bin/cli.ts +7 -2
  3. package/dist/bin/cli.js +7 -2
  4. package/dist/bin/cli.js.map +1 -1
  5. package/dist/os/adr/adr.module.d.ts.map +1 -1
  6. package/dist/os/adr/adr.module.js +2 -0
  7. package/dist/os/adr/adr.module.js.map +1 -1
  8. package/dist/os/audit/audit.module.d.ts.map +1 -1
  9. package/dist/os/audit/audit.module.js +2 -0
  10. package/dist/os/audit/audit.module.js.map +1 -1
  11. package/dist/os/compass/compass.module.d.ts.map +1 -1
  12. package/dist/os/compass/compass.module.js +48 -16
  13. package/dist/os/compass/compass.module.js.map +1 -1
  14. package/dist/os/compass/handlers/compass-audit-handler.d.ts +2 -0
  15. package/dist/os/compass/handlers/compass-audit-handler.d.ts.map +1 -1
  16. package/dist/os/compass/handlers/compass-audit-handler.js +39 -9
  17. package/dist/os/compass/handlers/compass-audit-handler.js.map +1 -1
  18. package/dist/os/compass/handlers/compass-docs-validate.d.ts +13 -0
  19. package/dist/os/compass/handlers/compass-docs-validate.d.ts.map +1 -0
  20. package/dist/os/compass/handlers/compass-docs-validate.js +326 -0
  21. package/dist/os/compass/handlers/compass-docs-validate.js.map +1 -0
  22. package/dist/os/compass/handlers/compass-inventory.d.ts.map +1 -1
  23. package/dist/os/compass/handlers/compass-inventory.js +5 -2
  24. package/dist/os/compass/handlers/compass-inventory.js.map +1 -1
  25. package/dist/os/compass/handlers/summary-record.d.ts +17 -3
  26. package/dist/os/compass/handlers/summary-record.d.ts.map +1 -1
  27. package/dist/os/compass/handlers/summary-record.js +107 -10
  28. package/dist/os/compass/handlers/summary-record.js.map +1 -1
  29. package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts +18 -0
  30. package/dist/os/compass/handlers/tests/forge-yaml-fixture.d.ts.map +1 -0
  31. package/dist/os/compass/handlers/tests/forge-yaml-fixture.js +64 -0
  32. package/dist/os/compass/handlers/tests/forge-yaml-fixture.js.map +1 -0
  33. package/dist/os/compass/policy.d.ts +6 -1
  34. package/dist/os/compass/policy.d.ts.map +1 -1
  35. package/dist/os/compass/policy.js +8 -2
  36. package/dist/os/compass/policy.js.map +1 -1
  37. package/dist/os/core/core.module.d.ts.map +1 -1
  38. package/dist/os/core/core.module.js +124 -73
  39. package/dist/os/core/core.module.js.map +1 -1
  40. package/dist/os/exploration/exploration.module.d.ts.map +1 -1
  41. package/dist/os/exploration/exploration.module.js +3 -0
  42. package/dist/os/exploration/exploration.module.js.map +1 -1
  43. package/dist/os/mission/handlers/archive.d.ts.map +1 -1
  44. package/dist/os/mission/handlers/archive.js +1 -2
  45. package/dist/os/mission/handlers/archive.js.map +1 -1
  46. package/dist/os/naming/naming.module.d.ts.map +1 -1
  47. package/dist/os/naming/naming.module.js +9 -2
  48. package/dist/os/naming/naming.module.js.map +1 -1
  49. package/dist/os/notes/notes.module.d.ts.map +1 -1
  50. package/dist/os/notes/notes.module.js +17 -6
  51. package/dist/os/notes/notes.module.js.map +1 -1
  52. package/dist/os/plan/plan.module.d.ts.map +1 -1
  53. package/dist/os/plan/plan.module.js +2 -0
  54. package/dist/os/plan/plan.module.js.map +1 -1
  55. package/dist/os/plugin/plugin.module.d.ts.map +1 -1
  56. package/dist/os/plugin/plugin.module.js +9 -2
  57. package/dist/os/plugin/plugin.module.js.map +1 -1
  58. package/dist/os/program/program.module.d.ts.map +1 -1
  59. package/dist/os/program/program.module.js +19 -4
  60. package/dist/os/program/program.module.js.map +1 -1
  61. package/dist/os/queue/handlers/queue-validate.d.ts.map +1 -1
  62. package/dist/os/queue/handlers/queue-validate.js +154 -7
  63. package/dist/os/queue/handlers/queue-validate.js.map +1 -1
  64. package/dist/os/queue/manifest.d.ts +17 -1
  65. package/dist/os/queue/manifest.d.ts.map +1 -1
  66. package/dist/os/queue/manifest.js +127 -6
  67. package/dist/os/queue/manifest.js.map +1 -1
  68. package/dist/os/queue/queue.module.d.ts.map +1 -1
  69. package/dist/os/queue/queue.module.js +32 -4
  70. package/dist/os/queue/queue.module.js.map +1 -1
  71. package/dist/os/queue/types.d.ts +100 -1
  72. package/dist/os/queue/types.d.ts.map +1 -1
  73. package/dist/os/queue/types.js +44 -0
  74. package/dist/os/queue/types.js.map +1 -1
  75. package/dist/os/rfc/handlers/implement-stamp.d.ts.map +1 -1
  76. package/dist/os/rfc/handlers/implement-stamp.js +28 -5
  77. package/dist/os/rfc/handlers/implement-stamp.js.map +1 -1
  78. package/dist/os/rfc/handlers/validate.js +1 -1
  79. package/dist/os/rfc/rfc.module.d.ts.map +1 -1
  80. package/dist/os/rfc/rfc.module.js +27 -3
  81. package/dist/os/rfc/rfc.module.js.map +1 -1
  82. package/dist/os/rfc/types.d.ts +11 -0
  83. package/dist/os/rfc/types.d.ts.map +1 -1
  84. package/dist/os/rfc/types.js +1 -0
  85. package/dist/os/rfc/types.js.map +1 -1
  86. package/dist/os/rfc/verification-evidence.d.ts +21 -0
  87. package/dist/os/rfc/verification-evidence.d.ts.map +1 -1
  88. package/dist/os/rfc/verification-evidence.js +140 -23
  89. package/dist/os/rfc/verification-evidence.js.map +1 -1
  90. package/dist/os/rfc/verification-refresh.d.ts.map +1 -1
  91. package/dist/os/rfc/verification-refresh.js +72 -37
  92. package/dist/os/rfc/verification-refresh.js.map +1 -1
  93. package/dist/os/session/handlers/save.d.ts.map +1 -1
  94. package/dist/os/session/handlers/save.js +46 -5
  95. package/dist/os/session/handlers/save.js.map +1 -1
  96. package/dist/os/session/session.module.d.ts.map +1 -1
  97. package/dist/os/session/session.module.js +5 -0
  98. package/dist/os/session/session.module.js.map +1 -1
  99. package/dist/os/spec/live-spec-merge.d.ts.map +1 -1
  100. package/dist/os/spec/live-spec-merge.js +55 -134
  101. package/dist/os/spec/live-spec-merge.js.map +1 -1
  102. package/dist/os/spec/live-spec-rebuild.d.ts +32 -0
  103. package/dist/os/spec/live-spec-rebuild.d.ts.map +1 -0
  104. package/dist/os/spec/live-spec-rebuild.js +272 -0
  105. package/dist/os/spec/live-spec-rebuild.js.map +1 -0
  106. package/dist/os/spec/live-spec-shared.d.ts +62 -0
  107. package/dist/os/spec/live-spec-shared.d.ts.map +1 -0
  108. package/dist/os/spec/live-spec-shared.js +315 -0
  109. package/dist/os/spec/live-spec-shared.js.map +1 -0
  110. package/dist/os/spec/live-spec-types.d.ts +17 -1
  111. package/dist/os/spec/live-spec-types.d.ts.map +1 -1
  112. package/dist/os/spec/live-spec-types.js +3 -0
  113. package/dist/os/spec/live-spec-types.js.map +1 -1
  114. package/dist/os/spec/live-spec-validate.d.ts.map +1 -1
  115. package/dist/os/spec/live-spec-validate.js +105 -2
  116. package/dist/os/spec/live-spec-validate.js.map +1 -1
  117. package/dist/os/spec/spec-materialize.d.ts +2 -0
  118. package/dist/os/spec/spec-materialize.d.ts.map +1 -1
  119. package/dist/os/spec/spec-materialize.js +45 -5
  120. package/dist/os/spec/spec-materialize.js.map +1 -1
  121. package/dist/os/spec/spec-schema.d.ts +19 -0
  122. package/dist/os/spec/spec-schema.d.ts.map +1 -1
  123. package/dist/os/spec/spec-schema.js +30 -0
  124. package/dist/os/spec/spec-schema.js.map +1 -1
  125. package/dist/os/spec/spec-status.d.ts +4 -0
  126. package/dist/os/spec/spec-status.d.ts.map +1 -1
  127. package/dist/os/spec/spec-status.js +19 -1
  128. package/dist/os/spec/spec-status.js.map +1 -1
  129. package/dist/os/spec/spec-validate.d.ts.map +1 -1
  130. package/dist/os/spec/spec-validate.js +55 -8
  131. package/dist/os/spec/spec-validate.js.map +1 -1
  132. package/dist/os/spec/spec.module.d.ts.map +1 -1
  133. package/dist/os/spec/spec.module.js +84 -8
  134. package/dist/os/spec/spec.module.js.map +1 -1
  135. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.d.ts.map +1 -1
  136. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js +10 -4
  137. package/dist/os/werkstatt/handlers/werkstatt-operation-validate.js.map +1 -1
  138. package/dist/os/werkstatt/werkstatt.module.d.ts.map +1 -1
  139. package/dist/os/werkstatt/werkstatt.module.js +13 -4
  140. package/dist/os/werkstatt/werkstatt.module.js.map +1 -1
  141. package/dist/os/workflow/workflow.module.d.ts.map +1 -1
  142. package/dist/os/workflow/workflow.module.js +13 -5
  143. package/dist/os/workflow/workflow.module.js.map +1 -1
  144. package/dist/src/cli-flags.d.ts.map +1 -1
  145. package/dist/src/cli-flags.js +25 -5
  146. package/dist/src/cli-flags.js.map +1 -1
  147. package/dist/src/config/forge-config.d.ts +24 -3
  148. package/dist/src/config/forge-config.d.ts.map +1 -1
  149. package/dist/src/config/forge-config.js +38 -7
  150. package/dist/src/config/forge-config.js.map +1 -1
  151. package/dist/src/onboarding/create.d.ts.map +1 -1
  152. package/dist/src/onboarding/create.js +26 -10
  153. package/dist/src/onboarding/create.js.map +1 -1
  154. package/dist/src/onboarding/doctor.d.ts.map +1 -1
  155. package/dist/src/onboarding/doctor.js +49 -2
  156. package/dist/src/onboarding/doctor.js.map +1 -1
  157. package/dist/src/onboarding/init.d.ts.map +1 -1
  158. package/dist/src/onboarding/init.js +8 -3
  159. package/dist/src/onboarding/init.js.map +1 -1
  160. package/dist/src/onboarding/upgrade.d.ts.map +1 -1
  161. package/dist/src/onboarding/upgrade.js +24 -8
  162. package/dist/src/onboarding/upgrade.js.map +1 -1
  163. package/dist/src/pipeline-status.d.ts +14 -1
  164. package/dist/src/pipeline-status.d.ts.map +1 -1
  165. package/dist/src/pipeline-status.js +28 -8
  166. package/dist/src/pipeline-status.js.map +1 -1
  167. package/dist/src/types.d.ts +7 -1
  168. package/dist/src/types.d.ts.map +1 -1
  169. package/dist/src/types.js +6 -0
  170. package/dist/src/types.js.map +1 -1
  171. package/dist/src/utils/generated-marker.d.ts +8 -0
  172. package/dist/src/utils/generated-marker.d.ts.map +1 -1
  173. package/dist/src/utils/generated-marker.js +25 -0
  174. package/dist/src/utils/generated-marker.js.map +1 -1
  175. package/dist/src/validators/skill-validate.d.ts.map +1 -1
  176. package/dist/src/validators/skill-validate.js +42 -15
  177. package/dist/src/validators/skill-validate.js.map +1 -1
  178. package/os/adr/adr.module.ts +2 -0
  179. package/os/audit/audit.module.ts +2 -0
  180. package/os/compass/compass.module.ts +50 -16
  181. package/os/compass/handlers/compass-audit-handler.ts +50 -9
  182. package/os/compass/handlers/compass-docs-validate.ts +359 -0
  183. package/os/compass/handlers/compass-inventory.ts +6 -3
  184. package/os/compass/handlers/summary-record.ts +118 -10
  185. package/os/compass/handlers/tests/compass-audit-record.test.ts +2 -1
  186. package/os/compass/handlers/tests/compass-audit-validate.test.ts +92 -3
  187. package/os/compass/handlers/tests/compass-docs-validate.test.ts +203 -0
  188. package/os/compass/handlers/tests/compass-ledger-scope.test.ts +2 -1
  189. package/os/compass/handlers/tests/compass-policy.test.ts +15 -18
  190. package/os/compass/handlers/tests/compass-v2-contract.test.ts +38 -0
  191. package/os/compass/handlers/tests/forge-yaml-fixture.ts +69 -0
  192. package/os/compass/handlers/tests/summary-record.test.ts +152 -0
  193. package/os/compass/policy.ts +8 -2
  194. package/os/core/core.module.ts +147 -75
  195. package/os/core/docs-archive.test.ts +136 -0
  196. package/os/exploration/exploration.module.ts +3 -0
  197. package/os/mission/handlers/archive.ts +1 -2
  198. package/os/naming/naming.module.ts +9 -2
  199. package/os/notes/notes.module.ts +17 -6
  200. package/os/plan/plan-0000-template.md +150 -0
  201. package/os/plan/plan.module.ts +2 -0
  202. package/os/plugin/plugin.module.ts +9 -2
  203. package/os/program/program.module.ts +19 -4
  204. package/os/queue/decision-ledger.test.ts +163 -0
  205. package/os/queue/handlers/queue-validate.ts +190 -8
  206. package/os/queue/manifest.ts +201 -7
  207. package/os/queue/queue-validate.test.ts +303 -0
  208. package/os/queue/queue.module.ts +32 -4
  209. package/os/queue/types.ts +56 -1
  210. package/os/rfc/handlers/implement-stamp.ts +35 -5
  211. package/os/rfc/handlers/validate.ts +1 -1
  212. package/os/rfc/rfc.module.ts +29 -3
  213. package/os/rfc/types.ts +17 -1
  214. package/os/rfc/verification-emit.test.ts +305 -0
  215. package/os/rfc/verification-evidence.ts +155 -24
  216. package/os/rfc/verification-refresh.test.ts +222 -1
  217. package/os/rfc/verification-refresh.ts +80 -38
  218. package/os/session/handlers/save.ts +41 -5
  219. package/os/session/session.module.ts +5 -0
  220. package/os/spec/live-spec-idempotency.pbt.test.ts +222 -0
  221. package/os/spec/live-spec-list-show-validate.test.ts +10 -6
  222. package/os/spec/live-spec-merge.test.ts +187 -7
  223. package/os/spec/live-spec-merge.ts +71 -155
  224. package/os/spec/live-spec-rebuild.test.ts +317 -0
  225. package/os/spec/live-spec-rebuild.ts +356 -0
  226. package/os/spec/live-spec-shared.ts +378 -0
  227. package/os/spec/live-spec-types.ts +21 -1
  228. package/os/spec/live-spec-validate.test.ts +317 -0
  229. package/os/spec/live-spec-validate.ts +106 -2
  230. package/os/spec/spec-materialize.test.ts +192 -0
  231. package/os/spec/spec-materialize.ts +48 -4
  232. package/os/spec/spec-schema.ts +49 -0
  233. package/os/spec/spec-status.ts +24 -0
  234. package/os/spec/spec-validate.test.ts +66 -0
  235. package/os/spec/spec-validate.ts +62 -8
  236. package/os/spec/spec.module.ts +85 -8
  237. package/os/werkstatt/handlers/werkstatt-operation-validate.ts +10 -4
  238. package/os/werkstatt/werkstatt.module.ts +13 -4
  239. package/os/workflow/workflow.module.ts +13 -5
  240. package/package.json +1 -1
  241. package/skills/_shared/fo-pipeline-conventions.md +126 -1
  242. package/skills/fo/fo-compass-annotate/SKILL.md +1 -1
  243. package/skills/fo/fo-doc-audit/SKILL.md +4 -4
  244. package/skills/fo/fo-explore/SKILL.md +2 -1
  245. package/skills/fo/fo-fix/SKILL.md +11 -3
  246. package/skills/fo/fo-handoff/SKILL.md +6 -8
  247. package/skills/fo/fo-idea-audit/SKILL.md +1 -1
  248. package/skills/fo/fo-idea-create-rfc/SKILL.md +3 -2
  249. package/skills/fo/fo-idea-enhance/SKILL.md +23 -4
  250. package/skills/fo/fo-idea-i-just-want-to-see-the-result/SKILL.md +86 -22
  251. package/skills/fo/fo-idea-implement/SKILL.md +57 -13
  252. package/skills/fo/fo-idea-plan/SKILL.md +28 -6
  253. package/skills/fo/fo-review/SKILL.md +69 -8
  254. package/skills/fo/fo-session-retro/SKILL.md +4 -3
  255. package/skills/fo/fo-session-save/SKILL.md +1 -1
  256. package/skills/fo/fo-step-commit/SKILL.md +2 -0
  257. package/skills/shared/grilling/SKILL.md +12 -0
  258. package/skills/shared/writing-great-skills/GLOSSARY.md +2 -0
  259. package/skills/shared/writing-great-skills/SKILL.md +2 -1
  260. package/src/cli-flags.ts +23 -5
  261. package/src/config/forge-config.ts +106 -57
  262. package/src/onboarding/create.ts +25 -9
  263. package/src/onboarding/doctor.ts +51 -2
  264. package/src/onboarding/init.ts +8 -3
  265. package/src/onboarding/upgrade.ts +36 -6
  266. package/src/pipeline-status.ts +32 -8
  267. package/src/tests/bindings-schema.test.ts +53 -1
  268. package/src/tests/cli-flags.test.ts +20 -0
  269. package/src/tests/cli-output.test.ts +13 -7
  270. package/src/tests/doctor-bindings.test.ts +7 -2
  271. package/src/tests/doctor-skills-unmanaged.test.ts +145 -0
  272. package/src/tests/fixtures/agents-generate-business-before.txt +7 -7
  273. package/src/tests/forge-config.test.ts +106 -2
  274. package/src/tests/implement-stamp.test.ts +38 -0
  275. package/src/tests/session-handlers.test.ts +33 -0
  276. package/src/tests/skill-validate.test.ts +180 -0
  277. package/src/tests/upgrade.test.ts +60 -0
  278. package/src/types.ts +13 -1
  279. package/src/utils/generated-marker.ts +28 -0
  280. package/src/validators/skill-validate.ts +43 -16
  281. package/skills/fo/fo-idea-implement/ADR-FLOW.md +0 -179
  282. package/skills/fo/fo-review/AXES.md +0 -70
@@ -2,16 +2,19 @@ import { describe, it, expect, beforeEach, afterEach } from "vitest";
2
2
  import { mkdtemp, mkdir, writeFile, readFile, rm } from "node:fs/promises";
3
3
  import { tmpdir } from "node:os";
4
4
  import { join } from "node:path";
5
+ import { execFileSync } from "node:child_process";
5
6
  import {
6
7
  runCompassSummaryRecord,
7
8
  parseChangeSummary,
8
9
  mergeHistoryIds,
9
10
  buildChangeSummaryBlock,
10
11
  stripConventionalPrefix,
12
+ stripGitTrailers,
11
13
  isValidGovernanceId,
12
14
  CHANGE_SUMMARY_WINDOW,
13
15
  } from "../summary-record.ts";
14
16
  import { resolveCompassPolicy } from "../../policy.ts";
17
+ import { policyWithIdPattern, cleanupForgeYamlFixtures } from "./forge-yaml-fixture.ts";
15
18
  import type { ForgeRuntimeContext } from "../../../../src/types.ts";
16
19
 
17
20
  // Generic policy — this path has no forge.yaml, so resolution falls back to
@@ -159,6 +162,51 @@ describe("compass.summary.record", () => {
159
162
  expect(missing.exitCode).toBe(1);
160
163
  });
161
164
 
165
+ it("skips auto-inject when the worktree diff already adds a same-ID item (id-in-diff)", async () => {
166
+ execFileSync("git", ["init"], { cwd: root });
167
+ execFileSync("git", ["config", "user.email", "t@t"], { cwd: root });
168
+ execFileSync("git", ["config", "user.name", "T"], { cwd: root });
169
+ await writeFile(join(root, "src", "a.ts"), TS_HEADER(["RFC-0001: existing item."]));
170
+ execFileSync("git", ["add", "-A"], { cwd: root });
171
+ execFileSync("git", ["commit", "-m", "baseline"], { cwd: root });
172
+ // The pending change carries a hand-authored descriptive item for the ID.
173
+ await writeFile(
174
+ join(root, "src", "a.ts"),
175
+ TS_HEADER(["RFC-0001: existing item.", "RFC-1095: descriptive hand-written entry"]),
176
+ );
177
+
178
+ const result = await runCompassSummaryRecord(
179
+ makeInput({ id: "RFC-1095", files: ["src/a.ts"], text: "generic subject line" }),
180
+ makeContext(root),
181
+ );
182
+
183
+ expect(result.data?.skipped).toEqual([{ file: "src/a.ts", reason: "id-in-diff" }]);
184
+ expect(result.data?.recorded).toEqual([]);
185
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
186
+ expect(source).not.toContain("generic subject line");
187
+ });
188
+
189
+ it("still records when the same-ID item already exists at HEAD (consecutive-commit stack)", async () => {
190
+ execFileSync("git", ["init"], { cwd: root });
191
+ execFileSync("git", ["config", "user.email", "t@t"], { cwd: root });
192
+ execFileSync("git", ["config", "user.name", "T"], { cwd: root });
193
+ await writeFile(
194
+ join(root, "src", "a.ts"),
195
+ TS_HEADER(["RFC-1095: step 1 — recorded by the previous commit"]),
196
+ );
197
+ execFileSync("git", ["add", "-A"], { cwd: root });
198
+ execFileSync("git", ["commit", "-m", "baseline"], { cwd: root });
199
+
200
+ const result = await runCompassSummaryRecord(
201
+ makeInput({ id: "RFC-1095", files: ["src/a.ts"], text: "step 2" }),
202
+ makeContext(root),
203
+ );
204
+
205
+ expect(result.data?.recorded).toEqual(["src/a.ts"]);
206
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
207
+ expect(source).toContain("<item>RFC-1095: step 2</item>");
208
+ });
209
+
162
210
  it("defaults item text to the bare ID when --text is absent", async () => {
163
211
  await writeFile(join(root, "src", "a.ts"), TS_HEADER([]));
164
212
  await runCompassSummaryRecord(
@@ -190,6 +238,65 @@ describe("compass.summary.record", () => {
190
238
  expect(source).toContain("<item>RFC-1095: record command</item>");
191
239
  expect(source).not.toContain("RFC-1095: RFC-1095");
192
240
  });
241
+
242
+ it("strips Generated-with/Co-Authored-By trailer blocks from the recorded item (RFC-1233 AC-1)", async () => {
243
+ await writeFile(join(root, "src", "a.ts"), TS_HEADER([]));
244
+ await runCompassSummaryRecord(
245
+ makeInput({
246
+ id: "RFC-1233",
247
+ files: ["src/a.ts"],
248
+ text: "trailer stripping\n\nGenerated with [Devin](https://devin.ai)\nCo-Authored-By: Devin <bot@users.noreply.github.com>",
249
+ }),
250
+ makeContext(root),
251
+ );
252
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
253
+ expect(source).toContain("<item>RFC-1233: trailer stripping</item>");
254
+ expect(source).not.toContain("Co-Authored-By");
255
+ expect(source).not.toContain("Generated with");
256
+ expect(source).not.toContain("devin.ai");
257
+ });
258
+
259
+ it("neutralizes a literal star-slash in --text so the item cannot terminate the block comment (RFC-1233 AC-2)", async () => {
260
+ await writeFile(join(root, "src", "a.ts"), TS_HEADER([]));
261
+ await runCompassSummaryRecord(
262
+ makeInput({
263
+ id: "RFC-1233",
264
+ files: ["src/a.ts"],
265
+ text: "glob src" + "/**/*.ts in comments",
266
+ }),
267
+ makeContext(root),
268
+ );
269
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
270
+ expect(source).toContain("RFC-1233: glob src");
271
+ expect(source.match(CS_BLOCK_RE)).not.toBeNull();
272
+ // The neutralized form keeps both characters readable but cannot close /*.
273
+ expect(source).toContain("glob src/**" + "∕*.ts in comments");
274
+ });
275
+
276
+ it("keeps a single-line subject identical — negative regression (RFC-1233 AC-3)", async () => {
277
+ await writeFile(join(root, "src", "a.ts"), TS_HEADER([]));
278
+ await runCompassSummaryRecord(
279
+ makeInput({ id: "RFC-1233", files: ["src/a.ts"], text: "plain subject line" }),
280
+ makeContext(root),
281
+ );
282
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
283
+ expect(source).toContain("<item>RFC-1233: plain subject line</item>");
284
+ });
285
+
286
+ it("preserves a Key: value-shaped line when it is not in the trailing block (RFC-1233 AC-4)", async () => {
287
+ await writeFile(join(root, "src", "a.ts"), TS_HEADER([]));
288
+ await runCompassSummaryRecord(
289
+ makeInput({
290
+ id: "RFC-1233",
291
+ files: ["src/a.ts"],
292
+ text: "fix the parser\n\nNote: this line is prose about the fix\nfinal summary line",
293
+ }),
294
+ makeContext(root),
295
+ );
296
+ const source = await readFile(join(root, "src", "a.ts"), "utf8");
297
+ expect(source).toContain("Note: this line is prose about the fix");
298
+ expect(source).toContain("final summary line");
299
+ });
193
300
  });
194
301
 
195
302
  describe("summary-record helpers", () => {
@@ -216,9 +323,54 @@ describe("summary-record helpers", () => {
216
323
  ]);
217
324
  });
218
325
 
326
+ afterEach(() => {
327
+ cleanupForgeYamlFixtures();
328
+ });
329
+
330
+ it("mergeHistoryIds sorts mission-format tokens under their namespace (RFC-1220)", () => {
331
+ const missionPolicy = policyWithIdPattern(
332
+ "\\b(?:[A-Z][A-Z0-9]*-)+\\d+\\b|\\b[a-z][a-z0-9-]*-m\\d{6}\\b",
333
+ );
334
+ expect(mergeHistoryIds(["acme-m000003"], ["acme-m000001", "RFC-0002"], missionPolicy)).toEqual([
335
+ "acme-m000001",
336
+ "acme-m000003",
337
+ "RFC-0002",
338
+ ]);
339
+ });
340
+
341
+ it("mergeHistoryIds appends unparseable admitted tokens last (RFC-1220)", () => {
342
+ const driftPolicy = policyWithIdPattern("\\b(?:[A-Z][A-Z0-9]*-)+\\d+\\b|\\b[A-Z]+-[A-Z]+\\b");
343
+ expect(mergeHistoryIds(["FOO-BAR"], ["RFC-0002", "RFC-0001"], driftPolicy)).toEqual([
344
+ "RFC-0001",
345
+ "RFC-0002",
346
+ "FOO-BAR",
347
+ ]);
348
+ });
349
+
219
350
  it("buildChangeSummaryBlock omits <history> when empty", () => {
220
351
  const block = buildChangeSummaryBlock(["RFC-1: a"], [], "x.ts");
221
352
  expect(block).not.toContain("<history>");
222
353
  expect(block).toContain("<item>RFC-1: a</item>");
223
354
  });
355
+
356
+ it("stripGitTrailers strips a Token:-shaped tail block (RFC-1233)", () => {
357
+ expect(
358
+ stripGitTrailers("subject\n\nbody line\nCo-Authored-By: Devin <bot@x>\nX-RFC: RFC-1233"),
359
+ ).toBe("subject\n\nbody line");
360
+ });
361
+
362
+ it("stripGitTrailers keeps a lone markdown-link tail (no strict trailer line)", () => {
363
+ const msg = "subject\n\nsee [the docs](https://example.com)";
364
+ expect(stripGitTrailers(msg)).toBe(msg);
365
+ });
366
+
367
+ it("stripGitTrailers on a trailer-only message returns empty", () => {
368
+ expect(stripGitTrailers("Co-Authored-By: Devin <bot@x>")).toBe("");
369
+ });
370
+
371
+ it("stripGitTrailers strips empty-value trailers (Token:) — interpret-trailers allows them", () => {
372
+ expect(stripGitTrailers("subject\n\nReviewed-by:\nSigned-off-by: Devin <bot@x>")).toBe(
373
+ "subject",
374
+ );
375
+ });
224
376
  });
@@ -12,6 +12,7 @@ are authored, how risky they are, and what counts as a governance ID
12
12
  </MODULE_CONTRACT>
13
13
  <CHANGE_SUMMARY>
14
14
  <item>RFC-1096: initial policy resolver — generic defaults + profile compass section + bindings.compass overrides.</item>
15
+ <item>RFC-1220: step 1 — widen governance-ID tail regex</item>
15
16
  </CHANGE_SUMMARY>
16
17
  */
17
18
 
@@ -212,9 +213,14 @@ function compilePattern(key: string, pattern: string, flags?: string): RegExp {
212
213
  }
213
214
  }
214
215
 
215
- /** Split a `NAMESPACE-NUMBER` governance ID on its last dash. */
216
+ /**
217
+ * Split a `NAMESPACE-NUMBER` governance ID on its last dash.
218
+ * Mission-format tails (`slug-mNNNNNN`) parse as `{ namespace: slug, numeric: N }`.
219
+ * The `m` stays outside the digit capture — `-(m?\d+)$` would capture `m000175`
220
+ * into the numeric group and produce `NaN` (RFC-1220).
221
+ */
216
222
  export function parseGovernanceIdParts(id: string): { namespace: string; numeric: number } | null {
217
- const match = id.match(/^(.*)-(\d+)$/);
223
+ const match = id.match(/^(.*)-m?(\d+)$/);
218
224
  if (!match) return null;
219
225
  return { namespace: match[1]!, numeric: Number(match[2]) };
220
226
  }