@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,144 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
5
|
+
import { lane_guard_policy, type LaneGuardMode } from '#scripts/lane/lane-guard-policy'
|
|
6
|
+
import { time_batch_guard, type GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
7
|
+
|
|
8
|
+
// The disk half of the batching guard (joshuafolkken/kit#1390): find the transcript, read enough of
|
|
9
|
+
// its end, remember when a call was last refused, and write the refusal Claude Code understands.
|
|
10
|
+
//
|
|
11
|
+
// **It is a `PreToolUse` hook, and that is the point of the Issue.** The live density line rides
|
|
12
|
+
// `PostToolUse`, where the round trip has already been spent and all that is left is to describe it.
|
|
13
|
+
// Three runs measured after that line shipped came in at 1.10–1.12 calls per round trip, unchanged —
|
|
14
|
+
// so what is added here intervenes in the decision instead of reporting on it.
|
|
15
|
+
//
|
|
16
|
+
// **What the transcript holds is the turns already closed, and nothing usable about the one in hand.**
|
|
17
|
+
// Claude Code writes one line per content block and starts the first tool as soon as that block parses,
|
|
18
|
+
// so a turn's later `tool_use` lines do not exist yet — measured on a live session, they arrive 1.4 to
|
|
19
|
+
// 15 seconds afterwards. The decision is therefore made from closed history alone;
|
|
20
|
+
// `time-batch-guard.ts` → "What it cannot know" carries the measurement and what it costs.
|
|
21
|
+
//
|
|
22
|
+
// **The shell is `hook-decision.ts`, shared with the investigation guard** (joshuafolkken/kit#1460):
|
|
23
|
+
// the payload schema, the deny envelope, the switch, the `.env` load, the stamp that makes a refusal
|
|
24
|
+
// unrepeatable, and the six steps every refusing hook takes in the same order. What stays here is this
|
|
25
|
+
// guard's own rule and its own two names, and the seven exports below are unchanged so nothing that
|
|
26
|
+
// reads them had to move.
|
|
27
|
+
|
|
28
|
+
// The escape hatch. **On by default**: this is a distributed convention, and a guard nobody enables
|
|
29
|
+
// would leave the Issue exactly where it started. What the variable buys is a way to switch a
|
|
30
|
+
// refusing hook off without editing the settings
|
|
31
|
+
// file — a machine debugging the guard itself, or a session where a run of genuinely dependent single
|
|
32
|
+
// calls is expected.
|
|
33
|
+
const SWITCH_ENV_KEY = 'JOSH_BATCH_GUARD'
|
|
34
|
+
|
|
35
|
+
// **The judgement is `time-batch-guard.ts`'s, not a second one.** Whether a call is one this guard may
|
|
36
|
+
// refuse and whether the run has stopped batching are both its, so a refusal here can never disagree
|
|
37
|
+
// with the report the Issue's own verification step reads.
|
|
38
|
+
// The transcript is read for a call the guard could act on either way: one it may refuse, or the one
|
|
39
|
+
// whole-file write it may only notify about (joshuafolkken/kit#1848). The read is skipped for the rest
|
|
40
|
+
// exactly as before — most of a run's calls are neither.
|
|
41
|
+
function is_batch_candidate(call: GuardedCall): boolean {
|
|
42
|
+
return time_batch_guard.is_guarded_call(call) || time_batch_guard.is_notice_call(call)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// **How the batching guard behaves for the session in hand, decided from the one-place enumeration**
|
|
46
|
+
// (joshuafolkken/kit#2138, joshuafolkken/kit#2164, joshuafolkken/kit#2178, joshuafolkken/kit#2276).
|
|
47
|
+
// Outside a lane child the mode is `refuse` and the guard is exactly what it always was; in a dispatched
|
|
48
|
+
// lane child it is `notice` — kit#2178 took it to `off` after kit#2164's generic notice did not move the
|
|
49
|
+
// density, and kit#2276 restores it as a notice that names the concrete recent calls and recurs every
|
|
50
|
+
// single-call turn, the two things #2164's notice lacked, so the density can be re-measured with the
|
|
51
|
+
// notice actually firing where it is measured. The wrappers below are three-valued so this needs no
|
|
52
|
+
// change beyond the enumeration. The enumeration reads `is_child_of` — the dispatch mark against this
|
|
53
|
+
// checkout's own issue — only for a guard whose mode it would actually change, so a person working in a
|
|
54
|
+
// lane sees the guard unchanged.
|
|
55
|
+
function batching_mode(): LaneGuardMode {
|
|
56
|
+
return lane_guard_policy.mode_here('batching')
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// A guard the enumeration turns fully `off` says nothing at all. Batching is `notice` in a lane child
|
|
60
|
+
// since kit#2276, so a candidate call is reached there; only a guard some future enumeration sets to
|
|
61
|
+
// `off` is skipped. On the main line the mode is `refuse`.
|
|
62
|
+
function is_candidate(call: GuardedCall): boolean {
|
|
63
|
+
return is_batch_candidate(call) && batching_mode() !== 'off'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// A refusable call is refused only where the mode is `refuse`. A lane child is `notice` (kit#2276), so
|
|
67
|
+
// it reaches here and is withheld the refusal — the notice branch below carries the guidance instead,
|
|
68
|
+
// because a refusal ends a headless child's turn (kit#2138).
|
|
69
|
+
function should_block_here(tail: string, call: GuardedCall, refused_at_ms: number): boolean {
|
|
70
|
+
if (batching_mode() !== 'refuse') return false
|
|
71
|
+
|
|
72
|
+
return time_batch_guard.should_block(tail, call, refused_at_ms)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The whole-file write earns a notice on every run (joshuafolkken/kit#1848). The second branch turns a
|
|
76
|
+
// refusable call into a notice under a `notice`-mode guard, which is the mode batching takes in a lane
|
|
77
|
+
// child again since kit#2276. Both read the notice's own record, so a notice never spends the refusal's
|
|
78
|
+
// stamp and re-fires on the notice's own `NOTICE_REFIRE_EVERY` cadence.
|
|
79
|
+
function should_notify_here(tail: string, call: GuardedCall, notified_at_ms: number): boolean {
|
|
80
|
+
if (time_batch_guard.should_notify(tail, call, notified_at_ms)) return true
|
|
81
|
+
if (batching_mode() !== 'notice') return false
|
|
82
|
+
|
|
83
|
+
return time_batch_guard.should_block(
|
|
84
|
+
tail,
|
|
85
|
+
call,
|
|
86
|
+
notified_at_ms,
|
|
87
|
+
time_batch_guard.NOTICE_REFIRE_EVERY,
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// The wording each notice carries, with the concrete calls the run just issued one-per-turn appended
|
|
92
|
+
// (joshuafolkken/kit#2276). The whole-file write keeps its own base text; the lane notice is reached
|
|
93
|
+
// under the `notice`-mode guard batching takes in a lane child again since kit#2276, so a headless
|
|
94
|
+
// child is shown *which* recent calls it could have batched rather than only told to batch.
|
|
95
|
+
function notice_text(call: GuardedCall, tail: string): string {
|
|
96
|
+
const base = time_batch_guard.is_notice_call(call)
|
|
97
|
+
? time_batch_guard.NOTICE
|
|
98
|
+
: time_batch_guard.LANE_NOTICE
|
|
99
|
+
|
|
100
|
+
return `${base}${time_batch_guard.recent_candidates(tail)}`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const GUARD = hook_decision.create_transcript_guard({
|
|
104
|
+
prefix: time_batch_guard.STAMP_PREFIX,
|
|
105
|
+
switch_key: SWITCH_ENV_KEY,
|
|
106
|
+
is_candidate,
|
|
107
|
+
should_block: should_block_here,
|
|
108
|
+
reason: time_batch_guard.REASON,
|
|
109
|
+
// The whole-file write is notified rather than refused, on a record of its own so it never spends
|
|
110
|
+
// the refusal's stamp (joshuafolkken/kit#1848); the lane-child refusable-call notice kit#2164 added
|
|
111
|
+
// here fires again since kit#2276 restored batching to `notice` in a lane child.
|
|
112
|
+
notify: {
|
|
113
|
+
prefix: time_batch_guard.NOTICE_STAMP_PREFIX,
|
|
114
|
+
should_notify: should_notify_here,
|
|
115
|
+
text: notice_text,
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
const batch_refusal = GUARD.refusal
|
|
120
|
+
const batch_outcome = GUARD.outcome
|
|
121
|
+
const { is_enabled, refusal_path } = GUARD
|
|
122
|
+
// The notice's stamp path, exposed the way `refusal_path` is so a test can clean it apart from the
|
|
123
|
+
// refusal's record (joshuafolkken/kit#1848).
|
|
124
|
+
const notice_refusal_path = hook_decision.create_refusal_stamp(
|
|
125
|
+
time_batch_guard.NOTICE_STAMP_PREFIX,
|
|
126
|
+
).path
|
|
127
|
+
const { deny_envelope, load_environment_file, DISABLED_VALUES } = hook_decision
|
|
128
|
+
|
|
129
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
130
|
+
if (process.stdin.isTTY) hook_decision.report_no_payload('batch:guard')
|
|
131
|
+
else hook_decision.write_outcome(await text(process.stdin), batch_outcome)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export {
|
|
135
|
+
batch_outcome,
|
|
136
|
+
batch_refusal,
|
|
137
|
+
deny_envelope,
|
|
138
|
+
is_enabled,
|
|
139
|
+
load_environment_file,
|
|
140
|
+
notice_refusal_path,
|
|
141
|
+
refusal_path,
|
|
142
|
+
DISABLED_VALUES,
|
|
143
|
+
SWITCH_ENV_KEY,
|
|
144
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { readFileSync } from 'node:fs'
|
|
3
|
+
import os from 'node:os'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
import { git_command } from '#scripts/git/git-command'
|
|
7
|
+
|
|
8
|
+
interface CheckResult {
|
|
9
|
+
success: boolean
|
|
10
|
+
message: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const PARENT_SEGMENT = '..'
|
|
14
|
+
const COMMIT_MESSAGE_FILE_NAME = 'COMMIT_EDITMSG'
|
|
15
|
+
// Only for a checkout git could not answer for; every real invocation has git's own answer.
|
|
16
|
+
const FALLBACK_GIT_DIRECTORY = '.git'
|
|
17
|
+
|
|
18
|
+
// Containment, decided after resolving — not a prefix of the spelling handed in. `path.relative`
|
|
19
|
+
// answers how to walk from the directory to the file, so a path that climbs back out of it starts
|
|
20
|
+
// with `..`, and one that never entered it comes back absolute. A string prefix would accept
|
|
21
|
+
// `<dir>/../../etc/passwd`, which is the whole file this guard refuses to read.
|
|
22
|
+
function is_inside(directory: string, resolved_path: string): boolean {
|
|
23
|
+
const relative = path.relative(directory, resolved_path)
|
|
24
|
+
|
|
25
|
+
return relative !== '' && !relative.startsWith(PARENT_SEGMENT) && !path.isAbsolute(relative)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// joshuafolkken/kit#1106: the guard used to be a prefix test — the path had to *start* with `.git/`,
|
|
29
|
+
// which is only the shape the main work tree produces. A linked work tree gets an absolute
|
|
30
|
+
// `<repo>/.git/worktrees/<name>/COMMIT_EDITMSG`, which shares no prefix with it, so the guard threw
|
|
31
|
+
// before the real check ran and no commit inside a work tree could succeed.
|
|
32
|
+
//
|
|
33
|
+
// The directories are asked of git rather than assumed to be named `.git`, because the name is not a
|
|
34
|
+
// property of a repository: a bare repository's git directory is the repository, and
|
|
35
|
+
// `--separate-git-dir` puts it anywhere at all. Matching a `.git` segment instead would refuse both,
|
|
36
|
+
// reproducing this defect one case over — and it would accept any path that merely passes through
|
|
37
|
+
// some `.git` directory, which is wider than what the guard is for.
|
|
38
|
+
function is_safe_commit_message_path(
|
|
39
|
+
file_path: string,
|
|
40
|
+
git_directories: ReadonlyArray<string>,
|
|
41
|
+
): boolean {
|
|
42
|
+
const resolved = path.resolve(file_path)
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
git_directories.some((directory) => is_inside(directory, resolved)) ||
|
|
46
|
+
is_inside(os.tmpdir(), resolved)
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Where git would have written the message, for a run that was passed no path. The work tree's own
|
|
51
|
+
// git directory rather than a literal `.git/`: in a linked work tree that name is a *file*, so the
|
|
52
|
+
// relative spelling this used to hardcode ends the run at ENOTDIR — the same defect as the guard's,
|
|
53
|
+
// on the branch the guard does not reach (joshuafolkken/kit#1106).
|
|
54
|
+
function default_commit_message_path(git_directories: ReadonlyArray<string>): string {
|
|
55
|
+
return path.join(git_directories[0] ?? FALLBACK_GIT_DIRECTORY, COMMIT_MESSAGE_FILE_NAME)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function get_commit_message(): Promise<string> {
|
|
59
|
+
const FILE_INDEX = 2
|
|
60
|
+
const commit_message_file = process.argv.at(FILE_INDEX)
|
|
61
|
+
const git_directories = await git_command.git_directories()
|
|
62
|
+
const message_path = commit_message_file ?? default_commit_message_path(git_directories)
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
commit_message_file !== undefined &&
|
|
66
|
+
!is_safe_commit_message_path(commit_message_file, git_directories)
|
|
67
|
+
) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Commit message file must be inside a git directory or the system temp dir: ${commit_message_file}`,
|
|
70
|
+
)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
return readFileSync(message_path, 'utf8').trim()
|
|
75
|
+
} catch (error) {
|
|
76
|
+
throw new Error(`Failed to read commit message file: ${message_path}`, { cause: error })
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function extract_issue_number(branch_name: string): string | undefined {
|
|
81
|
+
const branch_pattern = /^(\d+)-[\da-z-]+$/u
|
|
82
|
+
const match = branch_pattern.exec(branch_name)
|
|
83
|
+
|
|
84
|
+
return match?.[1]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function create_error_message(issue_number: string, branch: string, message: string): string {
|
|
88
|
+
return (
|
|
89
|
+
`🚫 Error: Commit message must include #${issue_number}\n` +
|
|
90
|
+
` Current branch: ${branch}\n` +
|
|
91
|
+
` Commit message: ${message}\n` +
|
|
92
|
+
` Please include #${issue_number} in your commit message\n`
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function check_commit_message(): Promise<CheckResult> {
|
|
97
|
+
const current_branch = await git_command.branch()
|
|
98
|
+
const issue_number = extract_issue_number(current_branch)
|
|
99
|
+
|
|
100
|
+
if (issue_number === undefined) {
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
message: `✅ Branch format check passed: '${current_branch}' (no issue number required)`,
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const commit_message = await get_commit_message()
|
|
108
|
+
|
|
109
|
+
if (!commit_message.includes(`#${issue_number}`)) {
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
message: create_error_message(issue_number, current_branch, commit_message),
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
message: `✅ Commit message check passed: Found #${issue_number}`,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function main(): Promise<void> {
|
|
123
|
+
const result = await check_commit_message()
|
|
124
|
+
|
|
125
|
+
console.info(result.message)
|
|
126
|
+
|
|
127
|
+
if (!result.success) process.exit(1)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main()
|
|
131
|
+
|
|
132
|
+
export { check_commit_message, extract_issue_number, is_safe_commit_message_path }
|
|
133
|
+
|
|
134
|
+
export type { CheckResult }
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { hook_decision, type GuardOutcome } from '#scripts/josh/hook-decision'
|
|
5
|
+
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
6
|
+
import { time_density_hook } from '#scripts/time-runtime/time-density-hook'
|
|
7
|
+
import { z } from 'zod'
|
|
8
|
+
import { build_envelope, compose_context, format_edited_payload } from './format-edited-file'
|
|
9
|
+
import { pretool_guard } from './pretool-guard'
|
|
10
|
+
|
|
11
|
+
const APPLY_PATCH_TOOL = 'apply_patch'
|
|
12
|
+
const EDIT_TOOL = 'Edit'
|
|
13
|
+
const PRETOOL_MODE = 'pretool'
|
|
14
|
+
const POSTTOOL_MODE = 'posttool'
|
|
15
|
+
const MODE_ARGUMENT_INDEX = 2
|
|
16
|
+
const PATCH_FILE_PATTERN = /^\*\*\* (?:Add|Delete|Update) File: (.+)$/gmu
|
|
17
|
+
const PATCH_MOVE_PATTERN = /^\*\*\* Move to: (.+)$/gmu
|
|
18
|
+
// One canonical formatter can spend at most 75 seconds across its bounded process fallbacks. Start
|
|
19
|
+
// at most two together and no later work, so every formatter that starts retains the 15-second
|
|
20
|
+
// margin inside the Codex hook's 90-second timeout. Remaining files are left to the verification gate.
|
|
21
|
+
const MAX_PARALLEL_FORMATS = 2
|
|
22
|
+
// One patch can touch several files, each returning its own unfixed-lint block; a blank line between
|
|
23
|
+
// them keeps the blocks readable when they are joined into the single envelope below.
|
|
24
|
+
const DIAGNOSTIC_SEPARATOR = '\n\n'
|
|
25
|
+
|
|
26
|
+
// Codex deliberately reports its canonical tool name even when an Edit or Write matcher selected
|
|
27
|
+
// the hook. Its apply_patch body is `tool_input.command`; the Claude-shaped handlers downstream
|
|
28
|
+
// instead classify Edit/Write and read `tool_input.file_path`. This module is the only translation
|
|
29
|
+
// boundary between those provider contracts.
|
|
30
|
+
const codex_payload_schema = z.looseObject({
|
|
31
|
+
tool_name: z.string().min(1),
|
|
32
|
+
tool_input: z.unknown(),
|
|
33
|
+
})
|
|
34
|
+
const patch_input_schema = z.object({ command: z.string().min(1) })
|
|
35
|
+
|
|
36
|
+
type PayloadFormatter = (raw_payload: string, project_root: string) => Promise<string | undefined>
|
|
37
|
+
|
|
38
|
+
function parse_payload(raw_payload: string): z.infer<typeof codex_payload_schema> | undefined {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = codex_payload_schema.safeParse(JSON.parse(raw_payload))
|
|
41
|
+
|
|
42
|
+
return parsed.success ? parsed.data : undefined
|
|
43
|
+
} catch {
|
|
44
|
+
return undefined
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function paths_matching(command: string, pattern: RegExp): Array<string> {
|
|
49
|
+
return [...command.matchAll(pattern)].flatMap((match) => {
|
|
50
|
+
const file_path = match[1]?.trim()
|
|
51
|
+
|
|
52
|
+
return file_path === undefined || file_path === '' ? [] : [file_path]
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function patch_paths(tool_input: unknown): Array<string> {
|
|
57
|
+
const parsed = patch_input_schema.safeParse(tool_input)
|
|
58
|
+
if (!parsed.success) return []
|
|
59
|
+
const paths = [
|
|
60
|
+
...paths_matching(parsed.data.command, PATCH_FILE_PATTERN),
|
|
61
|
+
...paths_matching(parsed.data.command, PATCH_MOVE_PATTERN),
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
return [...new Set(paths)]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function canonical_payload(
|
|
68
|
+
payload: z.infer<typeof codex_payload_schema>,
|
|
69
|
+
file_path: string,
|
|
70
|
+
file_paths: ReadonlyArray<string>,
|
|
71
|
+
): string {
|
|
72
|
+
return JSON.stringify({ ...payload, tool_name: EDIT_TOOL, tool_input: { file_path, file_paths } })
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function pretool_payload(raw_payload: string): string {
|
|
76
|
+
const payload = parse_payload(raw_payload)
|
|
77
|
+
if (payload?.tool_name !== APPLY_PATCH_TOOL) return raw_payload
|
|
78
|
+
const paths = patch_paths(payload.tool_input)
|
|
79
|
+
const [file_path] = paths
|
|
80
|
+
if (file_path === undefined) return raw_payload
|
|
81
|
+
|
|
82
|
+
return canonical_payload(payload, file_path, paths)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function posttool_payloads(raw_payload: string): Array<string> {
|
|
86
|
+
const payload = parse_payload(raw_payload)
|
|
87
|
+
if (payload?.tool_name !== APPLY_PATCH_TOOL) return [raw_payload]
|
|
88
|
+
|
|
89
|
+
return patch_paths(payload.tool_input).map((file_path) =>
|
|
90
|
+
canonical_payload(payload, file_path, [file_path]),
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function pretool_outcome(raw_payload: string): GuardOutcome {
|
|
95
|
+
return pretool_guard.pretool_outcome(pretool_payload(raw_payload))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// The formatters apply what eslint could fix silently and return what it could not; each patched
|
|
99
|
+
// file's unfixed block is joined so the whole patch's lint problems reach the model on one edit
|
|
100
|
+
// (joshuafolkken/kit#2275). `undefined` when every file was clean, so the ordinary patch adds nothing.
|
|
101
|
+
async function format_posttool_payloads(
|
|
102
|
+
raw_payload: string,
|
|
103
|
+
project_root: string,
|
|
104
|
+
formatter: PayloadFormatter = format_edited_payload,
|
|
105
|
+
): Promise<string | undefined> {
|
|
106
|
+
const planned = posttool_payloads(raw_payload).slice(0, MAX_PARALLEL_FORMATS)
|
|
107
|
+
const results = await bounded_pool.bounded_map(planned, MAX_PARALLEL_FORMATS, async (payload) => {
|
|
108
|
+
return await formatter(payload, project_root)
|
|
109
|
+
})
|
|
110
|
+
const blocks = results.filter((block): block is string => block !== undefined)
|
|
111
|
+
|
|
112
|
+
return blocks.length === 0 ? undefined : blocks.join(DIAGNOSTIC_SEPARATOR)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The density line and the unfixed-lint blocks reach the model the same way — as additionalContext on
|
|
116
|
+
// this one hook — so they are joined into the single envelope a `PostToolUse` payload can carry rather
|
|
117
|
+
// than written as two objects the harness could not parse.
|
|
118
|
+
async function write_posttool_context(raw_payload: string): Promise<void> {
|
|
119
|
+
const notice = time_density_hook.density_notice(raw_payload)
|
|
120
|
+
const diagnostics = await format_posttool_payloads(raw_payload, process.cwd())
|
|
121
|
+
const context = compose_context(notice, diagnostics)
|
|
122
|
+
|
|
123
|
+
if (context !== undefined) process.stdout.write(`${build_envelope(context)}\n`)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function run(raw_payload: string, mode: string): Promise<void> {
|
|
127
|
+
if (mode === PRETOOL_MODE) {
|
|
128
|
+
hook_decision.write_outcome(raw_payload, pretool_outcome)
|
|
129
|
+
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (mode === POSTTOOL_MODE) {
|
|
134
|
+
await write_posttool_context(raw_payload)
|
|
135
|
+
|
|
136
|
+
return
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
process.stderr.write(`codex-hook-adapter expects ${PRETOOL_MODE} or ${POSTTOOL_MODE}.\n`)
|
|
140
|
+
process.exitCode = 1
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
144
|
+
await run(await text(process.stdin), process.argv[MODE_ARGUMENT_INDEX] ?? '')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const codex_hook_adapter = {
|
|
148
|
+
format_posttool_payloads,
|
|
149
|
+
patch_paths,
|
|
150
|
+
posttool_payloads,
|
|
151
|
+
pretool_outcome,
|
|
152
|
+
pretool_payload,
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export { codex_hook_adapter }
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { execa } from 'execa'
|
|
4
|
+
|
|
5
|
+
// The spell half of the edit hook (joshuafolkken/kit#2296). joshuafolkken/kit#2275 gave the hook a way
|
|
6
|
+
// to hand the model an edit's lint problems on the spot rather than at the gate; the gate then still
|
|
7
|
+
// ran two extra times on average, and an unregistered word was one of the two things that put it there
|
|
8
|
+
// — a `cspell:dot` failure a run could only read one word at a time under the output cap. Checking the
|
|
9
|
+
// one edited file for unknown words the moment it changes closes that the same way the lint half does:
|
|
10
|
+
// a short `additionalContext` block, riding the same `PostToolUse` envelope, and no output at all when
|
|
11
|
+
// there is nothing to say.
|
|
12
|
+
|
|
13
|
+
// **The kinds worth spell-checking on an edit.** cspell will lint any path handed to it, so without a
|
|
14
|
+
// filter an edit to a binary asset would be read as text and report its bytes as unknown words. This is
|
|
15
|
+
// the text where a real unknown word can live; anything else is a no-op before a process starts. It is
|
|
16
|
+
// a spell-check concern of its own, not the prettier/eslint extension lists in `format-edited-file.ts`.
|
|
17
|
+
const CSPELL_EXTENSIONS: ReadonlySet<string> = new Set([
|
|
18
|
+
'.ts',
|
|
19
|
+
'.tsx',
|
|
20
|
+
'.js',
|
|
21
|
+
'.jsx',
|
|
22
|
+
'.mjs',
|
|
23
|
+
'.cjs',
|
|
24
|
+
'.svelte',
|
|
25
|
+
'.md',
|
|
26
|
+
'.mdx',
|
|
27
|
+
'.txt',
|
|
28
|
+
'.json',
|
|
29
|
+
'.jsonc',
|
|
30
|
+
'.yml',
|
|
31
|
+
'.yaml',
|
|
32
|
+
'.html',
|
|
33
|
+
'.css',
|
|
34
|
+
])
|
|
35
|
+
|
|
36
|
+
// `lint` so the sub-command is explicit, `--words-only --unique` so stdout is the unknown words and
|
|
37
|
+
// nothing else, `--no-progress --no-summary` so neither the progress line nor the tally is on it. The
|
|
38
|
+
// exit code is ignored: cspell exits non-zero precisely when it found words, which is the case this
|
|
39
|
+
// exists for.
|
|
40
|
+
const CSPELL_ARGS: ReadonlyArray<string> = [
|
|
41
|
+
'exec',
|
|
42
|
+
'cspell',
|
|
43
|
+
'lint',
|
|
44
|
+
'--words-only',
|
|
45
|
+
'--unique',
|
|
46
|
+
'--no-progress',
|
|
47
|
+
'--no-summary',
|
|
48
|
+
]
|
|
49
|
+
const PNPM = 'pnpm'
|
|
50
|
+
// A spell check that hangs would hold the edit's turn open; the bound is generous because reaching it
|
|
51
|
+
// means something is already wrong, exactly as the formatter spawns in `format-edited-file.ts`.
|
|
52
|
+
const PROCESS_TIMEOUT_MS = 15_000
|
|
53
|
+
|
|
54
|
+
const HEADER =
|
|
55
|
+
'The edit hook found words cspell does not know; fix them or add them to `cspell.config.yaml` now rather than at the gate:'
|
|
56
|
+
// additionalContext rides back on the edit, so a runaway list is bounded the same way the lint half is.
|
|
57
|
+
const MAX_DIAGNOSTIC_CHARS = 4000
|
|
58
|
+
const TRUNCATION_NOTICE = '\n…(unknown words truncated)'
|
|
59
|
+
|
|
60
|
+
type CspellRunner = (file_path: string, project_root: string) => Promise<string>
|
|
61
|
+
|
|
62
|
+
// One question before a process starts: is this a file under the project that spell-checking has
|
|
63
|
+
// anything to say about?
|
|
64
|
+
function is_checkable(file_path: string, project_root: string): boolean {
|
|
65
|
+
if (!existsSync(file_path) || !CSPELL_EXTENSIONS.has(path.extname(file_path).toLowerCase())) {
|
|
66
|
+
return false
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const relative = path.relative(path.resolve(project_root), path.resolve(file_path))
|
|
70
|
+
|
|
71
|
+
return relative !== '' && !relative.startsWith('..') && !path.isAbsolute(relative)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The live runner. `reject: false` because a non-zero exit is the ordinary way cspell reports words,
|
|
75
|
+
// and stderr is ignored so a config note never reaches the model as if it were an unknown word.
|
|
76
|
+
async function run_cspell(file_path: string, project_root: string): Promise<string> {
|
|
77
|
+
const result = await execa(PNPM, [...CSPELL_ARGS, file_path], {
|
|
78
|
+
reject: false,
|
|
79
|
+
cwd: project_root,
|
|
80
|
+
stdout: 'pipe',
|
|
81
|
+
stderr: 'ignore',
|
|
82
|
+
timeout: PROCESS_TIMEOUT_MS,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
return result.stdout
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// The block the model reads, or `undefined` when cspell knew every word — so an ordinary edit adds
|
|
89
|
+
// nothing to additionalContext. The words are cut to the bound before the header is added, so the cap
|
|
90
|
+
// covers the whole block.
|
|
91
|
+
function format_unknown_words(stdout: string): string | undefined {
|
|
92
|
+
const words = stdout
|
|
93
|
+
.split('\n')
|
|
94
|
+
.map((word) => word.trim())
|
|
95
|
+
.filter((word) => word.length > 0)
|
|
96
|
+
|
|
97
|
+
if (words.length === 0) return undefined
|
|
98
|
+
|
|
99
|
+
const joined = words.join('\n')
|
|
100
|
+
const body =
|
|
101
|
+
joined.length > MAX_DIAGNOSTIC_CHARS
|
|
102
|
+
? `${joined.slice(0, MAX_DIAGNOSTIC_CHARS)}${TRUNCATION_NOTICE}`
|
|
103
|
+
: joined
|
|
104
|
+
|
|
105
|
+
return `${HEADER}\n${body}`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Never turns a successful edit into a failure: a runner that throws — cspell missing, a timeout — is
|
|
109
|
+
// swallowed and reported as nothing to say, exactly as the lint half swallows a formatter that could
|
|
110
|
+
// not start.
|
|
111
|
+
async function spelling_diagnostics(
|
|
112
|
+
file_path: string | undefined,
|
|
113
|
+
project_root: string,
|
|
114
|
+
runner: CspellRunner = run_cspell,
|
|
115
|
+
): Promise<string | undefined> {
|
|
116
|
+
if (file_path === undefined || !is_checkable(file_path, project_root)) return undefined
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
return format_unknown_words(await runner(file_path, project_root))
|
|
120
|
+
} catch {
|
|
121
|
+
return undefined
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const edited_cspell = { format_unknown_words, is_checkable, spelling_diagnostics }
|
|
126
|
+
|
|
127
|
+
export type { CspellRunner }
|
|
128
|
+
export { edited_cspell, MAX_DIAGNOSTIC_CHARS }
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { plan_commands, type CommandRunner, type FormatCommand } from './format-edited-file'
|
|
4
|
+
|
|
5
|
+
// Shared across the two `format-edited-file` suites so neither redefines the other's fixtures. The
|
|
6
|
+
// per-suite temp directory stays in each test file — vitest isolates the files, so each evaluates
|
|
7
|
+
// this module and its own `afterAll` teardown of its own `mkdtemp`.
|
|
8
|
+
const PRETTIER = 'prettier'
|
|
9
|
+
const ESLINT = 'eslint'
|
|
10
|
+
|
|
11
|
+
// What a formatter that ran and had nothing to say returns, so a test runner reads as "this route
|
|
12
|
+
// worked" and no fallback is attempted.
|
|
13
|
+
const RAN_CLEANLY = { exit_code: 0, stdout: '' }
|
|
14
|
+
|
|
15
|
+
function payload_for(file_path: string): string {
|
|
16
|
+
return JSON.stringify({
|
|
17
|
+
hook_event_name: 'PostToolUse',
|
|
18
|
+
tool_input: { file_path },
|
|
19
|
+
tool_name: 'Edit',
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// What Claude Code hands this hook after a shell call, which the matcher covers since
|
|
24
|
+
// joshuafolkken/kit#1337: a command, and no edited path anywhere in the payload. The command edits a
|
|
25
|
+
// file on purpose — an agent working through `sed` is the mode the widening was measured against,
|
|
26
|
+
// and nothing here may start formatting a path it had to guess at.
|
|
27
|
+
function shell_payload(transcript_path?: string): string {
|
|
28
|
+
return JSON.stringify({
|
|
29
|
+
tool_name: 'Bash',
|
|
30
|
+
tool_input: { command: `sed -i '' s/a/b/ app.ts` },
|
|
31
|
+
transcript_path,
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function eslint_failing_runner(runs: Array<string>): CommandRunner {
|
|
36
|
+
return async (command) => {
|
|
37
|
+
await Promise.resolve()
|
|
38
|
+
|
|
39
|
+
if (command.bin === ESLINT) throw new Error('spawn ENOENT')
|
|
40
|
+
|
|
41
|
+
runs.push(command.bin)
|
|
42
|
+
|
|
43
|
+
return RAN_CLEANLY
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const failing_runner: CommandRunner = async () => {
|
|
48
|
+
await Promise.resolve()
|
|
49
|
+
throw new Error('the formatter failed to start')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function recording_runner(runs: Array<string>): CommandRunner {
|
|
53
|
+
return async (command) => {
|
|
54
|
+
runs.push(command.bin)
|
|
55
|
+
|
|
56
|
+
await Promise.resolve()
|
|
57
|
+
|
|
58
|
+
return RAN_CLEANLY
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// eslint exits non-zero with its problems on stdout when a `--fix` pass leaves something it could
|
|
63
|
+
// not fix; prettier runs cleanly. This is the shape the hook has to lift the diagnostics out of.
|
|
64
|
+
function eslint_reporting_runner(stdout: string): CommandRunner {
|
|
65
|
+
return async (command) => {
|
|
66
|
+
await Promise.resolve()
|
|
67
|
+
|
|
68
|
+
if (command.bin === ESLINT) return { exit_code: 1, stdout }
|
|
69
|
+
|
|
70
|
+
return RAN_CLEANLY
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface DirectoryHelpers {
|
|
75
|
+
write_fixture: (...segments: ReadonlyArray<string>) => string
|
|
76
|
+
plan_commands_in: (file_path: string) => ReadonlyArray<FormatCommand>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Bound to a suite's own temp directory so the call sites stay `write_fixture('app.ts')`. The nested
|
|
80
|
+
// functions close over `directory`, so they cannot be hoisted to module scope.
|
|
81
|
+
function make_directory_helpers(directory: string): DirectoryHelpers {
|
|
82
|
+
function write_fixture(...segments: ReadonlyArray<string>): string {
|
|
83
|
+
const file_path = path.join(directory, ...segments)
|
|
84
|
+
|
|
85
|
+
mkdirSync(path.dirname(file_path), { recursive: true })
|
|
86
|
+
writeFileSync(file_path, '\n', 'utf8')
|
|
87
|
+
|
|
88
|
+
return file_path
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function plan_commands_in(file_path: string): ReadonlyArray<FormatCommand> {
|
|
92
|
+
return plan_commands(file_path, directory)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { write_fixture, plan_commands_in }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export {
|
|
99
|
+
eslint_failing_runner,
|
|
100
|
+
eslint_reporting_runner,
|
|
101
|
+
failing_runner,
|
|
102
|
+
make_directory_helpers,
|
|
103
|
+
payload_for,
|
|
104
|
+
recording_runner,
|
|
105
|
+
shell_payload,
|
|
106
|
+
ESLINT,
|
|
107
|
+
PRETTIER,
|
|
108
|
+
RAN_CLEANLY,
|
|
109
|
+
}
|