@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,238 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import type { IssueReference } from './git-epic-reference'
|
|
3
|
+
import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
|
|
4
|
+
import { parse_json_array_or_undefined, parse_json_object_safe } from './parse-json-array'
|
|
5
|
+
import { blocking_issue_schema } from './schemas'
|
|
6
|
+
|
|
7
|
+
// The translation between one REST issue (`repos/{owner}/{repo}/issues/{N}`) and the JSON shape
|
|
8
|
+
// `gh issue view --json <fields>` used to answer with.
|
|
9
|
+
//
|
|
10
|
+
// `gh issue view` goes through GraphQL, which a cloud session is answered 403 for while the REST
|
|
11
|
+
// endpoint is served normally (joshuafolkken/kit#1022). The reads in `git-gh-issue-read.ts` are what
|
|
12
|
+
// every epic command goes through, so they move to REST — and every caller downstream keeps reading
|
|
13
|
+
// the field names it already reads. The mapping lives here rather than beside the requests because
|
|
14
|
+
// it is pure: given the two responses, it decides the answer with nothing else to know
|
|
15
|
+
// (joshuafolkken/kit#1024).
|
|
16
|
+
|
|
17
|
+
// Only the fields the mapping itself reads are named; every other key passes through untouched,
|
|
18
|
+
// which is what lets a caller ask for a field this file has never heard of.
|
|
19
|
+
//
|
|
20
|
+
// `number` is required so that a 200 carrying something other than an issue — a proxy's HTML error
|
|
21
|
+
// page, an API message object — fails the parse rather than passing as an issue whose every field is
|
|
22
|
+
// missing. `git-epic-close` would turn that into `is_closed: false` for every child and report it as
|
|
23
|
+
// fact. The dependency summary is absent on a pull request, which the issue endpoint serves as
|
|
24
|
+
// readily as an issue, so it stays optional and tolerates an explicit null.
|
|
25
|
+
const rest_issue_schema = z.looseObject({
|
|
26
|
+
number: z.number(),
|
|
27
|
+
issue_dependencies_summary: z.looseObject({ total_blocked_by: z.number().optional() }).nullish(),
|
|
28
|
+
// Present only on a pull request, which this endpoint serves as readily as an issue.
|
|
29
|
+
pull_request: z.looseObject({ merged_at: z.string().nullish() }).nullish(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
type RestIssue = z.infer<typeof rest_issue_schema>
|
|
33
|
+
type BlockingIssue = z.infer<typeof blocking_issue_schema>
|
|
34
|
+
|
|
35
|
+
// The `blockedBy` connection as `gh` reported it: `nodes` is a page, `totalCount` is exact.
|
|
36
|
+
interface BlockedBy {
|
|
37
|
+
nodes: Array<BlockingIssue>
|
|
38
|
+
totalCount: number
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// `https://api.github.com/repos/<owner>/<repo>` — the only shape REST writes, matched at the end so
|
|
42
|
+
// a host or an api prefix that changes does not break the read.
|
|
43
|
+
const REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u
|
|
44
|
+
const REPOSITORY_URL_GROUP = 1
|
|
45
|
+
|
|
46
|
+
const BLOCKED_BY_FIELD = 'blockedBy'
|
|
47
|
+
|
|
48
|
+
// The one field name here that `gh --json` never had, and it is spelled unlike the names beside it on
|
|
49
|
+
// purpose: `blockedBy` is a connection `gh` served inside the issue, while this is the exact count
|
|
50
|
+
// GitHub already puts in the listing's own `issue_dependencies_summary`. A caller that asks for it
|
|
51
|
+
// learns whether an issue has blockers **without** the per-issue request that reading `blockedBy`
|
|
52
|
+
// costs — which is what lets `epic:bundle` stop re-reading every open issue (joshuafolkken/kit#1736).
|
|
53
|
+
//
|
|
54
|
+
// It is `undefined` rather than `0` where the summary is absent — a pull request, which this
|
|
55
|
+
// endpoint serves as readily as an issue, carries none. Reading that as "no blockers" is the one
|
|
56
|
+
// misreading this field can cause, so the absence is preserved all the way to the caller.
|
|
57
|
+
const BLOCKED_BY_COUNT_FIELD = 'blocked_by_count'
|
|
58
|
+
const STATE_FIELD = 'state'
|
|
59
|
+
const BODY_FIELD = 'body'
|
|
60
|
+
const FIELD_SEPARATOR = ','
|
|
61
|
+
const EMPTY_BODY = ''
|
|
62
|
+
|
|
63
|
+
// The two field names REST and `gh --json` disagree on. `url` is the one that bites: REST's `url` is
|
|
64
|
+
// the API endpoint, while `gh` answers the browser URL — and `epic_issue.is_pull_request` decides
|
|
65
|
+
// from `/pull/` appearing in it, which the API endpoint never carries.
|
|
66
|
+
//
|
|
67
|
+
// A Map rather than an object literal so a camelCase key needs no naming-convention exemption.
|
|
68
|
+
const REST_FIELD_NAMES = new Map<string, string>([
|
|
69
|
+
['url', 'html_url'],
|
|
70
|
+
['createdAt', 'created_at'],
|
|
71
|
+
])
|
|
72
|
+
|
|
73
|
+
const NOT_AN_ISSUE_MESSAGE = 'gh api answered something other than an issue object'
|
|
74
|
+
const NOT_AN_ISSUE_LISTING_MESSAGE = 'gh api answered something other than an issue listing'
|
|
75
|
+
const NOT_A_BLOCKER_LISTING_MESSAGE = 'gh api answered something other than a blocked-by listing'
|
|
76
|
+
|
|
77
|
+
function rest_field_name(field: string): string {
|
|
78
|
+
return REST_FIELD_NAMES.get(field) ?? field
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `number,state,labels,blockedBy` — the argument every caller already passes, unchanged so that the
|
|
82
|
+
// call sites keep naming the fields `gh` named.
|
|
83
|
+
function split_fields(fields: string): Array<string> {
|
|
84
|
+
return fields
|
|
85
|
+
.split(FIELD_SEPARATOR)
|
|
86
|
+
.map((field) => field.trim())
|
|
87
|
+
.filter((field) => field.length > 0)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// `gh issue view` served a pull request as readily as an issue, and reported a merged one as
|
|
91
|
+
// `MERGED`. REST answers `closed`, and the difference is not cosmetic: `epic_issue.normalize_state`
|
|
92
|
+
// maps everything that is not `CLOSED` to `OPEN`, so `MERGED` is what keeps a pull request pasted
|
|
93
|
+
// into an epic's task list from letting the auto-close run, and what keeps `epic:audit`'s
|
|
94
|
+
// "both closed" check on its loud side. Mapping it to `CLOSED` would flip both guards in silence.
|
|
95
|
+
function to_issue_state(rest: RestIssue, value: unknown): unknown {
|
|
96
|
+
if (typeof rest.pull_request?.merged_at === 'string') return MERGED_STATE
|
|
97
|
+
|
|
98
|
+
return typeof value === 'string' ? to_gh_state(value) : value
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// The exact blocker count GitHub reports on the issue itself. `nodes` is one page, so this is what
|
|
102
|
+
// keeps `totalCount` meaning what it meant under GraphQL rather than collapsing to the page size.
|
|
103
|
+
function total_blocked_by(rest: RestIssue): number | undefined {
|
|
104
|
+
return rest.issue_dependencies_summary?.total_blocked_by
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function to_gh_field_value(field: string, rest: RestIssue): unknown {
|
|
108
|
+
if (field === BLOCKED_BY_COUNT_FIELD) return total_blocked_by(rest)
|
|
109
|
+
|
|
110
|
+
const value = rest[rest_field_name(field)]
|
|
111
|
+
|
|
112
|
+
if (field === STATE_FIELD) return to_issue_state(rest, value)
|
|
113
|
+
|
|
114
|
+
// REST answers JSON null for an issue with no body, where `gh --json body` answers an empty
|
|
115
|
+
// string — and `issue_get_body` hands its result straight to callers that expect text.
|
|
116
|
+
return field === BODY_FIELD ? (value ?? EMPTY_BODY) : value
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// A response that is not an issue object throws rather than degrading to an empty read: the callers
|
|
120
|
+
// catch it into `undefined`, which is the same "the read failed" every other failure produces, while
|
|
121
|
+
// a partial object would be reported as an issue whose fields are all missing.
|
|
122
|
+
function parse_rest_issue(rest_json: string): RestIssue {
|
|
123
|
+
const parsed = parse_json_object_safe(rest_json, rest_issue_schema)
|
|
124
|
+
if (parsed === undefined) throw new Error(NOT_AN_ISSUE_MESSAGE)
|
|
125
|
+
|
|
126
|
+
return parsed
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// `repos/{owner}/{repo}/issues` serves pull requests alongside issues; `gh issue list` never did,
|
|
130
|
+
// and its six callers all read the answer as issues. The key is present on a pull request and
|
|
131
|
+
// absent on an issue, which is the same signal `to_issue_state` already reads
|
|
132
|
+
// (joshuafolkken/kit#1025).
|
|
133
|
+
function is_pull_request(rest: RestIssue): boolean {
|
|
134
|
+
return rest.pull_request !== undefined && rest.pull_request !== null
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// One page of the listing endpoint, whose elements are the same objects `parse_rest_issue` reads one
|
|
138
|
+
// of. It throws for the reason that one does: a response that is not a listing — `gh` answering
|
|
139
|
+
// `{"message":"API rate limit exceeded"}` — must not degrade into an empty listing, which every
|
|
140
|
+
// caller here reads as "there is nothing" (joshuafolkken/kit#950).
|
|
141
|
+
function parse_rest_issues(rest_json: string): Array<RestIssue> {
|
|
142
|
+
const parsed = parse_json_array_or_undefined(rest_json, rest_issue_schema)
|
|
143
|
+
if (parsed === undefined) throw new Error(NOT_AN_ISSUE_LISTING_MESSAGE)
|
|
144
|
+
|
|
145
|
+
return parsed
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// The connection for an issue GitHub itself says has no blockers, answered without a request. `gh`
|
|
149
|
+
// sent `blockedBy` inside the issue response, so a second request per issue would double
|
|
150
|
+
// `epic:bundle`'s pass over the whole open backlog — and the issue's own summary settles the common
|
|
151
|
+
// case, which is an issue with no blockers at all (joshuafolkken/kit#1024).
|
|
152
|
+
function empty_blocked_by(): BlockedBy {
|
|
153
|
+
return { nodes: [], totalCount: 0 }
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The `owner/repo` a REST `repository_url` names — `https://api.github.com/repos/<owner>/<repo>`.
|
|
157
|
+
//
|
|
158
|
+
// A blocker relation may cross a repository, and the number alone cannot say which one it is: issue
|
|
159
|
+
// numbers are unique per repository, so a blocker read bare resolves against the blocked child's own
|
|
160
|
+
// repository and names a different issue there (joshuafolkken/kit#1126). Undefined when the field is
|
|
161
|
+
// absent or shaped otherwise; the caller then falls back to the repository it is reading in, which is
|
|
162
|
+
// what an unqualified relation has always meant.
|
|
163
|
+
function repo_of_url(repository_url: string | undefined): string | undefined {
|
|
164
|
+
const match = REPOSITORY_URL.exec(repository_url ?? '')
|
|
165
|
+
|
|
166
|
+
return match?.[REPOSITORY_URL_GROUP]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// `repos/{owner}/{repo}/issues/{N}/dependencies/blocked_by` answers a bare array of issues, which is
|
|
170
|
+
// mapped into the connection `blocked_by_schema` expects.
|
|
171
|
+
//
|
|
172
|
+
// A listing that will not parse throws instead of answering an empty connection. That direction is
|
|
173
|
+
// the point: an empty `nodes` reads as "this child has no blockers", and `epic:next` would then hand
|
|
174
|
+
// a dependent to an unattended run before its prerequisite (joshuafolkken/kit#1005).
|
|
175
|
+
function to_blocked_by(blockers_json: string, exact_total?: number): BlockedBy {
|
|
176
|
+
const parsed = parse_json_array_or_undefined(blockers_json, blocking_issue_schema)
|
|
177
|
+
if (parsed === undefined) throw new Error(NOT_A_BLOCKER_LISTING_MESSAGE)
|
|
178
|
+
|
|
179
|
+
const nodes = parsed.map((blocker) => ({ ...blocker, state: to_gh_state(blocker.state) }))
|
|
180
|
+
|
|
181
|
+
return { nodes, totalCount: exact_total ?? nodes.length }
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// The requested fields, under the names `gh` gave them. A field REST does not carry is left out
|
|
185
|
+
// rather than filled in, exactly as an unknown `--json` field produced nothing before.
|
|
186
|
+
function to_gh_issue(
|
|
187
|
+
rest: RestIssue,
|
|
188
|
+
fields: ReadonlyArray<string>,
|
|
189
|
+
blocked_by?: BlockedBy,
|
|
190
|
+
): Record<string, unknown> {
|
|
191
|
+
return Object.fromEntries(
|
|
192
|
+
fields.map((field) => [
|
|
193
|
+
field,
|
|
194
|
+
field === BLOCKED_BY_FIELD ? blocked_by : to_gh_field_value(field, rest),
|
|
195
|
+
]),
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// One field as `--jq .<field>` printed it: a string bare, anything else as JSON, an absent value as
|
|
200
|
+
// the empty answer that already meant "there is nothing to show".
|
|
201
|
+
function to_field_text(value: unknown): string {
|
|
202
|
+
if (typeof value === 'string') return value
|
|
203
|
+
|
|
204
|
+
return value === undefined || value === null ? EMPTY_BODY : JSON.stringify(value)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const CLOSED = 'CLOSED'
|
|
208
|
+
|
|
209
|
+
// One blocker node as a reference, keeping the state the relation response carried
|
|
210
|
+
// (joshuafolkken/kit#1943). Single-sourced here because the snapshot read and the candidate re-read
|
|
211
|
+
// both unwrap the same node, and the state is omitted rather than guessed when REST did not send it.
|
|
212
|
+
function reference_of_blocker(
|
|
213
|
+
node: z.infer<typeof blocking_issue_schema>,
|
|
214
|
+
fallback_repo: string,
|
|
215
|
+
): IssueReference {
|
|
216
|
+
const repo = repo_of_url(node.repository_url) ?? fallback_repo
|
|
217
|
+
|
|
218
|
+
if (node.state === undefined) return { repo, number: node.number }
|
|
219
|
+
|
|
220
|
+
return { repo, number: node.number, state: node.state.toUpperCase() === CLOSED ? CLOSED : 'OPEN' }
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const git_gh_issue_rest = {
|
|
224
|
+
empty_blocked_by,
|
|
225
|
+
repo_of_url,
|
|
226
|
+
reference_of_blocker,
|
|
227
|
+
split_fields,
|
|
228
|
+
is_pull_request,
|
|
229
|
+
parse_rest_issue,
|
|
230
|
+
parse_rest_issues,
|
|
231
|
+
total_blocked_by,
|
|
232
|
+
to_blocked_by,
|
|
233
|
+
to_gh_issue,
|
|
234
|
+
to_field_text,
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export type { BlockedBy, RestIssue }
|
|
238
|
+
export { git_gh_issue_rest, BLOCKED_BY_FIELD, BLOCKED_BY_COUNT_FIELD }
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import { git_gh_api_path } from './git-gh-api-path'
|
|
2
|
+
import { git_gh_exec, type GhApiRequest } from './git-gh-exec'
|
|
3
|
+
|
|
4
|
+
// Writing issues and labels through REST, in the return-value contracts the `gh <noun> <verb>`
|
|
5
|
+
// wrappers had.
|
|
6
|
+
//
|
|
7
|
+
// `gh issue edit` / `comment` / `create` / `close` and `gh label create` all go through GraphQL,
|
|
8
|
+
// which a cloud session is answered 403 for while the REST endpoints are served normally
|
|
9
|
+
// (joshuafolkken/kit#1022). Split out of `git-gh-issue.ts` rather than added to it: that file was
|
|
10
|
+
// already at 215 of the 300 lines a file may hold, and the reads had been split out for the same
|
|
11
|
+
// reason (joshuafolkken/kit#957, joshuafolkken/kit#1026).
|
|
12
|
+
//
|
|
13
|
+
// **Every path here was measured against the live API before it was written.**
|
|
14
|
+
// joshuafolkken/kit#1022 deliberately measured only the reads, because a write has side effects, and
|
|
15
|
+
// left the write side as candidates to confirm one at a time. They were confirmed on a pair of
|
|
16
|
+
// throwaway issues, and one of them did not behave as its name suggests — see `read_issue_id`.
|
|
17
|
+
//
|
|
18
|
+
// The bodies still travel over stdin: `exec_gh_api` hands `body` to gh as `--input -`, so multi-line
|
|
19
|
+
// markdown depends on no shell quoting, exactly as `--body-file -` did before.
|
|
20
|
+
|
|
21
|
+
// `gh api` promotes a request carrying `--input` to POST, so a creation names no method; the two
|
|
22
|
+
// verbs that are not implied by a body do.
|
|
23
|
+
const PATCH_METHOD = 'PATCH'
|
|
24
|
+
const DELETE_METHOD = 'DELETE'
|
|
25
|
+
|
|
26
|
+
// `gh issue edit`, `gh issue comment` and `gh issue create` each printed one URL, and the callers
|
|
27
|
+
// read it — `git-epic-run.ts` parses the epic's number back out of it. REST answers the whole
|
|
28
|
+
// object, so the same value is unwrapped out of it rather than the shape being changed.
|
|
29
|
+
const HTML_URL_FILTER = '.html_url'
|
|
30
|
+
const ID_FILTER = '.id'
|
|
31
|
+
|
|
32
|
+
const LABELS_SEGMENT = '/labels'
|
|
33
|
+
const COMMENTS_SEGMENT = '/comments'
|
|
34
|
+
const CLOSED_STATE = 'closed'
|
|
35
|
+
const COLOR_HASH = '#'
|
|
36
|
+
|
|
37
|
+
// The four writers below answered `boolean` under `gh`, and their callers read it: `git-epic-run.ts`
|
|
38
|
+
// only reports the epic label when it was applied, `git-epic-relations.ts` counts the relations it
|
|
39
|
+
// could not apply, and `git-epic-close.ts` prints "close it manually" on a false. One try/catch
|
|
40
|
+
// rather than four copies of it (`CLAUDE.md` → "No clones").
|
|
41
|
+
async function did_write_succeed(write: () => Promise<unknown>): Promise<boolean> {
|
|
42
|
+
try {
|
|
43
|
+
await write()
|
|
44
|
+
|
|
45
|
+
return true
|
|
46
|
+
} catch {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function issue_edit_body(issue_number: string, body: string): Promise<string> {
|
|
52
|
+
return await git_gh_exec.exec_gh_api({
|
|
53
|
+
path: git_gh_api_path.issue_api_path(issue_number),
|
|
54
|
+
method: PATCH_METHOD,
|
|
55
|
+
body: JSON.stringify({ body }),
|
|
56
|
+
jq_filter: HTML_URL_FILTER,
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function issue_comment(issue_number: string, body: string): Promise<string> {
|
|
61
|
+
return await git_gh_exec.exec_gh_api({
|
|
62
|
+
path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
|
|
63
|
+
body: JSON.stringify({ body }),
|
|
64
|
+
jq_filter: HTML_URL_FILTER,
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The same comment, counted rather than thrown. `josh epic --add --decision-file` posts one per child
|
|
69
|
+
// **after** the epic body already carries the record, so a refused comment costs that child's copy and
|
|
70
|
+
// nothing else — an exception there would leave the caller unable to tell a landed insertion from one
|
|
71
|
+
// that wrote nothing (joshuafolkken/kit#1350).
|
|
72
|
+
async function issue_try_comment(issue_number: string, body: string): Promise<boolean> {
|
|
73
|
+
return await did_write_succeed(async () => await issue_comment(issue_number, body))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// `gh issue close --comment` posted the comment and closed the issue in one call; REST splits them.
|
|
77
|
+
// **The comment goes first**, which is what keeps the return value meaning what it meant: a `false`
|
|
78
|
+
// then says "the issue is still open" in *both* failure branches, because the state change is the
|
|
79
|
+
// last thing attempted. Closing first would answer `false` for an issue that is in fact closed, and
|
|
80
|
+
// `git-epic-close.ts` prints "close it manually" on that answer.
|
|
81
|
+
//
|
|
82
|
+
// **`comment: undefined` closes without commenting**, and it is what the ordering above costs: a run
|
|
83
|
+
// whose comment landed and whose close was refused leaves the issue open carrying the comment, so
|
|
84
|
+
// the next run must close it without posting a second copy (joshuafolkken/kit#1039). The return
|
|
85
|
+
// value keeps meaning what it meant — with no comment to post, the state change is not merely the
|
|
86
|
+
// last thing attempted but the only one.
|
|
87
|
+
//
|
|
88
|
+
// It is a required parameter that may be `undefined` rather than an optional one: skipping the
|
|
89
|
+
// announcement is a decision the caller makes from what it read, never something a call site can
|
|
90
|
+
// fall into by leaving an argument off.
|
|
91
|
+
async function issue_close(issue_number: string, comment: string | undefined): Promise<boolean> {
|
|
92
|
+
return await did_write_succeed(async () => {
|
|
93
|
+
if (comment !== undefined) await issue_comment(issue_number, comment)
|
|
94
|
+
await git_gh_exec.exec_gh_api({
|
|
95
|
+
path: git_gh_api_path.issue_api_path(issue_number),
|
|
96
|
+
method: PATCH_METHOD,
|
|
97
|
+
body: JSON.stringify({ state: CLOSED_STATE }),
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// `gh label create` accepted `#5319e7` and stripped the `#` itself; REST answers 422
|
|
103
|
+
// `{"resource":"Label","code":"invalid","field":"color"}` for the same value. The one caller passes
|
|
104
|
+
// the hash form (`EPIC_LABEL_COLOR`), so dropping it here is what keeps that call site unchanged.
|
|
105
|
+
function to_label_color(color: string): string {
|
|
106
|
+
return color.startsWith(COLOR_HASH) ? color.slice(COLOR_HASH.length) : color
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// `|| true` semantics, unchanged: an existing label answers 422 `already_exists`, which is not an
|
|
110
|
+
// error here.
|
|
111
|
+
//
|
|
112
|
+
// **What swallowing it costs did change, and in the safe direction.** Under `gh`, a label this call
|
|
113
|
+
// failed to create surfaced later — `gh issue create --label epic` could not resolve it and failed
|
|
114
|
+
// there. REST does not fail: `POST /issues` with `labels: [...]`, and `POST /issues/{N}/labels`,
|
|
115
|
+
// both **create** a label the repository does not have, with a generated color and no description
|
|
116
|
+
// (measured on joshuafolkken/kit#1026). So a swallowed failure here costs the label's color and
|
|
117
|
+
// description, never the label itself — `epic:next` and the auto-close filter on the name, and the
|
|
118
|
+
// name is applied either way.
|
|
119
|
+
async function label_ensure(input: {
|
|
120
|
+
name: string
|
|
121
|
+
color: string
|
|
122
|
+
description: string
|
|
123
|
+
}): Promise<void> {
|
|
124
|
+
try {
|
|
125
|
+
await git_gh_exec.exec_gh_api({
|
|
126
|
+
path: `${git_gh_api_path.repo_api_path()}${LABELS_SEGMENT}`,
|
|
127
|
+
body: JSON.stringify({
|
|
128
|
+
name: input.name,
|
|
129
|
+
color: to_label_color(input.color),
|
|
130
|
+
description: input.description,
|
|
131
|
+
}),
|
|
132
|
+
})
|
|
133
|
+
} catch {
|
|
134
|
+
/* the label already exists */
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// What creating an issue over REST means, as one value both execution paths build from: the
|
|
139
|
+
// collection to post to, the JSON body, and the `.html_url` unwrap that answers the browser URL
|
|
140
|
+
// `gh issue create` used to print.
|
|
141
|
+
//
|
|
142
|
+
// It exists as a request rather than only as the writer below because `josh propagate` opens its
|
|
143
|
+
// consumer's issue **synchronously** and cannot await (joshuafolkken/kit#1042). Spelling the same
|
|
144
|
+
// three decisions out again at that call site would be a second definition of the same write
|
|
145
|
+
// (`CLAUDE.md` → "No clones"), so the request is shared and only the spawn differs.
|
|
146
|
+
//
|
|
147
|
+
// `repo` names another repository, which is what propagation needs — the issue belongs to the
|
|
148
|
+
// consumer, not to the repository the command runs in. `labels` is left off the body entirely when
|
|
149
|
+
// there is none, rather than sent as an empty array: an issue with no label is what omitting the
|
|
150
|
+
// field means to the endpoint, and it keeps the labelled form the only one that creates a label.
|
|
151
|
+
function issue_create_request(input: {
|
|
152
|
+
title: string
|
|
153
|
+
body: string
|
|
154
|
+
labels?: ReadonlyArray<string>
|
|
155
|
+
repo?: string
|
|
156
|
+
}): GhApiRequest {
|
|
157
|
+
const { labels } = input
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
path: git_gh_api_path.issues_api_path(input.repo),
|
|
161
|
+
body: JSON.stringify({
|
|
162
|
+
title: input.title,
|
|
163
|
+
...(labels !== undefined && { labels }),
|
|
164
|
+
body: input.body,
|
|
165
|
+
}),
|
|
166
|
+
jq_filter: HTML_URL_FILTER,
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// The browser URL of the created issue, which is what `gh issue create` printed and what
|
|
171
|
+
// `git-epic-run.ts` parses the epic's number out of.
|
|
172
|
+
async function issue_create_with_label(input: {
|
|
173
|
+
title: string
|
|
174
|
+
label: string
|
|
175
|
+
body: string
|
|
176
|
+
}): Promise<string> {
|
|
177
|
+
return await git_gh_exec.exec_gh_api(
|
|
178
|
+
issue_create_request({ title: input.title, body: input.body, labels: [input.label] }),
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Applied after the body edit so a failure leaves an issue with the epic sections and no label,
|
|
183
|
+
// which `epic:check` reports — rather than a labelled issue with nothing to track. The caller checks
|
|
184
|
+
// the return: the label is what the auto-close filters on (joshuafolkken/kit#865).
|
|
185
|
+
async function issue_add_label(issue_number: string, label: string): Promise<boolean> {
|
|
186
|
+
return await did_write_succeed(
|
|
187
|
+
async () =>
|
|
188
|
+
await git_gh_exec.exec_gh_api({
|
|
189
|
+
path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
|
|
190
|
+
body: JSON.stringify({ labels: [label] }),
|
|
191
|
+
}),
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// The counterpart to the addition above, for a run taking its own marker back off
|
|
196
|
+
// (joshuafolkken/kit#1794). **The name travels in the path, so it is encoded**: a label is free to
|
|
197
|
+
// contain a `/` or a `#`, and an unencoded one would address a path that is not this label's.
|
|
198
|
+
//
|
|
199
|
+
// **It throws rather than answering `boolean`**, which is the one place it departs from
|
|
200
|
+
// `issue_add_label`. Its caller is a post-merge cleanup step, and the guard there
|
|
201
|
+
// (`git-followup-cleanup.ts`) reports a failure by name with the command that finishes it by hand —
|
|
202
|
+
// a `false` swallowed here would reach that guard as a success and the step would be reported as
|
|
203
|
+
// done.
|
|
204
|
+
async function issue_remove_label(issue_number: string, label: string): Promise<void> {
|
|
205
|
+
const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`
|
|
206
|
+
|
|
207
|
+
await git_gh_exec.exec_gh_api({
|
|
208
|
+
path: `${labels_path}/${encodeURIComponent(label)}`,
|
|
209
|
+
method: DELETE_METHOD,
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// The blocker's **database id**, which is the only thing the dependencies endpoint accepts — and the
|
|
214
|
+
// reason this resolution exists rather than the issue number being sent straight through.
|
|
215
|
+
//
|
|
216
|
+
// The endpoint takes `{"issue_id": <n>}` and does not check that `<n>` is an issue in this
|
|
217
|
+
// repository, or that it is the number the caller meant. Posting `{"issue_id":1036}` to a scratch
|
|
218
|
+
// issue in this repository recorded an issue in a completely unrelated repository — the one whose
|
|
219
|
+
// database id happens to be 1036 — as a blocker, with a 200 and no warning (measured on
|
|
220
|
+
// joshuafolkken/kit#1026, which names it). Every caller here names a blocker by its issue number, so
|
|
221
|
+
// sending that number would silently record an arbitrary issue from anywhere on GitHub.
|
|
222
|
+
//
|
|
223
|
+
// A resolution that does not produce a usable id throws rather than returning something to send:
|
|
224
|
+
// `jq` prints an empty line for a field it cannot reach, and `Number('')` is `0`, which is a value
|
|
225
|
+
// the endpoint would happily be given.
|
|
226
|
+
async function read_issue_id(issue_number: string): Promise<number> {
|
|
227
|
+
const raw = await git_gh_exec.exec_gh_api({
|
|
228
|
+
path: git_gh_api_path.issue_api_path(issue_number),
|
|
229
|
+
jq_filter: ID_FILTER,
|
|
230
|
+
})
|
|
231
|
+
const issue_id = Number(raw.trim())
|
|
232
|
+
|
|
233
|
+
if (!Number.isSafeInteger(issue_id) || issue_id <= 0) {
|
|
234
|
+
throw new Error(`gh api answered no database id for issue #${issue_number}`)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return issue_id
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Applied after creation, never as part of it: the relation is a nicety and the Issue is not, so a
|
|
241
|
+
// failure here costs only the relation. It no longer depends on the gh CLI's version — the
|
|
242
|
+
// dependencies endpoint is REST, and `gh api` has proxied REST since long before `--add-blocked-by`
|
|
243
|
+
// existed (joshuafolkken/kit#1026).
|
|
244
|
+
async function issue_add_blocked_by(issue_number: string, blocker: string): Promise<boolean> {
|
|
245
|
+
return await did_write_succeed(async () => {
|
|
246
|
+
const issue_id = await read_issue_id(blocker)
|
|
247
|
+
|
|
248
|
+
await git_gh_exec.exec_gh_api({
|
|
249
|
+
path: git_gh_api_path.blocked_by_api_path(issue_number),
|
|
250
|
+
body: JSON.stringify({ issue_id }),
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// The counterpart, for an insertion that re-points an existing chain: inserting `#N` between `#B`
|
|
256
|
+
// and `#M` has to drop `#B -> #M`, or the epic would declare one order and record two
|
|
257
|
+
// (joshuafolkken/kit#890). The id goes in the path here rather than in a body, and the endpoint is
|
|
258
|
+
// idempotent — deleting a relation that is not there answers 200.
|
|
259
|
+
async function issue_remove_blocked_by(issue_number: string, blocker: string): Promise<boolean> {
|
|
260
|
+
return await did_write_succeed(async () => {
|
|
261
|
+
const issue_id = await read_issue_id(blocker)
|
|
262
|
+
const relations_path = git_gh_api_path.blocked_by_api_path(issue_number)
|
|
263
|
+
|
|
264
|
+
await git_gh_exec.exec_gh_api({
|
|
265
|
+
path: `${relations_path}/${String(issue_id)}`,
|
|
266
|
+
method: DELETE_METHOD,
|
|
267
|
+
})
|
|
268
|
+
})
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const git_gh_issue_write = {
|
|
272
|
+
issue_edit_body,
|
|
273
|
+
issue_comment,
|
|
274
|
+
issue_try_comment,
|
|
275
|
+
issue_close,
|
|
276
|
+
label_ensure,
|
|
277
|
+
issue_create_request,
|
|
278
|
+
issue_create_with_label,
|
|
279
|
+
issue_add_label,
|
|
280
|
+
issue_remove_label,
|
|
281
|
+
issue_add_blocked_by,
|
|
282
|
+
issue_remove_blocked_by,
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export { git_gh_issue_write }
|