@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,166 @@
|
|
|
1
|
+
import { closeSync, fstatSync, openSync, readSync } from 'node:fs'
|
|
2
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
import { time_density } from './time-density'
|
|
5
|
+
import { time_hook_transcript } from './time-hook-transcript'
|
|
6
|
+
|
|
7
|
+
// The disk half of the live density line (joshuafolkken/kit#1329): find the transcript, read enough
|
|
8
|
+
// of it, and remember when the line was last emitted.
|
|
9
|
+
//
|
|
10
|
+
// **It rides the hook that already runs, and adds no second one.** `.claude/settings.json` wires
|
|
11
|
+
// `pnpm josh format:edited` to `PostToolUse` for `Edit`, `Write` and `Bash`; a matcher covering every
|
|
12
|
+
// tool would put a process start in front of all ~250 calls of a run to say something on a handful of
|
|
13
|
+
// them.
|
|
14
|
+
//
|
|
15
|
+
// **`Bash` is in that list because the edit half was measured missing its audience**
|
|
16
|
+
// (joshuafolkken/kit#1337). Riding the edit hook was chosen on run #1299, where `Edit` was the
|
|
17
|
+
// most-called tool at 65 calls — and that run no longer represents how these sessions work. Of the
|
|
18
|
+
// ten most recent in this checkout, **seven called `Edit` and `Write` zero times**: they edit through
|
|
19
|
+
// `sed` instead, and they are the same sessions measured at 1.00–1.31 against the 1.50 floor, so the
|
|
20
|
+
// line was reaching none of the runs it exists for. `Bash` is 88–100% of their calls, which is why
|
|
21
|
+
// naming it alone reaches all of them and the read-only tools stay off the hook.
|
|
22
|
+
//
|
|
23
|
+
// **Nothing here may fail.** A `PostToolUse` hook runs after the edit has landed and cannot undo it,
|
|
24
|
+
// so a transcript that is missing, unreadable or not JSON at all ends as "no line", exactly as
|
|
25
|
+
// `format-edited-file.ts` treats a formatter it could not start. A transcript caught mid-append ends
|
|
26
|
+
// there too: `time_density.last_turn_calls` withholds the count when the tail's final line does not
|
|
27
|
+
// parse, because that line belongs to the turn the count is about.
|
|
28
|
+
|
|
29
|
+
// How much of the transcript's end is read. The file grows to several megabytes over a long run —
|
|
30
|
+
// 4.7 MB and 2,712 lines for the largest in this checkout — and reading all of it on every edit would
|
|
31
|
+
// put the run's own history in front of every write. A quarter of a megabyte is far more than the ten
|
|
32
|
+
// round trips the reading needs and is read in a couple of milliseconds.
|
|
33
|
+
const TAIL_BYTES = 262_144
|
|
34
|
+
const FILE_START = 0
|
|
35
|
+
// **One record per session, keyed on the transcript the payload named**, rather than per checkout the
|
|
36
|
+
// way `josh gate`'s stamp is. What is being throttled is a *run*, and a run is one session: keyed on
|
|
37
|
+
// the checkout, a session started — or cleared — within the interval of the previous one's line would
|
|
38
|
+
// inherit that silence through its opening stretch, which is the part of a run where the correction
|
|
39
|
+
// is worth the most. Keying on the transcript path also gives a delegated child its own budget, which
|
|
40
|
+
// is right for the same reason: it is a run of its own. The cost is one small record per session left
|
|
41
|
+
// in the temp directory rather than one per checkout reused — reaped with everything else there, and
|
|
42
|
+
// cheaper than the silence the shared key bought.
|
|
43
|
+
const NOTICE_PREFIX = 'josh-density-notice-'
|
|
44
|
+
// No record means nothing has been said yet, and the caller compares `now - this`. Zero makes that
|
|
45
|
+
// difference enormous, which is the answer wanted: the first eligible edit of a run emits.
|
|
46
|
+
const NEVER_MS = 0
|
|
47
|
+
|
|
48
|
+
// The two fields this reads. Claude Code hands a `PostToolUse` hook `transcript_path` beside the
|
|
49
|
+
// `tool_input` the formatter half uses, so a file is named rather than searched for — no
|
|
50
|
+
// home-directory walk.
|
|
51
|
+
//
|
|
52
|
+
// **`agent_id` is what makes a delegated unit answerable with its own transcript**
|
|
53
|
+
// (joshuafolkken/kit#1424). The path in the payload is the *parent* session's, whichever agent issued
|
|
54
|
+
// the call, so without this field the line a fork read described the parent's calls per round trip —
|
|
55
|
+
// a number about a run the reader is not in. `time-hook-transcript.ts` carries the derivation.
|
|
56
|
+
const payload_schema = z.object({
|
|
57
|
+
transcript_path: z.string().min(1).optional(),
|
|
58
|
+
// **`nullish`, not `optional`.** A payload spelling the absent agent as `null` has to read as "no
|
|
59
|
+
// fork"; rejected, it would fail `safeParse` for the whole payload and silence the line for every
|
|
60
|
+
// edit of the main line — the opposite of this module's stated failure direction.
|
|
61
|
+
agent_id: z.string().nullish(),
|
|
62
|
+
})
|
|
63
|
+
const notice_schema = z.object({ notified_at_ms: z.number() })
|
|
64
|
+
|
|
65
|
+
function parse_transcript_path(raw_payload: string): string | undefined {
|
|
66
|
+
const parsed = payload_schema.safeParse(JSON.parse(raw_payload))
|
|
67
|
+
|
|
68
|
+
if (!parsed.success || parsed.data.transcript_path === undefined) return undefined
|
|
69
|
+
|
|
70
|
+
return time_hook_transcript.transcript_of(parsed.data.transcript_path, parsed.data.agent_id)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// The last `max_bytes` of a file, as text. The leading line is usually cut mid-way, which every
|
|
74
|
+
// reader below already handles: an unparseable line is dropped rather than dated.
|
|
75
|
+
//
|
|
76
|
+
// **Only the bytes `readSync` reports are decoded.** `Buffer.alloc` zero-fills, and a short read — a
|
|
77
|
+
// real possibility on the network- and FUSE-backed home directories these transcripts can live on —
|
|
78
|
+
// would otherwise leave NUL padding on the end of the text, making the *last* line unparseable. That
|
|
79
|
+
// is the one line the turn's call count is read from.
|
|
80
|
+
function read_tail(file_path: string, max_bytes: number = TAIL_BYTES): string {
|
|
81
|
+
const descriptor = openSync(file_path, 'r')
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const { size } = fstatSync(descriptor)
|
|
85
|
+
const length = Math.min(size, max_bytes)
|
|
86
|
+
const buffer = Buffer.alloc(length)
|
|
87
|
+
const read = readSync(descriptor, buffer, FILE_START, length, size - length)
|
|
88
|
+
|
|
89
|
+
return buffer.subarray(FILE_START, read).toString('utf8')
|
|
90
|
+
} finally {
|
|
91
|
+
closeSync(descriptor)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function notice_path(transcript_path: string): string {
|
|
96
|
+
return stamp_file.stamp_path(NOTICE_PREFIX, transcript_path)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// A record that is absent, unreadable, planted by another account or not the shape written here all
|
|
100
|
+
// answer `NEVER_MS`. The failure direction is one extra line, never a silenced one.
|
|
101
|
+
function last_notice_ms(source: string): number {
|
|
102
|
+
const raw = stamp_file.read_stamp_text(source)
|
|
103
|
+
|
|
104
|
+
if (raw === undefined) return NEVER_MS
|
|
105
|
+
|
|
106
|
+
try {
|
|
107
|
+
return notice_schema.parse(JSON.parse(raw)).notified_at_ms
|
|
108
|
+
} catch {
|
|
109
|
+
return NEVER_MS
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// **Arming the throttle is best-effort, and never costs the line.** The caller prints and exits, so
|
|
114
|
+
// this write is the only place the throttle can be armed — but `write_stamp` creates exclusively, so
|
|
115
|
+
// a second hook running in the same session, a sticky temp directory, or a path another account owns
|
|
116
|
+
// each throw. Swallowed here rather than by the outer guard, which would discard the notice that had
|
|
117
|
+
// already been computed and silence exactly what `last_notice_ms` promises never to silence.
|
|
118
|
+
//
|
|
119
|
+
// **What this trades for is stated at its worst, not at its mildest.** A transient collision costs
|
|
120
|
+
// one extra line; a write that fails for the whole session — an unwritable temp directory, a path
|
|
121
|
+
// another account owns — arms nothing ever, so the interval is not stretched but gone, and the line
|
|
122
|
+
// lands on every single-call edit turn of the run. That is still the better direction: an agent that
|
|
123
|
+
// reads the same line repeatedly has been told something true, while one silenced by a temp-file
|
|
124
|
+
// permission has been told nothing at all and cannot tell.
|
|
125
|
+
function arm_throttle(target: string, now_ms: number): void {
|
|
126
|
+
try {
|
|
127
|
+
stamp_file.write_stamp(target, { notified_at_ms: now_ms })
|
|
128
|
+
} catch {
|
|
129
|
+
// Deliberately empty — see above.
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function notice_for(raw_payload: string, now_ms: number): string | undefined {
|
|
134
|
+
const transcript_path = parse_transcript_path(raw_payload)
|
|
135
|
+
|
|
136
|
+
if (transcript_path === undefined) return undefined
|
|
137
|
+
|
|
138
|
+
const reading = time_density.read_window(read_tail(transcript_path))
|
|
139
|
+
const target = notice_path(transcript_path)
|
|
140
|
+
|
|
141
|
+
if (!time_density.is_due(reading, now_ms - last_notice_ms(target))) return undefined
|
|
142
|
+
|
|
143
|
+
arm_throttle(target, now_ms)
|
|
144
|
+
|
|
145
|
+
return time_density.format_notice(reading)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// The whole call in one guard: every path above may throw on a file that moved or a payload that is
|
|
149
|
+
// not JSON, and neither is worth failing an edit over.
|
|
150
|
+
function density_notice(raw_payload: string, now_ms: number = Date.now()): string | undefined {
|
|
151
|
+
try {
|
|
152
|
+
return notice_for(raw_payload, now_ms)
|
|
153
|
+
} catch {
|
|
154
|
+
return undefined
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const time_density_hook = {
|
|
159
|
+
NOTICE_PREFIX,
|
|
160
|
+
TAIL_BYTES,
|
|
161
|
+
density_notice,
|
|
162
|
+
notice_path,
|
|
163
|
+
read_tail,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { time_density_hook }
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { cost_blocks } from '#scripts/cost-runtime/cost-blocks'
|
|
2
|
+
import { time_round_trips } from './time-round-trips'
|
|
3
|
+
import { time_spans, type TranscriptLine } from './time-spans'
|
|
4
|
+
|
|
5
|
+
// The round-trip density a run can be told **while it is still running** (joshuafolkken/kit#1329).
|
|
6
|
+
//
|
|
7
|
+
// `time-round-trips.ts` already computes the number this reads, and `josh time` already warns on it
|
|
8
|
+
// — after the run has ended. Measured on run #1299, that report changed nothing: the density stayed
|
|
9
|
+
// at 1.08 with 159 of 172 tool-issuing turns making a single call, because the norm
|
|
10
|
+
// joshuafolkken/kit#1304 shipped as prose in `CLAUDE.md` reaches a reader who has already finished.
|
|
11
|
+
// What was missing is the number arriving in time to change the next turn.
|
|
12
|
+
//
|
|
13
|
+
// **The density is `time_round_trips`, reused rather than restated.** A second calculation here
|
|
14
|
+
// would be the clone `CLAUDE.md` prohibits, and worse than an ordinary one: the live line and the
|
|
15
|
+
// end-of-run report would come to disagree about the very quantity the change is measured on.
|
|
16
|
+
//
|
|
17
|
+
// **The turn's own call count is read from the transcript, not inferred from timing.** Guessing turn
|
|
18
|
+
// boundaries from the gaps between calls would make the signal a heuristic about the thing it is
|
|
19
|
+
// trying to correct — a slow turn would look batched and a fast pair would look like one turn. Claude
|
|
20
|
+
// Code writes one line per content block with the assistant message's id on each, so the exact count
|
|
21
|
+
// is the `tool_use` blocks across the lines carrying the newest id.
|
|
22
|
+
|
|
23
|
+
// How many round trips the window must hold before it is allowed to say anything. A tail that caught
|
|
24
|
+
// three calls has no density worth quoting, and a warning drawn from one is noise the reader learns
|
|
25
|
+
// to skip — which costs more than the line saves.
|
|
26
|
+
const MIN_ROUND_TRIPS = 10
|
|
27
|
+
// At most one line per this interval, per checkout. The line lands in the run's context and stays
|
|
28
|
+
// there, so a reminder with no throttle would spend exactly the budget joshuafolkken/kit#1322 is
|
|
29
|
+
// about: 65 edits of run #1299 would have carried 65 copies of it. Five minutes is roughly 30 round
|
|
30
|
+
// trips at
|
|
31
|
+
// the 9.7s each cost in that run — often enough to reach the phase that is drifting, rare enough that
|
|
32
|
+
// a whole run pays well under a thousand tokens for the feedback.
|
|
33
|
+
const NOTICE_INTERVAL_MS = 300_000
|
|
34
|
+
// The count that means "this turn batched nothing". Zero is not that: it means the newest assistant
|
|
35
|
+
// message could not be identified, and a run is never told off on an unread transcript.
|
|
36
|
+
const ONE_CALL = 1
|
|
37
|
+
const NONE = 0
|
|
38
|
+
|
|
39
|
+
// What one look at the transcript tail found. `round_trip_count` rides along because the line quotes
|
|
40
|
+
// it — a density without the sample it was taken over cannot be judged by whoever reads it.
|
|
41
|
+
interface DensityReading {
|
|
42
|
+
density: number
|
|
43
|
+
round_trip_count: number
|
|
44
|
+
turn_calls: number
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// **A tail whose final line does not parse is not read at all.** That is the shape a transcript
|
|
48
|
+
// caught mid-append has, and the line it truncates belongs to the *newest* turn — the one the count
|
|
49
|
+
// is about. Dropping the torn line the way an unparseable leading line is dropped would read a turn
|
|
50
|
+
// of `[thinking, tool_use, tool_use]` as one call and warn a turn that batched, which is the advice
|
|
51
|
+
// inverted. Withholding is the only answer that cannot be wrong. The leading line is a different
|
|
52
|
+
// case: it belongs to a turn already long past, and no count is taken from it.
|
|
53
|
+
function has_whole_tail(text: string): boolean {
|
|
54
|
+
const last = text.split('\n').findLast((line) => line.trim() !== '')
|
|
55
|
+
|
|
56
|
+
return last !== undefined && time_spans.parse_line(last) !== undefined
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function assistant_lines(text: string): Array<TranscriptLine> {
|
|
60
|
+
return text
|
|
61
|
+
.split('\n')
|
|
62
|
+
.map((line) => time_spans.parse_line(line))
|
|
63
|
+
.filter((line): line is TranscriptLine => line?.type === time_spans.ASSISTANT_TYPE)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// The tool calls the newest assistant message issued, or `NONE` when there is no message to read.
|
|
67
|
+
//
|
|
68
|
+
// **Grouped by message id rather than taken off the last line.** One line holds one content block, so
|
|
69
|
+
// a turn that thought and then issued three calls is four lines; reading only the last of them would
|
|
70
|
+
// report every turn as having made exactly one call, which is the very verdict this line delivers.
|
|
71
|
+
// A line written without an id is left ungrouped for the same reason — every such line shares the
|
|
72
|
+
// empty string, and a bucket spanning the whole file would answer with the window's total.
|
|
73
|
+
function last_turn_calls(text: string): number {
|
|
74
|
+
if (!has_whole_tail(text)) return NONE
|
|
75
|
+
|
|
76
|
+
const lines = assistant_lines(text)
|
|
77
|
+
const message_id = lines.at(-1)?.message_id
|
|
78
|
+
|
|
79
|
+
if (message_id === undefined || message_id === time_spans.NO_MESSAGE_ID) return NONE
|
|
80
|
+
|
|
81
|
+
return lines
|
|
82
|
+
.filter((line) => line.message_id === message_id)
|
|
83
|
+
.flatMap((line) => line.blocks)
|
|
84
|
+
.filter((block) => block.type === cost_blocks.TOOL_USE_TYPE).length
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// The reading over whatever stretch of transcript was handed in. The caller passes a tail rather than
|
|
88
|
+
// the whole file, so this is deliberately a *recent* density: a run that batched for its first hour
|
|
89
|
+
// and stopped is one the line should still reach.
|
|
90
|
+
function read_window(text: string): DensityReading {
|
|
91
|
+
const { spans } = time_spans.parse_timeline(text)
|
|
92
|
+
const round_trip_count = time_round_trips.count_round_trips(spans)
|
|
93
|
+
const call_count = time_round_trips.count_calls(spans)
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
density: time_round_trips.per_round_trip(call_count, round_trip_count),
|
|
97
|
+
round_trip_count,
|
|
98
|
+
turn_calls: last_turn_calls(text),
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Four conditions, and each one withholds the line for a different reason: too little evidence, a
|
|
103
|
+
// turn that did batch, a run already clearing the floor, and one told recently enough.
|
|
104
|
+
//
|
|
105
|
+
// **The floor is `time_round_trips.is_below_floor`, not a threshold of its own.** The end-of-run
|
|
106
|
+
// warning and this line have to fire on the same runs, or a run is told it is fine while the report
|
|
107
|
+
// it gets afterwards says it was not.
|
|
108
|
+
function is_due(reading: DensityReading, since_last_ms: number): boolean {
|
|
109
|
+
if (
|
|
110
|
+
reading.round_trip_count < MIN_ROUND_TRIPS ||
|
|
111
|
+
reading.turn_calls !== ONE_CALL ||
|
|
112
|
+
!time_round_trips.is_below_floor(reading.density)
|
|
113
|
+
) {
|
|
114
|
+
return false
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return since_last_ms >= NOTICE_INTERVAL_MS
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// One line, and it says three things: what the density is, what it is being measured against, and
|
|
121
|
+
// what to do differently. The instruction is last because it is the only part worth acting on, and it
|
|
122
|
+
// names the resident rule rather than restating it — the rule is already in the run's context, and a
|
|
123
|
+
// second wording of it would be a clone that can drift.
|
|
124
|
+
function format_notice(reading: DensityReading): string {
|
|
125
|
+
const density = time_round_trips.format_density(reading.density)
|
|
126
|
+
const floor = time_round_trips.format_density(time_round_trips.CALLS_PER_ROUND_TRIP_FLOOR)
|
|
127
|
+
|
|
128
|
+
return (
|
|
129
|
+
`⚠ batching: ${density} calls per round trip over the last ${String(reading.round_trip_count)}, ` +
|
|
130
|
+
`under the ${floor} floor, and this turn issued one call. ` +
|
|
131
|
+
`Independent reads, greps, gh queries and edits go out together; the criterion is whether this ` +
|
|
132
|
+
`call's input needs another call's result, not what kind of call it is — ` +
|
|
133
|
+
`prompts/collaboration-workflow/turn-batching.md.`
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const time_density = {
|
|
138
|
+
MIN_ROUND_TRIPS,
|
|
139
|
+
NOTICE_INTERVAL_MS,
|
|
140
|
+
format_notice,
|
|
141
|
+
is_due,
|
|
142
|
+
last_turn_calls,
|
|
143
|
+
read_window,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export type { DensityReading }
|
|
147
|
+
export { time_density }
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { git_followup_stages, type FollowupStage } from '#scripts/git/git-followup-stages'
|
|
2
|
+
|
|
3
|
+
// Reading `followup`'s own stage rows back out of what it printed (joshuafolkken/kit#1445).
|
|
4
|
+
//
|
|
5
|
+
// joshuafolkken/kit#1349 gave `pnpm josh followup` a per-stage block — one
|
|
6
|
+
// `followup stage: <name> <n> s` row per lap — and declared the prefix as a constant so a reader
|
|
7
|
+
// could be added without matching a string the printer is free to reword. **There was no reader.**
|
|
8
|
+
// `josh time` sees a `followup` invocation as one Bash span, so the breakdown existed only on the
|
|
9
|
+
// screen of whoever happened to be watching that run: two runs could not be compared stage by stage,
|
|
10
|
+
// and a transcript recorded last week could not be read at all.
|
|
11
|
+
//
|
|
12
|
+
// **The prefix is imported rather than retyped**, which is the whole of what keeps this from being a
|
|
13
|
+
// guess about another module's output — the shape `time-reported-failure.ts` already uses for
|
|
14
|
+
// `status_icons`. A rename over there breaks the build here rather than silently emptying the table.
|
|
15
|
+
//
|
|
16
|
+
// **The parse is split from the aggregation, and the split is structural rather than tidy.** This
|
|
17
|
+
// module is reached from `time-transcript-line.ts`, which `time-spans.ts` imports; a single module
|
|
18
|
+
// that also aggregated would need `Span`, and `time-spans → time-transcript-line → here → time-spans`
|
|
19
|
+
// is a cycle. `time-single-check.ts` beside `time-single-checks.ts` is the same pair for the same
|
|
20
|
+
// reason, so this is that seam applied again rather than a new one.
|
|
21
|
+
//
|
|
22
|
+
// **What is read is the row, never the total.** `followup stages total:` is the sum of the rows, so
|
|
23
|
+
// parsing it would give this module a second source for one number and a way for the two to
|
|
24
|
+
// disagree; the caller sums the rows it has. The two prefixes do not collide — the total's fourteenth
|
|
25
|
+
// character is `s` where the row's is `:` — so a row scan cannot pick the total up by accident.
|
|
26
|
+
|
|
27
|
+
const LINE_SEPARATOR = '\n'
|
|
28
|
+
// **The row is read from its end, not from the gap in its middle.** The printer pads the stage name
|
|
29
|
+
// to a fixed width so the durations line up, and reading the two as whitespace-separated fields works
|
|
30
|
+
// only for as long as every name is shorter than that width — `completion-and-epic-close` is already
|
|
31
|
+
// 25 of the 26. A name that reached it would make `padEnd` a no-op, the printer would emit
|
|
32
|
+
// `some-very-long-stage12.3 s`, and a field split would take `some-very-long-stage12.3` for the name
|
|
33
|
+
// and `NaN` for the seconds — dropping the row silently, which is the going-quiet-without-failing this
|
|
34
|
+
// module's header argues against. The duration and its unit are `time_format.format_seconds`'s output,
|
|
35
|
+
// so the tail is the one part of the row whose shape the alignment cannot move.
|
|
36
|
+
const SECONDS_SUFFIX = ' s'
|
|
37
|
+
const DIGIT_OR_POINT = /[\d.]/u
|
|
38
|
+
// Written here rather than imported: `time-format.ts` keeps its own copy private, and reaching for
|
|
39
|
+
// `run-progress.ts` would pull a command module into the parse for one number.
|
|
40
|
+
const MS_PER_SECOND = 1000
|
|
41
|
+
const NO_STAGES: ReadonlyArray<FollowupStage> = []
|
|
42
|
+
|
|
43
|
+
// Leading whitespace is trimmed for the same reason `time-reported-failure.ts` trims it: the printer
|
|
44
|
+
// indents nothing, but a harness that wraps or previews a body may, and the row is still the row.
|
|
45
|
+
function stage_body(line: string): string | undefined {
|
|
46
|
+
const trimmed = line.trimStart()
|
|
47
|
+
|
|
48
|
+
if (!trimmed.startsWith(git_followup_stages.STAGE_LINE_PREFIX)) return undefined
|
|
49
|
+
|
|
50
|
+
return trimmed.slice(git_followup_stages.STAGE_LINE_PREFIX.length)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Where the duration begins: the run of digits and points closing the row. **Walked rather than
|
|
54
|
+
// matched.** A pattern describing the name as well would need a lazy or greedy prefix beside the
|
|
55
|
+
// number, which backtracks — `sonarjs/super-linear-regex` refuses it, and it is right to: this is one
|
|
56
|
+
// pass over a row whose length nothing bounds.
|
|
57
|
+
function digits_start(head: string): number {
|
|
58
|
+
let index = head.length
|
|
59
|
+
|
|
60
|
+
while (index > 0 && DIGIT_OR_POINT.test(head.charAt(index - 1))) index -= 1
|
|
61
|
+
|
|
62
|
+
return index
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// **An empty run is not a zero-second stage**, and it is tested for rather than folded into the
|
|
66
|
+
// number: `Number('')` is `0`, so a row that ended in the unit with no digits in front of it would
|
|
67
|
+
// otherwise be reported as a lap that ran and took no time — which is the reading this module exists
|
|
68
|
+
// to keep the table out of.
|
|
69
|
+
function is_duration(digits: string): boolean {
|
|
70
|
+
return digits !== '' && Number.isFinite(Number(digits))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// A row that does not end in a duration is dropped rather than counted as zero — a body the harness
|
|
74
|
+
// truncated is the common cause, and a zero there would read as a stage that ran and took no time.
|
|
75
|
+
function to_stage(body: string): FollowupStage | undefined {
|
|
76
|
+
const text = body.trimEnd()
|
|
77
|
+
|
|
78
|
+
if (!text.endsWith(SECONDS_SUFFIX)) return undefined
|
|
79
|
+
|
|
80
|
+
const head = text.slice(0, -SECONDS_SUFFIX.length)
|
|
81
|
+
const start = digits_start(head)
|
|
82
|
+
const name = head.slice(0, start).trim()
|
|
83
|
+
const digits = head.slice(start)
|
|
84
|
+
|
|
85
|
+
if (name === '' || !is_duration(digits)) return undefined
|
|
86
|
+
|
|
87
|
+
return { name, duration_ms: Number(digits) * MS_PER_SECOND }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// **The `includes` guard is the whole of what keeps this cheap.** `to_block` runs it over every tool
|
|
91
|
+
// result of every session, and almost none of them are a `followup` run: a scan that found nothing
|
|
92
|
+
// would still have allocated a line array per body. A substring test allocates nothing, and the split
|
|
93
|
+
// below is paid only by the handful of bodies that actually carry the block.
|
|
94
|
+
function read_stages(text: string): ReadonlyArray<FollowupStage> {
|
|
95
|
+
if (!text.includes(git_followup_stages.STAGE_LINE_PREFIX)) return NO_STAGES
|
|
96
|
+
|
|
97
|
+
return text
|
|
98
|
+
.split(LINE_SEPARATOR)
|
|
99
|
+
.map((line) => stage_body(line))
|
|
100
|
+
.filter((body): body is string => body !== undefined)
|
|
101
|
+
.map((body) => to_stage(body))
|
|
102
|
+
.filter((stage): stage is FollowupStage => stage !== undefined)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const time_followup_stage = { NO_STAGES, read_stages }
|
|
106
|
+
|
|
107
|
+
export { time_followup_stage }
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// The column and number formatting every timing report is laid out through (joshuafolkken/kit#1309).
|
|
2
|
+
//
|
|
3
|
+
// It was `time-report.ts`'s until three renderers shared it: the run scope's own tables, the epic
|
|
4
|
+
// scope's child rows, and the failure block `time-failures.ts` prints. Two of those already reached
|
|
5
|
+
// in through the `time_report` namespace for the widths, which is what made the split the honest
|
|
6
|
+
// place to cut — a second set of column rules beside a second renderer is the clone `CLAUDE.md`
|
|
7
|
+
// prohibits, in the one place where a drift would make two tables of the same report disagree about
|
|
8
|
+
// where the numeric column starts.
|
|
9
|
+
//
|
|
10
|
+
// **It holds no timing knowledge at all** — no spans, no categories, no phases. That is what keeps
|
|
11
|
+
// the dependency one-way: `time-report.ts` and `time-failures.ts` both import this, and nothing here
|
|
12
|
+
// imports either of them. **The words two blocks must spell identically are the exception**, and they
|
|
13
|
+
// are here for the reason `NO_CALLS` is: a label printed by two renderers, one of which cannot import
|
|
14
|
+
// the other, has to be written once or the two reports come to disagree about what a row is called.
|
|
15
|
+
|
|
16
|
+
const MS_PER_MINUTE = 60_000
|
|
17
|
+
const MS_PER_SECOND = 1000
|
|
18
|
+
const MINUTE_DECIMALS = 1
|
|
19
|
+
const SECOND_DECIMALS = 1
|
|
20
|
+
const PERCENT_SCALE = 100
|
|
21
|
+
const PERCENT_DECIMALS = 1
|
|
22
|
+
const LABEL_WIDTH = 24
|
|
23
|
+
// Wide enough for a three-digit run (`335.4 min`), so a long session's rows stay in column with a
|
|
24
|
+
// short one's rather than pushing the share out by a character.
|
|
25
|
+
const MINUTES_WIDTH = 9
|
|
26
|
+
// The answer a table gives where the half it sums was never read at all, kept apart from the phase
|
|
27
|
+
// table's `not detected` because the two ask different questions: a phase is about a marker, this is
|
|
28
|
+
// about whether anything was read to measure.
|
|
29
|
+
const NOT_MEASURED = 'not measured'
|
|
30
|
+
// What a row says instead of a rate when there was no round trip to divide by. It sits here rather
|
|
31
|
+
// than in `time-report.ts` because two blocks print it — the round-trip price and the bundling block —
|
|
32
|
+
// and `time-bundles.ts` cannot import `time-report.ts`, which imports it (joshuafolkken/kit#1344).
|
|
33
|
+
const NO_CALLS = 'no tool call to divide'
|
|
34
|
+
// The word both the CI-cycle block and the gate-runtime block put in front of their naked-seconds
|
|
35
|
+
// figure (joshuafolkken/kit#1812). Two renderers of the same report, and `time-cycles.ts` cannot
|
|
36
|
+
// import `time-gate-runs.ts` nor the reverse, so it is written once here — the rule this file's header
|
|
37
|
+
// states, and the reason `NO_CALLS` already sits beside it.
|
|
38
|
+
const NAKED_PREFIX = 'naked '
|
|
39
|
+
// The category labels, shared with the epic scope's table and with the round-trip block's price row
|
|
40
|
+
// rather than spelled out in each. The tables answer the same question at three scales, so a label
|
|
41
|
+
// renamed in one and not the others is a report that disagrees with itself — which is the defect
|
|
42
|
+
// joshuafolkken/kit#1295 was filed for. They moved here from `time-report.ts` when the price row
|
|
43
|
+
// became a third printer and its block a module that cannot import that file
|
|
44
|
+
// (joshuafolkken/kit#1385).
|
|
45
|
+
const MODEL_LABEL = 'model wait'
|
|
46
|
+
const TOOL_LABEL = 'tool execution'
|
|
47
|
+
const HUMAN_LABEL = 'human wait'
|
|
48
|
+
const CI_LABEL = 'CI wait'
|
|
49
|
+
// How many rows of a table any of these reports prints. Capped, because a long run touches thirty-odd
|
|
50
|
+
// distinct leading commands and a table that long is read by nobody. `--json` carries every row the
|
|
51
|
+
// report holds, so the display cap costs a caller nothing.
|
|
52
|
+
//
|
|
53
|
+
// **It moved here when the segment and per-invocation tables became the fourth and fifth renderers to
|
|
54
|
+
// need it** (joshuafolkken/kit#1311). Those two cannot import `time-report.ts`, which imports them —
|
|
55
|
+
// and a second cap beside a second renderer is exactly the drift this file was split out to prevent.
|
|
56
|
+
const MAX_ROWS = 15
|
|
57
|
+
// What separates the facts inside one row's third column — a check's conclusion from its outcome
|
|
58
|
+
// note, a distribution's range from its sample count. Written once so two renderers of the same
|
|
59
|
+
// report cannot come to punctuate their suffixes differently (joshuafolkken/kit#1312).
|
|
60
|
+
const SUFFIX_SEPARATOR = ' · '
|
|
61
|
+
// What joins the two ends of an aggregated row's range, and the unit the sample behind it is counted
|
|
62
|
+
// in. They sit here rather than beside one renderer because two of them print a spread now — the
|
|
63
|
+
// duration tables of `--last` and the turn-count table both scopes share — and a private copy beside
|
|
64
|
+
// the second is how one report would come to punctuate its ranges two ways
|
|
65
|
+
// (joshuafolkken/kit#1763).
|
|
66
|
+
const RANGE_SEPARATOR = ' – '
|
|
67
|
+
const RUN_UNIT = 'run(s)'
|
|
68
|
+
// The `HH:MM:SS` slice of an ISO instant, and what joins two of them into a window. UTC rather than
|
|
69
|
+
// local time, because the report's own `started_at` / `ended_at` already are — a table in one zone
|
|
70
|
+
// beside a header in another is a report that cannot be read against itself.
|
|
71
|
+
//
|
|
72
|
+
// **They moved here from `time-segments.ts` when the model-gap block became a second renderer of a
|
|
73
|
+
// clock window** (joshuafolkken/kit#1386). A private copy beside the second block is the clone
|
|
74
|
+
// `CLAUDE.md` prohibits, in the one place a drift would make two tables of the same report disagree
|
|
75
|
+
// about which hour a stretch sat in.
|
|
76
|
+
const CLOCK_START = 11
|
|
77
|
+
const CLOCK_END = 19
|
|
78
|
+
const WINDOW_ARROW = ' → '
|
|
79
|
+
|
|
80
|
+
// **The parenthetical says "this report" rather than "them all"** (joshuafolkken/kit#1301): since
|
|
81
|
+
// `--top` can cut the record itself before either rendering, a promise that `--json` carries every row
|
|
82
|
+
// *there ever was* would be false beside a `--top` above this display cap — and the report would then
|
|
83
|
+
// contradict its own truncation note. What was cut from the record, if anything, is said in `notes`;
|
|
84
|
+
// what is cut from a table is said here.
|
|
85
|
+
function overflow_line(row_count: number): Array<string> {
|
|
86
|
+
if (row_count <= MAX_ROWS) return []
|
|
87
|
+
|
|
88
|
+
return [
|
|
89
|
+
` … and ${String(row_count - MAX_ROWS)} more (--json carries every row this report holds)`,
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function format_minutes(duration_ms: number): string {
|
|
94
|
+
return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Seconds rather than minutes for a per-turn figure: one turn is tens of seconds, and `0.1 min` is
|
|
98
|
+
// too coarse to show the rise across a batch that this scale exists to make visible.
|
|
99
|
+
function format_seconds(duration_ms: number): string {
|
|
100
|
+
return `${(duration_ms / MS_PER_SECOND).toFixed(SECOND_DECIMALS)} s`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function format_share(part: number, whole: number): string {
|
|
104
|
+
if (whole === 0) return 'n/a'
|
|
105
|
+
|
|
106
|
+
return `${((part / whole) * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// A dollar figure, to the caller's own precision. Two cost blocks print money now — the phase costs
|
|
110
|
+
// and the per-subagent context-construction costs — and each rounds to a different place (a run total
|
|
111
|
+
// to the cent, a per-round-trip figure finer), so the decimals are the caller's and only the `$` and
|
|
112
|
+
// the `toFixed` are shared. It sits here beside the other number formatters rather than in one block,
|
|
113
|
+
// for the reason `format_minutes` does: a second copy beside the second renderer is how two cost rows
|
|
114
|
+
// of one report come to punctuate a dollar amount two ways (joshuafolkken/kit#1606).
|
|
115
|
+
function usd(amount: number, decimals: number): string {
|
|
116
|
+
return `$${amount.toFixed(decimals)}`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// The one place the three columns are laid out, so a row carrying words instead of a duration lines
|
|
120
|
+
// up with the rows that carry one rather than overrunning the numeric column.
|
|
121
|
+
function format_columns(label: string, minutes: string, suffix: string): string {
|
|
122
|
+
return ` ${label.padEnd(LABEL_WIDTH)}${minutes.padStart(MINUTES_WIDTH)} ${suffix}`
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function format_row(label: string, duration_ms: number, suffix: string): string {
|
|
126
|
+
return format_columns(label, format_minutes(duration_ms), suffix)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// **A share nobody read says so rather than totalling zero.** The duration column is left empty
|
|
130
|
+
// because there is no duration — not a short one — which is the same shape an undetected phase and a
|
|
131
|
+
// child that never ran already print.
|
|
132
|
+
function unmeasured_row(label: string): string {
|
|
133
|
+
return format_columns(label, '', NOT_MEASURED)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// **The ends are handed over already formatted**, so one aggregated table can spell its range in
|
|
137
|
+
// minutes and another in turns while both are punctuated identically. The sample count rides at the
|
|
138
|
+
// end because it is the qualifier: two rows with the same spread are not the same evidence when one
|
|
139
|
+
// was read from nine runs and the other from two.
|
|
140
|
+
function format_spread(min: string, max: string, sample_count: number): string {
|
|
141
|
+
const range = `${min}${RANGE_SEPARATOR}${max}`
|
|
142
|
+
|
|
143
|
+
return `${range}${SUFFIX_SEPARATOR}${String(sample_count)} ${RUN_UNIT}`
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function format_clock(timestamp_ms: number): string {
|
|
147
|
+
return new Date(timestamp_ms).toISOString().slice(CLOCK_START, CLOCK_END)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function format_window(started_ms: number, ended_ms: number): string {
|
|
151
|
+
return `${format_clock(started_ms)}${WINDOW_ARROW}${format_clock(ended_ms)}`
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The indent a report's notes sit under, beneath its heading. Written once because three renderers
|
|
155
|
+
// print them — the run scope, the epic scope and the distribution — and a fourth copy is how two
|
|
156
|
+
// tables of one command would come to indent the same sentence differently (joshuafolkken/kit#1312).
|
|
157
|
+
function note_lines(notes: ReadonlyArray<string>): Array<string> {
|
|
158
|
+
return notes.map((note) => ` ${note}`)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const time_format = {
|
|
162
|
+
MAX_ROWS,
|
|
163
|
+
NO_CALLS,
|
|
164
|
+
NAKED_PREFIX,
|
|
165
|
+
SUFFIX_SEPARATOR,
|
|
166
|
+
NOT_MEASURED,
|
|
167
|
+
MODEL_LABEL,
|
|
168
|
+
TOOL_LABEL,
|
|
169
|
+
HUMAN_LABEL,
|
|
170
|
+
CI_LABEL,
|
|
171
|
+
overflow_line,
|
|
172
|
+
format_minutes,
|
|
173
|
+
format_seconds,
|
|
174
|
+
format_share,
|
|
175
|
+
usd,
|
|
176
|
+
format_columns,
|
|
177
|
+
format_row,
|
|
178
|
+
format_spread,
|
|
179
|
+
// `format_clock` stays private: `format_window` is its only caller, and a namespace that offers
|
|
180
|
+
// both invites a second renderer to join the two with its own arrow.
|
|
181
|
+
format_window,
|
|
182
|
+
unmeasured_row,
|
|
183
|
+
note_lines,
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export { time_format }
|