@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,529 @@
|
|
|
1
|
+
import { time_bundle_call, type BundleFacts } from './time-bundle-call'
|
|
2
|
+
import { time_bundles } from './time-bundles'
|
|
3
|
+
import { time_call_identity } from './time-call-identity'
|
|
4
|
+
import { time_spans, type Span } from './time-spans'
|
|
5
|
+
import { time_transcript_line } from './time-transcript-line'
|
|
6
|
+
|
|
7
|
+
// Whether the call about to go out should be refused because the run has stopped batching
|
|
8
|
+
// (joshuafolkken/kit#1390).
|
|
9
|
+
//
|
|
10
|
+
// Two mechanisms already exist and neither moved the number. joshuafolkken/kit#1304 distributed the
|
|
11
|
+
// norm as prose; joshuafolkken/kit#1329 and joshuafolkken/kit#1337 put the density in front of the run
|
|
12
|
+
// while it was still going. Three consecutive runs measured 1.10–1.12 calls per round trip against a
|
|
13
|
+
// 1.50 floor, with 14–27 of every hundred round trips recoverable (joshuafolkken/kit#1344). What is
|
|
14
|
+
// left is not another way to *say* it: it is intervening in the decision itself.
|
|
15
|
+
//
|
|
16
|
+
// **The judgement is `time-bundle-call.ts`'s and `time-bundles.ts`'s, not a second one.** Whether a
|
|
17
|
+
// call is bundleable, what it names, and what counts as a run of single-call turns are already
|
|
18
|
+
// decided — by the very modules the end-of-run report is computed from. A guard with an opinion of its
|
|
19
|
+
// own would refuse calls the report then says were fine, and the Issue's own verification step reads
|
|
20
|
+
// that report.
|
|
21
|
+
//
|
|
22
|
+
// ## What it cannot know: the size of the turn it is interrupting
|
|
23
|
+
//
|
|
24
|
+
// **A `PreToolUse` hook cannot tell a batched turn from a single-call one, and no field in the
|
|
25
|
+
// transcript can be made to say.** Claude Code writes one line per content block and starts the first
|
|
26
|
+
// tool as soon as that block parses — measured on a live session, the later `tool_use` lines of one
|
|
27
|
+
// message arrive **1.4 to 15 seconds afterwards**. So at the instant the first call of a turn is
|
|
28
|
+
// judged, the turn looks single-call whatever it will turn out to be. `stop_reason` is no help: every
|
|
29
|
+
// line of a message carries the finished message's value, including the `thinking` line written before
|
|
30
|
+
// any tool ran, so it says nothing about how much of the message exists yet.
|
|
31
|
+
//
|
|
32
|
+
// **The guard therefore decides on closed history alone** — the run of single-call turns already
|
|
33
|
+
// behind it — and the refusal lands on the first call of the turn that follows. Where that turn was
|
|
34
|
+
// going to batch, the refusal is a false positive costing one round trip, which is the price
|
|
35
|
+
// joshuafolkken/kit#1390 named and accepted before this was built.
|
|
36
|
+
//
|
|
37
|
+
// **Reading the count anyway would have been worse than not reading it.** `time_density.last_turn_calls`
|
|
38
|
+
// answers exactly this question after the fact, and calling it here returns `1` for every turn — so a
|
|
39
|
+
// guard written against it would refuse the first call of every batched turn while reporting that it
|
|
40
|
+
// had checked. That is the first call of the very behavior this exists to produce, punished with a
|
|
41
|
+
// verdict nobody could see was empty.
|
|
42
|
+
//
|
|
43
|
+
// ## The refusal cannot repeat on the call in hand, but it does repeat as the run keeps single-calling
|
|
44
|
+
//
|
|
45
|
+
// A refusal repeating on the *same call* would wedge a run, and that is made structurally impossible in
|
|
46
|
+
// two ways. The caller records when it last fired, and the immediate re-look never re-fires: a call the
|
|
47
|
+
// run answered by re-issuing it unchanged is found on a refused span in the tail (`is_reissued_refusal`)
|
|
48
|
+
// and let through, so a turn can have at most one of its calls refused.
|
|
49
|
+
//
|
|
50
|
+
// **What used to follow from the record was silence for the rest of the run, and kit#2164 is what ends
|
|
51
|
+
// that.** The old rule fired only where the open sequence *began* after the last firing — and a run that
|
|
52
|
+
// ignored the refusal and kept single-calling never started a new sequence, so it was never spoken to
|
|
53
|
+
// again. Measured across every run, that came to one refusal per run against thousands of turns. The
|
|
54
|
+
// rule now fires the first time a run of single-call turns reaches the limit, and then **again every
|
|
55
|
+
// `REFIRE_EVERY` further single-call turns** it keeps issuing: `is_sequence_at_limit` counts the closed
|
|
56
|
+
// single-call turns since the last firing and re-fires once that count reaches the interval. A new
|
|
57
|
+
// sequence — the run batched, then lapsed again — is a first firing of its own, exactly as before.
|
|
58
|
+
//
|
|
59
|
+
// **The re-fire cannot wedge**, for the same reason the first firing cannot: each re-fire refuses a
|
|
60
|
+
// *different* call than the one already on a refused span, and a call the run re-issues unchanged after a
|
|
61
|
+
// re-fire is let through by `is_reissued_refusal` just as the first refusal's re-issue is.
|
|
62
|
+
//
|
|
63
|
+
// **And the caller must fail toward allowing.** With no instant on record every sequence looks new, so
|
|
64
|
+
// a caller that cannot record the refusal must not make it. `scripts/hooks/batch-guard.ts` states that half.
|
|
65
|
+
|
|
66
|
+
// How many consecutive single-call turns are allowed before one is refused. **Three, from the
|
|
67
|
+
// measurement rather than from taste**: joshuafolkken/kit#1344 found the longest bundleable sequence
|
|
68
|
+
// of each run at 3–5 turns, so refusing at the third catches most sequences while they still have
|
|
69
|
+
// turns left to save. Four or more gives most of them back; two would refuse the ordinary pair a
|
|
70
|
+
// person would never call a defect.
|
|
71
|
+
const CONSECUTIVE_LIMIT = 3
|
|
72
|
+
|
|
73
|
+
// **How many further single-call turns pass between one firing and the next, once a run keeps
|
|
74
|
+
// single-calling after being spoken to** (joshuafolkken/kit#2164). This is the `N` the acceptance
|
|
75
|
+
// criteria name, and it lives here as a single constant. Before this the guard fired once per unbroken
|
|
76
|
+
// run of single-call turns and then went silent — a run that ignored the first refusal and kept issuing
|
|
77
|
+
// single calls was never spoken to again, so over thousands of turns the guard delivered one notice. The
|
|
78
|
+
// re-fire turns that back into steady pressure: the same `CONSECUTIVE_LIMIT` cadence the first firing
|
|
79
|
+
// used, applied again from the last firing, so the reminder recurs every three continued single-call
|
|
80
|
+
// turns rather than once. It is deliberately not more frequent than the initial limit — a shorter
|
|
81
|
+
// interval would refuse a run that is only two single calls past a reminder it just answered.
|
|
82
|
+
const REFIRE_EVERY = CONSECUTIVE_LIMIT
|
|
83
|
+
const ONE_TURN = 1
|
|
84
|
+
const NONE = 0
|
|
85
|
+
|
|
86
|
+
// **The notice's own re-fire interval, and the `N` joshuafolkken/kit#2276 measured as too long.** A
|
|
87
|
+
// refusal that fired every single-call turn would refuse a run only one call past a reminder it just
|
|
88
|
+
// answered, so `REFIRE_EVERY` holds the refusal at the initial limit. **A notice cannot wedge** — the
|
|
89
|
+
// call proceeds either way — so nothing makes the notice pay that caution, and #2164 reusing the
|
|
90
|
+
// refusal's three-turn cadence for it is why a lane child single-calling was nudged only once per three
|
|
91
|
+
// mistakes. This is a single constant, the one the acceptance criteria name, kept apart from
|
|
92
|
+
// `REFIRE_EVERY` so the refusal's cadence and the notice's cannot drift into one number that is wrong
|
|
93
|
+
// for one of them.
|
|
94
|
+
const NOTICE_REFIRE_EVERY = ONE_TURN
|
|
95
|
+
|
|
96
|
+
// **How many of the most recent single-call turns the notice names** (joshuafolkken/kit#2276). #2164's
|
|
97
|
+
// notice ended at "batch what follows" and named no call, and the density did not move; naming the
|
|
98
|
+
// concrete calls the run just issued one-per-turn is the untried half of "why it did not work" — a
|
|
99
|
+
// reader shown *these three reads had no dependency* has something to act on that "batch more" never
|
|
100
|
+
// gave. Three, so the notice carries the sequence that tripped the limit without growing the per-turn
|
|
101
|
+
// context it rides on.
|
|
102
|
+
const NAMED_CANDIDATE_COUNT = 3
|
|
103
|
+
|
|
104
|
+
// **The turns already closed, so the one being interrupted is not among them.** A span exists only
|
|
105
|
+
// once its result has come back, and the call being judged has not run yet — so a sequence of
|
|
106
|
+
// `CONSECUTIVE_LIMIT - 1` closed turns is the state in which the next call would make the third.
|
|
107
|
+
const SEQUENCE_BEFORE_LIMIT = CONSECUTIVE_LIMIT - ONE_TURN
|
|
108
|
+
|
|
109
|
+
// The call about to go out, named the way the hook payload names it. A record rather than two
|
|
110
|
+
// parameters so the tool and its input cannot be handed over in the wrong order — both are strings on
|
|
111
|
+
// the caller's side often enough for that to compile.
|
|
112
|
+
interface GuardedCall {
|
|
113
|
+
name: string
|
|
114
|
+
input: unknown
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// **A write is refusable, and the exclusion that said otherwise is gone** (joshuafolkken/kit#1762).
|
|
118
|
+
// Read over 19 recorded runs, 261 of 1,737 round trips (15.0%) were recoverable by batching and **184
|
|
119
|
+
// of them (70.5%) were writes** — 158 `Edit` alone. The refusal's own text has always said the rule
|
|
120
|
+
// covers them ("edits are covered exactly as reads are"); the implementation had not caught up, so the
|
|
121
|
+
// largest single contributor to the waste was the one party the guard could never reach.
|
|
122
|
+
//
|
|
123
|
+
// **Two different things were rejected before this, and separating them is what unblocked it.** What
|
|
124
|
+
// was rejected on measured cost is *widening the hook's matcher and nothing else*: a matcher naming
|
|
125
|
+
// `Edit` in front of an `is_guarded_call` that answers `false` for every write starts a process that
|
|
126
|
+
// can only ever answer "allow". That reasoning is sound and is untouched — the predicate is widened
|
|
127
|
+
// first, so the matcher now reaches a question that has an answer. What was **not** rejected, because
|
|
128
|
+
// nobody had proposed it, is making a write refusable at all; "buy nothing a refusal could use" was a
|
|
129
|
+
// consequence of the exclusion below it rather than a ground of its own.
|
|
130
|
+
//
|
|
131
|
+
// **The safety objection was real, and it is narrowed rather than dismissed.** Claude Code denies one
|
|
132
|
+
// call of a turn and runs the rest, so a refused edit leaves its siblings applied and itself not, and
|
|
133
|
+
// the reissue can meet text that has moved under it. `depends_on_sequence` below closes the half that
|
|
134
|
+
// is visible: it withholds the refusal whenever the call in hand shares a target with the sequence
|
|
135
|
+
// behind it, writes included, so an edit to a file the run has already been rewriting is never
|
|
136
|
+
// refused.
|
|
137
|
+
//
|
|
138
|
+
// **The half it cannot close is the turn it is interrupting** — for the reason stated above, no field
|
|
139
|
+
// in the transcript says what else that turn issued. Three edits to one file batched into a single
|
|
140
|
+
// turn can therefore have their first refused while the other two apply. **The bound is that this
|
|
141
|
+
// surfaces rather than corrupts**: a refusable write is content-addressed — an `Edit` carries the
|
|
142
|
+
// `old_string` it was written against, an in-place `sed` a pattern — so a reissue either applies where
|
|
143
|
+
// it was meant to or fails to match and is reported. So the residual cost is one round trip in the
|
|
144
|
+
// ordinary case and a failed edit the run must redo in this one — the same false-positive price
|
|
145
|
+
// joshuafolkken/kit#1390 named and accepted for reads, now paid on the calls that carry most of the
|
|
146
|
+
// waste instead of only on the calls that carry the rest.
|
|
147
|
+
//
|
|
148
|
+
// **The dispatch it adds is measured, and it is not the figure the deleted text quoted.** One hook run
|
|
149
|
+
// is **0.53 s** in this checkout and about 0.4 s in a consumer, essentially all of it process startup —
|
|
150
|
+
// measured under `docs/josh-commands.md` → "`josh format:edited`", which is where that reading was
|
|
151
|
+
// taken. The "about 2.4 s" above was a `pnpm josh` dispatch measured before joshuafolkken/kit#1342 made
|
|
152
|
+
// this command eligible for the in-process path. Against that, one recovered round trip is a whole
|
|
153
|
+
// model turn.
|
|
154
|
+
//
|
|
155
|
+
// **The matcher is settings a consumer can widen, so what a call is stays this module's answer.**
|
|
156
|
+
// `is_guarded_call` is the guarantee and `.claude/settings.json` is the wiring; the two are kept apart
|
|
157
|
+
// so a consumer editing the second cannot change the first.
|
|
158
|
+
//
|
|
159
|
+
// **What a call *is* lives in `time-bundle-call.ts`** since joshuafolkken/kit#1509, beside the rest of
|
|
160
|
+
// it, because the sequence builder needs the same answer and a second copy here is what let the two
|
|
161
|
+
// disagree — the builder had no way to ask at all, so it read a run of edits to one file as a chain of
|
|
162
|
+
// dependent calls and no sequence ever formed.
|
|
163
|
+
|
|
164
|
+
// One line, and it says four things: what happened, what to do instead, where the rule is written, and
|
|
165
|
+
// what to do when the turn was already batching or the call really is alone. **The last of those is not
|
|
166
|
+
// a loophole, it is the honest half** — the guard cannot see the turn it interrupted, so a reader told
|
|
167
|
+
// only to batch would batch something that already was.
|
|
168
|
+
const REASON =
|
|
169
|
+
`⛔ batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so ` +
|
|
170
|
+
`this one would make ${String(CONSECUTIVE_LIMIT)} in a row. Reissue it in one turn together with ` +
|
|
171
|
+
`the calls meant to follow it that do not need its result. **The criterion is whether this call's ` +
|
|
172
|
+
`input needs another call's result, not what kind of call it is** — edits are covered exactly as ` +
|
|
173
|
+
`reads are, and it never authorizes weakening a verification gate or a review: fewer turns, never ` +
|
|
174
|
+
`less work. The measured cost and the rejected mechanisms are in ` +
|
|
175
|
+
`\`prompts/collaboration-workflow/turn-batching.md\`. If this turn was already batching, or the call ` +
|
|
176
|
+
`genuinely has nothing to go beside it, reissue it as it was: this fires once per run of ` +
|
|
177
|
+
`single-call turns and cannot repeat on the call in hand.`
|
|
178
|
+
|
|
179
|
+
// The notice a whole-file write earns instead of the refusal above (joshuafolkken/kit#1848). It says
|
|
180
|
+
// the same thing REASON does — reissue the calls that do not need each other in one turn — but as a
|
|
181
|
+
// **notice, not a refusal**: the write proceeds, because a `Write` cannot be refused safely (see
|
|
182
|
+
// `WHOLE_FILE_WRITE_TOOL` below). The honest half is here for the same reason it is on REASON — the
|
|
183
|
+
// guard cannot see the turn it is interrupting, so a reader told only to batch would batch a turn that
|
|
184
|
+
// already was. It carries no ⛔, so a person watching reads it as advice rather than a stop.
|
|
185
|
+
const NOTICE =
|
|
186
|
+
`💡 batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so ` +
|
|
187
|
+
`this Write makes ${String(CONSECUTIVE_LIMIT)} in a row. This is a notice, not a refusal — the ` +
|
|
188
|
+
`write proceeds. Where the writes meant to follow it do not need its result, issue them in one turn ` +
|
|
189
|
+
`together. **The criterion is whether a call's input needs another call's result, not what kind of ` +
|
|
190
|
+
`call it is** — it never authorizes weakening a verification gate or a review: fewer turns, never ` +
|
|
191
|
+
`less work. The measured cost and the rejected mechanisms are in ` +
|
|
192
|
+
`\`prompts/collaboration-workflow/turn-batching.md\`. If this run was already batching, or the write ` +
|
|
193
|
+
`genuinely has nothing to go beside it, carry on: this recurs every ` +
|
|
194
|
+
`${String(NOTICE_REFIRE_EVERY)} further single-call turn(s).`
|
|
195
|
+
|
|
196
|
+
// The notice a *refusable* call earns instead of its refusal when the run is a dispatched lane child
|
|
197
|
+
// (joshuafolkken/kit#2164). A headless `claude -p` child ends its turn on a denial, so the batching
|
|
198
|
+
// guard cannot refuse there — but the guidance is exactly as useful, so it is delivered as a notice: the
|
|
199
|
+
// call proceeds, and the model is told to batch what follows. It carries no ⛔, so a person watching
|
|
200
|
+
// reads it as advice rather than a stop, and it says the reminder recurs so a child that keeps
|
|
201
|
+
// single-calling knows the pressure is steady rather than spent.
|
|
202
|
+
const LANE_NOTICE =
|
|
203
|
+
`💡 batching: the last ${String(SEQUENCE_BEFORE_LIMIT)} turns each issued a single tool call, so ` +
|
|
204
|
+
`this one makes ${String(CONSECUTIVE_LIMIT)} in a row. This is a notice, not a refusal — the call ` +
|
|
205
|
+
`proceeds, because a dispatched lane child ends its turn on a denial. Where the calls meant to follow ` +
|
|
206
|
+
`it do not need its result, issue them in one turn together. **The criterion is whether a call's ` +
|
|
207
|
+
`input needs another call's result, not what kind of call it is** — it never authorizes weakening a ` +
|
|
208
|
+
`verification gate or a review: fewer turns, never less work. The measured cost and the rejected ` +
|
|
209
|
+
`mechanisms are in \`prompts/collaboration-workflow/turn-batching.md\`. If this run was already ` +
|
|
210
|
+
`batching, or the call genuinely has nothing to go beside it, carry on: this recurs every ` +
|
|
211
|
+
`${String(NOTICE_REFIRE_EVERY)} further single-call turn(s).`
|
|
212
|
+
|
|
213
|
+
// The one write that is never refused, because it is the one whose reissue is **unconditional**. Every
|
|
214
|
+
// other refusable write is content-addressed and so fails loudly when its turn's siblings moved the
|
|
215
|
+
// text under it; a `Write` carries the whole file, so reissuing it re-applies content composed before
|
|
216
|
+
// those siblings ran and overwrites an applied edit with no error anywhere. **A turn holding a `Write`
|
|
217
|
+
// and an `Edit` of one file is a shape a run actually produces** — create it, then adjust it — which is
|
|
218
|
+
// what separates this from a truncating shell redirect, where the colliding turn would have to hold two
|
|
219
|
+
// writers of one path and is not a shape that occurs.
|
|
220
|
+
//
|
|
221
|
+
// **It is not the blanket exclusion joshuafolkken/kit#1762 removed.** That one turned away every write
|
|
222
|
+
// for being a write; this turns away one tool because a false positive on it cannot surface. `Edit` —
|
|
223
|
+
// 164 of the 251 recoverable round trips against `Write`'s 37, read over 20 runs — is untouched, and
|
|
224
|
+
// the matcher leaves `Write` out for the cost reason above rather than relying on this line alone.
|
|
225
|
+
const WHOLE_FILE_WRITE_TOOL = 'Write'
|
|
226
|
+
|
|
227
|
+
// The one tool the write-side fold names (joshuafolkken/kit#2366). A span's label is its tool name for
|
|
228
|
+
// everything but Bash (`time-spans.ts`), so this is how a recent single-call turn is read as an edit
|
|
229
|
+
// that `edit:files` could fold — distinct from `Write`, which this command cannot content-address.
|
|
230
|
+
const EDIT_TOOL = 'Edit'
|
|
231
|
+
|
|
232
|
+
// Whether this call is one the guard could ever refuse, asked before any transcript is read. **The
|
|
233
|
+
// caller uses it to skip that read**: a quarter-megabyte read inside a hook that holds every call is
|
|
234
|
+
// not worth paying on a `pnpm josh` invocation the answer can never be about.
|
|
235
|
+
//
|
|
236
|
+
// **Bundleable is the whole test, because the criterion is dependency and not the kind of call.** The
|
|
237
|
+
// `may_write` term that used to sit beside it excluded the 70.5% of recoverable round trips that are
|
|
238
|
+
// writes (joshuafolkken/kit#1762). What keeps a write that genuinely cannot be refused safe is
|
|
239
|
+
// `depends_on_sequence`, which reads the targets, rather than a blanket exclusion here.
|
|
240
|
+
function is_guarded_call(call: GuardedCall): boolean {
|
|
241
|
+
if (call.name === WHOLE_FILE_WRITE_TOOL) return false
|
|
242
|
+
|
|
243
|
+
return time_bundle_call.call_facts(call.name, call.input).is_bundleable
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// The counterpart to `is_guarded_call` for the one tool it turns away: the whole-file write is the
|
|
247
|
+
// call the guard **notifies** about rather than refuses (joshuafolkken/kit#1848). It cannot be refused
|
|
248
|
+
// safely — its reissue overwrites an applied sibling in silence — yet a run of single-call `Write`
|
|
249
|
+
// turns was the largest recoverable contributor the refusal could never reach, so the notice carries
|
|
250
|
+
// the rule to it without the false-positive cost. `.claude/settings.json` names `Write` in the matcher
|
|
251
|
+
// so the hook is even reached, exactly as the predicate is what makes the matcher's answer non-empty.
|
|
252
|
+
function is_notice_call(call: GuardedCall): boolean {
|
|
253
|
+
return call.name === WHOLE_FILE_WRITE_TOOL
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// The same question narrowed to calls that write nothing — the test `is_guarded_call` used to be, kept
|
|
257
|
+
// under a name that says what it asks rather than deleted. **`scripts/delegation/investigation-reads.ts`
|
|
258
|
+
// is its caller**, and it needs this answer rather than the one above: it refuses a `Bash` line only
|
|
259
|
+
// where that line is unambiguously a read, so an in-place `sed` stays outside its reach even now that
|
|
260
|
+
// the batching guard can refuse one. Widening the single predicate in place would have loosened that
|
|
261
|
+
// guard silently, which is the one way this change could have gone wrong without a test noticing.
|
|
262
|
+
//
|
|
263
|
+
// **`may_write`, not `is_writing`** — this is a refusal test, and it is the one that has to over-call.
|
|
264
|
+
// The dependency test reads the other field, which may not (joshuafolkken/kit#1509).
|
|
265
|
+
function is_read_only_call(call: GuardedCall): boolean {
|
|
266
|
+
const facts = time_bundle_call.call_facts(call.name, call.input)
|
|
267
|
+
|
|
268
|
+
return facts.is_bundleable && !facts.may_write
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// **A shared target is a dependency, and it is what keeps the guard off the search-then-read pair.**
|
|
272
|
+
// `time-bundles.ts` treats two calls naming the same path — or one naming a directory the other reads
|
|
273
|
+
// inside of — as ordered, and reuses that test here so a call the report would never have counted as
|
|
274
|
+
// recoverable is never refused either.
|
|
275
|
+
//
|
|
276
|
+
// **It asks for the shared target alone, where `time_bundles.is_dependent` exempts a write following a
|
|
277
|
+
// write, because the two are answering different questions** (joshuafolkken/kit#1762). The builder asks
|
|
278
|
+
// "could these two have gone out together", and for two edits to one file the answer is yes — that
|
|
279
|
+
// exemption is what lets such a stretch form a sequence at all (joshuafolkken/kit#1509). This asks "is
|
|
280
|
+
// refusing this one safe", and there the same pair is the one case where it is not: the siblings of a
|
|
281
|
+
// refused edit still run, so an edit naming a file the run is already rewriting comes back to text that
|
|
282
|
+
// has moved under it. Both sides read `shares_target`, so there is one definition of what sharing a
|
|
283
|
+
// target means and two uses of it rather than a second copy.
|
|
284
|
+
function depends_on_sequence(sequence: ReadonlyArray<Span>, facts: BundleFacts): boolean {
|
|
285
|
+
return sequence.some((span) => time_bundles.shares_target(span.targets, facts.targets))
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// The instant the open sequence began, as far as the window shows. An empty sequence answers `NONE`,
|
|
289
|
+
// and `NONE` is never greater than a recorded refusal — so the length test in `is_sequence_at_limit` is
|
|
290
|
+
// what admits a run's first firing, and this decides only whether that firing is the sequence's first.
|
|
291
|
+
//
|
|
292
|
+
// **Both sides of that comparison are the same machine's wall clock**: the transcript's timestamps and
|
|
293
|
+
// the instant the caller recorded. A clock that jumped backwards makes a record read as later than
|
|
294
|
+
// every sequence, which withholds the firing — the safe direction, and the one every other failure here
|
|
295
|
+
// takes too.
|
|
296
|
+
function sequence_started_ms(sequence: ReadonlyArray<Span>): number {
|
|
297
|
+
return sequence[0]?.ended_ms ?? NONE
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// How many of the open sequence's closed single-call turns ended after the last firing. For a run whose
|
|
301
|
+
// last firing predates this sequence every turn counts; for one already spoken to inside this sequence
|
|
302
|
+
// only the turns issued since count — which is what the re-fire interval is measured against.
|
|
303
|
+
function turns_since(sequence: ReadonlyArray<Span>, last_fired_ms: number): number {
|
|
304
|
+
return sequence.filter((span) => span.ended_ms > last_fired_ms).length
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// **The firing test, first-time and re-fire in one** (joshuafolkken/kit#2164). The length and dependency
|
|
308
|
+
// gates are unchanged. What changed is the instant comparison: where a firing predates the open
|
|
309
|
+
// sequence it is that sequence's first, so the length gate alone decides it; where the run has already
|
|
310
|
+
// been spoken to inside this sequence, it re-fires only once `REFIRE_EVERY` further single-call turns
|
|
311
|
+
// have closed since. The old rule kept only the first branch, which is why it fell silent for the rest
|
|
312
|
+
// of a run that kept single-calling.
|
|
313
|
+
function is_sequence_at_limit(
|
|
314
|
+
sequence: ReadonlyArray<Span>,
|
|
315
|
+
facts: BundleFacts,
|
|
316
|
+
last_fired_ms: number,
|
|
317
|
+
refire_every: number,
|
|
318
|
+
): boolean {
|
|
319
|
+
if (sequence.length < SEQUENCE_BEFORE_LIMIT || depends_on_sequence(sequence, facts)) return false
|
|
320
|
+
|
|
321
|
+
if (last_fired_ms < sequence_started_ms(sequence)) return true
|
|
322
|
+
|
|
323
|
+
return turns_since(sequence, last_fired_ms) >= refire_every
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// **Nothing here reads the turn the call belongs to**, because nothing can: see "What it cannot know"
|
|
327
|
+
// above. The two call-shaped tests are asked of the call in hand, and everything else of the turns
|
|
328
|
+
// behind it.
|
|
329
|
+
// The sequence test both dispositions share, over spans the caller has already parsed: is the open run
|
|
330
|
+
// of single-call turns at the limit, for a call that began after the last time this disposition fired.
|
|
331
|
+
// Shared so the refusal and the notice cannot drift apart on what "three in a row" means
|
|
332
|
+
// (joshuafolkken/kit#1848), and taking spans rather than the tail so a disposition that also asks
|
|
333
|
+
// `is_reissued_refusal` parses the transcript once (joshuafolkken/kit#1979).
|
|
334
|
+
function is_at_limit(
|
|
335
|
+
spans: ReadonlyArray<Span>,
|
|
336
|
+
call: GuardedCall,
|
|
337
|
+
last_fired_ms: number,
|
|
338
|
+
refire_every: number,
|
|
339
|
+
): boolean {
|
|
340
|
+
return is_sequence_at_limit(
|
|
341
|
+
time_bundles.open_sequence(spans),
|
|
342
|
+
time_bundle_call.call_facts(call.name, call.input),
|
|
343
|
+
last_fired_ms,
|
|
344
|
+
refire_every,
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// This guard's own refusal label, as `time-transcript-line.ts` reads it back off a refused result: the
|
|
349
|
+
// token after the ⛔ and before the first colon of REASON. Derived from REASON rather than written a
|
|
350
|
+
// second time, so the two can never disagree about which refusals in the transcript are this guard's
|
|
351
|
+
// (joshuafolkken/kit#1979).
|
|
352
|
+
const GUARD_LABEL = time_transcript_line.guard_from_refusal(REASON)
|
|
353
|
+
|
|
354
|
+
// **A call the guard has already refused, found in the tail by the same identity the report compares
|
|
355
|
+
// re-issues on** (joshuafolkken/kit#1979). A refused call the run answered by re-issuing it unchanged
|
|
356
|
+
// is one that had nothing to batch — refusing the re-issue again buys a round trip and no batching,
|
|
357
|
+
// which is the waste `time-guard-refusals.ts`'s `same_args_reissue` counts. The identity is built
|
|
358
|
+
// through the same `to_tool_call` the transcript parse uses, so a refused span and the live call about
|
|
359
|
+
// to repeat it produce the identical string.
|
|
360
|
+
//
|
|
361
|
+
// **This is what the timestamp alone could not do.** `refused_at_ms` withholds the immediate
|
|
362
|
+
// re-refusal, but an unbroken run of single-call turns longer than the read window presents a sequence
|
|
363
|
+
// start that has moved forward and is refused again (see "What it cannot know" above). The refused span
|
|
364
|
+
// is still in the tail even when that start has scrolled out of view, so its identity is what survives.
|
|
365
|
+
// The first refusal of a novel call still fires — only a call already on a refused span of this guard's
|
|
366
|
+
// is let through, so a genuinely bundleable single call is refused exactly as before.
|
|
367
|
+
function is_reissued_refusal(spans: ReadonlyArray<Span>, call: GuardedCall): boolean {
|
|
368
|
+
const identity = time_call_identity.identity_of(
|
|
369
|
+
time_spans.to_tool_call(call.name, call.input, time_spans.NO_MESSAGE_ID),
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
return spans.some(
|
|
373
|
+
(span) =>
|
|
374
|
+
span.refusal_guard === GUARD_LABEL && time_call_identity.identity_of(span) === identity,
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// `refire_every` defaults to the refusal's cadence so every existing caller reads unchanged; the
|
|
379
|
+
// lane-child downgraded notice passes `NOTICE_REFIRE_EVERY` instead, so a refusable call turned into a
|
|
380
|
+
// notice recurs on the notice's tighter cadence rather than the refusal's (joshuafolkken/kit#2276).
|
|
381
|
+
function should_block(
|
|
382
|
+
text: string,
|
|
383
|
+
call: GuardedCall,
|
|
384
|
+
refused_at_ms: number,
|
|
385
|
+
refire_every: number = REFIRE_EVERY,
|
|
386
|
+
): boolean {
|
|
387
|
+
if (!is_guarded_call(call)) return false
|
|
388
|
+
|
|
389
|
+
const { spans } = time_spans.parse_timeline(text)
|
|
390
|
+
|
|
391
|
+
if (is_reissued_refusal(spans, call)) return false
|
|
392
|
+
|
|
393
|
+
return is_at_limit(spans, call, refused_at_ms, refire_every)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// The notice's rule: the same sequence test, gated on the whole-file write rather than on a refusable
|
|
397
|
+
// call. `notified_at_ms` is read from the notice's **own** record, so a notice never spends the
|
|
398
|
+
// refusal's stamp and cannot silence a genuine refusal of a later read or edit on the same run. A
|
|
399
|
+
// whole-file write is never refused, so it has no re-issue to detect — the reissue test is the
|
|
400
|
+
// refusal's alone.
|
|
401
|
+
function should_notify(text: string, call: GuardedCall, notified_at_ms: number): boolean {
|
|
402
|
+
if (!is_notice_call(call)) return false
|
|
403
|
+
|
|
404
|
+
const { spans } = time_spans.parse_timeline(text)
|
|
405
|
+
|
|
406
|
+
return is_at_limit(spans, call, notified_at_ms, NOTICE_REFIRE_EVERY)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// One recent single-call turn named the way a reader would recognize it: the tool, and the file it
|
|
410
|
+
// touched where the label does not already carry it (joshuafolkken/kit#2276). `label` is the tool name
|
|
411
|
+
// for a non-shell call and the command for a shell one, so the target is appended only where it adds
|
|
412
|
+
// something the label has not already said.
|
|
413
|
+
function describe_span(span: Span): string {
|
|
414
|
+
const target = span.targets[0] ?? ''
|
|
415
|
+
if (target === '' || span.label.includes(target)) return span.label
|
|
416
|
+
|
|
417
|
+
return `${span.label} ${target}`
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// **The fewest reads that a composite call can fold** (joshuafolkken/kit#2311). One path is a single
|
|
421
|
+
// call already, so nothing folds below two — the directive is withheld and the run keeps the guidance
|
|
422
|
+
// alone, exactly as it does when the recent turns were not reads at all.
|
|
423
|
+
const FOLD_MINIMUM = 2
|
|
424
|
+
|
|
425
|
+
// **The recent single-call turns that were file reads, each named by the one path it read.** A fold
|
|
426
|
+
// needs a *file* path, so three targets are dropped: one that named none (a bare `pwd`), a write (a run
|
|
427
|
+
// of edits has nothing for `read:files` to do), and a directory (`ls scripts/` names `scripts/`, which
|
|
428
|
+
// `read:files` cannot read — it would emit `Cannot read scripts/` and exit 1, so the paste-ready
|
|
429
|
+
// command must never carry it). The directory test is `has_extension` reused from the target scanner,
|
|
430
|
+
// not a second copy. Deduped, so a run that read one file twice folds it once and names it once.
|
|
431
|
+
function read_targets(sequence: ReadonlyArray<Span>): ReadonlyArray<string> {
|
|
432
|
+
const paths = sequence
|
|
433
|
+
.filter((span) => span.is_bundleable && !span.is_writing)
|
|
434
|
+
.map((span) => span.targets[0] ?? '')
|
|
435
|
+
.filter((path) => path !== '' && time_bundle_call.has_extension(path))
|
|
436
|
+
|
|
437
|
+
return [...new Set(paths)]
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// **The composite-command half of the notice** (joshuafolkken/kit#2311): the single call that folds the
|
|
441
|
+
// recent single-call reads, handed to the run ready to paste. Naming the concrete calls did not move the
|
|
442
|
+
// density (#2276) — the notice still asked the model to *reissue them in one turn*, which is a request
|
|
443
|
+
// for the parallel `tool_use` blocks the model structurally resists. The lever measured to move
|
|
444
|
+
// round-trip density is a composite command that folds a routine section into one call (`read:files`,
|
|
445
|
+
// kit#2202); so the guard now offers *that* command, the one the model can emit in a single turn,
|
|
446
|
+
// rather than another way to say "batch". Below two reads there is nothing to fold, so it is empty and
|
|
447
|
+
// the guidance stands alone.
|
|
448
|
+
function read_fold_directive(sequence: ReadonlyArray<Span>): string {
|
|
449
|
+
const paths = read_targets(sequence)
|
|
450
|
+
if (paths.length < FOLD_MINIMUM) return ''
|
|
451
|
+
|
|
452
|
+
return ` Fold them into one call: \`pnpm josh read:files ${paths.join(' ')}\`.`
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// **The write-side counterpart of the read fold** (joshuafolkken/kit#2366): the recent single-call
|
|
456
|
+
// `Edit` turns, folded into one `edit:files` call. The read fold pastes a whole command because a read
|
|
457
|
+
// is addressed by its path alone; an edit carries its own text, so the fold names the files and points
|
|
458
|
+
// at the command that applies a plan of edits over them in one call — the composite command the model
|
|
459
|
+
// can emit in a single turn where reissuing the edits as parallel `tool_use` blocks is the shape it
|
|
460
|
+
// resists. Only `Edit` counts: a whole-file `Write` creates content this command cannot content-address,
|
|
461
|
+
// and it earns its own notice already. Below two edits there is nothing to fold.
|
|
462
|
+
function write_targets(sequence: ReadonlyArray<Span>): ReadonlyArray<string> {
|
|
463
|
+
const paths = sequence
|
|
464
|
+
.filter((span) => span.label === EDIT_TOOL)
|
|
465
|
+
.map((span) => span.targets[0] ?? '')
|
|
466
|
+
.filter((path) => path !== '' && time_bundle_call.has_extension(path))
|
|
467
|
+
|
|
468
|
+
return [...new Set(paths)]
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function write_fold_directive(sequence: ReadonlyArray<Span>): string {
|
|
472
|
+
const paths = write_targets(sequence)
|
|
473
|
+
if (paths.length < FOLD_MINIMUM) return ''
|
|
474
|
+
|
|
475
|
+
return ` Fold them into one \`pnpm josh edit:files\` call with a plan over: ${paths.join(' ')}.`
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// **The concrete half of the notice** (joshuafolkken/kit#2276): the most recent single-call turns,
|
|
479
|
+
// named, so the model is shown the calls it should have batched rather than only told to batch — and,
|
|
480
|
+
// since kit#2311, the one `read:files` call that folds them where they were reads. Parsed from the tail
|
|
481
|
+
// here rather than threaded from `should_notify` because it runs only when a notice actually fires,
|
|
482
|
+
// which is rare enough that the second parse costs less than carrying the spans through the hook's
|
|
483
|
+
// notice contract. An empty sequence names nothing and the notice falls back to its guidance alone.
|
|
484
|
+
function recent_candidates(tail: string): string {
|
|
485
|
+
const recent = time_bundles
|
|
486
|
+
.open_sequence(time_spans.parse_timeline(tail).spans)
|
|
487
|
+
.slice(-NAMED_CANDIDATE_COUNT)
|
|
488
|
+
|
|
489
|
+
if (recent.length === NONE) return ''
|
|
490
|
+
|
|
491
|
+
const named = recent.map((span) => describe_span(span)).join(', ')
|
|
492
|
+
const folds = `${read_fold_directive(recent)}${write_fold_directive(recent)}`
|
|
493
|
+
|
|
494
|
+
return ` Just issued one per turn, so at least these could have shared a turn: ${named}.${folds}`
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// **This guard's own name for its once-per-run record.** It lives beside the rule rather than in
|
|
498
|
+
// `batch-guard.ts` because a second module now has to read the same record: `delivered-rules.ts`
|
|
499
|
+
// stands aside for this guard and has to ask whether it has *already* refused, and a second copy of
|
|
500
|
+
// the string is the clone that would let the two disagree about which file they are reading.
|
|
501
|
+
const STAMP_PREFIX = 'josh-batch-guard-'
|
|
502
|
+
|
|
503
|
+
// The notice's own record, distinct from `STAMP_PREFIX` so a notice fired on a Write cannot move the
|
|
504
|
+
// instant the refusal reads — the two dispositions dedupe independently, once each per run of
|
|
505
|
+
// single-call turns (joshuafolkken/kit#1848).
|
|
506
|
+
const NOTICE_STAMP_PREFIX = 'josh-batch-guard-notice-'
|
|
507
|
+
|
|
508
|
+
const time_batch_guard = {
|
|
509
|
+
CONSECUTIVE_LIMIT,
|
|
510
|
+
GUARD_LABEL,
|
|
511
|
+
LANE_NOTICE,
|
|
512
|
+
NAMED_CANDIDATE_COUNT,
|
|
513
|
+
NOTICE,
|
|
514
|
+
NOTICE_REFIRE_EVERY,
|
|
515
|
+
NOTICE_STAMP_PREFIX,
|
|
516
|
+
REASON,
|
|
517
|
+
REFIRE_EVERY,
|
|
518
|
+
SEQUENCE_BEFORE_LIMIT,
|
|
519
|
+
STAMP_PREFIX,
|
|
520
|
+
is_guarded_call,
|
|
521
|
+
is_notice_call,
|
|
522
|
+
is_read_only_call,
|
|
523
|
+
recent_candidates,
|
|
524
|
+
should_block,
|
|
525
|
+
should_notify,
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
export type { GuardedCall }
|
|
529
|
+
export { time_batch_guard }
|