safeword 0.78.2 → 0.78.3
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.
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/codex-plugin/hooks.json +5 -5
- package/codex-plugin/skills/bdd/references/SCENARIOS.md +3 -0
- package/codex-plugin/skills/bdd/references/TDD.md +11 -5
- package/codex-plugin/skills/closeout/SKILL.md +24 -16
- package/codex-plugin/skills/finish-review/SKILL.md +4 -3
- package/codex-plugin/skills/lint/SKILL.md +1 -1
- package/codex-plugin/skills/review-spec/SKILL.md +5 -1
- package/codex-plugin/skills/self-review/SKILL.md +2 -2
- package/codex-plugin/skills/ticket-system/SKILL.md +3 -0
- package/dist/{architecture-N5ZC4CDU.js → architecture-RQ377ZER.js} +6 -6
- package/dist/{architecture-document-UBA5UT4J.js → architecture-document-KS3CLSYN.js} +6 -6
- package/dist/{architecture-monorepo-E4JUYJGV.js → architecture-monorepo-NJWWU65G.js} +4 -4
- package/dist/{boundary-HLJILY7R.js → boundary-OPTC2RVJ.js} +6 -6
- package/dist/{chunk-NOTBZCKG.js → chunk-2XR7J5WL.js} +93 -42
- package/dist/chunk-2XR7J5WL.js.map +1 -0
- package/dist/{chunk-4CZS4YJV.js → chunk-3OKZ3X4O.js} +3 -3
- package/dist/{chunk-J7UDLLTK.js → chunk-76XHADUG.js} +39 -25
- package/dist/chunk-76XHADUG.js.map +1 -0
- package/dist/{chunk-4CKCRZDO.js → chunk-7ULZND56.js} +2 -2
- package/dist/{chunk-34NCOTP5.js → chunk-7XELS325.js} +2 -2
- package/dist/{chunk-USPVNZ63.js → chunk-BZWO3BVD.js} +11 -7
- package/dist/chunk-BZWO3BVD.js.map +1 -0
- package/dist/{chunk-GZ36UZJG.js → chunk-CFME47IY.js} +6 -6
- package/dist/{chunk-SME5SU3O.js → chunk-CNBZ3S5U.js} +255 -45
- package/dist/chunk-CNBZ3S5U.js.map +1 -0
- package/dist/{chunk-AV5LTEME.js → chunk-CRGPYC35.js} +8 -6
- package/dist/{chunk-AV5LTEME.js.map → chunk-CRGPYC35.js.map} +1 -1
- package/dist/{chunk-BQTC6YGN.js → chunk-D5ENZR6N.js} +2 -2
- package/dist/{chunk-V63TSN3C.js → chunk-FOYGZ4MK.js} +31 -10
- package/dist/chunk-FOYGZ4MK.js.map +1 -0
- package/dist/{chunk-ZRV7TOCX.js → chunk-G5AFQXXW.js} +2 -2
- package/dist/{chunk-S2T356DA.js → chunk-HF3DXZEA.js} +7 -10
- package/dist/chunk-HF3DXZEA.js.map +1 -0
- package/dist/{chunk-NSZGI7HK.js → chunk-HNCUIXDY.js} +9 -9
- package/dist/{chunk-NSZGI7HK.js.map → chunk-HNCUIXDY.js.map} +1 -1
- package/dist/{chunk-KXHVFCDT.js → chunk-IDRLACDS.js} +145 -19
- package/dist/chunk-IDRLACDS.js.map +1 -0
- package/dist/{chunk-BSOUMHMQ.js → chunk-IPTM5VE7.js} +101 -1094
- package/dist/chunk-IPTM5VE7.js.map +1 -0
- package/dist/chunk-JBOLNV2L.js +21 -0
- package/dist/chunk-JBOLNV2L.js.map +1 -0
- package/dist/chunk-JSR3HXFT.js +1231 -0
- package/dist/chunk-JSR3HXFT.js.map +1 -0
- package/dist/{chunk-I4KBHRZW.js → chunk-LH2FAQTI.js} +4 -4
- package/dist/{chunk-WVDRXD67.js → chunk-MLBZFB5A.js} +1 -1
- package/dist/chunk-MLBZFB5A.js.map +1 -0
- package/dist/{chunk-KFVEPQ7X.js → chunk-MVFHTUQ3.js} +2 -2
- package/dist/{chunk-BAVDDAN3.js → chunk-MZKTOX6X.js} +7 -7
- package/dist/{chunk-TJ627SKI.js → chunk-O3GZ77F7.js} +15 -1
- package/dist/chunk-O3GZ77F7.js.map +1 -0
- package/dist/{chunk-Q5KLE6ZF.js → chunk-OKPRQGFG.js} +2 -2
- package/dist/{chunk-QUDIOBHP.js → chunk-PD7ZXRHV.js} +139 -18
- package/dist/chunk-PD7ZXRHV.js.map +1 -0
- package/dist/chunk-QAHJSG53.js +30 -0
- package/dist/chunk-QAHJSG53.js.map +1 -0
- package/dist/{chunk-QTG2EXFT.js → chunk-QLOUSTQE.js} +2 -2
- package/dist/{chunk-QTG2EXFT.js.map → chunk-QLOUSTQE.js.map} +1 -1
- package/dist/{chunk-3SOJBMM6.js → chunk-R6BSRNU4.js} +6 -6
- package/dist/{chunk-3SOJBMM6.js.map → chunk-R6BSRNU4.js.map} +1 -1
- package/dist/{chunk-664YNAMR.js → chunk-RTFPKJJV.js} +5 -5
- package/dist/{chunk-GKR44BCH.js → chunk-RVDXBHUG.js} +2 -2
- package/dist/chunk-THLEVFEX.js +22 -0
- package/dist/chunk-THLEVFEX.js.map +1 -0
- package/dist/{chunk-A7Z27COA.js → chunk-VFWAZLEF.js} +3 -3
- package/dist/{chunk-3EJNDIAO.js → chunk-VZ5B2SIO.js} +2 -2
- package/dist/chunk-WAMQTZAH.js +19 -0
- package/dist/chunk-WAMQTZAH.js.map +1 -0
- package/dist/{chunk-FDHJ63FZ.js → chunk-WVA4Q6BX.js} +1 -1
- package/dist/{chunk-FDHJ63FZ.js.map → chunk-WVA4Q6BX.js.map} +1 -1
- package/dist/{cleanup-X556LNWM.js → cleanup-ELVHZPRC.js} +9 -9
- package/dist/{cleanup-command-RV2Q7G72.js → cleanup-command-5BY4FWAT.js} +12 -12
- package/dist/cli.js +143 -108
- package/dist/cli.js.map +1 -1
- package/dist/{clients-HP23HRN2.js → clients-WRPBRO6V.js} +2 -2
- package/dist/{codex-bootstrap-MGY2D6HU.js → codex-bootstrap-GYG7N4XU.js} +77 -34
- package/dist/codex-bootstrap-GYG7N4XU.js.map +1 -0
- package/dist/{codex-hook-IPX3PDXX.js → codex-hook-7ILIPLYM.js} +56 -48
- package/dist/codex-hook-7ILIPLYM.js.map +1 -0
- package/dist/{codify-J5ZLJ3HK.js → codify-HSDVRZFI.js} +11 -8
- package/dist/codify-HSDVRZFI.js.map +1 -0
- package/dist/{commands-L4AINARC.js → commands-X4KBCMHS.js} +115 -60
- package/dist/commands-X4KBCMHS.js.map +1 -0
- package/dist/{config-LUSJAK6B.js → config-TXJRCN3W.js} +2 -2
- package/dist/{configured-paths-SPQ5XWOM.js → configured-paths-4CRHLBIF.js} +4 -4
- package/dist/contract-B7NDKO5B.js +8 -0
- package/dist/{coordinator-SA75UB3C.js → coordinator-ZMD3467F.js} +231 -144
- package/dist/coordinator-ZMD3467F.js.map +1 -0
- package/dist/corpus-PUBXCCSN.js +15 -0
- package/dist/{doctor-DSC36R4U.js → doctor-RPXETRSJ.js} +18 -18
- package/dist/{feature-directories-VOHVV26X.js → feature-directories-ASNDEM7J.js} +6 -6
- package/dist/{finalization-7SMLMVLV.js → finalization-BGPOEBAL.js} +2 -2
- package/dist/{gh-cli-ZMO7D2KE.js → gh-cli-OTX7PORT.js} +2 -2
- package/dist/{github-rest-KGKS4V2H.js → github-rest-JCW32377.js} +2 -2
- package/dist/index.js +2 -2
- package/dist/{job-CDADLJDF.js → job-NXXG4U5K.js} +20 -21
- package/dist/job-NXXG4U5K.js.map +1 -0
- package/dist/{learning-sync-6BTHM6ZC.js → learning-sync-2WIAOTW3.js} +4 -4
- package/dist/{legacy-global-guidance-2JL4Y5EB.js → legacy-global-guidance-WTDI53H7.js} +5 -5
- package/dist/{lint-gherkin-COSHVS6Z.js → lint-gherkin-LS3CHW3J.js} +7 -7
- package/dist/{operations-XVRQSLJG.js → operations-OZKEQCS4.js} +12 -12
- package/dist/{output-3LB2OEHN.js → output-ZYTEW6SC.js} +2 -2
- package/dist/{packet-5WT5M3OS.js → packet-7S6CZJQR.js} +2 -2
- package/dist/presets/typescript/index.js +2 -2
- package/dist/{profile-UMKQ5JVO.js → profile-SDFSBKH5.js} +7 -7
- package/dist/{prompt-GWYDFMLO.js → prompt-LYPODDC3.js} +2 -2
- package/dist/remove-P5JQNS5P.js +23 -0
- package/dist/{retro-IFSVU5KS.js → retro-EQK2Z2Z6.js} +8 -8
- package/dist/{retro-draft-spool-4S3TCHWL.js → retro-draft-spool-MDPBVM6J.js} +2 -2
- package/dist/{retro-extract-OSBFAXLU.js → retro-extract-CZMDD4WB.js} +2 -2
- package/dist/{review-pr-6S2352CK.js → review-pr-CWRD446M.js} +2 -2
- package/dist/{review-pr-publication-CGHCRRUI.js → review-pr-publication-AIX2U3VM.js} +2 -2
- package/dist/{run-5JESKXUR.js → run-T45X6Z6C.js} +4 -4
- package/dist/{self-report-VPHBPPSJ.js → self-report-V7PHKTS6.js} +2 -2
- package/dist/status-F5TFEIZ6.js +21 -0
- package/dist/{status-EX4L3ELO.js → status-S24PDFXB.js} +18 -18
- package/dist/{sync-config-O7J7IDGE.js → sync-config-EUVBPUUG.js} +5 -5
- package/dist/{sync-tracker-U2GYOFUO.js → sync-tracker-5FSIIAMS.js} +6 -6
- package/dist/{test-execution-6LIPMBIH.js → test-execution-HASVO6EL.js} +8 -7
- package/dist/{test-execution-6LIPMBIH.js.map → test-execution-HASVO6EL.js.map} +1 -1
- package/dist/{test-plan-VASHZXJ7.js → test-plan-EM3PVGIX.js} +7 -6
- package/dist/{test-plan-VASHZXJ7.js.map → test-plan-EM3PVGIX.js.map} +1 -1
- package/dist/{ticket-new-3YXDIWPC.js → ticket-new-H6ZNIRS4.js} +11 -11
- package/dist/ticket-new-H6ZNIRS4.js.map +1 -0
- package/dist/{ticket-sync-LLUBXZ2R.js → ticket-sync-7QRH6PVT.js} +5 -5
- package/dist/{tracker-map-HR4MBYG5.js → tracker-map-7AGCTWBZ.js} +2 -2
- package/dist/{tracker-sync-YDICZN66.js → tracker-sync-MLVYGFQJ.js} +2 -2
- package/package.json +1 -1
- package/templates/SAFEWORD.md +2 -2
- package/templates/commands/lint.md +1 -1
- package/templates/scripts/closeout-cleanup.ts +127 -31
- package/templates/skills/bdd/SCENARIOS.md +3 -0
- package/templates/skills/bdd/TDD.md +11 -5
- package/templates/skills/closeout/SKILL.md +25 -17
- package/templates/skills/finish-review/SKILL.md +4 -3
- package/templates/skills/lint/SKILL.md +1 -1
- package/templates/skills/review-spec/SKILL.md +5 -1
- package/templates/skills/self-review/SKILL.md +2 -2
- package/templates/skills/ticket-system/SKILL.md +3 -0
- package/dist/chunk-6S7CTKGC.js +0 -128
- package/dist/chunk-6S7CTKGC.js.map +0 -1
- package/dist/chunk-BSOUMHMQ.js.map +0 -1
- package/dist/chunk-J7UDLLTK.js.map +0 -1
- package/dist/chunk-KXHVFCDT.js.map +0 -1
- package/dist/chunk-NOTBZCKG.js.map +0 -1
- package/dist/chunk-QUDIOBHP.js.map +0 -1
- package/dist/chunk-S2T356DA.js.map +0 -1
- package/dist/chunk-SME5SU3O.js.map +0 -1
- package/dist/chunk-TJ627SKI.js.map +0 -1
- package/dist/chunk-USPVNZ63.js.map +0 -1
- package/dist/chunk-V63TSN3C.js.map +0 -1
- package/dist/chunk-WRUXO3WA.js +0 -48
- package/dist/chunk-WRUXO3WA.js.map +0 -1
- package/dist/chunk-WVDRXD67.js.map +0 -1
- package/dist/codex-bootstrap-MGY2D6HU.js.map +0 -1
- package/dist/codex-hook-IPX3PDXX.js.map +0 -1
- package/dist/codify-J5ZLJ3HK.js.map +0 -1
- package/dist/commands-L4AINARC.js.map +0 -1
- package/dist/contract-KEZY6YC3.js +0 -8
- package/dist/coordinator-SA75UB3C.js.map +0 -1
- package/dist/corpus-PPOBTF4J.js +0 -15
- package/dist/job-CDADLJDF.js.map +0 -1
- package/dist/remove-E6HGNHOU.js +0 -22
- package/dist/status-7VIGNTUI.js +0 -21
- package/dist/ticket-new-3YXDIWPC.js.map +0 -1
- /package/dist/{architecture-N5ZC4CDU.js.map → architecture-RQ377ZER.js.map} +0 -0
- /package/dist/{architecture-document-UBA5UT4J.js.map → architecture-document-KS3CLSYN.js.map} +0 -0
- /package/dist/{architecture-monorepo-E4JUYJGV.js.map → architecture-monorepo-NJWWU65G.js.map} +0 -0
- /package/dist/{boundary-HLJILY7R.js.map → boundary-OPTC2RVJ.js.map} +0 -0
- /package/dist/{chunk-4CZS4YJV.js.map → chunk-3OKZ3X4O.js.map} +0 -0
- /package/dist/{chunk-4CKCRZDO.js.map → chunk-7ULZND56.js.map} +0 -0
- /package/dist/{chunk-34NCOTP5.js.map → chunk-7XELS325.js.map} +0 -0
- /package/dist/{chunk-GZ36UZJG.js.map → chunk-CFME47IY.js.map} +0 -0
- /package/dist/{chunk-BQTC6YGN.js.map → chunk-D5ENZR6N.js.map} +0 -0
- /package/dist/{chunk-ZRV7TOCX.js.map → chunk-G5AFQXXW.js.map} +0 -0
- /package/dist/{chunk-I4KBHRZW.js.map → chunk-LH2FAQTI.js.map} +0 -0
- /package/dist/{chunk-KFVEPQ7X.js.map → chunk-MVFHTUQ3.js.map} +0 -0
- /package/dist/{chunk-BAVDDAN3.js.map → chunk-MZKTOX6X.js.map} +0 -0
- /package/dist/{chunk-Q5KLE6ZF.js.map → chunk-OKPRQGFG.js.map} +0 -0
- /package/dist/{chunk-664YNAMR.js.map → chunk-RTFPKJJV.js.map} +0 -0
- /package/dist/{chunk-GKR44BCH.js.map → chunk-RVDXBHUG.js.map} +0 -0
- /package/dist/{chunk-A7Z27COA.js.map → chunk-VFWAZLEF.js.map} +0 -0
- /package/dist/{chunk-3EJNDIAO.js.map → chunk-VZ5B2SIO.js.map} +0 -0
- /package/dist/{cleanup-X556LNWM.js.map → cleanup-ELVHZPRC.js.map} +0 -0
- /package/dist/{cleanup-command-RV2Q7G72.js.map → cleanup-command-5BY4FWAT.js.map} +0 -0
- /package/dist/{clients-HP23HRN2.js.map → clients-WRPBRO6V.js.map} +0 -0
- /package/dist/{config-LUSJAK6B.js.map → config-TXJRCN3W.js.map} +0 -0
- /package/dist/{configured-paths-SPQ5XWOM.js.map → configured-paths-4CRHLBIF.js.map} +0 -0
- /package/dist/{contract-KEZY6YC3.js.map → contract-B7NDKO5B.js.map} +0 -0
- /package/dist/{corpus-PPOBTF4J.js.map → corpus-PUBXCCSN.js.map} +0 -0
- /package/dist/{doctor-DSC36R4U.js.map → doctor-RPXETRSJ.js.map} +0 -0
- /package/dist/{feature-directories-VOHVV26X.js.map → feature-directories-ASNDEM7J.js.map} +0 -0
- /package/dist/{finalization-7SMLMVLV.js.map → finalization-BGPOEBAL.js.map} +0 -0
- /package/dist/{gh-cli-ZMO7D2KE.js.map → gh-cli-OTX7PORT.js.map} +0 -0
- /package/dist/{github-rest-KGKS4V2H.js.map → github-rest-JCW32377.js.map} +0 -0
- /package/dist/{learning-sync-6BTHM6ZC.js.map → learning-sync-2WIAOTW3.js.map} +0 -0
- /package/dist/{legacy-global-guidance-2JL4Y5EB.js.map → legacy-global-guidance-WTDI53H7.js.map} +0 -0
- /package/dist/{lint-gherkin-COSHVS6Z.js.map → lint-gherkin-LS3CHW3J.js.map} +0 -0
- /package/dist/{operations-XVRQSLJG.js.map → operations-OZKEQCS4.js.map} +0 -0
- /package/dist/{output-3LB2OEHN.js.map → output-ZYTEW6SC.js.map} +0 -0
- /package/dist/{packet-5WT5M3OS.js.map → packet-7S6CZJQR.js.map} +0 -0
- /package/dist/{profile-UMKQ5JVO.js.map → profile-SDFSBKH5.js.map} +0 -0
- /package/dist/{prompt-GWYDFMLO.js.map → prompt-LYPODDC3.js.map} +0 -0
- /package/dist/{remove-E6HGNHOU.js.map → remove-P5JQNS5P.js.map} +0 -0
- /package/dist/{retro-IFSVU5KS.js.map → retro-EQK2Z2Z6.js.map} +0 -0
- /package/dist/{retro-draft-spool-4S3TCHWL.js.map → retro-draft-spool-MDPBVM6J.js.map} +0 -0
- /package/dist/{retro-extract-OSBFAXLU.js.map → retro-extract-CZMDD4WB.js.map} +0 -0
- /package/dist/{review-pr-6S2352CK.js.map → review-pr-CWRD446M.js.map} +0 -0
- /package/dist/{review-pr-publication-CGHCRRUI.js.map → review-pr-publication-AIX2U3VM.js.map} +0 -0
- /package/dist/{run-5JESKXUR.js.map → run-T45X6Z6C.js.map} +0 -0
- /package/dist/{self-report-VPHBPPSJ.js.map → self-report-V7PHKTS6.js.map} +0 -0
- /package/dist/{status-7VIGNTUI.js.map → status-F5TFEIZ6.js.map} +0 -0
- /package/dist/{status-EX4L3ELO.js.map → status-S24PDFXB.js.map} +0 -0
- /package/dist/{sync-config-O7J7IDGE.js.map → sync-config-EUVBPUUG.js.map} +0 -0
- /package/dist/{sync-tracker-U2GYOFUO.js.map → sync-tracker-5FSIIAMS.js.map} +0 -0
- /package/dist/{ticket-sync-LLUBXZ2R.js.map → ticket-sync-7QRH6PVT.js.map} +0 -0
- /package/dist/{tracker-map-HR4MBYG5.js.map → tracker-map-7AGCTWBZ.js.map} +0 -0
- /package/dist/{tracker-sync-YDICZN66.js.map → tracker-sync-MLVYGFQJ.js.map} +0 -0
package/codex-plugin/hooks.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "bunx --bun safeword@0.78.
|
|
9
|
+
"command": "bunx --bun safeword@0.78.3 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.
|
|
22
|
+
"command": "bunx --bun safeword@0.78.3 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.
|
|
35
|
+
"command": "bunx --bun safeword@0.78.3 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.
|
|
48
|
+
"command": "bunx --bun safeword@0.78.3 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.
|
|
61
|
+
"command": "bunx --bun safeword@0.78.3 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
|
|
59
|
-
|
|
60
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
69
|
-
already
|
|
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
|
-
|
|
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.
|
|
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
|
|
85
|
-
fallback and callers cannot nominate another receipt, session,
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
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
|
-
|
|
132
|
-
only the
|
|
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
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
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
|
|
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
|
|
14
|
-
|
|
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-
|
|
12
|
+
} from "./chunk-LH2FAQTI.js";
|
|
13
13
|
import {
|
|
14
14
|
discoverUnreadableWorkspaces,
|
|
15
15
|
extractMonorepoArchitectureSnapshot
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VZ5B2SIO.js";
|
|
17
17
|
import {
|
|
18
18
|
GENERATED_ARCHITECTURE_FILENAME,
|
|
19
19
|
isArchitectureDocumentEnforcementEnabled,
|
|
20
20
|
readConfiguredPath,
|
|
21
21
|
resolveGeneratedArchitecturePath,
|
|
22
22
|
toRepoDirectory
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-RVDXBHUG.js";
|
|
24
24
|
import {
|
|
25
25
|
readJson,
|
|
26
26
|
writeJson
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-HF3DXZEA.js";
|
|
28
|
+
import "./chunk-QLOUSTQE.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-
|
|
653
|
+
//# sourceMappingURL=architecture-RQ377ZER.js.map
|
|
@@ -7,11 +7,11 @@ import {
|
|
|
7
7
|
selfHeal,
|
|
8
8
|
selfHealProject,
|
|
9
9
|
selfHealProjectPreservingProse
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-LH2FAQTI.js";
|
|
11
|
+
import "./chunk-VZ5B2SIO.js";
|
|
12
|
+
import "./chunk-RVDXBHUG.js";
|
|
13
|
+
import "./chunk-HF3DXZEA.js";
|
|
14
|
+
import "./chunk-QLOUSTQE.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-
|
|
25
|
+
//# sourceMappingURL=architecture-document-KS3CLSYN.js.map
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
discoverWorkspaces,
|
|
4
4
|
extractMonorepoArchitectureSnapshot,
|
|
5
5
|
monorepoFingerprintOf
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-VZ5B2SIO.js";
|
|
7
|
+
import "./chunk-HF3DXZEA.js";
|
|
8
|
+
import "./chunk-QLOUSTQE.js";
|
|
9
9
|
export {
|
|
10
10
|
discoverUnreadableWorkspaces,
|
|
11
11
|
discoverWorkspaces,
|
|
12
12
|
extractMonorepoArchitectureSnapshot,
|
|
13
13
|
monorepoFingerprintOf
|
|
14
14
|
};
|
|
15
|
-
//# sourceMappingURL=architecture-monorepo-
|
|
15
|
+
//# sourceMappingURL=architecture-monorepo-NJWWU65G.js.map
|
|
@@ -7,25 +7,25 @@ import {
|
|
|
7
7
|
} from "./chunk-3D25MSWD.js";
|
|
8
8
|
import {
|
|
9
9
|
createPhaseAnchorScope
|
|
10
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
24
|
+
} from "./chunk-RVDXBHUG.js";
|
|
25
25
|
import {
|
|
26
26
|
readFileSafe
|
|
27
|
-
} from "./chunk-
|
|
28
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-HF3DXZEA.js";
|
|
28
|
+
import "./chunk-QLOUSTQE.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-
|
|
633
|
+
//# sourceMappingURL=boundary-OPTC2RVJ.js.map
|