@joshuafolkken/kit 1.872.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/.claude-plugin/plugin.json +11 -0
- package/.claude/settings.json +110 -0
- package/.claude/skills/dependency-update/SKILL.md +76 -0
- package/.claude/skills/epic-commands/SKILL.md +463 -0
- package/.claude/skills/verify-ui/SKILL.md +96 -0
- package/.claude/skills/workflow-commands/SKILL.md +265 -0
- package/.claude/skills/workflow-commands/background-commands.md +130 -0
- package/.claude/skills/workflow-commands/backlogrun-child.md +364 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +345 -0
- package/.claude/skills/workflow-commands/backlogrun-park.md +179 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +600 -0
- package/.claude/skills/workflow-commands/backlogrun-steps.md +604 -0
- package/.claude/skills/workflow-commands/backlogrun.md +109 -0
- package/.claude/skills/workflow-commands/chain-rule.md +98 -0
- package/.claude/skills/workflow-commands/delegation.md +52 -0
- package/.claude/skills/workflow-commands/followup-reference.md +118 -0
- package/.claude/skills/workflow-commands/followup.md +222 -0
- package/.claude/skills/workflow-commands/fullrun-steps.md +93 -0
- package/.claude/skills/workflow-commands/fullrun.md +82 -0
- package/.claude/skills/workflow-commands/halfrun.md +73 -0
- package/.claude/skills/workflow-commands/into-target.md +48 -0
- package/.claude/skills/workflow-commands/issue-comments.md +109 -0
- package/.claude/skills/workflow-commands/issue-fold-existing.md +27 -0
- package/.claude/skills/workflow-commands/issue-scout.md +45 -0
- package/.claude/skills/workflow-commands/kickoff.md +82 -0
- package/.claude/skills/workflow-commands/latest-gate.md +85 -0
- package/.claude/skills/workflow-commands/needs-human-review.md +64 -0
- package/.claude/skills/workflow-commands/observation-filing.md +349 -0
- package/.claude/skills/workflow-commands/pre-gate-cut.md +340 -0
- package/.claude/skills/workflow-commands/prerequisite.md +62 -0
- package/.claude/skills/workflow-commands/retrospective.md +81 -0
- package/.claude/skills/workflow-commands/rule-residency.md +267 -0
- package/.claude/skills/workflow-commands/split-assessment.md +130 -0
- package/.claude/skills/workflow-commands/target-repository.md +58 -0
- package/.claude/skills/workflow-commands/working-tree-hold.md +66 -0
- package/.claude-plugin/marketplace.json +15 -0
- package/.coderabbit.yaml +50 -0
- package/.codex/config.toml +8 -0
- package/.codex/hooks.json +71 -0
- package/.cursorrules +45 -0
- package/.gitattributes +7 -0
- package/.github/dependabot.yml +19 -0
- package/.github/pull_request_template.md +1 -0
- package/.github/release.yml +18 -0
- package/.github/workflows/auto-tag.yml +111 -0
- package/.github/workflows/ci.yml +681 -0
- package/.github/workflows/dependabot-auto-merge.yml +55 -0
- package/.github/workflows/production.yml +47 -0
- package/.github/workflows/publish.yml +39 -0
- package/.github/workflows/sonar-qube.yml +34 -0
- package/.mcp.json +8 -0
- package/.ncurc.json +3 -0
- package/.prettierignore +20 -0
- package/.vscode/extensions.json +21 -0
- package/.vscode/settings.json +41 -0
- package/AGENTS.md +29 -0
- package/CLAUDE.md +207 -0
- package/CODE_OF_CONDUCT.md +132 -0
- package/GEMINI.md +30 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/SECURITY.md +34 -0
- package/cspell/index.yaml +177 -0
- package/dist/CLAUDE.md +207 -0
- package/dist/config-merge/index.d.ts +29 -0
- package/dist/config-merge/index.js +459 -0
- package/dist/hooks/batch-guard.js +28 -0
- package/dist/hooks/chunk-25JL6FMS.js +4970 -0
- package/dist/hooks/chunk-2ANGT3XM.js +375 -0
- package/dist/hooks/chunk-2EI5GBSW.js +42 -0
- package/dist/hooks/chunk-2OT5XE2N.js +5014 -0
- package/dist/hooks/chunk-2RUPMGGV.js +137 -0
- package/dist/hooks/chunk-2XIGZQMQ.js +3299 -0
- package/dist/hooks/chunk-33ELOKEV.js +910 -0
- package/dist/hooks/chunk-33YRTKM7.js +230 -0
- package/dist/hooks/chunk-36JQU5NN.js +77 -0
- package/dist/hooks/chunk-3EJBTWVS.js +1769 -0
- package/dist/hooks/chunk-3FK5SFAC.js +432 -0
- package/dist/hooks/chunk-3PWPYDD2.js +240 -0
- package/dist/hooks/chunk-3TQU7TDH.js +375 -0
- package/dist/hooks/chunk-3TVLSFZ6.js +432 -0
- package/dist/hooks/chunk-3VXYCB4E.js +77 -0
- package/dist/hooks/chunk-44M6JXGV.js +3398 -0
- package/dist/hooks/chunk-46EEEHC3.js +240 -0
- package/dist/hooks/chunk-4A7UVP2P.js +364 -0
- package/dist/hooks/chunk-4LFQEZS4.js +137 -0
- package/dist/hooks/chunk-4OCX3V2T.js +469 -0
- package/dist/hooks/chunk-4OHA5DE7.js +49 -0
- package/dist/hooks/chunk-4PMDW3YD.js +68 -0
- package/dist/hooks/chunk-4QHBNAI4.js +68 -0
- package/dist/hooks/chunk-4SSB3FEE.js +3273 -0
- package/dist/hooks/chunk-5A2WQ2CQ.js +5390 -0
- package/dist/hooks/chunk-5EVA2JQB.js +5390 -0
- package/dist/hooks/chunk-5P7VF5VE.js +3230 -0
- package/dist/hooks/chunk-5QWJGGZP.js +49 -0
- package/dist/hooks/chunk-5U5EZYG6.js +77 -0
- package/dist/hooks/chunk-5VUUF3ZV.js +240 -0
- package/dist/hooks/chunk-5WA7UBT3.js +374 -0
- package/dist/hooks/chunk-6EBGRQ3Q.js +301 -0
- package/dist/hooks/chunk-6TVHWMD3.js +432 -0
- package/dist/hooks/chunk-6V5OPIUU.js +13 -0
- package/dist/hooks/chunk-6VAGLEMB.js +68 -0
- package/dist/hooks/chunk-75BTXKFJ.js +3424 -0
- package/dist/hooks/chunk-75RHN67S.js +137 -0
- package/dist/hooks/chunk-76KC3BDD.js +3414 -0
- package/dist/hooks/chunk-76SLS7CZ.js +898 -0
- package/dist/hooks/chunk-7DHZ4DWT.js +5015 -0
- package/dist/hooks/chunk-7INSJDGE.js +458 -0
- package/dist/hooks/chunk-7VJ4FTDX.js +268 -0
- package/dist/hooks/chunk-7XCYNHQK.js +77 -0
- package/dist/hooks/chunk-A5YJ3H7E.js +375 -0
- package/dist/hooks/chunk-AAEXXUUL.js +268 -0
- package/dist/hooks/chunk-ABVEVV2M.js +432 -0
- package/dist/hooks/chunk-ACN3YXFL.js +68 -0
- package/dist/hooks/chunk-AD3XE3QZ.js +397 -0
- package/dist/hooks/chunk-AENFZPZH.js +230 -0
- package/dist/hooks/chunk-AFKRFQ6W.js +68 -0
- package/dist/hooks/chunk-AHD5IPWI.js +375 -0
- package/dist/hooks/chunk-AMK5JGV7.js +77 -0
- package/dist/hooks/chunk-ARN7NCQI.js +425 -0
- package/dist/hooks/chunk-AUFY653N.js +3425 -0
- package/dist/hooks/chunk-AXQBNFEF.js +375 -0
- package/dist/hooks/chunk-AYC7R6U4.js +3316 -0
- package/dist/hooks/chunk-AYEA2FJ7.js +5015 -0
- package/dist/hooks/chunk-B2LIXYFL.js +77 -0
- package/dist/hooks/chunk-B4HPNY2I.js +375 -0
- package/dist/hooks/chunk-B4YNCUGB.js +469 -0
- package/dist/hooks/chunk-B57S3VWT.js +922 -0
- package/dist/hooks/chunk-BINZ3PLI.js +364 -0
- package/dist/hooks/chunk-BIWLABFK.js +432 -0
- package/dist/hooks/chunk-BODUSXKK.js +410 -0
- package/dist/hooks/chunk-BQBAT2YK.js +375 -0
- package/dist/hooks/chunk-BUJEBW75.js +391 -0
- package/dist/hooks/chunk-BVNWORKA.js +72 -0
- package/dist/hooks/chunk-BWI47LQS.js +5205 -0
- package/dist/hooks/chunk-C25HRMJX.js +137 -0
- package/dist/hooks/chunk-CBFZNC74.js +375 -0
- package/dist/hooks/chunk-CECYXS4Y.js +3424 -0
- package/dist/hooks/chunk-CELGUP5F.js +49 -0
- package/dist/hooks/chunk-CMHANU3F.js +3442 -0
- package/dist/hooks/chunk-CMN372LI.js +68 -0
- package/dist/hooks/chunk-CPGZLMMK.js +3299 -0
- package/dist/hooks/chunk-CTQKXDC7.js +268 -0
- package/dist/hooks/chunk-CYAT4RIT.js +68 -0
- package/dist/hooks/chunk-CYTWYCH2.js +5014 -0
- package/dist/hooks/chunk-CZSOLRBA.js +77 -0
- package/dist/hooks/chunk-D2PIDYJR.js +3438 -0
- package/dist/hooks/chunk-DE57HI6T.js +137 -0
- package/dist/hooks/chunk-DGXDGAPG.js +5306 -0
- package/dist/hooks/chunk-DNYRSYQG.js +5014 -0
- package/dist/hooks/chunk-DTAXH2A2.js +240 -0
- package/dist/hooks/chunk-E2IZUWI5.js +375 -0
- package/dist/hooks/chunk-E4L2K2BL.js +397 -0
- package/dist/hooks/chunk-E55NKX5F.js +68 -0
- package/dist/hooks/chunk-ECXVCCVD.js +3079 -0
- package/dist/hooks/chunk-EPHO443D.js +68 -0
- package/dist/hooks/chunk-EUFK2BI2.js +375 -0
- package/dist/hooks/chunk-EYCD5ZAV.js +137 -0
- package/dist/hooks/chunk-F2SDYJU4.js +240 -0
- package/dist/hooks/chunk-F4B5D5TF.js +68 -0
- package/dist/hooks/chunk-FGEO3NDX.js +432 -0
- package/dist/hooks/chunk-FJYI52RE.js +137 -0
- package/dist/hooks/chunk-FXAKJKTB.js +18 -0
- package/dist/hooks/chunk-FYTZHIY4.js +3085 -0
- package/dist/hooks/chunk-G7JL2A5K.js +375 -0
- package/dist/hooks/chunk-GA3ITDBW.js +42 -0
- package/dist/hooks/chunk-GDR4H4SV.js +469 -0
- package/dist/hooks/chunk-GFKDXPSM.js +2855 -0
- package/dist/hooks/chunk-GIMRTKFU.js +566 -0
- package/dist/hooks/chunk-GOPHRLGO.js +240 -0
- package/dist/hooks/chunk-GX4HO7SJ.js +230 -0
- package/dist/hooks/chunk-GXKKK23T.js +240 -0
- package/dist/hooks/chunk-GZ6FUVIK.js +566 -0
- package/dist/hooks/chunk-H5HPY5M5.js +2869 -0
- package/dist/hooks/chunk-HCF3OGEE.js +1829 -0
- package/dist/hooks/chunk-HDEXAOUM.js +469 -0
- package/dist/hooks/chunk-HM2TY3TN.js +469 -0
- package/dist/hooks/chunk-HOA7NXA2.js +55 -0
- package/dist/hooks/chunk-HOFEWH6H.js +240 -0
- package/dist/hooks/chunk-HUUI6S5J.js +2669 -0
- package/dist/hooks/chunk-I4D3NVUD.js +469 -0
- package/dist/hooks/chunk-I4Q6WAJE.js +68 -0
- package/dist/hooks/chunk-IB6N4CR2.js +432 -0
- package/dist/hooks/chunk-IFLDYJMD.js +469 -0
- package/dist/hooks/chunk-IGU466YD.js +77 -0
- package/dist/hooks/chunk-IJCQUHKY.js +375 -0
- package/dist/hooks/chunk-IKUMBDJB.js +230 -0
- package/dist/hooks/chunk-IM3BDIBJ.js +5005 -0
- package/dist/hooks/chunk-IMYMAODK.js +3431 -0
- package/dist/hooks/chunk-IN2ZVGXA.js +5005 -0
- package/dist/hooks/chunk-ITVJ2MKQ.js +18 -0
- package/dist/hooks/chunk-J5RIJYTM.js +2669 -0
- package/dist/hooks/chunk-JFLMH4K5.js +3460 -0
- package/dist/hooks/chunk-JR25IFML.js +77 -0
- package/dist/hooks/chunk-JT5AUXFI.js +432 -0
- package/dist/hooks/chunk-JY5YVN6N.js +3234 -0
- package/dist/hooks/chunk-K5Q4ETVI.js +391 -0
- package/dist/hooks/chunk-K67V2F24.js +137 -0
- package/dist/hooks/chunk-KABG6AEW.js +3460 -0
- package/dist/hooks/chunk-KATZESEC.js +3273 -0
- package/dist/hooks/chunk-KFH4H7W7.js +469 -0
- package/dist/hooks/chunk-KMUEI6RX.js +910 -0
- package/dist/hooks/chunk-KMV4OY77.js +3438 -0
- package/dist/hooks/chunk-KQAZNWEY.js +137 -0
- package/dist/hooks/chunk-KZZR6JER.js +5015 -0
- package/dist/hooks/chunk-LAR6DREP.js +77 -0
- package/dist/hooks/chunk-LNCJWEZD.js +5015 -0
- package/dist/hooks/chunk-LRYD2GLM.js +6 -0
- package/dist/hooks/chunk-LXBKYHDV.js +77 -0
- package/dist/hooks/chunk-LYLKIUNE.js +5024 -0
- package/dist/hooks/chunk-LZKCFOVC.js +432 -0
- package/dist/hooks/chunk-M4FCIYRI.js +77 -0
- package/dist/hooks/chunk-M5M7327Q.js +3425 -0
- package/dist/hooks/chunk-MF72MHSX.js +3455 -0
- package/dist/hooks/chunk-MK56LKDO.js +397 -0
- package/dist/hooks/chunk-N3MJADY7.js +240 -0
- package/dist/hooks/chunk-NFQSUDBN.js +458 -0
- package/dist/hooks/chunk-NHREKY45.js +137 -0
- package/dist/hooks/chunk-NP5TTAAW.js +375 -0
- package/dist/hooks/chunk-NQTLTKTJ.js +2993 -0
- package/dist/hooks/chunk-NVRCZPBZ.js +391 -0
- package/dist/hooks/chunk-O46HMMLJ.js +469 -0
- package/dist/hooks/chunk-OFJGH2L4.js +240 -0
- package/dist/hooks/chunk-OLFMCZH5.js +240 -0
- package/dist/hooks/chunk-OMCZS46I.js +49 -0
- package/dist/hooks/chunk-OQZEZW5G.js +469 -0
- package/dist/hooks/chunk-P2MDAT2Y.js +1897 -0
- package/dist/hooks/chunk-P3M2JJIF.js +68 -0
- package/dist/hooks/chunk-PDVHQITQ.js +3453 -0
- package/dist/hooks/chunk-PNT2AMDH.js +391 -0
- package/dist/hooks/chunk-PR2LVSY6.js +3445 -0
- package/dist/hooks/chunk-PRR5R4JK.js +137 -0
- package/dist/hooks/chunk-PXT44QVN.js +566 -0
- package/dist/hooks/chunk-PZLWJLAP.js +469 -0
- package/dist/hooks/chunk-Q2FEAZJ2.js +77 -0
- package/dist/hooks/chunk-Q32WETDO.js +3265 -0
- package/dist/hooks/chunk-Q45DUBLE.js +3600 -0
- package/dist/hooks/chunk-Q7NZSWQ5.js +240 -0
- package/dist/hooks/chunk-QH2JNAMK.js +3085 -0
- package/dist/hooks/chunk-QNNWYQ2R.js +375 -0
- package/dist/hooks/chunk-QPU5H2OS.js +68 -0
- package/dist/hooks/chunk-QRAHZ5TO.js +1829 -0
- package/dist/hooks/chunk-QUZ5HPIE.js +469 -0
- package/dist/hooks/chunk-QVCRG34O.js +2893 -0
- package/dist/hooks/chunk-R3MY4E3S.js +1675 -0
- package/dist/hooks/chunk-R6TXJJXP.js +77 -0
- package/dist/hooks/chunk-REJU6VT7.js +1829 -0
- package/dist/hooks/chunk-REQAQLRC.js +2993 -0
- package/dist/hooks/chunk-RFCXPAHH.js +391 -0
- package/dist/hooks/chunk-RHI6Y22X.js +137 -0
- package/dist/hooks/chunk-RKZVOBBS.js +469 -0
- package/dist/hooks/chunk-RL57TT2Y.js +566 -0
- package/dist/hooks/chunk-RORDOD4S.js +3321 -0
- package/dist/hooks/chunk-RZKYW5P2.js +77 -0
- package/dist/hooks/chunk-SJPJ6VSI.js +391 -0
- package/dist/hooks/chunk-SKSIJQQQ.js +432 -0
- package/dist/hooks/chunk-SSQDZKXG.js +268 -0
- package/dist/hooks/chunk-SSX23SJ2.js +89 -0
- package/dist/hooks/chunk-SYHFKE4C.js +77 -0
- package/dist/hooks/chunk-TCGNI2ZY.js +42 -0
- package/dist/hooks/chunk-TG3WXJF5.js +137 -0
- package/dist/hooks/chunk-TH7IJAY5.js +77 -0
- package/dist/hooks/chunk-TLZ27PCY.js +240 -0
- package/dist/hooks/chunk-U652FXTN.js +566 -0
- package/dist/hooks/chunk-UEK47YUF.js +268 -0
- package/dist/hooks/chunk-UIO45H3O.js +432 -0
- package/dist/hooks/chunk-UNLZEEVH.js +5005 -0
- package/dist/hooks/chunk-UNRVF3SZ.js +432 -0
- package/dist/hooks/chunk-USLFAFOI.js +3453 -0
- package/dist/hooks/chunk-VAEELMLL.js +442 -0
- package/dist/hooks/chunk-VALSWLDQ.js +3453 -0
- package/dist/hooks/chunk-VC5JEPNY.js +3398 -0
- package/dist/hooks/chunk-VEZVK6C7.js +230 -0
- package/dist/hooks/chunk-VK5JKFAR.js +49 -0
- package/dist/hooks/chunk-VNF2KP7Z.js +469 -0
- package/dist/hooks/chunk-VWWCUMW6.js +2669 -0
- package/dist/hooks/chunk-W4JARUQV.js +137 -0
- package/dist/hooks/chunk-WCYPBPJC.js +5014 -0
- package/dist/hooks/chunk-WEOBMNJG.js +2993 -0
- package/dist/hooks/chunk-WKJU3J5Y.js +5390 -0
- package/dist/hooks/chunk-WMN4TSVF.js +3299 -0
- package/dist/hooks/chunk-WNON54PT.js +3469 -0
- package/dist/hooks/chunk-WOVKBPPX.js +137 -0
- package/dist/hooks/chunk-WRVFORYJ.js +432 -0
- package/dist/hooks/chunk-WUBVYGQZ.js +240 -0
- package/dist/hooks/chunk-WWULTUOM.js +68 -0
- package/dist/hooks/chunk-WXHKKB45.js +4962 -0
- package/dist/hooks/chunk-XAI3YTHJ.js +469 -0
- package/dist/hooks/chunk-XFZH6JZJ.js +77 -0
- package/dist/hooks/chunk-XGPWX6IA.js +137 -0
- package/dist/hooks/chunk-XIXXIVGY.js +566 -0
- package/dist/hooks/chunk-XKDOYJGA.js +922 -0
- package/dist/hooks/chunk-YALTVBHM.js +432 -0
- package/dist/hooks/chunk-YEBEPBFK.js +5014 -0
- package/dist/hooks/chunk-YI2BQ3DK.js +3441 -0
- package/dist/hooks/chunk-YVNBCFGG.js +1829 -0
- package/dist/hooks/chunk-YXBN3RGG.js +432 -0
- package/dist/hooks/chunk-Z2OOJSW3.js +3163 -0
- package/dist/hooks/chunk-ZA3HVBOY.js +2644 -0
- package/dist/hooks/chunk-ZKID46U3.js +137 -0
- package/dist/hooks/chunk-ZPMU2JV6.js +49 -0
- package/dist/hooks/chunk-ZRKY4W7O.js +432 -0
- package/dist/hooks/chunk-ZTMRB7LJ.js +268 -0
- package/dist/hooks/chunk-ZVPPBQ3L.js +3413 -0
- package/dist/hooks/codex-hook-adapter.js +164 -0
- package/dist/hooks/duplicate-read-guard.js +29 -0
- package/dist/hooks/format-edited.js +37 -0
- package/dist/hooks/investigation-guard.js +31 -0
- package/dist/hooks/pretool-guard.js +21 -0
- package/dist/hooks/session-lang.js +34 -0
- package/dist/hooks/stop-guard.js +1597 -0
- package/dist/josh.js +1795 -0
- package/dist/managed-marker/index.d.ts +10 -0
- package/dist/managed-marker/index.js +32 -0
- package/dist/self-sync-guard/index.d.ts +10 -0
- package/dist/self-sync-guard/index.js +49 -0
- package/dist/version/index.d.ts +93 -0
- package/dist/version/index.js +1024 -0
- package/env/index.d.ts +7 -0
- package/env/index.js +62 -0
- package/eslint/base.js +233 -0
- package/eslint/checkout-rooted-parser.js +34 -0
- package/eslint/config-fingerprint.js +103 -0
- package/eslint/rules/code-quality.js +292 -0
- package/eslint/rules/english-only-prose.js +135 -0
- package/eslint/rules/formatting.js +44 -0
- package/eslint/rules/import.js +83 -0
- package/eslint/rules/namespace-object-export.js +107 -0
- package/eslint/rules/naming-convention.js +109 -0
- package/eslint/rules/promise.js +17 -0
- package/eslint/rules/sonarjs.js +45 -0
- package/eslint/rules/test-filename.js +91 -0
- package/eslint/rules/typescript.js +186 -0
- package/eslint/rules/unicorn.js +191 -0
- package/eslint/vanilla.js +1 -0
- package/evals/scenarios/consult-not-execute.json +20 -0
- package/evals/scenarios/no-implicit-workflow.json +26 -0
- package/evals/scenarios/overrides-both-locations.json +29 -0
- package/evals/scenarios/upstream-interrupt.json +23 -0
- package/evals/scenarios/workflow-skill-loaded.json +16 -0
- package/lefthook/base.yml +131 -0
- package/lefthook/vanilla.yml +7 -0
- package/package.json +169 -0
- package/playwright.config.ts +160 -0
- package/pnpm-workspace.yaml +41 -0
- package/ports/index.d.ts +17 -0
- package/ports/index.js +256 -0
- package/prettier/index.d.ts +3 -0
- package/prettier/index.js +31 -0
- package/prompts/agent-lint-protocol.json +79 -0
- package/prompts/agent-rules.md +63 -0
- package/prompts/coding-standards.md +382 -0
- package/prompts/collaboration-workflow/consultation-vs-execution.md +8 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +54 -0
- package/prompts/collaboration-workflow/distributed-docs.md +7 -0
- package/prompts/collaboration-workflow/durable-rules.md +24 -0
- package/prompts/collaboration-workflow/epic-audit.md +56 -0
- package/prompts/collaboration-workflow/epic-bundle.md +109 -0
- package/prompts/collaboration-workflow/file-edits.md +124 -0
- package/prompts/collaboration-workflow/gh-rest.md +57 -0
- package/prompts/collaboration-workflow/issue-citation.md +38 -0
- package/prompts/collaboration-workflow/issue-template.md +190 -0
- package/prompts/collaboration-workflow/latest-first.md +14 -0
- package/prompts/collaboration-workflow/no-clones.md +11 -0
- package/prompts/collaboration-workflow/operating-rules.md +123 -0
- package/prompts/collaboration-workflow/output-bounds.md +107 -0
- package/prompts/collaboration-workflow/overview.md +35 -0
- package/prompts/collaboration-workflow/plan-comment.md +85 -0
- package/prompts/collaboration-workflow/proposal-request.md +23 -0
- package/prompts/collaboration-workflow/report-format.md +206 -0
- package/prompts/collaboration-workflow/residency.md +94 -0
- package/prompts/collaboration-workflow/rule-delivery.md +146 -0
- package/prompts/collaboration-workflow/shell-body.md +82 -0
- package/prompts/collaboration-workflow/simplicity-first.md +9 -0
- package/prompts/collaboration-workflow/single-source-rules.md +13 -0
- package/prompts/collaboration-workflow/turn-batching.md +137 -0
- package/prompts/collaboration-workflow/upstream-interrupt.md +51 -0
- package/prompts/collaboration-workflow/wip-cap.md +118 -0
- package/prompts/collaboration-workflow.md +52 -0
- package/prompts/refactoring.md +103 -0
- package/prompts/review-rubric.md +338 -0
- package/prompts/review.md +217 -0
- package/prompts/sonar-hotspot-handling.md +77 -0
- package/prompts/testing-guide.md +277 -0
- package/scripts/adopt/adopt-logic.ts +107 -0
- package/scripts/adopt/adopt-toolkits.ts +181 -0
- package/scripts/adopt/adopt.ts +171 -0
- package/scripts/agent/agent-argv.ts +140 -0
- package/scripts/agent/agent-diagnostics.ts +120 -0
- package/scripts/agent/agent-event.ts +173 -0
- package/scripts/agent/agent-exit-record.ts +32 -0
- package/scripts/agent/agent-launch-environment.ts +71 -0
- package/scripts/agent/agent-role-profile.ts +329 -0
- package/scripts/agent/api-outage.ts +51 -0
- package/scripts/agent/claude-agent-argv.ts +151 -0
- package/scripts/agent/claude-result-event.ts +98 -0
- package/scripts/agent/codex-agent-argv.ts +94 -0
- package/scripts/agent/codex-home-source.ts +11 -0
- package/scripts/agent/interactive-ask.ts +91 -0
- package/scripts/auto-ok/auto-ok-cli.ts +516 -0
- package/scripts/backlog/backlog-arrival.ts +147 -0
- package/scripts/backlog/backlog-budget-cli.ts +220 -0
- package/scripts/backlog/backlog-budget.ts +284 -0
- package/scripts/backlog/backlog-defect-priority.ts +77 -0
- package/scripts/backlog/backlog-drive-cli.ts +377 -0
- package/scripts/backlog/backlog-drive-finish.ts +23 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +81 -0
- package/scripts/backlog/backlog-drive-named.ts +101 -0
- package/scripts/backlog/backlog-drive-offer-argv.ts +29 -0
- package/scripts/backlog/backlog-drive-owner.ts +22 -0
- package/scripts/backlog/backlog-drive-restore.ts +67 -0
- package/scripts/backlog/backlog-drive.ts +322 -0
- package/scripts/backlog/backlog-named.ts +164 -0
- package/scripts/backlog/backlog-next.ts +376 -0
- package/scripts/backlog/backlog-offer-cli.ts +279 -0
- package/scripts/backlog/backlog-offer.ts +93 -0
- package/scripts/backlog/backlog-plan-cli.ts +235 -0
- package/scripts/backlog/backlog-plan.ts +231 -0
- package/scripts/backlog/backlog-pool.ts +322 -0
- package/scripts/backlog/backlog-ready.ts +146 -0
- package/scripts/backlog/backlog-scope.ts +144 -0
- package/scripts/backlog/backlog-stalled-cli.ts +30 -0
- package/scripts/backlog/backlog-stalled-detect.ts +143 -0
- package/scripts/backlog/backlog-stalled.ts +118 -0
- package/scripts/behavior/behavior-assertion.ts +87 -0
- package/scripts/behavior/behavior-cli.ts +88 -0
- package/scripts/behavior/behavior-rules.ts +128 -0
- package/scripts/build/build-bin.ts +36 -0
- package/scripts/build/build-claude-md.ts +42 -0
- package/scripts/build/build-config-merge.ts +26 -0
- package/scripts/build/build-hooks.ts +79 -0
- package/scripts/build/build-library.ts +83 -0
- package/scripts/build/build-managed-marker.ts +26 -0
- package/scripts/build/build-self-sync-guard.ts +26 -0
- package/scripts/build/build-version.ts +25 -0
- package/scripts/build/local-bin.ts +97 -0
- package/scripts/build/shim-shell.ts +25 -0
- package/scripts/bytes/bytes-command.ts +181 -0
- package/scripts/cases/cases-cli.ts +48 -0
- package/scripts/cases/cases-logic.ts +100 -0
- package/scripts/claude/skill-meta.ts +37 -0
- package/scripts/claude/workflow-destination.ts +13 -0
- package/scripts/clone/clone-aggregate.ts +76 -0
- package/scripts/clone/clone-fingerprint.ts +96 -0
- package/scripts/clone/clone-scan-cli.ts +39 -0
- package/scripts/clone/clone-scan.ts +158 -0
- package/scripts/config-merge/index.ts +19 -0
- package/scripts/config-merge/json-format.ts +128 -0
- package/scripts/config-merge/list-patch.ts +61 -0
- package/scripts/config-merge/parse-jsonc.ts +14 -0
- package/scripts/config-merge/patch-json-key.ts +439 -0
- package/scripts/config-merge/patch-json-list.ts +38 -0
- package/scripts/config-merge/patch-yaml-list.ts +107 -0
- package/scripts/cost-runtime/codex-usage.ts +119 -0
- package/scripts/cost-runtime/context-cut-payback.ts +77 -0
- package/scripts/cost-runtime/context-cut-threshold.ts +21 -0
- package/scripts/cost-runtime/cost-attribute.ts +168 -0
- package/scripts/cost-runtime/cost-blocks.ts +149 -0
- package/scripts/cost-runtime/cost-cli.ts +318 -0
- package/scripts/cost-runtime/cost-corpus.ts +278 -0
- package/scripts/cost-runtime/cost-format.ts +32 -0
- package/scripts/cost-runtime/cost-pricing.ts +176 -0
- package/scripts/cost-runtime/cost-tokens.ts +84 -0
- package/scripts/cost-runtime/cost-transcript.ts +531 -0
- package/scripts/cost-runtime/cost-usage.ts +287 -0
- package/scripts/cost-runtime/cost-verdict.ts +89 -0
- package/scripts/cost-runtime/own-session.ts +58 -0
- package/scripts/cost-runtime/transcript-cwd.ts +14 -0
- package/scripts/delegation/delegation-cli.ts +91 -0
- package/scripts/delegation/delegation-policy.ts +178 -0
- package/scripts/delegation/duplicate-read-guard.ts +244 -0
- package/scripts/delegation/fanout-cli.ts +61 -0
- package/scripts/delegation/fanout.ts +95 -0
- package/scripts/delegation/investigation-guard.ts +131 -0
- package/scripts/delegation/investigation-reads.ts +637 -0
- package/scripts/discovery/repo-discovery.ts +166 -0
- package/scripts/discovery/repo-map-logic.ts +102 -0
- package/scripts/discovery/repo-origin.ts +153 -0
- package/scripts/discovery/repo-party-cli.ts +69 -0
- package/scripts/discovery/repo-party.ts +46 -0
- package/scripts/doctor/doctor-consumer.ts +181 -0
- package/scripts/doctor/doctor-io.ts +210 -0
- package/scripts/doctor/doctor-logic.ts +122 -0
- package/scripts/doctor/doctor-ports.ts +117 -0
- package/scripts/doctor/doctor.ts +232 -0
- package/scripts/document/backlogrun-parent-read-set.ts +48 -0
- package/scripts/document/bash-output-cap.ts +45 -0
- package/scripts/document/document-byte-budget.ts +183 -0
- package/scripts/document/document-byte-check.ts +131 -0
- package/scripts/document/document-reachability.ts +131 -0
- package/scripts/document/document-read-cli.ts +82 -0
- package/scripts/document/document-scan.ts +108 -0
- package/scripts/document/document-section-cli.ts +101 -0
- package/scripts/document/document-section.ts +156 -0
- package/scripts/document/edit-files-cli.ts +280 -0
- package/scripts/document/entry-read-budget.ts +154 -0
- package/scripts/document/entry-read-set.ts +471 -0
- package/scripts/document/generate-catalog.ts +69 -0
- package/scripts/document/lane-child-read-set.ts +88 -0
- package/scripts/document/read-files-cli.ts +135 -0
- package/scripts/document/read-set-cli.ts +295 -0
- package/scripts/document/read-set-point-of-use.ts +89 -0
- package/scripts/document/read-set-pricing.ts +52 -0
- package/scripts/document/read-set-trim.ts +78 -0
- package/scripts/document/retired-phrases.ts +143 -0
- package/scripts/document/review-agent-type.ts +46 -0
- package/scripts/document/single-source.ts +73 -0
- package/scripts/epic/epic-audit-checks.ts +452 -0
- package/scripts/epic/epic-audit-cli.ts +374 -0
- package/scripts/epic/epic-audit-orphans.ts +142 -0
- package/scripts/epic/epic-audit-rationale.ts +191 -0
- package/scripts/epic/epic-audit-report.ts +101 -0
- package/scripts/epic/epic-audit.ts +240 -0
- package/scripts/epic/epic-bundle-cli.ts +472 -0
- package/scripts/epic/epic-bundle-evidence.ts +147 -0
- package/scripts/epic/epic-bundle-gaps.ts +86 -0
- package/scripts/epic/epic-bundle-referenced.ts +195 -0
- package/scripts/epic/epic-bundle.ts +309 -0
- package/scripts/epic/epic-busy.ts +204 -0
- package/scripts/epic/epic-candidate-confirm.ts +279 -0
- package/scripts/epic/epic-classify.ts +294 -0
- package/scripts/epic/epic-cross-repo.ts +366 -0
- package/scripts/epic/epic-fetch.ts +370 -0
- package/scripts/epic/epic-graph.ts +279 -0
- package/scripts/epic/epic-index.ts +209 -0
- package/scripts/epic/epic-issue.ts +172 -0
- package/scripts/epic/epic-lane-offer.ts +207 -0
- package/scripts/epic/epic-nested.ts +37 -0
- package/scripts/epic/epic-next-read.ts +141 -0
- package/scripts/epic/epic-next-views.ts +144 -0
- package/scripts/epic/epic-next.ts +477 -0
- package/scripts/epic/epic-outside-blocker.ts +113 -0
- package/scripts/epic/epic-relation-recheck.ts +108 -0
- package/scripts/epic/epic-report.ts +200 -0
- package/scripts/gate/core-budget.ts +292 -0
- package/scripts/gate/gate-log.ts +95 -0
- package/scripts/gate/gate-plan.ts +356 -0
- package/scripts/gate/gate-report.ts +207 -0
- package/scripts/gate/gate-skip.ts +123 -0
- package/scripts/gate/gate-tree.ts +49 -0
- package/scripts/gate/hook-gate-reuse.ts +130 -0
- package/scripts/gate/pre-commit-type-check.ts +187 -0
- package/scripts/gate/scoped-green.ts +260 -0
- package/scripts/gate/type-check-step.ts +90 -0
- package/scripts/gate/verification-gate.ts +531 -0
- package/scripts/gh/fix-gh-packages-logic.ts +232 -0
- package/scripts/gh/fix-gh-packages.ts +129 -0
- package/scripts/gh/gh-cli-token.ts +18 -0
- package/scripts/gh/gh-spawn.ts +44 -0
- package/scripts/git/animation-helpers.ts +81 -0
- package/scripts/git/change-base.ts +26 -0
- package/scripts/git/changed-file-scope.ts +209 -0
- package/scripts/git/changed-paths.ts +30 -0
- package/scripts/git/constants.ts +41 -0
- package/scripts/git/git-ai-review-scan.ts +154 -0
- package/scripts/git/git-animation.ts +41 -0
- package/scripts/git/git-branch.ts +127 -0
- package/scripts/git/git-command.ts +587 -0
- package/scripts/git/git-commit.ts +27 -0
- package/scripts/git/git-common-directory.ts +38 -0
- package/scripts/git/git-epic-add-body.ts +365 -0
- package/scripts/git/git-epic-add-plan.ts +421 -0
- package/scripts/git/git-epic-add.ts +249 -0
- package/scripts/git/git-epic-body.ts +150 -0
- package/scripts/git/git-epic-chains.ts +411 -0
- package/scripts/git/git-epic-close-comment.ts +199 -0
- package/scripts/git/git-epic-close.ts +393 -0
- package/scripts/git/git-epic-decision.ts +171 -0
- package/scripts/git/git-epic-parse.ts +351 -0
- package/scripts/git/git-epic-promote.ts +102 -0
- package/scripts/git/git-epic-read.ts +73 -0
- package/scripts/git/git-epic-reconcile.ts +246 -0
- package/scripts/git/git-epic-reference.ts +98 -0
- package/scripts/git/git-epic-relations.ts +78 -0
- package/scripts/git/git-epic-remove-plan.ts +152 -0
- package/scripts/git/git-epic-remove.ts +101 -0
- package/scripts/git/git-epic-run.ts +223 -0
- package/scripts/git/git-epic-sections.ts +98 -0
- package/scripts/git/git-epic-shape.ts +81 -0
- package/scripts/git/git-epic-validate.ts +155 -0
- package/scripts/git/git-error.ts +78 -0
- package/scripts/git/git-execa-error.ts +35 -0
- package/scripts/git/git-fixture-workspace.ts +88 -0
- package/scripts/git/git-followup-cleanup.ts +88 -0
- package/scripts/git/git-followup-flush.ts +63 -0
- package/scripts/git/git-followup-label.ts +67 -0
- package/scripts/git/git-followup-pending.ts +95 -0
- package/scripts/git/git-followup-stages.ts +149 -0
- package/scripts/git/git-gh-api-path.ts +118 -0
- package/scripts/git/git-gh-check.ts +21 -0
- package/scripts/git/git-gh-command.ts +17 -0
- package/scripts/git/git-gh-exec.ts +344 -0
- package/scripts/git/git-gh-failure.ts +103 -0
- package/scripts/git/git-gh-helpers.ts +44 -0
- package/scripts/git/git-gh-issue-list.ts +257 -0
- package/scripts/git/git-gh-issue-read.ts +457 -0
- package/scripts/git/git-gh-issue-rest.ts +238 -0
- package/scripts/git/git-gh-issue-write.ts +285 -0
- package/scripts/git/git-gh-issue.ts +161 -0
- package/scripts/git/git-gh-pr-auto-merge.ts +85 -0
- package/scripts/git/git-gh-pr-read.ts +322 -0
- package/scripts/git/git-gh-pr-rest.ts +172 -0
- package/scripts/git/git-gh-pr-review.ts +103 -0
- package/scripts/git/git-gh-pr-rollup.ts +91 -0
- package/scripts/git/git-gh-pr-snapshot.ts +138 -0
- package/scripts/git/git-gh-pr.ts +219 -0
- package/scripts/git/git-gh-reachability.ts +56 -0
- package/scripts/git/git-gh-repo.ts +37 -0
- package/scripts/git/git-gh-rest-state.ts +14 -0
- package/scripts/git/git-issue.ts +168 -0
- package/scripts/git/git-location-environment.ts +62 -0
- package/scripts/git/git-ls-remote.ts +28 -0
- package/scripts/git/git-next-issues.ts +98 -0
- package/scripts/git/git-notify.ts +104 -0
- package/scripts/git/git-pr-ai-review.ts +180 -0
- package/scripts/git/git-pr-checks-eval.ts +265 -0
- package/scripts/git/git-pr-checks-parse.ts +153 -0
- package/scripts/git/git-pr-checks-watch.ts +184 -0
- package/scripts/git/git-pr-checks.ts +387 -0
- package/scripts/git/git-pr-coderabbit.ts +129 -0
- package/scripts/git/git-pr-confirmation.ts +64 -0
- package/scripts/git/git-pr-error.ts +25 -0
- package/scripts/git/git-pr-followup-wrapup.ts +225 -0
- package/scripts/git/git-pr-followup.ts +436 -0
- package/scripts/git/git-pr-managed-config.ts +69 -0
- package/scripts/git/git-pr-messages.ts +37 -0
- package/scripts/git/git-pr.ts +181 -0
- package/scripts/git/git-prompt-display.ts +22 -0
- package/scripts/git/git-prompt.ts +207 -0
- package/scripts/git/git-push-transport.ts +173 -0
- package/scripts/git/git-push.ts +27 -0
- package/scripts/git/git-remote-branch.ts +40 -0
- package/scripts/git/git-spawn.ts +47 -0
- package/scripts/git/git-staging.ts +128 -0
- package/scripts/git/git-stash.ts +124 -0
- package/scripts/git/git-status.ts +198 -0
- package/scripts/git/git-worktree.ts +110 -0
- package/scripts/git/github-issue-url.ts +105 -0
- package/scripts/git/gone-branch.ts +113 -0
- package/scripts/git/issue-labels.ts +279 -0
- package/scripts/git/listing-cutoff.ts +51 -0
- package/scripts/git/main-merge-guard.ts +134 -0
- package/scripts/git/main-merge.ts +120 -0
- package/scripts/git/main-sync.ts +121 -0
- package/scripts/git/parse-json-array.ts +102 -0
- package/scripts/git/schemas.ts +166 -0
- package/scripts/git/stash-orphans.ts +91 -0
- package/scripts/git/stash-pop-args.ts +59 -0
- package/scripts/git/stash-pop-cli.ts +105 -0
- package/scripts/git/telegram-notify.ts +404 -0
- package/scripts/hooks/batch-guard.ts +144 -0
- package/scripts/hooks/check-commit-message.ts +134 -0
- package/scripts/hooks/codex-hook-adapter.ts +155 -0
- package/scripts/hooks/edited-cspell.ts +128 -0
- package/scripts/hooks/format-edited-file-fixtures.ts +109 -0
- package/scripts/hooks/format-edited-file.ts +510 -0
- package/scripts/hooks/format-rewrite-notice.ts +99 -0
- package/scripts/hooks/pre-push-unit.ts +146 -0
- package/scripts/hooks/pretool-guard.ts +96 -0
- package/scripts/hooks/prevent-main-commit.ts +38 -0
- package/scripts/hooks/prompt-hooks.ts +38 -0
- package/scripts/hooks/reserved-run.ts +90 -0
- package/scripts/hooks/stop-guard.ts +135 -0
- package/scripts/init/claude-plugin-config.ts +51 -0
- package/scripts/init/distributed-paths.ts +100 -0
- package/scripts/init/hook-command-rewrite.ts +85 -0
- package/scripts/init/hook-launch.ts +31 -0
- package/scripts/init/init-actions.ts +147 -0
- package/scripts/init/init-ai-copy.ts +235 -0
- package/scripts/init/init-copy-content.ts +50 -0
- package/scripts/init/init-logic-deploy-vps.ts +43 -0
- package/scripts/init/init-logic-json-merge.ts +340 -0
- package/scripts/init/init-logic-migrate.ts +62 -0
- package/scripts/init/init-logic-package-key-order.ts +50 -0
- package/scripts/init/init-logic-secretlint.ts +36 -0
- package/scripts/init/init-logic-sonar.ts +197 -0
- package/scripts/init/init-logic-templates.ts +142 -0
- package/scripts/init/init-logic-workspace.ts +59 -0
- package/scripts/init/init-logic-yaml-merge.ts +57 -0
- package/scripts/init/init-logic.ts +474 -0
- package/scripts/init/init-paths.ts +11 -0
- package/scripts/init/init-sonar.ts +32 -0
- package/scripts/init/init.ts +219 -0
- package/scripts/init/kit-base-preset.ts +60 -0
- package/scripts/init/plugin-install-hint.ts +47 -0
- package/scripts/init/tsconfig-preset-migration.ts +67 -0
- package/scripts/issue/baseline-measure.ts +105 -0
- package/scripts/issue/behavior-change-lint.ts +122 -0
- package/scripts/issue/defect-rate-cli.ts +167 -0
- package/scripts/issue/defect-rate.ts +145 -0
- package/scripts/issue/issue-backlinks-cli.ts +97 -0
- package/scripts/issue/issue-backlinks.ts +164 -0
- package/scripts/issue/issue-cite-cli.ts +158 -0
- package/scripts/issue/issue-cite.ts +102 -0
- package/scripts/issue/issue-comment-cli.ts +95 -0
- package/scripts/issue/issue-fold-cli.ts +104 -0
- package/scripts/issue/issue-fold-existing-cli.ts +81 -0
- package/scripts/issue/issue-fold-existing.ts +73 -0
- package/scripts/issue/issue-fold.ts +42 -0
- package/scripts/issue/issue-lint-cli.ts +60 -0
- package/scripts/issue/issue-lint.ts +26 -0
- package/scripts/issue/issue-logic.ts +50 -0
- package/scripts/issue/issue-read-cli.ts +190 -0
- package/scripts/issue/issue-read.ts +145 -0
- package/scripts/issue/issue-scout-cli.ts +482 -0
- package/scripts/issue/issue-scout.ts +244 -0
- package/scripts/issue/issue-state-cli.ts +260 -0
- package/scripts/issue/issue-state.ts +109 -0
- package/scripts/issue/markdown-section.ts +39 -0
- package/scripts/issue/measure-rerun-cli.ts +98 -0
- package/scripts/issue/reproduction-measure.ts +59 -0
- package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +1171 -0
- package/scripts/josh/agent-session-environment.ts +188 -0
- package/scripts/josh/cli-body.ts +96 -0
- package/scripts/josh/command-suggest.ts +57 -0
- package/scripts/josh/file-map-stamp.ts +264 -0
- package/scripts/josh/hook-decision.ts +479 -0
- package/scripts/josh/josh-command-map.ts +196 -0
- package/scripts/josh/josh-command-types.ts +226 -0
- package/scripts/josh/josh-commands-ai.ts +327 -0
- package/scripts/josh/josh-commands-backlog.ts +54 -0
- package/scripts/josh/josh-commands-clone.ts +18 -0
- package/scripts/josh/josh-commands-development.ts +206 -0
- package/scripts/josh/josh-commands-document.ts +45 -0
- package/scripts/josh/josh-commands-guard.ts +38 -0
- package/scripts/josh/josh-commands-hooks.ts +42 -0
- package/scripts/josh/josh-commands-issue.ts +69 -0
- package/scripts/josh/josh-commands-lane.ts +75 -0
- package/scripts/josh/josh-commands-lint.ts +37 -0
- package/scripts/josh/josh-commands-maintenance.ts +80 -0
- package/scripts/josh/josh-commands-project.ts +53 -0
- package/scripts/josh/josh-commands-split.ts +20 -0
- package/scripts/josh/josh-commands-versioning.ts +48 -0
- package/scripts/josh/josh-commands-workflow.ts +116 -0
- package/scripts/josh/josh-composite-arguments.ts +55 -0
- package/scripts/josh/josh-environment-file.ts +31 -0
- package/scripts/josh/josh-in-process.ts +80 -0
- package/scripts/josh/josh-logic.ts +308 -0
- package/scripts/josh/josh-run.ts +53 -0
- package/scripts/josh/josh-script-reader.ts +11 -0
- package/scripts/josh/josh-verdict.ts +111 -0
- package/scripts/josh/josh.ts +60 -0
- package/scripts/josh/kit-only.ts +33 -0
- package/scripts/josh/path-decision.ts +104 -0
- package/scripts/josh/platform-temporary.ts +66 -0
- package/scripts/josh/process-identity.ts +335 -0
- package/scripts/josh/session-language-cli.ts +51 -0
- package/scripts/josh/session-language.ts +30 -0
- package/scripts/josh/stamp-file.ts +194 -0
- package/scripts/lane/lane-await.ts +165 -0
- package/scripts/lane/lane-cache-run.ts +39 -0
- package/scripts/lane/lane-cache.ts +135 -0
- package/scripts/lane/lane-capacity.ts +69 -0
- package/scripts/lane/lane-child-invocation.ts +73 -0
- package/scripts/lane/lane-child-marker.ts +58 -0
- package/scripts/lane/lane-cli.ts +410 -0
- package/scripts/lane/lane-close.ts +197 -0
- package/scripts/lane/lane-dispatch-log.ts +13 -0
- package/scripts/lane/lane-dispatch.ts +458 -0
- package/scripts/lane/lane-environment.ts +253 -0
- package/scripts/lane/lane-guard-policy.ts +136 -0
- package/scripts/lane/lane-install.ts +94 -0
- package/scripts/lane/lane-launch-cli.ts +133 -0
- package/scripts/lane/lane-occupancy.ts +112 -0
- package/scripts/lane/lane-open.ts +275 -0
- package/scripts/lane/lane-output.ts +124 -0
- package/scripts/lane/lane-paths.ts +96 -0
- package/scripts/lane/lane-reap.ts +137 -0
- package/scripts/lane/lane-registry.ts +261 -0
- package/scripts/lane/lane-relaunch.ts +68 -0
- package/scripts/lane/lane-report.ts +95 -0
- package/scripts/lane/lane-resume.ts +61 -0
- package/scripts/lane/lane-seed.ts +44 -0
- package/scripts/lane/lane-start-point.ts +175 -0
- package/scripts/lane/openai-lane-supervisor-cli.ts +32 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +63 -0
- package/scripts/lane/openai-lane-supervisor.ts +337 -0
- package/scripts/lib/bounded-pool.ts +109 -0
- package/scripts/lib/buffered-process.ts +82 -0
- package/scripts/lib/caddy-logs.sh +45 -0
- package/scripts/lib/cli-flags.ts +19 -0
- package/scripts/lib/json-value.ts +24 -0
- package/scripts/lib/poll.ts +57 -0
- package/scripts/lib/read-file.ts +16 -0
- package/scripts/lib/schemas.ts +67 -0
- package/scripts/lib/spawn-exit.ts +45 -0
- package/scripts/lib/status-icons.ts +24 -0
- package/scripts/lines/effective-limit.ts +156 -0
- package/scripts/lines/line-budget.ts +404 -0
- package/scripts/lines/line-targets.ts +80 -0
- package/scripts/lines/lines-command.ts +174 -0
- package/scripts/lint/cspell-cached.ts +41 -0
- package/scripts/lint/lint-parallel.ts +72 -0
- package/scripts/lint/lint-related-scope.ts +128 -0
- package/scripts/lint/lint-related.ts +104 -0
- package/scripts/managed-marker/index.ts +5 -0
- package/scripts/managed-marker/managed-marker-logic.ts +67 -0
- package/scripts/observations/observation-ledger-home.ts +32 -0
- package/scripts/observations/observation-ledger-line.ts +93 -0
- package/scripts/observations/observation-ledger.ts +35 -0
- package/scripts/observations/observations-flush-cli.ts +42 -0
- package/scripts/observations/observations-flush-landing.ts +97 -0
- package/scripts/observations/observations-flush.ts +420 -0
- package/scripts/overrides/lockfile-overrides.ts +105 -0
- package/scripts/overrides/overrides-check.ts +84 -0
- package/scripts/overrides/overrides-files.ts +19 -0
- package/scripts/overrides/overrides-logic.ts +211 -0
- package/scripts/overrides/schemas.ts +49 -0
- package/scripts/package/package-scout-cli.ts +195 -0
- package/scripts/package/package-scout-format.ts +151 -0
- package/scripts/package/package-scout.ts +121 -0
- package/scripts/ports/port-command.ts +87 -0
- package/scripts/propagate/propagate-git-failure.ts +191 -0
- package/scripts/propagate/propagate-git.ts +224 -0
- package/scripts/propagate/propagate-publish.ts +181 -0
- package/scripts/propagate/propagate-run.ts +201 -0
- package/scripts/propagate/propagate-steps.ts +421 -0
- package/scripts/propagate/propagate-targets.ts +160 -0
- package/scripts/propagate/propagate.ts +216 -0
- package/scripts/refactor/import-graph.ts +187 -0
- package/scripts/refactor/refactor-lint.ts +250 -0
- package/scripts/refactor/refactor-scan-cli.ts +10 -0
- package/scripts/refactor/refactor-scan.ts +124 -0
- package/scripts/refactor/refactor-targets.ts +103 -0
- package/scripts/release/release-cli.ts +88 -0
- package/scripts/release/release-history.ts +132 -0
- package/scripts/release/release-plan.ts +130 -0
- package/scripts/release/release-publish.ts +152 -0
- package/scripts/release/release-scope-cli.ts +103 -0
- package/scripts/release/release-tag.ts +93 -0
- package/scripts/release/release-worktree.ts +71 -0
- package/scripts/repo/auto-merge-setting-logic.ts +100 -0
- package/scripts/repo/auto-merge-setting.ts +37 -0
- package/scripts/repo/repo-setting.ts +112 -0
- package/scripts/report/report-lint-cli.ts +49 -0
- package/scripts/report/report-lint.ts +250 -0
- package/scripts/retrospective/retrospective-cli.ts +97 -0
- package/scripts/retrospective/retrospective.ts +127 -0
- package/scripts/review/disposition-cli.ts +44 -0
- package/scripts/review/disposition-logic.ts +45 -0
- package/scripts/review/live-evidence.ts +62 -0
- package/scripts/review/review-attest-cli.ts +115 -0
- package/scripts/review/review-attest.ts +319 -0
- package/scripts/review/review-brief-cli.ts +290 -0
- package/scripts/review/review-brief.ts +440 -0
- package/scripts/review/review-checkout.ts +56 -0
- package/scripts/review/review-finding-ledger.ts +167 -0
- package/scripts/review/review-findings-cli.ts +57 -0
- package/scripts/review/review-level.ts +86 -0
- package/scripts/review/review-record-cli.ts +196 -0
- package/scripts/review/review-record.ts +74 -0
- package/scripts/review/review-round2-cli.ts +84 -0
- package/scripts/review/review-round2.ts +139 -0
- package/scripts/review/review-stamps.ts +113 -0
- package/scripts/review/review-tree.ts +58 -0
- package/scripts/rules/bash-triggers.ts +44 -0
- package/scripts/rules/decision-oracle.ts +342 -0
- package/scripts/rules/delivered-rules-harness.ts +72 -0
- package/scripts/rules/delivered-rules.ts +793 -0
- package/scripts/rules/early-heartbeat.ts +241 -0
- package/scripts/rules/file-body.ts +150 -0
- package/scripts/rules/filing-cap.ts +133 -0
- package/scripts/rules/filing-offer.ts +81 -0
- package/scripts/rules/firing-point.ts +63 -0
- package/scripts/rules/gh-api.ts +65 -0
- package/scripts/rules/git-argv.ts +129 -0
- package/scripts/rules/git-force.ts +104 -0
- package/scripts/rules/implementation-cut-verdict.ts +84 -0
- package/scripts/rules/implementation-cut.ts +202 -0
- package/scripts/rules/issue-citation.ts +242 -0
- package/scripts/rules/issue-fold.ts +73 -0
- package/scripts/rules/issue-scout.ts +64 -0
- package/scripts/rules/josh-git-bare.ts +80 -0
- package/scripts/rules/lane-carry-conflict.ts +96 -0
- package/scripts/rules/lane-interactive-ask.ts +71 -0
- package/scripts/rules/lane-park.ts +122 -0
- package/scripts/rules/lane-switch-main.ts +139 -0
- package/scripts/rules/oracle-consulted.ts +81 -0
- package/scripts/rules/oracle-firing.ts +151 -0
- package/scripts/rules/oracle-list-cli.ts +81 -0
- package/scripts/rules/piped-verification.ts +126 -0
- package/scripts/rules/poll-loop.ts +125 -0
- package/scripts/rules/pre-gate-cut.ts +207 -0
- package/scripts/rules/prior-comment-read.ts +106 -0
- package/scripts/rules/raw-field-body.ts +56 -0
- package/scripts/rules/reply-language.ts +116 -0
- package/scripts/rules/rule-body-guard.ts +206 -0
- package/scripts/rules/rule-guard.ts +23 -0
- package/scripts/rules/rule-value-cli.ts +129 -0
- package/scripts/rules/rule-value.ts +397 -0
- package/scripts/rules/run-tail.ts +178 -0
- package/scripts/rules/shell-body-trigger.ts +204 -0
- package/scripts/rules/shell-segments.ts +45 -0
- package/scripts/rules/stop-rules.ts +329 -0
- package/scripts/rules/tail-commands.ts +35 -0
- package/scripts/rules/test-declared-commit.ts +51 -0
- package/scripts/rules/third-party-write.ts +90 -0
- package/scripts/rules/top-level-scripts-guard.ts +47 -0
- package/scripts/rules/worktree-guard.ts +130 -0
- package/scripts/run/detached-launch.ts +360 -0
- package/scripts/run/run-carry-args.ts +264 -0
- package/scripts/run/run-carry-change.ts +69 -0
- package/scripts/run/run-carry-cli.ts +441 -0
- package/scripts/run/run-carry-flush.ts +63 -0
- package/scripts/run/run-carry-stash.ts +71 -0
- package/scripts/run/run-carry-streak.ts +113 -0
- package/scripts/run/run-carry.ts +550 -0
- package/scripts/run/run-cut-args.ts +132 -0
- package/scripts/run/run-cut-cli.ts +461 -0
- package/scripts/run/run-cut-handoff.ts +126 -0
- package/scripts/run/run-cut.ts +531 -0
- package/scripts/run/run-ending-cli.ts +111 -0
- package/scripts/run/run-ending.ts +239 -0
- package/scripts/run/run-entry-cli.ts +135 -0
- package/scripts/run/run-entry.ts +95 -0
- package/scripts/run/run-event-cli.ts +210 -0
- package/scripts/run/run-event-follow.ts +65 -0
- package/scripts/run/run-event-render.ts +75 -0
- package/scripts/run/run-event-scope.ts +127 -0
- package/scripts/run/run-event-stream-emit.ts +140 -0
- package/scripts/run/run-event-stream.ts +258 -0
- package/scripts/run/run-event-watch.ts +37 -0
- package/scripts/run/run-headless.ts +105 -0
- package/scripts/run/run-hold-cli.ts +310 -0
- package/scripts/run/run-hold.ts +264 -0
- package/scripts/run/run-invocation.ts +237 -0
- package/scripts/run/run-issue-number.ts +19 -0
- package/scripts/run/run-liveness-cli.ts +169 -0
- package/scripts/run/run-liveness.ts +424 -0
- package/scripts/run/run-merge-cli.ts +385 -0
- package/scripts/run/run-merge-steps.ts +326 -0
- package/scripts/run/run-merge.ts +158 -0
- package/scripts/run/run-next-cli.ts +48 -0
- package/scripts/run/run-next.ts +80 -0
- package/scripts/run/run-preflight.ts +337 -0
- package/scripts/run/run-prep-cli.ts +151 -0
- package/scripts/run/run-prep.ts +84 -0
- package/scripts/run/run-progress-args.ts +65 -0
- package/scripts/run/run-progress-cli.ts +508 -0
- package/scripts/run/run-progress-clock.ts +320 -0
- package/scripts/run/run-progress-config.ts +119 -0
- package/scripts/run/run-progress-read.ts +199 -0
- package/scripts/run/run-progress.ts +366 -0
- package/scripts/run/run-report-cli.ts +71 -0
- package/scripts/run/run-report.ts +78 -0
- package/scripts/run/run-review-cli.ts +130 -0
- package/scripts/run/run-review-steps.ts +161 -0
- package/scripts/run/run-review.ts +121 -0
- package/scripts/run/run-ship-cli.ts +431 -0
- package/scripts/run/run-ship-detach.ts +200 -0
- package/scripts/run/run-ship-probe.ts +103 -0
- package/scripts/run/run-ship-return.ts +75 -0
- package/scripts/run/run-ship-review-steps.ts +227 -0
- package/scripts/run/run-ship-review.ts +177 -0
- package/scripts/run/run-ship-stage.ts +150 -0
- package/scripts/run/run-ship.ts +78 -0
- package/scripts/run/run-status-cli.ts +175 -0
- package/scripts/run/run-status.ts +77 -0
- package/scripts/run/run-step-cli.ts +111 -0
- package/scripts/run/run-step.ts +292 -0
- package/scripts/run/run-stop-notify.ts +52 -0
- package/scripts/run/run-stranded-cli.ts +31 -0
- package/scripts/run/run-stranded-detect.ts +134 -0
- package/scripts/run/run-stranded.ts +120 -0
- package/scripts/run/run-tail-cli.ts +105 -0
- package/scripts/run/run-tail.ts +61 -0
- package/scripts/run/run-transcript.golden.txt +57 -0
- package/scripts/run/run-wake-cli.ts +428 -0
- package/scripts/run/run-wake-describe.ts +97 -0
- package/scripts/run/run-wake-driver.ts +80 -0
- package/scripts/run/run-wake-handoff.ts +29 -0
- package/scripts/run/run-wake-loop.ts +223 -0
- package/scripts/run/run-wake-session.ts +150 -0
- package/scripts/run/run-wake-work.ts +104 -0
- package/scripts/run/run-wake.ts +607 -0
- package/scripts/run/run-watcher-guard-cli.ts +37 -0
- package/scripts/run/run-watcher-guard.ts +59 -0
- package/scripts/run/run-watcher-hook.ts +86 -0
- package/scripts/security/secretlint-scan.ts +86 -0
- package/scripts/security/security-audit-logic.ts +51 -0
- package/scripts/security/security-audit-provision-logic.ts +217 -0
- package/scripts/security/security-audit-provision.ts +186 -0
- package/scripts/security/security-audit.ts +132 -0
- package/scripts/security/security-updates-logic.ts +131 -0
- package/scripts/security/security-updates.ts +38 -0
- package/scripts/security/sonar-file.ts +44 -0
- package/scripts/self-sync-guard/index.ts +5 -0
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +98 -0
- package/scripts/self-sync-guard/self-sync-refusal.ts +22 -0
- package/scripts/sonar/sonar-hotspots-cli.ts +149 -0
- package/scripts/sonar/sonar-hotspots.ts +111 -0
- package/scripts/split/split-assess-cli.ts +52 -0
- package/scripts/split/split-assess.ts +124 -0
- package/scripts/sync/dependabot-pin-logic.ts +135 -0
- package/scripts/sync/directory-copy-guard.ts +187 -0
- package/scripts/sync/file-content.ts +49 -0
- package/scripts/sync/managed-config-scope-cli.ts +64 -0
- package/scripts/sync/managed-config-scope.ts +123 -0
- package/scripts/sync/plugin-skill-directories.ts +15 -0
- package/scripts/sync/reconcile-templates.ts +53 -0
- package/scripts/sync/removed-skill-manifest.ts +27 -0
- package/scripts/sync/skill-migration.ts +192 -0
- package/scripts/sync/sync-configs.ts +156 -0
- package/scripts/sync/sync-hook-safety.ts +82 -0
- package/scripts/sync/sync.ts +417 -0
- package/scripts/sync/synced-paths.ts +52 -0
- package/scripts/sync/template-source-logic.ts +122 -0
- package/scripts/sync/workflow-pin-logic.ts +240 -0
- package/scripts/test/classify-isolation.ts +149 -0
- package/scripts/test/e2e-retry-check.ts +150 -0
- package/scripts/test/http-fault-injection.ts +79 -0
- package/scripts/test/josh-harness-environment.ts +260 -0
- package/scripts/test/josh-harness.ts +96 -0
- package/scripts/test/pilot-files.ts +457 -0
- package/scripts/test/pilot-measure.ts +78 -0
- package/scripts/test/test-declared-changed.ts +99 -0
- package/scripts/test/test-declared-logic.ts +91 -0
- package/scripts/test/test-declared-match.ts +106 -0
- package/scripts/test/test-declared.ts +180 -0
- package/scripts/test/test-e2e-guard.ts +86 -0
- package/scripts/test/test-network-guard.ts +453 -0
- package/scripts/test/test-red-commit.ts +51 -0
- package/scripts/test/test-red-logic.ts +76 -0
- package/scripts/test/test-red.ts +154 -0
- package/scripts/test/test-related-scope.ts +115 -0
- package/scripts/test/test-related.ts +73 -0
- package/scripts/test/test-repository-guard.ts +317 -0
- package/scripts/test/test-state-guard.ts +85 -0
- package/scripts/test/test-stdout-guard.ts +54 -0
- package/scripts/test/test-telegram-guard.ts +90 -0
- package/scripts/test/test-type-logic.ts +31 -0
- package/scripts/test/test-unit-guard.ts +185 -0
- package/scripts/test/unit-guard-environment.ts +12 -0
- package/scripts/test/unit-projects.ts +139 -0
- package/scripts/test/unit-worker-share.ts +251 -0
- package/scripts/test/vitest-include-globs.ts +12 -0
- package/scripts/time-runtime/time-agent-bundles.ts +128 -0
- package/scripts/time-runtime/time-background.ts +300 -0
- package/scripts/time-runtime/time-batch-guard-fixtures.ts +66 -0
- package/scripts/time-runtime/time-batch-guard.ts +529 -0
- package/scripts/time-runtime/time-bundle-call.ts +575 -0
- package/scripts/time-runtime/time-bundles.ts +536 -0
- package/scripts/time-runtime/time-call-identity.ts +37 -0
- package/scripts/time-runtime/time-command-key.ts +35 -0
- package/scripts/time-runtime/time-density-hook.ts +166 -0
- package/scripts/time-runtime/time-density.ts +147 -0
- package/scripts/time-runtime/time-followup-stage.ts +107 -0
- package/scripts/time-runtime/time-format.ts +186 -0
- package/scripts/time-runtime/time-hook-transcript.ts +82 -0
- package/scripts/time-runtime/time-instant.ts +20 -0
- package/scripts/time-runtime/time-markers.ts +228 -0
- package/scripts/time-runtime/time-phase-names.ts +123 -0
- package/scripts/time-runtime/time-reported-failure.ts +227 -0
- package/scripts/time-runtime/time-round-trips.ts +279 -0
- package/scripts/time-runtime/time-shell.ts +286 -0
- package/scripts/time-runtime/time-single-check.ts +65 -0
- package/scripts/time-runtime/time-spans.ts +545 -0
- package/scripts/time-runtime/time-transcript-line.ts +253 -0
- package/scripts/time-runtime/time-writes.ts +71 -0
- package/scripts/ui/ui-routes-cli.ts +122 -0
- package/scripts/ui/ui-routes.ts +102 -0
- package/scripts/version/bump-version.ts +71 -0
- package/scripts/version/effective-upstream.ts +93 -0
- package/scripts/version/index.ts +25 -0
- package/scripts/version/kit-descriptor.ts +10 -0
- package/scripts/version/kit-version-config.ts +30 -0
- package/scripts/version/latest-corepack.ts +404 -0
- package/scripts/version/latest-lane-guard.ts +49 -0
- package/scripts/version/latest-regression.ts +93 -0
- package/scripts/version/latest-scope-cli.ts +147 -0
- package/scripts/version/latest-stamp.ts +107 -0
- package/scripts/version/latest-update.ts +198 -0
- package/scripts/version/package-manager-version.ts +95 -0
- package/scripts/version/parse-json.ts +13 -0
- package/scripts/version/preinstall-version-update.ts +84 -0
- package/scripts/version/publishable-range-check.ts +74 -0
- package/scripts/version/publishable-range.ts +123 -0
- package/scripts/version/release-age.ts +146 -0
- package/scripts/version/release-hold.ts +142 -0
- package/scripts/version/running-binary.ts +42 -0
- package/scripts/version/upgrade-command-guard.ts +49 -0
- package/scripts/version/upgrade-shell-command.ts +30 -0
- package/scripts/version/version-check-logic.ts +333 -0
- package/scripts/version/version-check.ts +14 -0
- package/scripts/version/version-command-config.ts +177 -0
- package/scripts/version/version-commands.ts +296 -0
- package/scripts/version/version-remote.ts +86 -0
- package/scripts/version/version-targets.ts +81 -0
- package/scripts/yaml/yaml-document.ts +46 -0
- package/scripts-ai/completion-gate.ts +13 -0
- package/scripts-ai/environment-loader.ts +9 -0
- package/scripts-ai/epic-check.ts +34 -0
- package/scripts-ai/epic-cli-argv.ts +77 -0
- package/scripts-ai/epic-cli-remove.ts +71 -0
- package/scripts-ai/epic-cli.ts +413 -0
- package/scripts-ai/epic.ts +192 -0
- package/scripts-ai/followup-issue-number.ts +31 -0
- package/scripts-ai/git-followup-finish.ts +217 -0
- package/scripts-ai/git-followup-workflow.ts +252 -0
- package/scripts-ai/git-workflow.ts +246 -0
- package/scripts-ai/telegram-test-logic.ts +88 -0
- package/scripts-ai/telegram-test.ts +130 -0
- package/templates/gitignore +76 -0
- package/templates/sonar-project.properties +52 -0
- package/templates/workflows/ci.yml +639 -0
- package/templates/workflows/dependabot-auto-merge.yml +428 -0
- package/tsconfig/base.json +50 -0
- package/tsconfig.sonar.json +34 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// The `shell-body` row's trigger, in a module of its own rather than inside the enumeration
|
|
2
|
+
// (joshuafolkken/kit#1198). Every other row's trigger is already shaped that way — `time_batch_guard`
|
|
3
|
+
// and `cost_blocks` each hold their own reading of a call — and this one needs a small model of what
|
|
4
|
+
// zsh does inside double quotes, which is more than an enumeration row should carry. The split also
|
|
5
|
+
// gives that model a suite of its own, so a regex change is read beside the cases it has to keep.
|
|
6
|
+
|
|
7
|
+
// A body handed to a command as an inline double-quoted argument, in the spellings a run reaches for:
|
|
8
|
+
// `gh`'s field flags (`-f` / `-F` / `--field` / `--raw-field` with `body=`), `gh`'s own `--body`, and
|
|
9
|
+
// `josh`'s `--body` and `--notify-message`. The value is captured so the decision can be made on what
|
|
10
|
+
// the body actually contains rather than on the flag alone.
|
|
11
|
+
//
|
|
12
|
+
// **`-b` is deliberately absent.** It is `gh`'s short `--body`, but it is also `git checkout -b`, and
|
|
13
|
+
// a branch name is not a body — covering it would refuse calls where nothing is wrong. The `*-file`
|
|
14
|
+
// spellings end in `-` where this pattern needs whitespace or `=`, so `--body-file <path>` and
|
|
15
|
+
// `--notify-message-file <path>` cannot match it.
|
|
16
|
+
const FIELD_FLAGS = '(?:-f|-F|--field|--raw-field)'
|
|
17
|
+
const MESSAGE_FLAGS = '(?:--body|--notify-message)'
|
|
18
|
+
|
|
19
|
+
// **The opening quote sits on either side of `body=`, and both spellings are the same command.** zsh
|
|
20
|
+
// strips the quotes before `gh` is started, so `-f body="… \`pnpm josh ms\` …"` and
|
|
21
|
+
// `-f "body=… \`pnpm josh ms\` …"` hand `gh` one identical argument and execute one identical
|
|
22
|
+
// backtick. A pattern that knew only the first fired on half of the calls it was written for.
|
|
23
|
+
//
|
|
24
|
+
// **They are two alternatives rather than one optional quote on each side.** An optional quote after
|
|
25
|
+
// `body=` would also match `--field body=@$HOME/b.md`, capture the unquoted path up to some later
|
|
26
|
+
// quote, find the `$` in it and refuse the very file form this rule asks callers to use.
|
|
27
|
+
//
|
|
28
|
+
// **The separator is `=` as readily as whitespace**, because `gh` accepts `--field=body="…"` for the
|
|
29
|
+
// same reason `--body=…` works — which `MESSAGE_OPENING` below has always allowed. A pattern that
|
|
30
|
+
// only knew the space stayed silent on a call that executes the backtick.
|
|
31
|
+
const FIELD_OPENING = String.raw`${FIELD_FLAGS}[\s=]*(?:'?body="|"body=)`
|
|
32
|
+
const MESSAGE_OPENING = String.raw`${MESSAGE_FLAGS}[\s=]+"`
|
|
33
|
+
|
|
34
|
+
// One command substitution nested inside another — the `$(pwd)` of `$(cat "$(pwd)/x.md")`. One level
|
|
35
|
+
// is every spelling a run composes; deeper nesting stops matching and is read as ordinary text.
|
|
36
|
+
const NESTED_SUBSTITUTION = String.raw`\$\([^()]*\)`
|
|
37
|
+
|
|
38
|
+
// A whole command substitution, the quotes inside it included. **It belongs to the value pattern and
|
|
39
|
+
// not only to the exemption below**: `"` is legal inside `$( … )`, so a value that stopped at the
|
|
40
|
+
// first one truncated `$(cat "$(pwd)/x.md")` to `$(cat `, found the `$` and refused a caller who was
|
|
41
|
+
// already passing the body by path — spending the run's one delivery on a call that kept the rule.
|
|
42
|
+
//
|
|
43
|
+
// The branches are kept disjoint — `[^()$]` excludes the `$` the other two start with — so the match
|
|
44
|
+
// is linear rather than a nested quantifier that backtracks.
|
|
45
|
+
const SUBSTITUTION = String.raw`\$\((?:[^()$]|\$(?!\()|${NESTED_SUBSTITUTION})*\)`
|
|
46
|
+
|
|
47
|
+
// The text between the opening quote and the closing one: ordinary characters, a backslash escape, a
|
|
48
|
+
// lone `$`, or a whole substitution consumed in one piece so its inner quotes do not end the value.
|
|
49
|
+
const QUOTED_VALUE = String.raw`(?:[^"\\$]|\\.|\$(?!\()|${SUBSTITUTION})*`
|
|
50
|
+
|
|
51
|
+
const INLINE_BODY_VALUE = new RegExp(
|
|
52
|
+
`(?:${FIELD_OPENING}|${MESSAGE_OPENING})(${QUOTED_VALUE})"`,
|
|
53
|
+
'gu',
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
// **What zsh evaluates inside double quotes, measured in this harness rather than assumed**
|
|
57
|
+
// (joshuafolkken/kit#1198): a backtick runs as command substitution and a `$` expands. `!` does
|
|
58
|
+
// **not** — history expansion is off in a non-interactive zsh, and `"hello!world"` survives intact —
|
|
59
|
+
// so it is deliberately absent: a rule that fired on every exclamation mark would be firing on turns
|
|
60
|
+
// where nothing is wrong, which `prompts/collaboration-workflow/rule-delivery.md` names as worse than
|
|
61
|
+
// no hook at all.
|
|
62
|
+
const SHELL_EVALUATED = /[`$]/u
|
|
63
|
+
|
|
64
|
+
// **The one exemption: a body that is *entirely* one command substitution.** `body="$(cat <path>)"`
|
|
65
|
+
// is the rule already being kept — the substitution's output is not re-scanned by the shell, so a
|
|
66
|
+
// body full of backticks reaches the command byte for byte, and refusing it would spend the run's one
|
|
67
|
+
// delivery on a caller who had already moved the body into a file.
|
|
68
|
+
//
|
|
69
|
+
// **It is anchored to the whole value, not to the `$(` alone.** Excusing `$(` anywhere would let
|
|
70
|
+
// `body="Result: run $(git log -1) to confirm"` through, and that one really is evaluated: the
|
|
71
|
+
// substitution replaces the text and the command runs.
|
|
72
|
+
const WHOLE_VALUE_SUBSTITUTION = new RegExp(`^${SUBSTITUTION}$`, 'u')
|
|
73
|
+
|
|
74
|
+
// **A backtick inside the substitution voids the exemption.** The exemption's reason is that the
|
|
75
|
+
// *output* is not re-scanned — but the substitution's own command is shell text, and a backtick in it
|
|
76
|
+
// runs exactly as an inline one does. `body="$(echo \`date\`)"` executes `date`, which is the damage
|
|
77
|
+
// joshuafolkken/kit#1198 was filed over, merely written one level in. A nested `$( … )` is the safe
|
|
78
|
+
// spelling of the same composition and stays exempt.
|
|
79
|
+
const BACKTICK = '`'
|
|
80
|
+
|
|
81
|
+
// **The other spelling of "already in a file": `body=@<path>`.** The unquoted `--field body=@<path>`
|
|
82
|
+
// never reaches the pattern at all, and `--field "body=@$HOME/body.md"` is that same call with the
|
|
83
|
+
// quote moved one character left — so it is excused for the same reason, and by the same shape of
|
|
84
|
+
// test as the substitution above: the *whole* value is the reference. A body that merely opens with
|
|
85
|
+
// an `@mention` is not one, so it carries a space and still fires.
|
|
86
|
+
const WHOLE_VALUE_FILE_REFERENCE = /^@\S+$/u
|
|
87
|
+
|
|
88
|
+
// A backslash escape makes the next character literal inside double quotes, so `\$` and `` \` `` are
|
|
89
|
+
// safe. They are dropped before the test rather than excluded from it, which is the same thing in one
|
|
90
|
+
// pass and keeps `SHELL_EVALUATED` readable.
|
|
91
|
+
const ESCAPED_PAIR = /\\./gu
|
|
92
|
+
|
|
93
|
+
function is_whole_value_substitution(literal: string): boolean {
|
|
94
|
+
return WHOLE_VALUE_SUBSTITUTION.test(literal) && !literal.includes(BACKTICK)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function is_body_already_in_a_file(literal: string): boolean {
|
|
98
|
+
return WHOLE_VALUE_FILE_REFERENCE.test(literal) || is_whole_value_substitution(literal)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function is_evaluated_value(raw_value: string): boolean {
|
|
102
|
+
const literal = raw_value.replaceAll(ESCAPED_PAIR, '')
|
|
103
|
+
|
|
104
|
+
if (is_body_already_in_a_file(literal)) return false
|
|
105
|
+
|
|
106
|
+
return SHELL_EVALUATED.test(literal)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// **The trigger is the body's content, not the flag.** Every worked example in this repository's
|
|
110
|
+
// prompts passes a placeholder (`-f body="<plan>"`), which is inert; the moment a real body carrying
|
|
111
|
+
// a backtick is substituted in, the call becomes the one that executes text. Keying on the flag would
|
|
112
|
+
// refuse the inert examples too — firing on turns where the rule is already being kept.
|
|
113
|
+
function is_shell_evaluated_body(command: string): boolean {
|
|
114
|
+
for (const match of command.matchAll(INLINE_BODY_VALUE)) {
|
|
115
|
+
if (is_evaluated_value(match[1] ?? '')) return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return false
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// **The safe spellings, which is what keeping this rule looks like** (joshuafolkken/kit#1643). They
|
|
122
|
+
// are the ones the refusal hands back: the `*-file` flags, a field whose value is a file reference,
|
|
123
|
+
// and `$'…'` quoting. The `*-file` flags cannot reach `INLINE_BODY_VALUE` at all — the note at the top
|
|
124
|
+
// of this file records why — so they are read straight off the command rather than out of a value.
|
|
125
|
+
const FILE_FLAG = /(?:--body-file|--notify-message-file)(?:[\s=]|$)/u
|
|
126
|
+
const FIELD_FILE_REFERENCE = new RegExp(String.raw`${FIELD_FLAGS}[\s=]*body=@\S`, 'u')
|
|
127
|
+
// **`$'…'` is the other form the refusal sanctions**, because zsh expands neither a backtick nor a `$`
|
|
128
|
+
// inside it. Only the **double**-quoted spans are blanked before it is read: blanking the single-quoted
|
|
129
|
+
// span is exactly what would hide the form itself, while leaving the double-quoted ones would credit
|
|
130
|
+
// `grep -rn "--body=$'" scripts/rules` — a run reading this repository — as one that passed a body.
|
|
131
|
+
const ANSI_C_BODY = /(?:(?:--body|--notify-message)[\s=]+|body=)\$'/u
|
|
132
|
+
const DOUBLE_QUOTED_SPAN = /"[^"]*"/gu
|
|
133
|
+
|
|
134
|
+
// **Any spelling that hands a command a body, whatever the quoting.** The trigger above reads double
|
|
135
|
+
// quotes alone, because those are the ones the shell evaluates; the occasion the rule governs is
|
|
136
|
+
// wider, and leaving a `$'…'` or single-quoted body out of it would drop from the denominator exactly
|
|
137
|
+
// the compliant runs this predicate was added to keep in it.
|
|
138
|
+
const BODY_FLAG = new RegExp(
|
|
139
|
+
String.raw`${FIELD_FLAGS}[\s=]*'?"?body=|${MESSAGE_FLAGS}[\s=]|--body-file[\s=]|--notify-message-file[\s=]`,
|
|
140
|
+
'u',
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
// **A flag is only a flag outside the quotes**, the same reading `run-tail.ts` takes of a pull-request
|
|
144
|
+
// title. This repository's own refusal text names `--body-file <path>`, so a `grep` or an `echo`
|
|
145
|
+
// quoting it would otherwise be scored as a run that passed a body by path. The quoted spellings of
|
|
146
|
+
// the same thing are not lost by blanking: `--field "body=@<path>"` is a whole-value file reference,
|
|
147
|
+
// which the literal branch below reads.
|
|
148
|
+
const QUOTED_SPAN = /"[^"]*"|'[^']*'/gu
|
|
149
|
+
|
|
150
|
+
function inline_body_literals(command: string): Array<string> {
|
|
151
|
+
return Array.from(command.matchAll(INLINE_BODY_VALUE), (match) =>
|
|
152
|
+
(match[1] ?? '').replaceAll(ESCAPED_PAIR, ''),
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function is_safe_body_form(command: string): boolean {
|
|
157
|
+
if (ANSI_C_BODY.test(command.replaceAll(DOUBLE_QUOTED_SPAN, ' '))) return true
|
|
158
|
+
|
|
159
|
+
const flags = command.replaceAll(QUOTED_SPAN, ' ')
|
|
160
|
+
|
|
161
|
+
if (FILE_FLAG.test(flags) || FIELD_FILE_REFERENCE.test(flags)) return true
|
|
162
|
+
|
|
163
|
+
return inline_body_literals(command).some((literal) => is_body_already_in_a_file(literal))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// **A call that passes its body safely and executes none inline.** The measurement asks a call whether
|
|
167
|
+
// it kept the rule before it asks whether it broke it, so a call doing both would be credited for the
|
|
168
|
+
// half it got right; requiring the absence of an evaluated body is what stops that.
|
|
169
|
+
function keeps_body_safe(command: string): boolean {
|
|
170
|
+
return is_safe_body_form(command) && !is_shell_evaluated_body(command)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// **The occasion this rule governs: a body handed to a command at all**, in every spelling. It is the
|
|
174
|
+
// denominator `rule-value.ts` reads, and it exists because this rule's trigger fires only on the
|
|
175
|
+
// violation — a run that passed every body safely would otherwise never appear in the reading.
|
|
176
|
+
function carries_a_body(command: string): boolean {
|
|
177
|
+
if (BODY_FLAG.test(command.replaceAll(QUOTED_SPAN, ' '))) return true
|
|
178
|
+
|
|
179
|
+
return inline_body_literals(command).length > 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// The instruction in the shape a refusal can carry: what the shell is about to do, the safe
|
|
183
|
+
// spellings, and the reissue sentence every delivery needs. The damage is named because it is the
|
|
184
|
+
// half that reads as unbelievable — the substituted text is *executed*, not discarded. It lives here
|
|
185
|
+
// beside its trigger rather than inline in the enumeration, the shape every newer row's reason takes
|
|
186
|
+
// (`git-force.ts`, `lane-carry-conflict.ts`).
|
|
187
|
+
const SHELL_BODY_REASON =
|
|
188
|
+
'⛔ shell-evaluated body: this command carries a body inline in double quotes, and that body ' +
|
|
189
|
+
'contains a backtick or a `$`, so the shell runs it — the text is executed rather than merely ' +
|
|
190
|
+
'mangled (joshuafolkken/kit#1198). Write the body to a file and pass it by path: `pnpm josh ' +
|
|
191
|
+
'issue:comment <N> --body-file <path>`, `pnpm josh followup --notify-message-file <path>`, or ' +
|
|
192
|
+
"`--body-file <path>` wherever offered. `$'…'` quoting is the other safe form; the rule and the " +
|
|
193
|
+
"trigger's blind spots are in `prompts/collaboration-workflow/shell-body.md`. Reissue this call " +
|
|
194
|
+
'once the body is in a file — it fires once per run and cannot repeat on the call in hand.'
|
|
195
|
+
|
|
196
|
+
const shell_body_trigger = {
|
|
197
|
+
SHELL_BODY_REASON,
|
|
198
|
+
carries_a_body,
|
|
199
|
+
is_safe_body_form,
|
|
200
|
+
is_shell_evaluated_body,
|
|
201
|
+
keeps_body_safe,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { shell_body_trigger }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
2
|
+
|
|
3
|
+
// **A shell line carries several commands, and each has to be judged on its own.** Every trigger in
|
|
4
|
+
// this directory that reads a command string needs the same cut, so the cut lives here rather than
|
|
5
|
+
// beside whichever trigger needed it first — the clone `CLAUDE.md` prohibits is two copies of a
|
|
6
|
+
// pattern that would then have to be corrected twice.
|
|
7
|
+
//
|
|
8
|
+
// **A bare `|` is deliberately not a separator.** It appears inside a `--jq` filter far more often
|
|
9
|
+
// than between two commands, and cutting there would split one call into fragments neither of which
|
|
10
|
+
// is command-shaped. The rule that *is* about a pipe reads the whole line instead
|
|
11
|
+
// (`piped-verification.ts`).
|
|
12
|
+
//
|
|
13
|
+
// **`early-heartbeat.ts` keeps its own separator on purpose** and is not a caller here: it adds `&`,
|
|
14
|
+
// because `sleep 1200 &` is an armed timer sent to the background and has to be seen as one. That is
|
|
15
|
+
// a different question about a different character, not a second copy of this answer.
|
|
16
|
+
const SEGMENT_SEPARATOR = /&&|\|\||;|\n/u
|
|
17
|
+
|
|
18
|
+
/** The line's commands, trimmed. Empty segments are kept: a caller anchoring at `^` rejects them. */
|
|
19
|
+
function segments_of(command: string): Array<string> {
|
|
20
|
+
return command.split(SEGMENT_SEPARATOR).map((segment) => segment.trim())
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// **Both spellings still match, and the expansion is no longer this file's** (joshuafolkken/kit#1643
|
|
24
|
+
// for the reading, joshuafolkken/kit#1789 for where it now happens). A `josh_names` here used to widen
|
|
25
|
+
// each caller's set with every alias standing for one of its names; `josh_command_of` expands the
|
|
26
|
+
// alias in the command it reads, so `pnpm josh ga` arrives as `josh gate` and a caller's canonical set
|
|
27
|
+
// matches it as it is. Widening as well would be a second copy of one rule, and the caller that
|
|
28
|
+
// forgot it would be the one that stops seeing `pnpm josh ga` at all — which is why each caller's own
|
|
29
|
+
// suite names a call in its alias spelling.
|
|
30
|
+
/** Whether this segment invokes one of the named josh subcommands, in either spelling. */
|
|
31
|
+
function is_josh_command(segment: string, names: ReadonlySet<string>): boolean {
|
|
32
|
+
const named = time_shell.josh_command_of(segment)
|
|
33
|
+
|
|
34
|
+
if (!named.startsWith(time_shell.JOSH_PREFIX)) return false
|
|
35
|
+
|
|
36
|
+
return names.has(named.slice(time_shell.JOSH_PREFIX.length))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const shell_segments = {
|
|
40
|
+
SEGMENT_SEPARATOR,
|
|
41
|
+
is_josh_command,
|
|
42
|
+
segments_of,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { shell_segments }
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
2
|
+
import { z } from 'zod'
|
|
3
|
+
import { filing_offer } from './filing-offer'
|
|
4
|
+
import { issue_citation } from './issue-citation'
|
|
5
|
+
import { reply_language } from './reply-language'
|
|
6
|
+
|
|
7
|
+
// The stop-time rules, delivered on the `Stop` hook (joshuafolkken/kit#2121, joshuafolkken/kit#2422,
|
|
8
|
+
// joshuafolkken/kit#2445).
|
|
9
|
+
//
|
|
10
|
+
// **It exists because `.claude/settings.json` wired no `Stop` event.** The four events it did wire
|
|
11
|
+
// (`SessionStart` / `UserPromptSubmit` / `PreToolUse` / `PostToolUse`) can catch the moment a call is
|
|
12
|
+
// about to run, but not the moment a run *stops* or *reports* — so three rules whose inputs are all
|
|
13
|
+
// mechanically readable could not be enforced structurally (`prompts/collaboration-workflow/rule-delivery.md`).
|
|
14
|
+
//
|
|
15
|
+
// **No second decision engine.** This loads on the same `hook_decision` foundation the PreToolUse
|
|
16
|
+
// guards share — the `.env` load and the switch — and reuses `lane-park`'s stop-notification judgement
|
|
17
|
+
// and `run:hold`'s record read rather than re-deriving either. What differs is only the event: a
|
|
18
|
+
// `Stop` payload has no tool call, and it blocks with `{"decision":"block"}` rather than a PreToolUse
|
|
19
|
+
// permission envelope. The stop guard is a second *entry* on the one foundation, exactly as
|
|
20
|
+
// `pretool-guard` is one — not a second copy of the plumbing.
|
|
21
|
+
//
|
|
22
|
+
// **Every rule refuses** (joshuafolkken/kit#2247). Missing the stop notification or leaving a hold
|
|
23
|
+
// on a clean tree costs a person a silent wait or a trampled tree; a bare `#N` in the reply reaches
|
|
24
|
+
// the person watching but not the model that could fix it, so it too blocks — `{"decision":"block"}`
|
|
25
|
+
// is the one channel a `Stop` hook has to the model, and `stop_hook_active` caps a false positive at a
|
|
26
|
+
// single wasted turn. The detection is tightened to match (`issue-citation.ts`, `filing-offer.ts`).
|
|
27
|
+
|
|
28
|
+
const SWITCH_ENV_KEY = 'JOSH_STOP_GUARD'
|
|
29
|
+
const BLOCK_DECISION = 'block'
|
|
30
|
+
|
|
31
|
+
// Only the fields the stop rules read. `last_assistant_message` is the turn's session-facing text —
|
|
32
|
+
// Claude Code hands it directly so the transcript's async lag is never in the citation path.
|
|
33
|
+
const stop_payload_schema = z.object({
|
|
34
|
+
transcript_path: z.string().min(1),
|
|
35
|
+
stop_hook_active: z.boolean().nullish(),
|
|
36
|
+
last_assistant_message: z.string().nullish(),
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
type StopPayload = z.infer<typeof stop_payload_schema>
|
|
40
|
+
|
|
41
|
+
// What one stop looks like to the rules, computed once by the CLI from the payload and the world.
|
|
42
|
+
interface StopContext {
|
|
43
|
+
// The `run:hold` record for this working tree is still in place (`held` or `stale`).
|
|
44
|
+
hold_present: boolean
|
|
45
|
+
// `git status --porcelain` came back empty.
|
|
46
|
+
tree_clean: boolean
|
|
47
|
+
// A `confirmation` notify is on this run's transcript tail.
|
|
48
|
+
notified: boolean
|
|
49
|
+
// The turn's session-facing reply text.
|
|
50
|
+
message: string
|
|
51
|
+
// This stop already forced a continuation earlier in the prompt — the loop-breaker Claude Code
|
|
52
|
+
// documents, so a run that will not comply is not blocked forever.
|
|
53
|
+
stop_hook_active: boolean
|
|
54
|
+
// A pre-gate cut record is in place for this work tree. A dispatched lane child ends its turn at
|
|
55
|
+
// the cut holding the tree by design and hands off to a fresh process (`pre-gate-cut.md`), so that
|
|
56
|
+
// turn-end is an automatic continuation, not the person-waiting pause the block rules are for.
|
|
57
|
+
cut_pending: boolean
|
|
58
|
+
// An Issue filing no guard refused is on this run's transcript tail — `filing_cap`'s count.
|
|
59
|
+
filed: boolean
|
|
60
|
+
// The owner of the repository the session runs in, or `undefined` when it cannot be read.
|
|
61
|
+
session_owner: string | undefined
|
|
62
|
+
// This session is a headless `backlogrun` parent with lanes still in flight and no cut handed its
|
|
63
|
+
// record off — `run-headless.ts` → `must_keep_waiting` (joshuafolkken/kit#2437).
|
|
64
|
+
headless_waiting: boolean
|
|
65
|
+
// How many headless-wait refusals sit on this run's transcript tail — the spin bound below.
|
|
66
|
+
headless_refusals: number
|
|
67
|
+
// This session is a dispatched lane child for this checkout — `lane_child_marker.is_child_of`.
|
|
68
|
+
lane_child: boolean
|
|
69
|
+
// The resolved `JOSH_SESSION_LANG` — `session_language.resolve_session_lang` (joshuafolkken/kit#2470).
|
|
70
|
+
session_lang: string
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface StopOutcome {
|
|
74
|
+
reason: string | undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const NO_OUTCOME: StopOutcome = { reason: undefined }
|
|
78
|
+
|
|
79
|
+
// **A mid-workflow stop is announced off-screen before it happens.** `CLAUDE.md` → "Mid-workflow stop
|
|
80
|
+
// notification" requires the `confirmation` Telegram before any pause; the hold is what says a run is
|
|
81
|
+
// mid-workflow, and the transcript is what says the notify was sent.
|
|
82
|
+
const STOP_NOTIFY_REASON =
|
|
83
|
+
'⛔ mid-workflow stop notification: this working tree is still held by a run and no `confirmation` ' +
|
|
84
|
+
'Telegram was sent this turn, so a person is being left to wait off-screen without knowing the run ' +
|
|
85
|
+
'paused. `CLAUDE.md` → "Mid-workflow stop notification" requires ' +
|
|
86
|
+
'`pnpm josh notify --task-type confirmation --issue-url "<url>" --body=$\'<reason>\'` before any ' +
|
|
87
|
+
'mid-workflow pause. Send it, then end with a one-line confirmation that it was sent — do not repeat ' +
|
|
88
|
+
'your previous reply. This fires only while the hold is held and no notify is on the transcript, and ' +
|
|
89
|
+
'`stop_hook_active` lets a second stop through so a run is never wedged.'
|
|
90
|
+
|
|
91
|
+
// **A clean tree that still holds is a tree the next run will trample.** `SKILL.md` → §2f: a stop that
|
|
92
|
+
// leaves the tree clean releases the hold; a `halfrun` pre-commit stop and a `needs-human-review` stop
|
|
93
|
+
// keep it because their tree is dirty, which is why this row is silent whenever the tree is not clean.
|
|
94
|
+
const HOLD_RELEASE_REASON =
|
|
95
|
+
'⛔ working-tree hold not released: this working tree is clean but its `run:hold` record is still in ' +
|
|
96
|
+
'place, so the next run here runs `git switch main && git pull` believing the tree is free while ' +
|
|
97
|
+
'you hold it. `.claude/skills/workflow-commands/SKILL.md` → §2f: a stop that leaves the tree clean ' +
|
|
98
|
+
'releases the hold with `pnpm josh run:release <N>` (bare for a `new` entry). A `halfrun` ' +
|
|
99
|
+
'pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty — this ' +
|
|
100
|
+
'row is silent there. Release it, then end with a one-line confirmation that it was released — do ' +
|
|
101
|
+
'not repeat your previous reply.'
|
|
102
|
+
|
|
103
|
+
// **A refusal that corrects rather than advises** (joshuafolkken/kit#2247). The bare `#N` is already
|
|
104
|
+
// on screen and the hook cannot unsay it, so the reason does the one thing that helps the *next* reply:
|
|
105
|
+
// it names the numbers it detected and hands over the exact `issue:cite` call that prints the
|
|
106
|
+
// paste-ready lines, then asks for the corrected citation lines alone — not the whole reply reissued
|
|
107
|
+
// (joshuafolkken/kit#2329). Reprinting the whole reply is what made the correction read as a duplicate;
|
|
108
|
+
// the bare copy already scrolled past stays, and the fix follows it as a short correction. The rule
|
|
109
|
+
// itself is not restated — it is resident in `CLAUDE.md` — only pointed at.
|
|
110
|
+
const ISSUE_CITATION_REASON =
|
|
111
|
+
'Session-facing output cites an Issue as a number-link so the reader can click through and see ' +
|
|
112
|
+
'which repository it is (`CLAUDE.md`, `prompts/collaboration-workflow/issue-citation.md`).'
|
|
113
|
+
|
|
114
|
+
function build_citation_reason(references: ReadonlyArray<string>): string {
|
|
115
|
+
const numbers = references.join(', ')
|
|
116
|
+
const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(' ')}`
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
`⛔ issue citation: your reply names an Issue as a bare \`#N\` (${numbers}). Run \`${command}\` ` +
|
|
120
|
+
`to print the paste-ready citation lines, then print the corrected citation lines alone — do not ` +
|
|
121
|
+
`repeat your previous reply. ${ISSUE_CITATION_REASON}`
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// **An offer to file is a Tier A filing deferred to the user** (joshuafolkken/kit#2422). The judgement
|
|
126
|
+
// is already made, so the reason hands over the filing chain rather than a question; the rule itself
|
|
127
|
+
// is resident in `SKILL.md` → §2i and only pointed at.
|
|
128
|
+
const FILING_OFFER_REASON =
|
|
129
|
+
'⛔ filing offer: your reply offers to file an Issue instead of filing it. Filing into a ' +
|
|
130
|
+
'first-party repository is Tier A — the trigger is the judgement that it is worth filing, not the ' +
|
|
131
|
+
"run's progress (`.claude/skills/workflow-commands/SKILL.md` → §2i, `observation-filing.md`). Run " +
|
|
132
|
+
'`pnpm josh issue:scout "<title>"`, file it, run `pnpm josh epic:bundle <new>`, then end with the ' +
|
|
133
|
+
'one-line citation of what was filed — do not repeat your previous reply. If it is not worth filing ' +
|
|
134
|
+
'after all, say so in one line instead.'
|
|
135
|
+
|
|
136
|
+
// **A headless parent's turn-end is its process's end** (joshuafolkken/kit#2437). Under `claude -p` the
|
|
137
|
+
// background waits die with the turn, so the lanes lose their parent and nothing re-invokes it. The
|
|
138
|
+
// reason hands over the foreground wait rather than a question, because there is nobody to answer one.
|
|
139
|
+
// The refusal's opening, which the transcript tail is counted by.
|
|
140
|
+
const HEADLESS_WAIT_MARKER = '⛔ headless parent:'
|
|
141
|
+
|
|
142
|
+
// Refusals with no foreground wait between them before the loop-breaker is honoured again. A parent
|
|
143
|
+
// that obeys runs a wait after each refusal, which resets the count; one that only re-stops piles them
|
|
144
|
+
// up. The bound lets that one end when "in flight" is a kept lane no child is working in
|
|
145
|
+
// (`backlogrun-park.md`), rather than spinning until the carry record expires.
|
|
146
|
+
const HEADLESS_REFUSAL_CAP = 3
|
|
147
|
+
|
|
148
|
+
// The foreground waits as they appear in a transcript's tool-call input — the JSON `command` field, so
|
|
149
|
+
// the refusal's own prose, which names the same commands, never matches.
|
|
150
|
+
const HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress']
|
|
151
|
+
|
|
152
|
+
const HEADLESS_WAIT_BODY =
|
|
153
|
+
' this is a `claude -p` `backlogrun` parent (`JOSH_RUN_HEADLESS`) with lanes still ' +
|
|
154
|
+
'in flight, and ending this turn ends the process — its background waits are killed with it and the ' +
|
|
155
|
+
'lanes are left without a parent. Wait in the foreground instead: run `pnpm josh lane:await <N...>` ' +
|
|
156
|
+
'for the in-flight lanes (and `pnpm josh run:progress --wait` for the heartbeat) as foreground ' +
|
|
157
|
+
'commands within the tool timeout, act on what they report, and continue the loop. End the turn only ' +
|
|
158
|
+
'after `pnpm josh run:carry --cut` or `--end` (`backlogrun-progress.md` → "The parent keeps no clock ' +
|
|
159
|
+
'of its own").'
|
|
160
|
+
|
|
161
|
+
const HEADLESS_WAIT_REASON = `${HEADLESS_WAIT_MARKER}${HEADLESS_WAIT_BODY}`
|
|
162
|
+
|
|
163
|
+
// **A lane child never asks a person for the index** (joshuafolkken/kit#2445). The index rule protects
|
|
164
|
+
// a person's own staging, and a lane is a per-run work tree with none to protect; the sanctioned commit
|
|
165
|
+
// flow is already authorized, so the reason hands it over instead of letting the run wait on a person.
|
|
166
|
+
// Both halves must appear — an index command and a request for permission — so a report that merely
|
|
167
|
+
// names `git add` is not refused.
|
|
168
|
+
const INDEX_COMMAND_PATTERN = /git (?:add|stage|rm --cached|restore --staged|restore -S)\b/u
|
|
169
|
+
const PERMISSION_PATTERN = /許可|承認|permission|approve|approval|authorization/iu
|
|
170
|
+
|
|
171
|
+
const LANE_INDEX_REASON =
|
|
172
|
+
'⛔ lane index permission: this is a dispatched lane child (`JOSH_LANE_CHILD`) and your reply asks ' +
|
|
173
|
+
"a person for permission to change the git index. A lane is a per-run work tree with no person's " +
|
|
174
|
+
'staging to protect, and the sanctioned commit flow is already authorized: remove any conflict ' +
|
|
175
|
+
'markers, then run `pnpm josh git -y`, which stages and commits them — a conflicted merge included. ' +
|
|
176
|
+
'This is Tier A (`.claude/skills/workflow-commands/chain-rule.md` → "origin/main is merged in before ' +
|
|
177
|
+
'the gate"). Do it and continue the run — do not repeat your previous reply.'
|
|
178
|
+
|
|
179
|
+
function asks_index_permission(message: string): boolean {
|
|
180
|
+
return INDEX_COMMAND_PATTERN.test(message) && PERMISSION_PATTERN.test(message)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function needs_index_route(context: StopContext): boolean {
|
|
184
|
+
return context.lane_child && asks_index_permission(context.message)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// **A refusal is the turn's only input, so it names the language the answer is written in**
|
|
188
|
+
// (joshuafolkken/kit#2470). The session-language line reaches a turn only through `UserPromptSubmit`;
|
|
189
|
+
// a turn this hook continues has no prompt, and an English refusal read alone was answered in English.
|
|
190
|
+
function language_note(lang: string): string {
|
|
191
|
+
return (
|
|
192
|
+
`Write your reply in the session language (JOSH_SESSION_LANG: ${lang}); code, commands and ` +
|
|
193
|
+
'identifiers stay as they are.'
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// **A reply that drifted out of the session language is sent back once to be rewritten**
|
|
198
|
+
// (joshuafolkken/kit#2470). The drift persists — each turn matches the language of the one before — so
|
|
199
|
+
// the rewrite has to happen on the turn it starts; `stop_hook_active` bounds it to one.
|
|
200
|
+
function build_language_reason(lang: string): string {
|
|
201
|
+
return (
|
|
202
|
+
`⛔ session language: your reply is not written in the session language (JOSH_SESSION_LANG: ` +
|
|
203
|
+
`${lang}). Rewrite it in that language and keep writing in it on the turns that follow, whatever ` +
|
|
204
|
+
'language a notification, tool output or hook message was in (`CLAUDE.md` → "Output language").'
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function language_reason(context: StopContext): string | undefined {
|
|
209
|
+
if (!reply_language.is_mismatch(context.message, context.session_lang)) return undefined
|
|
210
|
+
|
|
211
|
+
return build_language_reason(context.session_lang)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function needs_filing(context: StopContext): boolean {
|
|
215
|
+
if (context.filed || !filing_offer.offers_filing(context.message)) return false
|
|
216
|
+
|
|
217
|
+
return filing_offer.is_first_party_target(context.message, context.session_owner)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function needs_notify(context: StopContext): boolean {
|
|
221
|
+
return context.hold_present && !context.notified
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function needs_release(context: StopContext): boolean {
|
|
225
|
+
return context.hold_present && context.tree_clean
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function citation_reason(message: string): string | undefined {
|
|
229
|
+
const references = issue_citation.bare_references(message)
|
|
230
|
+
if (references.length === 0) return undefined
|
|
231
|
+
|
|
232
|
+
return build_citation_reason(references)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The three rules that read the reply itself, filing offer first and the language last. A drifted reply
|
|
236
|
+
// refused for another reason is not rewritten, but the drift still ends: `block_envelope` appends the
|
|
237
|
+
// session-language note to every refusal, so the turn it continues is written in the session language.
|
|
238
|
+
function reply_reason(context: StopContext): string | undefined {
|
|
239
|
+
if (needs_filing(context)) return FILING_OFFER_REASON
|
|
240
|
+
|
|
241
|
+
return citation_reason(context.message) ?? language_reason(context)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// The headless wait holds past the loop-breaker until the spin bound is reached.
|
|
245
|
+
function is_headless_held(context: StopContext): boolean {
|
|
246
|
+
if (!context.headless_waiting) return false
|
|
247
|
+
|
|
248
|
+
return !context.stop_hook_active || context.headless_refusals < HEADLESS_REFUSAL_CAP
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// The headless-wait refusals on a transcript tail since the last foreground wait the parent ran — a
|
|
252
|
+
// wait is progress, so only refusals with none between them count toward the spin bound.
|
|
253
|
+
function count_headless_refusals(tail: string): number {
|
|
254
|
+
const last_wait = Math.max(...HEADLESS_WAIT_CALLS.map((call) => tail.lastIndexOf(call)))
|
|
255
|
+
|
|
256
|
+
return tail.slice(Math.max(last_wait, 0)).split(HEADLESS_WAIT_MARKER).length - 1
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// The two hold rules, notify ahead of release — behind the lane index route (joshuafolkken/kit#2445),
|
|
260
|
+
// since the notify they would ask for announces a pause the run has no reason to take.
|
|
261
|
+
function hold_reason(context: StopContext): string | undefined {
|
|
262
|
+
if (needs_index_route(context)) return LANE_INDEX_REASON
|
|
263
|
+
if (needs_notify(context)) return STOP_NOTIFY_REASON
|
|
264
|
+
if (needs_release(context)) return HOLD_RELEASE_REASON
|
|
265
|
+
|
|
266
|
+
return undefined
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// First-wins across every rule. Two things stand every rule down: `stop_hook_active` (the
|
|
270
|
+
// loop-breaker, so a run that already got one continuation this prompt may stop) and a pre-gate cut in
|
|
271
|
+
// flight (a lane child's automatic turn-end, not a person-waiting pause). The two hold rules keep their
|
|
272
|
+
// order ahead of the reply rules, so a stop that both still owes its notify and holds a bare `#N` still
|
|
273
|
+
// reports the notify first; the filing offer goes ahead of the citation, since the filing it forces
|
|
274
|
+
// produces the citation the reply then needs.
|
|
275
|
+
//
|
|
276
|
+
// **The headless wait comes first and outlasts `stop_hook_active` up to its spin bound** (joshuafolkken/kit#2437).
|
|
277
|
+
// The loop-breaker exists so a person is not wedged behind a rule the run will not satisfy; a headless
|
|
278
|
+
// parent has no person, and letting its second stop through is exactly the silent end the rule is for.
|
|
279
|
+
// Each continuation it forces is a foreground wait of minutes, and the rule falls silent by itself once
|
|
280
|
+
// the lanes finish or a cut hands the record off; refusals with no wait between them are bounded.
|
|
281
|
+
function block_reason(context: StopContext): string | undefined {
|
|
282
|
+
if (is_headless_held(context)) return HEADLESS_WAIT_REASON
|
|
283
|
+
if (context.stop_hook_active || context.cut_pending) return undefined
|
|
284
|
+
|
|
285
|
+
return hold_reason(context) ?? reply_reason(context)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function stop_outcome(context: StopContext): StopOutcome {
|
|
289
|
+
return { reason: block_reason(context) }
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// The documented shape a `Stop` hook blocks with: `reason` is fed back to Claude, which then continues
|
|
293
|
+
// instead of stopping. Plain stdout is not it — only this envelope holds the stop. Every reason leaves
|
|
294
|
+
// with the session-language note, so no rule can hand the model an English-only turn.
|
|
295
|
+
function block_envelope(reason: string, lang: string): string {
|
|
296
|
+
return JSON.stringify({ decision: BLOCK_DECISION, reason: `${reason} ${language_note(lang)}` })
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function parse_stop_payload(raw_payload: string): StopPayload | undefined {
|
|
300
|
+
const parsed = stop_payload_schema.safeParse(JSON.parse(raw_payload))
|
|
301
|
+
|
|
302
|
+
return parsed.success ? parsed.data : undefined
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function is_enabled(): boolean {
|
|
306
|
+
return hook_decision.is_switch_enabled(SWITCH_ENV_KEY)
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const stop_rules = {
|
|
310
|
+
FILING_OFFER_REASON,
|
|
311
|
+
HEADLESS_REFUSAL_CAP,
|
|
312
|
+
HEADLESS_WAIT_REASON,
|
|
313
|
+
HOLD_RELEASE_REASON,
|
|
314
|
+
ISSUE_CITATION_REASON,
|
|
315
|
+
LANE_INDEX_REASON,
|
|
316
|
+
NO_OUTCOME,
|
|
317
|
+
STOP_NOTIFY_REASON,
|
|
318
|
+
SWITCH_ENV_KEY,
|
|
319
|
+
block_envelope,
|
|
320
|
+
block_reason,
|
|
321
|
+
build_language_reason,
|
|
322
|
+
count_headless_refusals,
|
|
323
|
+
is_enabled,
|
|
324
|
+
parse_stop_payload,
|
|
325
|
+
stop_outcome,
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
export type { StopContext, StopOutcome }
|
|
329
|
+
export { stop_rules }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { cost_blocks } from '#scripts/cost-runtime/cost-blocks'
|
|
2
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
3
|
+
import { time_transcript_line, type Block } from '#scripts/time-runtime/time-transcript-line'
|
|
4
|
+
|
|
5
|
+
// The `Bash` commands a run's transcript tail already issued, parsed once here rather than in each
|
|
6
|
+
// rule that needs them (joshuafolkken/kit#2119). `prior-comment-read.ts` had this reading first; the
|
|
7
|
+
// scout gate needs the same "what did the run already run" question, so a second copy would be the
|
|
8
|
+
// clone `CLAUDE.md` prohibits. The delivery path sees only the raw tail — `delivered-rules.ts` names
|
|
9
|
+
// the reason a run's own calls are not handed to it — so the earlier calls are recovered by parsing
|
|
10
|
+
// that tail the same way `time-batch-guard.ts` does.
|
|
11
|
+
|
|
12
|
+
// A `tool_use` block that ran a shell command.
|
|
13
|
+
function is_bash_use(block: Block): boolean {
|
|
14
|
+
return block.type === cost_blocks.TOOL_USE_TYPE && block.name === cost_blocks.BASH_TOOL
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// The Bash commands one transcript line issued, empty for a line that parses to none.
|
|
18
|
+
function bash_commands_of(line: string): ReadonlyArray<string> {
|
|
19
|
+
const parsed = time_transcript_line.parse_line(line)
|
|
20
|
+
|
|
21
|
+
if (parsed === undefined) return []
|
|
22
|
+
|
|
23
|
+
return parsed.blocks
|
|
24
|
+
.filter((block) => is_bash_use(block))
|
|
25
|
+
.map((block) => time_shell.bash_command(block.input))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Every Bash command the tail holds, in the order they were issued.
|
|
29
|
+
function prior_bash_commands(tail: string): ReadonlyArray<string> {
|
|
30
|
+
return tail.split('\n').flatMap((line) => bash_commands_of(line))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const tail_commands = { bash_commands_of, is_bash_use, prior_bash_commands }
|
|
34
|
+
|
|
35
|
+
export { tail_commands }
|