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,6 +1,6 @@
1
1
  {
2
2
  "name": "safeword",
3
- "version": "0.78.2",
3
+ "version": "0.78.4",
4
4
  "description": "Safeword workflow guidance and gates for Codex.",
5
5
  "author": {
6
6
  "name": "Arcade AI"
@@ -6,7 +6,7 @@
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
9
- "command": "bunx --bun safeword@0.78.2 hook codex session-start --plugin-hook",
9
+ "command": "bunx --bun safeword@0.78.4 hook codex session-start --plugin-hook",
10
10
  "timeout": 120,
11
11
  "statusMessage": "Loading Safeword standing instructions"
12
12
  }
@@ -19,7 +19,7 @@
19
19
  "hooks": [
20
20
  {
21
21
  "type": "command",
22
- "command": "bunx --bun safeword@0.78.2 hook codex pre-tool-use --plugin-hook",
22
+ "command": "bunx --bun safeword@0.78.4 hook codex pre-tool-use --plugin-hook",
23
23
  "timeout": 30,
24
24
  "statusMessage": "Checking Safeword edit gates"
25
25
  }
@@ -32,7 +32,7 @@
32
32
  "hooks": [
33
33
  {
34
34
  "type": "command",
35
- "command": "bunx --bun safeword@0.78.2 hook codex post-tool-use --plugin-hook",
35
+ "command": "bunx --bun safeword@0.78.4 hook codex post-tool-use --plugin-hook",
36
36
  "timeout": 30,
37
37
  "statusMessage": "Surfacing Safeword post-tool context"
38
38
  }
@@ -45,7 +45,7 @@
45
45
  "hooks": [
46
46
  {
47
47
  "type": "command",
48
- "command": "bunx --bun safeword@0.78.2 hook codex user-prompt-submit --plugin-hook",
48
+ "command": "bunx --bun safeword@0.78.4 hook codex user-prompt-submit --plugin-hook",
49
49
  "timeout": 30,
50
50
  "statusMessage": "Checking queued Safeword prompt context"
51
51
  }
@@ -58,7 +58,7 @@
58
58
  "hooks": [
59
59
  {
60
60
  "type": "command",
61
- "command": "bunx --bun safeword@0.78.2 hook codex stop --plugin-hook",
61
+ "command": "bunx --bun safeword@0.78.4 hook codex stop --plugin-hook",
62
62
  "timeout": 600,
63
63
  "statusMessage": "Checking Safeword stop continuation"
64
64
  }
@@ -118,6 +118,9 @@ Write each saved `.feature` scenario to these rules — they head off at authori
118
118
  - **Declarative, business language** — name the intent, not the UI mechanics. "When the customer submits the order" ✓, not "When the user clicks `#submit` and waits 200ms" ✗. Reads as living documentation and survives implementation changes.
119
119
  - **`Given` is state, not action** — establish the world, don't act in it. "Given the cart holds one item" ✓, not "Given the customer adds an item" ✗ (an action belongs in `When`).
120
120
  - **No `or` in the `Then`** — one outcome per scenario; "returns 200 **or** 201" is two scenarios. For one behavior across many inputs, use a `Scenario Outline` with an `Examples` table, not copy-pasted scenarios.
121
+ - **Keep acceptance examples representative** — scenarios cover externally meaningful behavior partitions and boundaries, not every parser permutation or corruption mechanism. Put exhaustive schema, arithmetic, malformed-field, and implementation-level matrices in table-driven lower-level tests.
122
+ - **Keep one numbered Rule boundary** — for a scenario under a numbered Rule, every asserted outcome must prove that enclosing Rule. If a `Then` also proves an independently valuable invariant owned by another Rule, split it into that Rule's scenario. Unnumbered grouping Rules and scenarios without lineage keep the exemptions below.
123
+ - **Keep outlines coherent** — rows vary one behavioral dimension and retain the same outcome shape. Unrelated defect mechanisms that merely share a generic rejection belong in separate scenarios or lower-level contract matrices.
121
124
 
122
125
  Two of these rules mirror gate checks — **one behavior** is AODI's **Atomic**, and externally-observable outcomes are its **Observable** (both in the Scenario Quality Gate below). Author for them here; the gate still validates every scenario adversarially.
123
126
 
@@ -55,9 +55,15 @@ same actor-facing entry point and actor-visible result that the `When` and
55
55
  when each behaviorally distinct example traverses the claimed boundary;
56
56
  otherwise narrow the scenario or add the missing proof.
57
57
  - **Keep evidence limits explicit.** When the real boundary cannot be automated
58
- reliably, use the existing `@manual` or `@live` path and perform and record
59
- that check separately. A tag, skip reason, or narrower automated test does
60
- not prove the broader scenario by itself.
58
+ reliably, use the existing `@manual` or `@live` path and record the command or
59
+ steps performed, observed result, and retained evidence identity in the ticket
60
+ work log under a concrete timestamped heading. Annotate the ledger with that
61
+ exact identity, for example `RED skip: manual — see work log 2026-08-14T18:30Z
62
+ "paid route proof"`, and record GREEN only after that manual check succeeds.
63
+ This annotation is agent-attested evidence; the gate checks that a reason is
64
+ present, not that the referenced work-log entry resolves. A tag, generic skip
65
+ reason, or narrower automated test does not prove the broader scenario by itself;
66
+ fixtures and lower-level tests may de-risk it, but cannot lend it their evidence.
61
67
 
62
68
  If a scenario accidentally names incidental UI mechanics rather than product
63
69
  behavior, loop back to define-behavior and rewrite it; do not silently reinterpret
@@ -72,7 +78,7 @@ When the scenario source is a `.feature` file and the Cucumber lane exists, RED
72
78
  - **Verify RED on the reported step status, not the exit code alone.** Safeword's scaffolded `test:bdd` runs cucumber-js _without_ `--dry-run`, so undefined/pending steps exit non-zero — a genuine RED. But `cucumber-js --dry-run` _reports_ undefined/ambiguous/pending steps while still **exiting 0**; a lane (or host profile) built on `--dry-run` will look green even when steps are missing. Never substitute a bare `--dry-run` for this RED check, and when a dry-run/check profile is the host's spec-ahead lane, confirm RED by the reported undefined/pending count it prints, not by its exit status.
73
79
  - Keep step definitions thin; call app, API, CLI, or shell helpers from steps. Do not bury business logic in Cucumber glue.
74
80
  - Use Vitest for lower-level implementation proof when it gives faster or more precise coverage, especially pure functions and module contracts.
75
- - A scenario is not complete until both the relevant implementation tests and `test:bdd` pass, unless the feature is explicitly tagged `@manual` or `@live` with a skip reason.
81
+ - A scenario is not complete until both the relevant implementation tests and `test:bdd` pass. An explicitly tagged `@manual` or `@live` scenario instead requires the ticket-work-log evidence and ledger annotations described above.
76
82
 
77
83
  ### Walking Skeleton (first scenario only)
78
84
 
@@ -102,7 +108,7 @@ Then they see the dashboard
102
108
 
103
109
  **Annotation rule (enforced by hook):** every `[x]` transition must carry either a commit SHA (proving which commit did that step) or `skip: <non-empty reason>` (a deliberate, auditable omission). Bare `[x]` without an annotation is blocked at the write-time hook. Pre-existing bare `[x]` from before this rule shipped is silently allowed — the validation is forward-looking only.
104
110
 
105
- **Uncommittable RED states:** Prefer a real RED commit. Use this escape hatch only when a partial RED state cannot pass structural commit gates because the repo rejects incomplete code, such as:
111
+ **Uncommittable RED states:** Prefer a real RED commit. For the uncommittable-partial-state reason below, use this escape hatch only when a partial RED state cannot pass structural commit gates because the repo rejects incomplete code. Manual/live evidence uses the separate path above. Examples of uncommittable partial states include:
106
112
 
107
113
  - a type-only scaffold that trips unused-property lint before behavior exists
108
114
  - an interface rename that cannot compile until all callers are updated
@@ -2,7 +2,7 @@
2
2
  name: closeout
3
3
  description: Close a completed local delivery safely. Use when wrapping up a
4
4
  finished coding session by verifying it, merging only with explicit authority,
5
- running the mandatory retrospective, and cleaning the exact merged branch and
5
+ capturing retrospective learning, and cleaning the exact merged branch and
6
6
  worktree. Do NOT use for cloud-agent tasks, unmerged work, or cleanup without
7
7
  a pull request.
8
8
  ---
@@ -62,29 +62,32 @@ unobservable results are not merge proof; report the recovery check and stop.
62
62
 
63
63
  If the command reported an error but fresh observation proves the expected head
64
64
  was merged, report that the remote merge succeeded, do not retry it, and proceed
65
- to the mandatory retrospective. On every invocation, re-observe durable state
65
+ to retrospective capture. On every invocation, re-observe durable state
66
66
  and continue only the unfinished suffix. Treat an absent cleanup target as
67
67
  complete only after proving it was the exact planned target. If the pull request
68
- is merged, its retrospective is complete, and its exact branch and worktree are
69
- already absent, report that the session is already closed.
68
+ is merged and its exact branch and worktree are already absent, report that the
69
+ session is already closed and report the retrospective's observed state.
70
70
 
71
71
  The guard records a private, atomic verification receipt in Git's shared common
72
72
  directory after green hosted CI covers a clean exact PR head, or after every
73
73
  local verification lane passes on that head.
74
74
  For 24 hours, that receipt can prove the immutable head when an interrupted
75
75
  cleanup must resume from a surviving worktree after the topic worktree is gone.
76
- A missing, stale, malformed, dirty-state, or wrong-head receipt blocks cleanup.
76
+ After the topic worktree is gone, a missing, stale, malformed, dirty-state, or
77
+ wrong-head receipt blocks interrupted cleanup resumption.
77
78
 
78
- ## 4. Complete the current session's retrospective
79
+ ## 4. Capture retrospective learning without making it cleanup authority
79
80
 
80
81
  After merge is independently confirmed, invoke the cleanup guard in preview
81
82
  mode. Its host hook supplies a short-lived, single-consumer binding to this exact
82
83
  session (and Cursor transcript). Codex Desktop may instead supply its authenticated
83
84
  current `CODEX_THREAD_ID`, consistent with SafeWord's other Codex identity bridges.
84
- A missing or expired binding or identity fails closed; there is no newest-session
85
- fallback and callers cannot nominate another receipt, session, transcript, or spool.
85
+ A missing or expired binding or identity is advisory for repository cleanup; there is
86
+ no newest-session fallback and callers cannot nominate another receipt, session,
87
+ transcript, or spool. Report the missing evidence without treating it as authority over
88
+ the worktree or branches.
86
89
 
87
- The guard runs `safeword retro run --json` itself and accepts only a
90
+ The guard runs `safeword retro run --json --auto-extract` itself and accepts only a
88
91
  successful result whose `data.agent_filing_needed` is `false` and whose derived
89
92
  current session has an empty filing spool. Zero substantial findings and every
90
93
  finding successfully filed are both complete outcomes.
@@ -95,13 +98,16 @@ validates the sealed byte prefix and runs retro only over the bounded appended
95
98
  window before advancing the receipt. A partial trailing record is neither
96
99
  sealed nor lost; mutation or truncation of the sealed prefix fails closed.
97
100
 
98
- Failed extraction, failed filing, pending drafts, malformed output, or an
99
- identity mismatch means no cleanup. Report every failure and its recovery
100
- action. A request to skip retro does not create a bypass: preserve the worktree
101
- and branches and explain that the retrospective is required before cleanup.
101
+ Repository cleanup does not depend on a complete retrospective. A missing binding, an
102
+ incomplete retrospective, extraction failure, malformed output, or identity mismatch is
103
+ advisory: report it and continue evaluating cleanup from fresh repository evidence.
104
+
105
+ Filing failure or pending drafts are advisory for repository cleanup too. Report the
106
+ exact recovery action and the risk that deleting the worktree could discard captured
107
+ but unfiled learning, but do not let retrospective state authorize or block cleanup.
102
108
 
103
109
  When the authenticated preview reports pending drafts and includes
104
- `plan.retro.spoolPath`, invoke the `safeword:retro-filer` skill with that exact
110
+ `plan.retro.spoolPath`, invoke the `$safeword:retro-filer` skill with that exact
105
111
  path, then rerun the preview. This is the closeout recovery continuation: the
106
112
  guard derived the path from its short-lived host-session binding, so do not
107
113
  substitute, discover, or accept a caller-provided spool path.
@@ -128,8 +134,10 @@ After the topic worktree is gone, preview requires its fresh clean-head receipt.
128
134
  It binds the resulting repository state and exact PR identity to `PLAN_DIGEST`.
129
135
  Report the complete operation list and all blockers. Do not apply a blocked plan.
130
136
 
131
- With the user's cleanup intent already established by invoking closeout, apply
132
- only the unchanged preview:
137
+ Invocation permits preview only and grants no destructive cleanup authority.
138
+ After reporting the exact operations and blockers, apply only when the current
139
+ user request explicitly authorizes cleanup. Cleanup authority is consumed when
140
+ apply is attempted, and applies only to the unchanged preview:
133
141
 
134
142
  ```sh
135
143
  bun .safeword/scripts/closeout-cleanup.ts --pr PR_NUMBER --yes --plan PLAN_DIGEST
@@ -7,9 +7,10 @@ description: Use only right after the shared review coordinator reports it's run
7
7
 
8
8
  # Finish Review After Route Exhaustion
9
9
 
10
- Use this workflow only as the immediate continuation of a class-1 coordinator
11
- result. It adds best-effort feedback when no CLI reviewer completed; it never
12
- creates independent-review evidence.
10
+ Use this workflow only as the immediate continuation of a class-1 (requires
11
+ independent/cross-model review, unlike class-2's self-verifiable checks)
12
+ coordinator result. It adds best-effort feedback when no CLI reviewer
13
+ completed; it never creates independent-review evidence.
13
14
 
14
15
  ## Entry gate
15
16
 
@@ -33,7 +33,7 @@ Run these commands based on project type. All detected languages run for polyglo
33
33
  bun run lint 2>&1 || true
34
34
  fi
35
35
  # Prettier - format all files
36
- bun run format --if-present 2>&1 || true
36
+ bun run --if-present format 2>&1 || true
37
37
  # TypeScript type check (if tsconfig.json exists)
38
38
  [ -f tsconfig.json ] && bunx tsc --noEmit 2>&1 || true
39
39
  }
@@ -78,7 +78,9 @@ Common vacuous patterns, each with its fix (apply only when you can state the do
78
78
  | **Deterministic** | Same result on repeated runs | Time/random/external dependency |
79
79
  | **Independent** | No ordering dependency | "After Scenario 2 runs..." |
80
80
 
81
- **Atomic** — a single `When`→`Then` is atomic even if the `Then` asserts several properties of ONE outcome ("returns 200 with body X"). Flag non-atomic only when two genuinely independent behaviors could pass/fail separately (two `When` steps, or two `Then`s asserting different system-level effects) — never for a merely compound `Then`.
81
+ **Atomic** — a single `When`→`Then` is atomic even if the `Then` asserts several properties of ONE outcome ("returns 200 with body X"). Flag non-atomic only when two genuinely independent behaviors could pass/fail separately (two `When` steps or two `Then`s asserting different system-level effects) — never for a merely compound `Then`.
82
+
83
+ **Rule ownership** — review a coherent outcome under the Rule whose invariant it proves. An outcome owned by a different Rule is a lineage defect, not an atomicity defect; move or split it and report that single root cause.
82
84
 
83
85
  **Observable** — an assertion on a user/caller-visible outcome ("is denied", "passes the gate", "the plan contains X") IS observable even if the mechanism is internal; flag non-observable only for internal-detail-only assertions ("the cache was populated", "the private field is set").
84
86
 
@@ -98,6 +100,8 @@ After AODI validation, argue against your own scenario list: "What breaks that n
98
100
 
99
101
  One lens to always run — **negative-case coverage**: for each happy-path scenario, is there a rejection-path counterpart? Partitioning should already have produced the invalid-input classes; this pass is the backstop. Common pairs — create ↔ duplicate, read ↔ not-found, update ↔ not-allowed, act ↔ precondition-failed. Treat a gap as **should-strengthen**, not must-fix — a sibling AC often already covers the rejection: _"Happy path X has no rejection counterpart — add a scenario for path Z?"_ For one behavior across many inputs, use a `Scenario Outline`.
100
102
 
103
+ For each `Scenario Outline`, confirm its rows vary one behavioral dimension and keep the same outcome shape. Do not group unrelated defect mechanisms merely because they share a generic rejection. Keep feature scenarios representative; exhaustive parser, schema, arithmetic, malformed-field, and implementation-corruption matrices belong in table-driven lower-level tests, while externally meaningful boundaries and failure classes required by the cross-cutting checks remain acceptance scenarios.
104
+
101
105
  ## Cross-cutting checks
102
106
 
103
107
  Eight lenses across the whole scenario set (not per scenario) — each asks "what's missing?":
@@ -10,8 +10,8 @@ description: Use when finishing spec.md before writing test-definitions.md, or
10
10
 
11
11
  Review the artifact you just authored, then earn its review stamp so the next
12
12
  step is unblocked. This is **Tier 1** — a fast, built-in first pass: you review
13
- your own work, no sub-agent involved. Tier 2 (the fork review at each phase
14
- exit) is the independent check; that happens separately.
13
+ your own work, no sub-agent involved. Tier 2 (the phase-exit review) is the
14
+ independent check; that happens separately.
15
15
 
16
16
  **Stakes set depth.** Tier 2 may never run — review as if your stamp is the last
17
17
  word before code gets built on this spec, because often it is. Cheap floor means
@@ -166,5 +166,8 @@ single-action task.
166
166
  | Need test definitions for a feature OR acceptance criteria | `./.safeword/templates/test-definitions-feature.md` |
167
167
  | Feature spans 3+ components OR needs technical spec | `./.safeword/templates/design-doc-template.md` |
168
168
  | Making decision with long-term impact OR trade-offs | `./.safeword/templates/architecture-template.md` |
169
+ | Recording a structural or hard-to-reverse decision as its own record | `./.safeword/templates/adr-template.md` |
170
+ | Planning a feature's implementation before TDD starts | `./.safeword/templates/impl-plan-template.md` |
171
+ | Guarding a temporary upstream workaround so its removal isn't missed | `./.safeword/templates/tripwire-template.md` |
169
172
  | Task needs context anchoring | `./.safeword/templates/ticket-template.md` |
170
173
  | Starting execution of a plan, ticket, or spec | `./.safeword/templates/work-log-template.md` |
@@ -9,23 +9,23 @@ import {
9
9
  planSelfHealProject,
10
10
  selfHealProject,
11
11
  selfHealProjectPreservingProse
12
- } from "./chunk-I4KBHRZW.js";
13
- import {
14
- discoverUnreadableWorkspaces,
15
- extractMonorepoArchitectureSnapshot
16
- } from "./chunk-3EJNDIAO.js";
12
+ } from "./chunk-VJUPD7JI.js";
17
13
  import {
18
14
  GENERATED_ARCHITECTURE_FILENAME,
19
15
  isArchitectureDocumentEnforcementEnabled,
20
16
  readConfiguredPath,
21
17
  resolveGeneratedArchitecturePath,
22
18
  toRepoDirectory
23
- } from "./chunk-GKR44BCH.js";
19
+ } from "./chunk-RVDXBHUG.js";
20
+ import {
21
+ discoverUnreadableWorkspaces,
22
+ extractMonorepoArchitectureSnapshot
23
+ } from "./chunk-VZ5B2SIO.js";
24
24
  import {
25
25
  readJson,
26
26
  writeJson
27
- } from "./chunk-S2T356DA.js";
28
- import "./chunk-QTG2EXFT.js";
27
+ } from "./chunk-HF3DXZEA.js";
28
+ import "./chunk-LUNHU6Z3.js";
29
29
 
30
30
  // src/commands/architecture.ts
31
31
  import { execFileSync } from "child_process";
@@ -650,4 +650,4 @@ export {
650
650
  architectureStage,
651
651
  architectureStaged
652
652
  };
653
- //# sourceMappingURL=architecture-N5ZC4CDU.js.map
653
+ //# sourceMappingURL=architecture-TCSDEFKH.js.map
@@ -7,11 +7,11 @@ import {
7
7
  selfHeal,
8
8
  selfHealProject,
9
9
  selfHealProjectPreservingProse
10
- } from "./chunk-I4KBHRZW.js";
11
- import "./chunk-3EJNDIAO.js";
12
- import "./chunk-GKR44BCH.js";
13
- import "./chunk-S2T356DA.js";
14
- import "./chunk-QTG2EXFT.js";
10
+ } from "./chunk-VJUPD7JI.js";
11
+ import "./chunk-RVDXBHUG.js";
12
+ import "./chunk-VZ5B2SIO.js";
13
+ import "./chunk-HF3DXZEA.js";
14
+ import "./chunk-LUNHU6Z3.js";
15
15
  export {
16
16
  isSafewordOwned,
17
17
  isWouldChangeAction,
@@ -22,4 +22,4 @@ export {
22
22
  selfHealProject,
23
23
  selfHealProjectPreservingProse
24
24
  };
25
- //# sourceMappingURL=architecture-document-UBA5UT4J.js.map
25
+ //# sourceMappingURL=architecture-document-L2ADWVMV.js.map
@@ -3,13 +3,13 @@ import {
3
3
  discoverWorkspaces,
4
4
  extractMonorepoArchitectureSnapshot,
5
5
  monorepoFingerprintOf
6
- } from "./chunk-3EJNDIAO.js";
7
- import "./chunk-S2T356DA.js";
8
- import "./chunk-QTG2EXFT.js";
6
+ } from "./chunk-VZ5B2SIO.js";
7
+ import "./chunk-HF3DXZEA.js";
8
+ import "./chunk-LUNHU6Z3.js";
9
9
  export {
10
10
  discoverUnreadableWorkspaces,
11
11
  discoverWorkspaces,
12
12
  extractMonorepoArchitectureSnapshot,
13
13
  monorepoFingerprintOf
14
14
  };
15
- //# sourceMappingURL=architecture-monorepo-E4JUYJGV.js.map
15
+ //# sourceMappingURL=architecture-monorepo-NKOQZBEY.js.map
@@ -7,25 +7,25 @@ import {
7
7
  } from "./chunk-3D25MSWD.js";
8
8
  import {
9
9
  createPhaseAnchorScope
10
- } from "./chunk-USPVNZ63.js";
10
+ } from "./chunk-BZWO3BVD.js";
11
11
  import {
12
12
  classifyAnnotation,
13
13
  isValidSha,
14
14
  isValidSkipReason,
15
15
  parseCheckboxAnnotation
16
16
  } from "./chunk-Z4ESH6KU.js";
17
- import "./chunk-Q5KLE6ZF.js";
17
+ import "./chunk-OKPRQGFG.js";
18
18
  import {
19
19
  warn
20
20
  } from "./chunk-QSLVO4XF.js";
21
21
  import {
22
22
  readConfiguredPathFromContent,
23
23
  ticketDirectoriesForConfiguredRoot
24
- } from "./chunk-GKR44BCH.js";
24
+ } from "./chunk-RVDXBHUG.js";
25
25
  import {
26
26
  readFileSafe
27
- } from "./chunk-S2T356DA.js";
28
- import "./chunk-QTG2EXFT.js";
27
+ } from "./chunk-HF3DXZEA.js";
28
+ import "./chunk-LUNHU6Z3.js";
29
29
 
30
30
  // src/commands/boundary.ts
31
31
  import { execFileSync as execFileSync2 } from "child_process";
@@ -630,4 +630,4 @@ function boundary(options) {
630
630
  export {
631
631
  boundary
632
632
  };
633
- //# sourceMappingURL=boundary-HLJILY7R.js.map
633
+ //# sourceMappingURL=boundary-QP2H7C46.js.map