safeword 0.82.3 → 0.82.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.
- package/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/codex-plugin/package.json +1 -1
- package/codex-plugin/skills/audit/SKILL.md +5 -5
- package/codex-plugin/skills/bdd/references/PLAN_IMPLEMENTATION.md +2 -2
- package/codex-plugin/skills/bdd/references/TDD.md +1 -1
- package/codex-plugin/skills/explain/SKILL.md +1 -1
- package/codex-plugin/skills/quality-review/SKILL.md +2 -2
- package/codex-plugin/skills/retro-filer/SKILL.md +2 -2
- package/codex-plugin/skills/review-spec/SKILL.md +2 -2
- package/codex-plugin/skills/self-review/SKILL.md +1 -1
- package/codex-plugin/templates/SAFEWORD.md +252 -0
- package/codex-plugin/templates/hooks/audit-principle-trace.ts +49 -0
- package/codex-plugin/templates/hooks/codex/post-tool-quality.ts +56 -0
- package/codex-plugin/templates/hooks/codex/post-tool-skill-nudge.ts +67 -0
- package/codex-plugin/templates/hooks/codex/pre-tool-quality-helpers.ts +140 -0
- package/codex-plugin/templates/hooks/codex/pre-tool-quality.ts +205 -0
- package/codex-plugin/templates/hooks/codex/stop.ts +276 -0
- package/codex-plugin/templates/hooks/cursor/after-file-edit.ts +56 -0
- package/codex-plugin/templates/hooks/cursor/before-shell-execution.ts +128 -0
- package/codex-plugin/templates/hooks/cursor/gate-adapter.ts +377 -0
- package/codex-plugin/templates/hooks/cursor/post-tool-quality.ts +56 -0
- package/codex-plugin/templates/hooks/cursor/post-tool-skill-nudge.ts +65 -0
- package/codex-plugin/templates/hooks/cursor/pre-tool-quality.ts +107 -0
- package/codex-plugin/templates/hooks/cursor/stop.ts +150 -0
- package/codex-plugin/templates/hooks/dependency-bootstrap.ts +31 -0
- package/codex-plugin/templates/hooks/lib/active-ticket.ts +497 -0
- package/codex-plugin/templates/hooks/lib/architecture-document-nudge.ts +177 -0
- package/codex-plugin/templates/hooks/lib/architecture-staged-scope.ts +165 -0
- package/codex-plugin/templates/hooks/lib/audit-scope.sh +103 -0
- package/codex-plugin/templates/hooks/lib/auto-upgrade-lock.ts +89 -0
- package/codex-plugin/templates/hooks/lib/auto-upgrade.ts +417 -0
- package/codex-plugin/templates/hooks/lib/bash-ledger-writes.ts +279 -0
- package/codex-plugin/templates/hooks/lib/blocked-on-gate.ts +106 -0
- package/codex-plugin/templates/hooks/lib/branch-staleness.ts +60 -0
- package/codex-plugin/templates/hooks/lib/checkbox-transitions.ts +79 -0
- package/codex-plugin/templates/hooks/lib/closeout-binding.ts +430 -0
- package/codex-plugin/templates/hooks/lib/cursor-run-identity.ts +290 -0
- package/codex-plugin/templates/hooks/lib/cursor-state.ts +94 -0
- package/codex-plugin/templates/hooks/lib/dependency-readiness.ts +1394 -0
- package/codex-plugin/templates/hooks/lib/dogfood.ts +30 -0
- package/codex-plugin/templates/hooks/lib/done-gate.ts +258 -0
- package/codex-plugin/templates/hooks/lib/drain-retro-spool.ts +103 -0
- package/codex-plugin/templates/hooks/lib/feature-provenance.ts +169 -0
- package/codex-plugin/templates/hooks/lib/git-operation.ts +42 -0
- package/codex-plugin/templates/hooks/lib/hierarchy.ts +217 -0
- package/codex-plugin/templates/hooks/lib/host-toolchain.ts +170 -0
- package/codex-plugin/templates/hooks/lib/impl-plan.ts +210 -0
- package/codex-plugin/templates/hooks/lib/inspiration.ts +557 -0
- package/codex-plugin/templates/hooks/lib/jsonl-spool.ts +126 -0
- package/codex-plugin/templates/hooks/lib/jtbd.ts +481 -0
- package/codex-plugin/templates/hooks/lib/learning-verification-stamps.ts +62 -0
- package/codex-plugin/templates/hooks/lib/ledger-git.ts +92 -0
- package/codex-plugin/templates/hooks/lib/ledger-validation.ts +230 -0
- package/codex-plugin/templates/hooks/lib/lint-config.ts +148 -0
- package/codex-plugin/templates/hooks/lib/lint.ts +499 -0
- package/codex-plugin/templates/hooks/lib/markdown-structure.ts +44 -0
- package/codex-plugin/templates/hooks/lib/namespace-root.ts +103 -0
- package/codex-plugin/templates/hooks/lib/parse-annotation.ts +59 -0
- package/codex-plugin/templates/hooks/lib/phase-provenance.ts +623 -0
- package/codex-plugin/templates/hooks/lib/plan-gate.ts +109 -0
- package/codex-plugin/templates/hooks/lib/principle-trace.ts +173 -0
- package/codex-plugin/templates/hooks/lib/process-kill-guard.ts +124 -0
- package/codex-plugin/templates/hooks/lib/project-knowledge.ts +39 -0
- package/codex-plugin/templates/hooks/lib/quality-state.ts +301 -0
- package/codex-plugin/templates/hooks/lib/quality.ts +616 -0
- package/codex-plugin/templates/hooks/lib/re-entry.ts +153 -0
- package/codex-plugin/templates/hooks/lib/readiness-pointer.ts +18 -0
- package/codex-plugin/templates/hooks/lib/replan-relevance.ts +215 -0
- package/codex-plugin/templates/hooks/lib/replan.ts +185 -0
- package/codex-plugin/templates/hooks/lib/retro-debug.ts +60 -0
- package/codex-plugin/templates/hooks/lib/retro-draft-spool.ts +329 -0
- package/codex-plugin/templates/hooks/lib/retro-extract.ts +674 -0
- package/codex-plugin/templates/hooks/lib/retro-filing-gate.ts +271 -0
- package/codex-plugin/templates/hooks/lib/retro-nudge.ts +92 -0
- package/codex-plugin/templates/hooks/lib/retro-trigger.ts +649 -0
- package/codex-plugin/templates/hooks/lib/review-ledger.ts +263 -0
- package/codex-plugin/templates/hooks/lib/review-trigger.ts +17 -0
- package/codex-plugin/templates/hooks/lib/run-identity.ts +156 -0
- package/codex-plugin/templates/hooks/lib/safeword-context.ts +116 -0
- package/codex-plugin/templates/hooks/lib/scenario-format.ts +25 -0
- package/codex-plugin/templates/hooks/lib/self-report.ts +599 -0
- package/codex-plugin/templates/hooks/lib/shell-segments.ts +253 -0
- package/codex-plugin/templates/hooks/lib/skill-invocation-log.ts +100 -0
- package/codex-plugin/templates/hooks/lib/skill-nudge.ts +264 -0
- package/codex-plugin/templates/hooks/lib/test-runner.ts +295 -0
- package/codex-plugin/templates/hooks/lib/typecheck-gate.ts +389 -0
- package/codex-plugin/templates/hooks/lib/update-cache.ts +165 -0
- package/codex-plugin/templates/hooks/lib/version.ts +79 -0
- package/codex-plugin/templates/hooks/lib/work-log-stamp.ts +84 -0
- package/codex-plugin/templates/hooks/post-tool-bypass-warn.ts +100 -0
- package/codex-plugin/templates/hooks/post-tool-dependency-readiness.ts +84 -0
- package/codex-plugin/templates/hooks/post-tool-lint.ts +59 -0
- package/codex-plugin/templates/hooks/post-tool-quality.ts +264 -0
- package/codex-plugin/templates/hooks/post-tool-skill-nudge.ts +177 -0
- package/codex-plugin/templates/hooks/post-tool-sync-learnings.ts +80 -0
- package/codex-plugin/templates/hooks/post-tool-work-log.ts +60 -0
- package/codex-plugin/templates/hooks/pre-tool-architecture-stage.ts +692 -0
- package/codex-plugin/templates/hooks/pre-tool-config-guard.ts +88 -0
- package/codex-plugin/templates/hooks/pre-tool-dependency-readiness.ts +83 -0
- package/codex-plugin/templates/hooks/pre-tool-git-bare-fix.sh +38 -0
- package/codex-plugin/templates/hooks/pre-tool-quality.ts +826 -0
- package/codex-plugin/templates/hooks/pre-tool-stale-main.ts +83 -0
- package/codex-plugin/templates/hooks/prompt-questions.ts +288 -0
- package/codex-plugin/templates/hooks/prompt-retro-nudge.ts +55 -0
- package/codex-plugin/templates/hooks/prompt-timestamp.ts +30 -0
- package/codex-plugin/templates/hooks/record-skill-invocation.ts +105 -0
- package/codex-plugin/templates/hooks/resolve-namespace-root.ts +15 -0
- package/codex-plugin/templates/hooks/resolve-project-knowledge.ts +10 -0
- package/codex-plugin/templates/hooks/resolve-verify-ticket.ts +271 -0
- package/codex-plugin/templates/hooks/run-review.ts +153 -0
- package/codex-plugin/templates/hooks/session-architecture-heal.ts +34 -0
- package/codex-plugin/templates/hooks/session-author-model.ts +33 -0
- package/codex-plugin/templates/hooks/session-auto-upgrade.ts +19 -0
- package/codex-plugin/templates/hooks/session-bun-check.sh +20 -0
- package/codex-plugin/templates/hooks/session-cleanup-quality.ts +28 -0
- package/codex-plugin/templates/hooks/session-codex-start.ts +40 -0
- package/codex-plugin/templates/hooks/session-compact-context.ts +88 -0
- package/codex-plugin/templates/hooks/session-cursor-auto-upgrade.ts +29 -0
- package/codex-plugin/templates/hooks/session-dependency-readiness.ts +44 -0
- package/codex-plugin/templates/hooks/session-lint-check.ts +69 -0
- package/codex-plugin/templates/hooks/session-reply-format.ts +27 -0
- package/codex-plugin/templates/hooks/session-safeword-context.ts +27 -0
- package/codex-plugin/templates/hooks/session-start-reentry.ts +103 -0
- package/codex-plugin/templates/hooks/session-version.ts +20 -0
- package/codex-plugin/templates/hooks/stop-quality.ts +925 -0
- package/codex-plugin/templates/hooks/stop-reentry.ts +138 -0
- package/codex-plugin/templates/hooks/stop-retro-filing.ts +65 -0
- package/codex-plugin/templates/hooks/stop-retro.ts +77 -0
- package/codex-plugin/templates/hooks/stop-self-report.ts +86 -0
- package/codex-plugin/templates/hooks/write-review-stamp.ts +282 -0
- package/dist/{architecture-SPLA537T.js → architecture-V6XNVK7J.js} +2 -2
- package/dist/{architecture-document-X7IACPVH.js → architecture-document-AMBH2C22.js} +2 -2
- package/dist/{architecture-monorepo-TYU665GX.js → architecture-monorepo-S3GETI3W.js} +2 -2
- package/dist/{boundary-LAP6BC2I.js → boundary-PRWLTQXI.js} +2 -2
- package/dist/{chunk-42D53GKH.js → chunk-BSBKSP54.js} +2 -2
- package/dist/{chunk-CXOSUFZO.js → chunk-F56GGOF4.js} +14 -14
- package/dist/{chunk-3OQI4CMW.js → chunk-TVNJO2EN.js} +2 -2
- package/dist/{chunk-3OQI4CMW.js.map → chunk-TVNJO2EN.js.map} +1 -1
- package/dist/{cleanup-T7RD524L.js → cleanup-POCMRGOY.js} +2 -2
- package/dist/{cleanup-command-34ARIVMG.js → cleanup-command-NMBIWBCL.js} +2 -2
- package/dist/cli.js +72 -72
- package/dist/{clients-W6LWFCYE.js → clients-ZORENKZW.js} +2 -2
- package/dist/{codex-bootstrap-BOSNKZX3.js → codex-bootstrap-DY5ZKDDU.js} +2 -2
- package/dist/{codex-hook-JZ7RFJH2.js → codex-hook-D7Z5PI56.js} +2 -2
- package/dist/{codify-FJOD3DQZ.js → codify-4EWI7RO7.js} +2 -2
- package/dist/{commands-5D3BW2QQ.js → commands-OPDQW2VC.js} +3 -3
- package/dist/{config-OKYRAPXX.js → config-C3K6XKRU.js} +2 -2
- package/dist/{configured-paths-ZBJHZ34Z.js → configured-paths-6457NJZB.js} +2 -2
- package/dist/{conformance-45CW4ADV.js → conformance-ARUIWFT5.js} +2 -2
- package/dist/{contract-23DXATJM.js → contract-H2EDHGLH.js} +2 -2
- package/dist/{coordinator-UM2RTYZJ.js → coordinator-QQ6IUSMG.js} +2 -2
- package/dist/{corpus-O7K6HKPE.js → corpus-MIZ4IKXY.js} +2 -2
- package/dist/{cursor-S3S4S5WU.js → cursor-R7HOMVFI.js} +2 -2
- package/dist/{doctor-IXLCNW7A.js → doctor-TWS4CZ4V.js} +4 -4
- package/dist/{drain-retro-spool-KYXTZIHB.js → drain-retro-spool-SVVDHTQB.js} +2 -2
- package/dist/{feature-directories-RZPGTR4Y.js → feature-directories-PFYOAAOF.js} +2 -2
- package/dist/{finalization-WZKDEEQU.js → finalization-WFNZABKW.js} +2 -2
- package/dist/{gh-cli-BTRHE2F4.js → gh-cli-GIZYMWII.js} +2 -2
- package/dist/{github-rest-2ULDQ4PI.js → github-rest-77H352TI.js} +2 -2
- package/dist/index.js +1 -1
- package/dist/{job-4HVJQNA6.js → job-VX2ZAJ5Z.js} +2 -2
- package/dist/{learning-sync-LZLJ6BSY.js → learning-sync-SN64DJ4Q.js} +2 -2
- package/dist/{legacy-global-guidance-SYVOCWCX.js → legacy-global-guidance-FJBCL3L7.js} +2 -2
- package/dist/{lint-gherkin-CS5CMDAD.js → lint-gherkin-HZHP5WBG.js} +2 -2
- package/dist/{namespace-root-MGV7337U.js → namespace-root-PJ65I3DJ.js} +2 -2
- package/dist/opencode/dispatcher.js +1 -1
- package/dist/{operations-GELN3ZW6.js → operations-EQXJ7BYM.js} +2 -2
- package/dist/{output-ZEQX6UW4.js → output-7Y6VDX5R.js} +2 -2
- package/dist/{packet-ILG65ZR4.js → packet-K34ZB2TK.js} +2 -2
- package/dist/presets/typescript/index.js +1 -1
- package/dist/{profile-TVWJ5GZC.js → profile-FWGIVRAM.js} +2 -2
- package/dist/{profile-TYVJFN3O.js → profile-VKMIMY52.js} +2 -2
- package/dist/{prompt-ONDA3ELP.js → prompt-EA5VOXUE.js} +2 -2
- package/dist/{public-retros-ECV2NINQ.js → public-retros-IC2KNXUC.js} +2 -2
- package/dist/{remove-OTCXKOV5.js → remove-LO6BIE3H.js} +2 -2
- package/dist/{retro-6UT3T23G.js → retro-OMGVS6KF.js} +8 -8
- package/dist/{retro-draft-spool-Y67X2YD5.js → retro-draft-spool-VPLRX5YF.js} +2 -2
- package/dist/{retro-drain-J6KHR7MM.js → retro-drain-MARKKH5Q.js} +3 -3
- package/dist/{retro-extract-6T6UAKVJ.js → retro-extract-SAJIQKKB.js} +2 -2
- package/dist/{review-knowledge-ZOTMWM77.js → review-knowledge-NSFPJXAA.js} +2 -2
- package/dist/{review-pr-72QYYVRG.js → review-pr-ACTDSS7E.js} +2 -2
- package/dist/{review-pr-publication-V5LSOVG4.js → review-pr-publication-5WNYDBMK.js} +2 -2
- package/dist/{run-FEQDD6O4.js → run-KRCAVD7D.js} +2 -2
- package/dist/{schema-OGK5Q44B.js → schema-2KLQRVP7.js} +2 -2
- package/dist/{self-report-7RUV6DLM.js → self-report-47Y2JICD.js} +2 -2
- package/dist/{status-ZG5ECUUS.js → status-2JYTWRI4.js} +2 -2
- package/dist/{status-2CO4D67Q.js → status-YOPKHEW5.js} +4 -4
- package/dist/{sync-config-4KUDZDP3.js → sync-config-GIHPD6UC.js} +2 -2
- package/dist/{sync-tracker-IGBQZU42.js → sync-tracker-CVV4HE77.js} +2 -2
- package/dist/{test-execution-HC2YQLAD.js → test-execution-327VEM7Y.js} +2 -2
- package/dist/{test-plan-SVOCUTOG.js → test-plan-DE5NQMVD.js} +2 -2
- package/dist/{ticket-new-BO3DPPDM.js → ticket-new-PMTEOLA4.js} +2 -2
- package/dist/{ticket-sync-H62KS5VP.js → ticket-sync-XZ2K4IEV.js} +2 -2
- package/dist/{tracker-map-NM5KPKEN.js → tracker-map-CZ5EM64B.js} +2 -2
- package/dist/{tracker-sync-JGXVL7Z2.js → tracker-sync-MU3KNTV2.js} +2 -2
- package/package.json +1 -1
- /package/dist/{architecture-SPLA537T.js.map → architecture-V6XNVK7J.js.map} +0 -0
- /package/dist/{architecture-document-X7IACPVH.js.map → architecture-document-AMBH2C22.js.map} +0 -0
- /package/dist/{architecture-monorepo-TYU665GX.js.map → architecture-monorepo-S3GETI3W.js.map} +0 -0
- /package/dist/{boundary-LAP6BC2I.js.map → boundary-PRWLTQXI.js.map} +0 -0
- /package/dist/{chunk-42D53GKH.js.map → chunk-BSBKSP54.js.map} +0 -0
- /package/dist/{chunk-CXOSUFZO.js.map → chunk-F56GGOF4.js.map} +0 -0
- /package/dist/{cleanup-T7RD524L.js.map → cleanup-POCMRGOY.js.map} +0 -0
- /package/dist/{cleanup-command-34ARIVMG.js.map → cleanup-command-NMBIWBCL.js.map} +0 -0
- /package/dist/{clients-W6LWFCYE.js.map → clients-ZORENKZW.js.map} +0 -0
- /package/dist/{codex-bootstrap-BOSNKZX3.js.map → codex-bootstrap-DY5ZKDDU.js.map} +0 -0
- /package/dist/{codex-hook-JZ7RFJH2.js.map → codex-hook-D7Z5PI56.js.map} +0 -0
- /package/dist/{codify-FJOD3DQZ.js.map → codify-4EWI7RO7.js.map} +0 -0
- /package/dist/{commands-5D3BW2QQ.js.map → commands-OPDQW2VC.js.map} +0 -0
- /package/dist/{config-OKYRAPXX.js.map → config-C3K6XKRU.js.map} +0 -0
- /package/dist/{configured-paths-ZBJHZ34Z.js.map → configured-paths-6457NJZB.js.map} +0 -0
- /package/dist/{conformance-45CW4ADV.js.map → conformance-ARUIWFT5.js.map} +0 -0
- /package/dist/{contract-23DXATJM.js.map → contract-H2EDHGLH.js.map} +0 -0
- /package/dist/{coordinator-UM2RTYZJ.js.map → coordinator-QQ6IUSMG.js.map} +0 -0
- /package/dist/{corpus-O7K6HKPE.js.map → corpus-MIZ4IKXY.js.map} +0 -0
- /package/dist/{cursor-S3S4S5WU.js.map → cursor-R7HOMVFI.js.map} +0 -0
- /package/dist/{doctor-IXLCNW7A.js.map → doctor-TWS4CZ4V.js.map} +0 -0
- /package/dist/{drain-retro-spool-KYXTZIHB.js.map → drain-retro-spool-SVVDHTQB.js.map} +0 -0
- /package/dist/{feature-directories-RZPGTR4Y.js.map → feature-directories-PFYOAAOF.js.map} +0 -0
- /package/dist/{finalization-WZKDEEQU.js.map → finalization-WFNZABKW.js.map} +0 -0
- /package/dist/{gh-cli-BTRHE2F4.js.map → gh-cli-GIZYMWII.js.map} +0 -0
- /package/dist/{github-rest-2ULDQ4PI.js.map → github-rest-77H352TI.js.map} +0 -0
- /package/dist/{job-4HVJQNA6.js.map → job-VX2ZAJ5Z.js.map} +0 -0
- /package/dist/{learning-sync-LZLJ6BSY.js.map → learning-sync-SN64DJ4Q.js.map} +0 -0
- /package/dist/{legacy-global-guidance-SYVOCWCX.js.map → legacy-global-guidance-FJBCL3L7.js.map} +0 -0
- /package/dist/{lint-gherkin-CS5CMDAD.js.map → lint-gherkin-HZHP5WBG.js.map} +0 -0
- /package/dist/{namespace-root-MGV7337U.js.map → namespace-root-PJ65I3DJ.js.map} +0 -0
- /package/dist/{operations-GELN3ZW6.js.map → operations-EQXJ7BYM.js.map} +0 -0
- /package/dist/{output-ZEQX6UW4.js.map → output-7Y6VDX5R.js.map} +0 -0
- /package/dist/{packet-ILG65ZR4.js.map → packet-K34ZB2TK.js.map} +0 -0
- /package/dist/{profile-TVWJ5GZC.js.map → profile-FWGIVRAM.js.map} +0 -0
- /package/dist/{profile-TYVJFN3O.js.map → profile-VKMIMY52.js.map} +0 -0
- /package/dist/{prompt-ONDA3ELP.js.map → prompt-EA5VOXUE.js.map} +0 -0
- /package/dist/{public-retros-ECV2NINQ.js.map → public-retros-IC2KNXUC.js.map} +0 -0
- /package/dist/{remove-OTCXKOV5.js.map → remove-LO6BIE3H.js.map} +0 -0
- /package/dist/{retro-6UT3T23G.js.map → retro-OMGVS6KF.js.map} +0 -0
- /package/dist/{retro-draft-spool-Y67X2YD5.js.map → retro-draft-spool-VPLRX5YF.js.map} +0 -0
- /package/dist/{retro-drain-J6KHR7MM.js.map → retro-drain-MARKKH5Q.js.map} +0 -0
- /package/dist/{retro-extract-6T6UAKVJ.js.map → retro-extract-SAJIQKKB.js.map} +0 -0
- /package/dist/{review-knowledge-ZOTMWM77.js.map → review-knowledge-NSFPJXAA.js.map} +0 -0
- /package/dist/{review-pr-72QYYVRG.js.map → review-pr-ACTDSS7E.js.map} +0 -0
- /package/dist/{review-pr-publication-V5LSOVG4.js.map → review-pr-publication-5WNYDBMK.js.map} +0 -0
- /package/dist/{run-FEQDD6O4.js.map → run-KRCAVD7D.js.map} +0 -0
- /package/dist/{schema-OGK5Q44B.js.map → schema-2KLQRVP7.js.map} +0 -0
- /package/dist/{self-report-7RUV6DLM.js.map → self-report-47Y2JICD.js.map} +0 -0
- /package/dist/{status-2CO4D67Q.js.map → status-2JYTWRI4.js.map} +0 -0
- /package/dist/{status-ZG5ECUUS.js.map → status-YOPKHEW5.js.map} +0 -0
- /package/dist/{sync-config-4KUDZDP3.js.map → sync-config-GIHPD6UC.js.map} +0 -0
- /package/dist/{sync-tracker-IGBQZU42.js.map → sync-tracker-CVV4HE77.js.map} +0 -0
- /package/dist/{test-execution-HC2YQLAD.js.map → test-execution-327VEM7Y.js.map} +0 -0
- /package/dist/{test-plan-SVOCUTOG.js.map → test-plan-DE5NQMVD.js.map} +0 -0
- /package/dist/{ticket-new-BO3DPPDM.js.map → ticket-new-PMTEOLA4.js.map} +0 -0
- /package/dist/{ticket-sync-H62KS5VP.js.map → ticket-sync-XZ2K4IEV.js.map} +0 -0
- /package/dist/{tracker-map-NM5KPKEN.js.map → tracker-map-CZ5EM64B.js.map} +0 -0
- /package/dist/{tracker-sync-JGXVL7Z2.js.map → tracker-sync-MU3KNTV2.js.map} +0 -0
|
@@ -561,7 +561,7 @@ Changed project learnings in the resolved namespace root's `learnings/*.md` must
|
|
|
561
561
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2> /dev/null || pwd)}"
|
|
562
562
|
source "$PROJECT_DIR/.safeword/hooks/lib/audit-scope.sh"
|
|
563
563
|
audit_scope_initialize "$PROJECT_DIR" || exit $?
|
|
564
|
-
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
564
|
+
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR")"
|
|
565
565
|
|
|
566
566
|
learning_is_in_audit_scope() {
|
|
567
567
|
[ "$AUDIT_SCOPE_MODE" = "repository" ] && return 0
|
|
@@ -721,13 +721,13 @@ audit_scope_initialize "$PROJECT_DIR" || exit $?
|
|
|
721
721
|
|
|
722
722
|
# Resolve the namespace root (honors config paths.projectRoot in real runs).
|
|
723
723
|
# Fall back on directory existence — robust when the resolver hook is absent.
|
|
724
|
-
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
724
|
+
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR" 2> /dev/null)"
|
|
725
725
|
[ -d "$NS_ROOT" ] || {
|
|
726
726
|
if [ -d "$PROJECT_DIR/.project" ]; then NS_ROOT="$PROJECT_DIR/.project"; else NS_ROOT="$PROJECT_DIR/.safeword-project"; fi
|
|
727
727
|
}
|
|
728
|
-
PERSONAS_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
729
|
-
SURFACES_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
730
|
-
GLOSSARY_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
728
|
+
PERSONAS_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR" --key personas 2> /dev/null)"
|
|
729
|
+
SURFACES_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR" --key surfaces 2> /dev/null)"
|
|
730
|
+
GLOSSARY_FILE="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR" --key glossary 2> /dev/null)"
|
|
731
731
|
[ -n "$PERSONAS_FILE" ] || PERSONAS_FILE="$NS_ROOT/personas.md"
|
|
732
732
|
[ -n "$SURFACES_FILE" ] || SURFACES_FILE="$NS_ROOT/surfaces.md"
|
|
733
733
|
[ -n "$GLOSSARY_FILE" ] || GLOSSARY_FILE="$NS_ROOT/glossary.md"
|
|
@@ -159,10 +159,10 @@ findings remain. Return findings through the typed reviewer result contract.
|
|
|
159
159
|
|
|
160
160
|
## Exit: review, then (optionally) the user
|
|
161
161
|
|
|
162
|
-
1. **Independent review first.** At review time, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
162
|
+
1. **Independent review first.** At review time, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project review-knowledge --json`. Resolve a review-capable Safeword CLI, then invoke the coordinator with the current files identified by the resolver:
|
|
163
163
|
|
|
164
164
|
```bash
|
|
165
|
-
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
165
|
+
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" review run plan-implementation --agent-handoff --json --context spec.md ticket.md feature-file principles-file personas-file surfaces-file architecture-records -- impl-plan.md
|
|
166
166
|
```
|
|
167
167
|
|
|
168
168
|
The shared coordinator sends that bounded packet to the opposite headless agent when available; its typed verdict, failure classification, and independence level are authoritative. `impl-plan.md` is the work under review; all resolved feature and project artifacts are bounded context. Only when that typed result is `REVIEW_ROUTES_EXHAUSTED`, invoke `$safeword:finish-review` immediately with the original result and the same accepted targets; return every other result unchanged and do not substitute another private subagent. Fix findings, re-resolve the sources, re-review, then stamp the exit with the returned agent provenance (`write-review-stamp.ts --author-agent "author-agent" --reviewer-agent "actual-reviewer" --independence "independence" --phase plan-implementation`, where the review gate is enabled). Add `--model` only when the executed reviewer reports a verifiable model identifier; the coordinator never invents one. Human handoff happens **only after** this review passes — raw planning output is never presented for approval. Exception, any time: information only the user has (intent, priorities, constraints not in code or docs) routes to the user the moment the gap appears — `$safeword:elicit`.
|
|
@@ -196,7 +196,7 @@ Off by default. When `.safeword/config.json` sets `architectureReviewGate: true`
|
|
|
196
196
|
2. **A fresh-context review.** Resolve a review-capable Safeword CLI, then run the shared coordinator with only the bounded design evidence:
|
|
197
197
|
|
|
198
198
|
```bash
|
|
199
|
-
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
199
|
+
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" review run plan-implementation impl-plan.md ticket-spec feature-file --agent-handoff --json
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
The shared coordinator prefers the opposite headless agent. Only when its typed result is `REVIEW_ROUTES_EXHAUSTED`, invoke `$safeword:finish-review` with the original result and the same accepted targets; return every other result unchanged. Degraded findings cannot satisfy a required independent-review gate. On an independent pass, stamp it:
|
|
@@ -39,7 +39,7 @@ Gather the durable trail safeword already keeps, then narrate it. Run:
|
|
|
39
39
|
|
|
40
40
|
```bash
|
|
41
41
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(git rev-parse --show-toplevel 2> /dev/null || pwd)}"
|
|
42
|
-
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
42
|
+
NS_ROOT="$(bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project namespace-root --cwd "$PROJECT_DIR")"
|
|
43
43
|
# What you're on now: the last re-entry line names the current ticket + Next
|
|
44
44
|
tail -3 "$NS_ROOT/re-entry.md" 2> /dev/null
|
|
45
45
|
# Fallback when re-entry is empty: in_progress tickets (not epics)
|
|
@@ -50,7 +50,7 @@ If in a BDD workflow, read the current ticket from `<namespace-root>/tickets/` a
|
|
|
50
50
|
|
|
51
51
|
### Project-principle challenge
|
|
52
52
|
|
|
53
|
-
For a BDD ticket, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
53
|
+
For a BDD ticket, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project review-knowledge --json` at the
|
|
54
54
|
start of each pass and read the current `principles`, `personas`, and `surfaces`
|
|
55
55
|
paths and content it returns (including overrides such as `paths.principles`).
|
|
56
56
|
Do not substitute labels or intake-era content.
|
|
@@ -212,7 +212,7 @@ Each pass:
|
|
|
212
212
|
guarantee a bare `safeword` on `PATH`:
|
|
213
213
|
|
|
214
214
|
```bash
|
|
215
|
-
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
215
|
+
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" review run quality-review [--context path/to/evidence] --agent-handoff --json -- changed-file [more-changed-files...]
|
|
216
216
|
```
|
|
217
217
|
|
|
218
218
|
A healthy deep review may return `REVIEW_PENDING` after its foreground
|
|
@@ -17,7 +17,7 @@ a caller-nominated path. The spool contains sanitized safeword findings for
|
|
|
17
17
|
## Procedure
|
|
18
18
|
|
|
19
19
|
1. Before reading or making any tracker call, run
|
|
20
|
-
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
20
|
+
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project retro-drain "<spool-path>" --validated-jsonl`.
|
|
21
21
|
Use only its JSONL stdout as the filing input. A nonzero exit means validation
|
|
22
22
|
failed: make no search, comment, or create call, leave the spool unchanged,
|
|
23
23
|
and report `retro-filer: cannot file - draft validation failed`. If its output
|
|
@@ -60,7 +60,7 @@ a caller-nominated path. The spool contains sanitized safeword findings for
|
|
|
60
60
|
the draft only when the append succeeded and the exact ack is visible. If the
|
|
61
61
|
append or verification fails, leave the draft in place.
|
|
62
62
|
5. Create at most five new issues per run. Drain only by running
|
|
63
|
-
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
63
|
+
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project retro-drain "<spool-path>"`; never rewrite or
|
|
64
64
|
delete the spool directly. The helper removes only drafts whose valid ack is
|
|
65
65
|
reader-visible, so unfiled or unacknowledged drafts remain. If tracker write
|
|
66
66
|
access is unavailable, leave the spool unchanged and report
|
|
@@ -35,7 +35,7 @@ Adversarially review a ticket's scenarios: treat them as if you're trying to bre
|
|
|
35
35
|
- **Manual re-run** — invoke `$safeword:review-spec` anytime after `define-behavior` (e.g., scenarios changed during implement and you want to re-validate). Allowed on a closed ticket too — a post-hoc audit is still readable.
|
|
36
36
|
|
|
37
37
|
Read the active ticket's `.feature` source first. At review time, run
|
|
38
|
-
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
38
|
+
`bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project review-knowledge --json` and read the current
|
|
39
39
|
`principles`, `personas`, and `surfaces` source paths and content it returns, so
|
|
40
40
|
the review is grounded in project knowledge rather than labels or stale intake
|
|
41
41
|
context. The resolver honors `paths.principles`, `paths.personas`, and
|
|
@@ -58,7 +58,7 @@ Resolve a review-capable Safeword CLI first; source checkouts do not guarantee
|
|
|
58
58
|
a bare `safeword` on `PATH`:
|
|
59
59
|
|
|
60
60
|
```bash
|
|
61
|
-
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
61
|
+
SAFEWORD_REVIEW_PROGRESS=1 bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" review run scenario-gate feature-file [legacy-test-definitions] --context ticket-spec [dimensions-file] principles-file personas-file surfaces-file --agent-handoff --json
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
The coordinator's assigned/actual reviewer, failure classification, and
|
|
@@ -45,7 +45,7 @@ installed helper — report it to the user and resolve before retrying.
|
|
|
45
45
|
## Review the spec (do this now, with the stamp written)
|
|
46
46
|
|
|
47
47
|
The stamp records that a review was invoked; the actual scrutiny is yours. At
|
|
48
|
-
review time, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.
|
|
48
|
+
review time, run `bun "${CODEX_HOME:-$HOME/.codex}/plugins/cache/safeword/safeword/0.82.4/runtime/cli.js" project review-knowledge --json` and use its
|
|
49
49
|
current `principles`, `personas`, and `surfaces` source paths and content—not
|
|
50
50
|
labels remembered from intake. These resolve from `paths.principles`,
|
|
51
51
|
`paths.personas`, and `paths.surfaces` when configured. Read those sources with the active ticket's
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# SAFEWORD Agent Instructions
|
|
2
|
+
|
|
3
|
+
The standing operating model for this project. Read at session start; re-scan by topic as situations arise. Project-specific rules live in `./CLAUDE.md`. Triggered playbooks live in `./.safeword/guides/`.
|
|
4
|
+
|
|
5
|
+
Project knowledge (tickets, learnings, principles, personas, glossary, surfaces) lives under the **project namespace root**: configurable via `paths.projectRoot` in `.safeword/config.json`, `.project/` by default, with legacy `.safeword-project/` honored only when that directory already exists. Paths below use `<namespace-root>` for the resolved directory.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Workflow
|
|
10
|
+
|
|
11
|
+
A safeword session runs through these phases in order. Each phase has an exit criterion — meet it before advancing.
|
|
12
|
+
|
|
13
|
+
### 1. Clarify (Propose-and-Converge)
|
|
14
|
+
|
|
15
|
+
Understand what the user is asking before classifying or building. **Propose-and-Converge** means: lead with a perspective, then surface open questions _inside_ that proposal. Don't ask first — propose first.
|
|
16
|
+
|
|
17
|
+
Each turn, restate what you heard, contribute a perspective/sketch/reframe, and surface the remaining open questions inside that contribution. Incorporate what the user confirms to narrow the open set; advance once none remain and the user accepts.
|
|
18
|
+
|
|
19
|
+
Research before proposing anything significant — and the order is load-bearing:
|
|
20
|
+
|
|
21
|
+
1. **Frame** the problem and its hard constraints: prior tickets, the data model, non-negotiable framework idioms. Don't read the soft conventions yet.
|
|
22
|
+
2. **Design the ideal.** Run `$safeword:figure-it-out` to weigh 2-3 options on correctness, simplicity, and no-bloat, and pick the best architecture _as if the codebase didn't exist_. Computing this first gives the next step a yardstick.
|
|
23
|
+
3. **Survey the existing patterns** in the area you're about to touch — now, not before. Surveying earlier anchors the design to the status quo and quietly shrinks it to match.
|
|
24
|
+
4. **Reconcile.** Conform to the existing pattern by default — deviate only when the ideal is a real improvement, not taste. When your ideal diverges from what exists, record the call: to deviate, name a concrete defect of the existing pattern the ideal fixes, the call-site count you're splitting, a one-line pre-mortem ("assume this was wrong — what broke?"), and the follow-up ticket to uplevel the rest. Reversible and local → a few lines in the ticket; irreversible or cross-cutting (data model, public API) → promote to an ADR. See `./.safeword/guides/architecture-guide.md`.
|
|
25
|
+
|
|
26
|
+
Depth scales with ambiguity. Clear request → 0 turns. One open question → 1 turn. Vague idea → 2-3 turns of increasingly specific proposals.
|
|
27
|
+
|
|
28
|
+
If the user references a ticket ID/slug or says "resume" / "continue", skip Clarify and resume at the ticket's current phase.
|
|
29
|
+
|
|
30
|
+
**Replan on resume.** The plan may be stale: a `Resume check: N commit(s)…` line means someone else's commits touched files this ticket references since you last worked on it. This is opt-in: if the user declines or just proceeds, investigate nothing. If the user accepts ("check the plan"), spawn a fresh sub-agent (`isolation: worktree`) to judge whether scope still holds and report back **in chat only** — proposing one of still-good / change-scope / cancel / split / merge, with rationale. If the verdict is change-scope or split, run `$safeword:figure-it-out` before proposing a new approach — scope changed because the world changed, which is exactly when re-deciding from memory is most dangerous. Never edit the ticket without explicit approval. If the sub-agent errors or times out, note it in one line and proceed with the work — don't retry in a loop (the heads-up won't re-fire until new commits land).
|
|
31
|
+
|
|
32
|
+
**Contribution techniques** to weave into proposals (pick the one that fits the gap):
|
|
33
|
+
|
|
34
|
+
- Failure modes — when reliability or error handling is unclear.
|
|
35
|
+
- Boundaries — when scope could expand indefinitely.
|
|
36
|
+
- Scenario walkthrough — when the description is abstract.
|
|
37
|
+
- Regret test — when deciding what stays in or out of scope.
|
|
38
|
+
- User experience — when success criteria aren't described.
|
|
39
|
+
|
|
40
|
+
Before proceeding, run the **specificity self-test**: can you describe the behavior that changes, the behavior that stays the same, and an observable "done" state? Any "no" means open questions remain — surface them.
|
|
41
|
+
|
|
42
|
+
**Readiness triage.** The five-dimension check the prompt pointer abbreviates:
|
|
43
|
+
|
|
44
|
+
- **Intent** — why, and for whom.
|
|
45
|
+
- **Done** — a measurable end-state.
|
|
46
|
+
- **Constraints** — what must not break, reversibility.
|
|
47
|
+
- **Riskiest assumption** — and the cheapest way to test it before building.
|
|
48
|
+
- **Request shape** — is this the problem, or someone's guess at the fix?
|
|
49
|
+
|
|
50
|
+
Scale depth by blast radius — reversible, local work proceeds; irreversible or high-blast work resolves the open unknowns first. You're ready when your remaining questions are about edge-cases and trade-offs, not basics. For one-way-door (irreversible) features, intake offers a deeper **cold-start executability check** at exit (`.safeword/guides/cold-start-check.md`) — a context-free agent attempts to plan the work from the captured spec alone, surfacing what it couldn't reconstruct; runnable on demand too.
|
|
51
|
+
|
|
52
|
+
**PM-grade intake** is the name for how these fit together, scaled by blast radius — one protocol, not three disconnected mechanisms:
|
|
53
|
+
|
|
54
|
+
- The readiness pointer nudges every turn.
|
|
55
|
+
- The Intake Brief (who asked · cost of inaction · reversibility) is authored for features.
|
|
56
|
+
- The cold-start executability check fires only for one-way-door work.
|
|
57
|
+
- `$safeword:elicit`, `$safeword:brainstorm`, and `$safeword:figure-it-out` get pulled in as the gaps demand (unknown intent · empty option space · options to weigh).
|
|
58
|
+
|
|
59
|
+
**Project principles.** Before choosing scope or design, read the configured
|
|
60
|
+
principles file (`paths.principles`, default `<namespace-root>/principles.md`)
|
|
61
|
+
when it exists. Apply it as a decision lens, not a checklist: a principle pays
|
|
62
|
+
rent only when it changes behavior, design, proof, or a deliberate deviation.
|
|
63
|
+
Features record applicable principles in `impl-plan.md`'s Design alignment as
|
|
64
|
+
**principle → concrete consequence → proof**. Tasks note a principle only when
|
|
65
|
+
it materially changes the task; patches apply it silently unless they need an
|
|
66
|
+
explicit exception. Never claim an experiential principle is proven by tests
|
|
67
|
+
alone — tests prove observable mechanics; user evidence proves the experience.
|
|
68
|
+
|
|
69
|
+
If the conversation feels circular, make a best-guess proposal: "Here's my best read — should I build this, or is something off?"
|
|
70
|
+
|
|
71
|
+
Exit: user accepts your proposal. For features, intake builds its artifacts in order, each anchoring the next:
|
|
72
|
+
|
|
73
|
+
1. Load personas, glossary, and surfaces from the configured project-knowledge files.
|
|
74
|
+
2. Open with a short **Intake Brief** in `spec.md` (who asked · cost of inaction · reversibility) — the framing for the decision to build, which also triages whether this is a feature or a leaner task.
|
|
75
|
+
3. Author the Jobs To Be Done in `spec.md` — one persona from the configured personas file per job, in the "When I…, I want…, so I can…" form. Jobs are outcomes the persona wants to be true; never drop or narrow one because of how it would be built. Feasibility, state, and which layer serves it are plan-implementation questions.
|
|
76
|
+
4. Decompose each job into numbered Rules — one testable invariant per `#### <jtbd-id>.R<n>`, the level that define-behavior scenarios later prove against. (Acceptance Criteria — `#### <jtbd-id>.AC<n>` — is the still-supported legacy alternative; one criteria kind per job, never both.)
|
|
77
|
+
5. Let jobs-and-rules anchor the engineering scope you write to ticket frontmatter — every resolved question produces scope (accepted choice = in scope, rejected alternative = out of scope):
|
|
78
|
+
|
|
79
|
+
- **`scope`** — what you're building (derived from accepted choices).
|
|
80
|
+
- **`out_of_scope`** — what you're not building (rejected alternatives + domain-knowledge exclusions).
|
|
81
|
+
- **`done_when`** — observable outcomes.
|
|
82
|
+
|
|
83
|
+
In define-behavior, each scenario carries its lineage `<jtbd-id>.R<#>.<scenario_name>` (snake_case; `.AC<#>` on the legacy path) so `safeword doctor` flags coverage gaps — uncovered rules, orphan scenarios. The bdd skill's DISCOVERY.md walks these sub-steps end to end with a worked example; SCENARIOS.md covers the numbering.
|
|
84
|
+
|
|
85
|
+
If the user is exploring without intent to build, follow their lead — not every conversation produces a ticket.
|
|
86
|
+
|
|
87
|
+
### 2. Classify (Sizing)
|
|
88
|
+
|
|
89
|
+
Pick the work level internally. Don't announce it as a label ("Feature detected!"); state your scope read as part of your proposal.
|
|
90
|
+
|
|
91
|
+
Three questions:
|
|
92
|
+
|
|
93
|
+
1. How many files will this touch?
|
|
94
|
+
2. Does this introduce new persistent state?
|
|
95
|
+
3. Are there multiple user flows?
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
All no or 1 file → patch (fix directly)
|
|
99
|
+
1-2 files, one testable behavior → task (TDD)
|
|
100
|
+
3+ files OR new state OR multiple flows → feature (write scenarios first)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Fallback: task. User can `$safeword:bdd` to override.
|
|
104
|
+
|
|
105
|
+
Sizing reads the jobs; it never edits them. A job that implies new state or a new flow makes the work **bigger** — that is a signal to split into an epic, never to drop the job so the work fits a smaller box. If you find yourself pruning jobs and the size falls, you sized the proposal instead of the work.
|
|
106
|
+
|
|
107
|
+
Calibration the rules don't capture:
|
|
108
|
+
|
|
109
|
+
- "Change button color to red" → task (1 file but real behavior change).
|
|
110
|
+
- "Add dark mode toggle" → feature (3+ files, new state).
|
|
111
|
+
- "Implement the fix for bug #123" → task (bug fix, despite "implement").
|
|
112
|
+
- "Build the Docker image" → patch (infrastructure, not product).
|
|
113
|
+
- "Clear pre-existing lint debt across 17 files" → task (mechanical cleanup — no behavior to discover, so the file count is noise).
|
|
114
|
+
|
|
115
|
+
### 3. Build
|
|
116
|
+
|
|
117
|
+
- **patch:** restate what you're fixing, fix it. `$safeword:bdd` to override.
|
|
118
|
+
- **task:** restate scope, run TDD (RED → GREEN → REFACTOR). `$safeword:bdd` to override.
|
|
119
|
+
- **feature:** include sizing in the proposal ("this touches N components with new state — I'd write scenarios"). Run `$safeword:bdd`; skip straight to TDD to override.
|
|
120
|
+
|
|
121
|
+
### 4. Verify
|
|
122
|
+
|
|
123
|
+
Never ask the user to test what you can test yourself. Run the relevant tests after every fix, task, or feature. Verify everything passes before claiming done.
|
|
124
|
+
|
|
125
|
+
### 5. Done
|
|
126
|
+
|
|
127
|
+
The done gate hard-blocks until `verify.md` exists in the ticket folder. Run `$safeword:verify` — it produces the artifact.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Code Philosophy
|
|
132
|
+
|
|
133
|
+
Optimize for **Clarity → Simplicity → Correctness**, in that order. When in doubt, choose the simpler solution that works today.
|
|
134
|
+
|
|
135
|
+
- **Elegant code:** readable at a glance; clear naming; minimal cognitive load.
|
|
136
|
+
- **No bloat:** delete unused code; no premature abstractions; no "just in case"; reuse existing patterns/tools before adding new ones.
|
|
137
|
+
- **Explicit errors:** every catch re-throws with context, or logs with details.
|
|
138
|
+
- **Self-documenting:** comment only the non-obvious "why" — business rules, workarounds. Wrap comments and docstrings at 100 columns.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Anti-Patterns
|
|
143
|
+
|
|
144
|
+
| Don't | Do | Why |
|
|
145
|
+
| ---------------------------- | ------------------------------------------------ | ------------------------- |
|
|
146
|
+
| `catch (e) {}` | `throw new Error(\`Failed to X: ${e.message}\`)` | Silent failures hide bugs |
|
|
147
|
+
| Utility class for 1 function | Single exported function | Abstraction without reuse |
|
|
148
|
+
| Factory for simple object | Direct construction | Indirection without value |
|
|
149
|
+
| `data`, `tmp`, `d` | `userProfile`, `pendingOrder` | Names should explain |
|
|
150
|
+
| Code "for later" | Delete it; add when needed | YAGNI |
|
|
151
|
+
| >50 lines for nice-to-have | Ask whether it's essential now | Scope creep |
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Authority: docs and research, not memory
|
|
156
|
+
|
|
157
|
+
Training data drifts. Memory of "how X worked" is not authority — the current source is.
|
|
158
|
+
|
|
159
|
+
**Library, framework, or API mechanics** (syntax, config, behavior):
|
|
160
|
+
|
|
161
|
+
1. Find the installed version — `package.json`, lockfile, `requirements.txt`, `go.mod`, `Gemfile`, `Cargo.toml`, whichever the project uses.
|
|
162
|
+
2. Read the docs for _that_ version. Use whichever source is wired up: Context7, the official docs site, the project README at the pinned ref, MDN, `node_modules/<pkg>/README.md`.
|
|
163
|
+
3. If no source is reachable or the version is ambiguous, ask before guessing.
|
|
164
|
+
|
|
165
|
+
**Adding a dependency** (a package not yet in the project) — there's no installed version to read, and the version you recall is stale by definition. Use the live `Current time:` line injected by `prompt-timestamp.ts` when the host provides one; otherwise use the current system date from the session. Then verify the current version for that date before pinning. Prefer the package manager's resolver command (`bun add <pkg>`, `npm install <pkg>`, `uv add`, `cargo add`, `go get <module>@latest`, etc.) or a registry command such as `npm view <pkg> version`, `pip index versions`, `go list -m -versions`, or crates.io. Pin what the registry reports today, never a number from memory.
|
|
166
|
+
|
|
167
|
+
**Design choices** (algorithm, architecture, security, performance, concurrency, accessibility, ML/stats) — call `$safeword:figure-it-out`. Its core rule: no recommendation without current evidence. It enumerates research domains, fetches live docs, and weighs options before committing.
|
|
168
|
+
|
|
169
|
+
Blog posts, tweets, marketing, and "I remember reading…" don't count for any tier. Treat them as leads, not evidence.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Guides
|
|
174
|
+
|
|
175
|
+
Read the matching guide when its trigger fires:
|
|
176
|
+
|
|
177
|
+
| Trigger | Guide |
|
|
178
|
+
| ---------------------------------------------------------------- | ----------------------------------------------- |
|
|
179
|
+
| Starting a feature/task OR writing specs/test-definitions | `./.safeword/guides/planning-guide.md` |
|
|
180
|
+
| Choosing test type, doing TDD, or a test is failing | `./.safeword/guides/testing-guide.md` |
|
|
181
|
+
| Creating or updating a design doc | `./.safeword/guides/design-doc-guide.md` |
|
|
182
|
+
| Making an architectural decision or writing an ADR | `./.safeword/guides/architecture-guide.md` |
|
|
183
|
+
| Understanding the generated `architecture.generated.md` doc | `./.safeword/guides/architecture-guide.md` |
|
|
184
|
+
| Data-heavy project needing formal data architecture | `./.safeword/guides/data-architecture-guide.md` |
|
|
185
|
+
| Writing learnings or agent config (CLAUDE.md, .cursor/rules) | `./.safeword/guides/llm-writing-guide.md` |
|
|
186
|
+
| Updating CLAUDE.md, SAFEWORD.md, or any context file | `./.safeword/guides/context-files-guide.md` |
|
|
187
|
+
| Hit the same bug repeatedly or discovered an undocumented gotcha | `./.safeword/guides/learning-extraction.md` |
|
|
188
|
+
| Process hanging, port in use, or zombie process suspected | `./.safeword/guides/zombie-process-cleanup.md` |
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Standing Rules
|
|
193
|
+
|
|
194
|
+
**TodoWrite.** Use for 3+ step or non-trivial work, or when the user provides multiple requests. Set it up before diving in; keep one task `in_progress` at a time; mark completed as you finish each.
|
|
195
|
+
|
|
196
|
+
**Commit frequently.** After each GREEN phase, before and after refactors, when switching tasks. The LOC gate fires near 400 lines — commit to reset it.
|
|
197
|
+
|
|
198
|
+
**Draft pull requests.** Create every pull request as a draft by default (`gh pr create --draft` on GitHub). Only create or mark a pull request ready for review when the user explicitly asks; a request to push, publish, or open a pull request does not count.
|
|
199
|
+
|
|
200
|
+
**Worktree entry (all hosts).** At session start and after moving roots or creating a worktree, run `pwd && git rev-parse --show-toplevel && git branch --show-current && git rev-parse --short HEAD` before evidence gathering or edits. Do not guess a package directory or probe a speculative path. Work from the reported repository root; use `<namespace-root>/architecture.generated.md` to find monorepo packages when present, otherwise inspect the root once. If the path, repo root, branch, or commit is wrong, stop and fix the workspace before touching files.
|
|
201
|
+
|
|
202
|
+
**Learnings.** Project-specific lessons live in `<namespace-root>/learnings/`. Before non-trivial work, scan `INDEX.md` or grep for your topic. When you solve something non-obvious, add `<slug>.md` with a `Covers:` line; `safeword project sync-learnings` regenerates the index.
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Enforcement
|
|
207
|
+
|
|
208
|
+
Safeword runs hooks each turn to track your phase and TDD step. Four gates hard-block:
|
|
209
|
+
|
|
210
|
+
- **Phase gate** — can't start TDD without `test-definitions.md`; can't create `test-definitions.md` without `scope` / `out_of_scope` / `done_when` in ticket frontmatter.
|
|
211
|
+
- **Plan gate** — a new-flow feature can't enter `implement` without a valid `impl-plan.md` (authored during the plan-implementation phase, status `planned`), and can't reach `verify`/`done` until the plan is reconciled to `implemented`.
|
|
212
|
+
- **LOC gate** — commit every ~400 lines of project code (blast-radius control).
|
|
213
|
+
- **Done gate** — can't close a ticket without `verify.md` in the ticket folder.
|
|
214
|
+
|
|
215
|
+
The prompt hook injects your current phase each turn as a reminder.
|
|
216
|
+
|
|
217
|
+
When a gate blocks, the user can run `$safeword:explain` for a plain-English version of the block — what it's asking for and how to clear it. Offer it in one line when the user seems unsure (asks "what?", pastes a block back, or stalls); stay quiet when they're moving fine. Don't make them ask twice to understand a block.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Talking to the user
|
|
222
|
+
|
|
223
|
+
This is the most-read surface of safeword. **Write to be scanned, not read.** Short replies stay short — a one-line answer needs no structure. When a reply is long enough to need structure, the user should land on the answer in seconds, see the shape at a glance, and drop into detail only when they choose to.
|
|
224
|
+
|
|
225
|
+
**Lead with the answer.** First sentence is the result, the fix, or the call. Explanation follows only if it adds something.
|
|
226
|
+
|
|
227
|
+
> Do: "Fixed — `packages/cli/src/auth.ts:42` was swallowing the refresh error."
|
|
228
|
+
> Don't: "Great question! Let me walk you through what I found..."
|
|
229
|
+
|
|
230
|
+
**End with the call.** Close by naming what's next — a question, a choice, or a proposed step; don't bury it mid-reply. For structured replies (verdicts, reviews, recommendations, audits), make that closing line a literal `**Next:** <imperative>`: the stop hook captures it verbatim for the session's re-entry brief, so the token is load-bearing, not decoration. Short conversational replies can end with the question itself.
|
|
231
|
+
|
|
232
|
+
**Debate-then-pick.** When there's a real choice, surface 2-3 options weighed in one breath, then the pick — one line each on the candidates, one on the tradeoff, one on the call. Don't ping-pong one option at a time. Skip the debate when there's no real choice (rename, mechanical edit, single obvious path).
|
|
233
|
+
|
|
234
|
+
**Frame the structural choice.** Name the architectural call ("reuse `quality-state.ts` paths vs. duplicate the list") before the surface change ("add a check"). The proposal _is_ the architectural read, not a description of what to type.
|
|
235
|
+
|
|
236
|
+
**Front-load load-bearing words.** The first two words of every line, bullet, and heading do the work — readers eye-jump down the left edge before deciding where to drop in. Start with the noun or verb that carries the meaning. "Failed because…" beats "It looks like the test failed because…"
|
|
237
|
+
|
|
238
|
+
**Speak plainly.** Use everyday words. Don't make the user learn safeword's internal vocabulary (Propose-and-Converge, sizing, gates, phases) — just describe what's happening. Prefer the plain phrase over a technical term whenever either works; reach for the term only when it's shorter or more precise than spelling it out.
|
|
239
|
+
|
|
240
|
+
**Gloss jargon at the decision point.** Don't assume the user reads code. The first time a stack or domain term is load-bearing in an _ask_ — a block, a decision, a step they must take — gloss it inline in one clause ("the refresh token (the credential that renews a login) expired"). Once per turn, never re-explained; a fluent reader skips it at no cost. Leave background narration unglossed.
|
|
241
|
+
|
|
242
|
+
**Match length to the ask.** A one-line question gets a one-line reply — no headers, no bullets, no preamble. Complex tasks get a short answer followed by the detail that supports it. Keep status updates terse and end-of-turn summaries brief — a sentence or two, not a paragraph.
|
|
243
|
+
|
|
244
|
+
**Cite code as `path:line`.** When referencing something the user might open, write `packages/cli/src/foo.ts:142` inline. Not "the foo file." Not in a code block.
|
|
245
|
+
|
|
246
|
+
**Name tickets by slug, not ID.** Refer to a ticket by its slug or title with the ID as a trailing locator — `embed-figure-it-out (ZBVGPF)`, never bare `ZBVGPF`. The 6-char code is collision-proof but unreadable; the slug is already in the folder name.
|
|
247
|
+
|
|
248
|
+
**Use structure only when it carries weight.** Headings when the reply is long enough to navigate — and make them information-carrying, not generic ("What changed" beats "Summary"). Tables only for actual reference material — never as decision trees in disguise. Bullets only when items are genuinely parallel. Default to prose. Never output a series of overly short bullet points.
|
|
249
|
+
|
|
250
|
+
**Use bold sparingly** — only where reading the bold alone would tell the story. Bold-on-every-sentence reads as noise.
|
|
251
|
+
|
|
252
|
+
**Skip:** preambles ("I'll now..."), recaps of what the user just said, sycophantic openers ("Great question!"), hedging caveats ("It depends, but..."), restating actions the user can see in the tool log.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
4
|
+
import process from 'node:process';
|
|
5
|
+
import nodePath from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { checkPrincipleTrace } from './lib/principle-trace.ts';
|
|
8
|
+
import { resolveNamespaceRoot } from './lib/namespace-root.ts';
|
|
9
|
+
|
|
10
|
+
const projectDirectory = process.argv[2] ?? process.cwd();
|
|
11
|
+
const explicitPlan = process.argv[3];
|
|
12
|
+
const plans =
|
|
13
|
+
explicitPlan === undefined ? activeImplPlans(projectDirectory) : [nodePath.resolve(explicitPlan)];
|
|
14
|
+
|
|
15
|
+
for (const planPath of plans) {
|
|
16
|
+
const plan = readFileSync(planPath, 'utf8');
|
|
17
|
+
for (const finding of checkPrincipleTrace(projectDirectory, plan)) {
|
|
18
|
+
process.stdout.write(`${finding} (${nodePath.relative(projectDirectory, planPath)})\n`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function activeImplPlans(directory: string): string[] {
|
|
23
|
+
const ticketsDirectory = nodePath.join(resolveNamespaceRoot(directory), 'tickets');
|
|
24
|
+
try {
|
|
25
|
+
return readdirSync(ticketsDirectory, { withFileTypes: true })
|
|
26
|
+
.filter(entry => entry.isDirectory())
|
|
27
|
+
.map(entry => nodePath.join(ticketsDirectory, entry.name))
|
|
28
|
+
.filter(ticketDirectory => {
|
|
29
|
+
try {
|
|
30
|
+
return /^status:\s*in_progress\s*$/mu.test(
|
|
31
|
+
readFileSync(nodePath.join(ticketDirectory, 'ticket.md'), 'utf8'),
|
|
32
|
+
);
|
|
33
|
+
} catch {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
.map(ticketDirectory => nodePath.join(ticketDirectory, 'impl-plan.md'))
|
|
38
|
+
.filter(planPath => {
|
|
39
|
+
try {
|
|
40
|
+
readFileSync(planPath, 'utf8');
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
} catch {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Safeword: Codex PostToolUse adapter — maintains quality state.
|
|
3
|
+
//
|
|
4
|
+
// The LOC blast-radius gate and the review-stamp/session-context plumbing read
|
|
5
|
+
// per-session state (LOC since last commit, active ticket binding,
|
|
6
|
+
// commit-clears-gate) that is written by the Claude post-tool-quality.ts
|
|
7
|
+
// accumulator. Codex doesn't run that Claude hook, so this adapter translates
|
|
8
|
+
// the Codex payload (notably apply_patch, whose target paths are embedded in
|
|
9
|
+
// the patch text) and spawns it as the source of truth after each edit/shell.
|
|
10
|
+
// Mirrors the Cursor postToolUse adapter; keyed on session_id to match the
|
|
11
|
+
// PreToolUse adapter's `codex-<id>` state key.
|
|
12
|
+
//
|
|
13
|
+
// Every translated target runs (each updates state); any review nudge the
|
|
14
|
+
// accumulator emits is forwarded verbatim — Codex PostToolUse shares Claude's
|
|
15
|
+
// hookSpecificOutput.additionalContext output shape.
|
|
16
|
+
|
|
17
|
+
import nodePath from 'node:path';
|
|
18
|
+
import { fileURLToPath } from 'node:url';
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
type CodexHookInput,
|
|
22
|
+
runClaudeHookAsCodex,
|
|
23
|
+
translateCodexInputToClaudeInputs,
|
|
24
|
+
} from './pre-tool-quality-helpers.ts';
|
|
25
|
+
import { installCrashCapture } from '../lib/self-report.ts';
|
|
26
|
+
|
|
27
|
+
installCrashCapture('codex-post-tool-quality', undefined, 'codex');
|
|
28
|
+
|
|
29
|
+
async function readInput(): Promise<CodexHookInput | undefined> {
|
|
30
|
+
try {
|
|
31
|
+
return JSON.parse(await Bun.stdin.text()) as CodexHookInput;
|
|
32
|
+
} catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const input = await readInput();
|
|
38
|
+
if (!input) process.exit(0);
|
|
39
|
+
|
|
40
|
+
const translatedInputs = translateCodexInputToClaudeInputs(input);
|
|
41
|
+
if (translatedInputs.length === 0) process.exit(0);
|
|
42
|
+
|
|
43
|
+
const hookDirectory = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
44
|
+
const claudeHookPath = nodePath.join(hookDirectory, '..', 'post-tool-quality.ts');
|
|
45
|
+
|
|
46
|
+
// Run ALL targets — each spawn accumulates state — then forward the first
|
|
47
|
+
// non-empty additionalContext payload.
|
|
48
|
+
const outputs = translatedInputs.map(
|
|
49
|
+
translated => runClaudeHookAsCodex(claudeHookPath, translated).stdout ?? '',
|
|
50
|
+
);
|
|
51
|
+
const firstOutput = outputs.find(output => output.trim() !== '');
|
|
52
|
+
if (firstOutput !== undefined) {
|
|
53
|
+
process.stdout.write(firstOutput);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
process.exit(0);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Safeword: Codex PostToolUse adapter for the language-skill nudge.
|
|
3
|
+
//
|
|
4
|
+
// Codex PostToolUse supports hookSpecificOutput.additionalContext (GA) — the
|
|
5
|
+
// SAME output shape the standalone post-tool-skill-nudge.ts hook already emits.
|
|
6
|
+
// So this adapter only translates Codex INPUT (notably apply_patch, whose target
|
|
7
|
+
// path is embedded in the patch text) into the Claude-shaped input the hook
|
|
8
|
+
// understands, runs it per target, and aggregates every valid nudge. Fail-open:
|
|
9
|
+
// no target / no nudge → exit 0 with no output.
|
|
10
|
+
|
|
11
|
+
import nodePath from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
type CodexHookInput,
|
|
16
|
+
runClaudeHookAsCodex,
|
|
17
|
+
translateCodexInputToClaudeInputs,
|
|
18
|
+
} from './pre-tool-quality-helpers.ts';
|
|
19
|
+
|
|
20
|
+
async function readInput(): Promise<CodexHookInput | undefined> {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(await Bun.stdin.text()) as CodexHookInput;
|
|
23
|
+
} catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function postToolAdditionalContext(stdout: string | undefined): string | undefined {
|
|
29
|
+
try {
|
|
30
|
+
const output = JSON.parse(stdout ?? '') as {
|
|
31
|
+
hookSpecificOutput?: { hookEventName?: string; additionalContext?: unknown };
|
|
32
|
+
};
|
|
33
|
+
const context = output.hookSpecificOutput?.additionalContext;
|
|
34
|
+
return output.hookSpecificOutput?.hookEventName === 'PostToolUse' && typeof context === 'string'
|
|
35
|
+
? context
|
|
36
|
+
: undefined;
|
|
37
|
+
} catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const input = await readInput();
|
|
43
|
+
if (!input) process.exit(0);
|
|
44
|
+
|
|
45
|
+
const translatedInputs = translateCodexInputToClaudeInputs(input);
|
|
46
|
+
if (translatedInputs.length === 0) process.exit(0);
|
|
47
|
+
|
|
48
|
+
const hookDirectory = nodePath.dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const claudeHookPath = nodePath.join(hookDirectory, '..', 'post-tool-skill-nudge.ts');
|
|
50
|
+
|
|
51
|
+
const contexts: string[] = [];
|
|
52
|
+
for (const translated of translatedInputs) {
|
|
53
|
+
const result = runClaudeHookAsCodex(claudeHookPath, translated);
|
|
54
|
+
const context = postToolAdditionalContext(result.stdout);
|
|
55
|
+
if (context !== undefined) contexts.push(context);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (contexts.length > 0) {
|
|
59
|
+
process.stdout.write(
|
|
60
|
+
`${JSON.stringify({
|
|
61
|
+
hookSpecificOutput: {
|
|
62
|
+
hookEventName: 'PostToolUse',
|
|
63
|
+
additionalContext: contexts.join('\n\n'),
|
|
64
|
+
},
|
|
65
|
+
})}\n`,
|
|
66
|
+
);
|
|
67
|
+
}
|