@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,178 @@
|
|
|
1
|
+
// Which steps of a run may be delegated to a cheaper execution tier (joshuafolkken/kit#969).
|
|
2
|
+
//
|
|
3
|
+
// **The decision takes no judgement.** "This one is simple enough" is a judgement made under cost
|
|
4
|
+
// pressure, and cost pressure resolves it toward "simple enough" exactly when a mistake is most
|
|
5
|
+
// likely to be shipped — the same reason `josh review:level` decides the review depth from the
|
|
6
|
+
// changed paths rather than from how big the change feels.
|
|
7
|
+
//
|
|
8
|
+
// So the list is an enumeration and **anything not on it is kept**. A step nobody thought about
|
|
9
|
+
// lands on the expensive side, which is the direction that costs money rather than correctness.
|
|
10
|
+
|
|
11
|
+
type DelegationVerdict = 'delegate' | 'keep'
|
|
12
|
+
|
|
13
|
+
const DELEGATE_VERDICT: DelegationVerdict = 'delegate'
|
|
14
|
+
const KEEP_VERDICT: DelegationVerdict = 'keep'
|
|
15
|
+
|
|
16
|
+
interface DelegatableStep {
|
|
17
|
+
name: string
|
|
18
|
+
// What the cheaper tier is asked to do.
|
|
19
|
+
does: string
|
|
20
|
+
// **The reason it may be delegated at all.** A step is delegatable only when a wrong result is
|
|
21
|
+
// *caught*, not merely unlikely — and caught by something that runs in the parent tier and costs
|
|
22
|
+
// less than redoing the step. Without that, a quiet mistake ships.
|
|
23
|
+
verifier: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Where the pre-implementation reading stops being cheaper in the main line (joshuafolkken/kit#1426).
|
|
27
|
+
//
|
|
28
|
+
// **A count, not a forecast.** The reads are counted as they are made rather than predicted before
|
|
29
|
+
// the investigation starts, so nothing here rests on guessing how large it will be. Two files the run
|
|
30
|
+
// will not edit stay in the main line, because delegating costs two extra main-line turns — one to
|
|
31
|
+
// write the brief, one to read the result, about 18 seconds at run #1406's measured 8.8 s of model
|
|
32
|
+
// wait per turn — and below the threshold that round trip costs more than carrying the text.
|
|
33
|
+
const INVESTIGATION_FILE_THRESHOLD = 3
|
|
34
|
+
|
|
35
|
+
// The enumeration. Short on purpose: every entry had to name a verifier, and most candidates could
|
|
36
|
+
// not (below).
|
|
37
|
+
const DELEGATABLE_STEPS: ReadonlyArray<DelegatableStep> = [
|
|
38
|
+
{
|
|
39
|
+
name: 'gate-fix',
|
|
40
|
+
does: 'apply the fixes the verification gate already named — a lint rule, a type error, a spelling the dictionary rejects',
|
|
41
|
+
verifier:
|
|
42
|
+
'`pnpm josh gate` is re-run; a wrong fix fails it again, and the failure names the file',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
name: 'epic-child',
|
|
46
|
+
// One row, two entry points: an epic's child under `epicrun` and one named issue of a
|
|
47
|
+
// `backlogrun` are the same unit — same brief, same summary, same verifier
|
|
48
|
+
// (joshuafolkken/kit#1149, folded from `queue` into `backlogrun` by joshuafolkken/kit#1984). A
|
|
49
|
+
// second row for the batch would be the clone `CLAUDE.md` prohibits.
|
|
50
|
+
does: "run one child of a batch end to end in an isolated unit — an epic's child or one named issue of a `backlogrun` alike — plan, verification gate, PR, merge — and return only its summary to the parent loop",
|
|
51
|
+
verifier:
|
|
52
|
+
"the parent reads the child's state from GitHub with `pnpm josh issue:state`, not from the summary; a child reported done but not merged is still open, which is the failure showing rather than a run continuing, and its own gate, `/code-review` and CI ran inside the unit before `followup` would touch the PR",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'followup-filing',
|
|
56
|
+
// The late-run follow-up filing chain — issue:scout → file the Issue → epic:bundle → epic --add
|
|
57
|
+
// — is a dependency chain `batch:guard` correctly keeps one call per step, and what makes it
|
|
58
|
+
// expensive is the ~340k context it runs in at the tail of a run, not the step count
|
|
59
|
+
// (joshuafolkken/kit#1892). A fresh unit runs the same chain at a small context, and the review
|
|
60
|
+
// round cap already composed the finding text, so what the unit is handed is mechanical: run the
|
|
61
|
+
// four commands and act on their deterministic answers. This is not `batch:guard`'s business —
|
|
62
|
+
// the chain stays one call per step; delegation only moves it to a cheaper context.
|
|
63
|
+
does: 'run the late-run follow-up filing chain in an isolated unit — issue:scout, file the Issue, epic:bundle, epic --add — given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer',
|
|
64
|
+
verifier:
|
|
65
|
+
"the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:scout` / `epic:bundle` are deterministic, so the unit's work is the mechanical execution `issue:state` confirms",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'implementation-unit',
|
|
69
|
+
// The Step 0 change list already decided *what* to change — that design stays in the main line,
|
|
70
|
+
// which is why `design` is rejected below. What is delegated is the *writing* of one unit of that
|
|
71
|
+
// list, and only a unit whose files are disjoint from every other dispatched unit: two subagents
|
|
72
|
+
// editing one file in parallel race on it. `pnpm josh fanout` confirms that disjointness
|
|
73
|
+
// mechanically, so the split is read off the file sets rather than judged (joshuafolkken/kit#2345).
|
|
74
|
+
does: 'implement one file-disjoint unit of the Step 0 change list in an isolated subagent — the files it edits shared with no other dispatched unit, confirmed by `pnpm josh fanout` — and return the edited files, never a summary standing in for the diff; the main line keeps integration and the verification gate. Units that share a file, or an Issue that will not split, stay serial',
|
|
75
|
+
verifier:
|
|
76
|
+
"the parent runs the whole integrated change through `pnpm josh gate` and a `/code-review` subagent it would run anyway — a unit's mistake fails the same gate and review a serial edit passes through, so delegating writes nothing the backstop does not already catch, and the `pnpm josh fanout` disjointness removes the one failure parallelism adds, two units colliding on a file",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'survey',
|
|
80
|
+
does: 'read across many files and report where something appears — every reference to a symbol, which documents carry a marker',
|
|
81
|
+
verifier:
|
|
82
|
+
'the reported locations are checked directly; a fabricated or missed location does not survive one `grep` of what it claimed',
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'investigation',
|
|
86
|
+
// Not `survey`: that row reports *where* something appears and is checked by one `grep`, while
|
|
87
|
+
// this one reports *how the subject works* and is checked by opening the lines it cited. The two
|
|
88
|
+
// verifiers differ, so widening `survey` would put both in one field and lose the boundary below.
|
|
89
|
+
// **No ordinal.** `${N}rd` would print `1rd` for any other threshold, past a test that only looks
|
|
90
|
+
// for the numeral, so the count is phrased as a plain "N or more".
|
|
91
|
+
does: `read the Issue's subject to find out how it currently works — once ${String(INVESTIGATION_FILE_THRESHOLD)} or more files the run will not edit have to be read — and return the conclusion plus the \`file:line\` citations that support it, never the file text, which would put the cost back where it was. A throwaway probe script is written, run and deleted inside the unit, which returns its output alone`,
|
|
92
|
+
verifier:
|
|
93
|
+
'the parent opens the cited lines; a conclusion those lines do not support fails there, and reading a handful of cited regions costs far less than redoing the reading. The unit reports what the code does and never what to change — deciding that is `diagnosis`, which stays kept, so a unit returning a root cause would be delegating the rejected row under this name',
|
|
94
|
+
},
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
// Steps that were considered and are **not** delegatable, kept as a list rather than dropped: the
|
|
98
|
+
// next person to propose one of them should find the reason rather than re-derive it.
|
|
99
|
+
interface RejectedStep {
|
|
100
|
+
name: string
|
|
101
|
+
because: string
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const REJECTED_STEPS: ReadonlyArray<RejectedStep> = [
|
|
105
|
+
{
|
|
106
|
+
name: 'notify-body',
|
|
107
|
+
because:
|
|
108
|
+
'no verifier. A notification with a wrong body is sent and read as though it were right; nothing in the run disagrees with it afterwards',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'issue-comment',
|
|
112
|
+
because:
|
|
113
|
+
'no verifier. A decision log or completion comment that says the wrong thing is the record, so there is nothing left to check it against',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'status-read',
|
|
117
|
+
because:
|
|
118
|
+
'a misread routes the run to the wrong child, and no later step disagrees. Running the status command is already cheap; what is expensive is acting on it, which is not this step',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: 'diagnosis',
|
|
122
|
+
because: 'a wrong root cause produces a fix that passes the gate and leaves the defect',
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
name: 'design',
|
|
126
|
+
because: 'the cost of a wrong design is paid by every step after it',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'split-assessment',
|
|
130
|
+
because: 'a missed split widens one Issue into a batch nobody authorized',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'review',
|
|
134
|
+
because: 'the review is the last thing between a defect and a merge; a cheaper one finds less',
|
|
135
|
+
},
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
function find_step(name: string): DelegatableStep | undefined {
|
|
139
|
+
return DELEGATABLE_STEPS.find((step) => step.name === name.trim())
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function verdict_for(name: string): DelegationVerdict {
|
|
143
|
+
return find_step(name) === undefined ? KEEP_VERDICT : DELEGATE_VERDICT
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function rejection_for(name: string): RejectedStep | undefined {
|
|
147
|
+
return REJECTED_STEPS.find((step) => step.name === name.trim())
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Why the answer is what it is. A verdict with no reason is a rule an agent cannot check itself
|
|
151
|
+
// against, and `keep` is the answer that most needs one — most of the time it means "nobody has
|
|
152
|
+
// listed this", not "this was judged too risky".
|
|
153
|
+
function reason_for(name: string): string {
|
|
154
|
+
const step = find_step(name)
|
|
155
|
+
|
|
156
|
+
if (step !== undefined) return `delegatable: ${step.verifier}`
|
|
157
|
+
|
|
158
|
+
const rejected = rejection_for(name)
|
|
159
|
+
|
|
160
|
+
if (rejected !== undefined) return `kept deliberately: ${rejected.because}`
|
|
161
|
+
|
|
162
|
+
return 'kept by default: not on the delegatable list, and the list is the whole of it'
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const delegation_policy = {
|
|
166
|
+
DELEGATE_VERDICT,
|
|
167
|
+
INVESTIGATION_FILE_THRESHOLD,
|
|
168
|
+
KEEP_VERDICT,
|
|
169
|
+
DELEGATABLE_STEPS,
|
|
170
|
+
REJECTED_STEPS,
|
|
171
|
+
find_step,
|
|
172
|
+
verdict_for,
|
|
173
|
+
rejection_for,
|
|
174
|
+
reason_for,
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export type { DelegatableStep, DelegationVerdict, RejectedStep }
|
|
178
|
+
export { delegation_policy }
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { statSync } from 'node:fs'
|
|
3
|
+
import { text } from 'node:stream/consumers'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
6
|
+
import { lane_guard_policy, type LaneGuardMode } from '#scripts/lane/lane-guard-policy'
|
|
7
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
8
|
+
import type { GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
9
|
+
import { time_spans, type Span } from '#scripts/time-runtime/time-spans'
|
|
10
|
+
import { investigation_reads } from './investigation-reads'
|
|
11
|
+
|
|
12
|
+
// Refuse the second whole-file `Read` of a path whose content has not changed since the run last read
|
|
13
|
+
// it (joshuafolkken/kit#2298). Measured across the latest five lanes, a run re-read the same unchanged
|
|
14
|
+
// path 8.0 times on average — `#2282` read `pre-gate-cut.md` three times — and each round trip pays
|
|
15
|
+
// ~17 seconds to return text the run already holds. The remedy is the one `investigation-guard.ts`
|
|
16
|
+
// already proved: intervene in the `PreToolUse` decision rather than describe the rule in prose.
|
|
17
|
+
//
|
|
18
|
+
// **It is unchanged content that is caught, never a repeat read.** The transcript says *when* the run
|
|
19
|
+
// last read the path; the filesystem says *whether* it has changed since. A file whose `mtime` is
|
|
20
|
+
// newer than that read has been edited — or merged, or grown by a background task — so the re-read is
|
|
21
|
+
// let through; only a file untouched since the read returns nothing new. Reading the change off the
|
|
22
|
+
// disk rather than off the transcript is what makes an edit, a `git` checkout and a `tasks/*.output`
|
|
23
|
+
// that grew all read the same: any of them moves the `mtime`.
|
|
24
|
+
//
|
|
25
|
+
// **How it speaks is decided by the one-place lane enumeration, exactly as the batching guard's is.**
|
|
26
|
+
// On the interactive main line a refusal is guidance, so the guard `refuse`s; in a dispatched lane
|
|
27
|
+
// child a denial ends the headless turn with nothing committed (joshuafolkken/kit#2138), and the
|
|
28
|
+
// duplicates the Issue measured are in those very children — so there it is a `notice`, nudging the run
|
|
29
|
+
// without killing it. `lane-guard-policy.ts` is the single source of both modes.
|
|
30
|
+
//
|
|
31
|
+
// **The escape hatch is on by default**, for `investigation-guard.ts`'s reason: a distributed guard
|
|
32
|
+
// nobody enables leaves the Issue where it started. The variable buys a way to switch it off without
|
|
33
|
+
// editing the settings file — debugging the guard, or a session whose re-reads really are all needed.
|
|
34
|
+
const SWITCH_ENV_KEY = 'JOSH_DUPLICATE_READ_GUARD'
|
|
35
|
+
const LANE_GUARD_ID = 'duplicate-read'
|
|
36
|
+
const STAMP_PREFIX = 'josh-duplicate-read-guard-'
|
|
37
|
+
const NOTICE_STAMP_PREFIX = 'josh-duplicate-read-notice-'
|
|
38
|
+
const READ_TOOL = 'Read'
|
|
39
|
+
// A glob resolves to a literal path with a `*` in it, which names no single file to stat.
|
|
40
|
+
const GLOB_CHARACTERS = /[*?]/u
|
|
41
|
+
|
|
42
|
+
// What the refusal tells the model — the deny reason is the only text that reaches it, so it has to
|
|
43
|
+
// name why the read was stopped and how to proceed. A run refused and told nothing reads it as a
|
|
44
|
+
// broken tool.
|
|
45
|
+
const REASON = `⛔ duplicate read: this file was already read in this session and has not changed since (its mtime predates that read), so reading it again returns nothing new. Scroll up to the earlier result instead of re-reading it. A read with a new offset/limit, or of a file that has since changed, is allowed; set \`JOSH_DUPLICATE_READ_GUARD=off\` to disable this guard.`
|
|
46
|
+
|
|
47
|
+
// The same guidance carried without a `permissionDecision`, for a dispatched lane child where a denial
|
|
48
|
+
// would end the turn (joshuafolkken/kit#2138). It nudges rather than blocks, so the run survives.
|
|
49
|
+
const NOTICE = `⚠ duplicate read: this file was already read in this session and has not changed since, so re-reading it returns nothing new — scroll up to the earlier result instead of re-reading it. Set \`JOSH_DUPLICATE_READ_GUARD=off\` to silence this.`
|
|
50
|
+
|
|
51
|
+
// **A paginated read is a read of a different region, not a repeat.** A run that read lines 1–100 and
|
|
52
|
+
// now wants 101–200 needs the second call, so a read carrying an `offset` or a `limit` is never the
|
|
53
|
+
// whole-file re-read this guard is about — the count the Issue measured is whole-file reads.
|
|
54
|
+
function is_paginated(input: Record<string, unknown>): boolean {
|
|
55
|
+
return input['offset'] !== undefined || input['limit'] !== undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// A `file_path` that names one readable file: a non-empty string that is not a glob. A glob resolves
|
|
59
|
+
// to a literal path with a `*` in it, which names no single file to stat.
|
|
60
|
+
function names_one_file(file_path: unknown): file_path is string {
|
|
61
|
+
return typeof file_path === 'string' && file_path !== '' && !GLOB_CHARACTERS.test(file_path)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The absolute path of a refusable whole-file `Read`, or `undefined` for any call this guard leaves
|
|
65
|
+
// alone: a non-`Read` tool, a paginated read, or a target that names no single file. Resolved through
|
|
66
|
+
// `investigation-reads.ts` so the two ways a path reaches here — a tool field and a transcript span —
|
|
67
|
+
// compare as one string.
|
|
68
|
+
function read_target(call: GuardedCall): string | undefined {
|
|
69
|
+
if (call.name !== READ_TOOL || !json_value.is_record(call.input)) return undefined
|
|
70
|
+
|
|
71
|
+
const { input } = call
|
|
72
|
+
|
|
73
|
+
if (is_paginated(input) || !names_one_file(input['file_path'])) return undefined
|
|
74
|
+
|
|
75
|
+
return investigation_reads.resolved(input['file_path'])
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function is_refusable_call(call: GuardedCall): boolean {
|
|
79
|
+
return read_target(call) !== undefined
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// A read the run made and that returned — a denied or errored read carried no text into the prompt, so
|
|
83
|
+
// it is not a read this guard measures against. It is `investigation-reads.ts`'s own exclusion, asked
|
|
84
|
+
// here of a `Read` span alone.
|
|
85
|
+
function is_successful_read(span: Span): boolean {
|
|
86
|
+
const is_read = investigation_reads.READ_TOOLS.has(span.label)
|
|
87
|
+
|
|
88
|
+
return is_read && span.outcome !== time_spans.FAILED_OUTCOME
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function reads_target(span: Span, target: string): boolean {
|
|
92
|
+
return span.targets.some((one) => investigation_reads.resolved(one) === target)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// **The instant the run last read this exact path, or `NEVER_MS` where the tail holds no such read.**
|
|
96
|
+
// The most recent successful read wins: an earlier read that has since been superseded says nothing
|
|
97
|
+
// about whether the content is current. The tail is the same bounded window the other guards read, so
|
|
98
|
+
// a first read that has scrolled out reads as "never read" — a miss, never a false refusal.
|
|
99
|
+
function last_read_ms(spans: ReadonlyArray<Span>, target: string): number {
|
|
100
|
+
const times = spans
|
|
101
|
+
.filter((span) => is_successful_read(span) && reads_target(span, target))
|
|
102
|
+
.map((span) => span.ended_ms)
|
|
103
|
+
|
|
104
|
+
return times.length === 0 ? hook_decision.NEVER_MS : Math.max(...times)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The file's modification time in epoch milliseconds, comparable to a span's `ended_ms` because both
|
|
108
|
+
// are this machine's wall clock. **A stat that fails allows the call** — a deleted or unreadable file
|
|
109
|
+
// is not something to refuse over, and "could not read mtime/size" is the fallback the Issue names.
|
|
110
|
+
function file_mtime_ms(target: string): number | undefined {
|
|
111
|
+
try {
|
|
112
|
+
return statSync(target).mtimeMs
|
|
113
|
+
} catch {
|
|
114
|
+
return undefined
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// What the rule needs about the run: when the target was last read, and when the window opens.
|
|
119
|
+
interface ReadWindow {
|
|
120
|
+
last_ms: number
|
|
121
|
+
window_start_ms: number
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function read_window(tail: string, target: string): ReadWindow {
|
|
125
|
+
const { spans, started_ms } = time_spans.parse_timeline(tail)
|
|
126
|
+
|
|
127
|
+
return { last_ms: last_read_ms(spans, target), window_start_ms: started_ms }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// **The re-read returns nothing new.** The path was read before (`last_ms` is set) and the file has
|
|
131
|
+
// not changed since (`mtime` predates that read). A missing stat is not "unchanged" — it is the
|
|
132
|
+
// fallback that allows the call.
|
|
133
|
+
function is_unchanged_reread(last_ms: number, mtime: number | undefined): boolean {
|
|
134
|
+
if (mtime === undefined || last_ms === hook_decision.NEVER_MS) return false
|
|
135
|
+
|
|
136
|
+
return mtime < last_ms
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// **One firing per accumulation, re-armed by a later read and by nothing else.** A run spoken to once
|
|
140
|
+
// and reading on anyway is not spoken to again — a false positive costs one round trip, never the wedge
|
|
141
|
+
// of the same call flagged on every look. It re-arms when a fresh successful read of the target lands
|
|
142
|
+
// after the last firing (a new redundant episode), or when that firing has scrolled out of the window,
|
|
143
|
+
// which is `investigation-reads.ts`'s own pair of arms. `fired_at_ms` is the refusal's stamp on the
|
|
144
|
+
// main line and the notice's own stamp in a lane child, so the two dedupe independently.
|
|
145
|
+
function is_rearmed(window: ReadWindow, fired_at_ms: number): boolean {
|
|
146
|
+
if (fired_at_ms === hook_decision.NEVER_MS || fired_at_ms < window.window_start_ms) return true
|
|
147
|
+
|
|
148
|
+
return window.last_ms > fired_at_ms
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// The pure rule, shared by the refusal and the notice: is this call an unchanged re-read that the
|
|
152
|
+
// enumeration's mode should act on, given whatever this disposition last fired at.
|
|
153
|
+
function is_redundant_reread(tail: string, call: GuardedCall, fired_at_ms: number): boolean {
|
|
154
|
+
const target = read_target(call)
|
|
155
|
+
|
|
156
|
+
if (target === undefined) return false
|
|
157
|
+
|
|
158
|
+
const window = read_window(tail, target)
|
|
159
|
+
|
|
160
|
+
if (!is_unchanged_reread(window.last_ms, file_mtime_ms(target))) return false
|
|
161
|
+
|
|
162
|
+
return is_rearmed(window, fired_at_ms)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// **How this guard behaves for the session in hand, from the one-place enumeration** — `refuse` on the
|
|
166
|
+
// main line, `notice` in a dispatched lane child (joshuafolkken/kit#2298). The enumeration reads the
|
|
167
|
+
// dispatch mark against this checkout's own issue only for a mode it would change, so a person working
|
|
168
|
+
// in a lane sees the guard refuse exactly as the main line does.
|
|
169
|
+
function duplicate_mode(): LaneGuardMode {
|
|
170
|
+
return lane_guard_policy.mode_here(LANE_GUARD_ID)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// A candidate call is reached unless the enumeration turns the guard fully `off`; today no mode does,
|
|
174
|
+
// but the three-valued wrapper keeps that a change to the enumeration rather than to this file.
|
|
175
|
+
function is_candidate(call: GuardedCall): boolean {
|
|
176
|
+
return is_refusable_call(call) && duplicate_mode() !== 'off'
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// A refusable call is refused only where the mode is `refuse`. A lane child is `notice`, so it reaches
|
|
180
|
+
// here and is withheld the refusal — the notice branch carries the guidance instead, because a refusal
|
|
181
|
+
// ends a headless child's turn (joshuafolkken/kit#2138).
|
|
182
|
+
function should_block_here(tail: string, call: GuardedCall, refused_at_ms: number): boolean {
|
|
183
|
+
if (duplicate_mode() !== 'refuse') return false
|
|
184
|
+
|
|
185
|
+
return is_redundant_reread(tail, call, refused_at_ms)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// The `notice`-mode branch, reached in a dispatched lane child. It reads the notice's own last-fired
|
|
189
|
+
// instant, so a notice never spends the refusal's stamp and re-arms on the same "a newer read landed"
|
|
190
|
+
// rule the refusal does.
|
|
191
|
+
function should_notify_here(tail: string, call: GuardedCall, notified_at_ms: number): boolean {
|
|
192
|
+
if (duplicate_mode() !== 'notice') return false
|
|
193
|
+
|
|
194
|
+
return is_redundant_reread(tail, call, notified_at_ms)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const GUARD = hook_decision.create_transcript_guard({
|
|
198
|
+
prefix: STAMP_PREFIX,
|
|
199
|
+
switch_key: SWITCH_ENV_KEY,
|
|
200
|
+
is_candidate,
|
|
201
|
+
should_block: should_block_here,
|
|
202
|
+
reason: REASON,
|
|
203
|
+
notify: {
|
|
204
|
+
prefix: NOTICE_STAMP_PREFIX,
|
|
205
|
+
should_notify: should_notify_here,
|
|
206
|
+
text: () => NOTICE,
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
const duplicate_read_refusal = GUARD.refusal
|
|
211
|
+
const duplicate_read_outcome = GUARD.outcome
|
|
212
|
+
const { is_enabled, refusal_path } = GUARD
|
|
213
|
+
const notice_refusal_path = hook_decision.create_refusal_stamp(NOTICE_STAMP_PREFIX).path
|
|
214
|
+
const { deny_envelope, DISABLED_VALUES } = hook_decision
|
|
215
|
+
|
|
216
|
+
const duplicate_reads = {
|
|
217
|
+
REASON,
|
|
218
|
+
NOTICE,
|
|
219
|
+
SWITCH_ENV_KEY,
|
|
220
|
+
is_candidate,
|
|
221
|
+
is_rearmed,
|
|
222
|
+
is_redundant_reread,
|
|
223
|
+
is_refusable_call,
|
|
224
|
+
is_unchanged_reread,
|
|
225
|
+
last_read_ms,
|
|
226
|
+
read_target,
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
230
|
+
if (process.stdin.isTTY) hook_decision.report_no_payload('duplicate-read:guard')
|
|
231
|
+
else hook_decision.write_outcome(await text(process.stdin), duplicate_read_outcome)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export {
|
|
235
|
+
deny_envelope,
|
|
236
|
+
DISABLED_VALUES,
|
|
237
|
+
duplicate_read_outcome,
|
|
238
|
+
duplicate_read_refusal,
|
|
239
|
+
duplicate_reads,
|
|
240
|
+
is_enabled,
|
|
241
|
+
notice_refusal_path,
|
|
242
|
+
refusal_path,
|
|
243
|
+
SWITCH_ENV_KEY,
|
|
244
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { fanout, type FanoutUnit } from './fanout'
|
|
4
|
+
|
|
5
|
+
// `josh fanout <unit-files> <unit-files> …` — may the Step 0 change list be cut into file-disjoint
|
|
6
|
+
// units and dispatched in one fan-out turn? (joshuafolkken/kit#2345)
|
|
7
|
+
//
|
|
8
|
+
// A command rather than a paragraph, for the reason `josh delegate` is one: "these units look
|
|
9
|
+
// independent" is a judgement made under the same cost pressure, and the answer is mechanical — read
|
|
10
|
+
// off the file sets. Each argument is one unit's comma-separated file list; the verdict is on stdout
|
|
11
|
+
// so `$(josh fanout …)` reads it, the reason on stderr so a person sees why.
|
|
12
|
+
|
|
13
|
+
const ARGV_OFFSET = 2
|
|
14
|
+
const FAILURE_EXIT_CODE = 1
|
|
15
|
+
const USAGE =
|
|
16
|
+
'Usage: josh fanout <unit-files> <unit-files> [<unit-files> …] (each a comma-separated file list)'
|
|
17
|
+
|
|
18
|
+
const FILE_SEPARATOR = ','
|
|
19
|
+
|
|
20
|
+
// One argument to one unit: split on commas, trim, drop the empties a stray comma leaves.
|
|
21
|
+
function parse_unit(argument: string): FanoutUnit {
|
|
22
|
+
const files = argument
|
|
23
|
+
.split(FILE_SEPARATOR)
|
|
24
|
+
.map((file) => file.trim())
|
|
25
|
+
.filter((file) => file !== '')
|
|
26
|
+
|
|
27
|
+
return { files }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Refused when nothing was passed, or when a unit parses to no files at all — an empty unit says
|
|
31
|
+
// nothing about disjointness and is a typo, not a verdict.
|
|
32
|
+
function is_refused(units: ReadonlyArray<FanoutUnit>): boolean {
|
|
33
|
+
return units.length === 0 || units.some((unit) => unit.files.length === 0)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function run(argv: ReadonlyArray<string>): number {
|
|
37
|
+
const units = argv.map((argument) => parse_unit(argument))
|
|
38
|
+
|
|
39
|
+
if (is_refused(units)) {
|
|
40
|
+
console.error(USAGE)
|
|
41
|
+
|
|
42
|
+
return FAILURE_EXIT_CODE
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const result = fanout.fanout_result(units)
|
|
46
|
+
|
|
47
|
+
console.info(result.verdict)
|
|
48
|
+
console.error(result.reason)
|
|
49
|
+
|
|
50
|
+
return 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function main(argv: ReadonlyArray<string>): void {
|
|
54
|
+
process.exitCode = run(argv)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const fanout_cli = { USAGE, parse_unit, is_refused, run, main }
|
|
58
|
+
|
|
59
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
60
|
+
|
|
61
|
+
export { fanout_cli }
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Whether the Step 0 change list can be cut into file-disjoint units and dispatched in one fan-out
|
|
2
|
+
// turn, or must stay serial because two proposed units would edit the same file (joshuafolkken/kit#2345).
|
|
3
|
+
//
|
|
4
|
+
// **File-disjointness is the necessary condition, and it is mechanical.** Two subagents editing the
|
|
5
|
+
// same file in parallel race on that file — the later write lands on top of the earlier, or the gate
|
|
6
|
+
// has to reconcile a collision the parallelism was supposed to save. So the split is refused the
|
|
7
|
+
// moment any file appears in more than one unit, and the default is serial: fewer than two units is
|
|
8
|
+
// nothing to run in parallel. Nothing here is a judgement — the answer is read off the file sets.
|
|
9
|
+
|
|
10
|
+
type FanoutVerdict = 'parallel' | 'serial'
|
|
11
|
+
|
|
12
|
+
const PARALLEL_VERDICT: FanoutVerdict = 'parallel'
|
|
13
|
+
const SERIAL_VERDICT: FanoutVerdict = 'serial'
|
|
14
|
+
|
|
15
|
+
// One unit is nothing to parallelize; the fan-out only pays off from two independent units up.
|
|
16
|
+
const MIN_UNITS_TO_PARALLELIZE = 2
|
|
17
|
+
|
|
18
|
+
// A file carried by this many units or more is shared, so the units cannot run in parallel.
|
|
19
|
+
const SHARED_THRESHOLD = 2
|
|
20
|
+
|
|
21
|
+
interface FanoutUnit {
|
|
22
|
+
// The files this one unit edits, already split from the argument and trimmed.
|
|
23
|
+
files: ReadonlyArray<string>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface FanoutResult {
|
|
27
|
+
verdict: FanoutVerdict
|
|
28
|
+
// The reason, for a person; the verdict alone is what a shell reads.
|
|
29
|
+
reason: string
|
|
30
|
+
// The files that appear in more than one unit — empty on a `parallel` verdict.
|
|
31
|
+
overlaps: ReadonlyArray<string>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// The distinct files one unit edits. De-duplicated, so a file listed twice inside one unit is not
|
|
35
|
+
// counted as an overlap with anyone else.
|
|
36
|
+
function unit_files(unit: FanoutUnit): Array<string> {
|
|
37
|
+
return [...new Set(unit.files)]
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// How many units carry each file, across all units.
|
|
41
|
+
function file_counts(units: ReadonlyArray<FanoutUnit>): Map<string, number> {
|
|
42
|
+
const counts = new Map<string, number>()
|
|
43
|
+
const files = units.flatMap((unit) => unit_files(unit))
|
|
44
|
+
|
|
45
|
+
for (const file of files) {
|
|
46
|
+
counts.set(file, (counts.get(file) ?? 0) + 1)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return counts
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The files carried by two or more units, sorted.
|
|
53
|
+
function overlapping_files(units: ReadonlyArray<FanoutUnit>): Array<string> {
|
|
54
|
+
return [...file_counts(units)]
|
|
55
|
+
.filter(([, count]) => count >= SHARED_THRESHOLD)
|
|
56
|
+
.map(([file]) => file)
|
|
57
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The verdict for a set of proposed units. Serial below two units, serial on any shared file naming
|
|
61
|
+
// what collides, parallel only when every unit's file set is disjoint from every other's.
|
|
62
|
+
function fanout_result(units: ReadonlyArray<FanoutUnit>): FanoutResult {
|
|
63
|
+
if (units.length < MIN_UNITS_TO_PARALLELIZE) {
|
|
64
|
+
return {
|
|
65
|
+
verdict: SERIAL_VERDICT,
|
|
66
|
+
reason: 'fewer than two units — nothing to run in parallel',
|
|
67
|
+
overlaps: [],
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const overlaps = overlapping_files(units)
|
|
72
|
+
|
|
73
|
+
if (overlaps.length > 0) {
|
|
74
|
+
const reason = `units share ${overlaps.join(', ')} — parallel edits would race, so run serial`
|
|
75
|
+
|
|
76
|
+
return { verdict: SERIAL_VERDICT, reason, overlaps }
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
verdict: PARALLEL_VERDICT,
|
|
81
|
+
reason: `${String(units.length)} file-disjoint units`,
|
|
82
|
+
overlaps: [],
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const fanout = {
|
|
87
|
+
PARALLEL_VERDICT,
|
|
88
|
+
SERIAL_VERDICT,
|
|
89
|
+
MIN_UNITS_TO_PARALLELIZE,
|
|
90
|
+
overlapping_files,
|
|
91
|
+
fanout_result,
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type { FanoutResult, FanoutUnit, FanoutVerdict }
|
|
95
|
+
export { fanout }
|