@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,318 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { parseArgs } from 'node:util'
|
|
4
|
+
import { agent_role_profile, type AgentProvider } from '#scripts/agent/agent-role-profile'
|
|
5
|
+
import { codex_usage } from './codex-usage'
|
|
6
|
+
import { CONTEXT_CUT_THRESHOLD } from './context-cut-threshold'
|
|
7
|
+
import { cost_corpus } from './cost-corpus'
|
|
8
|
+
import { cost_transcript, type SessionUsage } from './cost-transcript'
|
|
9
|
+
import { cost_usage } from './cost-usage'
|
|
10
|
+
import { cost_verdict, type OverMeasurement } from './cost-verdict'
|
|
11
|
+
import { own_session } from './own-session'
|
|
12
|
+
import { transcript_cwd } from './transcript-cwd'
|
|
13
|
+
|
|
14
|
+
// `josh cost` — what the next turn of a run will cost, read from the active provider's own session
|
|
15
|
+
// usage (joshuafolkken/kit#962).
|
|
16
|
+
//
|
|
17
|
+
// Since #2016 this is the `--over` hand-off verdict alone. The readerless report scopes
|
|
18
|
+
// (`--session` / `--issue` / `--all` / `--run` / `--json`) and the `--cap` counterfactual were
|
|
19
|
+
// retired because no rule or decision read them — leaving only the entry judgment `fullrun` /
|
|
20
|
+
// `backlogrun` / `halfrun` / `pre-gate-cut` ask, and the `josh time` run-timing report keeps the
|
|
21
|
+
// hand-off aggregates used to compare the shared context-cut threshold.
|
|
22
|
+
|
|
23
|
+
const ARGV_OFFSET = 2
|
|
24
|
+
const FAILURE_EXIT_CODE = 1
|
|
25
|
+
const USAGE = 'Usage: josh cost (--cut | --over <tokens-per-request>) [--path <dir>]'
|
|
26
|
+
// The read-only verdict's third answer, beside `cost_verdict`'s over/under: a session that cannot be
|
|
27
|
+
// priced at all. Kept here rather than in `cost_verdict`, which only ever decides over vs under.
|
|
28
|
+
const UNMEASURABLE_VERDICT = 'unmeasurable'
|
|
29
|
+
|
|
30
|
+
type CostVerdict = ReturnType<typeof cost_verdict.classify> | typeof UNMEASURABLE_VERDICT
|
|
31
|
+
|
|
32
|
+
interface Options {
|
|
33
|
+
over?: number
|
|
34
|
+
// The target project whose transcripts to read, or absent for this process's own working
|
|
35
|
+
// directory (joshuafolkken/kit#1987). From the kit checkout, `--path <dir>` reads another
|
|
36
|
+
// project's cost.
|
|
37
|
+
path?: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface RawValues {
|
|
41
|
+
cut?: boolean | undefined
|
|
42
|
+
over?: string | undefined
|
|
43
|
+
path?: string | undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
type Environment = Readonly<Record<string, string | undefined>>
|
|
47
|
+
|
|
48
|
+
interface RunContext {
|
|
49
|
+
over: number
|
|
50
|
+
path: string | undefined
|
|
51
|
+
provider: AgentProvider
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// A threshold of 0 is a legitimate limit — "hand off after any request at all" — so it is accepted.
|
|
55
|
+
// Negative is refused: there is no such thing as a negative cost. An empty value is refused too, so
|
|
56
|
+
// `--over=` does not arrive as "hand off after any request" and stop an unattended run after its
|
|
57
|
+
// first child.
|
|
58
|
+
function to_threshold(raw: string | undefined): number | undefined {
|
|
59
|
+
if (raw === undefined) return undefined
|
|
60
|
+
if (raw.trim() === '') return undefined
|
|
61
|
+
|
|
62
|
+
const parsed = Number(raw)
|
|
63
|
+
|
|
64
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : undefined
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// A flag that was given but did not parse is a refusal, not an absent flag: `--over abc` must not
|
|
68
|
+
// silently become "no threshold".
|
|
69
|
+
function is_unparsed(raw: string | undefined, parsed: number | undefined): boolean {
|
|
70
|
+
return parsed === undefined && raw !== undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function selected_threshold(values: RawValues): number | undefined {
|
|
74
|
+
if (values.cut === true) return CONTEXT_CUT_THRESHOLD
|
|
75
|
+
|
|
76
|
+
return to_threshold(values.over)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function threshold_option(over: number | undefined): Pick<Options, 'over'> {
|
|
80
|
+
return over === undefined ? {} : { over }
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function path_option(path: string | undefined): Pick<Options, 'path'> {
|
|
84
|
+
return path === undefined ? {} : { path }
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// `exactOptionalPropertyTypes` rejects `{ over: undefined }`, so an absent flag contributes no key
|
|
88
|
+
// at all rather than an undefined one.
|
|
89
|
+
function to_options(values: RawValues): Options | undefined {
|
|
90
|
+
if (values.cut === true && values.over !== undefined) return undefined
|
|
91
|
+
|
|
92
|
+
const over = selected_threshold(values)
|
|
93
|
+
|
|
94
|
+
if (is_unparsed(values.over, over)) return undefined
|
|
95
|
+
|
|
96
|
+
return { ...threshold_option(over), ...path_option(values.path) }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const PARSE_ARGS_OPTIONS = {
|
|
100
|
+
cut: { type: 'boolean' },
|
|
101
|
+
over: { type: 'string' },
|
|
102
|
+
path: { type: 'string' },
|
|
103
|
+
} as const
|
|
104
|
+
|
|
105
|
+
function parse_options(argv: ReadonlyArray<string>): Options | undefined {
|
|
106
|
+
try {
|
|
107
|
+
const { values } = parseArgs({ args: [...argv], options: PARSE_ARGS_OPTIONS, strict: true })
|
|
108
|
+
|
|
109
|
+
return to_options(values)
|
|
110
|
+
} catch {
|
|
111
|
+
return undefined
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// An empty corpus is reported, never priced at zero. "No transcript was found" and "this run was
|
|
116
|
+
// free" are different answers, and only one of them is ever true. `session_id` names the session the
|
|
117
|
+
// environment pointed at when its transcript is the one absent (joshuafolkken/kit#2403), so the
|
|
118
|
+
// message says "No transcript named <id>" rather than the whole-corpus "No transcripts found". The
|
|
119
|
+
// wording is `cost_transcript`'s, so `josh time` says the same thing about the same directory.
|
|
120
|
+
function report_empty(cwd: string, session_id: string | undefined): number {
|
|
121
|
+
const searched = cost_transcript.searched_directories(cost_transcript.transcript_directories(cwd))
|
|
122
|
+
|
|
123
|
+
for (const line of cost_transcript.missing_message(searched, session_id)) console.error(line)
|
|
124
|
+
|
|
125
|
+
return FAILURE_EXIT_CODE
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function provider_of(environment: Environment): AgentProvider | undefined {
|
|
129
|
+
const resolved = agent_role_profile.resolve_provider(environment)
|
|
130
|
+
|
|
131
|
+
return resolved.kind === 'provider' ? resolved.provider : undefined
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// The own-session measurement, and — when there is none — which of the two "nothing to measure"
|
|
135
|
+
// answers it is (joshuafolkken/kit#2403). `absent`: the environment named a session whose transcript
|
|
136
|
+
// is not in this corpus, reported by that name and never measured as another session's newest file.
|
|
137
|
+
// `empty`: no transcript at all. `measured` still carries a session that exists but billed nothing,
|
|
138
|
+
// which `report_over` reports as "no requests" — a third, distinct answer.
|
|
139
|
+
type OwnMeasurement =
|
|
140
|
+
| { kind: 'measured'; measurement: OverMeasurement }
|
|
141
|
+
| { kind: 'absent'; session_id: string }
|
|
142
|
+
| { kind: 'empty' }
|
|
143
|
+
|
|
144
|
+
function measurement_of(session: SessionUsage): OverMeasurement {
|
|
145
|
+
return {
|
|
146
|
+
billed_input_per_request: session.records.map((record) =>
|
|
147
|
+
cost_usage.billed_input(record.totals),
|
|
148
|
+
),
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function anthropic_own(target: string, environment: Environment): OwnMeasurement {
|
|
153
|
+
const corpus = cost_corpus.load_corpus(target)
|
|
154
|
+
const selection = own_session.select_own_session(corpus.files, environment)
|
|
155
|
+
if (selection.kind === 'absent') return { kind: 'absent', session_id: selection.session_id }
|
|
156
|
+
|
|
157
|
+
const session = corpus.sessions[selection.index]
|
|
158
|
+
if (session === undefined) return { kind: 'empty' }
|
|
159
|
+
|
|
160
|
+
return { kind: 'measured', measurement: measurement_of(session) }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function anthropic_measurement(
|
|
164
|
+
target: string,
|
|
165
|
+
environment: Environment,
|
|
166
|
+
): OverMeasurement | undefined {
|
|
167
|
+
const own = anthropic_own(target, environment)
|
|
168
|
+
|
|
169
|
+
return own.kind === 'measured' ? own.measurement : undefined
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function same_openai_project(target: string, cwd: string): boolean {
|
|
173
|
+
return cost_transcript.session_cwd(target) === cost_transcript.session_cwd(cwd)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function reject_openai_cross_project(context: RunContext, target: string, cwd: string): boolean {
|
|
177
|
+
if (
|
|
178
|
+
context.provider !== 'openai' ||
|
|
179
|
+
context.path === undefined ||
|
|
180
|
+
same_openai_project(target, cwd)
|
|
181
|
+
) {
|
|
182
|
+
return false
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
console.error(
|
|
186
|
+
'OpenAI --path cannot select a thread from another project; run josh cost in that project.',
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
return true
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// The active provider's own-session measurement, read the same way for `--over` and for the
|
|
193
|
+
// read-only `session_verdict` below, so the two never drift on which session they price.
|
|
194
|
+
function measure(
|
|
195
|
+
target: string,
|
|
196
|
+
provider: AgentProvider,
|
|
197
|
+
environment: Environment,
|
|
198
|
+
): OverMeasurement | undefined {
|
|
199
|
+
return provider === 'openai'
|
|
200
|
+
? codex_usage.measurement(target, cost_transcript.home_directory(), environment)
|
|
201
|
+
: anthropic_measurement(target, environment)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// `--over` for the anthropic provider: measured → the verdict; `absent` → the named session's
|
|
205
|
+
// missing message; `empty` → the whole-corpus missing message. A measured session that billed
|
|
206
|
+
// nothing falls to `report_over`'s "no requests", which keeps a 0-request transcript distinct from a
|
|
207
|
+
// transcript that is not there at all (joshuafolkken/kit#2403).
|
|
208
|
+
function run_over_anthropic(own: OwnMeasurement, target: string, limit: number): number {
|
|
209
|
+
if (own.kind === 'measured') return cost_verdict.report_over(own.measurement, limit)
|
|
210
|
+
|
|
211
|
+
return report_empty(target, own.kind === 'absent' ? own.session_id : undefined)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function run_over_codex(target: string, limit: number, environment: Environment): number {
|
|
215
|
+
const measurement = measure(target, 'openai', environment)
|
|
216
|
+
if (measurement !== undefined) return cost_verdict.report_over(measurement, limit)
|
|
217
|
+
|
|
218
|
+
console.error(`No Codex usage found for the current OpenAI thread under ${target}.`)
|
|
219
|
+
|
|
220
|
+
return FAILURE_EXIT_CODE
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// `--over`: what the next turn of this session will cost, read from the session's own transcript
|
|
224
|
+
// alone — identified by id, not by mtime (joshuafolkken/kit#2403).
|
|
225
|
+
function run_over(
|
|
226
|
+
target: string,
|
|
227
|
+
limit: number,
|
|
228
|
+
provider: AgentProvider,
|
|
229
|
+
environment: Environment,
|
|
230
|
+
): number {
|
|
231
|
+
if (provider === 'anthropic') {
|
|
232
|
+
return run_over_anthropic(anthropic_own(target, environment), target, limit)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return run_over_codex(target, limit, environment)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// A measurement priced against the shared cut threshold, or `unmeasurable` for the empty session a
|
|
239
|
+
// `report_over` would refuse. Split from `session_verdict` so neither carries more than one decision.
|
|
240
|
+
function verdict_of(measurement: OverMeasurement | undefined): CostVerdict {
|
|
241
|
+
if (measurement === undefined || measurement.billed_input_per_request.length === 0) {
|
|
242
|
+
return UNMEASURABLE_VERDICT
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return cost_verdict.classify(measurement, CONTEXT_CUT_THRESHOLD)
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// The `--cut` verdict as a value, printing nothing (joshuafolkken/kit#2165). `run:status` bundles
|
|
249
|
+
// this beside the issue state and the carry record, so it needs the token rather than the exit code
|
|
250
|
+
// `run` returns. `unmeasurable` is the read-only counterpart of `report_empty` / the empty-session
|
|
251
|
+
// error: a session with no provider, no transcript of its own, or no request cannot be priced, and
|
|
252
|
+
// saying so is not the same as `under`.
|
|
253
|
+
function session_verdict(
|
|
254
|
+
cwd: string = process.cwd(),
|
|
255
|
+
environment: Environment = process.env,
|
|
256
|
+
): CostVerdict {
|
|
257
|
+
const provider = provider_of(environment)
|
|
258
|
+
if (provider === undefined) return UNMEASURABLE_VERDICT
|
|
259
|
+
|
|
260
|
+
return verdict_of(measure(cwd, provider, environment))
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function run_context(
|
|
264
|
+
argv: ReadonlyArray<string>,
|
|
265
|
+
environment: Environment,
|
|
266
|
+
): RunContext | undefined {
|
|
267
|
+
const options = parse_options(argv)
|
|
268
|
+
if (options?.over === undefined) return undefined
|
|
269
|
+
const provider = provider_of(environment)
|
|
270
|
+
if (provider === undefined) return undefined
|
|
271
|
+
|
|
272
|
+
return { over: options.over, path: options.path, provider }
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// This process's own working directory, kept as-is: from a lane the transcript search covers the
|
|
276
|
+
// lane's own slug alone (joshuafolkken/kit#2236), so pre-rewriting the cwd to the main checkout here
|
|
277
|
+
// would drop the lane's own slug and hide a dispatched child's transcript (joshuafolkken/kit#1749).
|
|
278
|
+
// `time-cli.ts` gives the same reason.
|
|
279
|
+
function run(
|
|
280
|
+
argv: ReadonlyArray<string>,
|
|
281
|
+
cwd: string = process.cwd(),
|
|
282
|
+
environment: Environment = process.env,
|
|
283
|
+
): number {
|
|
284
|
+
const context = run_context(argv, environment)
|
|
285
|
+
|
|
286
|
+
if (context === undefined) {
|
|
287
|
+
console.error(USAGE)
|
|
288
|
+
|
|
289
|
+
return FAILURE_EXIT_CODE
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// `--path <dir>` reads the target project instead of the process cwd (joshuafolkken/kit#1987).
|
|
293
|
+
const target = transcript_cwd.resolve(context.path, cwd)
|
|
294
|
+
if (reject_openai_cross_project(context, target, cwd)) return FAILURE_EXIT_CODE
|
|
295
|
+
|
|
296
|
+
return run_over(target, context.over, context.provider, environment)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function main(argv: ReadonlyArray<string>): void {
|
|
300
|
+
process.exitCode = run(argv)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const cost_cli = {
|
|
304
|
+
UNMEASURABLE_VERDICT,
|
|
305
|
+
USAGE,
|
|
306
|
+
parse_options,
|
|
307
|
+
to_threshold,
|
|
308
|
+
load_corpus: cost_corpus.load_corpus,
|
|
309
|
+
attributed: cost_corpus.attributed,
|
|
310
|
+
run,
|
|
311
|
+
session_verdict,
|
|
312
|
+
main,
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
316
|
+
|
|
317
|
+
export type { CostVerdict, Options }
|
|
318
|
+
export { cost_cli }
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { cost_attribute } from './cost-attribute'
|
|
2
|
+
import { cost_transcript, type SessionFile, type SessionUsage } from './cost-transcript'
|
|
3
|
+
import type { UsageRecord } from './cost-usage'
|
|
4
|
+
|
|
5
|
+
// The counters a corpus read could not account for, kept beside the sessions it read. Defined here
|
|
6
|
+
// because `accumulate_missing` is the only producer left once the readerless report modules that
|
|
7
|
+
// once rendered it were retired (#2016).
|
|
8
|
+
interface MissingData {
|
|
9
|
+
no_usage_lines: number
|
|
10
|
+
malformed_lines: number
|
|
11
|
+
unreadable_sessions: number
|
|
12
|
+
// Delegated units whose owning session's issue could not be determined, so their cost is charged
|
|
13
|
+
// to no issue at all (joshuafolkken/kit#1812). Filled by the attribution, which is the only step
|
|
14
|
+
// that knows a unit could not follow its parent; zero from a per-session tally.
|
|
15
|
+
unattributed_sessions: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// The corpus of a project's session transcripts, and how each request in it attributes to an issue
|
|
19
|
+
// (joshuafolkken/kit#962, joshuafolkken/kit#1812). Split out of `cost-cli.ts` when that file passed
|
|
20
|
+
// its length limit: the CLI parses flags and prints reports, and this is the reading underneath every
|
|
21
|
+
// scope it prints — the same walk `josh time`'s phase costs read through `cost_cli.attributed`.
|
|
22
|
+
|
|
23
|
+
interface Corpus {
|
|
24
|
+
sessions: Array<SessionUsage>
|
|
25
|
+
// Kept beside the sessions so the whole-session scope can re-read its transcript for the two
|
|
26
|
+
// decompositions (joshuafolkken/kit#1151). Parsed lazily and only for that one file: classifying
|
|
27
|
+
// the content blocks of all 158 transcripts to print one issue's cost would be work nothing reads.
|
|
28
|
+
files: Array<SessionFile>
|
|
29
|
+
missing: MissingData
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function accumulate_missing(sessions: ReadonlyArray<SessionUsage>): MissingData {
|
|
33
|
+
return {
|
|
34
|
+
no_usage_lines: sessions.reduce((sum, session) => sum + session.no_usage_lines, 0),
|
|
35
|
+
malformed_lines: sessions.reduce((sum, session) => sum + session.malformed_lines, 0),
|
|
36
|
+
unreadable_sessions: sessions.filter((session) => !session.is_readable).length,
|
|
37
|
+
// Filled by the attribution, which is the only step that knows a unit could not follow its
|
|
38
|
+
// parent; a per-session tally cannot see it, so it is zero here and set for an issue scope below.
|
|
39
|
+
unattributed_sessions: 0,
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Every session for this project, newest first. Once the readerless `--session` scope was retired
|
|
44
|
+
// (#2016) no caller narrows the set, so the whole corpus is read.
|
|
45
|
+
function load_corpus(cwd: string): Corpus {
|
|
46
|
+
const files = cost_transcript.list_sessions_across(cost_transcript.transcript_directories(cwd))
|
|
47
|
+
const sessions = files.map((file) => cost_transcript.read_session(file))
|
|
48
|
+
|
|
49
|
+
return { sessions, files, missing: accumulate_missing(sessions) }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface AttributedRecord {
|
|
53
|
+
record: UsageRecord
|
|
54
|
+
issue: number
|
|
55
|
+
// The resident baseline of the session this record was read from. Carried per record because a
|
|
56
|
+
// scope that spans sessions has no single baseline, and the first record of a *filtered* set is
|
|
57
|
+
// a warm mid-session request rather than a preamble — reading it as one reported an issue as
|
|
58
|
+
// 86.5% resident against a real session's 27.7%.
|
|
59
|
+
baseline_tokens: number
|
|
60
|
+
// The session this record was read from, and whether that session is a delegated unit. The cost
|
|
61
|
+
// curve is built from the non-delegated (main-line) sessions' records alone, so it needs both to
|
|
62
|
+
// group an issue's records back by session and drop the units (joshuafolkken/kit#1853).
|
|
63
|
+
session_id: string
|
|
64
|
+
is_delegated: boolean
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
interface SessionMeta {
|
|
68
|
+
is_delegated: boolean
|
|
69
|
+
owner: string
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Whether each session is a delegated unit, and which session delegated it. Read from the files
|
|
73
|
+
// rather than the usages because only the discovery knows where a transcript was found — a unit lives
|
|
74
|
+
// at `<parent>/subagents/agent-<id>.jsonl`, and its owner is the half in front of the separator.
|
|
75
|
+
function session_meta(corpus: Corpus): Map<string, SessionMeta> {
|
|
76
|
+
return new Map(
|
|
77
|
+
corpus.files.map((file) => [
|
|
78
|
+
file.session_id,
|
|
79
|
+
{ is_delegated: file.is_delegated, owner: cost_transcript.owning_session_id(file) },
|
|
80
|
+
]),
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Every distinct issue a session's own records attribute to. A delegated unit reads this from the
|
|
85
|
+
// session that delegated it (joshuafolkken/kit#1812): a `fullrun`'s parent names exactly one, so its
|
|
86
|
+
// units follow it; a parent that ran several names them all, and its unattributed unit could belong to
|
|
87
|
+
// any of them.
|
|
88
|
+
function issue_set(records: ReadonlyArray<UsageRecord>): Set<number> {
|
|
89
|
+
const issues = cost_attribute
|
|
90
|
+
.group_by_issue(records)
|
|
91
|
+
.map((group) => group.issue)
|
|
92
|
+
.filter((issue) => issue !== cost_attribute.UNATTRIBUTED_KEY)
|
|
93
|
+
|
|
94
|
+
return new Set(issues)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// The one issue to inherit, or `UNATTRIBUTED_KEY` where the parent named none or more than one — in
|
|
98
|
+
// which case a unit's own-branchless records stay unattributed and the set above says which issues
|
|
99
|
+
// they might have belonged to.
|
|
100
|
+
function sole_of(issues: ReadonlySet<number>): number {
|
|
101
|
+
if (issues.size !== 1) return cost_attribute.UNATTRIBUTED_KEY
|
|
102
|
+
|
|
103
|
+
return [...issues][0] ?? cost_attribute.UNATTRIBUTED_KEY
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Each non-delegated session's issue set, keyed by session id, for its units to read.
|
|
107
|
+
function owner_sets(
|
|
108
|
+
corpus: Corpus,
|
|
109
|
+
meta: ReadonlyMap<string, SessionMeta>,
|
|
110
|
+
): Map<string, Set<number>> {
|
|
111
|
+
const own = corpus.sessions.filter(
|
|
112
|
+
(session) => meta.get(session.session_id)?.is_delegated !== true,
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
return new Map(own.map((session) => [session.session_id, issue_set(session.records)]))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// A session's records, each tagged with the issue its own branch names — and, for a delegated unit,
|
|
119
|
+
// the parent's sole issue substituted wherever the branch named none (joshuafolkken/kit#1812). A child
|
|
120
|
+
// that committed carries its own `<N>-` branch exactly as a top-level session does, so it attributes
|
|
121
|
+
// by its own records; only a sub-step that never commits — a review, a survey — carries `main`
|
|
122
|
+
// throughout and falls to the inherited issue. `inherited` is `UNATTRIBUTED_KEY` for a non-delegated
|
|
123
|
+
// session, which makes the substitution a no-op and leaves its branch-driven grouping exactly as before.
|
|
124
|
+
function pairs_with_inherited(
|
|
125
|
+
session: SessionUsage,
|
|
126
|
+
inherited: number,
|
|
127
|
+
is_delegated: boolean,
|
|
128
|
+
): Array<AttributedRecord> {
|
|
129
|
+
return cost_attribute.group_by_issue(session.records).flatMap((group) =>
|
|
130
|
+
group.records.map((record) => ({
|
|
131
|
+
record,
|
|
132
|
+
issue: group.issue === cost_attribute.UNATTRIBUTED_KEY ? inherited : group.issue,
|
|
133
|
+
baseline_tokens: session.baseline_tokens,
|
|
134
|
+
session_id: session.session_id,
|
|
135
|
+
is_delegated,
|
|
136
|
+
})),
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const NO_ISSUES: ReadonlySet<number> = new Set()
|
|
141
|
+
|
|
142
|
+
// The issues the session that delegated this unit touched — or an empty set where the unit is not
|
|
143
|
+
// delegated, its parent is not in the corpus, or that parent named no issue. An empty set reads as
|
|
144
|
+
// "could belong to any issue", the honest candidate for a unit its parent gives nothing to place.
|
|
145
|
+
function parent_issues(
|
|
146
|
+
session: SessionUsage,
|
|
147
|
+
meta: ReadonlyMap<string, SessionMeta>,
|
|
148
|
+
owners: ReadonlyMap<string, Set<number>>,
|
|
149
|
+
): ReadonlySet<number> {
|
|
150
|
+
const entry = meta.get(session.session_id)
|
|
151
|
+
|
|
152
|
+
if (entry?.is_delegated !== true) return NO_ISSUES
|
|
153
|
+
|
|
154
|
+
return owners.get(entry.owner) ?? NO_ISSUES
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
interface SessionPairs {
|
|
158
|
+
pairs: Array<AttributedRecord>
|
|
159
|
+
// Present for a delegated unit whose cost could not all be attributed: the issues its parent
|
|
160
|
+
// touched, which an issue scope counts as a floor when the set contains that issue or is empty.
|
|
161
|
+
unattributed_candidates?: ReadonlySet<number>
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function pairs_of_session(
|
|
165
|
+
session: SessionUsage,
|
|
166
|
+
meta: ReadonlyMap<string, SessionMeta>,
|
|
167
|
+
owners: ReadonlyMap<string, Set<number>>,
|
|
168
|
+
): SessionPairs {
|
|
169
|
+
const is_delegated = meta.get(session.session_id)?.is_delegated === true
|
|
170
|
+
const candidates = parent_issues(session, meta, owners)
|
|
171
|
+
const inherited = is_delegated ? sole_of(candidates) : cost_attribute.UNATTRIBUTED_KEY
|
|
172
|
+
const pairs = pairs_with_inherited(session, inherited, is_delegated)
|
|
173
|
+
const has_unattributed = pairs.some((pair) => pair.issue === cost_attribute.UNATTRIBUTED_KEY)
|
|
174
|
+
|
|
175
|
+
if (!is_delegated || !has_unattributed) return { pairs }
|
|
176
|
+
|
|
177
|
+
return { pairs, unattributed_candidates: candidates }
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
interface CorpusAttribution {
|
|
181
|
+
pairs: Array<AttributedRecord>
|
|
182
|
+
// One entry per delegated unit whose cost could not be attributed: the issues its parent touched.
|
|
183
|
+
unattributed: Array<ReadonlySet<number>>
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Attribution across the whole corpus, delegated units followed to the session that delegated them
|
|
187
|
+
// (joshuafolkken/kit#1812). The fill-forward walk itself is untouched — a unit is tagged with its
|
|
188
|
+
// parent's issue and a non-delegated session keeps `group_by_issue` exactly as before — so
|
|
189
|
+
// `josh cost --issue` and `josh time`'s phase costs, which both read this, stay in step.
|
|
190
|
+
function attribute_corpus(corpus: Corpus): CorpusAttribution {
|
|
191
|
+
const meta = session_meta(corpus)
|
|
192
|
+
const owners = owner_sets(corpus, meta)
|
|
193
|
+
const per_session = corpus.sessions.map((session) => pairs_of_session(session, meta, owners))
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
pairs: per_session.flatMap((one) => one.pairs),
|
|
197
|
+
unattributed: per_session.flatMap((one) =>
|
|
198
|
+
one.unattributed_candidates === undefined ? [] : [one.unattributed_candidates],
|
|
199
|
+
),
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// How many unattributed units an issue scope must treat as a floor: those whose parent touched that
|
|
204
|
+
// issue, and those whose parent named nothing (so the unit could belong to any issue).
|
|
205
|
+
function floor_for_issue(
|
|
206
|
+
unattributed: ReadonlyArray<ReadonlySet<number>>,
|
|
207
|
+
issue_number: number,
|
|
208
|
+
): number {
|
|
209
|
+
return unattributed.filter((set) => set.size === 0 || set.has(issue_number)).length
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// An occurrence carrying an issue beats one that does not. A copy written before the branch existed
|
|
213
|
+
// has nothing to attribute it to, so keeping it would move a real request into `unattributed`.
|
|
214
|
+
function is_better(candidate: AttributedRecord, existing: AttributedRecord): boolean {
|
|
215
|
+
const { UNATTRIBUTED_KEY } = cost_attribute
|
|
216
|
+
|
|
217
|
+
return existing.issue === UNATTRIBUTED_KEY && candidate.issue !== UNATTRIBUTED_KEY
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function values_of(best: ReadonlyMap<string, AttributedRecord>): Array<AttributedRecord> {
|
|
221
|
+
const collected: Array<AttributedRecord> = []
|
|
222
|
+
|
|
223
|
+
for (const [, pair] of best) collected.push(pair)
|
|
224
|
+
|
|
225
|
+
return collected
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// **Dedupe again, across sessions.** Resuming or forking a session copies the earlier lines into a
|
|
229
|
+
// new transcript file, so one billed request appears in several — 152 such request ids in this
|
|
230
|
+
// repository's own transcripts, some in three files. Per-session dedup does not see them, and every
|
|
231
|
+
// scope spanning more than one session would bill those requests twice or three times.
|
|
232
|
+
function dedupe_across_sessions(pairs: ReadonlyArray<AttributedRecord>): Array<AttributedRecord> {
|
|
233
|
+
const best = new Map<string, AttributedRecord>()
|
|
234
|
+
|
|
235
|
+
for (const pair of pairs) {
|
|
236
|
+
const existing = best.get(pair.record.request_id)
|
|
237
|
+
|
|
238
|
+
if (existing === undefined || is_better(pair, existing)) {
|
|
239
|
+
best.set(pair.record.request_id, pair)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return values_of(best)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function attributed(corpus: Corpus): Array<AttributedRecord> {
|
|
247
|
+
return dedupe_across_sessions(attribute_corpus(corpus).pairs)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// The in-scope records of each non-delegated (main-line) session, grouped and kept in the order they
|
|
251
|
+
// were read. The curve is built from these: a delegated unit starts from low context, so mixing its
|
|
252
|
+
// records into the positional quartiles breaks the growth curve a hand-off decision reads
|
|
253
|
+
// (joshuafolkken/kit#1853). A single-issue run on one session yields one group; a run resumed in a
|
|
254
|
+
// second session yields two, which the curve then withholds rather than mixing.
|
|
255
|
+
function mainline_records(pairs: ReadonlyArray<AttributedRecord>): Array<Array<UsageRecord>> {
|
|
256
|
+
const groups = new Map<string, Array<UsageRecord>>()
|
|
257
|
+
|
|
258
|
+
for (const pair of pairs) {
|
|
259
|
+
if (pair.is_delegated) continue
|
|
260
|
+
|
|
261
|
+
groups.set(pair.session_id, [...(groups.get(pair.session_id) ?? []), pair.record])
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return [...groups.values()]
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const cost_corpus = {
|
|
268
|
+
accumulate_missing,
|
|
269
|
+
load_corpus,
|
|
270
|
+
attribute_corpus,
|
|
271
|
+
floor_for_issue,
|
|
272
|
+
dedupe_across_sessions,
|
|
273
|
+
attributed,
|
|
274
|
+
mainline_records,
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export type { AttributedRecord, Corpus, MissingData }
|
|
278
|
+
export { cost_corpus }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// The three figures a cost report prints — a dollar amount, a token count, a percentage share — and
|
|
2
|
+
// the precision each uses. Shared by the run-tree report modules and by `josh time`'s reports, which
|
|
3
|
+
// render the same figures.
|
|
4
|
+
|
|
5
|
+
const USD_DECIMALS = 4
|
|
6
|
+
const PERCENT_SCALE = 100
|
|
7
|
+
const PERCENT_DECIMALS = 1
|
|
8
|
+
|
|
9
|
+
function format_usd(usd: number): string {
|
|
10
|
+
return `$${usd.toFixed(USD_DECIMALS)}`
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function format_tokens(count: number): string {
|
|
14
|
+
return count.toLocaleString('en-US')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function format_share(part: number, whole: number): string {
|
|
18
|
+
if (whole === 0) return 'n/a'
|
|
19
|
+
|
|
20
|
+
return `${((part / whole) * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const cost_format = {
|
|
24
|
+
USD_DECIMALS,
|
|
25
|
+
PERCENT_SCALE,
|
|
26
|
+
PERCENT_DECIMALS,
|
|
27
|
+
format_usd,
|
|
28
|
+
format_tokens,
|
|
29
|
+
format_share,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { cost_format }
|