@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,152 @@
|
|
|
1
|
+
import { git_command } from '#scripts/git/git-command'
|
|
2
|
+
import { git_gh_command } from '#scripts/git/git-gh-command'
|
|
3
|
+
import { git_pr_checks } from '#scripts/git/git-pr-checks'
|
|
4
|
+
import { git_remote_branch } from '#scripts/git/git-remote-branch'
|
|
5
|
+
import { write_version } from '#scripts/version/bump-version'
|
|
6
|
+
import { version_targets } from '#scripts/version/version-targets'
|
|
7
|
+
import type { ReleasePlan } from './release-plan'
|
|
8
|
+
import { release_tag } from './release-tag'
|
|
9
|
+
import { release_worktree } from './release-worktree'
|
|
10
|
+
|
|
11
|
+
// The write half of `pnpm josh release`: the branch, the commit, the pull request, the merge and the
|
|
12
|
+
// wait for the tag (joshuafolkken/kit#1169).
|
|
13
|
+
//
|
|
14
|
+
// **The merge goes through the same gate every other pull request does.** `wait_for_pr_success` is
|
|
15
|
+
// the merge gate `pnpm josh followup` waits on, and it is called here rather than reimplemented —
|
|
16
|
+
// weakening it for a release commit would open exactly the "merge without green CI" path the issue's
|
|
17
|
+
// closing note prohibits.
|
|
18
|
+
|
|
19
|
+
const { PACKAGE_JSON } = version_targets
|
|
20
|
+
const SUCCESS_EXIT_CODE = 0
|
|
21
|
+
const FAILURE_EXIT_CODE = 1
|
|
22
|
+
|
|
23
|
+
function branch_name_for(version: string): string {
|
|
24
|
+
return `release/v${version}`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function commit_message(version: string): string {
|
|
28
|
+
return `Release v${version}`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// **No `closes #N`.** A release carries whatever merged since the last one, so it closes no single
|
|
32
|
+
// issue; the mapping from issue to release is recovered from the merge commits between two tags,
|
|
33
|
+
// which is what `.github/release.yml` already classifies.
|
|
34
|
+
function pull_request_body(plan: ReleasePlan): string {
|
|
35
|
+
return [
|
|
36
|
+
`${String(plan.pending)} merge(s) have landed on main since \`${plan.base}\`, the commit that last changed the version.`,
|
|
37
|
+
'',
|
|
38
|
+
`Raising the version by that many minors: \`${plan.current_version}\` → \`${plan.next_version}\`.`,
|
|
39
|
+
'',
|
|
40
|
+
'Opened by `pnpm josh release` (joshuafolkken/kit#1169).',
|
|
41
|
+
].join('\n')
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// **A branch already there is a previous release attempt, not a name collision.** The wait for CI
|
|
45
|
+
// can throw — a timeout, a red required check, a `gh` failure — and the branch and its pull request
|
|
46
|
+
// survive it. Re-running then recomputes the same `pending`, so the branch name is identical and
|
|
47
|
+
// `git checkout -b` fails with git's own opaque message. Saying what is actually there leaves the
|
|
48
|
+
// person one decision rather than one diagnosis.
|
|
49
|
+
function existing_branch_message(branch_name: string): string {
|
|
50
|
+
return `\`${branch_name}\` already exists — a previous release attempt got as far as opening it. Finish or delete that pull request and branch, then run \`pnpm josh release\` again.`
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// **A remote that cannot be asked is refused, not read as "no branch there"** (joshuafolkken/kit#1641).
|
|
54
|
+
// `pnpm josh release` pushes, opens a pull request, merges it and waits for a tag, so it cannot
|
|
55
|
+
// finish without the remote in any case: refusing here is the failure the run was going to have
|
|
56
|
+
// anyway, moved in front of the version write and the commit — which is the whole point of this
|
|
57
|
+
// guard. Silently answering "not taken" instead would put the raw error back after two writes.
|
|
58
|
+
function unreachable_remote_message(branch_name: string): string {
|
|
59
|
+
return `Could not ask origin whether \`${branch_name}\` already exists, so \`pnpm josh release\` stops before writing the version. It needs the remote to push, open the pull request and merge it. Restore the connection and run \`pnpm josh release\` again.`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// **The remote is asked as well as the local branch.** A previous attempt pushed before it opened
|
|
63
|
+
// the pull request, so deleting the local branch — or retrying from a second checkout — leaves the
|
|
64
|
+
// remote one standing on its own. Checking only locally there lets the run write the version, commit
|
|
65
|
+
// it and reach `push`, which then fails with git's non-fast-forward message: the raw error this
|
|
66
|
+
// guard exists to replace, and now after two writes rather than before them.
|
|
67
|
+
//
|
|
68
|
+
// **`git branch --list --remotes` could not answer it, which is why origin is asked directly.** Its
|
|
69
|
+
// short names carry the remote — `origin/x`, never `x` — so the unprefixed pattern this used to pass
|
|
70
|
+
// matched nothing and the remote arm reported "absent" for every branch that has ever existed. The
|
|
71
|
+
// remote-tracking refs it reads are stale anyway, since nothing in this workflow prunes them, so
|
|
72
|
+
// `git_remote_branch.ask` puts the question to origin itself.
|
|
73
|
+
async function is_release_branch_taken(branch_name: string): Promise<boolean> {
|
|
74
|
+
if (await git_command.branch_exists(branch_name)) return true
|
|
75
|
+
|
|
76
|
+
const answer = await git_remote_branch.ask(branch_name)
|
|
77
|
+
|
|
78
|
+
if (answer === 'unreachable') throw new Error(unreachable_remote_message(branch_name))
|
|
79
|
+
|
|
80
|
+
return answer === 'present'
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function refuse_existing_branch(branch_name: string): Promise<void> {
|
|
84
|
+
if (!(await is_release_branch_taken(branch_name))) return
|
|
85
|
+
|
|
86
|
+
throw new Error(existing_branch_message(branch_name))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// **No `checkout -b` and no branch guard here** (joshuafolkken/kit#2411). The work tree is already
|
|
90
|
+
// sitting on the release branch — `release_worktree.create` cut it that way — and the guard ran
|
|
91
|
+
// before that creation, because `worktree_add` makes the branch local and `branch_exists` would then
|
|
92
|
+
// report every release as already taken. This runs after `process.chdir` into the work tree, so the
|
|
93
|
+
// version write and the git commands all act on it rather than on the root.
|
|
94
|
+
async function commit_release(plan: ReleasePlan): Promise<void> {
|
|
95
|
+
write_version(plan.next_version)
|
|
96
|
+
await git_command.add_path(PACKAGE_JSON)
|
|
97
|
+
await git_command.commit(commit_message(plan.next_version))
|
|
98
|
+
await git_command.push()
|
|
99
|
+
console.info(
|
|
100
|
+
await git_gh_command.pr_create(commit_message(plan.next_version), pull_request_body(plan)),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function merge_and_tag(plan: ReleasePlan, branch_name: string): Promise<number> {
|
|
105
|
+
await git_pr_checks.wait_for_pr_success(branch_name)
|
|
106
|
+
await git_gh_command.pr_merge(branch_name)
|
|
107
|
+
|
|
108
|
+
const is_tagged = await release_tag.wait_for_tag(plan.next_version)
|
|
109
|
+
|
|
110
|
+
console.info(release_tag.format_result(plan.next_version, is_tagged))
|
|
111
|
+
|
|
112
|
+
return is_tagged ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// The whole release happens inside a work tree cut for it, so the root checkout is never touched: the
|
|
116
|
+
// branch guard runs before the tree exists, `process.chdir` points the version write and the git
|
|
117
|
+
// commands at the tree, and the `finally` returns to the root and removes the tree — whichever way
|
|
118
|
+
// the wait ended, so a failed tag watch cleans up rather than leaving debris behind.
|
|
119
|
+
async function publish(plan: ReleasePlan): Promise<number> {
|
|
120
|
+
const branch_name = branch_name_for(plan.next_version)
|
|
121
|
+
|
|
122
|
+
await refuse_existing_branch(branch_name)
|
|
123
|
+
|
|
124
|
+
const directory = await release_worktree.create(branch_name)
|
|
125
|
+
const previous_cwd = process.cwd()
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
process.chdir(directory)
|
|
129
|
+
await commit_release(plan)
|
|
130
|
+
|
|
131
|
+
return await merge_and_tag(plan, branch_name)
|
|
132
|
+
} finally {
|
|
133
|
+
process.chdir(previous_cwd)
|
|
134
|
+
await release_worktree.remove(directory, branch_name)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const release_publish = {
|
|
139
|
+
branch_name_for,
|
|
140
|
+
commit_message,
|
|
141
|
+
existing_branch_message,
|
|
142
|
+
// Exported so the three answers the guard has to separate — here, on origin, on neither — are
|
|
143
|
+
// asserted directly rather than through `publish`, whose next step writes `package.json`.
|
|
144
|
+
is_release_branch_taken,
|
|
145
|
+
publish,
|
|
146
|
+
pull_request_body,
|
|
147
|
+
unreachable_remote_message,
|
|
148
|
+
FAILURE_EXIT_CODE,
|
|
149
|
+
SUCCESS_EXIT_CODE,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export { release_publish }
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { git_followup_pending } from '#scripts/git/git-followup-pending'
|
|
4
|
+
import { path_decision } from '#scripts/josh/path-decision'
|
|
5
|
+
import { release_plan } from './release-plan'
|
|
6
|
+
|
|
7
|
+
// **Whether a release is owed is a command's answer, not a judgement** (joshuafolkken/kit#1582).
|
|
8
|
+
//
|
|
9
|
+
// joshuafolkken/kit#1169 took the version off the branch and put it behind one command a person
|
|
10
|
+
// types, and nothing ever said *when* to type it. Nothing fails when nobody does — CI green, every
|
|
11
|
+
// pull request merged, every Issue closed — so 53 merges reached main unreleased and no consumer of
|
|
12
|
+
// this package saw one of them.
|
|
13
|
+
//
|
|
14
|
+
// **`pnpm josh release --dry-run` cannot be the check.** It refuses off the default branch and on a
|
|
15
|
+
// dirty working tree, and it counts against `HEAD`; every position a run asks the question from is
|
|
16
|
+
// a feature branch or a lane, which is exactly where it throws.
|
|
17
|
+
//
|
|
18
|
+
// **So this counts nothing of its own.** It reads the number `pnpm josh followup` already puts in
|
|
19
|
+
// the completion notification — `git_followup_pending.read_pending`, which fetches the default
|
|
20
|
+
// branch and counts `--first-parent` merges against `origin/<default>` — and turns it into a
|
|
21
|
+
// verdict. One counting path, two readers.
|
|
22
|
+
//
|
|
23
|
+
// The flag parse and the printing come from `path_decision`, the contract every mechanically-decided
|
|
24
|
+
// command here shares. Only its `parse_options` / `run_path_decision` are path-specific, and this
|
|
25
|
+
// decision is not made from changed paths, so those two are the ones left alone.
|
|
26
|
+
const ARGV_OFFSET = 2
|
|
27
|
+
const USAGE = 'Usage: josh release:scope [--json]'
|
|
28
|
+
const JSON_KEY = 'scope'
|
|
29
|
+
// Not `path_decision.KNOWN_FLAGS`: that set carries `--staged`, which means nothing here, and a
|
|
30
|
+
// command that accepts a flag it ignores answers a question nobody asked.
|
|
31
|
+
const KNOWN_FLAGS: ReadonlyArray<string> = [path_decision.JSON_FLAG]
|
|
32
|
+
const REQUIRED_SCOPE = 'required'
|
|
33
|
+
const SKIPPED_SCOPE = 'skip'
|
|
34
|
+
const UNKNOWN_SCOPE = 'unknown'
|
|
35
|
+
const SUCCESS_EXIT_CODE = 0
|
|
36
|
+
const FAILURE_EXIT_CODE = 1
|
|
37
|
+
const NOTHING_PENDING_REASON = 'main has taken no merge since the version last changed'
|
|
38
|
+
const RELEASE_HINT = 'run `pnpm josh release` on the default branch of the primary checkout'
|
|
39
|
+
// **Not `skip`.** An unreadable version, a fetch that could not run or a base the search cannot
|
|
40
|
+
// resolve is not "nothing is waiting to ship", and reporting it as one is how a release goes
|
|
41
|
+
// missing quietly a second time.
|
|
42
|
+
const UNKNOWN_REASON = 'the unreleased-merge count could not be read — report unknown, never skip'
|
|
43
|
+
|
|
44
|
+
type ReleaseScope = typeof REQUIRED_SCOPE | typeof SKIPPED_SCOPE | typeof UNKNOWN_SCOPE
|
|
45
|
+
|
|
46
|
+
interface Decision {
|
|
47
|
+
scope: ReleaseScope
|
|
48
|
+
reason: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// **The threshold is one, and the position carries the rest.** A release per invocation is the
|
|
52
|
+
// cadence joshuafolkken/kit#1582 asks for — its own complaint is that accumulating makes a single
|
|
53
|
+
// version larger and its contents harder to trace afterwards — so anything above zero is owed. What
|
|
54
|
+
// keeps this from firing per child of a batch is where the question is asked, which belongs to the
|
|
55
|
+
// procedure rather than to this command.
|
|
56
|
+
function decide(pending: number | undefined): Decision {
|
|
57
|
+
if (pending === undefined) return { scope: UNKNOWN_SCOPE, reason: UNKNOWN_REASON }
|
|
58
|
+
|
|
59
|
+
const line = release_plan.format_pending_line(pending)
|
|
60
|
+
|
|
61
|
+
if (pending === 0) return { scope: SKIPPED_SCOPE, reason: `${line} — ${NOTHING_PENDING_REASON}` }
|
|
62
|
+
|
|
63
|
+
return { scope: REQUIRED_SCOPE, reason: `${line} — ${RELEASE_HINT}` }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
67
|
+
if (path_decision.has_unknown_flag(argv, KNOWN_FLAGS)) {
|
|
68
|
+
console.error(USAGE)
|
|
69
|
+
|
|
70
|
+
return FAILURE_EXIT_CODE
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const decision = decide(await git_followup_pending.read_pending({}))
|
|
74
|
+
const is_json = argv.includes(path_decision.JSON_FLAG)
|
|
75
|
+
|
|
76
|
+
path_decision.print_decision(JSON_KEY, decision.scope, decision.reason, is_json)
|
|
77
|
+
|
|
78
|
+
return SUCCESS_EXIT_CODE
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
82
|
+
process.exitCode = await run(argv)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const release_scope_cli = {
|
|
86
|
+
decide,
|
|
87
|
+
main,
|
|
88
|
+
run,
|
|
89
|
+
JSON_KEY,
|
|
90
|
+
KNOWN_FLAGS,
|
|
91
|
+
NOTHING_PENDING_REASON,
|
|
92
|
+
RELEASE_HINT,
|
|
93
|
+
REQUIRED_SCOPE,
|
|
94
|
+
SKIPPED_SCOPE,
|
|
95
|
+
UNKNOWN_REASON,
|
|
96
|
+
UNKNOWN_SCOPE,
|
|
97
|
+
USAGE,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
101
|
+
|
|
102
|
+
export type { Decision }
|
|
103
|
+
export { release_scope_cli }
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { git_gh_api_path } from '#scripts/git/git-gh-api-path'
|
|
2
|
+
import { git_gh_exec } from '#scripts/git/git-gh-exec'
|
|
3
|
+
import { poll, type PollOptions } from '#scripts/lib/poll'
|
|
4
|
+
|
|
5
|
+
// **The release is not finished when the pull request merges — it is finished when the tag exists.**
|
|
6
|
+
//
|
|
7
|
+
// Merging is what starts the distribution chain: `ci.yml`'s `notify-auto-tag` dispatches, `auto-tag.yml`
|
|
8
|
+
// creates `v<version>`, and `publish.yml` / `production.yml` run off that tag. Every link after the
|
|
9
|
+
// merge can fail silently, and one of them is known to (joshuafolkken/kit#1481: a later push to main
|
|
10
|
+
// cancels the release commit's CI run, so nothing dispatches and nothing is tagged). An automatic
|
|
11
|
+
// release would have been picked up by the next cycle; a release a person types has no next cycle, so
|
|
12
|
+
// the person walks away believing something shipped when nothing did.
|
|
13
|
+
//
|
|
14
|
+
// So this waits for the tag and **reports its absence as a failure** (joshuafolkken/kit#1169 → §3).
|
|
15
|
+
|
|
16
|
+
const HTTP_OK = 200
|
|
17
|
+
const TAG_POLL_INTERVAL_MS = 15_000
|
|
18
|
+
const MILLISECONDS_PER_SECOND = 1000
|
|
19
|
+
|
|
20
|
+
// Long enough for main's full CI run plus the dispatch hop that follows it. A release that has not
|
|
21
|
+
// been tagged after this has not been slow, it has been lost — which is the answer this reports.
|
|
22
|
+
const DEFAULT_TIMEOUT_SECONDS = 1800
|
|
23
|
+
const TIMEOUT_ENV = 'JOSH_RELEASE_TAG_TIMEOUT_SECONDS'
|
|
24
|
+
|
|
25
|
+
function tag_name(version: string): string {
|
|
26
|
+
return `v${version}`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function configured_timeout_seconds(raw: string | undefined): number {
|
|
30
|
+
const parsed = Number(raw)
|
|
31
|
+
|
|
32
|
+
if (!Number.isFinite(parsed) || parsed <= 0) return DEFAULT_TIMEOUT_SECONDS
|
|
33
|
+
|
|
34
|
+
return parsed
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function attempts_for(timeout_seconds: number): number {
|
|
38
|
+
const budget_ms = timeout_seconds * MILLISECONDS_PER_SECOND
|
|
39
|
+
|
|
40
|
+
return Math.max(1, Math.ceil(budget_ms / TAG_POLL_INTERVAL_MS))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// REST answers 404 for a tag that does not exist, so the status code alone is the whole question.
|
|
44
|
+
async function tag_exists(version: string): Promise<boolean> {
|
|
45
|
+
const status = await git_gh_exec.exec_gh_api_status(
|
|
46
|
+
git_gh_api_path.tag_ref_api_path(tag_name(version)),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return status === HTTP_OK
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function wait_for_tag(
|
|
53
|
+
version: string,
|
|
54
|
+
sleeper?: (duration_ms: number) => Promise<void>,
|
|
55
|
+
): Promise<boolean> {
|
|
56
|
+
const timeout_seconds = configured_timeout_seconds(process.env[TIMEOUT_ENV])
|
|
57
|
+
// Spread rather than a conditional call: `exactOptionalPropertyTypes` refuses an explicit
|
|
58
|
+
// `sleeper: undefined`, and writing the call twice to satisfy it would duplicate the predicate.
|
|
59
|
+
const options: PollOptions = {
|
|
60
|
+
attempts: attempts_for(timeout_seconds),
|
|
61
|
+
interval_ms: TAG_POLL_INTERVAL_MS,
|
|
62
|
+
...(sleeper !== undefined && { sleeper }),
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return await poll.poll_until(async () => await tag_exists(version), options)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// **The failure text says what did not happen rather than what went wrong**, because the command
|
|
69
|
+
// cannot know which link broke — only that the tag it was waiting for is not there, and that nothing
|
|
70
|
+
// downstream of the tag can have run.
|
|
71
|
+
function format_result(version: string, is_tagged: boolean): string {
|
|
72
|
+
if (is_tagged) return `🏷 ${tag_name(version)} exists — the release is published.`
|
|
73
|
+
|
|
74
|
+
return [
|
|
75
|
+
`❌ ${tag_name(version)} never appeared.`,
|
|
76
|
+
` The release pull request merged, but no tag was created, so nothing was published.`,
|
|
77
|
+
` Check the CI run on main: a later push cancels the release commit's run, which skips the tag (joshuafolkken/kit#1481).`,
|
|
78
|
+
].join('\n')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const release_tag = {
|
|
82
|
+
attempts_for,
|
|
83
|
+
configured_timeout_seconds,
|
|
84
|
+
format_result,
|
|
85
|
+
tag_exists,
|
|
86
|
+
tag_name,
|
|
87
|
+
wait_for_tag,
|
|
88
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
89
|
+
TAG_POLL_INTERVAL_MS,
|
|
90
|
+
TIMEOUT_ENV,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export { release_tag }
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { git_command } from '#scripts/git/git-command'
|
|
3
|
+
import { git_worktree } from '#scripts/git/git-worktree'
|
|
4
|
+
import { lane_install } from '#scripts/lane/lane-install'
|
|
5
|
+
import { lane_paths } from '#scripts/lane/lane-paths'
|
|
6
|
+
|
|
7
|
+
// The dedicated linked work tree `pnpm josh release` runs inside (joshuafolkken/kit#2411). The whole
|
|
8
|
+
// point is that the release never touches the root checkout: it is cut fresh from
|
|
9
|
+
// `origin/<default>` as the `release/v<version>` branch, the version bump / commit / push all happen
|
|
10
|
+
// there, and it is removed whichever way the run ends. That lets a release run beside a `backlogrun`
|
|
11
|
+
// — which keeps the root on the default branch — and lets a release start even when the root is dirty
|
|
12
|
+
// or sitting on another branch.
|
|
13
|
+
|
|
14
|
+
// The release work tree lives under the same sibling hidden directory the lanes do
|
|
15
|
+
// (`.<repo>-lanes/`), so it inherits the same "not inside the repository" placement. Lanes are named
|
|
16
|
+
// by their numeric issue number (`lane_paths` matches `^\d+$`) and their seat locks are named
|
|
17
|
+
// separately, so a fixed non-numeric name collides with neither.
|
|
18
|
+
const RELEASE_WORKTREE_NAME = 'release'
|
|
19
|
+
|
|
20
|
+
function directory_for(repository_root: string): string {
|
|
21
|
+
return path.join(lane_paths.lane_root(repository_root), RELEASE_WORKTREE_NAME)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function install_failed_message(directory: string, output: string): string {
|
|
25
|
+
return `Could not install dependencies in the release work tree \`${directory}\`:\n${output}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// The work tree and its local branch both go, in that order: a branch checked out in a work tree
|
|
29
|
+
// cannot be deleted, so the tree is removed first. `branch_delete` uses `-D` because the release
|
|
30
|
+
// branch is unmerged against the *local* default (the merge happened on GitHub), which `-d` refuses.
|
|
31
|
+
async function remove(directory: string, branch_name: string): Promise<void> {
|
|
32
|
+
await git_worktree.worktree_remove(directory)
|
|
33
|
+
await git_worktree.branch_delete(branch_name)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// **The dependency install is not optional, and disabling the hook is not the way around it**
|
|
37
|
+
// (joshuafolkken/kit#2411). The release commit goes through lefthook's pre-commit, which runs
|
|
38
|
+
// `pnpm exec` / `pnpm josh`, and a sibling work tree has no `node_modules` above it — so the tree
|
|
39
|
+
// needs its own, installed the same way a lane's is. A failed install cleans up the tree it created
|
|
40
|
+
// rather than leaving debris, then reports what git printed.
|
|
41
|
+
async function install_or_clean(directory: string, branch_name: string): Promise<void> {
|
|
42
|
+
const result = await lane_install.install_dependencies(directory)
|
|
43
|
+
|
|
44
|
+
if (result.is_installed) return
|
|
45
|
+
|
|
46
|
+
await remove(directory, branch_name)
|
|
47
|
+
throw new Error(install_failed_message(directory, result.output))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// **The tree is cut from `origin/<default>`, not from the root's HEAD.** git refuses a second work
|
|
51
|
+
// tree on the default branch, so the tree is created directly on the release branch — `git worktree
|
|
52
|
+
// add --no-track -b release/v<version> <dir> origin/<default>`, which `worktree_add` already spells
|
|
53
|
+
// when it is given a start point.
|
|
54
|
+
async function create(branch_name: string): Promise<string> {
|
|
55
|
+
const directory = directory_for(process.cwd())
|
|
56
|
+
const default_branch = await git_command.get_default_branch()
|
|
57
|
+
|
|
58
|
+
await git_worktree.worktree_add(directory, branch_name, `origin/${default_branch}`)
|
|
59
|
+
await install_or_clean(directory, branch_name)
|
|
60
|
+
|
|
61
|
+
return directory
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const release_worktree = {
|
|
65
|
+
directory_for,
|
|
66
|
+
create,
|
|
67
|
+
remove,
|
|
68
|
+
RELEASE_WORKTREE_NAME,
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { release_worktree }
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { repo_setting, type RepoSettingStatus } from './repo-setting'
|
|
2
|
+
|
|
3
|
+
// GitHub's repository-level "Allow auto-merge" setting, as reported by the `allow_auto_merge` field
|
|
4
|
+
// of `GET /repos/{owner}/{repo}`.
|
|
5
|
+
//
|
|
6
|
+
// joshuafolkken/kit#834 added `.github/workflows/dependabot-auto-merge.yml` to the distributed
|
|
7
|
+
// files, so a synced consumer now runs `gh pr merge --auto` on every github-actions patch and minor
|
|
8
|
+
// bump. That command needs this setting: without it the step fails with `Auto-merge is not allowed
|
|
9
|
+
// for this repository`, and the pull request sits green and unmerged — which is the exact state
|
|
10
|
+
// joshuafolkken/app-kit#184 was found in, and the same defect kit itself hit in
|
|
11
|
+
// joshuafolkken/kit#802. The setting is off by default, so distributing the workflow without
|
|
12
|
+
// reporting it would hand every consumer a workflow that never merges anything.
|
|
13
|
+
type AutoMergeStatus = RepoSettingStatus
|
|
14
|
+
|
|
15
|
+
const SETTING_LABEL = 'Repository auto-merge'
|
|
16
|
+
const ALLOW_AUTO_MERGE_FIELD = 'allow_auto_merge'
|
|
17
|
+
const ORIGIN_ISSUE = 'joshuafolkken/kit#834'
|
|
18
|
+
const WORKFLOW_PATH = '.github/workflows/dependabot-auto-merge.yml'
|
|
19
|
+
|
|
20
|
+
// The remediation for `disabled`, addressed at the repository the report actually resolved. kit
|
|
21
|
+
// prints it and never runs it: changing a repository setting is outward-facing, needs admin scope,
|
|
22
|
+
// and is the maintainer's call — the same line joshuafolkken/kit#805 drew for
|
|
23
|
+
// `automated-security-fixes`, which is why `josh doctor --fix` does not enable this either.
|
|
24
|
+
function enable_command(repo: string | undefined): string {
|
|
25
|
+
return `gh api -X PATCH repos/${repo_setting.command_target(repo)} -f ${ALLOW_AUTO_MERGE_FIELD}=true`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Classify one `gh api` result. A failed call, unparseable output and a non-boolean field all land
|
|
29
|
+
// on `unreadable`: a missing answer is not a negative answer, and reporting one as `disabled` would
|
|
30
|
+
// tell a maintainer to change a setting that may already be correct.
|
|
31
|
+
function classify_auto_merge(exit_code: number, stdout: string): AutoMergeStatus {
|
|
32
|
+
return repo_setting.classify_boolean_setting(
|
|
33
|
+
repo_setting.parse_payload(exit_code, stdout),
|
|
34
|
+
ALLOW_AUTO_MERGE_FIELD,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// What the reader loses while the setting is off, and how to get it back.
|
|
39
|
+
function format_disabled_detail(repo: string | undefined): ReadonlyArray<string> {
|
|
40
|
+
return [
|
|
41
|
+
` off, so ${WORKFLOW_PATH} fails with`,
|
|
42
|
+
' `Auto-merge is not allowed for this repository` and Dependabot pull requests stay open.',
|
|
43
|
+
` Enable: ${enable_command(repo)}`,
|
|
44
|
+
` ${ORIGIN_ISSUE} distributes the workflow; kit never changes a repository setting.`,
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Why the setting could not be read. The two branches have different causes and must not share
|
|
49
|
+
// wording: when the repository itself was never identified, admin access is beside the point and
|
|
50
|
+
// naming a settings page names no page the reader can open.
|
|
51
|
+
//
|
|
52
|
+
// For an identified repository the causes are listed rather than asserted. `allow_auto_merge` is
|
|
53
|
+
// absent from the response for a token without the right scope, and the same branch catches a 404,
|
|
54
|
+
// a timeout, an offline run and an unparseable body — so naming any one of them as the cause would
|
|
55
|
+
// be a false diagnosis. No enable command here either: it would be wrong whenever the setting is
|
|
56
|
+
// actually on and merely unreadable.
|
|
57
|
+
function format_unreadable_detail(repo: string | undefined): ReadonlyArray<string> {
|
|
58
|
+
if (repo === undefined) {
|
|
59
|
+
return [
|
|
60
|
+
' The repository could not be identified — `gh` is missing, unauthenticated, or this is',
|
|
61
|
+
' not a GitHub remote.',
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return [
|
|
66
|
+
' No admin access, or the request failed (offline, timed out, or an unexpected response).',
|
|
67
|
+
" Check Settings → General → Pull Requests → Allow auto-merge on the repository's page.",
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// The report block for one repository: a single status line, plus the consequence and its
|
|
72
|
+
// remediation when the setting is off, or the possible causes when it could not be read.
|
|
73
|
+
function format_auto_merge_report(
|
|
74
|
+
status: AutoMergeStatus,
|
|
75
|
+
repo: string | undefined,
|
|
76
|
+
): ReadonlyArray<string> {
|
|
77
|
+
const target = repo_setting.report_target(repo)
|
|
78
|
+
if (status === 'enabled') return [` ✔ ${SETTING_LABEL}: enabled (${target})`]
|
|
79
|
+
|
|
80
|
+
if (status === 'unreadable') {
|
|
81
|
+
return [
|
|
82
|
+
` ⚠ ${SETTING_LABEL}: could not be read (${target}) — not checked, not necessarily off`,
|
|
83
|
+
...format_unreadable_detail(repo),
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return [` ⚠ ${SETTING_LABEL}: disabled (${target})`, ...format_disabled_detail(repo)]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const auto_merge_setting_logic = {
|
|
91
|
+
SETTING_LABEL,
|
|
92
|
+
ALLOW_AUTO_MERGE_FIELD,
|
|
93
|
+
WORKFLOW_PATH,
|
|
94
|
+
enable_command,
|
|
95
|
+
classify_auto_merge,
|
|
96
|
+
format_auto_merge_report,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type { AutoMergeStatus }
|
|
100
|
+
export { auto_merge_setting_logic }
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { auto_merge_setting_logic, type AutoMergeStatus } from './auto-merge-setting-logic'
|
|
2
|
+
import { repo_setting } from './repo-setting'
|
|
3
|
+
|
|
4
|
+
// Read the repository's "Allow auto-merge" setting. Never throws and never propagates a non-zero
|
|
5
|
+
// exit: an unreadable answer is a reported status, not a command failure (joshuafolkken/kit#834).
|
|
6
|
+
//
|
|
7
|
+
// The whole repository object is requested rather than a `--jq` projection, because a projection
|
|
8
|
+
// cannot distinguish a field that is `false` from a field the response never carried — and that
|
|
9
|
+
// distinction is the entire point of the `unreadable` status.
|
|
10
|
+
function read_auto_merge(repo: string): AutoMergeStatus {
|
|
11
|
+
const { exit_code, stdout } = repo_setting.query_repo_api(`repos/${repo}`)
|
|
12
|
+
|
|
13
|
+
return auto_merge_setting_logic.classify_auto_merge(exit_code, stdout)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Report the repository's setting as a blank-line-separated block. A repository that cannot be
|
|
17
|
+
// resolved (no `gh`, not a GitHub remote) reports `unreadable` rather than skipping the check
|
|
18
|
+
// silently: an absent answer must not look like a clean one.
|
|
19
|
+
//
|
|
20
|
+
// `repo` is supplied by the caller rather than defaulted, for the same reason as the
|
|
21
|
+
// security-updates report — a default parameter fires on an explicitly-passed `undefined` and would
|
|
22
|
+
// re-spawn `gh repo view` in the very path where the caller's own lookup already failed.
|
|
23
|
+
function report_auto_merge_section(repo: string | undefined): AutoMergeStatus {
|
|
24
|
+
const status = repo === undefined ? 'unreadable' : read_auto_merge(repo)
|
|
25
|
+
|
|
26
|
+
repo_setting.print_section(auto_merge_setting_logic.format_auto_merge_report(status, repo))
|
|
27
|
+
|
|
28
|
+
return status
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const auto_merge_setting = {
|
|
32
|
+
GH_TIMEOUT_MS: repo_setting.GH_TIMEOUT_MS,
|
|
33
|
+
read_auto_merge,
|
|
34
|
+
report_auto_merge_section,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { auto_merge_setting }
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { git_gh_exec } from '#scripts/git/git-gh-exec'
|
|
2
|
+
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
3
|
+
import { read_spawn_stdout } from '#scripts/lib/spawn-exit'
|
|
4
|
+
import { execaSync } from 'execa'
|
|
5
|
+
|
|
6
|
+
// The shared half of every "report a GitHub repository setting kit cannot write" check.
|
|
7
|
+
//
|
|
8
|
+
// Two such checks exist — `automated-security-fixes` (joshuafolkken/kit#805) and `allow_auto_merge`
|
|
9
|
+
// (joshuafolkken/kit#834) — and they agree on everything that is not wording: the same bounded
|
|
10
|
+
// `gh api` call, the same rule that an answer which cannot be read is never reported as a negative
|
|
11
|
+
// answer, and the same blank-line-separated report block. That agreement is the contract, so it
|
|
12
|
+
// lives here once rather than being re-derived per setting.
|
|
13
|
+
type RepoSettingStatus = 'enabled' | 'disabled' | 'unreadable'
|
|
14
|
+
|
|
15
|
+
// Bounded, unlike the repository lookup: these calls only decide what a report *says*, never what
|
|
16
|
+
// gets written, so a timeout degrades to `could not be read` and costs nothing. `josh doctor` made
|
|
17
|
+
// no network calls at all before joshuafolkken/kit#805, and this keeps it prompt.
|
|
18
|
+
const GH_TIMEOUT_MS = 5000
|
|
19
|
+
|
|
20
|
+
// A literal `<owner>/<repo>` would be unusable when pasted into a shell, where `<` redirects — but
|
|
21
|
+
// it is still the honest rendering when the repository could not be resolved at all.
|
|
22
|
+
const REPO_PLACEHOLDER = '<owner>/<repo>'
|
|
23
|
+
const UNKNOWN_REPOSITORY = 'unknown repository'
|
|
24
|
+
|
|
25
|
+
interface RepoApiResult {
|
|
26
|
+
exit_code: number
|
|
27
|
+
stdout: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// One `gh api` call. Never throws and never propagates a non-zero exit: an unreadable answer is a
|
|
31
|
+
// reported status, not a command failure.
|
|
32
|
+
function query_repo_api(api_path: string): RepoApiResult {
|
|
33
|
+
const result = execaSync('gh', ['api', api_path], {
|
|
34
|
+
...git_gh_exec.direct_environment(),
|
|
35
|
+
cwd: PROJECT_ROOT,
|
|
36
|
+
reject: false,
|
|
37
|
+
timeout: GH_TIMEOUT_MS,
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return { exit_code: result.exitCode ?? 1, stdout: read_spawn_stdout(result) }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// The response body as an object, or nothing. A non-zero exit covers every case where the answer
|
|
44
|
+
// cannot be trusted — a 404 on a repository that never had the setting, a token without the scope,
|
|
45
|
+
// no network — and they collapse together with unparseable output because none of them proves the
|
|
46
|
+
// setting is off.
|
|
47
|
+
function parse_payload(exit_code: number, stdout: string): object | undefined {
|
|
48
|
+
if (exit_code !== 0) return undefined
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const parsed: unknown = JSON.parse(stdout)
|
|
52
|
+
|
|
53
|
+
return typeof parsed === 'object' && parsed !== null ? parsed : undefined
|
|
54
|
+
} catch {
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Read one field off a parsed body. `Reflect.get` rather than an index signature: the body is
|
|
60
|
+
// external JSON, so declaring it as a record would need a type assertion to claim a shape the
|
|
61
|
+
// response never promised.
|
|
62
|
+
function read_field(payload: object | undefined, field: string): unknown {
|
|
63
|
+
return payload === undefined ? undefined : Reflect.get(payload, field)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// A missing payload, a missing field, or a field that is not a boolean are all unreadable: a
|
|
67
|
+
// missing answer is not a negative answer, and reporting one as `disabled` would raise a false
|
|
68
|
+
// alarm — the failure mode both settings exist to remove.
|
|
69
|
+
function classify_boolean_setting(payload: object | undefined, field: string): RepoSettingStatus {
|
|
70
|
+
const value = read_field(payload, field)
|
|
71
|
+
if (typeof value !== 'boolean') return 'unreadable'
|
|
72
|
+
|
|
73
|
+
return value ? 'enabled' : 'disabled'
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// The repository a remediation command should address. Falls back to the placeholder rather than to
|
|
77
|
+
// prose, because this value is pasted into a shell.
|
|
78
|
+
function command_target(repo: string | undefined): string {
|
|
79
|
+
return repo ?? REPO_PLACEHOLDER
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// The repository a status line should name. Falls back to prose rather than to the placeholder,
|
|
83
|
+
// because this value is read, not pasted.
|
|
84
|
+
function report_target(repo: string | undefined): string {
|
|
85
|
+
return repo ?? UNKNOWN_REPOSITORY
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// The blank-line-separated report block, shared by every caller so the separator and the ordering
|
|
89
|
+
// contract live in one place.
|
|
90
|
+
function print_section(lines: ReadonlyArray<string>): void {
|
|
91
|
+
console.info('')
|
|
92
|
+
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
console.info(line)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const repo_setting = {
|
|
99
|
+
GH_TIMEOUT_MS,
|
|
100
|
+
REPO_PLACEHOLDER,
|
|
101
|
+
UNKNOWN_REPOSITORY,
|
|
102
|
+
query_repo_api,
|
|
103
|
+
parse_payload,
|
|
104
|
+
read_field,
|
|
105
|
+
classify_boolean_setting,
|
|
106
|
+
command_target,
|
|
107
|
+
report_target,
|
|
108
|
+
print_section,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export type { RepoSettingStatus }
|
|
112
|
+
export { repo_setting }
|