@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,220 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { parseArgs } from 'node:util'
|
|
4
|
+
import { path_decision } from '#scripts/josh/path-decision'
|
|
5
|
+
import { backlog_budget, type BacklogAnswer, type BudgetInput } from './backlog-budget'
|
|
6
|
+
|
|
7
|
+
// The thin half of `josh backlog:budget` (joshuafolkken/kit#1632): read the loop's state off the
|
|
8
|
+
// command line, hand it to the pure decision, print the verdict on stdout and the reason on stderr
|
|
9
|
+
// through the printer every mechanically-decided command in this repository already shares.
|
|
10
|
+
|
|
11
|
+
const ARGV_OFFSET = 2
|
|
12
|
+
const SUCCESS_EXIT_CODE = 0
|
|
13
|
+
const FAILURE_EXIT_CODE = 1
|
|
14
|
+
const JSON_KEY = 'budget'
|
|
15
|
+
|
|
16
|
+
const USAGE = `Usage: josh backlog:budget --answer <${backlog_budget.ANSWERS.join('|')}> --started <ISO-8601> [--active <ISO-8601>, required unless the watch is off] [--merged <count>] [--running <count>] [--max <count>] [--idle <minutes>, 0 to turn the watch off] [--json]`
|
|
17
|
+
|
|
18
|
+
const OPTIONS = {
|
|
19
|
+
active: { type: 'string' },
|
|
20
|
+
answer: { type: 'string' },
|
|
21
|
+
idle: { type: 'string' },
|
|
22
|
+
json: { type: 'boolean' },
|
|
23
|
+
max: { type: 'string' },
|
|
24
|
+
merged: { type: 'string' },
|
|
25
|
+
running: { type: 'string' },
|
|
26
|
+
started: { type: 'string' },
|
|
27
|
+
} as const
|
|
28
|
+
|
|
29
|
+
type OptionName = keyof typeof OPTIONS
|
|
30
|
+
type ParsedValues = Partial<Record<OptionName, string | boolean>>
|
|
31
|
+
|
|
32
|
+
// A misspelled flag is refused rather than defaulted, the contract `path_decision.has_unknown_flag`
|
|
33
|
+
// states for the path-decided commands: an invocation nobody can read is never answered.
|
|
34
|
+
function read_arguments(argv: ReadonlyArray<string>): ParsedValues | undefined {
|
|
35
|
+
try {
|
|
36
|
+
return parseArgs({ args: [...argv], options: OPTIONS, strict: true }).values
|
|
37
|
+
} catch {
|
|
38
|
+
return undefined
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function text_of(value: string | boolean | undefined): string | undefined {
|
|
43
|
+
return typeof value === 'string' ? value : undefined
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// `find` rather than a cast: an unrecognized word has to be refused, and a type assertion would
|
|
47
|
+
// carry it into the decision as a fifth answer nothing branches on.
|
|
48
|
+
function to_answer(raw: string | undefined): BacklogAnswer | undefined {
|
|
49
|
+
return backlog_budget.ANSWERS.find((answer) => answer === raw)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function to_time_ms(raw: string | undefined): number | undefined {
|
|
53
|
+
if (raw === undefined) return undefined
|
|
54
|
+
|
|
55
|
+
const parsed = Date.parse(raw)
|
|
56
|
+
|
|
57
|
+
return Number.isNaN(parsed) ? undefined : parsed
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Digits and nothing else. `Number('')`, `Number(' ')` and `Number('0x10')` are all safe integers, so
|
|
61
|
+
// a check that only asked `Number.isSafeInteger` would read an unset shell variable — `--max
|
|
62
|
+
// "$max_issues"` — as a maximum of zero and finish the run having done nothing.
|
|
63
|
+
const COUNT_PATTERN = /^\d+$/u
|
|
64
|
+
|
|
65
|
+
function to_count(raw: string | undefined): number | undefined {
|
|
66
|
+
if (raw === undefined || !COUNT_PATTERN.test(raw)) return undefined
|
|
67
|
+
|
|
68
|
+
const parsed = Number(raw)
|
|
69
|
+
|
|
70
|
+
return Number.isSafeInteger(parsed) ? parsed : undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// A flag that was given but could not be read makes the whole invocation unreadable. Falling back to
|
|
74
|
+
// the default instead would answer a question nobody asked — a mistyped `--idle 0` would read as the
|
|
75
|
+
// default 30-minute watch and hold a run open that was asked to finish at its first empty backlog.
|
|
76
|
+
function is_readable(raw: string | undefined, parsed: number | undefined): boolean {
|
|
77
|
+
return raw === undefined || parsed !== undefined
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const COUNT_NAMES = ['idle', 'max', 'merged', 'running'] as const
|
|
81
|
+
|
|
82
|
+
type Counts = Record<(typeof COUNT_NAMES)[number], number | undefined>
|
|
83
|
+
|
|
84
|
+
function counts_of(values: ParsedValues): Counts {
|
|
85
|
+
return {
|
|
86
|
+
idle: to_count(text_of(values.idle)),
|
|
87
|
+
max: to_count(text_of(values.max)),
|
|
88
|
+
merged: to_count(text_of(values.merged)),
|
|
89
|
+
running: to_count(text_of(values.running)),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function are_counts_readable(values: ParsedValues, counts: Counts): boolean {
|
|
94
|
+
return COUNT_NAMES.every((name) => is_readable(text_of(values[name]), counts[name]))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// **`--idle 0` is how the watch is turned off, and omitting the flag takes the default**
|
|
98
|
+
// (joshuafolkken/kit#1676) — the inverse of what shipped before. The old refusal rested on "the flag
|
|
99
|
+
// is optional, so 0 is not needed", and turning the default on is exactly what removes that footing:
|
|
100
|
+
// an omitted flag now means the default watch, so the number line has to reach a value that means
|
|
101
|
+
// none. Zero reads as "watch for no minutes", which is the same thing said in the flag's own units.
|
|
102
|
+
const NO_IDLE_MINUTES = 0
|
|
103
|
+
|
|
104
|
+
function to_idle_ms(idle_minutes: number | undefined): number | undefined {
|
|
105
|
+
if (idle_minutes === undefined) return backlog_budget.DEFAULT_IDLE_MS
|
|
106
|
+
if (idle_minutes === NO_IDLE_MINUTES) return undefined
|
|
107
|
+
|
|
108
|
+
return idle_minutes * backlog_budget.MS_PER_MINUTE
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// An idle watch measured from the run's start is not the watch that was asked for. A run already
|
|
112
|
+
// working for longer than the budget would answer `stop` on its very first empty backlog, printing an
|
|
113
|
+
// emptiness it never saw. So an invocation whose watch is on and that carries no `--active` is
|
|
114
|
+
// unreadable rather than defaulted — and since the watch is now on by default, that makes `--active`
|
|
115
|
+
// required of every caller that has not turned it off.
|
|
116
|
+
//
|
|
117
|
+
// **Refused rather than answered with a `stop` that names the missing flag.** A `stop` is the word
|
|
118
|
+
// the loop acts on, and it cannot tell one that ends a run properly from one that means "I could not
|
|
119
|
+
// measure the watch" — which is the emptiness-never-seen failure again, one layer up. A refusal
|
|
120
|
+
// lands on the very first ask, before the run has started anything, and the fix is one flag the loop
|
|
121
|
+
// already holds: it always knows when it last had work.
|
|
122
|
+
function is_watch_readable(values: ParsedValues): boolean {
|
|
123
|
+
if (to_idle_ms(to_count(text_of(values.idle))) === undefined) return true
|
|
124
|
+
|
|
125
|
+
return text_of(values.active) !== undefined
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function are_values_readable(values: ParsedValues): boolean {
|
|
129
|
+
return (
|
|
130
|
+
is_readable(text_of(values.active), to_time_ms(text_of(values.active))) &&
|
|
131
|
+
is_watch_readable(values) &&
|
|
132
|
+
are_counts_readable(values, counts_of(values))
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// What the two required flags carry, once they have been read. Split out so the assembly below can
|
|
137
|
+
// take the defaults without the refusals above sharing its complexity budget.
|
|
138
|
+
type InputBase = Pick<BudgetInput, 'answer' | 'now_ms' | 'started_at_ms'>
|
|
139
|
+
|
|
140
|
+
function input_of(values: ParsedValues, base: InputBase): BudgetInput {
|
|
141
|
+
const counts = counts_of(values)
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
...base,
|
|
145
|
+
active_at_ms: to_time_ms(text_of(values.active)) ?? base.started_at_ms,
|
|
146
|
+
merged: counts.merged ?? 0,
|
|
147
|
+
running: counts.running ?? 0,
|
|
148
|
+
max_issues: counts.max,
|
|
149
|
+
idle_budget_ms: to_idle_ms(counts.idle),
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function build_input(values: ParsedValues, now_ms: number): BudgetInput | undefined {
|
|
154
|
+
const answer = to_answer(text_of(values.answer))
|
|
155
|
+
|
|
156
|
+
if (answer === undefined) return undefined
|
|
157
|
+
|
|
158
|
+
const started_at_ms = to_time_ms(text_of(values.started))
|
|
159
|
+
|
|
160
|
+
if (started_at_ms === undefined) return undefined
|
|
161
|
+
if (!are_values_readable(values)) return undefined
|
|
162
|
+
|
|
163
|
+
return input_of(values, { answer, now_ms, started_at_ms })
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function refuse(): number {
|
|
167
|
+
console.error(USAGE)
|
|
168
|
+
|
|
169
|
+
return FAILURE_EXIT_CODE
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function run(argv: ReadonlyArray<string>, now_ms: number = Date.now()): number {
|
|
173
|
+
const values = read_arguments(argv)
|
|
174
|
+
|
|
175
|
+
if (values === undefined) return refuse()
|
|
176
|
+
|
|
177
|
+
const input = build_input(values, now_ms)
|
|
178
|
+
|
|
179
|
+
if (input === undefined) return refuse()
|
|
180
|
+
|
|
181
|
+
const { verdict, reason } = backlog_budget.decide(input)
|
|
182
|
+
|
|
183
|
+
if (values.json === true) {
|
|
184
|
+
console.info(
|
|
185
|
+
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: backlog_budget.is_finish(input) }),
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
return SUCCESS_EXIT_CODE
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
path_decision.print_decision(JSON_KEY, verdict, reason, false)
|
|
192
|
+
|
|
193
|
+
return SUCCESS_EXIT_CODE
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// `process.exitCode` rather than `process.exit()`, for the reason `backlog:next` records: the whole
|
|
197
|
+
// contract is `answer=$(pnpm josh backlog:budget …)`, and exiting outright can cut the pipe before it
|
|
198
|
+
// has drained.
|
|
199
|
+
function main(argv: ReadonlyArray<string>): void {
|
|
200
|
+
process.exitCode = run(argv)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const backlog_budget_cli = {
|
|
204
|
+
JSON_KEY,
|
|
205
|
+
OPTIONS,
|
|
206
|
+
SUCCESS_EXIT_CODE,
|
|
207
|
+
USAGE,
|
|
208
|
+
build_input,
|
|
209
|
+
main,
|
|
210
|
+
read_arguments,
|
|
211
|
+
run,
|
|
212
|
+
to_answer,
|
|
213
|
+
to_count,
|
|
214
|
+
to_time_ms,
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
218
|
+
|
|
219
|
+
export { backlog_budget_cli }
|
|
220
|
+
export type { ParsedValues }
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
// `josh backlog:budget` — whether a `backlogrun` may start more work, keep watching, or finish
|
|
2
|
+
// (joshuafolkken/kit#1632).
|
|
3
|
+
//
|
|
4
|
+
// `backlog:next` says what may start; it says nothing about when the run itself should end. Before
|
|
5
|
+
// this existed a `backlogrun` had exactly two endings and neither could be declared in advance: it
|
|
6
|
+
// finished the moment the backlog read empty, so an issue a person opted in three minutes later
|
|
7
|
+
// needed a whole new session, or it ran to the 8-hour whole-run bound, which is a limit on waiting
|
|
8
|
+
// rather than a statement of scale.
|
|
9
|
+
//
|
|
10
|
+
// **The idle watch is on by default and the maximum is not** (joshuafolkken/kit#1676). A
|
|
11
|
+
// `backlogrun` with neither flag given watches an empty backlog for `DEFAULT_IDLE_MINUTES` before it
|
|
12
|
+
// finishes, and takes as many issues as the backlog holds. `--idle 0` is how the watch is turned off.
|
|
13
|
+
//
|
|
14
|
+
// The decision is a command's rather than the loop's own arithmetic, for the reason `josh delegate`
|
|
15
|
+
// and `josh review:level` are commands: a count and an elapsed time kept in an agent's head are a
|
|
16
|
+
// one-shot judgement, and joshuafolkken/kit#1460 measured exactly that failure — a threshold asked
|
|
17
|
+
// once and then never again while the run walked past it eight times.
|
|
18
|
+
|
|
19
|
+
const MS_PER_MINUTE = 60_000
|
|
20
|
+
const MINUTES_PER_HOUR = 60
|
|
21
|
+
// `backlogrun-progress.md` → "Waiting, and never waiting forever" carried this as prose only. Held here it is
|
|
22
|
+
// the same bound, decided the same way as the two new ones rather than by an agent reading a clock.
|
|
23
|
+
const WHOLE_RUN_BUDGET_HOURS = 8
|
|
24
|
+
const WHOLE_RUN_BUDGET_MINUTES = WHOLE_RUN_BUDGET_HOURS * MINUTES_PER_HOUR
|
|
25
|
+
const WHOLE_RUN_BUDGET_MS = WHOLE_RUN_BUDGET_MINUTES * MS_PER_MINUTE
|
|
26
|
+
|
|
27
|
+
// **The default idle watch, and why it is this number** (joshuafolkken/kit#1676). The documents used
|
|
28
|
+
// 30 as an example, and an example is not a reason; these three are.
|
|
29
|
+
//
|
|
30
|
+
// - **Below it the watch is a coin flip.** What it waits for is a person noticing the run has gone
|
|
31
|
+
// quiet, filing an issue and applying `auto-ok`. Ten minutes does not reliably outlast that.
|
|
32
|
+
// - **Above it the run pays for nothing.** At `IDLE_POLL_MINUTES` a 30-minute watch is six asks —
|
|
33
|
+
// about one child's worth of turns, spent while the run holds no working tree and no lane.
|
|
34
|
+
// - **It is about the length of one child** — 12 to 28 minutes measured on joshuafolkken/kit#1477 —
|
|
35
|
+
// so a run that has emptied its backlog waits roughly as long as one more issue would have taken.
|
|
36
|
+
const DEFAULT_IDLE_MINUTES = 30
|
|
37
|
+
const DEFAULT_IDLE_MS = DEFAULT_IDLE_MINUTES * MS_PER_MINUTE
|
|
38
|
+
|
|
39
|
+
// **What a watching run sleeps between asks, and it is not the loop's 60-second polling interval.**
|
|
40
|
+
// That one is sized to a child's `fullrun`, which finishes in minutes; a watch is waiting on a person
|
|
41
|
+
// to file an issue and opt it in, which happens on human timescales. Polling a watch every minute
|
|
42
|
+
// would spend thirty of the parent session's own requests — each one billing the whole session
|
|
43
|
+
// history — to learn nothing thirty times. `backlogrun-progress.md` → "Waiting, and never waiting forever" holds
|
|
44
|
+
// the row; the figure is here because `idle_watch_reason` below has to say it.
|
|
45
|
+
const IDLE_POLL_MINUTES = 5
|
|
46
|
+
|
|
47
|
+
const RUN_VERDICT = 'run'
|
|
48
|
+
const WATCH_VERDICT = 'watch'
|
|
49
|
+
const STOP_VERDICT = 'stop'
|
|
50
|
+
|
|
51
|
+
// `run` — start what `backlog:next` offered. `watch` — sleep the polling interval and ask again,
|
|
52
|
+
// except while something of the run's own is in flight, where the wake is the progress watcher's exit
|
|
53
|
+
// and the interval is only a floor (`backlogrun.md` → "The wake exists only while something is in
|
|
54
|
+
// flight").
|
|
55
|
+
// `stop` — report and finish. There is no fourth: an answer the loop cannot act on is a verdict
|
|
56
|
+
// nobody can write a loop against.
|
|
57
|
+
type BudgetVerdict = typeof RUN_VERDICT | typeof WATCH_VERDICT | typeof STOP_VERDICT
|
|
58
|
+
|
|
59
|
+
// What `backlog:next` answered, in the words this decision needs. The mapping is mechanical and is
|
|
60
|
+
// written once, in `backlogrun-steps.md` → "The loop": numbers are `candidates`, `wait` is `blocked` while
|
|
61
|
+
// this run has children in flight and `exhausted` when it does not, `none` is `exhausted`, `stop` is
|
|
62
|
+
// `parked`, and `error` or a failed listing is `unreadable`.
|
|
63
|
+
const ANSWERS = ['blocked', 'candidates', 'exhausted', 'parked', 'unreadable'] as const
|
|
64
|
+
|
|
65
|
+
type BacklogAnswer = (typeof ANSWERS)[number]
|
|
66
|
+
|
|
67
|
+
interface BudgetInput {
|
|
68
|
+
answer: BacklogAnswer
|
|
69
|
+
// Issues this run has merged so far.
|
|
70
|
+
merged: number
|
|
71
|
+
// Children this run has started that have not merged yet. Counted against the maximum alongside
|
|
72
|
+
// the merged ones, because children run in lanes: a wave started before any of them merged would
|
|
73
|
+
// otherwise be measured against a maximum that cannot see it.
|
|
74
|
+
running: number
|
|
75
|
+
started_at_ms: number
|
|
76
|
+
// When this run last had work — the most recent ask that was not `exhausted`, or the run's start.
|
|
77
|
+
// Refreshing it is what restarts the idle watch when a candidate appears during one.
|
|
78
|
+
active_at_ms: number
|
|
79
|
+
now_ms: number
|
|
80
|
+
// `undefined` means unlimited. Named rather than optional: `exactOptionalPropertyTypes` makes an
|
|
81
|
+
// optional property that also admits `undefined` redundant to write and to read (Sonar S4782), and
|
|
82
|
+
// every construction site here knows whether a budget was given.
|
|
83
|
+
max_issues: number | undefined
|
|
84
|
+
// `undefined` means the idle watch is off, which is what `--idle 0` asks for. The default is on:
|
|
85
|
+
// the command resolves an absent `--idle` to `DEFAULT_IDLE_MS` before it reaches here.
|
|
86
|
+
idle_budget_ms: number | undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface BudgetDecision {
|
|
90
|
+
verdict: BudgetVerdict
|
|
91
|
+
reason: string
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const WHOLE_RUN_REASON = `The whole-run bound of ${String(WHOLE_RUN_BUDGET_HOURS)} hours has passed. An unattended run that has not finished overnight needs a person, not more waiting.`
|
|
95
|
+
|
|
96
|
+
const PARKED_REASON =
|
|
97
|
+
'Nothing opted in can proceed without a person. Report the parked issues and finish.'
|
|
98
|
+
|
|
99
|
+
const UNREADABLE_REASON =
|
|
100
|
+
'The backlog listing could not be read, so nothing was offered. Report what the command printed and finish — it is not an empty backlog.'
|
|
101
|
+
|
|
102
|
+
const BLOCKED_REASON =
|
|
103
|
+
'Everything opted in is blocked or already running, so waiting can still change the answer. Poll again at the polling interval.'
|
|
104
|
+
|
|
105
|
+
const NO_IDLE_WATCH_REASON =
|
|
106
|
+
'The backlog is empty and the idle watch was turned off with `--idle 0`, so the run finishes here.'
|
|
107
|
+
|
|
108
|
+
function to_minutes(duration_ms: number): string {
|
|
109
|
+
return String(Math.ceil(duration_ms / MS_PER_MINUTE))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Every count below is written as a trailing clause rather than as the subject of a sentence, so a
|
|
113
|
+
// reason built from 1 reads as well as one built from 5. These strings are quoted verbatim into the
|
|
114
|
+
// completion report, where "1 issues have merged" is what a person actually sees.
|
|
115
|
+
function max_reached_reason(merged: number, max_issues: number): string {
|
|
116
|
+
return `This run's maximum of ${String(max_issues)} is reached, with ${String(merged)} merged. Report what was done, including how many were picked up during an idle watch, and finish.`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function draining_reason(running: number, reason: string): string {
|
|
120
|
+
return `Start nothing more and poll until the running children merge (running: ${String(running)}). Then report and finish — ${reason}`
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function idle_expired_reason(idle_budget_ms: number): string {
|
|
124
|
+
return `The backlog stayed empty for the whole ${to_minutes(idle_budget_ms)}-minute idle watch. Report what was done, including how many were picked up during the watch, and finish.`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Never longer than the watch has left: "about 2 minutes left, ask again in 5 minutes" would overrun
|
|
128
|
+
// the budget a person declared, and a sentence that contradicts itself is read as neither half.
|
|
129
|
+
function next_ask_minutes(left_ms: number): string {
|
|
130
|
+
const left_minutes = Number(to_minutes(left_ms))
|
|
131
|
+
|
|
132
|
+
return String(Math.min(IDLE_POLL_MINUTES, left_minutes))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function idle_watch_reason(left_ms: number): string {
|
|
136
|
+
return `The backlog is empty and the idle watch has about ${to_minutes(left_ms)} minutes left. Release the working tree, ask again in ${next_ask_minutes(left_ms)} minutes, and restart the watch the moment a candidate appears.`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// **A watch that opens while children are still in lanes is not the idle watch's ordinary shape**, and
|
|
140
|
+
// it became reachable the moment the watch was turned on by default (joshuafolkken/kit#1676): the
|
|
141
|
+
// backlog can answer `exhausted` while this run's own children are still merging. Two things the
|
|
142
|
+
// sentence above would get wrong there — the working tree is still held, because the hold is released
|
|
143
|
+
// at the *last* child's merge, and a five-minute poll would leave a merge unnoticed for five minutes.
|
|
144
|
+
//
|
|
145
|
+
// **The watch runs down while they drain, and the sentence does not promise otherwise.** Pausing it
|
|
146
|
+
// would mean moving `active_at` on an ask that answered `exhausted`, which is the one thing that
|
|
147
|
+
// moment is defined not to do — so a drain longer than the budget ends the run at the drain. That is
|
|
148
|
+
// the honest ending: the backlog was empty at every ask, which is exactly what the watch measures.
|
|
149
|
+
function running_watch_reason(running: number, left_ms: number): string {
|
|
150
|
+
return `The backlog is empty and the idle watch has about ${to_minutes(left_ms)} minutes left, with ${String(running)} still running. Keep the working tree until they merge and poll at the polling interval, not the idle poll — the watch is running down meanwhile.`
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function watching_reason(input: BudgetInput, left_ms: number): string {
|
|
154
|
+
if (input.running === 0) return idle_watch_reason(left_ms)
|
|
155
|
+
|
|
156
|
+
return running_watch_reason(input.running, left_ms)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// What the maximum has already taken: merged issues and the children still running. Counting only
|
|
160
|
+
// the merged ones would let a second wave start before the first had merged and take the run past
|
|
161
|
+
// the maximum a person declared.
|
|
162
|
+
function taken_by(input: BudgetInput): number {
|
|
163
|
+
return input.merged + input.running
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function run_reason(input: BudgetInput): string {
|
|
167
|
+
const { max_issues } = input
|
|
168
|
+
|
|
169
|
+
if (max_issues === undefined) return 'No maximum was given, so start every issue offered.'
|
|
170
|
+
|
|
171
|
+
return `Start at most ${String(max_issues - taken_by(input))} more: this run's maximum is ${String(max_issues)}, with ${String(input.merged)} merged and ${String(input.running)} running.`
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// The two answers that end a run whatever the budgets say. Neither is a budget decision — the graph
|
|
175
|
+
// said so — but both reach this command, because the loop asks one question rather than branching on
|
|
176
|
+
// `backlog:next`'s word itself and then asking a second.
|
|
177
|
+
const ANSWER_STOP_REASONS: Readonly<Partial<Record<BacklogAnswer, string>>> = {
|
|
178
|
+
parked: PARKED_REASON,
|
|
179
|
+
unreadable: UNREADABLE_REASON,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function whole_run_reason(input: BudgetInput): string | undefined {
|
|
183
|
+
if (input.now_ms - input.started_at_ms < WHOLE_RUN_BUDGET_MS) return undefined
|
|
184
|
+
|
|
185
|
+
return WHOLE_RUN_REASON
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// The answer-level stops come first, ahead of every budget. Both of them say something the person
|
|
189
|
+
// has to act on — issues are parked, or the listing could not be read — and the reason printed here
|
|
190
|
+
// is quoted verbatim into the completion report, so a budget reason in front of one would report a
|
|
191
|
+
// tidy ending for a run whose backlog actually broke.
|
|
192
|
+
function stop_reason(input: BudgetInput): string | undefined {
|
|
193
|
+
return ANSWER_STOP_REASONS[input.answer] ?? whole_run_reason(input)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Every ending goes through here, so no ending abandons a lane. Children already started have to
|
|
197
|
+
// merge and be reported whatever ended the run — the maximum, a parked backlog, a listing that could
|
|
198
|
+
// not be read, or the whole-run bound — so a `stop` while any of them is still running would leave
|
|
199
|
+
// open lanes behind and merged work unmentioned.
|
|
200
|
+
function stopping(input: BudgetInput, reason: string): BudgetDecision {
|
|
201
|
+
if (input.running === 0) return { verdict: STOP_VERDICT, reason }
|
|
202
|
+
|
|
203
|
+
return { verdict: WATCH_VERDICT, reason: draining_reason(input.running, reason) }
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// The maximum is checked before the answer, so reaching it ends the run whatever `backlog:next` was
|
|
207
|
+
// about to offer. The acceptance criterion is that reaching it reports and finishes, and a run that
|
|
208
|
+
// first finished the wave it had already started would report a number the person never approved.
|
|
209
|
+
function max_decision(input: BudgetInput): BudgetDecision | undefined {
|
|
210
|
+
const { max_issues } = input
|
|
211
|
+
|
|
212
|
+
if (max_issues === undefined || taken_by(input) < max_issues) return undefined
|
|
213
|
+
|
|
214
|
+
return stopping(input, max_reached_reason(input.merged, max_issues))
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// An empty backlog is watched rather than acted on, which is now the default — and the watch lives
|
|
218
|
+
// *inside* the whole-run bound, which `stop_reason` has already applied above. Only `--idle 0` takes
|
|
219
|
+
// the other branch, where an empty backlog is the run's ending.
|
|
220
|
+
function idle_decision(input: BudgetInput): BudgetDecision {
|
|
221
|
+
const { idle_budget_ms } = input
|
|
222
|
+
|
|
223
|
+
if (idle_budget_ms === undefined) return stopping(input, NO_IDLE_WATCH_REASON)
|
|
224
|
+
|
|
225
|
+
const left_ms = idle_budget_ms - (input.now_ms - input.active_at_ms)
|
|
226
|
+
|
|
227
|
+
if (left_ms <= 0) return stopping(input, idle_expired_reason(idle_budget_ms))
|
|
228
|
+
|
|
229
|
+
return { verdict: WATCH_VERDICT, reason: watching_reason(input, left_ms) }
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Whether a `stop` for this input is the run finishing — the idle watch ending on an empty backlog —
|
|
233
|
+
// rather than stopping on something a person must act on: a parked backlog, an unreadable listing, the
|
|
234
|
+
// maximum or the whole-run bound. The two end the carry record differently (`--end` against
|
|
235
|
+
// `--end --stopped`), and `backlog:drive` reads which one from here (joshuafolkken/kit#2508).
|
|
236
|
+
function is_finish(input: BudgetInput): boolean {
|
|
237
|
+
return stop_reason(input) === undefined && max_decision(input) === undefined
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function decide(input: BudgetInput): BudgetDecision {
|
|
241
|
+
const reason = stop_reason(input)
|
|
242
|
+
|
|
243
|
+
if (reason !== undefined) return stopping(input, reason)
|
|
244
|
+
|
|
245
|
+
const capped = max_decision(input)
|
|
246
|
+
|
|
247
|
+
if (capped !== undefined) return capped
|
|
248
|
+
if (input.answer === 'candidates') return { verdict: RUN_VERDICT, reason: run_reason(input) }
|
|
249
|
+
if (input.answer === 'blocked') return { verdict: WATCH_VERDICT, reason: BLOCKED_REASON }
|
|
250
|
+
|
|
251
|
+
return idle_decision(input)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const backlog_budget = {
|
|
255
|
+
ANSWERS,
|
|
256
|
+
ANSWER_STOP_REASONS,
|
|
257
|
+
BLOCKED_REASON,
|
|
258
|
+
DEFAULT_IDLE_MINUTES,
|
|
259
|
+
DEFAULT_IDLE_MS,
|
|
260
|
+
IDLE_POLL_MINUTES,
|
|
261
|
+
MS_PER_MINUTE,
|
|
262
|
+
NO_IDLE_WATCH_REASON,
|
|
263
|
+
PARKED_REASON,
|
|
264
|
+
RUN_VERDICT,
|
|
265
|
+
STOP_VERDICT,
|
|
266
|
+
UNREADABLE_REASON,
|
|
267
|
+
WATCH_VERDICT,
|
|
268
|
+
WHOLE_RUN_BUDGET_HOURS,
|
|
269
|
+
WHOLE_RUN_BUDGET_MINUTES,
|
|
270
|
+
WHOLE_RUN_BUDGET_MS,
|
|
271
|
+
WHOLE_RUN_REASON,
|
|
272
|
+
decide,
|
|
273
|
+
draining_reason,
|
|
274
|
+
idle_expired_reason,
|
|
275
|
+
idle_watch_reason,
|
|
276
|
+
is_finish,
|
|
277
|
+
max_reached_reason,
|
|
278
|
+
run_reason,
|
|
279
|
+
running_watch_reason,
|
|
280
|
+
taken_by,
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export { backlog_budget }
|
|
284
|
+
export type { BacklogAnswer, BudgetDecision, BudgetInput, BudgetVerdict }
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { EpicChild } from '#scripts/epic/epic-graph'
|
|
2
|
+
import type { EpicNextResult, RepoCandidates } from '#scripts/epic/epic-report'
|
|
3
|
+
import { git_gh_command } from '#scripts/git/git-gh-command'
|
|
4
|
+
import { defect_rate, type DefectRate, type IssueKind } from '#scripts/issue/defect-rate'
|
|
5
|
+
import { defect_rate_cli } from '#scripts/issue/defect-rate-cli'
|
|
6
|
+
|
|
7
|
+
// While the defect rate is above its baseline, `backlog:next` offers defects and hardening first and
|
|
8
|
+
// defers new mechanisms (joshuafolkken/kit#2455). The re-ordering stays inside the runnable set — every
|
|
9
|
+
// candidate is already ready to start — so no dependency the graph recorded is crossed.
|
|
10
|
+
|
|
11
|
+
const UNMEASURED_MESSAGE =
|
|
12
|
+
'The defect rate could not be read from GitHub, so the backlog is offered in its usual order.'
|
|
13
|
+
|
|
14
|
+
// Lower goes first. The sort is stable, so each kind keeps the order the graph gave it.
|
|
15
|
+
const KIND_RANK: Readonly<Record<IssueKind, number>> = { defect: 0, other: 1, mechanism: 2 }
|
|
16
|
+
|
|
17
|
+
function above_message(measured: DefectRate): string {
|
|
18
|
+
return `The defect rate ${defect_rate.rate_text(measured)} is above its baseline ${String(defect_rate.BASELINE_RATE)}, so defects are offered first and new mechanisms last.`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// An unreadable body reads as empty: the labels still classify `route:interrupt`, and anything else
|
|
22
|
+
// keeps its usual place rather than being deferred on a read that failed.
|
|
23
|
+
async function kind_of_child(child: EpicChild): Promise<IssueKind> {
|
|
24
|
+
const body = await git_gh_command.issue_get_body(String(child.number), child.repo)
|
|
25
|
+
|
|
26
|
+
return defect_rate.kind_of({ body: body ?? '', labels: child.labels })
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function reorder_bundle(bundle: RepoCandidates): Promise<RepoCandidates> {
|
|
30
|
+
const kinds = await Promise.all(bundle.children.map(async (child) => await kind_of_child(child)))
|
|
31
|
+
const ranked = bundle.children.map((child, index) => ({
|
|
32
|
+
child,
|
|
33
|
+
rank: KIND_RANK[kinds[index] ?? 'other'],
|
|
34
|
+
}))
|
|
35
|
+
const children = ranked.toSorted((left, right) => left.rank - right.rank).map((row) => row.child)
|
|
36
|
+
|
|
37
|
+
return { ...bundle, children }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async function reorder(result: EpicNextResult, repo: string): Promise<EpicNextResult> {
|
|
41
|
+
const candidates = await Promise.all(
|
|
42
|
+
result.candidates.map(async (bundle) =>
|
|
43
|
+
bundle.repo === repo ? await reorder_bundle(bundle) : bundle,
|
|
44
|
+
),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return { ...result, candidates }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// The result as `backlog:next` should offer it. Only a `run` answer has anything to order, and only
|
|
51
|
+
// this repository's bundle is re-ordered, because only its numbers reach standard output.
|
|
52
|
+
async function prioritize(
|
|
53
|
+
result: EpicNextResult,
|
|
54
|
+
repo: string,
|
|
55
|
+
now_ms: number = Date.now(),
|
|
56
|
+
): Promise<EpicNextResult> {
|
|
57
|
+
if (result.verdict !== 'run') return result
|
|
58
|
+
|
|
59
|
+
const days = defect_rate.DEFAULT_WINDOW_DAYS
|
|
60
|
+
const measured = await defect_rate_cli.measure_window(repo, days, now_ms)
|
|
61
|
+
|
|
62
|
+
if (measured === undefined) {
|
|
63
|
+
console.error(UNMEASURED_MESSAGE)
|
|
64
|
+
|
|
65
|
+
return result
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!defect_rate.is_above_baseline(measured)) return result
|
|
69
|
+
|
|
70
|
+
console.error(above_message(measured))
|
|
71
|
+
|
|
72
|
+
return await reorder(result, repo)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const backlog_defect_priority = { UNMEASURED_MESSAGE, KIND_RANK, prioritize }
|
|
76
|
+
|
|
77
|
+
export { backlog_defect_priority }
|