@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,294 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ALREADY_DONE_LABEL,
|
|
3
|
+
has_label_name,
|
|
4
|
+
IN_PROGRESS_LABEL,
|
|
5
|
+
NEEDS_DECISION_LABEL,
|
|
6
|
+
} from '#scripts/git/issue-labels'
|
|
7
|
+
import { epic_graph, type EpicChild, type IssueReference } from './epic-graph'
|
|
8
|
+
import { epic_nested } from './epic-nested'
|
|
9
|
+
import {
|
|
10
|
+
epic_outside_blocker,
|
|
11
|
+
type DependencyVerdict,
|
|
12
|
+
type OutsideNotice,
|
|
13
|
+
type ResolveDependency,
|
|
14
|
+
} from './epic-outside-blocker'
|
|
15
|
+
|
|
16
|
+
// Sorting an epic's open children into what a caller should do about them.
|
|
17
|
+
//
|
|
18
|
+
// The categories are decided by *whether waiting helps*, never by which label a child carries. The
|
|
19
|
+
// difference is not academic: the moment kit's child closes and app-kit's child is waiting for the
|
|
20
|
+
// release to publish, there is no runnable child, nothing carries `in-progress` (kit's child is
|
|
21
|
+
// closed) and nothing carries `needs-decision` (nothing was parked). A label-based reading sees
|
|
22
|
+
// "nothing running, nothing parked" and stops — in the one situation where it should wait
|
|
23
|
+
// (joshuafolkken/kit#860).
|
|
24
|
+
|
|
25
|
+
// What a caller does with a child: run it, wait for it, or stop and report it.
|
|
26
|
+
type ChildCategory = 'runnable' | 'time' | 'human' | 'done'
|
|
27
|
+
|
|
28
|
+
// `DependencyVerdict` and `ResolveDependency` live in `epic-outside-blocker.ts`, which weighs a
|
|
29
|
+
// blocker no graph tracks with the same resolver (joshuafolkken/kit#1943), and are re-exported below.
|
|
30
|
+
|
|
31
|
+
interface Classification {
|
|
32
|
+
runnable: ReadonlyArray<EpicChild>
|
|
33
|
+
time: ReadonlyArray<EpicChild>
|
|
34
|
+
human: ReadonlyArray<EpicChild>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const CLOSED = 'CLOSED'
|
|
38
|
+
|
|
39
|
+
// The default resolver: a closed blocker is resolved, anything else defers to the blocker itself.
|
|
40
|
+
function resolve_by_state(blocker: EpicChild): DependencyVerdict {
|
|
41
|
+
return blocker.state === CLOSED ? 'resolved' : 'inherit'
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Case-insensitive, through the shared comparison rather than `Array.includes`. GitHub keeps the
|
|
45
|
+
// casing a label was created with and treats `Epic` and `epic` as one label, so a repository that
|
|
46
|
+
// predates these scripts can answer with either spelling — and a child read by eye against the
|
|
47
|
+
// lowercase string is one this classification never sees (`scripts/git/issue-labels.ts`).
|
|
48
|
+
function has_label(child: EpicChild, label: string): boolean {
|
|
49
|
+
return has_label_name(child.labels, label)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The labels that put a child in `human` on their own. `needs-decision` waits for an answer nobody
|
|
53
|
+
// has given; `already-done` has its answer — the work is merged, and the close that is left is Tier C
|
|
54
|
+
// and so a person's (joshuafolkken/kit#1679). Neither is resolved by waiting, which is what separates
|
|
55
|
+
// them from `in-progress` below.
|
|
56
|
+
const HUMAN_LABELS: ReadonlyArray<string> = [NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL]
|
|
57
|
+
|
|
58
|
+
function has_human_label(child: EpicChild): boolean {
|
|
59
|
+
return HUMAN_LABELS.some((label) => has_label(child, label))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// What a child is before its dependencies are considered. A parked child is `human` whatever blocks
|
|
63
|
+
// it, and a child already being worked on is `time` — someone else's session will finish it.
|
|
64
|
+
//
|
|
65
|
+
// **A child that is itself an epic is `human`** (joshuafolkken/kit#1476). An epic is not a unit of
|
|
66
|
+
// work, so a run handed one has nothing to implement; before this the row fell straight through to
|
|
67
|
+
// `from_blockers`, which mints `runnable` for anything unblocked, and `epicrun` passed the epic to
|
|
68
|
+
// `fullrun` as an ordinary issue. `human` rather than `time` because no amount of waiting turns an
|
|
69
|
+
// epic into work: a person has to flatten the row or restructure the epics, and meta-epic support is
|
|
70
|
+
// frozen (joshuafolkken/kit#894). What the question is — and, just as importantly, what it is not —
|
|
71
|
+
// is `epic-nested.ts`, which the audit asks the same way.
|
|
72
|
+
function local_category(child: EpicChild): ChildCategory | undefined {
|
|
73
|
+
if (child.state === CLOSED) return 'done'
|
|
74
|
+
if (epic_nested.is_nested_epic(child) || has_human_label(child)) return 'human'
|
|
75
|
+
if (has_label(child, IN_PROGRESS_LABEL)) return 'time'
|
|
76
|
+
|
|
77
|
+
return undefined
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// A blocker's category, as it applies to whatever it blocks. A blocker that is runnable or already
|
|
81
|
+
// done is one that waiting resolves, so it reads as `time` for the child behind it.
|
|
82
|
+
function inherited_category(blocker_category: ChildCategory): ChildCategory {
|
|
83
|
+
return blocker_category === 'human' ? 'human' : 'time'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// What one dependency contributes: nothing when resolved, otherwise the category it forces.
|
|
87
|
+
function dependency_category(
|
|
88
|
+
verdict: DependencyVerdict,
|
|
89
|
+
blocker_category: ChildCategory,
|
|
90
|
+
): ChildCategory | undefined {
|
|
91
|
+
if (verdict === 'resolved') return undefined
|
|
92
|
+
if (verdict === 'inherit') return inherited_category(blocker_category)
|
|
93
|
+
|
|
94
|
+
return verdict
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// The context one classification pass carries: the graph, the resolver, and the answers so far.
|
|
98
|
+
interface ClassifyContext {
|
|
99
|
+
index: ReadonlyMap<string, EpicChild>
|
|
100
|
+
resolve: ResolveDependency
|
|
101
|
+
// Keyed by identity — repository plus number — because two children of one epic can share a
|
|
102
|
+
// number across repositories (joshuafolkken/kit#864).
|
|
103
|
+
memo: Map<string, ChildCategory>
|
|
104
|
+
// Every issue this invocation may run, keyed like `index` (joshuafolkken/kit#1943). A blocker
|
|
105
|
+
// outside `index` waits when it is in here and goes to a person when it is not.
|
|
106
|
+
running: ReadonlySet<string>
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Announced once per invocation rather than once per pass. One `epic:next --repo` classifies the same
|
|
110
|
+
// children several times — the report, the candidate confirmation, and once per candidate it withholds
|
|
111
|
+
// — so an unguarded warning said the same thing up to four times, in two wordings.
|
|
112
|
+
const reported = new Set<string>()
|
|
113
|
+
|
|
114
|
+
// Discard what has been announced. Called once per command invocation, beside
|
|
115
|
+
// `epic_cross_repo.reset_publish_cache`, for the same reason: a long-lived process must not go quiet
|
|
116
|
+
// about a relation it is still ignoring.
|
|
117
|
+
function reset_reported(): void {
|
|
118
|
+
reported.clear()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function report_notice(notice: OutsideNotice): void {
|
|
122
|
+
if (reported.has(notice.key)) return
|
|
123
|
+
|
|
124
|
+
reported.add(notice.key)
|
|
125
|
+
console.warn(notice.message)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// A blocker no graph in this invocation tracks. It used to be announced and dropped, which offered a
|
|
129
|
+
// child waiting on another epic's open issue as runnable; it is weighed now, and what could not be
|
|
130
|
+
// decided is still said out loud (joshuafolkken/kit#1126, joshuafolkken/kit#1943).
|
|
131
|
+
function outside_category(
|
|
132
|
+
child: EpicChild,
|
|
133
|
+
reference: IssueReference,
|
|
134
|
+
context: ClassifyContext,
|
|
135
|
+
): ChildCategory | undefined {
|
|
136
|
+
const answer = epic_outside_blocker.outside_category(
|
|
137
|
+
child,
|
|
138
|
+
reference,
|
|
139
|
+
context.resolve,
|
|
140
|
+
context.running,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
if (answer.notice !== undefined) report_notice(answer.notice)
|
|
144
|
+
|
|
145
|
+
return answer.category
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Said out loud because the report cannot say it: a withheld epic prints as a bare `#N` under
|
|
149
|
+
// "Waiting on a person", which is true of a parked issue and of an epic alike, and the two need
|
|
150
|
+
// entirely different things done to them (joshuafolkken/kit#1476).
|
|
151
|
+
function report_nested_epic(child: EpicChild): void {
|
|
152
|
+
const line = `epic:${epic_graph.key_of(child)}`
|
|
153
|
+
if (reported.has(line)) return
|
|
154
|
+
|
|
155
|
+
reported.add(line)
|
|
156
|
+
console.warn(
|
|
157
|
+
`⚠ ${epic_graph.key_of(child)} is itself an epic — a run cannot implement one, ` +
|
|
158
|
+
'so it is withheld rather than offered',
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Announced once per classification pass, deduplicated by `reported` like every other notice here.
|
|
163
|
+
// Closed children are skipped: a finished epic is the part of the graph nobody has to act on.
|
|
164
|
+
function report_nested_epics(children: ReadonlyArray<EpicChild>): void {
|
|
165
|
+
for (const child of children) {
|
|
166
|
+
if (child.state !== CLOSED && epic_nested.is_nested_epic(child)) report_nested_epic(child)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// What one recorded relation contributes. A blocker inside the epic is resolved through the caller's
|
|
171
|
+
// resolver; one outside it is weighed against what this invocation runs.
|
|
172
|
+
function relation_category(
|
|
173
|
+
child: EpicChild,
|
|
174
|
+
blocker_reference: IssueReference,
|
|
175
|
+
context: ClassifyContext,
|
|
176
|
+
): ChildCategory | undefined {
|
|
177
|
+
const blocker = context.index.get(epic_graph.blocker_key(blocker_reference))
|
|
178
|
+
|
|
179
|
+
if (blocker === undefined) return outside_category(child, blocker_reference, context)
|
|
180
|
+
|
|
181
|
+
return dependency_category(
|
|
182
|
+
context.resolve(blocker, child),
|
|
183
|
+
context.memo.get(epic_graph.key_of(blocker)) ?? 'time',
|
|
184
|
+
)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// The categories every blocker inside the epic forces on `child`. Reads the memo rather than
|
|
188
|
+
// recursing: the loop below categorizes in dependency order, so every blocker already has an answer.
|
|
189
|
+
function blocker_categories(child: EpicChild, context: ClassifyContext): Array<ChildCategory> {
|
|
190
|
+
return child.blocked_by
|
|
191
|
+
.map((blocker) => relation_category(child, blocker, context))
|
|
192
|
+
.filter((category): category is ChildCategory => category !== undefined)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// The category the blockers add up to. `human` wins over `time`: a child waiting on both a parked
|
|
196
|
+
// blocker and a running one cannot proceed on time alone, and calling it merely waiting would have
|
|
197
|
+
// a caller wait for something only a person can release.
|
|
198
|
+
function from_blockers(categories: ReadonlyArray<ChildCategory>): ChildCategory {
|
|
199
|
+
if (categories.includes('human')) return 'human'
|
|
200
|
+
|
|
201
|
+
return categories.length > 0 ? 'time' : 'runnable'
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function compute_category(child: EpicChild, context: ClassifyContext): ChildCategory {
|
|
205
|
+
return local_category(child) ?? from_blockers(blocker_categories(child, context))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Whether every blocker of `node` inside the epic already has a category.
|
|
209
|
+
function is_ready(node: string, context: ClassifyContext): boolean {
|
|
210
|
+
return epic_graph
|
|
211
|
+
.blockers_of(context.index, node)
|
|
212
|
+
.every((blocker) => !context.index.has(blocker) || context.memo.has(blocker))
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Categorize in dependency order by peeling, the same way the cycle check does. Iterative on
|
|
216
|
+
// purpose: the recursive form is a mutually recursive pair, and a cycle would make it never return.
|
|
217
|
+
function fill_memo(children: ReadonlyArray<EpicChild>, context: ClassifyContext): void {
|
|
218
|
+
const pending = new Set(children.map((child) => epic_graph.key_of(child)))
|
|
219
|
+
|
|
220
|
+
const peel = (): number => {
|
|
221
|
+
const ready = [...pending].filter((node) => is_ready(node, context))
|
|
222
|
+
|
|
223
|
+
for (const node of ready) {
|
|
224
|
+
const child = context.index.get(node)
|
|
225
|
+
|
|
226
|
+
if (child !== undefined) context.memo.set(node, compute_category(child, context))
|
|
227
|
+
pending.delete(node)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return ready.length
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
while (peel() > 0) {
|
|
234
|
+
/* keep going until a pass categorizes nothing */
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Only a cycle leaves anything here, and `find_anomalies` rejects one before this runs. Marking
|
|
238
|
+
// the remainder as waiting rather than dropping it keeps the buckets accounting for every child.
|
|
239
|
+
for (const node of pending) context.memo.set(node, 'time')
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Every open child, sorted. Closed children are simply absent — they are the part of the epic that
|
|
243
|
+
// is finished, and a caller has nothing to do with them.
|
|
244
|
+
//
|
|
245
|
+
// `running` defaults to these children alone, which is one epic's answer; a caller that runs several
|
|
246
|
+
// graphs, or a backlog, passes the whole set so a blocker in another of them waits rather than stops.
|
|
247
|
+
function new_context(
|
|
248
|
+
children: ReadonlyArray<EpicChild>,
|
|
249
|
+
resolve: ResolveDependency = resolve_by_state,
|
|
250
|
+
running: ReadonlySet<string> = epic_outside_blocker.running_keys(children),
|
|
251
|
+
): ClassifyContext {
|
|
252
|
+
return {
|
|
253
|
+
index: epic_graph.index_children(children),
|
|
254
|
+
resolve,
|
|
255
|
+
memo: new Map<string, ChildCategory>(),
|
|
256
|
+
running,
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function classify_children(
|
|
261
|
+
children: ReadonlyArray<EpicChild>,
|
|
262
|
+
resolve?: ResolveDependency,
|
|
263
|
+
running?: ReadonlySet<string>,
|
|
264
|
+
): Classification {
|
|
265
|
+
const context = new_context(children, resolve, running)
|
|
266
|
+
const buckets: Record<'runnable' | 'time' | 'human', Array<EpicChild>> = {
|
|
267
|
+
runnable: [],
|
|
268
|
+
time: [],
|
|
269
|
+
human: [],
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
fill_memo(children, context)
|
|
273
|
+
report_nested_epics(children)
|
|
274
|
+
|
|
275
|
+
for (const child of children) {
|
|
276
|
+
const category = context.memo.get(epic_graph.key_of(child)) ?? 'time'
|
|
277
|
+
|
|
278
|
+
if (category !== 'done') buckets[category].push(child)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return buckets
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const epic_classify = {
|
|
285
|
+
resolve_by_state,
|
|
286
|
+
reset_reported,
|
|
287
|
+
local_category,
|
|
288
|
+
classify_children,
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export type { Classification, ChildCategory }
|
|
292
|
+
export { epic_classify }
|
|
293
|
+
|
|
294
|
+
export { type DependencyVerdict, type ResolveDependency } from './epic-outside-blocker'
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import { repo_map_logic } from '#scripts/discovery/repo-map-logic'
|
|
2
|
+
import { repo_origin } from '#scripts/discovery/repo-origin'
|
|
3
|
+
import { git_gh_api_path } from '#scripts/git/git-gh-api-path'
|
|
4
|
+
import { git_gh_exec } from '#scripts/git/git-gh-exec'
|
|
5
|
+
import { propagate_publish } from '#scripts/propagate/propagate-publish'
|
|
6
|
+
import { derive_versions_endpoint } from '#scripts/version/version-command-config'
|
|
7
|
+
import { execaSync } from 'execa'
|
|
8
|
+
import { load } from 'js-yaml'
|
|
9
|
+
import type { DependencyVerdict } from './epic-classify'
|
|
10
|
+
import type { EpicChild } from './epic-graph'
|
|
11
|
+
|
|
12
|
+
// Resolving a dependency that crosses a repository boundary.
|
|
13
|
+
//
|
|
14
|
+
// `blocked-by` is satisfied the moment the blocking issue closes, and across repositories that is
|
|
15
|
+
// too early. Merging kit's issue does not publish kit — the merge, the auto-tag and the publish run
|
|
16
|
+
// one after another — so a consumer child told it may start at that moment either fails to install
|
|
17
|
+
// the version it needs or, worse, installs the previous one and implements against it. That failure
|
|
18
|
+
// shows up as "it breaks sometimes", which is the hardest kind to diagnose (joshuafolkken/kit#864).
|
|
19
|
+
//
|
|
20
|
+
// The publish check itself is joshuafolkken/kit#863's, imported rather than restated: two
|
|
21
|
+
// implementations of "has this version appeared" would drift, and the looser one would decide.
|
|
22
|
+
|
|
23
|
+
// The package a repository distributes, by convention: the npm scope is the GitHub owner and the
|
|
24
|
+
// package name is the repository name. Every first-party repository follows it, and the version
|
|
25
|
+
// command already derives its registry endpoint the same way.
|
|
26
|
+
function package_name_for(repo: string): string | undefined {
|
|
27
|
+
const identity = repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${repo}`)
|
|
28
|
+
if (identity === undefined) return undefined
|
|
29
|
+
|
|
30
|
+
return `@${identity.owner}/${identity.repo}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// The registry answer per repository, for one classification pass. Several children commonly depend
|
|
34
|
+
// on the same blocker, and each edge would otherwise spawn its own blocking `gh` call for an answer
|
|
35
|
+
// that cannot have changed in between.
|
|
36
|
+
const published_cache = new Map<string, ReadonlyArray<string> | undefined>()
|
|
37
|
+
|
|
38
|
+
function fetch_versions_for(repo: string): ReadonlyArray<string> | undefined {
|
|
39
|
+
const package_name = package_name_for(repo)
|
|
40
|
+
if (package_name === undefined) return undefined
|
|
41
|
+
|
|
42
|
+
return propagate_publish.fetch_published_versions(derive_versions_endpoint(package_name))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function published_versions(repo: string): ReadonlyArray<string> | undefined {
|
|
46
|
+
if (published_cache.has(repo)) return published_cache.get(repo)
|
|
47
|
+
const versions = fetch_versions_for(repo)
|
|
48
|
+
|
|
49
|
+
published_cache.set(repo, versions)
|
|
50
|
+
|
|
51
|
+
return versions
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// The default-branch version per repository — the other half of the answer `published_cache` holds,
|
|
55
|
+
// cached for the same reason and cleared with it.
|
|
56
|
+
const version_cache = new Map<string, ManifestAnswer>()
|
|
57
|
+
|
|
58
|
+
// Discard the cached registry and manifest answers. A long-lived process — an `epicrun` polling every
|
|
59
|
+
// minute — must see a release that appeared since its last round.
|
|
60
|
+
function reset_publish_cache(): void {
|
|
61
|
+
published_cache.clear()
|
|
62
|
+
version_cache.clear()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Whether a version of the blocker's package has appeared in the registry.
|
|
66
|
+
function is_published(repo: string, version: string): boolean {
|
|
67
|
+
const versions = published_versions(repo)
|
|
68
|
+
if (versions === undefined) return false
|
|
69
|
+
|
|
70
|
+
return propagate_publish.is_version_published(versions, version)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const GH_TIMEOUT_MS = 20_000
|
|
74
|
+
const SUCCESS_EXIT_CODE = 0
|
|
75
|
+
// The manifest arrives base64-encoded in the API's `content` field; `jq` decodes and reads it.
|
|
76
|
+
const VERSION_JQ = '.content | @base64d | fromjson | {version, private, workspaces} | tojson'
|
|
77
|
+
const PNPM_WORKSPACE_FILE = 'pnpm-workspace.yaml'
|
|
78
|
+
const WORKSPACE_JQ = '.content | @base64d'
|
|
79
|
+
const NOT_FOUND_STATUS = 404
|
|
80
|
+
|
|
81
|
+
// What the blocker repository's default branch says about what it ships.
|
|
82
|
+
//
|
|
83
|
+
// **`absent` is not `unreadable`, and joshuafolkken/kit#1129 is the difference.** A repository with no
|
|
84
|
+
// manifest, or one whose manifest says `private`, publishes nothing — so a closed blocker there has
|
|
85
|
+
// no release anyone could wait for, and waiting means waiting until the run's own eight-hour timeout
|
|
86
|
+
// with nothing an operator can edit to clear it. A read that merely failed says none of that.
|
|
87
|
+
//
|
|
88
|
+
// **It is read from the repository rather than from the registry, and that is the whole design.** The
|
|
89
|
+
// registry answers 404 both for a package that was never published *and* for one this token may not
|
|
90
|
+
// see — a renamed repository, a private package, a missing `read:packages` scope — so resolving on a
|
|
91
|
+
// registry 404 would start a consumer child before its blocker's release existed. The manifest is a
|
|
92
|
+
// fact about the repository we already have access to, and `private: true` is a positive statement
|
|
93
|
+
// rather than an inference from an absence.
|
|
94
|
+
// **`private` alone does not settle it** (joshuafolkken/kit#1134). A workspace root is private by
|
|
95
|
+
// convention while the packages under it publish, so reading one as "ships nothing" would resolve a
|
|
96
|
+
// dependency before its blocker's release existed — the direction this module may not fail in.
|
|
97
|
+
// `is_workspace` is what keeps that case waiting.
|
|
98
|
+
type ManifestAnswer =
|
|
99
|
+
| { kind: 'manifest'; version: string | undefined; is_private: boolean; is_workspace: boolean }
|
|
100
|
+
| { kind: 'absent' }
|
|
101
|
+
| { kind: 'unreadable' }
|
|
102
|
+
|
|
103
|
+
// The version another repository's default branch declares — the last one it published.
|
|
104
|
+
//
|
|
105
|
+
// Read from GitHub rather than from a local checkout: a consumer's state is a GitHub fact, and the
|
|
106
|
+
// wait must work before anyone has cloned the repository.
|
|
107
|
+
//
|
|
108
|
+
// **It moves when `josh release` runs, not when a child merges** (joshuafolkken/kit#1486). A child's
|
|
109
|
+
// pull request carries no version change at all, so the number here right after one merges is still
|
|
110
|
+
// the previous release. The target of a wait is therefore the version that follows the release the
|
|
111
|
+
// change lands in, never the one the merge itself leaves behind.
|
|
112
|
+
//
|
|
113
|
+
// Never "whatever is newest": a consumer several releases behind would be satisfied by any publish
|
|
114
|
+
// at all, including one that predates the change it is waiting for.
|
|
115
|
+
function manifest_path(repo: string): string {
|
|
116
|
+
return `${git_gh_api_path.repo_api_path(repo)}/contents/package.json`
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// What the layout question answered. `unreadable` is a third answer rather than a boolean's loser:
|
|
120
|
+
// a probe that failed says nothing about the layout, and laundering it into "is a workspace" turns
|
|
121
|
+
// one transient read into a permanent wait.
|
|
122
|
+
type WorkspaceCheck = 'workspace' | 'single' | 'unreadable'
|
|
123
|
+
|
|
124
|
+
// Whether `pnpm-workspace.yaml` actually declares members.
|
|
125
|
+
//
|
|
126
|
+
// **The file's existence proves nothing.** `josh sync` distributes it to every consumer regardless of
|
|
127
|
+
// layout — it carries `allowBuilds`, `overrides` and the like — so probing for its presence read every
|
|
128
|
+
// private first-party repository as a workspace and restored joshuafolkken/kit#1129's eight-hour wait
|
|
129
|
+
// for all of them. Measured: 20 of 20 private first-party checkouts have the file and none declares
|
|
130
|
+
// `packages:` (joshuafolkken/kit#1134). What makes a repository a workspace is a non-empty `packages`
|
|
131
|
+
// key, so that is what is read.
|
|
132
|
+
function declares_packages(yaml: string): boolean {
|
|
133
|
+
try {
|
|
134
|
+
const parsed: unknown = load(yaml)
|
|
135
|
+
if (typeof parsed !== 'object' || parsed === null) return false
|
|
136
|
+
const { packages } = parsed as { packages?: unknown }
|
|
137
|
+
|
|
138
|
+
return Array.isArray(packages) && packages.length > 0
|
|
139
|
+
} catch {
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function pnpm_workspace_path(repo: string): string {
|
|
145
|
+
return `${git_gh_api_path.repo_api_path(repo)}/contents/${PNPM_WORKSPACE_FILE}`
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// A read that failed for any reason other than a missing file leaves the layout unknown.
|
|
149
|
+
function classify_workspace_failure(repo: string): WorkspaceCheck {
|
|
150
|
+
const probe = execaSync('gh', ['api', '--include', '--silent', pnpm_workspace_path(repo)], {
|
|
151
|
+
...git_gh_exec.direct_environment(),
|
|
152
|
+
reject: false,
|
|
153
|
+
timeout: GH_TIMEOUT_MS,
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
return git_gh_exec.parse_status_line(probe.stdout) === NOT_FOUND_STATUS ? 'single' : 'unreadable'
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function read_pnpm_workspace(repo: string): WorkspaceCheck {
|
|
160
|
+
const result = execaSync('gh', ['api', pnpm_workspace_path(repo), '--jq', WORKSPACE_JQ], {
|
|
161
|
+
...git_gh_exec.direct_environment(),
|
|
162
|
+
reject: false,
|
|
163
|
+
timeout: GH_TIMEOUT_MS,
|
|
164
|
+
})
|
|
165
|
+
if (result.exitCode !== SUCCESS_EXIT_CODE) return classify_workspace_failure(repo)
|
|
166
|
+
|
|
167
|
+
return declares_packages(result.stdout) ? 'workspace' : 'single'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Whether the repository declares a workspace. `workspaces` covers npm and yarn; pnpm keeps its
|
|
171
|
+
// members in `pnpm-workspace.yaml` and leaves the manifest without the field, so that file is read —
|
|
172
|
+
// but only in the one case where the answer can still change the verdict, which is a private root
|
|
173
|
+
// with no `workspaces` entries. A public root publishes, and a private non-workspace root does not,
|
|
174
|
+
// whatever the file would say.
|
|
175
|
+
//
|
|
176
|
+
// `null` counts as absent, not as a declaration: `jq`'s `{version, private, workspaces}` shorthand
|
|
177
|
+
// emits an explicit `"workspaces": null` for a manifest with no such key, so testing only against
|
|
178
|
+
// `undefined` read every private repository as a workspace.
|
|
179
|
+
// Whether the manifest's own `workspaces` field settles it. `null` counts as absent rather than as a
|
|
180
|
+
// declaration; an empty array is a workspace that lists nothing, which is not one.
|
|
181
|
+
function declared_workspaces(declared: unknown): WorkspaceCheck | undefined {
|
|
182
|
+
if (declared === undefined || declared === null) return undefined
|
|
183
|
+
if (Array.isArray(declared)) return declared.length > 0 ? 'workspace' : 'single'
|
|
184
|
+
|
|
185
|
+
return 'workspace'
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function workspace_check(repo: string, fields: { workspaces?: unknown }): WorkspaceCheck {
|
|
189
|
+
return declared_workspaces(fields.workspaces) ?? read_pnpm_workspace(repo)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
interface ManifestFields {
|
|
193
|
+
version?: unknown
|
|
194
|
+
private?: unknown
|
|
195
|
+
workspaces?: unknown
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// The fields read out of a manifest that parsed. `is_private` is strictly the boolean, which is the
|
|
199
|
+
// only form npm defines: a looser test — a truthy string, say — would call *more* repositories "ships
|
|
200
|
+
// nothing", and that is the unsafe direction here, because answering it wrongly resolves a dependency
|
|
201
|
+
// and starts a child before its blocker's release. A manifest that misspells `private` therefore
|
|
202
|
+
// waits, which is the failure that is merely slow rather than the one that is wrong.
|
|
203
|
+
function to_answer(repo: string, fields: ManifestFields): ManifestAnswer {
|
|
204
|
+
const version = typeof fields.version === 'string' ? fields.version : undefined
|
|
205
|
+
|
|
206
|
+
if (fields.private !== true) {
|
|
207
|
+
return { kind: 'manifest', version, is_private: false, is_workspace: false }
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const check = workspace_check(repo, fields)
|
|
211
|
+
// A layout nobody could read is not a repository that ships nothing. Answering `unreadable` keeps
|
|
212
|
+
// the dependency waiting, which is the direction that merely costs time.
|
|
213
|
+
if (check === 'unreadable') return { kind: 'unreadable' }
|
|
214
|
+
|
|
215
|
+
return { kind: 'manifest', version, is_private: true, is_workspace: check === 'workspace' }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function to_manifest(repo: string, stdout: string): ManifestAnswer {
|
|
219
|
+
try {
|
|
220
|
+
const parsed: unknown = JSON.parse(stdout.trim())
|
|
221
|
+
if (typeof parsed !== 'object' || parsed === null) return { kind: 'unreadable' }
|
|
222
|
+
|
|
223
|
+
return to_answer(repo, parsed)
|
|
224
|
+
} catch {
|
|
225
|
+
return { kind: 'unreadable' }
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Why the read failed, asked only when it did. The status line is the protocol rather than prose, so
|
|
230
|
+
// a missing manifest is told from a rate limit by matching a contract instead of a message — through
|
|
231
|
+
// `git_gh_exec.parse_status_line` rather than a second copy of it.
|
|
232
|
+
//
|
|
233
|
+
// `git_gh_exec.exec_gh_api_status` asks the same question and is **not** reused: it is async, and
|
|
234
|
+
// every caller down to `resolve_cross_repo` is synchronous. What is worth sharing is the parser,
|
|
235
|
+
// which is shared; the spawn is four lines and duplicating it costs less than turning the
|
|
236
|
+
// classifier, the resolver and `epic_classify` async for one probe. A 404 here is trustworthy in a way
|
|
237
|
+
// a registry 404 is not: the repository's issues are already being read, so access is established and
|
|
238
|
+
// what is missing is the file.
|
|
239
|
+
function classify_manifest_failure(repo: string): ManifestAnswer {
|
|
240
|
+
const probe = execaSync('gh', ['api', '--include', '--silent', manifest_path(repo)], {
|
|
241
|
+
...git_gh_exec.direct_environment(),
|
|
242
|
+
reject: false,
|
|
243
|
+
timeout: GH_TIMEOUT_MS,
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
kind:
|
|
248
|
+
git_gh_exec.parse_status_line(probe.stdout) === NOT_FOUND_STATUS ? 'absent' : 'unreadable',
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function fetch_manifest(repo: string): ManifestAnswer {
|
|
253
|
+
const result = execaSync('gh', ['api', manifest_path(repo), '--jq', VERSION_JQ], {
|
|
254
|
+
...git_gh_exec.direct_environment(),
|
|
255
|
+
reject: false,
|
|
256
|
+
timeout: GH_TIMEOUT_MS,
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
return result.exitCode === SUCCESS_EXIT_CODE
|
|
260
|
+
? to_manifest(repo, result.stdout)
|
|
261
|
+
: classify_manifest_failure(repo)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Read once per pass, for the reason `published_cache` holds the other half: every edge to one
|
|
265
|
+
// repository asks the same question, and joshuafolkken/kit#1121 made a pass run once per withheld
|
|
266
|
+
// candidate rather than once — so an uncached read is a blocking `gh` call multiplied by both.
|
|
267
|
+
function read_manifest(repo: string): ManifestAnswer {
|
|
268
|
+
const cached = version_cache.get(repo)
|
|
269
|
+
if (cached !== undefined) return cached
|
|
270
|
+
const answer = fetch_manifest(repo)
|
|
271
|
+
|
|
272
|
+
version_cache.set(repo, answer)
|
|
273
|
+
|
|
274
|
+
return answer
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// The version the default branch declares, for a caller that only wants that.
|
|
278
|
+
function read_default_branch_version(repo: string): string | undefined {
|
|
279
|
+
const answer = read_manifest(repo)
|
|
280
|
+
|
|
281
|
+
return answer.kind === 'manifest' ? answer.version : undefined
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Whether the repository ships no package at all: no manifest on its default branch, or one that
|
|
285
|
+
// declares itself private. Either way there is no release for a dependency to wait on.
|
|
286
|
+
//
|
|
287
|
+
// **A workspace root is excluded, and the exclusion is deliberately coarse** (joshuafolkken/kit#1134).
|
|
288
|
+
// Such a root is private by convention while its packages publish, so reading one as shipping nothing
|
|
289
|
+
// would start a dependent before its blocker's release existed. What is asked is only whether the
|
|
290
|
+
// repository *is* a workspace — the members are not enumerated and nothing looks for which of them
|
|
291
|
+
// publishes, so a workspace whose members are all private waits when it need not. That is the safe
|
|
292
|
+
// direction: waiting ends at the run's own timeout, resolving early does not end at all.
|
|
293
|
+
function publishes_nothing(repo: string): boolean {
|
|
294
|
+
const answer = read_manifest(repo)
|
|
295
|
+
|
|
296
|
+
if (answer.kind === 'absent') return true
|
|
297
|
+
|
|
298
|
+
return answer.kind === 'manifest' && answer.is_private && !answer.is_workspace
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// A version that could not be read leaves the dependency waiting rather than resolved: not knowing
|
|
302
|
+
// what to wait for is not the same as having nothing to wait for.
|
|
303
|
+
//
|
|
304
|
+
// **"Ships nothing" is asked first, and it is a different question** (joshuafolkken/kit#1129, the
|
|
305
|
+
// state joshuafolkken/kit#1126 made reachable). Waiting is right only where something could still
|
|
306
|
+
// arrive; a closed blocker in a repository that publishes no package has no release for
|
|
307
|
+
// `is_published` to ever find, so it waited until the run's own eight-hour timeout with nothing an
|
|
308
|
+
// operator could edit to clear it. It is answered from that repository's own manifest and never from
|
|
309
|
+
// the registry, for the reason `ManifestAnswer` records: a registry 404 also means "this token may
|
|
310
|
+
// not see it", and resolving on one would start a consumer child before its blocker's release
|
|
311
|
+
// existed.
|
|
312
|
+
function publish_verdict(repo: string, version: string | undefined): DependencyVerdict {
|
|
313
|
+
if (publishes_nothing(repo)) return 'resolved'
|
|
314
|
+
if (version === undefined) return 'time'
|
|
315
|
+
|
|
316
|
+
return is_published(repo, version) ? 'resolved' : 'time'
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// What a cross-repository dependency needs, and in what order it is asked.
|
|
320
|
+
//
|
|
321
|
+
// The evaluation is an AND, and the order matters: while the blocker is still open the registry is
|
|
322
|
+
// never consulted. An epic therefore never sits waiting on a publish from the moment it starts — the
|
|
323
|
+
// wait is "the previous child finished, now wait for its release", which is the only moment the
|
|
324
|
+
// question is meaningful.
|
|
325
|
+
function resolve_cross_repo(
|
|
326
|
+
blocker: EpicChild,
|
|
327
|
+
blocked: EpicChild,
|
|
328
|
+
read_target_version: (repo: string) => string | undefined = read_default_branch_version,
|
|
329
|
+
): DependencyVerdict {
|
|
330
|
+
if (blocker.state !== 'CLOSED') return 'inherit'
|
|
331
|
+
if (blocker.repo === blocked.repo) return 'resolved'
|
|
332
|
+
|
|
333
|
+
return publish_verdict(blocker.repo, read_target_version(blocker.repo))
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// The owner half of an `owner/repo`, in the one place that splits it. Read straight off the string
|
|
337
|
+
// rather than through a URL parse: the callers need something to hand `is_same_owner_repo`, and a
|
|
338
|
+
// repository name that does not parse fails there rather than here.
|
|
339
|
+
function owner_of(repo: string): string {
|
|
340
|
+
return repo.split('/', 1)[0] ?? ''
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Whether a repository may be depended on at all. Inherited from joshuafolkken/kit#869's
|
|
344
|
+
// restriction rather than restated: a child in a repository this owner does not own is not something
|
|
345
|
+
// to wait for, dispatch to, or write into — nor, since joshuafolkken/kit#1014, an issue reference to
|
|
346
|
+
// resolve: a body that mentions a third party's issue must not send this command to their tracker.
|
|
347
|
+
function is_same_owner_repo(repo: string, current_owner: string): boolean {
|
|
348
|
+
const identity = repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${repo}`)
|
|
349
|
+
if (identity === undefined) return false
|
|
350
|
+
|
|
351
|
+
return repo_map_logic.is_same_owner(identity, current_owner)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const epic_cross_repo = {
|
|
355
|
+
publishes_nothing,
|
|
356
|
+
read_manifest,
|
|
357
|
+
read_default_branch_version,
|
|
358
|
+
reset_publish_cache,
|
|
359
|
+
package_name_for,
|
|
360
|
+
is_published,
|
|
361
|
+
resolve_cross_repo,
|
|
362
|
+
owner_of,
|
|
363
|
+
is_same_owner_repo,
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export { epic_cross_repo }
|