@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,637 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { cost_blocks } from '#scripts/cost-runtime/cost-blocks'
|
|
3
|
+
import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
|
|
4
|
+
import { hook_decision, type GuardRun } from '#scripts/josh/hook-decision'
|
|
5
|
+
import { time_batch_guard, type GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
6
|
+
import { time_bundle_call } from '#scripts/time-runtime/time-bundle-call'
|
|
7
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
8
|
+
import { time_spans, type Span } from '#scripts/time-runtime/time-spans'
|
|
9
|
+
import { delegation_policy } from './delegation-policy'
|
|
10
|
+
|
|
11
|
+
// How many files a run has read and not edited **since its last delegated unit**
|
|
12
|
+
// (joshuafolkken/kit#1460).
|
|
13
|
+
//
|
|
14
|
+
// **joshuafolkken/kit#1426 made the threshold a count rather than a forecast, and left the counting
|
|
15
|
+
// to the agent.** Measured on run #1441, that is a one-shot judgement: `josh delegate investigation`
|
|
16
|
+
// was called once at t+4.0 min, the unit returned at t+7.2, and the main line then read **8 more
|
|
17
|
+
// files it did not edit** — more than twice the threshold — without the question being asked a second
|
|
18
|
+
// time. The count is a memory, and after a delegation the run remembers the *step* as done rather
|
|
19
|
+
// than the *counter* as reset.
|
|
20
|
+
//
|
|
21
|
+
// **So the counting happens here, off the transcript, and not in the agent's head.** A delegation
|
|
22
|
+
// clears the set; a read adds to it; an edit takes its file back out of it. Nothing has to be
|
|
23
|
+
// remembered, which is why the threshold necessarily fires again — a second accumulation is
|
|
24
|
+
// indistinguishable from the first.
|
|
25
|
+
//
|
|
26
|
+
// **Why a mechanism and not wording.** joshuafolkken/kit#1344 measured three consecutive runs after
|
|
27
|
+
// the batching norm was distributed as prose and as a live notice: 1.10–1.12 calls per round trip
|
|
28
|
+
// against a 1.50 floor, unchanged. joshuafolkken/kit#1390 read that as the answer — intervene in the
|
|
29
|
+
// decision instead of describing it — and this is the same conclusion applied to the same class of
|
|
30
|
+
// rule. The wording is corrected too, but it is not what is expected to move the number.
|
|
31
|
+
|
|
32
|
+
const READ_TOOLS: ReadonlySet<string> = new Set(['Read'])
|
|
33
|
+
// The label a subagent call carries is the verbatim tool name (`time-spans.ts` → `to_tool_call`), and
|
|
34
|
+
// both spellings are in use: `Task` in the published tool set, `Agent` in this harness's transcripts.
|
|
35
|
+
// Neither has a constant anywhere, so the pair is named here rather than matched loosely.
|
|
36
|
+
const DELEGATION_TOOLS: ReadonlySet<string> = new Set(['Agent', 'Task'])
|
|
37
|
+
|
|
38
|
+
// **Narrower than `time-bundle-call.ts`'s `READ_COMMANDS`, deliberately.** That list answers which
|
|
39
|
+
// calls are bundleable, and it holds `grep`, `ls` and `wc` — commands that report *about* a file
|
|
40
|
+
// without carrying its text. What this rule counts is text arriving in the prompt, so only the
|
|
41
|
+
// commands that print a file belong here.
|
|
42
|
+
const CONTENT_READ_COMMANDS: ReadonlyArray<string> = [
|
|
43
|
+
'bat',
|
|
44
|
+
'cat',
|
|
45
|
+
'head',
|
|
46
|
+
'less',
|
|
47
|
+
'more',
|
|
48
|
+
'nl',
|
|
49
|
+
'sed',
|
|
50
|
+
'tail',
|
|
51
|
+
]
|
|
52
|
+
// Built through `bash_label` so the `Bash: ` prefix is spelled in one place — the labels on a span
|
|
53
|
+
// come from that same function.
|
|
54
|
+
const CONTENT_READ_LABELS: ReadonlySet<string> = new Set(
|
|
55
|
+
CONTENT_READ_COMMANDS.map((command) => time_shell.bash_label(command)),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
// What the refusal tells the model. It has to name the count, the command and the return shape,
|
|
59
|
+
// because the deny reason is the only text that reaches the model — a run that is refused and told
|
|
60
|
+
// nothing reads it as a broken tool.
|
|
61
|
+
const REASON = `⛔ investigation: ${String(delegation_policy.INVESTIGATION_FILE_THRESHOLD)} files read and not edited since the last delegated unit, so the reading from here goes to a unit of its own. Ask \`pnpm josh delegate investigation\`, then brief a unit with what the main line has already concluded and what is left to find out; it returns the conclusion plus its \`file:line\` citations, never the file text. Keep a read in the main line only where this run will edit that file — an \`Edit\` cannot be issued against text you do not hold. This run's own instructions and the harness's own session files — a backgrounded call's output, a persisted tool result, this session's scratchpad — are never counted, so they are not what took the count here. The rule is \`.claude/skills/workflow-commands/SKILL.md\` → §2b, "The pre-implementation reading".`
|
|
62
|
+
|
|
63
|
+
interface ReadTally {
|
|
64
|
+
// The files read and not since edited, resolved so the two ways a target reaches here compare.
|
|
65
|
+
pending: ReadonlyArray<string>
|
|
66
|
+
// How many of those entered the set **after** the instant the caller asked about — the refusal's,
|
|
67
|
+
// in the one call that matters (joshuafolkken/kit#1764). It is the second way a refusal re-arms:
|
|
68
|
+
// a run that ignores the one refusal it gets goes on accumulating, and a threshold's worth of new
|
|
69
|
+
// unedited files is a second accumulation whatever the run did about the first.
|
|
70
|
+
pending_since: number
|
|
71
|
+
// When the last delegated unit closed, or `NEVER_MS` where the window holds none. This is what
|
|
72
|
+
// re-arms a refusal: a delegation after the recorded one is a new accumulation.
|
|
73
|
+
reset_ms: number
|
|
74
|
+
// The first instant the window covers. A refusal recorded before it cannot be checked against a
|
|
75
|
+
// delegation any more, because the delegation that would re-arm it has scrolled out.
|
|
76
|
+
window_start_ms: number
|
|
77
|
+
// The files this run has successfully edited within the window, resolved (joshuafolkken/kit#1840).
|
|
78
|
+
// A re-read of one of them is a read of a file the run edited, which §2b keeps in the main line — so
|
|
79
|
+
// it is excluded from the count and from a call's projected growth rather than counted as fresh
|
|
80
|
+
// investigation.
|
|
81
|
+
edited: ReadonlySet<string>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// **The run's own instructions are not the Issue's subject, so reading them is not what §2b delegates.**
|
|
85
|
+
// #1426's rule is about reading to find out how the subject works; `CLAUDE.md`, a `prompts/` topic and
|
|
86
|
+
// a skill file are read to find out what to *do*, they are read by nearly every run, and a unit cannot
|
|
87
|
+
// be sent to read them on the main line's behalf. #1441's own measurement excluded 5 of them by hand
|
|
88
|
+
// for exactly this reason, and a count that includes them trips on a run that has investigated nothing.
|
|
89
|
+
//
|
|
90
|
+
// **Matched against the path relative to the repository root, so `prompts` means *this* repository's**:
|
|
91
|
+
// `includes('prompts/')` also exempted `scripts/eval/prompts/x.ts`, which is subject code, and
|
|
92
|
+
// `endsWith('CLAUDE.md')` also exempted `MY_CLAUDE.md`. A file outside the checkout is subject
|
|
93
|
+
// material like any other — only these paths inside it are the run's own instructions.
|
|
94
|
+
const INSTRUCTION_PATHS: ReadonlyArray<string> = ['prompts', '.claude/skills']
|
|
95
|
+
const INSTRUCTION_FILES: ReadonlySet<string> = new Set(['CLAUDE.md', 'AGENTS.md', 'GEMINI.md'])
|
|
96
|
+
const REPOSITORY_ROOT = process.cwd()
|
|
97
|
+
|
|
98
|
+
// **The two ways a target reaches this file spell the same path differently.** A tool call carries
|
|
99
|
+
// `file_path`, which Claude Code requires to be absolute; a shell line carries the word as it was
|
|
100
|
+
// typed, normalized only for a leading `./`. Left as they are, `cat scripts/x.ts` followed by an
|
|
101
|
+
// `Edit` of `/…/scripts/x.ts` never cancels — the file stays pending for the rest of the run — and
|
|
102
|
+
// reading the same file once each way counts twice.
|
|
103
|
+
function resolved(target: string): string {
|
|
104
|
+
return path.resolve(REPOSITORY_ROOT, target)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// **Anchored at the repository root, not matched anywhere in the absolute path.** Testing the
|
|
108
|
+
// absolute string made every file in the repository an instruction document for anyone whose checkout
|
|
109
|
+
// sits under a directory called `prompts` — which disarmed the guard entirely, in silence.
|
|
110
|
+
// Both path predicates below ask the same question of the repository root, so the expression is named
|
|
111
|
+
// once rather than written twice — they differ only in what they do with the answer.
|
|
112
|
+
function repository_relative(absolute: string): string {
|
|
113
|
+
return path.relative(REPOSITORY_ROOT, absolute)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function is_instruction_document(target: string): boolean {
|
|
117
|
+
const relative = repository_relative(resolved(target))
|
|
118
|
+
const segments = relative.split(path.sep)
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
INSTRUCTION_FILES.has(segments.at(-1) ?? '') ||
|
|
122
|
+
INSTRUCTION_PATHS.some((prefix) => relative.startsWith(`${prefix}${path.sep}`))
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// **The harness's own session files are not the subject either, and it is the same test that excludes
|
|
127
|
+
// them** (joshuafolkken/kit#1771): no unit can be sent to read one on the main line's behalf. A
|
|
128
|
+
// backgrounded call's result reaches its run *only* as `tasks/<id>.output` under this session's temp
|
|
129
|
+
// tree, and a tool result too large for the transcript reaches it *only* as a file the harness wrote
|
|
130
|
+
// under `.claude/projects/`. Refusing either refuses a run the answer to an instruction it issued
|
|
131
|
+
// itself — and the remedy the refusal names does not exist for a file that belongs to this session
|
|
132
|
+
// alone, so the round trip buys nothing and the read is simply reissued.
|
|
133
|
+
//
|
|
134
|
+
// **Anchored on a directory the harness *writes*, never on the session tree as a whole.** Exempting
|
|
135
|
+
// the whole tree would have disarmed the guard in silence for anything a run unpacks or clones into
|
|
136
|
+
// its scratchpad to investigate — real subject material, read to find out how something works, that
|
|
137
|
+
// would never have reached the count. That is the failure the instruction-document half's own anchor
|
|
138
|
+
// note describes, and it is why the scratchpad is deliberately **not** exempt: what stays exempt is
|
|
139
|
+
// what the harness itself wrote.
|
|
140
|
+
const SESSION_TEMP_SEGMENT = /^claude-\d+$/u
|
|
141
|
+
// **Single-sourced from `cost-transcript.ts`**, which already owns where the harness keeps a session's
|
|
142
|
+
// state and builds the transcript directory out of it — spelling `.claude/projects` a second time here
|
|
143
|
+
// is the clone `CLAUDE.md` prohibits. That module joins the value onto a home directory and this one
|
|
144
|
+
// matches it as a run of segments, so what the two share is the fact rather than the use.
|
|
145
|
+
//
|
|
146
|
+
// **The `tasks/<id>.output` spelling is deliberately *not* borrowed from `time-background.ts`.** This
|
|
147
|
+
// rule matches the session *tree*, which covers that file, the scratchpad and the transcript in one
|
|
148
|
+
// test; matching the file name would need a second rule for each of the others.
|
|
149
|
+
const SESSION_STATE_SEGMENTS = cost_transcript.TRANSCRIPT_ROOT.split(path.sep)
|
|
150
|
+
// What the harness writes into a session's temp tree has a fixed shape — `tasks/<id>.output`, a
|
|
151
|
+
// backgrounded call's result — and **both halves are required**. The directory name alone is not
|
|
152
|
+
// enough: `tasks/` is one of the commonest directory names a repository has, and a run may unpack or
|
|
153
|
+
// clone one into its scratchpad, where matching the name would re-open the silent false negative one
|
|
154
|
+
// level down. Persisted tool results and the transcript need no entry here at all — they live under
|
|
155
|
+
// the state root above, which is exempt whole.
|
|
156
|
+
const HARNESS_OUTPUT_DIRECTORY = 'tasks'
|
|
157
|
+
const HARNESS_OUTPUT_EXTENSION = '.output'
|
|
158
|
+
// `at()` counts from the end, so the file itself is -1 and the directory holding it is -2.
|
|
159
|
+
const FILE_SEGMENT_INDEX = -1
|
|
160
|
+
const PARENT_SEGMENT_INDEX = -2
|
|
161
|
+
|
|
162
|
+
// The state root holds transcripts and persisted results and no subject code, so it is exempt whole.
|
|
163
|
+
// It is not anchored to the home directory: `cost-transcript.ts` is this package's only file allowed
|
|
164
|
+
// to look that up at all (`scripts/hooks/no-global-shim-write.test.ts`), and two adjacent segments outside
|
|
165
|
+
// the checkout are specific enough without it.
|
|
166
|
+
function has_state_root(segments: ReadonlyArray<string>, index: number): boolean {
|
|
167
|
+
return SESSION_STATE_SEGMENTS.every((segment, offset) => segments[index + offset] === segment)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// The file's **own parent** is tested rather than any directory above it, and the name has to match
|
|
171
|
+
// as well — see the shape note above for why one without the other is not enough.
|
|
172
|
+
function is_harness_output(segments: ReadonlyArray<string>): boolean {
|
|
173
|
+
return (
|
|
174
|
+
segments.some((segment) => SESSION_TEMP_SEGMENT.test(segment)) &&
|
|
175
|
+
segments.at(PARENT_SEGMENT_INDEX) === HARNESS_OUTPUT_DIRECTORY &&
|
|
176
|
+
(segments.at(FILE_SEGMENT_INDEX) ?? '').endsWith(HARNESS_OUTPUT_EXTENSION)
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// **A path inside the checkout is never one of these, whatever its directories are called.** The
|
|
181
|
+
// instruction-document test above is anchored at the repository root because matching the absolute
|
|
182
|
+
// string made every file an instruction document for a checkout sitting under a directory called
|
|
183
|
+
// `prompts`; this test cannot borrow that anchor, since the files it names live outside the checkout by
|
|
184
|
+
// construction. So the anchor is inverted — leaving the repository is a precondition — and a
|
|
185
|
+
// repository file can therefore never be exempted here, whatever it is named.
|
|
186
|
+
function is_outside_repository(absolute: string): boolean {
|
|
187
|
+
return repository_relative(absolute).startsWith('..')
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function is_session_artifact(target: string): boolean {
|
|
191
|
+
const absolute = resolved(target)
|
|
192
|
+
const segments = absolute.split(path.sep)
|
|
193
|
+
|
|
194
|
+
if (!is_outside_repository(absolute)) return false
|
|
195
|
+
|
|
196
|
+
return (
|
|
197
|
+
segments.some((_segment, index) => has_state_root(segments, index)) ||
|
|
198
|
+
is_harness_output(segments)
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// The two exclusions answer one question — could a unit be sent to read this instead? — so a target
|
|
203
|
+
// failing either is not the Issue's subject and never reaches the count.
|
|
204
|
+
function is_subject_file(target: string): boolean {
|
|
205
|
+
return !is_instruction_document(target) && !is_session_artifact(target)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// A shell glob resolves to a literal path with a `*` in it, which no edit can ever name — so left in,
|
|
209
|
+
// it stays pending until the next delegation and keeps contributing to a count it does not belong in.
|
|
210
|
+
function is_nameable_file(target: string): boolean {
|
|
211
|
+
return !target.includes('*') && !target.includes('?')
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function is_content_read(label: string): boolean {
|
|
215
|
+
return READ_TOOLS.has(label) || CONTENT_READ_LABELS.has(label)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function subject_targets(targets: ReadonlyArray<string>): ReadonlyArray<string> {
|
|
219
|
+
return targets
|
|
220
|
+
.filter((target) => is_nameable_file(target) && is_subject_file(target))
|
|
221
|
+
.map((target) => resolved(target))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function call_targets(call: GuardedCall): ReadonlyArray<string> {
|
|
225
|
+
return subject_targets(time_bundle_call.call_facts(call.name, call.input).targets)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// **The instant a delegation closed, not the one it opened.** The refusal this re-arms was recorded
|
|
229
|
+
// before the unit was ever briefed, so either end of that span is after it — and the closing instant
|
|
230
|
+
// needs no duration arithmetic to derive, which keeps the one number this rule compares free of
|
|
231
|
+
// `to_spans`' own bookkeeping.
|
|
232
|
+
function delegation_instant(span: Span | undefined): number {
|
|
233
|
+
return span === undefined ? hook_decision.NEVER_MS : span.ended_ms
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// **A span whose outcome was failure changed nothing, so it is not what this rule acts on**
|
|
237
|
+
// (joshuafolkken/kit#1764, joshuafolkken/kit#1840). A failed **read** carried no text into the
|
|
238
|
+
// prompt — the case that matters is the guard's own refusal: Claude Code writes a denied call to the
|
|
239
|
+
// transcript as a `tool_use` block with an errored `tool_result`, and the stamp is written *before*
|
|
240
|
+
// the reason is returned, so counting the denied read's targets would pre-load `pending_since` with
|
|
241
|
+
// the very read the refusal stopped. A failed **edit** wrote nothing, so it does not exempt a later
|
|
242
|
+
// read of its target either — `edited_files` below asks the same question for that reason. An
|
|
243
|
+
// **unknown** outcome still counts, because a result nobody recorded is not a failure.
|
|
244
|
+
function is_failed_outcome(span: Span): boolean {
|
|
245
|
+
return span.outcome === time_spans.FAILED_OUTCOME
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// **Every file the run successfully wrote within the window, resolved** (joshuafolkken/kit#1840). It
|
|
249
|
+
// is the one source of "this run edited that file", shared by the live tally and the replay: a read of
|
|
250
|
+
// a file the run edits is reading §2b keeps in the main line, so it is never counted — whether the read
|
|
251
|
+
// came before the edit or after it. A failed edit wrote nothing and so exempts nothing, and a file
|
|
252
|
+
// edited outside the window is unknown rather than assumed: the set is only ever as wide as the tail
|
|
253
|
+
// the hook read, which is the bound joshuafolkken/kit#1764 already holds the accumulation to.
|
|
254
|
+
function edited_files(spans: ReadonlyArray<Span>): Set<string> {
|
|
255
|
+
const written = spans
|
|
256
|
+
.filter((span) => !is_failed_outcome(span))
|
|
257
|
+
.flatMap((span) => subject_targets(span.writes))
|
|
258
|
+
|
|
259
|
+
return new Set(written)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// **The set records *when* each file entered it, which is the whole of the second re-arm**
|
|
263
|
+
// (joshuafolkken/kit#1764). A plain set could say how many files were pending and never how many of
|
|
264
|
+
// them arrived after the refusal, so a run that ignored its one refusal was indistinguishable from
|
|
265
|
+
// one that had read nothing since. The first entry stands: a re-read of a file already pending is
|
|
266
|
+
// not a new accumulation, exactly as it is not a new count.
|
|
267
|
+
function add_all(
|
|
268
|
+
pending: Map<string, number>,
|
|
269
|
+
targets: ReadonlyArray<string>,
|
|
270
|
+
at_ms: number,
|
|
271
|
+
): void {
|
|
272
|
+
for (const target of targets) if (!pending.has(target)) pending.set(target, at_ms)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// **A file the run edited is never added to the set in the first place** (joshuafolkken/kit#1840).
|
|
276
|
+
// `edited_files` has already gathered every successful write in the window, so a read of one of them —
|
|
277
|
+
// before the edit or after it — is filtered here rather than added and then subtracted. This closes
|
|
278
|
+
// the re-read-after-edit gap the old subtract-on-the-edit-span could not: a subtraction runs only on
|
|
279
|
+
// the edit's own span, so a read issued *after* the edit was added and stayed. `sed -i`, `MultiEdit`
|
|
280
|
+
// and `NotebookEdit` need no special case any more — each is a write, so its target is in `edited` and
|
|
281
|
+
// never enters the read count.
|
|
282
|
+
function apply_span(pending: Map<string, number>, span: Span, edited: ReadonlySet<string>): void {
|
|
283
|
+
if (DELEGATION_TOOLS.has(span.label)) {
|
|
284
|
+
pending.clear()
|
|
285
|
+
|
|
286
|
+
return
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (!is_content_read(span.label) || is_failed_outcome(span)) return
|
|
290
|
+
|
|
291
|
+
const fresh = subject_targets(span.targets).filter((target) => !edited.has(target))
|
|
292
|
+
|
|
293
|
+
add_all(pending, fresh, span.ended_ms)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
function last_delegation_ms(spans: ReadonlyArray<Span>): number {
|
|
297
|
+
return delegation_instant(spans.findLast((span) => DELEGATION_TOOLS.has(span.label)))
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// **The window is the tail the hook read, not the whole run.** That is the same bound the batching
|
|
301
|
+
// guard works under, and it costs nothing here: the set is cleared at every delegation anyway, so a
|
|
302
|
+
// tail that reaches back past the last one already holds the whole accumulation.
|
|
303
|
+
function pending_after(pending: ReadonlyMap<string, number>, since_ms: number): number {
|
|
304
|
+
return [...pending.values()].filter((at_ms) => at_ms > since_ms).length
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function tally_of(text: string, since_ms: number = hook_decision.NEVER_MS): ReadTally {
|
|
308
|
+
const { spans, started_ms } = time_spans.parse_timeline(text)
|
|
309
|
+
const edited = edited_files(spans)
|
|
310
|
+
const pending = new Map<string, number>()
|
|
311
|
+
|
|
312
|
+
for (const span of spans) apply_span(pending, span, edited)
|
|
313
|
+
|
|
314
|
+
return {
|
|
315
|
+
pending: [...pending.keys()],
|
|
316
|
+
pending_since: pending_after(pending, since_ms),
|
|
317
|
+
reset_ms: last_delegation_ms(spans),
|
|
318
|
+
window_start_ms: started_ms,
|
|
319
|
+
edited,
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// **The call has to actually add a file the count does not already hold.** Its targets are filtered
|
|
324
|
+
// against `edited` first, so a re-read of a file the run edited is not the `+ 1` that trips the
|
|
325
|
+
// threshold — the same exclusion `apply_span` makes for the pending set this is compared against
|
|
326
|
+
// (joshuafolkken/kit#1840). The `Set` union still absorbs a re-read of something already pending — a
|
|
327
|
+
// second `sed -n` window of the same file, or a `Read` with a new `offset` — which would not have
|
|
328
|
+
// grown the count either. The default empty set is for the exported callers that ask about
|
|
329
|
+
// accumulation alone — a test, or any reader with no edited set in hand.
|
|
330
|
+
function projected_count(
|
|
331
|
+
pending: ReadonlyArray<string>,
|
|
332
|
+
call: GuardedCall,
|
|
333
|
+
edited: ReadonlySet<string> = new Set<string>(),
|
|
334
|
+
): number {
|
|
335
|
+
return new Set([...pending, ...call_targets(call).filter((target) => !edited.has(target))]).size
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// **The read that takes the count *up to* the threshold is the boundary.** The ones below it stay in
|
|
339
|
+
// the main line, which is what keeps a small investigation from paying the two turns a brief and a
|
|
340
|
+
// result cost.
|
|
341
|
+
//
|
|
342
|
+
// **It is the *accumulated* count that has to reach the boundary, never the projected one.** Counting
|
|
343
|
+
// the call's own targets toward it let one bundled multi-file read — `cat a.ts b.ts c.ts`, exactly the
|
|
344
|
+
// batching `CLAUDE.md` mandates — be refused as the first call of a run, with a reason claiming three
|
|
345
|
+
// files had already been read. The boundary is crossed by a call, not jumped over by one.
|
|
346
|
+
function is_at_threshold(pending_count: number): boolean {
|
|
347
|
+
return pending_count + 1 >= delegation_policy.INVESTIGATION_FILE_THRESHOLD
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// **One refusal per accumulation, re-armed by a delegation and by nothing else.** A run that reads on
|
|
351
|
+
// regardless is not refused again, so a false positive — three files the run was about to edit — costs
|
|
352
|
+
// one round trip rather than wedging the run. And a run that *does* delegate is refused again as soon
|
|
353
|
+
// as three more unedited files pile up, which is the whole of joshuafolkken/kit#1460.
|
|
354
|
+
//
|
|
355
|
+
// **A refusal older than the window re-arms too**, and without that arm the guard fell permanently
|
|
356
|
+
// silent on exactly the run lengths the Issue was filed about: once the last delegation scrolls out of
|
|
357
|
+
// the 256 KB tail there is no `reset_ms` left to beat, and one stale stamp disarmed the rest of the
|
|
358
|
+
// session. This is the bound `batch-guard.ts` already documents for its own window — one extra
|
|
359
|
+
// refusal per window rather than silence — and it errs toward delegating, which is the goal.
|
|
360
|
+
//
|
|
361
|
+
// **And a further accumulation re-arms it, which is what "one refusal per accumulation" had always
|
|
362
|
+
// meant and never done** (joshuafolkken/kit#1764). A delegation was the only thing that could clear
|
|
363
|
+
// the disarm, so a run that *ignored* the refusal — read on without delegating — was never spoken to
|
|
364
|
+
// again however many unedited files it went on to open: the one case the threshold exists for was the
|
|
365
|
+
// one case it stopped covering. `docs/josh-commands.md` had already published the corrected
|
|
366
|
+
// behavior — "one per accumulation and re-arms after the next three unedited reads" — against code
|
|
367
|
+
// that did nothing of the kind, which is the shipped-mechanism-not-working defect
|
|
368
|
+
// joshuafolkken/kit#1262 declared highest priority.
|
|
369
|
+
//
|
|
370
|
+
// **It is not a refusal on the next call.** The count has to climb a whole threshold again, so a
|
|
371
|
+
// false positive still costs one round trip; what it cannot do any more is buy silence for the rest
|
|
372
|
+
// of the run.
|
|
373
|
+
//
|
|
374
|
+
// **A delegated unit is not re-armed here because it is not refused at all** (joshuafolkken/kit#1840).
|
|
375
|
+
// The hook counts a unit's reading against the unit (joshuafolkken/kit#1424), and the refusal asks for
|
|
376
|
+
// a dispatch — but a unit is already where §2b sends the reading, and a read-only one (`Explore`,
|
|
377
|
+
// `Plan`) has no `Agent` tool to dispatch with. It was formerly degraded to a single first refusal,
|
|
378
|
+
// which still asked for an action the unit could not take; now the unit short circuit in `should_block`
|
|
379
|
+
// turns it off entirely, so this function is the parent's alone and needs no delegation condition.
|
|
380
|
+
function has_cleared_the_disarm(tally: ReadTally, refused_at_ms: number): boolean {
|
|
381
|
+
return tally.reset_ms > refused_at_ms || refused_at_ms < tally.window_start_ms
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function is_rearmed(tally: ReadTally, refused_at_ms: number): boolean {
|
|
385
|
+
if (refused_at_ms === hook_decision.NEVER_MS || has_cleared_the_disarm(tally, refused_at_ms)) {
|
|
386
|
+
return true
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return is_at_threshold(tally.pending_since)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// A transcript under a session's `subagents/` directory is a delegated unit's. The segment is
|
|
393
|
+
// `cost-transcript.ts`'s, which owns the layout — spelling it a second time here is the clone
|
|
394
|
+
// `CLAUDE.md` prohibits, and the hook is handed the derived fork path rather than the parent's
|
|
395
|
+
// (`hook-decision.ts` → `guard_reason_for_payload`).
|
|
396
|
+
function is_unit_transcript(transcript: string): boolean {
|
|
397
|
+
return transcript.split(path.sep).includes(cost_transcript.UNIT_DIRECTORY)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// The run-level question `should_block` asks of the payload: is this a delegated unit's transcript?
|
|
401
|
+
// `run` is absent in the pure-tally tests, which are the parent's context by construction.
|
|
402
|
+
function is_unit_run(run: GuardRun | undefined): boolean {
|
|
403
|
+
return run !== undefined && is_unit_transcript(run.transcript)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function is_refusable_command(call: GuardedCall): boolean {
|
|
407
|
+
const label = time_shell.bash_label(time_shell.bash_command(call.input))
|
|
408
|
+
|
|
409
|
+
return CONTENT_READ_LABELS.has(label) && time_batch_guard.is_read_only_call(call)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// **A `Read` is always safe to refuse; a `Bash` line is refused only where it writes nothing.** This
|
|
413
|
+
// guard counts *reading*, so a line that also writes is one it has no business stopping — a `sed -i`
|
|
414
|
+
// is work rather than investigation, and refusing one would leave the siblings of its turn applied and
|
|
415
|
+
// itself not for no gain in what this guard measures.
|
|
416
|
+
//
|
|
417
|
+
// **It asks `is_read_only_call`, which is what `is_guarded_call` used to mean**
|
|
418
|
+
// (joshuafolkken/kit#1762). The batching guard can now refuse a write, and the two guards ask
|
|
419
|
+
// different questions of the same call: that one asks whether the call could have gone out beside
|
|
420
|
+
// another, this one whether the call is reading. A single shared predicate would have moved this one
|
|
421
|
+
// silently when that one widened, so the read-only test kept its semantics under a name that states
|
|
422
|
+
// them. A `sed -n` read is therefore still **counted and never refused**; the refusal lands on the
|
|
423
|
+
// next call that is unambiguously a read.
|
|
424
|
+
//
|
|
425
|
+
// **A call naming no subject file is never refused either**, which covers two cases in one rule: a
|
|
426
|
+
// call that names only instruction documents — refusing `CLAUDE.md` would stop a run reading the very
|
|
427
|
+
// rule being enforced — and a call whose targets could not be read at all, which cannot move the count
|
|
428
|
+
// and so has nothing to be refused for.
|
|
429
|
+
function is_refusable_call(call: GuardedCall): boolean {
|
|
430
|
+
if (call_targets(call).length === 0) return false
|
|
431
|
+
if (READ_TOOLS.has(call.name)) return true
|
|
432
|
+
|
|
433
|
+
return call.name === cost_blocks.BASH_TOOL && is_refusable_command(call)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function should_block(
|
|
437
|
+
text: string,
|
|
438
|
+
call: GuardedCall,
|
|
439
|
+
refused_at_ms: number,
|
|
440
|
+
run?: GuardRun,
|
|
441
|
+
): boolean {
|
|
442
|
+
// A delegated unit is never refused (joshuafolkken/kit#1840): the remedy the refusal names — send
|
|
443
|
+
// the reading to a unit — does not exist inside one. Asked before the tail is parsed, since the
|
|
444
|
+
// answer needs none of it.
|
|
445
|
+
if (!is_refusable_call(call) || is_unit_run(run)) return false
|
|
446
|
+
|
|
447
|
+
const tally = tally_of(text, refused_at_ms)
|
|
448
|
+
|
|
449
|
+
if (!is_at_threshold(tally.pending.length)) return false
|
|
450
|
+
|
|
451
|
+
return (
|
|
452
|
+
projected_count(tally.pending, call, tally.edited) > tally.pending.length &&
|
|
453
|
+
is_rearmed(tally, refused_at_ms)
|
|
454
|
+
)
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// What a read this rule saw was, in the four answers the rule itself can give
|
|
458
|
+
// (joshuafolkken/kit#1764). `pnpm josh time` prints them as a block, and the ids are here rather than
|
|
459
|
+
// there because each one is a fact about the guard: the two above the line are the reading §2b leaves
|
|
460
|
+
// in the main line on purpose, and the two below it are the reading it sends to a unit.
|
|
461
|
+
//
|
|
462
|
+
// **The last is the gap, and naming it is the point.** A read that reached the threshold and was not
|
|
463
|
+
// refused is neither by design nor caught, and nothing could see it — so the 35.9% of a run's turns
|
|
464
|
+
// that `investigation` accounts for could not be told apart from the reading that belongs there. Two
|
|
465
|
+
// things put a read in it, and the row deliberately covers both: a refusal already standing that the
|
|
466
|
+
// arm above had not re-armed, and a spelling the guard never refuses at all (`sed -n`, below).
|
|
467
|
+
const EDIT_TARGET_CLASS = 'edit targets'
|
|
468
|
+
const UNDER_THRESHOLD_CLASS = 'under the threshold'
|
|
469
|
+
const REFUSED_CLASS = 'refused'
|
|
470
|
+
// Kept inside `time-format.ts`'s 24-character label column, which the fuller phrasing overflowed —
|
|
471
|
+
// the prose beside the block is where the two reasons are named.
|
|
472
|
+
const LET_THROUGH_CLASS = 'let through'
|
|
473
|
+
const READ_CLASSES: ReadonlyArray<string> = [
|
|
474
|
+
EDIT_TARGET_CLASS,
|
|
475
|
+
UNDER_THRESHOLD_CLASS,
|
|
476
|
+
REFUSED_CLASS,
|
|
477
|
+
LET_THROUGH_CLASS,
|
|
478
|
+
]
|
|
479
|
+
|
|
480
|
+
// **The live guard refuses a `Read` always and a shell read only where the line cannot also write**,
|
|
481
|
+
// which is why `Bash: sed` is counted and never refused: `sed -n` prints and `sed -i` rewrites, and
|
|
482
|
+
// `time-batch-guard.ts` → `is_read_only_call` answers conservatively for both. A span carries the
|
|
483
|
+
// label but not the command, so the replay asks the question the span *can* answer — and of the eight
|
|
484
|
+
// printing commands, `sed` is the only one on `time-bundle-call.ts`'s writing list. **The residual is
|
|
485
|
+
// named rather than hidden**: a redirection inside a `cat` line also stops the live call being refusable
|
|
486
|
+
// and is invisible here, so a handful of such reads land in `refused` that the guard would have let
|
|
487
|
+
// through. It is the same direction as the row below and far smaller.
|
|
488
|
+
const NEVER_REFUSED_LABELS: ReadonlySet<string> = new Set([time_shell.bash_label('sed')])
|
|
489
|
+
|
|
490
|
+
// The guard's state as a replay walks a recorded run, which is `ReadTally` plus the one thing a live
|
|
491
|
+
// hook keeps on disk instead — the instant it last refused.
|
|
492
|
+
interface Replay {
|
|
493
|
+
pending: Map<string, number>
|
|
494
|
+
reset_ms: number
|
|
495
|
+
window_start_ms: number
|
|
496
|
+
refused_at_ms: number
|
|
497
|
+
// The whole run's successful writes, gathered once by `classified_reads` and carried so `tally_now`
|
|
498
|
+
// can hand them to the same exclusion the live guard makes (joshuafolkken/kit#1840).
|
|
499
|
+
edited: ReadonlySet<string>
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// The tally the live guard would have held at this instant, so the re-arm is asked of the one
|
|
503
|
+
// function that answers it rather than of a second copy of the rule.
|
|
504
|
+
function tally_now(replay: Replay): ReadTally {
|
|
505
|
+
return {
|
|
506
|
+
pending: [...replay.pending.keys()],
|
|
507
|
+
pending_since: pending_after(replay.pending, replay.refused_at_ms),
|
|
508
|
+
reset_ms: replay.reset_ms,
|
|
509
|
+
window_start_ms: replay.window_start_ms,
|
|
510
|
+
edited: replay.edited,
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// The same two conditions `should_block` asks: the accumulated count is at the boundary, and this
|
|
515
|
+
// read actually adds a file to it.
|
|
516
|
+
function reaches_threshold(replay: Replay, targets: ReadonlyArray<string>): boolean {
|
|
517
|
+
const added = targets.filter((target) => !replay.pending.has(target))
|
|
518
|
+
|
|
519
|
+
return added.length > 0 && is_at_threshold(replay.pending.size)
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Whether the guard would have refused this read had it been armed — the same two conditions
|
|
523
|
+
// `is_refusable_call` puts in front of every refusal, asked of a span.
|
|
524
|
+
function would_refuse(replay: Replay, span: Span): boolean {
|
|
525
|
+
if (NEVER_REFUSED_LABELS.has(span.label)) return false
|
|
526
|
+
|
|
527
|
+
return is_rearmed(tally_now(replay), replay.refused_at_ms)
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function class_of(replay: Replay, span: Span, edited: ReadonlySet<string>): string {
|
|
531
|
+
// Exclude the edited files first, so the threshold is judged on the same set `should_block` judges
|
|
532
|
+
// it on: an all-edited read is an edit target, and a mixed read reaches the threshold only on its
|
|
533
|
+
// genuinely new files, never on a file the run edited (joshuafolkken/kit#1840).
|
|
534
|
+
const fresh = subject_targets(span.targets).filter((target) => !edited.has(target))
|
|
535
|
+
|
|
536
|
+
if (fresh.length === 0) return EDIT_TARGET_CLASS
|
|
537
|
+
if (!reaches_threshold(replay, fresh)) return UNDER_THRESHOLD_CLASS
|
|
538
|
+
|
|
539
|
+
return would_refuse(replay, span) ? REFUSED_CLASS : LET_THROUGH_CLASS
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// A span that is not a read, or whose every target was an instruction document or a session file,
|
|
543
|
+
// classifies as nothing at all — it never reached the count, so putting it in a row would report the
|
|
544
|
+
// guard as having an opinion about it.
|
|
545
|
+
function read_class(replay: Replay, span: Span, edited: ReadonlySet<string>): string | undefined {
|
|
546
|
+
if (!is_content_read(span.label)) return undefined
|
|
547
|
+
if (subject_targets(span.targets).length === 0) return undefined
|
|
548
|
+
|
|
549
|
+
return class_of(replay, span, edited)
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
function step(replay: Replay, span: Span, edited: ReadonlySet<string>): string | undefined {
|
|
553
|
+
if (DELEGATION_TOOLS.has(span.label)) {
|
|
554
|
+
replay.reset_ms = span.ended_ms
|
|
555
|
+
apply_span(replay.pending, span, edited)
|
|
556
|
+
|
|
557
|
+
return undefined
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const found = read_class(replay, span, edited)
|
|
561
|
+
|
|
562
|
+
// A refusal moves the disarm forward, exactly as the hook's own stamp does.
|
|
563
|
+
if (found === REFUSED_CLASS) replay.refused_at_ms = span.ended_ms
|
|
564
|
+
|
|
565
|
+
apply_span(replay.pending, span, edited)
|
|
566
|
+
|
|
567
|
+
return found
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// **A read paired with where it fell in the run** (joshuafolkken/kit#1868). `index` is the read span's
|
|
571
|
+
// position in the array handed to `classified_reads`; `time-investigation.ts` classifies that same
|
|
572
|
+
// array's phases and pairs the two by index, so it can say which phase — setup above all — each read
|
|
573
|
+
// landed in.
|
|
574
|
+
interface ClassifiedRead {
|
|
575
|
+
found: string
|
|
576
|
+
index: number
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
const FIRST_SPAN = 0
|
|
580
|
+
|
|
581
|
+
function fresh_replay(spans: ReadonlyArray<Span>, edited: ReadonlySet<string>): Replay {
|
|
582
|
+
return {
|
|
583
|
+
pending: new Map<string, number>(),
|
|
584
|
+
reset_ms: hook_decision.NEVER_MS,
|
|
585
|
+
window_start_ms: spans[FIRST_SPAN]?.ended_ms ?? hook_decision.NEVER_MS,
|
|
586
|
+
refused_at_ms: hook_decision.NEVER_MS,
|
|
587
|
+
edited,
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// **What each of a run's reads was, replayed through this rule's own predicates**
|
|
592
|
+
// (joshuafolkken/kit#1764). It is the measurement half of the guard and shares every decision with
|
|
593
|
+
// it — the subject test, the threshold, the delegation reset and the re-arm — because a second walk
|
|
594
|
+
// that merely resembled the guard would answer about a rule nobody ships. Each read carries its span's
|
|
595
|
+
// index, so `time-investigation.ts` can place it in a phase (joshuafolkken/kit#1868).
|
|
596
|
+
function classified_reads(spans: ReadonlyArray<Span>): Array<ClassifiedRead> {
|
|
597
|
+
const edited = edited_files(spans)
|
|
598
|
+
const replay = fresh_replay(spans, edited)
|
|
599
|
+
const reads: Array<ClassifiedRead> = []
|
|
600
|
+
|
|
601
|
+
for (const [index, span] of spans.entries()) {
|
|
602
|
+
const found = step(replay, span, edited)
|
|
603
|
+
|
|
604
|
+
if (found !== undefined) reads.push({ found, index })
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return reads
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
const investigation_reads = {
|
|
611
|
+
CONTENT_READ_COMMANDS,
|
|
612
|
+
EDIT_TARGET_CLASS,
|
|
613
|
+
LET_THROUGH_CLASS,
|
|
614
|
+
READ_CLASSES,
|
|
615
|
+
REFUSED_CLASS,
|
|
616
|
+
UNDER_THRESHOLD_CLASS,
|
|
617
|
+
classified_reads,
|
|
618
|
+
subject_targets,
|
|
619
|
+
DELEGATION_TOOLS,
|
|
620
|
+
READ_TOOLS,
|
|
621
|
+
REASON,
|
|
622
|
+
is_at_threshold,
|
|
623
|
+
is_content_read,
|
|
624
|
+
is_instruction_document,
|
|
625
|
+
is_rearmed,
|
|
626
|
+
is_refusable_call,
|
|
627
|
+
is_session_artifact,
|
|
628
|
+
is_subject_file,
|
|
629
|
+
projected_count,
|
|
630
|
+
repository_relative,
|
|
631
|
+
resolved,
|
|
632
|
+
should_block,
|
|
633
|
+
tally_of,
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export type { ClassifiedRead, ReadTally }
|
|
637
|
+
export { investigation_reads }
|