@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,69 @@
|
|
|
1
|
+
import { managed_config_scope, type ManagedHit } from '#scripts/sync/managed-config-scope'
|
|
2
|
+
import { changed_paths } from './changed-paths'
|
|
3
|
+
import { git_command } from './git-command'
|
|
4
|
+
|
|
5
|
+
// **The tracked diff against the merge base — untracked files excluded.**
|
|
6
|
+
// `changed_paths.read_changed_paths(false)` appends the untracked files as well, and those are not in
|
|
7
|
+
// the pull request: a stray untracked file under a distributed path would put a line in the report
|
|
8
|
+
// asserting that *this pull request* changes a distributed file, which would be false.
|
|
9
|
+
//
|
|
10
|
+
// **What it compares is the merge base against the work tree, not against `HEAD`**, so an uncommitted
|
|
11
|
+
// edit to a tracked file still counts. That is deliberate rather than overlooked: `followup` runs
|
|
12
|
+
// straight after `josh git` has committed and pushed, so the two agree in the case this report is
|
|
13
|
+
// for, and where they disagree the error falls on the side of naming a path that is about to be
|
|
14
|
+
// committed rather than omitting one.
|
|
15
|
+
//
|
|
16
|
+
// The line splitting stays the shared helper's, so this answers from the same definition of a changed
|
|
17
|
+
// path as the review level and the eval scope.
|
|
18
|
+
async function read_branch_paths(): Promise<Array<string>> {
|
|
19
|
+
return changed_paths.to_paths(await git_command.diff_main_names())
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const REPORT_HEADING =
|
|
23
|
+
'This pull request changes files that `josh sync` distributes to every consumer project.'
|
|
24
|
+
const REPORT_PATHS_HEADING = 'Distributed paths in this diff:'
|
|
25
|
+
|
|
26
|
+
function build_report(hits: ReadonlyArray<ManagedHit>): Array<string> {
|
|
27
|
+
return [REPORT_HEADING, REPORT_PATHS_HEADING, managed_config_scope.format_hits(hits)]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// **This reports; it does not stop the merge** (joshuafolkken/kit#1592). joshuafolkken/kit#1578 made
|
|
31
|
+
// it a confirmation gate that exited non-zero ahead of the CI wait, and in kit the condition it tests
|
|
32
|
+
// is nearly always true: kit is the distribution source, so every change to `CLAUDE.md`, to
|
|
33
|
+
// `prompts/`, to `.claude/skills/` or to the distributed part of `docs/` is by definition a change to
|
|
34
|
+
// a distributed path. Measured on `epicrun #1413`, **two of three children stopped here** — and in
|
|
35
|
+
// both the distributed file was what the Issue's own acceptance criteria had ordered changed. The
|
|
36
|
+
// gate was not catching an unintended edit; it was stopping the work.
|
|
37
|
+
//
|
|
38
|
+
// **There is deliberately no branch on which repository this is.** The alternative — stop in a
|
|
39
|
+
// consumer, where editing a distributed file really is the mistake `CLAUDE.md` → "Route
|
|
40
|
+
// distributed-doc / config changes upstream to kit" names, and stay quiet in kit — was weighed and
|
|
41
|
+
// rejected on joshuafolkken/kit#1592: it needs a distribution-source test this package does not have,
|
|
42
|
+
// no case is recorded of the gate saving a consumer's work, and the report below reaches a consumer's
|
|
43
|
+
// reader just as well. `managed_config_scope` matches both ends of every mapping and distinguishes no
|
|
44
|
+
// repository, and that property is kept rather than worked around.
|
|
45
|
+
//
|
|
46
|
+
// **What is left is the signal without the stop.** The claimed paths and the list that claimed each
|
|
47
|
+
// one go into the completion notification and into the completion report on the Issue, so a
|
|
48
|
+
// distributed change is still impossible to miss after the fact.
|
|
49
|
+
async function handle_managed_config_changes(input: {
|
|
50
|
+
should_merge: boolean
|
|
51
|
+
}): Promise<Array<string>> {
|
|
52
|
+
// **Nothing to report when nothing merges.** `--no-merge` ends with the pull request open for a
|
|
53
|
+
// person to look at, and the distribution has not happened yet; the report belongs to the run that
|
|
54
|
+
// actually lands the change on the default branch.
|
|
55
|
+
if (!input.should_merge) return []
|
|
56
|
+
|
|
57
|
+
const hits = managed_config_scope.find_managed_paths(await read_branch_paths())
|
|
58
|
+
|
|
59
|
+
if (hits.length === 0) return []
|
|
60
|
+
|
|
61
|
+
return build_report(hits)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const git_pr_managed_config = {
|
|
65
|
+
handle_managed_config_changes,
|
|
66
|
+
build_report,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { git_pr_managed_config }
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// What `pnpm josh git` prints once the pull request is open. It no longer claims anything about the
|
|
2
|
+
// checks: this command returns before they have run (joshuafolkken/kit#1232), and the old
|
|
3
|
+
// "All checks passed successfully." was printed on the strength of a watch whose verdict decided
|
|
4
|
+
// nothing. Naming `pnpm josh followup` here is the whole replacement — it is what waits, and what
|
|
5
|
+
// merges.
|
|
6
|
+
function display_pr_opened_message(): void {
|
|
7
|
+
console.info('')
|
|
8
|
+
console.info('✅ Pull request opened.')
|
|
9
|
+
console.info('')
|
|
10
|
+
console.info('`pnpm josh followup` waits for the checks and merges.')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function display_pr_url(pr_url: string): void {
|
|
14
|
+
console.info('')
|
|
15
|
+
console.info(`🔗 PR: ${pr_url}`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function display_merged_pr_message(): void {
|
|
19
|
+
console.info('')
|
|
20
|
+
console.info('ℹ️ Existing PR is already merged. Creating a new PR...')
|
|
21
|
+
console.info('')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function display_pr_exists_message(): void {
|
|
25
|
+
console.info('')
|
|
26
|
+
console.info('ℹ️ Pull request already exists.')
|
|
27
|
+
console.info('')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const git_pr_messages = {
|
|
31
|
+
display_pr_opened_message,
|
|
32
|
+
display_merged_pr_message,
|
|
33
|
+
display_pr_exists_message,
|
|
34
|
+
display_pr_url,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { git_pr_messages }
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { animation_helpers, type AnimationOptions } from './animation-helpers'
|
|
2
|
+
import { git_gh_command } from './git-gh-command'
|
|
3
|
+
import type { IssueInfo } from './git-issue'
|
|
4
|
+
import { git_pr_error } from './git-pr-error'
|
|
5
|
+
import { git_pr_messages } from './git-pr-messages'
|
|
6
|
+
import { pr_info_schema } from './schemas'
|
|
7
|
+
|
|
8
|
+
// **Answers the new pull request's URL, and `undefined` when one already existed.** `pr_create`
|
|
9
|
+
// filters its REST response to `.html_url`, so the address is in hand the moment the call returns —
|
|
10
|
+
// which matters now that nothing waits before reporting it (joshuafolkken/kit#1232). `pr_get_url`
|
|
11
|
+
// resolves the branch through the `?head=…` listing, and that listing is eventually consistent: read
|
|
12
|
+
// in the same instant the pull request was created it can answer nothing, and `pr_get_url` folds
|
|
13
|
+
// "not there yet" and "the read failed" into the same `undefined`. The five-second sleep used to
|
|
14
|
+
// cover that gap incidentally.
|
|
15
|
+
async function create_pr(title: string, body: string): Promise<string | undefined> {
|
|
16
|
+
const config: AnimationOptions<string> = {
|
|
17
|
+
icon_selector: () => '✅',
|
|
18
|
+
error_message: 'Failed to create PR',
|
|
19
|
+
result_formatter: () => 'PR created.',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
return await animation_helpers.execute_with_animation(
|
|
24
|
+
'Creating pull request...',
|
|
25
|
+
async () => await git_gh_command.pr_create(title, body),
|
|
26
|
+
config,
|
|
27
|
+
)
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (git_pr_error.is_pr_already_exists_error(error)) {
|
|
30
|
+
git_pr_messages.display_pr_exists_message()
|
|
31
|
+
|
|
32
|
+
return undefined
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
throw error
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function display_pr_url_if_available(branch_name: string): Promise<void> {
|
|
40
|
+
const pr_url = await git_gh_command.pr_get_url(branch_name)
|
|
41
|
+
|
|
42
|
+
if (pr_url !== undefined) {
|
|
43
|
+
git_pr_messages.display_pr_url(pr_url)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// **This command stops at "the pull request is open"; it does not wait for the checks**
|
|
48
|
+
// (joshuafolkken/kit#1232). It used to sleep five seconds and then watch the rollup on a two-minute
|
|
49
|
+
// budget — measured at 119.8 seconds of one 1555-second run, 7.7% of it — and the answer decided
|
|
50
|
+
// nothing: only `timed_out` was read, and only to pick which message to print. What actually blocks
|
|
51
|
+
// a merge is `pnpm josh followup`, whose `wait_for_pr_success` asks a stricter question (CLEAN merge
|
|
52
|
+
// state, every required check green, no standing change request) and starts that wait from scratch
|
|
53
|
+
// the moment this command returns. So the wait here was the same answer, paid for twice.
|
|
54
|
+
//
|
|
55
|
+
// **The conflict read went with it, and its replacement is not here.** `git-conflict.ts` read
|
|
56
|
+
// `mergeStateStatus` right after the watch reported the checks settled, where `BLOCKED` genuinely
|
|
57
|
+
// meant something. Called at *this* point it would fire on every healthy pull request instead:
|
|
58
|
+
// GitHub reports `BLOCKED` as soon as a required check is queued. The conflict is caught in
|
|
59
|
+
// `git-pr-checks-eval.ts` now, where `DIRTY` ends the wait on its first poll — about ten seconds,
|
|
60
|
+
// against the two minutes this watch took to reach the same conclusion.
|
|
61
|
+
async function report_open_pr(branch_name: string, created_url?: string): Promise<void> {
|
|
62
|
+
git_pr_messages.display_pr_opened_message()
|
|
63
|
+
|
|
64
|
+
if (created_url !== undefined && created_url.length > 0) {
|
|
65
|
+
git_pr_messages.display_pr_url(created_url)
|
|
66
|
+
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await display_pr_url_if_available(branch_name)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const PR_STATE_MERGED = 'MERGED'
|
|
74
|
+
|
|
75
|
+
async function create_and_report(title: string, body: string, branch_name: string): Promise<void> {
|
|
76
|
+
const created_url = await create_pr(title, body)
|
|
77
|
+
|
|
78
|
+
await report_open_pr(branch_name, created_url)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function parse_pr_state(pr_info_json: string): string | undefined {
|
|
82
|
+
try {
|
|
83
|
+
const result = pr_info_schema.safeParse(JSON.parse(pr_info_json))
|
|
84
|
+
|
|
85
|
+
return result.success ? result.data.state : undefined
|
|
86
|
+
} catch {
|
|
87
|
+
return undefined
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function get_pr_state_safe(branch_name: string): Promise<string | undefined> {
|
|
92
|
+
try {
|
|
93
|
+
const pr_info_json = await git_gh_command.pr_view(branch_name)
|
|
94
|
+
|
|
95
|
+
if (pr_info_json.length === 0) {
|
|
96
|
+
return undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return parse_pr_state(pr_info_json)
|
|
100
|
+
} catch {
|
|
101
|
+
return undefined
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function is_pr_state_merged(pr_state: string | undefined): boolean {
|
|
106
|
+
return pr_state === PR_STATE_MERGED
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// A body the caller supplied is written onto the pull request that is already open, rather than
|
|
110
|
+
// dropped with the create that did not happen (joshuafolkken/kit#2446): a rerun carrying the
|
|
111
|
+
// live-execution evidence is how a merge `followup` refused for lacking it is recovered.
|
|
112
|
+
async function report_existing_pr(
|
|
113
|
+
body: string,
|
|
114
|
+
branch_name: string,
|
|
115
|
+
should_replace_body: boolean,
|
|
116
|
+
): Promise<void> {
|
|
117
|
+
if (should_replace_body) await git_gh_command.pr_update_body(branch_name, body)
|
|
118
|
+
|
|
119
|
+
await report_open_pr(branch_name)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function handle_existing_pr(
|
|
123
|
+
title: string,
|
|
124
|
+
body: string,
|
|
125
|
+
branch_name: string,
|
|
126
|
+
should_replace_body: boolean,
|
|
127
|
+
): Promise<void> {
|
|
128
|
+
const pr_state_result = await get_pr_state_safe(branch_name)
|
|
129
|
+
|
|
130
|
+
if (is_pr_state_merged(pr_state_result)) {
|
|
131
|
+
git_pr_messages.display_merged_pr_message()
|
|
132
|
+
await create_and_report(title, body, branch_name)
|
|
133
|
+
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
await report_existing_pr(body, branch_name, should_replace_body)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function create(
|
|
141
|
+
title: string,
|
|
142
|
+
body: string,
|
|
143
|
+
branch_name: string,
|
|
144
|
+
should_replace_body = false,
|
|
145
|
+
): Promise<void> {
|
|
146
|
+
const has_pr = await git_gh_command.pr_exists(branch_name)
|
|
147
|
+
|
|
148
|
+
if (!has_pr) {
|
|
149
|
+
await create_and_report(title, body, branch_name)
|
|
150
|
+
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
await handle_existing_pr(title, body, branch_name, should_replace_body)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function build_title(issue_info: IssueInfo): string {
|
|
158
|
+
return `${issue_info.title} #${issue_info.number}`
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function build_body(issue_info: IssueInfo, extra_body?: string): string {
|
|
162
|
+
const closes = `closes #${issue_info.number}`
|
|
163
|
+
|
|
164
|
+
if (extra_body === undefined) return closes
|
|
165
|
+
|
|
166
|
+
return `${closes}\n\n${extra_body}`
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function create_with_issue_info(issue_info: IssueInfo, extra_body?: string): Promise<void> {
|
|
170
|
+
const title = build_title(issue_info)
|
|
171
|
+
const body = build_body(issue_info, extra_body)
|
|
172
|
+
|
|
173
|
+
await create(title, body, issue_info.branch_name, extra_body !== undefined)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const git_pr = {
|
|
177
|
+
create,
|
|
178
|
+
create_with_issue_info,
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export { git_pr }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { SEPARATOR_LINE } from './constants'
|
|
2
|
+
|
|
3
|
+
function display_start_separator(): void {
|
|
4
|
+
console.info('')
|
|
5
|
+
console.info(SEPARATOR_LINE)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function display_end_separator(): void {
|
|
9
|
+
console.info(SEPARATOR_LINE)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function display_invalid_answer_message(): void {
|
|
13
|
+
console.info('💡 Reply y / n.')
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const git_prompt_display = {
|
|
17
|
+
display_start_separator,
|
|
18
|
+
display_end_separator,
|
|
19
|
+
display_invalid_answer_message,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { git_prompt_display }
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { stdin as input, stdout as output } from 'node:process'
|
|
2
|
+
import { createInterface, type Interface } from 'node:readline/promises'
|
|
3
|
+
import { git_prompt_display } from './git-prompt-display'
|
|
4
|
+
|
|
5
|
+
const OPERATION_CANCELLED_MESSAGE = '💡 Operation cancelled.'
|
|
6
|
+
|
|
7
|
+
const PROMPT_MESSAGES = {
|
|
8
|
+
unstaged_files: '💬 Unstaged files found. Continue anyway? (y/n): ',
|
|
9
|
+
package_json_not_staged: '💬 package.json is not staged. Continue anyway? (y/n): ',
|
|
10
|
+
version_not_updated: '💬 package.json version is not updated. Continue anyway? (y/n): ',
|
|
11
|
+
commit: '💬 Commit staged changes now? (y/n): ',
|
|
12
|
+
push: '💬 Push changes to remote? (y/n): ',
|
|
13
|
+
pr: '💬 Create pull request? (y/n): ',
|
|
14
|
+
} as const
|
|
15
|
+
|
|
16
|
+
type PromptCallback<T> = (prompt: Interface) => Promise<T>
|
|
17
|
+
|
|
18
|
+
interface AskOptions {
|
|
19
|
+
show_separators: boolean
|
|
20
|
+
is_first_call: boolean
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function is_valid_yes_no_answer(answer: string): boolean {
|
|
24
|
+
return answer === 'y' || answer === 'n'
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function ask_yes_no_unified(
|
|
28
|
+
prompt: Interface,
|
|
29
|
+
question: string,
|
|
30
|
+
options: AskOptions,
|
|
31
|
+
): Promise<boolean> {
|
|
32
|
+
if (options.show_separators && options.is_first_call) {
|
|
33
|
+
git_prompt_display.display_start_separator()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const raw_answer: unknown = await prompt.question(question)
|
|
37
|
+
// eslint-disable-next-line unicorn/no-useless-coercion -- raw_answer is unknown, String() coercion is required
|
|
38
|
+
const answer = String(raw_answer).trim().toLowerCase()
|
|
39
|
+
|
|
40
|
+
if (!is_valid_yes_no_answer(answer)) {
|
|
41
|
+
git_prompt_display.display_invalid_answer_message()
|
|
42
|
+
|
|
43
|
+
return await ask_yes_no_unified(prompt, question, { ...options, is_first_call: false })
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (options.show_separators) {
|
|
47
|
+
git_prompt_display.display_end_separator()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return answer === 'y'
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function ask_yes_no(prompt: Interface, question: string): Promise<boolean> {
|
|
54
|
+
return await ask_yes_no_unified(prompt, question, { show_separators: true, is_first_call: true })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function ask_yes_no_simple(prompt: Interface, question: string): Promise<boolean> {
|
|
58
|
+
return await ask_yes_no_unified(prompt, question, { show_separators: false, is_first_call: true })
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function create_prompt(): Interface | undefined {
|
|
62
|
+
return process.stdin.isTTY ? createInterface({ input, output }) : undefined
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function handle_prompt_fallback<T>(fallback_value?: T): T {
|
|
66
|
+
if (fallback_value !== undefined) {
|
|
67
|
+
return fallback_value
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
throw new Error('TTY not available')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function with_prompt<T>(callback: PromptCallback<T>, fallback_value?: T): Promise<T> {
|
|
74
|
+
const prompt = create_prompt()
|
|
75
|
+
|
|
76
|
+
if (prompt === undefined) {
|
|
77
|
+
return handle_prompt_fallback(fallback_value)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
// eslint-disable-next-line promise/prefer-await-to-callbacks
|
|
82
|
+
return await callback(prompt)
|
|
83
|
+
} finally {
|
|
84
|
+
prompt.close()
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function confirm_with_exit_on_cancel(should_continue: () => Promise<boolean>): Promise<void> {
|
|
89
|
+
const is_confirmed = await should_continue()
|
|
90
|
+
|
|
91
|
+
if (is_confirmed) {
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
console.info(OPERATION_CANCELLED_MESSAGE)
|
|
96
|
+
console.info('')
|
|
97
|
+
process.exit(1)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function create_confirm_function(message: string): () => Promise<boolean> {
|
|
101
|
+
return async (): Promise<boolean> => {
|
|
102
|
+
return await with_prompt(async (prompt) => await ask_yes_no(prompt, message), false)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function confirm_continue(): Promise<boolean> {
|
|
107
|
+
return await create_confirm_function(PROMPT_MESSAGES.unstaged_files)()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function confirm_without_package_json(): Promise<boolean> {
|
|
111
|
+
return await create_confirm_function(PROMPT_MESSAGES.package_json_not_staged)()
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function confirm_unstaged_files(): Promise<void> {
|
|
115
|
+
await confirm_with_exit_on_cancel(confirm_continue)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function confirm_missing_package_json(): Promise<void> {
|
|
119
|
+
await confirm_with_exit_on_cancel(confirm_without_package_json)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async function confirm_version_not_updated(): Promise<boolean> {
|
|
123
|
+
return await create_confirm_function(PROMPT_MESSAGES.version_not_updated)()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function confirm_without_version_update(): Promise<void> {
|
|
127
|
+
await confirm_with_exit_on_cancel(confirm_version_not_updated)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function confirm_commit(): Promise<boolean> {
|
|
131
|
+
return await create_confirm_function(PROMPT_MESSAGES.commit)()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function confirm_push(): Promise<boolean> {
|
|
135
|
+
return await create_confirm_function(PROMPT_MESSAGES.push)()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function confirm_pr(): Promise<boolean> {
|
|
139
|
+
return await create_confirm_function(PROMPT_MESSAGES.pr)()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function ask_issue_info(prompt: Interface, question: string): Promise<string> {
|
|
143
|
+
git_prompt_display.display_start_separator()
|
|
144
|
+
const raw_answer: unknown = await prompt.question(question)
|
|
145
|
+
// eslint-disable-next-line unicorn/no-useless-coercion -- raw_answer is unknown, String() coercion is required
|
|
146
|
+
const answer = String(raw_answer)
|
|
147
|
+
|
|
148
|
+
git_prompt_display.display_end_separator()
|
|
149
|
+
|
|
150
|
+
return answer.trim()
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function get_issue_info(): Promise<string> {
|
|
154
|
+
return await with_prompt(async (prompt) => {
|
|
155
|
+
const result: string = await ask_issue_info(
|
|
156
|
+
prompt,
|
|
157
|
+
'💬 Enter issue title and number (e.g., "title #52"): ',
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
return result
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
interface WorkflowConfirmations {
|
|
165
|
+
commit: boolean
|
|
166
|
+
push: boolean
|
|
167
|
+
pr: boolean
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
async function confirm_workflow_steps(): Promise<WorkflowConfirmations> {
|
|
171
|
+
const fallback: WorkflowConfirmations = { commit: false, push: false, pr: false }
|
|
172
|
+
|
|
173
|
+
return await with_prompt(async (prompt) => {
|
|
174
|
+
git_prompt_display.display_start_separator()
|
|
175
|
+
console.info('💬 Confirm workflow steps:')
|
|
176
|
+
console.info('')
|
|
177
|
+
|
|
178
|
+
const should_commit = await ask_yes_no_simple(prompt, PROMPT_MESSAGES.commit)
|
|
179
|
+
const should_push = await ask_yes_no_simple(prompt, PROMPT_MESSAGES.push)
|
|
180
|
+
const should_create_pr = await ask_yes_no_simple(prompt, PROMPT_MESSAGES.pr)
|
|
181
|
+
|
|
182
|
+
git_prompt_display.display_end_separator()
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
commit: should_commit,
|
|
186
|
+
push: should_push,
|
|
187
|
+
pr: should_create_pr,
|
|
188
|
+
}
|
|
189
|
+
}, fallback)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const git_prompt = {
|
|
193
|
+
confirm_continue,
|
|
194
|
+
confirm_unstaged_files,
|
|
195
|
+
confirm_without_package_json,
|
|
196
|
+
confirm_missing_package_json,
|
|
197
|
+
confirm_version_not_updated,
|
|
198
|
+
confirm_without_version_update,
|
|
199
|
+
confirm_commit,
|
|
200
|
+
confirm_push,
|
|
201
|
+
confirm_pr,
|
|
202
|
+
get_issue_info,
|
|
203
|
+
confirm_workflow_steps,
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export type { WorkflowConfirmations }
|
|
207
|
+
export { git_prompt, ask_yes_no, ask_yes_no_simple }
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { execa } from 'execa'
|
|
2
|
+
import { git_utilities } from './constants'
|
|
3
|
+
import { create_spawn_error, get_exit_code, has_timed_out } from './git-execa-error'
|
|
4
|
+
|
|
5
|
+
const MS_PER_SECOND = 1000
|
|
6
|
+
|
|
7
|
+
// The budget for one `git push`, and the reason a push can no longer wait without end
|
|
8
|
+
// (joshuafolkken/kit#1251). Measured on PR #1244: the commit itself took 0.6 seconds and the push
|
|
9
|
+
// then sat silent for 8 minutes 13 seconds before it was found by hand and killed — about 9 minutes
|
|
10
|
+
// 50 seconds of a 72-minute run, with no way while waiting to tell a stalled push from a slow one.
|
|
11
|
+
// `execa` has always accepted a `timeout`; the push path never passed one, which left it the single
|
|
12
|
+
// unbounded network call in this directory beside `GH_REQUEST_TIMEOUT_MS`.
|
|
13
|
+
//
|
|
14
|
+
// **It sits at that same layer, and is deliberately larger.** That budget covers one REST request;
|
|
15
|
+
// a push transfers objects, so this number is read off what a healthy push actually costs here — 22
|
|
16
|
+
// seconds on the manual re-run that finally succeeded, 33 seconds on PR #1247. 120 is roughly four
|
|
17
|
+
// times the slower of the two, which leaves room for a first push of a large branch while staying
|
|
18
|
+
// far under the 6 minutes 45 seconds the hang had already reached when it was noticed.
|
|
19
|
+
//
|
|
20
|
+
// **It bounds one push, not one command.** A push killed on the budget is retried exactly once, and
|
|
21
|
+
// `git_command.push` may then fall back to a `--set-upstream` push that is itself bounded and
|
|
22
|
+
// retried — so a `josh git` that hits every one of those waits takes longer than two budgets.
|
|
23
|
+
//
|
|
24
|
+
// **Time spent at a credential prompt counts against it.** With `stdio: 'inherit'` an encrypted key
|
|
25
|
+
// with no agent behind it prompts on the inherited terminal, and the budget does not know the
|
|
26
|
+
// difference between waiting on a remote and waiting on a person. Two minutes is a generous window
|
|
27
|
+
// for typing a passphrase you were just asked for, and the failure names the command to re-run.
|
|
28
|
+
const PUSH_TIMEOUT_SECONDS = 120
|
|
29
|
+
const PUSH_TIMEOUT_MS = PUSH_TIMEOUT_SECONDS * MS_PER_SECOND
|
|
30
|
+
const PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`
|
|
31
|
+
|
|
32
|
+
// What a push killed on the budget is labelled with. "Nobody ever got an answer" and "the remote
|
|
33
|
+
// said no" are different diagnoses, and only the first one is worth retrying.
|
|
34
|
+
const PUSH_TIMEOUT_MESSAGE = 'git push timed out'
|
|
35
|
+
|
|
36
|
+
// A timeout has no exit code — the process was killed rather than allowed to exit — so `cause` says
|
|
37
|
+
// so in the slot every other git failure puts a number in. `is_upstream_not_set_error` compares
|
|
38
|
+
// against '128', which this can never equal, so a timed-out bare push is never mistaken for a
|
|
39
|
+
// missing upstream and retried as `--set-upstream`.
|
|
40
|
+
const PUSH_TIMEOUT_EXIT_CODE = 'timeout'
|
|
41
|
+
|
|
42
|
+
// SSH's own liveness probe: three unanswered checks 15 seconds apart, so a connection that dies
|
|
43
|
+
// mid-transfer is noticed in about 45 seconds instead of waiting on the TCP default. The budget
|
|
44
|
+
// above bounds the damage either way; this is what makes the common case fail in seconds rather
|
|
45
|
+
// than sit out the whole budget.
|
|
46
|
+
const SSH_KEEPALIVE_OPTIONS = '-o ServerAliveInterval=15 -o ServerAliveCountMax=3'
|
|
47
|
+
const SSH_COMMAND_VARIABLE = 'GIT_SSH_COMMAND'
|
|
48
|
+
const SSH_LEGACY_VARIABLE = 'GIT_SSH'
|
|
49
|
+
const KEEPALIVE_SSH_COMMAND = `ssh ${SSH_KEEPALIVE_OPTIONS}`
|
|
50
|
+
const SSH_COMMAND_CONFIG_KEY = 'core.sshCommand'
|
|
51
|
+
const PUSH_SUBCOMMAND = 'push'
|
|
52
|
+
|
|
53
|
+
// Whatever already decides how ssh is invoked, or an empty string when nothing does. git reads three
|
|
54
|
+
// sources in this order — `GIT_SSH_COMMAND`, `core.sshCommand`, then the legacy `GIT_SSH` — and the
|
|
55
|
+
// last one has to be asked as well precisely because it loses: setting `GIT_SSH_COMMAND` on top of a
|
|
56
|
+
// `GIT_SSH=plink.exe` outranks it, so the push would run an ssh binary the user did not choose.
|
|
57
|
+
function to_environment_value(name: string): string {
|
|
58
|
+
return process.env[name]?.trim() ?? ''
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function to_configured_ssh_command(): string {
|
|
62
|
+
const from_command = to_environment_value(SSH_COMMAND_VARIABLE)
|
|
63
|
+
|
|
64
|
+
return from_command === '' ? to_environment_value(SSH_LEGACY_VARIABLE) : from_command
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Whether any of those three sources answered. **A hit means hands off entirely.**
|
|
68
|
+
//
|
|
69
|
+
// Appending the options to a command someone else chose is not safe, because they are OpenSSH's:
|
|
70
|
+
// `plink` and `TortoiseGitPlink` are supported ssh commands on the platform `get_git_command_for_spawn`
|
|
71
|
+
// goes out of its way to handle, and a wrapper script with a fixed argument list is common on any
|
|
72
|
+
// platform — each of them exits on a usage error rather than pushing. Setting the variable while
|
|
73
|
+
// `core.sshCommand` is configured is the same mistake from the other side: the environment wins, so
|
|
74
|
+
// a per-repository key would be silently replaced by a plain `ssh`.
|
|
75
|
+
//
|
|
76
|
+
// What those users lose is the keepalive, not the fix: the budget above still bounds their push, and
|
|
77
|
+
// `ServerAliveInterval` belongs in their own ssh config where it applies to every tool they run.
|
|
78
|
+
async function has_configured_ssh_command(): Promise<boolean> {
|
|
79
|
+
if (to_configured_ssh_command() !== '') return true
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
const git_command_bin = git_utilities.get_git_command_for_spawn()
|
|
83
|
+
// execa runs the binary directly with an argument array and no `shell` option, so CLI
|
|
84
|
+
// args cannot break out of a shell sandbox; the git command and args are internally
|
|
85
|
+
// controlled, never untrusted input. tssecurity:S8705 is a false positive here.
|
|
86
|
+
const { stdout } = await execa(git_command_bin, ['config', '--get', SSH_COMMAND_CONFIG_KEY]) // NOSONAR
|
|
87
|
+
|
|
88
|
+
return stdout.trim() !== ''
|
|
89
|
+
} catch {
|
|
90
|
+
// `git config --get` exits 1 when the key is unset, which is the answer rather than a failure.
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface PushOptions {
|
|
96
|
+
stdio: 'inherit'
|
|
97
|
+
timeout: number
|
|
98
|
+
env: Record<string, string>
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function to_push_options(): Promise<PushOptions> {
|
|
102
|
+
const should_keep_alive = !(await has_configured_ssh_command())
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
stdio: 'inherit',
|
|
106
|
+
timeout: PUSH_TIMEOUT_MS,
|
|
107
|
+
env: should_keep_alive ? { [SSH_COMMAND_VARIABLE]: KEEPALIVE_SSH_COMMAND } : {},
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// One attempt. `true` means the budget killed it — the only failure worth trying again; every other
|
|
112
|
+
// failure is git's own answer and is thrown here, so the caller below never sees it.
|
|
113
|
+
async function did_push_time_out(arguments_list: Array<string>): Promise<boolean> {
|
|
114
|
+
const git_command_bin = git_utilities.get_git_command_for_spawn()
|
|
115
|
+
const options = await to_push_options()
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
// execa runs the binary directly with an argument array and no `shell` option, so CLI
|
|
119
|
+
// args cannot break out of a shell sandbox; the git command and args are internally
|
|
120
|
+
// controlled, never untrusted input. tssecurity:S8705 is a false positive here.
|
|
121
|
+
await execa(git_command_bin, [PUSH_SUBCOMMAND, ...arguments_list], options) // NOSONAR
|
|
122
|
+
|
|
123
|
+
return false
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (has_timed_out(error)) return true
|
|
126
|
+
|
|
127
|
+
throw create_spawn_error(PUSH_SUBCOMMAND, get_exit_code(error))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function to_manual_command(arguments_list: Array<string>): string {
|
|
132
|
+
return ['git', PUSH_SUBCOMMAND, ...arguments_list].join(' ')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function to_retry_notice(arguments_list: Array<string>): string {
|
|
136
|
+
return `${PUSH_TIMEOUT_MESSAGE} after ${PUSH_TIMEOUT_LABEL} — retrying once: ${to_manual_command(arguments_list)}`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Both halves of the report matter. The count says the wait was bounded twice rather than once, and
|
|
140
|
+
// the command is what makes the failure actionable without reconstructing the arguments — the
|
|
141
|
+
// `--set-upstream` form in particular is not what a person would type from memory.
|
|
142
|
+
function create_timeout_error(arguments_list: Array<string>): Error {
|
|
143
|
+
const message = `${PUSH_TIMEOUT_MESSAGE} twice (${PUSH_TIMEOUT_LABEL} each). Re-run it by hand: ${to_manual_command(arguments_list)}`
|
|
144
|
+
|
|
145
|
+
return new Error(message, { cause: { exit_code: PUSH_TIMEOUT_EXIT_CODE } })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// One push, bounded and retried once — and **only** on a timeout. A push the remote rejected (a
|
|
149
|
+
// stale branch, a blocked hook, no upstream) answers the same way every time, so retrying it would
|
|
150
|
+
// buy a second wait to reach an identical failure; a hang is the one outcome a second attempt has
|
|
151
|
+
// been observed to clear, which is what the manual re-run on PR #1244 did in 22 seconds.
|
|
152
|
+
async function push(arguments_list: Array<string>): Promise<void> {
|
|
153
|
+
if (!(await did_push_time_out(arguments_list))) return
|
|
154
|
+
|
|
155
|
+
console.warn(to_retry_notice(arguments_list))
|
|
156
|
+
|
|
157
|
+
if (!(await did_push_time_out(arguments_list))) return
|
|
158
|
+
|
|
159
|
+
throw create_timeout_error(arguments_list)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const git_push_transport = {
|
|
163
|
+
push,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { git_push_transport }
|
|
167
|
+
export {
|
|
168
|
+
KEEPALIVE_SSH_COMMAND,
|
|
169
|
+
PUSH_TIMEOUT_MESSAGE,
|
|
170
|
+
PUSH_TIMEOUT_MS,
|
|
171
|
+
SSH_COMMAND_VARIABLE,
|
|
172
|
+
SSH_LEGACY_VARIABLE,
|
|
173
|
+
}
|