safeword 0.78.2 → 0.78.4

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 (224) hide show
  1. package/codex-plugin/.codex-plugin/plugin.json +1 -1
  2. package/codex-plugin/hooks.json +5 -5
  3. package/codex-plugin/skills/bdd/references/SCENARIOS.md +3 -0
  4. package/codex-plugin/skills/bdd/references/TDD.md +11 -5
  5. package/codex-plugin/skills/closeout/SKILL.md +24 -16
  6. package/codex-plugin/skills/finish-review/SKILL.md +4 -3
  7. package/codex-plugin/skills/lint/SKILL.md +1 -1
  8. package/codex-plugin/skills/review-spec/SKILL.md +5 -1
  9. package/codex-plugin/skills/self-review/SKILL.md +2 -2
  10. package/codex-plugin/skills/ticket-system/SKILL.md +3 -0
  11. package/dist/{architecture-N5ZC4CDU.js → architecture-TCSDEFKH.js} +9 -9
  12. package/dist/{architecture-document-UBA5UT4J.js → architecture-document-L2ADWVMV.js} +6 -6
  13. package/dist/{architecture-monorepo-E4JUYJGV.js → architecture-monorepo-NKOQZBEY.js} +4 -4
  14. package/dist/{boundary-HLJILY7R.js → boundary-QP2H7C46.js} +6 -6
  15. package/dist/{chunk-NOTBZCKG.js → chunk-2XR7J5WL.js} +93 -42
  16. package/dist/chunk-2XR7J5WL.js.map +1 -0
  17. package/dist/{chunk-4CZS4YJV.js → chunk-3OKZ3X4O.js} +3 -3
  18. package/dist/{chunk-GZ36UZJG.js → chunk-73TABQRT.js} +10 -10
  19. package/dist/{chunk-4CKCRZDO.js → chunk-7ULZND56.js} +2 -2
  20. package/dist/{chunk-34NCOTP5.js → chunk-7XELS325.js} +2 -2
  21. package/dist/{chunk-USPVNZ63.js → chunk-BZWO3BVD.js} +11 -7
  22. package/dist/chunk-BZWO3BVD.js.map +1 -0
  23. package/dist/{chunk-BQTC6YGN.js → chunk-D5ENZR6N.js} +2 -2
  24. package/dist/{chunk-SME5SU3O.js → chunk-DBXX5K74.js} +258 -48
  25. package/dist/chunk-DBXX5K74.js.map +1 -0
  26. package/dist/{chunk-V63TSN3C.js → chunk-FOYGZ4MK.js} +31 -10
  27. package/dist/chunk-FOYGZ4MK.js.map +1 -0
  28. package/dist/{chunk-ZRV7TOCX.js → chunk-G5AFQXXW.js} +2 -2
  29. package/dist/{chunk-AXAGJLMP.js → chunk-G757F3EU.js} +4 -4
  30. package/dist/{chunk-KXHVFCDT.js → chunk-GFDINP7M.js} +153 -27
  31. package/dist/chunk-GFDINP7M.js.map +1 -0
  32. package/dist/{chunk-S2T356DA.js → chunk-HF3DXZEA.js} +7 -10
  33. package/dist/chunk-HF3DXZEA.js.map +1 -0
  34. package/dist/{chunk-NSZGI7HK.js → chunk-HNCUIXDY.js} +9 -9
  35. package/dist/{chunk-NSZGI7HK.js.map → chunk-HNCUIXDY.js.map} +1 -1
  36. package/dist/{chunk-BSOUMHMQ.js → chunk-IPTM5VE7.js} +101 -1094
  37. package/dist/chunk-IPTM5VE7.js.map +1 -0
  38. package/dist/chunk-JBOLNV2L.js +21 -0
  39. package/dist/chunk-JBOLNV2L.js.map +1 -0
  40. package/dist/chunk-JSR3HXFT.js +1231 -0
  41. package/dist/chunk-JSR3HXFT.js.map +1 -0
  42. package/dist/{chunk-BAVDDAN3.js → chunk-KS2ESRQL.js} +9 -9
  43. package/dist/chunk-LFC6CMMX.js +136 -0
  44. package/dist/chunk-LFC6CMMX.js.map +1 -0
  45. package/dist/{chunk-QTG2EXFT.js → chunk-LUNHU6Z3.js} +2 -2
  46. package/dist/{chunk-QTG2EXFT.js.map → chunk-LUNHU6Z3.js.map} +1 -1
  47. package/dist/{chunk-WVDRXD67.js → chunk-MLBZFB5A.js} +1 -1
  48. package/dist/chunk-MLBZFB5A.js.map +1 -0
  49. package/dist/{chunk-KFVEPQ7X.js → chunk-MVFHTUQ3.js} +2 -2
  50. package/dist/{chunk-TJ627SKI.js → chunk-O3GZ77F7.js} +15 -1
  51. package/dist/chunk-O3GZ77F7.js.map +1 -0
  52. package/dist/{chunk-Q5KLE6ZF.js → chunk-OKPRQGFG.js} +2 -2
  53. package/dist/{chunk-QUDIOBHP.js → chunk-PD7ZXRHV.js} +139 -18
  54. package/dist/chunk-PD7ZXRHV.js.map +1 -0
  55. package/dist/chunk-QAHJSG53.js +30 -0
  56. package/dist/chunk-QAHJSG53.js.map +1 -0
  57. package/dist/{chunk-3SOJBMM6.js → chunk-R6BSRNU4.js} +6 -6
  58. package/dist/{chunk-3SOJBMM6.js.map → chunk-R6BSRNU4.js.map} +1 -1
  59. package/dist/{chunk-J7UDLLTK.js → chunk-RQ7RZYNB.js} +39 -25
  60. package/dist/chunk-RQ7RZYNB.js.map +1 -0
  61. package/dist/{chunk-664YNAMR.js → chunk-RTFPKJJV.js} +5 -5
  62. package/dist/{chunk-GKR44BCH.js → chunk-RVDXBHUG.js} +2 -2
  63. package/dist/chunk-THLEVFEX.js +22 -0
  64. package/dist/chunk-THLEVFEX.js.map +1 -0
  65. package/dist/{chunk-A7Z27COA.js → chunk-VFWAZLEF.js} +3 -3
  66. package/dist/{chunk-I4KBHRZW.js → chunk-VJUPD7JI.js} +7 -7
  67. package/dist/{chunk-3EJNDIAO.js → chunk-VZ5B2SIO.js} +2 -2
  68. package/dist/chunk-WAMQTZAH.js +19 -0
  69. package/dist/chunk-WAMQTZAH.js.map +1 -0
  70. package/dist/{chunk-FDHJ63FZ.js → chunk-WVA4Q6BX.js} +1 -1
  71. package/dist/{chunk-FDHJ63FZ.js.map → chunk-WVA4Q6BX.js.map} +1 -1
  72. package/dist/{chunk-AV5LTEME.js → chunk-YZ5JGDOV.js} +30 -134
  73. package/dist/chunk-YZ5JGDOV.js.map +1 -0
  74. package/dist/{cleanup-X556LNWM.js → cleanup-JNLZ7AXA.js} +9 -9
  75. package/dist/{cleanup-command-RV2Q7G72.js → cleanup-command-MFAYNYRW.js} +15 -15
  76. package/dist/cli.js +152 -109
  77. package/dist/cli.js.map +1 -1
  78. package/dist/{clients-HP23HRN2.js → clients-7AJBKEWF.js} +2 -2
  79. package/dist/codex-bootstrap-KFNUS63Y.js +252 -0
  80. package/dist/codex-bootstrap-KFNUS63Y.js.map +1 -0
  81. package/dist/{codex-hook-IPX3PDXX.js → codex-hook-TNMYVOR7.js} +57 -49
  82. package/dist/codex-hook-TNMYVOR7.js.map +1 -0
  83. package/dist/{codify-J5ZLJ3HK.js → codify-RBWBRXQO.js} +11 -8
  84. package/dist/codify-RBWBRXQO.js.map +1 -0
  85. package/dist/{commands-L4AINARC.js → commands-4UXHBZFD.js} +127 -71
  86. package/dist/commands-4UXHBZFD.js.map +1 -0
  87. package/dist/{config-LUSJAK6B.js → config-GS7BTZJD.js} +2 -2
  88. package/dist/{configured-paths-SPQ5XWOM.js → configured-paths-CREUDQF3.js} +4 -4
  89. package/dist/contract-42CIWIWV.js +8 -0
  90. package/dist/{coordinator-SA75UB3C.js → coordinator-WOPGWDXK.js} +231 -144
  91. package/dist/coordinator-WOPGWDXK.js.map +1 -0
  92. package/dist/corpus-CAFYEMBO.js +15 -0
  93. package/dist/{doctor-DSC36R4U.js → doctor-AZP5D7QP.js} +21 -21
  94. package/dist/{feature-directories-VOHVV26X.js → feature-directories-6TLM7Y4H.js} +6 -6
  95. package/dist/{finalization-7SMLMVLV.js → finalization-AQT3SOP7.js} +4 -4
  96. package/dist/{gh-cli-ZMO7D2KE.js → gh-cli-XCQT5ST7.js} +2 -2
  97. package/dist/{github-rest-KGKS4V2H.js → github-rest-CXFJ2NFF.js} +2 -2
  98. package/dist/index.js +2 -2
  99. package/dist/{job-CDADLJDF.js → job-4POTQJZK.js} +20 -21
  100. package/dist/job-4POTQJZK.js.map +1 -0
  101. package/dist/{learning-sync-6BTHM6ZC.js → learning-sync-QVXBOP6J.js} +4 -4
  102. package/dist/{legacy-global-guidance-2JL4Y5EB.js → legacy-global-guidance-CPGUUNJI.js} +5 -5
  103. package/dist/{lint-gherkin-COSHVS6Z.js → lint-gherkin-LZ45NG4A.js} +7 -7
  104. package/dist/{operations-XVRQSLJG.js → operations-ODOA5CDG.js} +18 -16
  105. package/dist/{output-3LB2OEHN.js → output-QTZCFLAY.js} +2 -2
  106. package/dist/{packet-5WT5M3OS.js → packet-5G6RT2EW.js} +2 -2
  107. package/dist/presets/typescript/index.js +2 -2
  108. package/dist/{profile-UMKQ5JVO.js → profile-QGLZNLRU.js} +7 -7
  109. package/dist/{prompt-GWYDFMLO.js → prompt-UCTSCXSS.js} +2 -2
  110. package/dist/remove-UQPEXXNP.js +23 -0
  111. package/dist/{retro-IFSVU5KS.js → retro-ELKR6GHF.js} +8 -8
  112. package/dist/{retro-draft-spool-4S3TCHWL.js → retro-draft-spool-M75BTT32.js} +2 -2
  113. package/dist/{retro-extract-OSBFAXLU.js → retro-extract-RA6THOC4.js} +2 -2
  114. package/dist/{review-pr-6S2352CK.js → review-pr-MN6QESAJ.js} +2 -2
  115. package/dist/{review-pr-publication-CGHCRRUI.js → review-pr-publication-6AVOGWR2.js} +2 -2
  116. package/dist/{run-5JESKXUR.js → run-JFDGRAH2.js} +4 -4
  117. package/dist/{self-report-VPHBPPSJ.js → self-report-5APRPB5P.js} +2 -2
  118. package/dist/status-ATFG6Q3K.js +21 -0
  119. package/dist/{status-EX4L3ELO.js → status-HIQSP3F5.js} +21 -21
  120. package/dist/{sync-config-O7J7IDGE.js → sync-config-XPAJKBRO.js} +5 -5
  121. package/dist/{sync-tracker-U2GYOFUO.js → sync-tracker-3E5BWX73.js} +6 -6
  122. package/dist/{test-execution-6LIPMBIH.js → test-execution-VDECX7TO.js} +8 -7
  123. package/dist/{test-execution-6LIPMBIH.js.map → test-execution-VDECX7TO.js.map} +1 -1
  124. package/dist/{test-plan-VASHZXJ7.js → test-plan-2L7A7UZV.js} +7 -6
  125. package/dist/{test-plan-VASHZXJ7.js.map → test-plan-2L7A7UZV.js.map} +1 -1
  126. package/dist/{ticket-new-3YXDIWPC.js → ticket-new-HZKNZ5GO.js} +11 -11
  127. package/dist/ticket-new-HZKNZ5GO.js.map +1 -0
  128. package/dist/{ticket-sync-LLUBXZ2R.js → ticket-sync-4QJD3KOL.js} +5 -5
  129. package/dist/{tracker-map-HR4MBYG5.js → tracker-map-CFMFIEER.js} +2 -2
  130. package/dist/{tracker-sync-YDICZN66.js → tracker-sync-MOPJE6M7.js} +2 -2
  131. package/package.json +1 -1
  132. package/templates/SAFEWORD.md +2 -2
  133. package/templates/commands/lint.md +1 -1
  134. package/templates/scripts/closeout-cleanup.ts +127 -31
  135. package/templates/skills/bdd/SCENARIOS.md +3 -0
  136. package/templates/skills/bdd/TDD.md +11 -5
  137. package/templates/skills/closeout/SKILL.md +25 -17
  138. package/templates/skills/finish-review/SKILL.md +4 -3
  139. package/templates/skills/lint/SKILL.md +1 -1
  140. package/templates/skills/review-spec/SKILL.md +5 -1
  141. package/templates/skills/self-review/SKILL.md +2 -2
  142. package/templates/skills/ticket-system/SKILL.md +3 -0
  143. package/dist/chunk-6S7CTKGC.js +0 -128
  144. package/dist/chunk-6S7CTKGC.js.map +0 -1
  145. package/dist/chunk-AV5LTEME.js.map +0 -1
  146. package/dist/chunk-BSOUMHMQ.js.map +0 -1
  147. package/dist/chunk-J7UDLLTK.js.map +0 -1
  148. package/dist/chunk-KXHVFCDT.js.map +0 -1
  149. package/dist/chunk-NOTBZCKG.js.map +0 -1
  150. package/dist/chunk-QUDIOBHP.js.map +0 -1
  151. package/dist/chunk-S2T356DA.js.map +0 -1
  152. package/dist/chunk-SME5SU3O.js.map +0 -1
  153. package/dist/chunk-TJ627SKI.js.map +0 -1
  154. package/dist/chunk-USPVNZ63.js.map +0 -1
  155. package/dist/chunk-V63TSN3C.js.map +0 -1
  156. package/dist/chunk-WRUXO3WA.js +0 -48
  157. package/dist/chunk-WRUXO3WA.js.map +0 -1
  158. package/dist/chunk-WVDRXD67.js.map +0 -1
  159. package/dist/codex-bootstrap-MGY2D6HU.js +0 -178
  160. package/dist/codex-bootstrap-MGY2D6HU.js.map +0 -1
  161. package/dist/codex-hook-IPX3PDXX.js.map +0 -1
  162. package/dist/codify-J5ZLJ3HK.js.map +0 -1
  163. package/dist/commands-L4AINARC.js.map +0 -1
  164. package/dist/contract-KEZY6YC3.js +0 -8
  165. package/dist/coordinator-SA75UB3C.js.map +0 -1
  166. package/dist/corpus-PPOBTF4J.js +0 -15
  167. package/dist/job-CDADLJDF.js.map +0 -1
  168. package/dist/remove-E6HGNHOU.js +0 -22
  169. package/dist/status-7VIGNTUI.js +0 -21
  170. package/dist/ticket-new-3YXDIWPC.js.map +0 -1
  171. /package/dist/{architecture-N5ZC4CDU.js.map → architecture-TCSDEFKH.js.map} +0 -0
  172. /package/dist/{architecture-document-UBA5UT4J.js.map → architecture-document-L2ADWVMV.js.map} +0 -0
  173. /package/dist/{architecture-monorepo-E4JUYJGV.js.map → architecture-monorepo-NKOQZBEY.js.map} +0 -0
  174. /package/dist/{boundary-HLJILY7R.js.map → boundary-QP2H7C46.js.map} +0 -0
  175. /package/dist/{chunk-4CZS4YJV.js.map → chunk-3OKZ3X4O.js.map} +0 -0
  176. /package/dist/{chunk-GZ36UZJG.js.map → chunk-73TABQRT.js.map} +0 -0
  177. /package/dist/{chunk-4CKCRZDO.js.map → chunk-7ULZND56.js.map} +0 -0
  178. /package/dist/{chunk-34NCOTP5.js.map → chunk-7XELS325.js.map} +0 -0
  179. /package/dist/{chunk-BQTC6YGN.js.map → chunk-D5ENZR6N.js.map} +0 -0
  180. /package/dist/{chunk-ZRV7TOCX.js.map → chunk-G5AFQXXW.js.map} +0 -0
  181. /package/dist/{chunk-AXAGJLMP.js.map → chunk-G757F3EU.js.map} +0 -0
  182. /package/dist/{chunk-BAVDDAN3.js.map → chunk-KS2ESRQL.js.map} +0 -0
  183. /package/dist/{chunk-KFVEPQ7X.js.map → chunk-MVFHTUQ3.js.map} +0 -0
  184. /package/dist/{chunk-Q5KLE6ZF.js.map → chunk-OKPRQGFG.js.map} +0 -0
  185. /package/dist/{chunk-664YNAMR.js.map → chunk-RTFPKJJV.js.map} +0 -0
  186. /package/dist/{chunk-GKR44BCH.js.map → chunk-RVDXBHUG.js.map} +0 -0
  187. /package/dist/{chunk-A7Z27COA.js.map → chunk-VFWAZLEF.js.map} +0 -0
  188. /package/dist/{chunk-I4KBHRZW.js.map → chunk-VJUPD7JI.js.map} +0 -0
  189. /package/dist/{chunk-3EJNDIAO.js.map → chunk-VZ5B2SIO.js.map} +0 -0
  190. /package/dist/{cleanup-X556LNWM.js.map → cleanup-JNLZ7AXA.js.map} +0 -0
  191. /package/dist/{cleanup-command-RV2Q7G72.js.map → cleanup-command-MFAYNYRW.js.map} +0 -0
  192. /package/dist/{clients-HP23HRN2.js.map → clients-7AJBKEWF.js.map} +0 -0
  193. /package/dist/{config-LUSJAK6B.js.map → config-GS7BTZJD.js.map} +0 -0
  194. /package/dist/{configured-paths-SPQ5XWOM.js.map → configured-paths-CREUDQF3.js.map} +0 -0
  195. /package/dist/{contract-KEZY6YC3.js.map → contract-42CIWIWV.js.map} +0 -0
  196. /package/dist/{corpus-PPOBTF4J.js.map → corpus-CAFYEMBO.js.map} +0 -0
  197. /package/dist/{doctor-DSC36R4U.js.map → doctor-AZP5D7QP.js.map} +0 -0
  198. /package/dist/{feature-directories-VOHVV26X.js.map → feature-directories-6TLM7Y4H.js.map} +0 -0
  199. /package/dist/{finalization-7SMLMVLV.js.map → finalization-AQT3SOP7.js.map} +0 -0
  200. /package/dist/{gh-cli-ZMO7D2KE.js.map → gh-cli-XCQT5ST7.js.map} +0 -0
  201. /package/dist/{github-rest-KGKS4V2H.js.map → github-rest-CXFJ2NFF.js.map} +0 -0
  202. /package/dist/{learning-sync-6BTHM6ZC.js.map → learning-sync-QVXBOP6J.js.map} +0 -0
  203. /package/dist/{legacy-global-guidance-2JL4Y5EB.js.map → legacy-global-guidance-CPGUUNJI.js.map} +0 -0
  204. /package/dist/{lint-gherkin-COSHVS6Z.js.map → lint-gherkin-LZ45NG4A.js.map} +0 -0
  205. /package/dist/{operations-XVRQSLJG.js.map → operations-ODOA5CDG.js.map} +0 -0
  206. /package/dist/{output-3LB2OEHN.js.map → output-QTZCFLAY.js.map} +0 -0
  207. /package/dist/{packet-5WT5M3OS.js.map → packet-5G6RT2EW.js.map} +0 -0
  208. /package/dist/{profile-UMKQ5JVO.js.map → profile-QGLZNLRU.js.map} +0 -0
  209. /package/dist/{prompt-GWYDFMLO.js.map → prompt-UCTSCXSS.js.map} +0 -0
  210. /package/dist/{remove-E6HGNHOU.js.map → remove-UQPEXXNP.js.map} +0 -0
  211. /package/dist/{retro-IFSVU5KS.js.map → retro-ELKR6GHF.js.map} +0 -0
  212. /package/dist/{retro-draft-spool-4S3TCHWL.js.map → retro-draft-spool-M75BTT32.js.map} +0 -0
  213. /package/dist/{retro-extract-OSBFAXLU.js.map → retro-extract-RA6THOC4.js.map} +0 -0
  214. /package/dist/{review-pr-6S2352CK.js.map → review-pr-MN6QESAJ.js.map} +0 -0
  215. /package/dist/{review-pr-publication-CGHCRRUI.js.map → review-pr-publication-6AVOGWR2.js.map} +0 -0
  216. /package/dist/{run-5JESKXUR.js.map → run-JFDGRAH2.js.map} +0 -0
  217. /package/dist/{self-report-VPHBPPSJ.js.map → self-report-5APRPB5P.js.map} +0 -0
  218. /package/dist/{status-7VIGNTUI.js.map → status-ATFG6Q3K.js.map} +0 -0
  219. /package/dist/{status-EX4L3ELO.js.map → status-HIQSP3F5.js.map} +0 -0
  220. /package/dist/{sync-config-O7J7IDGE.js.map → sync-config-XPAJKBRO.js.map} +0 -0
  221. /package/dist/{sync-tracker-U2GYOFUO.js.map → sync-tracker-3E5BWX73.js.map} +0 -0
  222. /package/dist/{ticket-sync-LLUBXZ2R.js.map → ticket-sync-4QJD3KOL.js.map} +0 -0
  223. /package/dist/{tracker-map-HR4MBYG5.js.map → tracker-map-CFMFIEER.js.map} +0 -0
  224. /package/dist/{tracker-sync-YDICZN66.js.map → tracker-sync-MOPJE6M7.js.map} +0 -0
@@ -1,12 +1,17 @@
1
1
  // src/cli-protocol/review-presentation.ts
2
2
  var REVIEW_AGENTS = /* @__PURE__ */ new Set(["claude", "codex"]);
3
3
  var REVIEW_AUTHORS = /* @__PURE__ */ new Set(["claude", "codex", "cursor"]);
4
- var REPLACED_REVIEW_FINDINGS = /* @__PURE__ */ new Set(["REVIEW_INDEPENDENCE", "REVIEW_INDEPENDENCE_DEGRADED"]);
4
+ var REPLACED_REVIEW_FINDINGS = /* @__PURE__ */ new Set([
5
+ "REVIEW_INDEPENDENCE",
6
+ "REVIEW_NOT_REQUESTED",
7
+ "REVIEW_STALE"
8
+ ]);
5
9
  var RETRYABLE_REVIEW_FAILURES = /* @__PURE__ */ new Set([
6
10
  "timed_out",
7
11
  "process_failed",
8
12
  "invalid_output",
9
- "source_changed"
13
+ "REVIEWER_PROVENANCE_MISSING",
14
+ "REVIEWER_PROVENANCE_CONTRADICTORY"
10
15
  ]);
11
16
  function isRecord(value) {
12
17
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -17,7 +22,8 @@ function reviewCoverage(data) {
17
22
  if (typeof author !== "string" || !REVIEW_AUTHORS.has(author) || typeof reviewer !== "string") {
18
23
  return "incomplete";
19
24
  }
20
- if (data.independence === "degraded" && reviewer === author) return "standard";
25
+ if (data.independence === "degraded" && REVIEW_AGENTS.has(reviewer) && reviewer === author)
26
+ return "standard";
21
27
  if (data.independence === "cross-agent" && REVIEW_AGENTS.has(reviewer) && reviewer !== author) {
22
28
  return "independent";
23
29
  }
@@ -26,7 +32,7 @@ function reviewCoverage(data) {
26
32
  function reviewVerdict(data) {
27
33
  const output = data.reviewer_output;
28
34
  if (!isRecord(output)) return void 0;
29
- if (typeof output.reviewer_agent !== "string" || !REVIEW_AUTHORS.has(output.reviewer_agent) || output.reviewer_agent !== data.actual_reviewer) {
35
+ if (typeof output.reviewer_agent !== "string" || !REVIEW_AGENTS.has(output.reviewer_agent) || output.reviewer_agent !== data.actual_reviewer) {
30
36
  return void 0;
31
37
  }
32
38
  return output.verdict === "approve" || output.verdict === "request_changes" ? output.verdict : void 0;
@@ -58,16 +64,27 @@ function blockedReviewCoverageLine(data, coverage, verdict) {
58
64
  }
59
65
  return incompleteCoverageLine(data);
60
66
  }
67
+ function specialReviewCoverageLine(status, state) {
68
+ if (status === "existing_route" && state === "healthy") return "Review not requested.";
69
+ if (status === "pending" && state === "action_required") {
70
+ return "Review running in the background.";
71
+ }
72
+ if (status === "stale" && state === "action_required") {
73
+ return "Review stale \u2014 sources changed during the check.";
74
+ }
75
+ return void 0;
76
+ }
61
77
  function reviewCoverageLine(data, state) {
62
- const coverage = reviewCoverage(data);
63
78
  const status = data.status;
79
+ const specialLine = specialReviewCoverageLine(status, state);
80
+ if (specialLine !== void 0) return specialLine;
64
81
  const verdict = reviewVerdict(data);
65
82
  if (!reviewStateMatchesStatus(state, status)) return incompleteCoverageLine(data);
66
83
  if (!reviewPolicyMatchesStatus(data)) return "Review incomplete.";
67
84
  if (!reviewVerdictMatchesStatus(status, verdict)) return incompleteCoverageLine(data);
68
- if (status === "blocked" && verdict !== void 0) {
69
- return blockedReviewCoverageLine(data, coverage, verdict);
70
- }
85
+ if (verdict === void 0) return incompleteCoverageLine(data);
86
+ const coverage = reviewCoverage(data);
87
+ if (status === "blocked") return blockedReviewCoverageLine(data, coverage, verdict);
71
88
  if (coverage === "incomplete") return "Review incomplete.";
72
89
  if (verdict === "request_changes") return `Review changes requested \u2014 ${coverage} coverage.`;
73
90
  return `Review complete \u2014 ${coverage} coverage.`;
@@ -90,6 +107,9 @@ function suggestionForFailure(failure, label) {
90
107
  if (failure === "not_installed") {
91
108
  return `To add independent coverage, install or update ${label}, then retry review.`;
92
109
  }
110
+ if (failure === "untrusted_install") {
111
+ return `To add independent coverage, move ${label} to a trusted non-writable-by-group directory, then retry review.`;
112
+ }
93
113
  if (failure === "unsupported") {
94
114
  return `To add independent coverage, update ${label}, then retry review.`;
95
115
  }
@@ -106,9 +126,10 @@ function suggestionForFailure(failure, label) {
106
126
  }
107
127
  function reviewResultLines(result, options) {
108
128
  if (!isRecord(result.data) || result.data.command !== "review run") return void 0;
129
+ if (result.state === "failed" && result.errors.length > 0) return void 0;
109
130
  const messages = result.findings.filter((finding) => !REPLACED_REVIEW_FINDINGS.has(finding.code)).map((finding) => finding.message);
110
131
  messages.push(...result.errors.map((error) => error.message));
111
- const lines = [reviewCoverageLine(result.data, result.state), ...new Set(messages)];
132
+ const lines = [reviewCoverageLine(result.data, result.state), ...messages];
112
133
  if (options.verbose === true) {
113
134
  const suggestion = reviewUpgradeSuggestion(result.data, result.state);
114
135
  if (suggestion !== void 0) lines.push(suggestion);
@@ -411,4 +432,4 @@ export {
411
432
  renderJsonResult,
412
433
  renderHumanStreams
413
434
  };
414
- //# sourceMappingURL=chunk-V63TSN3C.js.map
435
+ //# sourceMappingURL=chunk-FOYGZ4MK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli-protocol/review-presentation.ts","../src/cli-protocol/result.ts"],"sourcesContent":["import type { CliResult } from './result.js';\n\ntype ReviewCoverage = 'standard' | 'independent' | 'incomplete';\ntype ReviewVerdict = 'approve' | 'request_changes';\n\nconst REVIEW_AGENTS = new Set(['claude', 'codex']);\nconst REVIEW_AUTHORS = new Set(['claude', 'codex', 'cursor']);\nconst REPLACED_REVIEW_FINDINGS = new Set([\n 'REVIEW_INDEPENDENCE',\n 'REVIEW_NOT_REQUESTED',\n 'REVIEW_STALE',\n]);\nconst RETRYABLE_REVIEW_FAILURES = new Set([\n 'timed_out',\n 'process_failed',\n 'invalid_output',\n 'REVIEWER_PROVENANCE_MISSING',\n 'REVIEWER_PROVENANCE_CONTRADICTORY',\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction reviewCoverage(data: Record<string, unknown>): ReviewCoverage {\n const author = data.author_agent;\n const reviewer = data.actual_reviewer;\n if (typeof author !== 'string' || !REVIEW_AUTHORS.has(author) || typeof reviewer !== 'string') {\n return 'incomplete';\n }\n if (data.independence === 'degraded' && REVIEW_AGENTS.has(reviewer) && reviewer === author)\n return 'standard';\n if (data.independence === 'cross-agent' && REVIEW_AGENTS.has(reviewer) && reviewer !== author) {\n return 'independent';\n }\n return 'incomplete';\n}\n\nfunction reviewVerdict(data: Record<string, unknown>): ReviewVerdict | undefined {\n const output = data.reviewer_output;\n if (!isRecord(output)) return undefined;\n if (\n typeof output.reviewer_agent !== 'string' ||\n !REVIEW_AGENTS.has(output.reviewer_agent) ||\n output.reviewer_agent !== data.actual_reviewer\n ) {\n return undefined;\n }\n return output.verdict === 'approve' || output.verdict === 'request_changes'\n ? output.verdict\n : undefined;\n}\n\nfunction reviewVerdictMatchesStatus(status: unknown, verdict: ReviewVerdict | undefined): boolean {\n if (status === 'approved') return verdict === 'approve';\n if (status === 'changes_requested') return verdict === 'request_changes';\n return status === 'blocked' && verdict !== undefined;\n}\n\nfunction reviewPolicyMatchesStatus(data: Record<string, unknown>): boolean {\n if (data.status === 'blocked') {\n return data.review_policy === 'prefer' || data.review_policy === 'require';\n }\n return (\n (data.status === 'approved' || data.status === 'changes_requested') &&\n data.review_policy === undefined\n );\n}\n\nfunction reviewStateMatchesStatus(state: CliResult['state'], status: unknown): boolean {\n if (status === 'approved') return state === 'healthy';\n return (status === 'changes_requested' || status === 'blocked') && state === 'action_required';\n}\n\nfunction isConsistentReviewResult(\n data: Record<string, unknown>,\n state: CliResult['state'],\n verdict: ReviewVerdict | undefined,\n): boolean {\n return (\n reviewStateMatchesStatus(state, data.status) &&\n reviewPolicyMatchesStatus(data) &&\n reviewVerdictMatchesStatus(data.status, verdict)\n );\n}\n\nfunction incompleteCoverageLine(data: Record<string, unknown>): string {\n return data.status === 'blocked' && data.review_policy === 'require'\n ? 'Review incomplete — required independent coverage is unsatisfied.'\n : 'Review incomplete.';\n}\n\nfunction blockedReviewCoverageLine(\n data: Record<string, unknown>,\n coverage: ReviewCoverage,\n verdict: ReviewVerdict,\n): string {\n if (coverage === 'standard' && data.review_policy === 'require') {\n return verdict === 'request_changes'\n ? 'Review blocked — changes requested with standard coverage; required independent coverage is unsatisfied.'\n : 'Review blocked — standard coverage achieved; required independent coverage is unsatisfied.';\n }\n return incompleteCoverageLine(data);\n}\n\nfunction specialReviewCoverageLine(status: unknown, state: CliResult['state']): string | undefined {\n if (status === 'existing_route' && state === 'healthy') return 'Review not requested.';\n if (status === 'pending' && state === 'action_required') {\n return 'Review running in the background.';\n }\n if (status === 'stale' && state === 'action_required') {\n return 'Review stale — sources changed during the check.';\n }\n return undefined;\n}\n\nfunction reviewCoverageLine(data: Record<string, unknown>, state: CliResult['state']): string {\n const status = data.status;\n const specialLine = specialReviewCoverageLine(status, state);\n if (specialLine !== undefined) return specialLine;\n\n const verdict = reviewVerdict(data);\n if (!reviewStateMatchesStatus(state, status)) return incompleteCoverageLine(data);\n if (!reviewPolicyMatchesStatus(data)) return 'Review incomplete.';\n if (!reviewVerdictMatchesStatus(status, verdict)) return incompleteCoverageLine(data);\n // Preserve an explicit narrowing guard for blockedReviewCoverageLine below.\n if (verdict === undefined) return incompleteCoverageLine(data);\n const coverage = reviewCoverage(data);\n if (status === 'blocked') return blockedReviewCoverageLine(data, coverage, verdict);\n if (coverage === 'incomplete') return 'Review incomplete.';\n if (verdict === 'request_changes') return `Review changes requested — ${coverage} coverage.`;\n return `Review complete — ${coverage} coverage.`;\n}\n\nfunction isCompletedStandardReview(\n data: Record<string, unknown>,\n state: CliResult['state'],\n): boolean {\n const verdict = reviewVerdict(data);\n return (\n data.status === 'approved' &&\n isConsistentReviewResult(data, state, verdict) &&\n reviewCoverage(data) === 'standard'\n );\n}\n\nfunction reviewUpgradeSuggestion(\n data: Record<string, unknown>,\n state: CliResult['state'],\n): string | undefined {\n if (!isCompletedStandardReview(data, state)) return undefined;\n const author = data.author_agent;\n const reviewer = data.assigned_reviewer;\n if (\n typeof author !== 'string' ||\n typeof reviewer !== 'string' ||\n !REVIEW_AGENTS.has(reviewer) ||\n reviewer === author\n ) {\n return undefined;\n }\n const label = `${reviewer.charAt(0).toUpperCase()}${reviewer.slice(1)}`;\n return suggestionForFailure(data.preferred_failure, label);\n}\n\nfunction suggestionForFailure(failure: unknown, label: string): string | undefined {\n if (failure === 'not_installed') {\n return `To add independent coverage, install or update ${label}, then retry review.`;\n }\n if (failure === 'untrusted_install') {\n return `To add independent coverage, move ${label} to a trusted non-writable-by-group directory, then retry review.`;\n }\n if (failure === 'unsupported') {\n return `To add independent coverage, update ${label}, then retry review.`;\n }\n if (failure === 'probe_timed_out' || failure === 'launch_failed') {\n return `To add independent coverage, run ${label} --help to diagnose it, then retry review.`;\n }\n if (failure === 'not_authenticated') {\n return `To add independent coverage, sign in to ${label}, then retry review.`;\n }\n if (RETRYABLE_REVIEW_FAILURES.has(String(failure))) {\n return `To add independent coverage, retry ${label} review.`;\n }\n return undefined;\n}\n\nexport function reviewResultLines(\n result: CliResult,\n options: { verbose?: boolean },\n): string[] | undefined {\n if (!isRecord(result.data) || result.data.command !== 'review run') return undefined;\n if (result.state === 'failed' && result.errors.length > 0) return undefined;\n const messages = result.findings\n .filter(finding => !REPLACED_REVIEW_FINDINGS.has(finding.code))\n .map(finding => finding.message);\n messages.push(...result.errors.map(error => error.message));\n const lines = [reviewCoverageLine(result.data, result.state), ...messages];\n if (options.verbose === true) {\n const suggestion = reviewUpgradeSuggestion(result.data, result.state);\n if (suggestion !== undefined) lines.push(suggestion);\n }\n return lines;\n}\n","import { reviewResultLines } from './review-presentation.js';\n\ntype ResultState = 'healthy' | 'changed' | 'action_required' | 'failed';\n\nexport interface Finding {\n readonly code: string;\n readonly message: string;\n readonly severity: 'info' | 'warning' | 'error';\n readonly detail?: string;\n readonly metadata?: Readonly<Record<string, unknown>>;\n}\n\ninterface ResultError {\n readonly code: string;\n readonly message: string;\n readonly retryable: boolean;\n readonly detail?: string;\n}\n\ninterface CommandNextAction {\n readonly command: string;\n readonly mutates: boolean;\n readonly requiresHuman: boolean;\n}\n\ninterface HumanNextAction {\n readonly kind: 'human';\n readonly instruction: string;\n readonly mutates: false;\n readonly requiresHuman: true;\n}\n\nexport type NextAction = CommandNextAction | HumanNextAction;\n\ninterface RecoveryAction {\n readonly command: string;\n readonly description: string;\n readonly requiresHuman: boolean;\n}\n\nexport interface Effect {\n readonly kind: string;\n readonly target: string;\n readonly operation?: string;\n}\n\nexport interface Effects {\n readonly files: readonly Effect[];\n readonly packages: readonly Effect[];\n readonly configuration: readonly Effect[];\n readonly network: readonly Effect[];\n readonly destructive: readonly Effect[];\n}\n\nexport interface CliResult {\n readonly schemaVersion: 1;\n readonly ok: boolean;\n readonly state: ResultState;\n readonly changed: boolean;\n readonly findings: readonly Finding[];\n readonly effects: Effects;\n readonly errors: readonly ResultError[];\n readonly recovery: readonly RecoveryAction[];\n readonly nextActions: readonly NextAction[];\n /** Process status for commands that must preserve a delegated program's exit. */\n readonly exitCode?: number;\n readonly presentation?: {\n readonly kind: 'raw';\n readonly body: string;\n };\n readonly data?: unknown;\n}\n\ninterface ResultInput {\n readonly state: ResultState;\n readonly changed?: boolean;\n readonly findings?: readonly Finding[];\n readonly effects?: Partial<Effects>;\n readonly errors?: readonly ResultError[];\n readonly recovery?: readonly RecoveryAction[];\n readonly nextActions?: readonly NextAction[];\n readonly exitCode?: number;\n readonly presentation?: NonNullable<CliResult['presentation']>;\n readonly data?: unknown;\n}\n\nconst EMPTY_EFFECTS: Effects = {\n files: [],\n packages: [],\n configuration: [],\n network: [],\n destructive: [],\n};\n\nexport function combineEffects(groups: readonly Partial<Effects>[]): Effects {\n return {\n files: groups.flatMap(effects => effects.files ?? []),\n packages: groups.flatMap(effects => effects.packages ?? []),\n configuration: groups.flatMap(effects => effects.configuration ?? []),\n network: groups.flatMap(effects => effects.network ?? []),\n destructive: groups.flatMap(effects => effects.destructive ?? []),\n };\n}\n\n/** Aggregate state precedence shared by commands that combine several results. */\nexport function combinedResultState(results: readonly CliResult[]): CliResult['state'] {\n if (results.some(result => result.state === 'failed')) return 'failed';\n if (results.some(result => result.state === 'action_required')) return 'action_required';\n if (results.some(result => result.state === 'changed')) return 'changed';\n return 'healthy';\n}\n\nexport function createResult(input: ResultInput): CliResult {\n return {\n schemaVersion: 1,\n ok: input.state !== 'failed',\n state: input.state,\n changed: input.changed ?? input.state === 'changed',\n findings: input.findings ?? [],\n effects: { ...EMPTY_EFFECTS, ...input.effects },\n errors: input.errors ?? [],\n recovery: input.recovery ?? [],\n nextActions: input.nextActions ?? [],\n ...(input.exitCode !== undefined && { exitCode: input.exitCode }),\n ...(input.presentation !== undefined && { presentation: input.presentation }),\n ...(input.data !== undefined && { data: input.data }),\n };\n}\n\nexport function withDeprecation(\n result: CliResult,\n legacy: string,\n replacement: string,\n compatibility: {\n readonly introducedIn: string;\n readonly retention: 'indefinite';\n readonly redundantOptions?: readonly {\n readonly key: string;\n readonly flag: string;\n readonly replacement: string;\n }[];\n },\n options: Readonly<Record<string, unknown>> = {},\n): CliResult {\n const redundantOptionFindings: Finding[] = (compatibility.redundantOptions ?? [])\n .filter(option => options[option.key] === true)\n .map(option => ({\n code: 'CLI_OPTION_REDUNDANT',\n message: `\\`${option.flag}\\` is accepted for compatibility but has no effect; use \\`${option.replacement}\\`.`,\n severity: 'warning',\n metadata: {\n option: option.flag,\n replacement: option.replacement,\n retention: compatibility.retention,\n },\n }));\n return {\n ...result,\n findings: [\n ...result.findings,\n {\n code: 'CLI_ALIAS_DEPRECATED',\n message: `\\`${legacy}\\` is deprecated; use \\`${replacement}\\`.`,\n severity: 'warning',\n metadata: {\n replacement,\n introduced_in: compatibility.introducedIn,\n retention: compatibility.retention,\n },\n },\n ...redundantOptionFindings,\n ],\n };\n}\n\nexport function exitStatusFor(result: CliResult): number {\n if (result.exitCode !== undefined) return result.exitCode;\n if (result.state === 'failed') return 1;\n if (result.state === 'action_required') return 2;\n return 0;\n}\n\nfunction toWireResult(result: CliResult): Record<string, unknown> {\n return {\n schema_version: result.schemaVersion,\n ok: result.ok,\n state: result.state,\n changed: result.changed,\n findings: result.findings.map(({ code, message, severity, detail, metadata }) => ({\n code,\n message,\n severity,\n ...(detail !== undefined && { detail }),\n ...(metadata !== undefined && { metadata }),\n })),\n effects: result.effects,\n errors: result.errors.map(({ code, message, retryable, detail }) => ({\n code,\n message,\n retryable,\n ...(detail !== undefined && { detail }),\n })),\n recovery: result.recovery.map(({ command, description, requiresHuman }) => ({\n command,\n description,\n requires_human: requiresHuman,\n })),\n next_actions: result.nextActions.map(action =>\n 'command' in action\n ? {\n command: action.command,\n mutates: action.mutates,\n requires_human: action.requiresHuman,\n }\n : {\n kind: action.kind,\n instruction: action.instruction,\n mutates: action.mutates,\n requires_human: action.requiresHuman,\n },\n ),\n ...(result.data !== undefined && { data: result.data }),\n };\n}\n\nexport function renderJsonResult(result: CliResult): string {\n return JSON.stringify(toWireResult(result));\n}\n\nconst VERDICTS: Readonly<Record<ResultState, string>> = {\n healthy: 'Healthy',\n changed: 'Complete',\n action_required: 'Needs attention',\n failed: 'Failed',\n};\n\nfunction uniqueMessages(result: CliResult): string[] {\n const messages = result.findings.map(finding => finding.message);\n messages.push(...result.errors.map(error => error.message));\n return [...new Set(messages)];\n}\n\nfunction suppressHumanOutput(result: CliResult, options: { quiet?: boolean }): boolean {\n return options.quiet === true && result.state === 'healthy';\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction effectLines(category: string, effects: unknown): string[] {\n if (!Array.isArray(effects)) return [];\n return effects.flatMap(effect =>\n isRecord(effect) && typeof effect.kind === 'string' && typeof effect.target === 'string'\n ? [`${category}: ${effect.kind} ${effect.target}`]\n : [],\n );\n}\n\nfunction nextActionLabel(action: NextAction): string {\n return 'command' in action ? action.command : action.instruction;\n}\n\nfunction plannedEffectLines(data: unknown): string[] {\n if (!isRecord(data)) return [];\n const plan = data.plan;\n if (!isRecord(plan)) return [];\n const effects = plan.effects;\n if (!isRecord(effects)) return [];\n const categories = ['files', 'packages', 'configuration', 'network', 'destructive'];\n const lines = categories.flatMap(category => effectLines(category, effects[category]));\n return lines.length === 0 ? [] : ['Planned effects:', ...lines];\n}\n\nconst SURFACE_LABELS: Readonly<Record<string, string>> = {\n project: 'Project',\n claude: 'Claude',\n codex: 'Codex',\n cursor: 'Cursor',\n};\n\nconst SURFACE_OUTCOMES: Readonly<Record<string, string>> = {\n healthy: 'ready',\n changed: 'updated',\n action_required: 'needs attention',\n failed: 'failed',\n};\n\n/** Labelled surfaces of a `command`-tagged result payload, or [] when it is not that command. */\nfunction labelledSurfaces(\n data: unknown,\n command: string,\n): { readonly label: string; readonly surface: Record<string, unknown> }[] {\n if (!isRecord(data) || data.command !== command || !Array.isArray(data.surfaces)) return [];\n return data.surfaces.flatMap(surface => {\n if (!isRecord(surface) || typeof surface.name !== 'string') return [];\n const label = SURFACE_LABELS[surface.name];\n return label === undefined ? [] : [{ label, surface }];\n });\n}\n\nfunction installSurfaceLines(data: unknown): string[] {\n return labelledSurfaces(data, 'install').flatMap(({ label, surface }) => {\n if (surface.selected === false) return [`${label}: not selected`];\n const outcome = typeof surface.state === 'string' ? SURFACE_OUTCOMES[surface.state] : undefined;\n return outcome === undefined ? [] : [`${label}: ${outcome}`];\n });\n}\n\nfunction installActivationLines(data: unknown): string[] {\n return labelledSurfaces(data, 'install').flatMap(({ label, surface }) => {\n if (!Array.isArray(surface.activation_actions)) return [];\n return surface.activation_actions.flatMap(action =>\n typeof action === 'string' ? [`${label} activation: ${action}`] : [],\n );\n });\n}\n\nfunction doctorDiagnosticCauses(data: unknown): ReadonlySet<string> {\n if (!isRecord(data) || data.command !== 'doctor' || !Array.isArray(data.diagnostics)) {\n return new Set();\n }\n return new Set(\n data.diagnostics.flatMap(diagnostic =>\n isRecord(diagnostic) && typeof diagnostic.cause === 'string' ? [diagnostic.cause] : [],\n ),\n );\n}\n\nfunction doctorDiagnosticLines(data: unknown): string[] {\n if (!isRecord(data) || data.command !== 'doctor' || !Array.isArray(data.coverage)) return [];\n\n const coverage = data.coverage.flatMap(item => {\n if (!isRecord(item) || typeof item.surface !== 'string') return [];\n const label = SURFACE_LABELS[item.surface] ?? item.surface;\n const outcome = typeof item.state === 'string' ? SURFACE_OUTCOMES[item.state] : undefined;\n const evidence = isRecord(item.evidence)\n ? Object.entries(item.evidence)\n .filter((entry): entry is [string, string | number | boolean] =>\n ['string', 'number', 'boolean'].includes(typeof entry[1]),\n )\n .map(([key, value]) => `${key.replaceAll('_', ' ')}=${String(value)}`)\n : [];\n const evidenceSuffix = evidence.length === 0 ? '' : ` (${evidence.join(', ')})`;\n return [`- ${label}: ${outcome ?? 'unknown'}${evidenceSuffix}`];\n });\n const diagnostics = Array.isArray(data.diagnostics)\n ? data.diagnostics.flatMap(item => {\n if (\n !isRecord(item) ||\n typeof item.surface !== 'string' ||\n typeof item.code !== 'string' ||\n typeof item.cause !== 'string'\n ) {\n return [];\n }\n const label = SURFACE_LABELS[item.surface] ?? item.surface;\n return [`- ${label} [${item.code}]: ${item.cause}`];\n })\n : [];\n\n return [\n ...(coverage.length === 0 ? [] : ['Diagnostic coverage:', ...coverage]),\n ...(diagnostics.length === 0 ? [] : ['Causes:', ...diagnostics]),\n ];\n}\n\nconst EFFECT_LABELS: Readonly<Record<string, string>> = {\n create: 'Created',\n update: 'Updated',\n delete: 'Deleted',\n install: 'Installed',\n uninstall: 'Uninstalled',\n remove: 'Removed',\n write: 'Written',\n};\n\nfunction completedEffectLines(result: CliResult): string[] {\n const visibleCategories = [\n result.effects.files,\n result.effects.packages,\n result.effects.configuration,\n result.effects.destructive,\n ];\n const lines = visibleCategories.flatMap(effects =>\n effects.map(effect => `${EFFECT_LABELS[effect.kind] ?? 'Changed'}: ${effect.target}`),\n );\n lines.push(\n ...result.effects.network.map(\n effect => `Network: ${effect.operation ?? effect.kind} ${effect.target}`,\n ),\n );\n return lines;\n}\n\nexport function renderHumanResult(\n result: CliResult,\n options: { quiet?: boolean; verbose?: boolean } = {},\n): string {\n const rendered = renderHumanStreams(result, options);\n return rendered.stdout || rendered.stderr;\n}\n\nexport interface HumanResultStreams {\n readonly stdout: string;\n readonly stderr: string;\n}\n\nfunction resultBodyLines(result: CliResult, options: { verbose?: boolean }): string[] {\n const reviewLines = reviewResultLines(result, options);\n if (reviewLines !== undefined) return reviewLines;\n const diagnosticCauses = doctorDiagnosticCauses(result.data);\n const messages = uniqueMessages(result).filter(message => !diagnosticCauses.has(message));\n const lines = [\n VERDICTS[result.state],\n `Changed: ${result.changed ? 'yes' : 'no'}`,\n ...installSurfaceLines(result.data),\n ...installActivationLines(result.data),\n ...doctorDiagnosticLines(result.data),\n ...messages,\n ...plannedEffectLines(result.data),\n ];\n\n if (options.verbose === true) {\n const details = [\n ...result.findings.map(finding => finding.detail),\n ...result.errors.map(error => error.detail),\n ].filter((detail): detail is string => detail !== undefined);\n lines.push(...completedEffectLines(result), ...details);\n }\n return lines;\n}\n\nexport function renderHumanStreams(\n result: CliResult,\n options: { quiet?: boolean; verbose?: boolean } = {},\n): HumanResultStreams {\n if (result.presentation?.kind === 'raw') {\n return {\n stdout: result.presentation.body.replace(/\\n$/, ''),\n stderr: options.quiet === true ? '' : uniqueMessages(result).join('\\n'),\n };\n }\n if (suppressHumanOutput(result, options)) return { stdout: '', stderr: '' };\n\n const lines = resultBodyLines(result, options);\n\n const primaryAction = result.nextActions[0];\n if (primaryAction !== undefined) lines.push(`Next: ${nextActionLabel(primaryAction)}`);\n const body = lines.join('\\n');\n return result.state === 'failed' ? { stdout: '', stderr: body } : { stdout: body, stderr: '' };\n}\n"],"mappings":"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","names":["isRecord"]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createResult
3
- } from "./chunk-V63TSN3C.js";
3
+ } from "./chunk-FOYGZ4MK.js";
4
4
 
5
5
  // src/cli-protocol/plan.ts
6
6
  import { createHash } from "crypto";
@@ -61,4 +61,4 @@ export {
61
61
  createPlan,
62
62
  toWirePlan
63
63
  };
64
- //# sourceMappingURL=chunk-ZRV7TOCX.js.map
64
+ //# sourceMappingURL=chunk-G5AFQXXW.js.map
@@ -1,6 +1,3 @@
1
- import {
2
- CODEX_MIGRATION_SCHEMA
3
- } from "./chunk-AVAUUIDB.js";
4
1
  import {
5
2
  durableRename,
6
3
  writeDurableFile
@@ -8,6 +5,9 @@ import {
8
5
  import {
9
6
  CodexMigrationError
10
7
  } from "./chunk-CDWNLTHY.js";
8
+ import {
9
+ CODEX_MIGRATION_SCHEMA
10
+ } from "./chunk-AVAUUIDB.js";
11
11
 
12
12
  // src/codex-plugin/finalization.ts
13
13
  import { createHash, randomUUID } from "crypto";
@@ -492,4 +492,4 @@ export {
492
492
  observeCodexRecoveryPlan,
493
493
  applyCodexFinalization
494
494
  };
495
- //# sourceMappingURL=chunk-AXAGJLMP.js.map
495
+ //# sourceMappingURL=chunk-G757F3EU.js.map
@@ -16,47 +16,54 @@ import {
16
16
  findFeatureLineageIssues
17
17
  } from "./chunk-XROROJLI.js";
18
18
  import {
19
+ collectExecutableFeatureFiles,
19
20
  createPhaseAnchorEnvironment,
21
+ featureSourceFileName,
20
22
  findFeatureSourcePath,
21
23
  hasDefaultExecutableFeatureFiles,
22
24
  readFrontmatterScalar
23
- } from "./chunk-USPVNZ63.js";
25
+ } from "./chunk-BZWO3BVD.js";
24
26
  import {
25
27
  createProjectContext,
26
28
  getMissingPacks,
27
29
  reconcile
28
- } from "./chunk-NOTBZCKG.js";
30
+ } from "./chunk-2XR7J5WL.js";
31
+ import {
32
+ WORKSPACE_ROOTS
33
+ } from "./chunk-OKPRQGFG.js";
29
34
  import {
30
35
  legacyObservationIsEmpty,
31
36
  observeClaudeLegacy
32
- } from "./chunk-4CKCRZDO.js";
37
+ } from "./chunk-7ULZND56.js";
33
38
  import {
34
39
  hasLegacyClaudePluginMode,
35
40
  readClaudePluginMode
36
- } from "./chunk-FDHJ63FZ.js";
41
+ } from "./chunk-WVA4Q6BX.js";
42
+ import {
43
+ codexFinalizationIsComplete
44
+ } from "./chunk-G757F3EU.js";
45
+ import {
46
+ findDanglingDependencies,
47
+ findTicketsInCycles,
48
+ formatTicketReference,
49
+ inspectTicketIndexConflicts,
50
+ readTickets
51
+ } from "./chunk-MVFHTUQ3.js";
37
52
  import {
38
53
  BDD_LANE_FILE_PATHS,
39
54
  BDD_LANE_SCRIPT,
40
55
  SAFEWORD_SCHEMA,
41
- getMissingPythonToolDependencies,
42
56
  hasImportLinterScaffoldTarget,
43
57
  isCursorProjectPath,
44
58
  schemaForProjectSurfaces,
45
59
  typescriptPackages
46
- } from "./chunk-BSOUMHMQ.js";
60
+ } from "./chunk-IPTM5VE7.js";
47
61
  import {
48
- codexFinalizationIsComplete
49
- } from "./chunk-AXAGJLMP.js";
50
- import {
51
- findDanglingDependencies,
52
- findTicketsInCycles,
53
- formatTicketReference,
54
- inspectTicketIndexConflicts,
55
- readTickets
56
- } from "./chunk-KFVEPQ7X.js";
62
+ getPythonToolDependencyGaps
63
+ } from "./chunk-JSR3HXFT.js";
57
64
  import {
58
65
  createResult
59
- } from "./chunk-V63TSN3C.js";
66
+ } from "./chunk-FOYGZ4MK.js";
60
67
  import {
61
68
  VERSION
62
69
  } from "./chunk-UAFM77KW.js";
@@ -67,15 +74,16 @@ import {
67
74
  resolveConfiguredPath,
68
75
  resolveTicketsDirectory,
69
76
  toRepoRelativePath
70
- } from "./chunk-GKR44BCH.js";
77
+ } from "./chunk-RVDXBHUG.js";
71
78
  import {
72
79
  exists,
73
80
  isDirectory,
74
81
  readFileSafe,
75
82
  readJson
76
- } from "./chunk-S2T356DA.js";
83
+ } from "./chunk-HF3DXZEA.js";
77
84
 
78
85
  // src/health.ts
86
+ import { execFileSync } from "child_process";
79
87
  import { readdirSync as readdirSync2 } from "fs";
80
88
  import nodePath2 from "path";
81
89
 
@@ -531,6 +539,11 @@ function findGlossaryIssues(cwd) {
531
539
  function findCucumberHarnessAdvisories(cwd, { existingCucumberHarness, scaffoldBddLane }) {
532
540
  if (existingCucumberHarness === void 0) return [];
533
541
  if (scaffoldBddLane) {
542
+ if (isWorkspaceCucumberHarness(existingCucumberHarness)) {
543
+ return [
544
+ `A workspace Cucumber harness (${existingCucumberHarness}) is preserved alongside Safeword's root starter lane. This is informational: Safeword does not remove or modify project test infrastructure. The starter lane reads the default workspace features directories; set paths.features / paths.steps only when this harness uses nonstandard locations.`
545
+ ];
546
+ }
534
547
  return [buildLeftoverLaneAdvisory(cwd, existingCucumberHarness)];
535
548
  }
536
549
  if (readConfiguredPath(cwd, "features") !== void 0 || hasDefaultExecutableFeatureFiles(cwd)) {
@@ -540,6 +553,9 @@ function findCucumberHarnessAdvisories(cwd, { existingCucumberHarness, scaffoldB
540
553
  `Detected a cucumber harness (${existingCucumberHarness}) but paths.features is not set in .safeword/config.json \u2014 project codify, project lint-gherkin, and doctor cannot see your suite. Add e.g. "paths": { "features": "tests/behaviors", "steps": "tests/steps" } (paths.steps only matters when the scaffolded runner reads relocated TypeScript steps).`
541
554
  ];
542
555
  }
556
+ function isWorkspaceCucumberHarness(evidence) {
557
+ return WORKSPACE_ROOTS.some((root) => evidence.startsWith(`${root}/`));
558
+ }
543
559
  function buildLeftoverLaneAdvisory(cwd, evidence) {
544
560
  const leftovers = BDD_LANE_FILE_PATHS.filter(
545
561
  (filePath) => exists(nodePath2.join(cwd, filePath))
@@ -607,13 +623,119 @@ function archAlignmentHasContent(implPlanContent) {
607
623
  function emptyCoverageDiagnostics() {
608
624
  return { issues: [], advisories: [] };
609
625
  }
626
+ var CURRENT_WORK_BASE_REFS = [
627
+ "refs/remotes/origin/HEAD",
628
+ "refs/remotes/origin/main",
629
+ "refs/remotes/origin/master",
630
+ "refs/heads/main",
631
+ "refs/heads/master"
632
+ ];
633
+ function readGit(cwd, args) {
634
+ try {
635
+ return execFileSync("git", args, {
636
+ cwd,
637
+ encoding: "utf8",
638
+ maxBuffer: 10 * 1024 * 1024,
639
+ stdio: ["ignore", "pipe", "pipe"]
640
+ });
641
+ } catch {
642
+ return void 0;
643
+ }
644
+ }
645
+ function addNulSeparatedPaths(target, output) {
646
+ for (const path of output.split("\0")) {
647
+ if (path !== "") target.add(path);
648
+ }
649
+ }
650
+ function currentWorkPathsWithHead(cwd) {
651
+ const baseReference = CURRENT_WORK_BASE_REFS.find(
652
+ (candidate) => readGit(cwd, ["rev-parse", "--verify", "--quiet", candidate]) !== void 0
653
+ );
654
+ if (baseReference === void 0) return void 0;
655
+ const mergeBase = readGit(cwd, ["merge-base", "HEAD", baseReference])?.trim();
656
+ if (mergeBase === void 0 || mergeBase === "") return void 0;
657
+ const committed = readGit(cwd, [
658
+ "diff",
659
+ "--relative",
660
+ "--name-only",
661
+ "-z",
662
+ `${mergeBase}...HEAD`
663
+ ]);
664
+ const working = readGit(cwd, ["diff", "--relative", "--name-only", "-z", "HEAD"]);
665
+ if (committed === void 0 || working === void 0) return void 0;
666
+ const paths = /* @__PURE__ */ new Set();
667
+ addNulSeparatedPaths(paths, committed);
668
+ addNulSeparatedPaths(paths, working);
669
+ return [...paths];
670
+ }
671
+ function currentWorkPathsWithoutHead(cwd) {
672
+ const staged = readGit(cwd, ["diff", "--cached", "--name-only", "-z"]);
673
+ if (staged === void 0) return void 0;
674
+ const paths = /* @__PURE__ */ new Set();
675
+ addNulSeparatedPaths(paths, staged);
676
+ return [...paths];
677
+ }
678
+ function currentWorkPaths(cwd) {
679
+ if (readGit(cwd, ["rev-parse", "--is-inside-work-tree"])?.trim() !== "true") return void 0;
680
+ const hasHead = readGit(cwd, ["rev-parse", "--verify", "--quiet", "HEAD^{commit}"]);
681
+ const changedPaths = hasHead === void 0 ? currentWorkPathsWithoutHead(cwd) : currentWorkPathsWithHead(cwd);
682
+ if (changedPaths === void 0) return void 0;
683
+ const untracked = readGit(cwd, ["ls-files", "--others", "--exclude-standard", "-z"]);
684
+ if (untracked === void 0) return void 0;
685
+ const paths = new Set(changedPaths);
686
+ addNulSeparatedPaths(paths, untracked);
687
+ return [...paths];
688
+ }
689
+ function ticketIdsFromChangedPaths(paths, ticketPrefix) {
690
+ const ticketIds = /* @__PURE__ */ new Set();
691
+ for (const path of paths) {
692
+ if (!path.startsWith(ticketPrefix)) continue;
693
+ const [ticketId] = path.slice(ticketPrefix.length).split("/", 1);
694
+ if (ticketId !== void 0 && ticketId !== "") ticketIds.add(ticketId);
695
+ }
696
+ return ticketIds;
697
+ }
698
+ function addTicketsForChangedFeatureSources(cwd, ticketsRoot, featureFiles, changedFeatures, ticketIds) {
699
+ for (const ticketId of listTicketIds(ticketsRoot)) {
700
+ const featurePath = findFeatureSourcePath(cwd, ticketId, featureFiles);
701
+ if (featurePath !== void 0 && changedFeatures.paths.has(featurePath) || featurePath === void 0 && changedFeatures.fileNames.has(featureSourceFileName(cwd, ticketId))) {
702
+ ticketIds.add(ticketId);
703
+ }
704
+ }
705
+ }
706
+ function currentWorkCoverageTicketIds(cwd, ticketsRoot, featureFiles) {
707
+ const paths = currentWorkPaths(cwd);
708
+ if (paths === void 0) return listTicketIds(ticketsRoot);
709
+ if (paths.length === 0) return [];
710
+ const ticketsRelative = toRepoRelativePath(cwd, ticketsRoot).split(nodePath2.sep).join("/");
711
+ if (ticketsRelative === ".." || ticketsRelative.startsWith("../")) return [];
712
+ const ticketPrefix = `${ticketsRelative}/`;
713
+ const changedFeatures = {
714
+ paths: new Set(
715
+ paths.filter((path) => path.endsWith(".feature")).map((path) => nodePath2.resolve(cwd, path))
716
+ ),
717
+ fileNames: new Set(
718
+ paths.filter((path) => path.endsWith(".feature")).map((path) => nodePath2.basename(path))
719
+ )
720
+ };
721
+ const ticketIds = ticketIdsFromChangedPaths(paths, ticketPrefix);
722
+ if (changedFeatures.paths.size === 0) return [...ticketIds];
723
+ addTicketsForChangedFeatureSources(cwd, ticketsRoot, featureFiles, changedFeatures, ticketIds);
724
+ return [...ticketIds];
725
+ }
610
726
  function findCoverageDiagnostics(cwd) {
611
727
  const ticketsRoot = resolveTicketsDirectory(cwd);
612
728
  const all = emptyCoverageDiagnostics();
613
729
  const configuredFeatures = readConfiguredPath(cwd, "features");
614
730
  const anchorEnvironment = createPhaseAnchorEnvironment(cwd, configuredFeatures);
615
- for (const ticketId of listTicketIds(ticketsRoot)) {
616
- const ticketDiagnostics = coverageDiagnosticsForTicket(cwd, ticketsRoot, ticketId);
731
+ const featureFiles = collectExecutableFeatureFiles(cwd);
732
+ for (const ticketId of currentWorkCoverageTicketIds(cwd, ticketsRoot, featureFiles)) {
733
+ const ticketDiagnostics = coverageDiagnosticsForTicket(
734
+ cwd,
735
+ ticketsRoot,
736
+ ticketId,
737
+ featureFiles
738
+ );
617
739
  all.issues.push(...ticketDiagnostics.issues);
618
740
  all.advisories.push(...ticketDiagnostics.advisories);
619
741
  const anchorAdvisory = phaseAnchorAdvisoryForTicket(
@@ -640,14 +762,14 @@ function phaseAnchorAdvisoryForTicket(cwd, ticketsRoot, ticketId, anchorEnvironm
640
762
  if (verdict.kind !== "unanchored") return void 0;
641
763
  return `${formatCoverageTicketLabel(ticketId, content)}: ${verdict.reason} The anchor is the exited phase's artifact \u2014 boundary checks verify it against the tree.`;
642
764
  }
643
- function coverageDiagnosticsForTicket(cwd, ticketsRoot, ticketId) {
765
+ function coverageDiagnosticsForTicket(cwd, ticketsRoot, ticketId, featureFiles) {
644
766
  const ticketDirectory = nodePath2.join(ticketsRoot, ticketId);
645
767
  const ticketContent = readFileSafe(nodePath2.join(ticketDirectory, "ticket.md"));
646
768
  if (ticketContent === void 0 || !isInProgress(ticketContent))
647
769
  return emptyCoverageDiagnostics();
648
770
  const specContent = readFileSafe(nodePath2.join(ticketDirectory, "spec.md"));
649
771
  if (specContent === void 0) return emptyCoverageDiagnostics();
650
- const featureSource = readFeatureSource(cwd, ticketId);
772
+ const featureSource = readFeatureSource(cwd, ticketId, featureFiles);
651
773
  try {
652
774
  const report = featureSource === void 0 ? buildCoverageReport(
653
775
  specContent,
@@ -694,8 +816,8 @@ function formatFeatureLineageIssues(cwd, ticketId, featureSource, ticketContent)
694
816
  (issue) => `${label}: ${relativePath}: ${issue}`
695
817
  );
696
818
  }
697
- function readFeatureSource(cwd, ticketFolder) {
698
- const featurePath = findFeatureSourcePath(cwd, ticketFolder);
819
+ function readFeatureSource(cwd, ticketFolder, featureFiles) {
820
+ const featurePath = findFeatureSourcePath(cwd, ticketFolder, featureFiles);
699
821
  const content = featurePath === void 0 ? void 0 : readFileSafe(featurePath);
700
822
  return featurePath === void 0 || content === void 0 ? void 0 : { path: featurePath, content };
701
823
  }
@@ -806,7 +928,11 @@ function findMissingPatches(cwd, actions) {
806
928
  }
807
929
  function findMissingPythonToolDeclarations(cwd, context) {
808
930
  if (!context.languages?.python) return [];
809
- return getMissingPythonToolDependencies(cwd, hasImportLinterScaffoldTarget(cwd));
931
+ return [
932
+ ...new Set(
933
+ getPythonToolDependencyGaps(cwd, hasImportLinterScaffoldTarget).flatMap((gap) => gap.tools)
934
+ )
935
+ ];
810
936
  }
811
937
  async function checkHealth(cwd, options = {}) {
812
938
  const safewordDirectory = nodePath2.join(cwd, ".safeword");
@@ -844,7 +970,7 @@ async function checkHealth(cwd, options = {}) {
844
970
  ...missingClaudeSettingsIssues(cwd, healthSchema)
845
971
  ];
846
972
  const missingPacks = options.skipPackageChecks ? [] : getMissingPacks(cwd);
847
- const missingPythonTools = findMissingPythonToolDeclarations(cwd, ctx);
973
+ const missingPythonTools = options.skipPythonToolChecks ? [] : findMissingPythonToolDeclarations(cwd, ctx);
848
974
  const coverageDiagnostics = findCoverageDiagnostics(cwd);
849
975
  const ticketIndexConflicts = inspectTicketIndexConflicts(cwd);
850
976
  issues.push(...coverageDiagnostics.issues);
@@ -962,4 +1088,4 @@ export {
962
1088
  observeCursorProject,
963
1089
  unselectedCursorFinding
964
1090
  };
965
- //# sourceMappingURL=chunk-KXHVFCDT.js.map
1091
+ //# sourceMappingURL=chunk-GFDINP7M.js.map