@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,108 @@
|
|
|
1
|
+
import { git_epic_parse } from '#scripts/git/git-epic-parse'
|
|
2
|
+
import { epic_graph, type EpicChild, type IssueReference } from './epic-graph'
|
|
3
|
+
|
|
4
|
+
// joshuafolkken/kit#1113: a second look at the relations, taken only where the first one is about to
|
|
5
|
+
// become a verdict.
|
|
6
|
+
//
|
|
7
|
+
// `read_blocked_by` answers from the issue's own `issue_dependencies_summary` when that summary says
|
|
8
|
+
// zero, which is what keeps a pass over the whole backlog to one request per issue that declares a
|
|
9
|
+
// blocker (joshuafolkken/kit#1024). The summary is GitHub's count, and it can disagree with the
|
|
10
|
+
// listing it counts: measured on joshuafolkken/kit#1111, whose summary read `total_blocked_by: 0`
|
|
11
|
+
// while `dependencies/blocked_by` returned `#1106`, and where re-POSTing that relation was refused
|
|
12
|
+
// with `Target issue has already been taken` — so the relation was real and only the counter was
|
|
13
|
+
// wrong. `epic:next` read the epic as self-contradictory, printed `declared but not recorded:
|
|
14
|
+
// #1106 -> #1111`, and exited 1. An unattended run stops there, on a graph with nothing to fix.
|
|
15
|
+
//
|
|
16
|
+
// It corrects nothing else. A relation that is genuinely absent still comes back absent, and the
|
|
17
|
+
// mismatch is still reported — the point is that the report is now about the relations rather than
|
|
18
|
+
// about a counter.
|
|
19
|
+
|
|
20
|
+
// A body may legitimately be ahead of its relations — an epic written before `josh` recorded them,
|
|
21
|
+
// or one whose recording failed — and `missing_relations` calls that case a mismatch too. There the
|
|
22
|
+
// declaration can name every child, so an uncapped recheck fans out one request per child of a
|
|
23
|
+
// 200-child epic, concurrently, to confirm what the body already implies. Past this many suspects
|
|
24
|
+
// the mismatch is not a stale counter and is reported unchecked: a stale counter is one relation
|
|
25
|
+
// GitHub miscounted, not the whole graph.
|
|
26
|
+
const RECHECK_LIMIT = 20
|
|
27
|
+
|
|
28
|
+
// How the caller reads one child's blockers without consulting the summary. Injected so the
|
|
29
|
+
// decision above can be tested without a network, and so this module needs no opinion about how a
|
|
30
|
+
// child in another repository is addressed.
|
|
31
|
+
type BlockersReader = (child: EpicChild) => Promise<Array<IssueReference>>
|
|
32
|
+
|
|
33
|
+
// The children a declared-but-unrecorded link points at. `link.blocked` is the child whose
|
|
34
|
+
// `blocked_by` would have to carry the blocker, so it is the only side worth reading again.
|
|
35
|
+
//
|
|
36
|
+
// Restricted to `declared_repo` because a declared link is written as a bare number, which names an
|
|
37
|
+
// issue in the epic's own repository — `epic_graph` matches those by number alone. An epic tracking
|
|
38
|
+
// both `#40` and `owner/other#40` would otherwise have the second child re-read on the first one's
|
|
39
|
+
// account, and its relations replaced with a different issue's (joshuafolkken/kit#1014).
|
|
40
|
+
function suspect_children(
|
|
41
|
+
children: ReadonlyArray<EpicChild>,
|
|
42
|
+
body: string | undefined,
|
|
43
|
+
declared_repo: string,
|
|
44
|
+
): Set<number> {
|
|
45
|
+
const links = git_epic_parse.parse_dependency_links(body)
|
|
46
|
+
const local = children.filter((child) => child.repo === declared_repo)
|
|
47
|
+
|
|
48
|
+
return new Set(
|
|
49
|
+
epic_graph.missing_relations(links, local, declared_repo).map((link) => link.blocked),
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// A read that fails leaves the child exactly as the first read found it, and says so. The mismatch
|
|
54
|
+
// is then reported as it was before — the honest answer, since nothing was learned — but a run that
|
|
55
|
+
// exits 1 on it should not have to guess whether the correction was even attempted.
|
|
56
|
+
async function reread_child(child: EpicChild, read_blockers: BlockersReader): Promise<EpicChild> {
|
|
57
|
+
try {
|
|
58
|
+
return { ...child, blocked_by: await read_blockers(child) }
|
|
59
|
+
} catch (error) {
|
|
60
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
61
|
+
|
|
62
|
+
console.warn(
|
|
63
|
+
`⚠ could not re-read the blockers of #${String(child.number)}: ${reason}\n` +
|
|
64
|
+
' a mismatch reported below may be this read failing rather than a missing relation',
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return child
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Said out loud for the same reason the failed read is: `epic:next` exits 1 on the mismatch that
|
|
72
|
+
// follows, and an operator reading that message should not have to guess whether the correction was
|
|
73
|
+
// even attempted.
|
|
74
|
+
function skipped_over_limit(
|
|
75
|
+
children: ReadonlyArray<EpicChild>,
|
|
76
|
+
suspect_count: number,
|
|
77
|
+
): ReadonlyArray<EpicChild> {
|
|
78
|
+
console.warn(
|
|
79
|
+
`⚠ ${String(suspect_count)} declared links are unrecorded, past the ${String(RECHECK_LIMIT)} this re-reads\n` +
|
|
80
|
+
' the mismatch below is reported from the first read; the body is likely ahead of the relations',
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return children
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function recheck_missing_relations(
|
|
87
|
+
children: ReadonlyArray<EpicChild>,
|
|
88
|
+
body: string | undefined,
|
|
89
|
+
declared_repo: string,
|
|
90
|
+
read_blockers: BlockersReader,
|
|
91
|
+
): Promise<ReadonlyArray<EpicChild>> {
|
|
92
|
+
const suspects = suspect_children(children, body, declared_repo)
|
|
93
|
+
if (suspects.size === 0) return children
|
|
94
|
+
if (suspects.size > RECHECK_LIMIT) return skipped_over_limit(children, suspects.size)
|
|
95
|
+
|
|
96
|
+
return await Promise.all(
|
|
97
|
+
children.map(async (child) =>
|
|
98
|
+
suspects.has(child.number) && child.repo === declared_repo
|
|
99
|
+
? await reread_child(child, read_blockers)
|
|
100
|
+
: child,
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const epic_relation_recheck = { recheck_missing_relations, suspect_children, RECHECK_LIMIT }
|
|
106
|
+
|
|
107
|
+
export type { BlockersReader }
|
|
108
|
+
export { epic_relation_recheck }
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import type { Classification } from './epic-classify'
|
|
2
|
+
import { epic_graph, type EpicChild, type GraphAnomaly } from './epic-graph'
|
|
3
|
+
|
|
4
|
+
// Turning a classification into the answer a caller acts on.
|
|
5
|
+
//
|
|
6
|
+
// The verdict is what `epicrun` (joshuafolkken/kit#861) branches on, so the three "nothing to run"
|
|
7
|
+
// cases are kept apart: waiting, stopping, and being finished are different instructions
|
|
8
|
+
// (joshuafolkken/kit#860).
|
|
9
|
+
|
|
10
|
+
// What the caller should do next.
|
|
11
|
+
type EpicVerdict = 'run' | 'wait' | 'stop' | 'complete' | 'error'
|
|
12
|
+
|
|
13
|
+
interface RepoCandidates {
|
|
14
|
+
repo: string
|
|
15
|
+
children: ReadonlyArray<EpicChild>
|
|
16
|
+
// The local checkout a runner would work in, from joshuafolkken/kit#869's map. Absent when the
|
|
17
|
+
// repository is not checked out here — reported rather than cloned, since creating a working tree
|
|
18
|
+
// nobody asked for is not a step this command takes (joshuafolkken/kit#864).
|
|
19
|
+
path?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface EpicNextResult {
|
|
23
|
+
verdict: EpicVerdict
|
|
24
|
+
// Runnable children bundled per repository. How many of one bundle may start at once is the
|
|
25
|
+
// repository's free-lane count, which `epic-lane-offer.ts` decides and this report does not know
|
|
26
|
+
// (joshuafolkken/kit#1491).
|
|
27
|
+
candidates: ReadonlyArray<RepoCandidates>
|
|
28
|
+
waiting: ReadonlyArray<EpicChild>
|
|
29
|
+
blocked_on_people: ReadonlyArray<EpicChild>
|
|
30
|
+
anomalies: ReadonlyArray<GraphAnomaly>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Bundle by repository, repositories in name order, so a run is reproducible rather than dependent
|
|
34
|
+
// on the order GitHub happened to list the repositories in. **The children are not re-ordered at
|
|
35
|
+
// all** since joshuafolkken/kit#1583 — they keep the order the epic's task list gave them, which is
|
|
36
|
+
// how an epic says which of its runnable children goes first; the reasoning is at `bundle_by_repo`
|
|
37
|
+
// below.
|
|
38
|
+
// The discovery map is keyed lowercase — GitHub resolves owner and repository names
|
|
39
|
+
// case-insensitively — so the lookup lowercases too. Without it any capital in a repository name
|
|
40
|
+
// printed "no local checkout" for a repository that is checked out (joshuafolkken/kit#864).
|
|
41
|
+
//
|
|
42
|
+
// `exactOptionalPropertyTypes` rejects `{ path: undefined }`, so the key is added only when there
|
|
43
|
+
// is a path to put in it.
|
|
44
|
+
function to_path_field(path: string | undefined): { path?: string } {
|
|
45
|
+
return path === undefined ? {} : { path }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function bundle_by_repo(
|
|
49
|
+
children: ReadonlyArray<EpicChild>,
|
|
50
|
+
paths: ReadonlyMap<string, string> = new Map(),
|
|
51
|
+
): Array<RepoCandidates> {
|
|
52
|
+
const grouped = new Map<string, Array<EpicChild>>()
|
|
53
|
+
|
|
54
|
+
for (const child of children) {
|
|
55
|
+
const bucket = grouped.get(child.repo) ?? []
|
|
56
|
+
|
|
57
|
+
bucket.push(child)
|
|
58
|
+
grouped.set(child.repo, bucket)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const repos: Array<string> = []
|
|
62
|
+
|
|
63
|
+
for (const [repo] of grouped) repos.push(repo)
|
|
64
|
+
|
|
65
|
+
// **The children keep the order they arrived in, which is the order the epic's task list names
|
|
66
|
+
// them** (joshuafolkken/kit#1583). They used to be re-sorted by issue number here, on the premise
|
|
67
|
+
// that number order is split order — true only of an epic whose children were all filed in one
|
|
68
|
+
// split, and false of every epic that grows as work is found: there the number order is *filing*
|
|
69
|
+
// order, and an epic had no way at all to say which of its runnable children should go first.
|
|
70
|
+
//
|
|
71
|
+
// Nothing else had to change to make the body order authoritative: `epic-fetch.ts` →
|
|
72
|
+
// `fetch_children` already reads the task list in body order and `epic-classify.ts` fills
|
|
73
|
+
// `runnable` in that order, so this sort was the one step discarding it.
|
|
74
|
+
//
|
|
75
|
+
// **The repositories are still sorted by name**, which is a different question — that is grouping,
|
|
76
|
+
// not the order work is offered in.
|
|
77
|
+
return repos
|
|
78
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
79
|
+
.map((repo) => ({
|
|
80
|
+
repo,
|
|
81
|
+
children: grouped.get(repo) ?? [],
|
|
82
|
+
...to_path_field(paths.get(repo.toLowerCase())),
|
|
83
|
+
}))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// The verdict, in the order the decision has to be made. Waiting is checked before stopping for the
|
|
87
|
+
// reason the categories exist: a run that stops while something is still resolving on its own gives
|
|
88
|
+
// up on an epic that was going to finish.
|
|
89
|
+
function decide_verdict(classification: Classification, anomalies: number): EpicVerdict {
|
|
90
|
+
if (anomalies > 0) return 'error'
|
|
91
|
+
if (classification.runnable.length > 0) return 'run'
|
|
92
|
+
if (classification.time.length > 0) return 'wait'
|
|
93
|
+
if (classification.human.length > 0) return 'stop'
|
|
94
|
+
|
|
95
|
+
return 'complete'
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// An unusable graph offers nothing. Emptied here rather than left to each caller to check the
|
|
99
|
+
// verdict first: a candidate list that is populated while the verdict says `error` is work somebody
|
|
100
|
+
// will eventually start, and the anomaly exists to say that nothing may start.
|
|
101
|
+
function build_result(
|
|
102
|
+
classification: Classification,
|
|
103
|
+
anomalies: ReadonlyArray<GraphAnomaly>,
|
|
104
|
+
paths: ReadonlyMap<string, string> = new Map(),
|
|
105
|
+
): EpicNextResult {
|
|
106
|
+
const verdict = decide_verdict(classification, anomalies.length)
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
verdict,
|
|
110
|
+
candidates: verdict === 'error' ? [] : bundle_by_repo(classification.runnable, paths),
|
|
111
|
+
waiting: classification.time,
|
|
112
|
+
blocked_on_people: classification.human,
|
|
113
|
+
anomalies,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Every runnable child of one repository, in the order they would be offered — **the order the
|
|
118
|
+
// epic's own task list names them** (joshuafolkken/kit#1583). It was lowest number first until then,
|
|
119
|
+
// on the premise that number order is split order; an epic that gains children as work is found has
|
|
120
|
+
// no such property, and the epic could not express a priority at all.
|
|
121
|
+
//
|
|
122
|
+
// **Priority is not dependency, and this is the difference.** A child high in the list that is stuck
|
|
123
|
+
// never reaches `runnable`, so it is skipped rather than blocking the ones below it — which is what a
|
|
124
|
+
// declared `blocked-by` chain would do instead, and why an order recorded as a chain stops the batch
|
|
125
|
+
// the moment one child needs a person.
|
|
126
|
+
//
|
|
127
|
+
// The whole bundle rather than only its head, because the confirmation walk needs the rest of it: a
|
|
128
|
+
// candidate whose relations listing disagrees with its summary is withheld and the next one is
|
|
129
|
+
// confirmed in its place (joshuafolkken/kit#1121).
|
|
130
|
+
function candidates_for_repo(result: EpicNextResult, repo: string): ReadonlyArray<EpicChild> {
|
|
131
|
+
return result.candidates.find((bundle) => bundle.repo === repo)?.children ?? []
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// The repository, with the checkout a runner would use. A repository with no local checkout says so
|
|
135
|
+
// rather than being omitted: it is still where the work belongs.
|
|
136
|
+
function format_bundle_heading(bundle: RepoCandidates): string {
|
|
137
|
+
return ` ${bundle.repo} ${bundle.path ?? '(no local checkout)'}`
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// A child in another repository is written `owner/repo#N`, not a bare `#N` — a bare number resolves
|
|
141
|
+
// against the reader's own repository and would linkify to the wrong issue there
|
|
142
|
+
// (joshuafolkken/kit#2329). This reuses the one spelling `epic_graph.format_reference` already gives
|
|
143
|
+
// every other read of a child, rather than a second one here.
|
|
144
|
+
function format_child(child: EpicChild, current_repo: string): string {
|
|
145
|
+
return ` ${epic_graph.format_reference(child, current_repo)}`
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function format_group(
|
|
149
|
+
label: string,
|
|
150
|
+
children: ReadonlyArray<EpicChild>,
|
|
151
|
+
current_repo: string,
|
|
152
|
+
): Array<string> {
|
|
153
|
+
if (children.length === 0) return []
|
|
154
|
+
|
|
155
|
+
return [label, ...children.map((child) => format_child(child, current_repo))]
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const VERDICT_LINES: Readonly<Record<EpicVerdict, string>> = {
|
|
159
|
+
run: 'Runnable children (each takes a free lane in its repository):',
|
|
160
|
+
wait: 'Nothing is runnable yet, but these resolve on their own — wait and ask again:',
|
|
161
|
+
stop: 'Nothing will resolve on its own. These need a person:',
|
|
162
|
+
complete: 'Every child is closed; the epic is complete.',
|
|
163
|
+
error: 'The dependency graph is unusable:',
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// The report. Every open child appears exactly once, so a caller can see that nothing was dropped.
|
|
167
|
+
function format_result(result: EpicNextResult, current_repo: string): string {
|
|
168
|
+
if (result.verdict === 'error') {
|
|
169
|
+
return [VERDICT_LINES.error, ...result.anomalies.map((anomaly) => anomaly.message)].join('\n')
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const lines = [VERDICT_LINES[result.verdict]]
|
|
173
|
+
|
|
174
|
+
for (const bundle of result.candidates) {
|
|
175
|
+
lines.push(
|
|
176
|
+
format_bundle_heading(bundle),
|
|
177
|
+
...bundle.children.map((child) => format_child(child, current_repo)),
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
lines.push(
|
|
182
|
+
...format_group(' Waiting on time:', result.waiting, current_repo),
|
|
183
|
+
...format_group(' Waiting on a person:', result.blocked_on_people, current_repo),
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return lines.join('\n')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const epic_report = {
|
|
190
|
+
bundle_by_repo,
|
|
191
|
+
format_bundle_heading,
|
|
192
|
+
decide_verdict,
|
|
193
|
+
build_result,
|
|
194
|
+
candidates_for_repo,
|
|
195
|
+
format_result,
|
|
196
|
+
VERDICT_LINES,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export type { EpicNextResult, EpicVerdict, RepoCandidates }
|
|
200
|
+
export { epic_report }
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { readdirSync } from 'node:fs'
|
|
3
|
+
import { availableParallelism } from 'node:os'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { PLATFORM_TEMP_ROOT } from '#scripts/josh/platform-temporary'
|
|
6
|
+
import { process_identity } from '#scripts/josh/process-identity'
|
|
7
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
8
|
+
import { z } from 'zod'
|
|
9
|
+
|
|
10
|
+
// A machine-wide weighted core budget with admission control (joshuafolkken/kit#2351).
|
|
11
|
+
//
|
|
12
|
+
// **The gate's CPU budget used to be decided once, at the gate's start, and never revisited.**
|
|
13
|
+
// `announce_gate_plan` counted the unit runs alive the instant it began and sized itself against that
|
|
14
|
+
// one reading — so the common case (nothing else in a gate yet) had every gate conclude it was alone
|
|
15
|
+
// and reserve the whole machine, and only a gate that *started* later deferred. Three overlapping gates
|
|
16
|
+
// therefore demanded thirty cores of an eleven-core machine, which is the "usually fine, occasionally
|
|
17
|
+
// saturates" this module removes.
|
|
18
|
+
//
|
|
19
|
+
// **The fix is admission rather than recomputation.** A heavy step declares the cores it needs, claims
|
|
20
|
+
// a place in a machine-wide ledger, and waits while the ledger is full — so the peak cannot exceed the
|
|
21
|
+
// budget by construction, and the asymmetry ("whoever started first took everything") disappears
|
|
22
|
+
// because a place is claimed in claim order rather than seized at start. Waiting is what replaces the
|
|
23
|
+
// recomputation `unit-worker-share.ts` did: a step that could not fit does not shrink, it defers.
|
|
24
|
+
//
|
|
25
|
+
// **A solo run is bit-for-bit unchanged, and that is arithmetic rather than a branch.** The gate's
|
|
26
|
+
// weights are its `reserved_cores` (the static checks) and its `unit_worker_cap` (the unit suite), and
|
|
27
|
+
// `reserved(2 + 1 + 1) + unit_cap(cores - 4)` is exactly `cores` — so a single gate's four claims sum
|
|
28
|
+
// to the whole budget and every one is admitted the instant it is made, with no poll and no wait. Under
|
|
29
|
+
// concurrency the same weights sum past the budget and the ledger is what holds the machine down.
|
|
30
|
+
//
|
|
31
|
+
// **Liveness is `process_identity`'s, reused rather than re-invented** (joshuafolkken/kit#1245). A run
|
|
32
|
+
// killed outright leaves its marker behind, and a ledger that trusted the file alone would fill forever
|
|
33
|
+
// and admit nothing. The pid-and-start-time pair a marker carries is the same identity the unit-run
|
|
34
|
+
// marker keeps, swept on read the moment its process is gone.
|
|
35
|
+
|
|
36
|
+
const RESERVED_PREFIX = 'josh-core-reserved-'
|
|
37
|
+
const RESERVED_SUFFIX = '.json'
|
|
38
|
+
// How often a waiting reservation re-reads the ledger: short enough that a freed place is taken up
|
|
39
|
+
// promptly, long enough that the wait itself burns no measurable CPU.
|
|
40
|
+
const POLL_INTERVAL_MS = 50
|
|
41
|
+
// The longest a reservation waits before it is admitted at minimum width regardless — a heavy step must
|
|
42
|
+
// make progress even if the budget never clears, so a leaked or wedged sibling cannot stall the machine
|
|
43
|
+
// for good. Two minutes is well past a unit suite's worst measured time under six-way load.
|
|
44
|
+
const WAIT_CAP_MS = 120_000
|
|
45
|
+
// The head of the ledger is always admitted, so the smallest budget worth planning against is one core.
|
|
46
|
+
const MIN_BUDGET = 1
|
|
47
|
+
|
|
48
|
+
const reservation_schema = z.object({
|
|
49
|
+
pid: z.number(),
|
|
50
|
+
process_start: z.string().optional(),
|
|
51
|
+
weight: z.number(),
|
|
52
|
+
claimed_at: z.number(),
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
type Reservation = z.infer<typeof reservation_schema>
|
|
56
|
+
|
|
57
|
+
interface LiveReservation {
|
|
58
|
+
// The marker's filename, which is its identity in the ledger and the tiebreak when two reservations
|
|
59
|
+
// share a claim time.
|
|
60
|
+
key: string
|
|
61
|
+
reservation: Reservation
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
interface ReserveOptions {
|
|
65
|
+
budget?: number
|
|
66
|
+
wait_cap_ms?: number
|
|
67
|
+
poll_interval_ms?: number
|
|
68
|
+
directory?: string
|
|
69
|
+
now?: () => number
|
|
70
|
+
sleep?: (ms: number) => Promise<void>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface Handle {
|
|
74
|
+
target: string
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function marker_name(key: string): string {
|
|
78
|
+
return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// **"Cannot tell" counts as live**, the same direction `unit-worker-share.ts` takes: being wrong that
|
|
82
|
+
// way costs a reservation a slower admission, while the other way admits past a run that is still there.
|
|
83
|
+
function is_running(reservation: Reservation): boolean {
|
|
84
|
+
return process_identity.is_same_process(reservation.pid, reservation.process_start) !== false
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function read_reservation(source: string): Reservation | undefined {
|
|
88
|
+
const raw = stamp_file.read_stamp_text(source)
|
|
89
|
+
|
|
90
|
+
if (raw === undefined) return undefined
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const parsed = reservation_schema.safeParse(JSON.parse(raw))
|
|
94
|
+
|
|
95
|
+
return parsed.success ? parsed.data : undefined
|
|
96
|
+
} catch {
|
|
97
|
+
return undefined
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// **A dead marker is removed, not merely skipped** — otherwise a reissued pid turns a leaked place into
|
|
102
|
+
// a phantom that fills the budget for good. The unlink never throws: a marker this account may not
|
|
103
|
+
// remove is left alone, exactly as `unit-worker-share.ts` leaves it.
|
|
104
|
+
function sweep_marker(source: string): void {
|
|
105
|
+
try {
|
|
106
|
+
stamp_file.remove_stamp(source)
|
|
107
|
+
} catch {
|
|
108
|
+
/* not ours to remove; counting it out is the whole requirement */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function live_reservation(source: string): Reservation | undefined {
|
|
113
|
+
const reservation = read_reservation(source)
|
|
114
|
+
|
|
115
|
+
if (reservation === undefined) return undefined
|
|
116
|
+
if (is_running(reservation)) return reservation
|
|
117
|
+
|
|
118
|
+
sweep_marker(source)
|
|
119
|
+
|
|
120
|
+
return undefined
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// An unreadable temp directory answers "no other reservation", the direction that admits rather than
|
|
124
|
+
// stalls a run on a guess.
|
|
125
|
+
function marker_files(directory: string): Array<string> {
|
|
126
|
+
try {
|
|
127
|
+
return readdirSync(directory).filter((name) => name.startsWith(RESERVED_PREFIX))
|
|
128
|
+
} catch {
|
|
129
|
+
return []
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function live_reservations(directory: string = PLATFORM_TEMP_ROOT): Array<LiveReservation> {
|
|
134
|
+
return marker_files(directory).flatMap((name) => {
|
|
135
|
+
const reservation = live_reservation(path.join(directory, name))
|
|
136
|
+
|
|
137
|
+
return reservation === undefined ? [] : [{ key: name, reservation }]
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Claim order, with the filename as the tiebreak so every reader agrees on the same ledger order
|
|
142
|
+
// however the wall clock rounded two near-simultaneous claims.
|
|
143
|
+
function compare_claim(left: LiveReservation, right: LiveReservation): number {
|
|
144
|
+
const by_time = left.reservation.claimed_at - right.reservation.claimed_at
|
|
145
|
+
|
|
146
|
+
return by_time === 0 ? left.key.localeCompare(right.key) : by_time
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// **The keys admitted under FIFO.** The head always runs — a single check heavier than the whole
|
|
150
|
+
// machine must not wait for room that will never come — and each later reservation runs while the
|
|
151
|
+
// cumulative weight ahead of it still fits the budget. The first that does not fit stops the walk, so a
|
|
152
|
+
// place is never jumped: admission is in claim order, which is what removes the start-time asymmetry.
|
|
153
|
+
function admitted_keys(reservations: ReadonlyArray<LiveReservation>, budget: number): Set<string> {
|
|
154
|
+
const admitted = new Set<string>()
|
|
155
|
+
let cumulative = 0
|
|
156
|
+
|
|
157
|
+
for (const [index, entry] of reservations.toSorted(compare_claim).entries()) {
|
|
158
|
+
cumulative += entry.reservation.weight
|
|
159
|
+
|
|
160
|
+
if (index !== 0 && cumulative > budget) break
|
|
161
|
+
|
|
162
|
+
admitted.add(entry.key)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return admitted
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function is_admitted(
|
|
169
|
+
key: string,
|
|
170
|
+
reservations: ReadonlyArray<LiveReservation>,
|
|
171
|
+
budget: number,
|
|
172
|
+
): boolean {
|
|
173
|
+
return admitted_keys(reservations, budget).has(key)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// The weight actually running at once — what the reproduction test asserts stays within the budget.
|
|
177
|
+
function admitted_load(reservations: ReadonlyArray<LiveReservation>, budget: number): number {
|
|
178
|
+
const admitted = admitted_keys(reservations, budget)
|
|
179
|
+
|
|
180
|
+
return reservations
|
|
181
|
+
.filter((entry) => admitted.has(entry.key))
|
|
182
|
+
.reduce((total, entry) => total + entry.reservation.weight, 0)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// `Math.max` propagates `NaN` rather than clamping it, so an unusable budget is caught before it could
|
|
186
|
+
// make every comparison false and admit everything — the hole `gate-plan.ts` closes for the same reason.
|
|
187
|
+
function normalize_budget(budget: number): number {
|
|
188
|
+
return Number.isFinite(budget) ? Math.max(MIN_BUDGET, Math.floor(budget)) : MIN_BUDGET
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async function default_sleep(ms: number): Promise<void> {
|
|
192
|
+
await new Promise<void>((resolve) => {
|
|
193
|
+
setTimeout(resolve, ms)
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function write_reservation(target: string, weight: number, claimed_at: number): void {
|
|
198
|
+
stamp_file.write_stamp(target, { ...process_identity.own_fields(), weight, claimed_at })
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// The clock and cadence a wait runs on, resolved apart from the ledger fields so `reserve` stays under
|
|
202
|
+
// the complexity limit — each default is a branch, and six in one function is past it.
|
|
203
|
+
interface TimingConfig {
|
|
204
|
+
now: () => number
|
|
205
|
+
sleep: (ms: number) => Promise<void>
|
|
206
|
+
poll_interval_ms: number
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
interface WaitContext extends TimingConfig {
|
|
210
|
+
key: string
|
|
211
|
+
directory: string
|
|
212
|
+
budget: number
|
|
213
|
+
deadline: number
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function resolve_timing(options: ReserveOptions): TimingConfig {
|
|
217
|
+
return {
|
|
218
|
+
now: options.now ?? Date.now,
|
|
219
|
+
sleep: options.sleep ?? default_sleep,
|
|
220
|
+
poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS,
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Poll the ledger until this reservation is admitted, or until the wait cap admits it at minimum width.
|
|
225
|
+
// A solo run is admitted on the first read — its own claim is the ledger's head — so the loop body never
|
|
226
|
+
// runs and the wait costs nothing.
|
|
227
|
+
async function await_admission(context: WaitContext): Promise<void> {
|
|
228
|
+
while (!is_admitted(context.key, live_reservations(context.directory), context.budget)) {
|
|
229
|
+
if (context.now() >= context.deadline) return
|
|
230
|
+
|
|
231
|
+
await context.sleep(context.poll_interval_ms)
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function reserve(weight: number, options: ReserveOptions = {}): Promise<Handle> {
|
|
236
|
+
const timing = resolve_timing(options)
|
|
237
|
+
const directory = options.directory ?? PLATFORM_TEMP_ROOT
|
|
238
|
+
const budget = normalize_budget(options.budget ?? availableParallelism())
|
|
239
|
+
const claimed_at = timing.now()
|
|
240
|
+
const name = marker_name(randomUUID())
|
|
241
|
+
const target = path.join(directory, name)
|
|
242
|
+
|
|
243
|
+
write_reservation(target, weight, claimed_at)
|
|
244
|
+
await await_admission({
|
|
245
|
+
...timing,
|
|
246
|
+
key: name,
|
|
247
|
+
directory,
|
|
248
|
+
budget,
|
|
249
|
+
deadline: claimed_at + (options.wait_cap_ms ?? WAIT_CAP_MS),
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return { target }
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function release(handle: Handle): void {
|
|
256
|
+
sweep_marker(handle.target)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// The whole reservation lifetime around a step: claim a place, wait for admission, run, and free the
|
|
260
|
+
// place on any exit. `finally`, so a step that threw still releases its cores.
|
|
261
|
+
async function with_core_reservation<T>(
|
|
262
|
+
weight: number,
|
|
263
|
+
run: () => Promise<T>,
|
|
264
|
+
options: ReserveOptions = {},
|
|
265
|
+
): Promise<T> {
|
|
266
|
+
const handle = await reserve(weight, options)
|
|
267
|
+
|
|
268
|
+
try {
|
|
269
|
+
return await run()
|
|
270
|
+
} finally {
|
|
271
|
+
release(handle)
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const core_budget = {
|
|
276
|
+
MIN_BUDGET,
|
|
277
|
+
POLL_INTERVAL_MS,
|
|
278
|
+
RESERVED_PREFIX,
|
|
279
|
+
WAIT_CAP_MS,
|
|
280
|
+
admitted_keys,
|
|
281
|
+
admitted_load,
|
|
282
|
+
is_admitted,
|
|
283
|
+
is_running,
|
|
284
|
+
live_reservations,
|
|
285
|
+
read_reservation,
|
|
286
|
+
release,
|
|
287
|
+
reserve,
|
|
288
|
+
with_core_reservation,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export type { LiveReservation, Reservation, ReserveOptions }
|
|
292
|
+
export { core_budget }
|