@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,241 @@
|
|
|
1
|
+
import { hook_decision, type GuardRun } from '#scripts/josh/hook-decision'
|
|
2
|
+
import { run_progress } from '#scripts/run/run-progress'
|
|
3
|
+
import { run_progress_clock } from '#scripts/run/run-progress-clock'
|
|
4
|
+
import { run_progress_config } from '#scripts/run/run-progress-config'
|
|
5
|
+
import type { GuardedCall } from '#scripts/time-runtime/time-batch-guard'
|
|
6
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
7
|
+
import { shell_segments } from './shell-segments'
|
|
8
|
+
|
|
9
|
+
// The trigger and the decision behind the `early-heartbeat` row of `delivered-rules.ts`
|
|
10
|
+
// (joshuafolkken/kit#1570).
|
|
11
|
+
//
|
|
12
|
+
// **The promise was kept and the interval was not.** `josh run:progress --mark` was called at every
|
|
13
|
+
// real report exactly as `backlogrun.md` requires, and reports still arrived 3–5 minutes apart on a
|
|
14
|
+
// 15-minute setting. The clock was never the problem: the parent armed a wait timer of its own on the
|
|
15
|
+
// turn a timer fired **and** on the turn a delegated child's completion woke it, so two timers ran at
|
|
16
|
+
// once and each produced a report the other knew nothing about. Nothing read the marked clock before
|
|
17
|
+
// writing — `run:progress` refuses its own early lines, and there was no such refusal in front of the
|
|
18
|
+
// parent's own prose.
|
|
19
|
+
//
|
|
20
|
+
// **So the refusal is put in front of the arm, not in front of the report.** A report is written in
|
|
21
|
+
// prose and no hook can see it coming; the `Bash` call that sleeps is a call, and a call can be
|
|
22
|
+
// refused — the same reading joshuafolkken/kit#1556 took for a verification behind a pipe.
|
|
23
|
+
//
|
|
24
|
+
// **An explicit ask is not a heartbeat, and it is exempt by construction rather than by exception.**
|
|
25
|
+
// What is refused here is arming a *timer*; a person asking "how is it going" arrives as a turn with
|
|
26
|
+
// no timer in front of it, and `pnpm josh run:progress --once` prints one line whatever the clock says
|
|
27
|
+
// (`run-progress-cli.ts` → `once`). There is no rule to write for it, and so no rule to get wrong.
|
|
28
|
+
|
|
29
|
+
const ARM_PREFIX = 'josh-heartbeat-arm-'
|
|
30
|
+
|
|
31
|
+
// A shell line carries several commands, and each is judged on its own — the same separators
|
|
32
|
+
// `delivered-rules.ts` cuts an Issue read on, plus the two spellings an arm actually reaches for:
|
|
33
|
+
// `sleep 1200 || true`, and `sleep 1200 &` sent to the background. `&&` is listed before `&` so the pair is
|
|
34
|
+
// never cut in half. A bare `|` is deliberately absent: a sleep is never piped into anything.
|
|
35
|
+
const SEGMENT_SEPARATOR = /&&|\|\||;|&|\n/u
|
|
36
|
+
// `sleep 600`, `sleep 10m`, `sleep 1.5`. The whole segment has to be the sleep: a `sleep` carrying
|
|
37
|
+
// arguments this does not model is not something to guess the duration of.
|
|
38
|
+
// cspell:ignore smhd
|
|
39
|
+
const SLEEP_SEGMENT = /^sleep\s+(\d+(?:\.\d+)?)([smhd]?)$/u
|
|
40
|
+
// What may stand beside the sleep without making the call something other than a wait — the marker a
|
|
41
|
+
// waking turn prints for itself. Anything that does work is not a wait timer.
|
|
42
|
+
const INERT_SEGMENT = /^(?::|true|(?:echo|printf|date)\b.*)$/u
|
|
43
|
+
// **A loop is not an arm.** `until <condition>; do sleep 30; done` ends on the condition and reports
|
|
44
|
+
// the condition; refusing it would take polling away from a run that is waiting on a thing rather
|
|
45
|
+
// than on a clock, which is the opposite of what this rule is for.
|
|
46
|
+
const LOOP_KEYWORD = /\b(?:while|until|for|do|done)\b/u
|
|
47
|
+
|
|
48
|
+
// GNU `sleep` takes a suffix and BSD `sleep` does not, so both spellings are read. A bare number is
|
|
49
|
+
// seconds, which is the one every shell agrees on.
|
|
50
|
+
const SECONDS_PER_UNIT: Readonly<Record<string, number>> = { d: 86_400, h: 3600, m: 60, s: 1 }
|
|
51
|
+
const BARE_NUMBER_SECONDS = 1
|
|
52
|
+
|
|
53
|
+
const AMOUNT_GROUP = 1
|
|
54
|
+
const UNIT_GROUP = 2
|
|
55
|
+
|
|
56
|
+
const NO_SECONDS = 0
|
|
57
|
+
|
|
58
|
+
// **The record holds the instant the armed timer expires**, and it is read through the shared refusal
|
|
59
|
+
// stamp because that shell already answers `NEVER_MS` for a record that is absent, unreadable or
|
|
60
|
+
// someone else's — which is exactly "no timer is live". Its field is named `refused_at_ms` for the
|
|
61
|
+
// refusals it was written for; a second implementation of the same read-parse-fallback path would be
|
|
62
|
+
// the clone `CLAUDE.md` prohibits, and this record is a temporary file nobody else reads.
|
|
63
|
+
const ARM_RECORD = hook_decision.create_refusal_stamp(ARM_PREFIX)
|
|
64
|
+
|
|
65
|
+
function segments_of(command: string): Array<string> {
|
|
66
|
+
return command
|
|
67
|
+
.split(SEGMENT_SEPARATOR)
|
|
68
|
+
.map((segment) => segment.trim())
|
|
69
|
+
.filter((segment) => segment !== '')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function sleep_seconds(segment: string): number | undefined {
|
|
73
|
+
const matched = SLEEP_SEGMENT.exec(segment)
|
|
74
|
+
|
|
75
|
+
if (matched === null) return undefined
|
|
76
|
+
|
|
77
|
+
const unit = matched[UNIT_GROUP] ?? ''
|
|
78
|
+
|
|
79
|
+
return Number(matched[AMOUNT_GROUP]) * (SECONDS_PER_UNIT[unit] ?? BARE_NUMBER_SECONDS)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function is_wait_or_inert(segment: string): boolean {
|
|
83
|
+
return sleep_seconds(segment) !== undefined || INERT_SEGMENT.test(segment)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether this call's whole purpose is to wait.
|
|
88
|
+
*
|
|
89
|
+
* **The shape is the discriminator, because the intent is not visible.** A call that sleeps and then
|
|
90
|
+
* does work is waiting *for* that work; a call that only sleeps is arming a timer, and the turn it
|
|
91
|
+
* wakes is the one that writes the report. Judged from the call alone, so nothing is read before the
|
|
92
|
+
* cheap answer is available.
|
|
93
|
+
*/
|
|
94
|
+
function is_wait_timer(command: string): boolean {
|
|
95
|
+
if (LOOP_KEYWORD.test(command)) return false
|
|
96
|
+
|
|
97
|
+
const segments = segments_of(command)
|
|
98
|
+
|
|
99
|
+
if (segments.every((segment) => sleep_seconds(segment) === undefined)) return false
|
|
100
|
+
|
|
101
|
+
return segments.every((segment) => is_wait_or_inert(segment))
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** How long the armed timer runs — the sum, because `sleep 60 && sleep 60` waits for two minutes. */
|
|
105
|
+
function wait_duration_ms(command: string): number {
|
|
106
|
+
const seconds = segments_of(command).reduce(
|
|
107
|
+
(total, segment) => total + (sleep_seconds(segment) ?? NO_SECONDS),
|
|
108
|
+
NO_SECONDS,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return seconds * run_progress.MS_PER_SECOND
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function is_armed(target: string, now_ms: number): boolean {
|
|
115
|
+
return now_ms < ARM_RECORD.last_ms(target)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Where the report this timer produces would land, or `undefined` when the arm must be refused.
|
|
120
|
+
*
|
|
121
|
+
* **A timer longer than the interval is refused rather than trimmed.** The watcher reports on its own
|
|
122
|
+
* every interval, so nothing legitimate waits longer than one — and the alternative, recording a
|
|
123
|
+
* shorter expiry than the timer really has, would let a second timer be armed while the first was
|
|
124
|
+
* still running, which is the defect this rule exists to prevent. Refusing instead keeps every record
|
|
125
|
+
* exact **and** bounds a record that turns out to be wrong to one interval, since no arm can reach
|
|
126
|
+
* further than that.
|
|
127
|
+
*
|
|
128
|
+
* **The rest is applied to where the report lands, not to where the arm is made.** A timer armed the
|
|
129
|
+
* moment a real report went out is legitimate exactly when it runs the full interval, and a rule that
|
|
130
|
+
* measured the arm would refuse the one arm that is always right.
|
|
131
|
+
*/
|
|
132
|
+
function landing_ms(command: string, now_ms: number, last_report_ms: number): number | undefined {
|
|
133
|
+
const interval_ms = run_progress_config.configured_interval_ms()
|
|
134
|
+
const duration_ms = wait_duration_ms(command)
|
|
135
|
+
|
|
136
|
+
if (duration_ms > interval_ms) return undefined
|
|
137
|
+
|
|
138
|
+
const lands_ms = now_ms + duration_ms
|
|
139
|
+
|
|
140
|
+
return run_progress.is_due(last_report_ms, lands_ms, interval_ms) ? lands_ms : undefined
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The two conditions the Issue names, and one that scopes the rule to the runs it was written for.
|
|
145
|
+
*
|
|
146
|
+
* **No progress record means no clock, and no clock means no rule.** An ordinary conversational
|
|
147
|
+
* session never starts the watcher and never marks, so it reads `undefined` here and nothing is
|
|
148
|
+
* refused — the scope joshuafolkken/kit#1570 set out of bounds, held by the absence of a record rather
|
|
149
|
+
* than by a second judgement about what kind of session this is.
|
|
150
|
+
*
|
|
151
|
+
* **A live timer is counted from the record this function writes, never from the processes on the
|
|
152
|
+
* machine.** A process count cannot tell a heartbeat timer from a build step that sleeps, and a timer
|
|
153
|
+
* killed with its shell would leave the count wrong for the rest of the run; a record that expires at
|
|
154
|
+
* the instant the timer fires cannot.
|
|
155
|
+
*
|
|
156
|
+
* **`can_record` is false where the call may never run.** The record is written at `PreToolUse`,
|
|
157
|
+
* before the sleep starts, and nothing runs it back — so a call another hook is about to refuse would
|
|
158
|
+
* leave a timer recorded as live that never existed, and lock out the legitimate arm that follows.
|
|
159
|
+
* The caller answers that question, because it is the one that knows what the other hooks are doing.
|
|
160
|
+
* **Refusing is unaffected**: a rule that also stayed silent there would be silent on exactly the lone
|
|
161
|
+
* `Bash` call an arm always is. What it costs is the other direction — an arm that *was* allowed and
|
|
162
|
+
* did run inside that window is not recorded, so a second one before it fires is not caught. That is
|
|
163
|
+
* the lesser of the two, because a missing record loses one detection while a wrong one blocks every
|
|
164
|
+
* arm until it expires.
|
|
165
|
+
*/
|
|
166
|
+
function decide(call: GuardedCall, run: GuardRun, can_record: boolean): boolean {
|
|
167
|
+
const last_report_ms = run_progress_clock.read_last_report_sync()
|
|
168
|
+
|
|
169
|
+
if (last_report_ms === undefined) return false
|
|
170
|
+
|
|
171
|
+
const target = ARM_RECORD.path(run.transcript)
|
|
172
|
+
|
|
173
|
+
if (is_armed(target, run.now_ms)) return true
|
|
174
|
+
|
|
175
|
+
const lands_ms = landing_ms(time_shell.bash_command(call.input), run.now_ms, last_report_ms)
|
|
176
|
+
|
|
177
|
+
if (lands_ms === undefined) return true
|
|
178
|
+
if (can_record) ARM_RECORD.record(target, lands_ms)
|
|
179
|
+
|
|
180
|
+
return false
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// The instruction in the shape a refusal can carry: what the call is about to do, what already does it
|
|
184
|
+
// properly, and the one command an explicit ask is answered with. The measurement is named because it
|
|
185
|
+
// is the half that makes the rule believable — the promise was kept and the interval was not.
|
|
186
|
+
const EARLY_HEARTBEAT_REASON =
|
|
187
|
+
'⛔ early heartbeat: this call arms a wait timer of its own, and the progress clock is not yours ' +
|
|
188
|
+
'to keep. `pnpm josh run:progress --wait` waits the interval out for you ' +
|
|
189
|
+
'(`JOSH_PROGRESS_INTERVAL_MINUTES`, or `josh.progress_interval_minutes` in `package.json`, ' +
|
|
190
|
+
'default 20 minutes), prints the five labelled lines and exits — start it in the background, relay ' +
|
|
191
|
+
'the lines it printed when it exits, and start the next one. Two timers armed at ' +
|
|
192
|
+
'once is what produced reports 3–5 minutes apart on a 15-minute setting ' +
|
|
193
|
+
'(joshuafolkken/kit#1570): a new one was armed on the turn a timer fired and again on the turn a ' +
|
|
194
|
+
"child's completion woke the run, and `--mark` recorded each report without anything refusing the " +
|
|
195
|
+
'early ones. **An explicit ask is not a heartbeat**: if the person asked for progress now, run ' +
|
|
196
|
+
'`pnpm josh run:progress --once`, which prints the five labelled lines whatever the clock says. ' +
|
|
197
|
+
'If you are ' +
|
|
198
|
+
'waiting on something rather than on a clock, wait on the thing itself — `pnpm josh followup` ' +
|
|
199
|
+
'waits for CI. The procedure is `.claude/skills/workflow-commands/backlogrun.md` → "Progress while ' +
|
|
200
|
+
'the run is quiet". **This rule fires on every early arm, not once per run**, so reissuing the ' +
|
|
201
|
+
'same sleep will be refused again.'
|
|
202
|
+
|
|
203
|
+
// **Keeping this rule is letting the watcher hold the clock** — `pnpm josh run:progress --wait` waits
|
|
204
|
+
// the interval out, and `--once` answers an explicit ask. `--mark` is neither: it records a report
|
|
205
|
+
// that has already gone out rather than waiting for the next one, and crediting it would score every
|
|
206
|
+
// run that reported at all as having kept a rule about waiting.
|
|
207
|
+
// The canonical name; both spellings match, because the alias is expanded where the command is read
|
|
208
|
+
// (joshuafolkken/kit#1789).
|
|
209
|
+
const PROGRESS_NAMES: ReadonlySet<string> = new Set(['run:progress'])
|
|
210
|
+
const WATCH_FLAG = /(?:^|\s)--(?:wait|once)(?=\s|$)/u
|
|
211
|
+
|
|
212
|
+
function is_progress_watch_segment(segment: string): boolean {
|
|
213
|
+
return shell_segments.is_josh_command(segment, PROGRESS_NAMES) && WATCH_FLAG.test(segment)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// The quoted spans are blanked first: this separator set cuts on `\n`, so a notify body carrying the
|
|
217
|
+
// watcher's own command on a line of its own would otherwise be credited as the watcher running.
|
|
218
|
+
function is_progress_watch(command: string): boolean {
|
|
219
|
+
return segments_of(time_shell.unquoted(command)).some((segment) =>
|
|
220
|
+
is_progress_watch_segment(segment),
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// **The occasion this rule governs: waiting for the run's next progress report**, in either spelling
|
|
225
|
+
// (joshuafolkken/kit#1643). The trigger fires only on the hand-armed timer, so a run that always let
|
|
226
|
+
// the watcher wait would never appear in the reading at all.
|
|
227
|
+
function waits_for_progress(command: string): boolean {
|
|
228
|
+
return is_wait_timer(command) || is_progress_watch(command)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const early_heartbeat = {
|
|
232
|
+
ARM_PREFIX,
|
|
233
|
+
EARLY_HEARTBEAT_REASON,
|
|
234
|
+
decide,
|
|
235
|
+
is_progress_watch,
|
|
236
|
+
is_wait_timer,
|
|
237
|
+
wait_duration_ms,
|
|
238
|
+
waits_for_progress,
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export { early_heartbeat }
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs'
|
|
2
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
3
|
+
import { bash_triggers } from './bash-triggers'
|
|
4
|
+
import { shell_segments } from './shell-segments'
|
|
5
|
+
|
|
6
|
+
// The trigger and the delivered text behind the `file-body` row of `delivered-rules.ts`
|
|
7
|
+
// (joshuafolkken/kit#2120). Group 3 of the three Bash-string gaps: a file's new body carried inline in
|
|
8
|
+
// a shell command, the form `CLAUDE.md` → "Never carry a file's new text inside a shell command" and
|
|
9
|
+
// `file-edits.md` forbid.
|
|
10
|
+
//
|
|
11
|
+
// **The detector existed for measurement and refused nothing.** `time-writes.ts` already knew a
|
|
12
|
+
// redirection and a heredoc write a file; nothing turned that knowledge into a refusal. This row does,
|
|
13
|
+
// and it keeps `file-edits.md`'s allow/deny table exactly: the one branch is whether the redirect target is an
|
|
14
|
+
// existing file, and a synchronous `stat` decides it — a new-file creation and a read-only heredoc stay
|
|
15
|
+
// silent, an existing-file rewrite is refused.
|
|
16
|
+
//
|
|
17
|
+
// **Three shapes, one row.** (1) A heredoc whose redirect or `tee` target already exists. (2) an
|
|
18
|
+
// interpreter reading a heredoc — or a `node -e` — whose body writes a file: the canonical `python3 -
|
|
19
|
+
// <<'PY' … open(f,'w') … PY`, which has no shell redirect to stat, is caught by its body instead. (3)
|
|
20
|
+
// an in-place `perl -0pi -e`. A read-only heredoc (`cat <<'EOF'`, a compute-only `python3 -`) writes
|
|
21
|
+
// nothing and stays silent — the enumeration's rule that a non-firing turn is a kept turn.
|
|
22
|
+
//
|
|
23
|
+
// **It fires on every occurrence** (`git-force.ts`): each inline body is paid for again, so
|
|
24
|
+
// refused-once-and-free-after would let the second rewrite through.
|
|
25
|
+
|
|
26
|
+
// A heredoc marker in any of its spellings: `<<EOF`, `<< 'EOF'`, `<<-"EOF"`. Its presence is what
|
|
27
|
+
// separates a body-carrying write from an ordinary redirect a run legitimately uses to extract text.
|
|
28
|
+
const HEREDOC = /<<-?\s*['"]?\w+/u
|
|
29
|
+
// The first physical line carries the command, its redirect and the heredoc marker; the body follows on
|
|
30
|
+
// the lines after it. The two are read separately so the redirect target is found on the command line
|
|
31
|
+
// and the write indicators are scanned in the body.
|
|
32
|
+
const LINE_BREAK = '\n'
|
|
33
|
+
|
|
34
|
+
function first_line(command: string): string {
|
|
35
|
+
const [line] = command.split(LINE_BREAK)
|
|
36
|
+
|
|
37
|
+
return line ?? ''
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function has_heredoc(command: string): boolean {
|
|
41
|
+
return HEREDOC.test(command)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// A file redirect (`> path`, `>> path`) or a `tee path`, with the target captured. A descriptor
|
|
45
|
+
// redirect (`2>&1`) and an append-to-fd are excluded — the `&` after `>` marks them.
|
|
46
|
+
const FILE_REDIRECT = /(?:^|\s)>>?\s*(?!&)("[^"]+"|'[^']+'|\S+)/u
|
|
47
|
+
const TEE_TARGET = /\btee\s+(?:-a\s+)?(?!-)("[^"]+"|'[^']+'|\S+)/u
|
|
48
|
+
const QUOTES = /^['"]|['"]$/gu
|
|
49
|
+
|
|
50
|
+
function redirect_target(line: string): string | undefined {
|
|
51
|
+
const target = FILE_REDIRECT.exec(line)?.[1] ?? TEE_TARGET.exec(line)?.[1]
|
|
52
|
+
|
|
53
|
+
return target === undefined ? undefined : target.replaceAll(QUOTES, '')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Shape 1: a heredoc write whose target already exists. The existence check is injected so the suite
|
|
57
|
+
// controls it without touching the real filesystem, the same way `lane-park.ts` injects the lane fact.
|
|
58
|
+
function writes_existing_file(command: string, has_file: (path: string) => boolean): boolean {
|
|
59
|
+
if (!has_heredoc(command)) return false
|
|
60
|
+
|
|
61
|
+
const target = redirect_target(first_line(command))
|
|
62
|
+
|
|
63
|
+
return target !== undefined && has_file(target)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The interpreters that carry a body to run rather than a region to read. `cat` / `grep` / `sed -n`
|
|
67
|
+
// are deliberately absent — a heredoc fed to them is the read-only form `file-edits.md` allows.
|
|
68
|
+
const BODY_INTERPRETERS: ReadonlySet<string> = new Set(['python', 'python3', 'ruby', 'perl', 'php'])
|
|
69
|
+
const NODE = 'node'
|
|
70
|
+
const NODE_EVAL = /(?:^|\s)(?:-e|--eval)\b/u
|
|
71
|
+
|
|
72
|
+
// A body that writes a file, in Python and Node spellings — split across two patterns so neither
|
|
73
|
+
// exceeds the regex-complexity ceiling. The named write calls: `writeFile` covers `writeFileSync`,
|
|
74
|
+
// `appendFile` covers its sync form, and `.write(` covers `.writelines(`.
|
|
75
|
+
const WRITE_CALL = /writeFile|appendFile|createWriteStream|\.write(?:lines)?\s*\(/u
|
|
76
|
+
// The mode-string and relocation forms: an `open(…, "w"|"a"|"x")`, `os.replace`, `shutil.copy` / `move`.
|
|
77
|
+
// A mode string of `r` alone (a read) matches none of these, so a compute- or read-only heredoc stays
|
|
78
|
+
// silent.
|
|
79
|
+
const WRITE_MODE = /open\s*\([^)]*['"][rbt+]*[wax]|os\.replace|shutil\.(?:copy|move)/u
|
|
80
|
+
|
|
81
|
+
function body_writes(command: string): boolean {
|
|
82
|
+
return WRITE_CALL.test(command) || WRITE_MODE.test(command)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Shape 2: an interpreter reading a heredoc, or a `node -e`, whose body writes.
|
|
86
|
+
function is_interpreter_write(segment: string, command: string): boolean {
|
|
87
|
+
const leading = time_shell.leading_word(segment)
|
|
88
|
+
|
|
89
|
+
if (BODY_INTERPRETERS.has(leading)) return has_heredoc(command) && body_writes(command)
|
|
90
|
+
|
|
91
|
+
return leading === NODE && NODE_EVAL.test(segment) && body_writes(segment)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Shape 3: an in-place `perl` edit — `-i`, `-pi`, `-0pi`. A lowercase `i` in the flag cluster is the
|
|
95
|
+
// in-place switch; the capital `-I` (an include path) is not, so the pattern keys on the lowercase.
|
|
96
|
+
const PERL = 'perl'
|
|
97
|
+
const PERL_IN_PLACE = /^-[A-Za-z0-9]*i/u
|
|
98
|
+
const WHITESPACE = /\s+/u
|
|
99
|
+
|
|
100
|
+
function is_in_place_perl(segment: string): boolean {
|
|
101
|
+
if (time_shell.leading_word(segment) !== PERL) return false
|
|
102
|
+
|
|
103
|
+
return segment.split(WHITESPACE).some((word) => PERL_IN_PLACE.test(word))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// The interpreter and perl shapes are read per first-line segment, so a heredoc marker on the same line
|
|
107
|
+
// is judged against the command that opened it rather than against a later one in a chain.
|
|
108
|
+
function has_body_interpreter(command: string): boolean {
|
|
109
|
+
return shell_segments
|
|
110
|
+
.segments_of(first_line(command))
|
|
111
|
+
.some((segment) => is_interpreter_write(segment, command) || is_in_place_perl(segment))
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function carries_a_file_body(
|
|
115
|
+
command: string,
|
|
116
|
+
has_file: (path: string) => boolean = existsSync,
|
|
117
|
+
): boolean {
|
|
118
|
+
return writes_existing_file(command, has_file) || has_body_interpreter(command)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// The instruction in the shape a refusal can carry: what the command is doing, the safe tool, and the
|
|
122
|
+
// file forms that stay allowed. The measured cost is named because it is the half that reads as
|
|
123
|
+
// surprising — the command body is billed on every later request of the run.
|
|
124
|
+
const FILE_BODY_REASON =
|
|
125
|
+
"⛔ file body in a shell command: this carries a file's new text inline — a heredoc rewriting an " +
|
|
126
|
+
'existing file, an interpreter (`python3 - <<`, `node -e`) whose body writes, or an in-place `perl ' +
|
|
127
|
+
'-0pi -e`. `CLAUDE.md` forbids it because the command body is re-read on every later request of the ' +
|
|
128
|
+
'run, so an editing script written early is billed for the rest of it (`file-edits.md` measured one ' +
|
|
129
|
+
'run at ~2m45s spent retyping existing lines). Edit a region with the Edit tool (old / new), or pass ' +
|
|
130
|
+
'a body by path (`--field body=@<path>`, `--body-file <path>`). A new-file creation (`cat > ' +
|
|
131
|
+
'<new-file> <<EOF`), a read-only heredoc (`cat <<EOF`), and a short `sed -i` stay allowed. **This ' +
|
|
132
|
+
'rule fires on every occurrence, not once per run.**'
|
|
133
|
+
|
|
134
|
+
const ROW = {
|
|
135
|
+
id: 'file-body',
|
|
136
|
+
is_trigger: bash_triggers.on_bash_command((command: string) => carries_a_file_body(command)),
|
|
137
|
+
reason: FILE_BODY_REASON,
|
|
138
|
+
decide: (): boolean => true,
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const file_body = {
|
|
142
|
+
FILE_BODY_REASON,
|
|
143
|
+
ROW,
|
|
144
|
+
carries_a_file_body,
|
|
145
|
+
is_in_place_perl,
|
|
146
|
+
is_interpreter_write,
|
|
147
|
+
writes_existing_file,
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { file_body }
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { GuardRun } from '#scripts/josh/hook-decision'
|
|
2
|
+
import { time_density_hook } from '#scripts/time-runtime/time-density-hook'
|
|
3
|
+
import { time_shell } from '#scripts/time-runtime/time-shell'
|
|
4
|
+
import { time_transcript_line, type Block } from '#scripts/time-runtime/time-transcript-line'
|
|
5
|
+
import { bash_triggers } from './bash-triggers'
|
|
6
|
+
import { tail_commands } from './tail-commands'
|
|
7
|
+
|
|
8
|
+
// The trigger and the decision behind the `filing-cap` row of `delivered-rules.ts`
|
|
9
|
+
// (joshuafolkken/kit#2119).
|
|
10
|
+
//
|
|
11
|
+
// **Automatic filing is capped at 10 Issues per run, refused at the eleventh filing.** §2d and
|
|
12
|
+
// `observation-filing.md` state the ceiling; nothing counted it, so a run that over-filed was held
|
|
13
|
+
// only by self-restraint. The input is mechanical — how many Issues this run has already filed — so
|
|
14
|
+
// it is a delivered rule rather than resident prose. **No new predicate**: the filing is
|
|
15
|
+
// `bash_triggers.is_issue_filing`, reused verbatim.
|
|
16
|
+
//
|
|
17
|
+
// **It fires on every filing past the cap, not once per run.** The subject is a recurring act — one
|
|
18
|
+
// more filing — so `DeliveredRule.decide` is the right disposition (joshuafolkken/kit#1570): refused
|
|
19
|
+
// once and free afterwards would put the enforcement back on the self-restraint that failed.
|
|
20
|
+
//
|
|
21
|
+
// **A guard-refused filing does not count.** Claude Code writes a denied call to the transcript as a
|
|
22
|
+
// `tool_use` block with an errored `tool_result`, so the WIP cap's own reissue would otherwise
|
|
23
|
+
// double-count one Issue — the same exclusion `investigation-reads.ts` makes for a refused read
|
|
24
|
+
// (joshuafolkken/kit#1764). The filing is counted only where its result carried no guard refusal.
|
|
25
|
+
|
|
26
|
+
const FILING_CAP = 10
|
|
27
|
+
// The current call is not yet on the tail, so the count read there is of filings *already* made. At
|
|
28
|
+
// this many, the call in hand is the eleventh and is refused.
|
|
29
|
+
const CAP_REACHED = FILING_CAP
|
|
30
|
+
|
|
31
|
+
interface TailFilings {
|
|
32
|
+
// The `tool_use` id of every filing on the tail.
|
|
33
|
+
filing_ids: Array<string>
|
|
34
|
+
// Each result's id mapped to the guard that refused it, and `''` for a result no guard refused.
|
|
35
|
+
refusals: Map<string, string>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function is_filing_use(block: Block): boolean {
|
|
39
|
+
if (!tail_commands.is_bash_use(block)) return false
|
|
40
|
+
|
|
41
|
+
return bash_triggers.is_issue_filing(time_shell.bash_command(block.input))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function collect_block(block: Block, found: TailFilings): void {
|
|
45
|
+
if (block.result_id !== '') found.refusals.set(block.result_id, block.refusal_guard)
|
|
46
|
+
if (is_filing_use(block)) found.filing_ids.push(block.id)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function collect_line(line: string, found: TailFilings): void {
|
|
50
|
+
const parsed = time_transcript_line.parse_line(line)
|
|
51
|
+
|
|
52
|
+
if (parsed === undefined) return
|
|
53
|
+
|
|
54
|
+
for (const block of parsed.blocks) collect_block(block, found)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function scan_tail(tail: string): TailFilings {
|
|
58
|
+
const found: TailFilings = { filing_ids: [], refusals: new Map<string, string>() }
|
|
59
|
+
|
|
60
|
+
for (const line of tail.split('\n')) collect_line(line, found)
|
|
61
|
+
|
|
62
|
+
return found
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// How many Issues the run has already filed, counting only filings no guard refused.
|
|
66
|
+
function prior_filing_count(tail: string): number {
|
|
67
|
+
const { filing_ids, refusals } = scan_tail(tail)
|
|
68
|
+
|
|
69
|
+
return filing_ids.filter((id) => (refusals.get(id) ?? '') === '').length
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// A person's prompt: a `user` line carrying no tool result. Tool results ride `user` lines too, so the
|
|
73
|
+
// absence of one is what marks the line as typed rather than returned.
|
|
74
|
+
function is_prompt_line(line: string): boolean {
|
|
75
|
+
const parsed = time_transcript_line.parse_line(line)
|
|
76
|
+
|
|
77
|
+
if (parsed?.type !== 'user') return false
|
|
78
|
+
|
|
79
|
+
return parsed.blocks.every((block) => block.result_id === '')
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The tail from the last prompt on, so a filing an earlier turn made does not answer for this one
|
|
83
|
+
// (joshuafolkken/kit#2422). A tail with no prompt on it is returned whole.
|
|
84
|
+
function current_turn(tail: string): string {
|
|
85
|
+
const lines = tail.split('\n')
|
|
86
|
+
const start = lines.findLastIndex((line) => is_prompt_line(line))
|
|
87
|
+
|
|
88
|
+
return lines.slice(Math.max(start, 0)).join('\n')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// How many Issues this turn has filed — the per-run count read over `current_turn`.
|
|
92
|
+
function turn_filing_count(tail: string): number {
|
|
93
|
+
return prior_filing_count(current_turn(tail))
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// **Fires on every filing past the cap, not once per run.** It records nothing and ignores the
|
|
97
|
+
// last-fired instant, so `decide` — which the enumeration asks unconditionally — refuses each filing
|
|
98
|
+
// while the count stands at or above the ceiling. `can_record` has nothing to protect for a row that
|
|
99
|
+
// writes no stamp.
|
|
100
|
+
function decide(_call: unknown, run: GuardRun): boolean {
|
|
101
|
+
return prior_filing_count(time_density_hook.read_tail(run.transcript)) >= CAP_REACHED
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const FILING_CAP_REASON =
|
|
105
|
+
`⛔ filing cap: this run has already filed ${String(FILING_CAP)} Issues, the per-run ceiling — on ` +
|
|
106
|
+
'reaching it, stop and report rather than filing more. Automatic filing is capped so a run cannot ' +
|
|
107
|
+
'manufacture Issues faster than they can be closed (`.claude/skills/workflow-commands/SKILL.md` → ' +
|
|
108
|
+
"§2d, `observation-filing.md`). A further Issue that genuinely must exist is a person's call, not " +
|
|
109
|
+
"this run's. **This rule fires on every filing past the cap, not once per run**, so reissuing the " +
|
|
110
|
+
'same filing will be refused again.'
|
|
111
|
+
|
|
112
|
+
// The enumeration row itself, so `delivered-rules.ts` spreads one entry rather than restating the
|
|
113
|
+
// trigger and reason it already single-sources here. It declares no `keeps`: staying under a cap is
|
|
114
|
+
// not a call, so the row is reported unmeasured rather than scored on an act that does not exist —
|
|
115
|
+
// the honest answer `investigation` gives for the same reason.
|
|
116
|
+
const ROW = {
|
|
117
|
+
id: 'filing-cap',
|
|
118
|
+
is_trigger: bash_triggers.on_bash_command(bash_triggers.is_issue_filing),
|
|
119
|
+
reason: FILING_CAP_REASON,
|
|
120
|
+
decide,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const filing_cap = {
|
|
124
|
+
FILING_CAP,
|
|
125
|
+
FILING_CAP_REASON,
|
|
126
|
+
ROW,
|
|
127
|
+
current_turn,
|
|
128
|
+
decide,
|
|
129
|
+
prior_filing_count,
|
|
130
|
+
turn_filing_count,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { filing_cap }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { repo_party } from '#scripts/discovery/repo-party'
|
|
2
|
+
import { issue_citation } from './issue-citation'
|
|
3
|
+
|
|
4
|
+
// The predicates behind the `filing-offer` row of the stop guard (joshuafolkken/kit#2422).
|
|
5
|
+
//
|
|
6
|
+
// **A first-party filing is Tier A, and an offer to file is that filing deferred to the user.**
|
|
7
|
+
// `SKILL.md` → §2i says a run that judges something worth filing files it without asking, yet a reply
|
|
8
|
+
// can still end on "it is worth filing — say so if you want it filed". The rule was resident; what was
|
|
9
|
+
// missing was anything that fired at the moment of hesitation. That moment is one `Stop` payload: a
|
|
10
|
+
// reply that offers to file, on a turn that filed nothing.
|
|
11
|
+
//
|
|
12
|
+
// **The detection is tightened the way `issue-citation.ts` is**, because a block costs a turn: only
|
|
13
|
+
// the run's own prose is read (`issue_citation.prose_lines` — no fenced example, no quote line), and
|
|
14
|
+
// only a phrase that *asks* is matched. A reply reporting a filing ("Filed …", or its Japanese past
|
|
15
|
+
// tense) carries no asking phrase, and a filing already on the transcript tail stands the row down
|
|
16
|
+
// regardless of wording.
|
|
17
|
+
//
|
|
18
|
+
// **A third-party target is never pushed toward a filing.** It is Tier C (`CLAUDE.md` → "Third-party
|
|
19
|
+
// repositories are Tier C"), so any `owner/repo` the reply names whose owner is not the session's —
|
|
20
|
+
// `repo_party.classify`, the one definition `josh repo:party` reads — keeps the row silent, and so
|
|
21
|
+
// does a session owner that cannot be read. The failure direction is a missed nudge, never a Tier C
|
|
22
|
+
// write prompted by the hook.
|
|
23
|
+
|
|
24
|
+
// The phrases that offer a filing rather than report one. Japanese first — the session language —
|
|
25
|
+
// then English. Each asks for permission, proposes, or judges the filing appropriate without making it.
|
|
26
|
+
const OFFER_PATTERNS: ReadonlyArray<RegExp> = [
|
|
27
|
+
/起票(?:して)?(?:も)?(?:よければ|よろしければ|よいですか|良いですか|よろしいですか|いいですか)/u,
|
|
28
|
+
/起票(?:しましょうか|しますか|するのが妥当|すべきだと|すべきと|を提案|をご提案)/u,
|
|
29
|
+
/Issue\s*[化に](?:しましょうか|しますか|してよければ)/iu,
|
|
30
|
+
/\b(?:shall|should)\s+I\s+(?:file|open|raise)\b/iu,
|
|
31
|
+
/\b(?:want|like)\s+me\s+to\s+(?:file|open|raise)\b/iu,
|
|
32
|
+
/\blet\s+me\s+know\s+if\s+you\s+(?:want|would\s+like)\s+(?:me\s+to\s+file|it\s+filed)\b/iu,
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
// A GitHub URL's owner, as group 1. The qualified `owner/repo#N` spelling is read by
|
|
36
|
+
// `issue_citation.bare_references` instead, whose backward prefix scan stays linear.
|
|
37
|
+
const GITHUB_URL_OWNER = /github\.com\/([\w.-]+)\//gu
|
|
38
|
+
const OWNER_SEPARATOR = '/'
|
|
39
|
+
|
|
40
|
+
function is_offer_line(line: string): boolean {
|
|
41
|
+
return OFFER_PATTERNS.some((pattern) => pattern.test(line))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Whether the run's own prose offers to file an Issue instead of filing it.
|
|
45
|
+
function offers_filing(message: string): boolean {
|
|
46
|
+
return issue_citation.prose_lines(message).some((line) => is_offer_line(line))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function url_owners(message: string): ReadonlyArray<string> {
|
|
50
|
+
return [...message.matchAll(GITHUB_URL_OWNER)].map((match) => match[1] ?? '')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The owners of the qualified `owner/repo#N` references the prose writes out.
|
|
54
|
+
function qualified_owners(message: string): ReadonlyArray<string> {
|
|
55
|
+
return issue_citation
|
|
56
|
+
.bare_references(message)
|
|
57
|
+
.filter((reference) => reference.includes(OWNER_SEPARATOR))
|
|
58
|
+
.map((reference) => reference.split(OWNER_SEPARATOR)[0] ?? '')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Every repository owner the reply names, from either spelling.
|
|
62
|
+
function mentioned_owners(message: string): ReadonlyArray<string> {
|
|
63
|
+
return [...url_owners(message), ...qualified_owners(message)]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Whether the filing the reply offers targets a first-party repository: the session owner is readable
|
|
67
|
+
// and every owner the reply names is it. A reply naming no repository offers a filing here, which is
|
|
68
|
+
// first-party by definition once the session owner is known. The whole reply is read, not the offer
|
|
69
|
+
// line alone: Japanese prose names the target on one line and asks on the next, and reading only the
|
|
70
|
+
// ask would push a Tier C filing — so a third-party link cited as context costs a missed nudge instead.
|
|
71
|
+
function is_first_party_target(message: string, session_owner: string | undefined): boolean {
|
|
72
|
+
if (session_owner === undefined) return false
|
|
73
|
+
|
|
74
|
+
return mentioned_owners(message).every(
|
|
75
|
+
(owner) => repo_party.classify(session_owner, owner) === repo_party.FIRST_PARTY,
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const filing_offer = { is_first_party_target, mentioned_owners, offers_filing }
|
|
80
|
+
|
|
81
|
+
export { filing_offer }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// A behavior-change Issue names its **firing point** — the tool call first invoked at the moment
|
|
2
|
+
// the rule it changes would break (`prompts/collaboration-workflow/issue-template.md`). This
|
|
3
|
+
// classifies that name against the rule-delivery table (joshuafolkken/kit#2212).
|
|
4
|
+
//
|
|
5
|
+
// **Why the name matters.** joshuafolkken/kit#2201 placed a correct rule whose named tool call was
|
|
6
|
+
// one call behind the one that actually broke it: the lane child's turn ended at `AskUserQuestion`,
|
|
7
|
+
// which the guard never saw. A rule delivered by a hook can only fire on a tool the hook is wired to;
|
|
8
|
+
// a firing point naming a tool outside that set is a rule no hook can enforce, and saying so at filing
|
|
9
|
+
// time is the whole point of the check.
|
|
10
|
+
|
|
11
|
+
// **The hook-deliverable set — the single source is `rule-delivery.md`'s delivery table.** The
|
|
12
|
+
// `PreToolUse` guard is wired to `Bash|Edit|Read|Write` (`scripts/hooks/pretool-guard.ts`), and the
|
|
13
|
+
// lane-child interactive-ask row triggers on `AskUserQuestion`. A firing point naming one of these can
|
|
14
|
+
// be delivered at the moment it binds; anything else cannot.
|
|
15
|
+
const HOOK_DELIVERABLE_TOOLS: ReadonlyArray<string> = [
|
|
16
|
+
'Bash',
|
|
17
|
+
'Edit',
|
|
18
|
+
'Read',
|
|
19
|
+
'Write',
|
|
20
|
+
'AskUserQuestion',
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
// **Known Claude Code tool calls that a hook cannot deliver a rule on.** They are real tools, so a
|
|
24
|
+
// firing point naming one is not a typo — it is a rule whose enforcement stays with the parent's
|
|
25
|
+
// self-restraint, the thing that failed in joshuafolkken/kit#2201. Kept apart from
|
|
26
|
+
// `HOOK_DELIVERABLE_TOOLS` so `not-delivered` (a real but undeliverable tool) reads differently from
|
|
27
|
+
// `unknown` (not a tool call name at all).
|
|
28
|
+
const KNOWN_UNDELIVERABLE_TOOLS: ReadonlyArray<string> = [
|
|
29
|
+
'Grep',
|
|
30
|
+
'Glob',
|
|
31
|
+
'WebFetch',
|
|
32
|
+
'WebSearch',
|
|
33
|
+
'TodoWrite',
|
|
34
|
+
'Task',
|
|
35
|
+
'Agent',
|
|
36
|
+
'NotebookEdit',
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
type FiringPointVerdict = 'delivered' | 'not-delivered' | 'unknown'
|
|
40
|
+
|
|
41
|
+
function includes_name(names: ReadonlyArray<string>, name: string): boolean {
|
|
42
|
+
return names.includes(name.trim())
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Where a firing point's tool name sits against the delivery table: `delivered` when a hook can carry
|
|
46
|
+
// the rule (a match), `not-delivered` when the tool is real but undeliverable (a mismatch), and
|
|
47
|
+
// `unknown` when the name is not a tool call at all (off the table).
|
|
48
|
+
function classify(name: string): FiringPointVerdict {
|
|
49
|
+
if (includes_name(HOOK_DELIVERABLE_TOOLS, name)) return 'delivered'
|
|
50
|
+
|
|
51
|
+
if (includes_name(KNOWN_UNDELIVERABLE_TOOLS, name)) return 'not-delivered'
|
|
52
|
+
|
|
53
|
+
return 'unknown'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const firing_point = {
|
|
57
|
+
HOOK_DELIVERABLE_TOOLS,
|
|
58
|
+
KNOWN_UNDELIVERABLE_TOOLS,
|
|
59
|
+
classify,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type { FiringPointVerdict }
|
|
63
|
+
export { firing_point }
|