@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,101 @@
|
|
|
1
|
+
import { git_epic_decision } from './git-epic-decision'
|
|
2
|
+
import { git_epic_read } from './git-epic-read'
|
|
3
|
+
import { format_dependency_links } from './git-epic-reference'
|
|
4
|
+
import { git_epic_relations } from './git-epic-relations'
|
|
5
|
+
import { git_epic_remove_plan, type RemovePlan } from './git-epic-remove-plan'
|
|
6
|
+
import { git_gh_command } from './git-gh-command'
|
|
7
|
+
|
|
8
|
+
// `josh epic --remove <E> <M> <N> [<N2> ...] [--decision-file <path|->]` — delete a declared order
|
|
9
|
+
// from the epic's body and from the native `blocked-by` relations in one input
|
|
10
|
+
// (joshuafolkken/kit#1712).
|
|
11
|
+
//
|
|
12
|
+
// It is `--add`'s missing counterpart. `--add` exists because writing the declaration and the
|
|
13
|
+
// relations separately is what leaves them disagreeing; deleting them separately leaves them
|
|
14
|
+
// disagreeing in exactly the same way, and there was no command for it at all — so the only route
|
|
15
|
+
// was the hand edit `CLAUDE.md` forbids, twenty-nine times over on epic joshuafolkken/kit#1262.
|
|
16
|
+
|
|
17
|
+
const FAILURE_EXIT_CODE = 1
|
|
18
|
+
const SUCCESS_EXIT_CODE = 0
|
|
19
|
+
|
|
20
|
+
interface RemoveOrderInput {
|
|
21
|
+
epic_number: number
|
|
22
|
+
path: ReadonlyArray<number>
|
|
23
|
+
decision?: string | undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// The record is posted on **both ends** of every deleted order, not on one of them. Whoever later
|
|
27
|
+
// asks why `#B` is no longer waiting on `#A` may be reading either issue, and a record on one of
|
|
28
|
+
// them is a record the other reader never sees.
|
|
29
|
+
async function comment_decision(ends: ReadonlyArray<number>, decision: string): Promise<void> {
|
|
30
|
+
const posted = await Promise.all(
|
|
31
|
+
ends.map(async (end) => await git_gh_command.issue_try_comment(String(end), decision)),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
console.info(
|
|
35
|
+
git_epic_decision.format_decision_report({
|
|
36
|
+
total: ends.length,
|
|
37
|
+
failures: posted.filter((is_posted) => !is_posted).length,
|
|
38
|
+
}),
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function report_relations(plan: RemovePlan, failures: number): void {
|
|
43
|
+
if (plan.removed.length === 0) return
|
|
44
|
+
|
|
45
|
+
console.info(
|
|
46
|
+
git_epic_relations.format_relation_report({ links: plan.removed, failures, action: 'drop' }),
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async function write_plan(
|
|
51
|
+
epic_number: number,
|
|
52
|
+
plan: RemovePlan,
|
|
53
|
+
decision: string | undefined,
|
|
54
|
+
): Promise<void> {
|
|
55
|
+
await git_gh_command.issue_edit_body(String(epic_number), plan.body)
|
|
56
|
+
console.info(
|
|
57
|
+
`📋 Removed ${format_dependency_links(plan.links)} from epic #${String(epic_number)}.`,
|
|
58
|
+
)
|
|
59
|
+
report_relations(plan, await git_epic_relations.apply_relations(plan.removed, 'drop'))
|
|
60
|
+
|
|
61
|
+
if (decision !== undefined) await comment_decision(plan.ends, decision)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Delete a declared order, or refuse without writing anything. Every refusal happens before the body
|
|
65
|
+
// edit, so a rejected invocation leaves the epic exactly as it was.
|
|
66
|
+
async function remove_order(input: RemoveOrderInput): Promise<number> {
|
|
67
|
+
const epic = await git_epic_read.read_epic(input.epic_number)
|
|
68
|
+
|
|
69
|
+
if ('error' in epic) {
|
|
70
|
+
console.error(`✖ ${epic.error}`)
|
|
71
|
+
|
|
72
|
+
return FAILURE_EXIT_CODE
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const outcome = git_epic_remove_plan.build_removal_plan({
|
|
76
|
+
epic_number: input.epic_number,
|
|
77
|
+
body: epic.subject.body,
|
|
78
|
+
labels: epic.subject.labels,
|
|
79
|
+
path: input.path,
|
|
80
|
+
recorded: epic.recorded,
|
|
81
|
+
repo: epic.repo,
|
|
82
|
+
decision: input.decision,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
if ('error' in outcome) {
|
|
86
|
+
console.error(`✖ ${outcome.error}`)
|
|
87
|
+
|
|
88
|
+
return FAILURE_EXIT_CODE
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await write_plan(input.epic_number, outcome.plan, input.decision)
|
|
92
|
+
|
|
93
|
+
return SUCCESS_EXIT_CODE
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const git_epic_remove = {
|
|
97
|
+
remove_order,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export { git_epic_remove }
|
|
101
|
+
export type { RemoveOrderInput }
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { git_epic_body } from './git-epic-body'
|
|
2
|
+
import { git_epic_promote } from './git-epic-promote'
|
|
3
|
+
import { git_epic_relations } from './git-epic-relations'
|
|
4
|
+
import { git_epic_validate, type EpicSubject } from './git-epic-validate'
|
|
5
|
+
import { git_gh_command } from './git-gh-command'
|
|
6
|
+
import { EPIC_LABEL } from './issue-labels'
|
|
7
|
+
|
|
8
|
+
const EPIC_LABEL_COLOR = '#5319e7'
|
|
9
|
+
const EPIC_LABEL_DESCRIPTION = 'Tracks a batch of child issues from one split'
|
|
10
|
+
const FAILURE_EXIT_CODE = 1
|
|
11
|
+
const SUCCESS_EXIT_CODE = 0
|
|
12
|
+
|
|
13
|
+
interface CreateEpicInput {
|
|
14
|
+
title: string
|
|
15
|
+
children: ReadonlyArray<number>
|
|
16
|
+
rationale: string
|
|
17
|
+
is_ordered: boolean
|
|
18
|
+
origin?: string | undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// The relations the declared order implies, applied through the shared module `--add` also uses so
|
|
22
|
+
// the two cannot drift. A failure is reported and stepped over rather than aborting a batch that is
|
|
23
|
+
// otherwise fine — see `git-epic-relations.ts` for why the relation is not part of the contract.
|
|
24
|
+
async function apply_dependencies(input: {
|
|
25
|
+
children: ReadonlyArray<number>
|
|
26
|
+
is_ordered: boolean
|
|
27
|
+
}): Promise<void> {
|
|
28
|
+
const pairs = git_epic_body.build_dependency_pairs(input.children, input.is_ordered)
|
|
29
|
+
if (pairs.length === 0) return
|
|
30
|
+
|
|
31
|
+
const failures = await git_epic_relations.apply_relations(pairs, 'record')
|
|
32
|
+
|
|
33
|
+
console.info(
|
|
34
|
+
git_epic_relations.format_relation_report({
|
|
35
|
+
links: pairs,
|
|
36
|
+
failures,
|
|
37
|
+
action: 'record',
|
|
38
|
+
}),
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// The epic's own number, from the URL `gh issue create` prints. Needed because the run command in
|
|
43
|
+
// the body names the epic, and the number only exists once the issue does.
|
|
44
|
+
const ISSUE_URL_NUMBER = /\/(?<number>\d+)\s*$/u
|
|
45
|
+
|
|
46
|
+
function parse_created_number(url: string): number | undefined {
|
|
47
|
+
const { groups } = ISSUE_URL_NUMBER.exec(url.trim()) ?? {}
|
|
48
|
+
const { number: raw } = groups ?? {}
|
|
49
|
+
if (raw === undefined) return undefined
|
|
50
|
+
const parsed = Number(raw)
|
|
51
|
+
|
|
52
|
+
return Number.isSafeInteger(parsed) ? parsed : undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Rewrite the body once the number is known, so `## Execution` carries a command that can be run as
|
|
56
|
+
// written rather than a placeholder. A failure here costs the substitution and nothing else — the
|
|
57
|
+
// epic and its task list are already correct, and nothing machine-readable lives in that section.
|
|
58
|
+
async function fill_run_command(
|
|
59
|
+
epic_number: number | undefined,
|
|
60
|
+
input: CreateEpicInput,
|
|
61
|
+
): Promise<void> {
|
|
62
|
+
if (epic_number === undefined) {
|
|
63
|
+
console.info(
|
|
64
|
+
`⚠️ Could not read the new epic's number from its URL; the Execution section still says \`${git_epic_body.format_run_command(undefined)}\`.`,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
await git_gh_command.issue_edit_body(
|
|
72
|
+
String(epic_number),
|
|
73
|
+
git_epic_body.build_epic_body({
|
|
74
|
+
children: input.children,
|
|
75
|
+
rationale: input.rationale,
|
|
76
|
+
is_ordered: input.is_ordered,
|
|
77
|
+
origin: input.origin,
|
|
78
|
+
epic_number,
|
|
79
|
+
}),
|
|
80
|
+
)
|
|
81
|
+
} catch {
|
|
82
|
+
console.info('⚠️ Could not substitute the epic number into the Execution section.')
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function create_epic(input: CreateEpicInput): Promise<number> {
|
|
87
|
+
await git_gh_command.label_ensure({
|
|
88
|
+
name: EPIC_LABEL,
|
|
89
|
+
color: EPIC_LABEL_COLOR,
|
|
90
|
+
description: EPIC_LABEL_DESCRIPTION,
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
const body = git_epic_body.build_epic_body({
|
|
94
|
+
children: input.children,
|
|
95
|
+
rationale: input.rationale,
|
|
96
|
+
is_ordered: input.is_ordered,
|
|
97
|
+
origin: input.origin,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const url = await git_gh_command.issue_create_with_label({
|
|
101
|
+
title: input.title,
|
|
102
|
+
label: EPIC_LABEL,
|
|
103
|
+
body,
|
|
104
|
+
})
|
|
105
|
+
const epic_number = parse_created_number(url)
|
|
106
|
+
|
|
107
|
+
console.info(`📋 Created epic: ${url}`)
|
|
108
|
+
await apply_dependencies({ children: input.children, is_ordered: input.is_ordered })
|
|
109
|
+
await fill_run_command(epic_number, input)
|
|
110
|
+
console.info(`▶ Run the children with: ${git_epic_body.format_run_command(epic_number)}`)
|
|
111
|
+
|
|
112
|
+
return SUCCESS_EXIT_CODE
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface PromoteEpicInput {
|
|
116
|
+
epic_number: number
|
|
117
|
+
children: ReadonlyArray<number>
|
|
118
|
+
rationale: string
|
|
119
|
+
is_ordered: boolean
|
|
120
|
+
origin?: string | undefined
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// The issue being promoted, or the reason it cannot be. Refused when it already carries the epic
|
|
124
|
+
// sections — a second append would give the auto-close two task lists to disagree about.
|
|
125
|
+
async function read_promotion_subject(epic_number: number): Promise<EpicSubject | undefined> {
|
|
126
|
+
const subject = git_epic_validate.parse_epic_subject(
|
|
127
|
+
await git_gh_command.issue_get_labels_and_body(String(epic_number)),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if (subject === undefined) {
|
|
131
|
+
console.error(`✖ Could not read issue #${String(epic_number)}.`)
|
|
132
|
+
|
|
133
|
+
return undefined
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (git_epic_promote.has_conflicting_tracking(subject.body)) {
|
|
137
|
+
const reason = git_epic_promote.conflict_reason(subject.body)
|
|
138
|
+
|
|
139
|
+
console.error(`✖ Cannot promote #${String(epic_number)}: ${reason}.`)
|
|
140
|
+
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return subject
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Write the promoted body and apply the label. The label is what `git-epic-close.ts` filters on, so
|
|
148
|
+
// an unlabelled issue is one the auto-close skips forever — a failure there is reported rather than
|
|
149
|
+
// logged past.
|
|
150
|
+
async function write_promotion(
|
|
151
|
+
input: PromoteEpicInput,
|
|
152
|
+
existing_body: string | undefined,
|
|
153
|
+
): Promise<number> {
|
|
154
|
+
const body = git_epic_promote.build_promoted_body({ ...input, body: existing_body })
|
|
155
|
+
|
|
156
|
+
const tracking_error = git_epic_promote.find_tracking_error(body, input.children)
|
|
157
|
+
|
|
158
|
+
if (tracking_error !== undefined) {
|
|
159
|
+
console.error(`✖ ${tracking_error}`)
|
|
160
|
+
|
|
161
|
+
return FAILURE_EXIT_CODE
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
await git_gh_command.issue_edit_body(String(input.epic_number), body)
|
|
165
|
+
|
|
166
|
+
if (await git_gh_command.issue_add_label(String(input.epic_number), EPIC_LABEL)) {
|
|
167
|
+
return SUCCESS_EXIT_CODE
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
console.error(
|
|
171
|
+
`✖ Wrote the epic sections to #${String(input.epic_number)} but could not apply the \`${EPIC_LABEL}\` label; apply it by hand.`,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
return FAILURE_EXIT_CODE
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Promote an existing issue into an epic: append the epic sections, apply the label, and record the
|
|
178
|
+
// dependency relations exactly as a new epic would.
|
|
179
|
+
async function promote_epic(input: PromoteEpicInput): Promise<number> {
|
|
180
|
+
const subject = await read_promotion_subject(input.epic_number)
|
|
181
|
+
if (subject === undefined) return FAILURE_EXIT_CODE
|
|
182
|
+
|
|
183
|
+
await git_gh_command.label_ensure({
|
|
184
|
+
name: EPIC_LABEL,
|
|
185
|
+
color: EPIC_LABEL_COLOR,
|
|
186
|
+
description: EPIC_LABEL_DESCRIPTION,
|
|
187
|
+
})
|
|
188
|
+
const written = await write_promotion(input, subject.body)
|
|
189
|
+
if (written !== SUCCESS_EXIT_CODE) return written
|
|
190
|
+
|
|
191
|
+
console.info(`📋 Promoted #${String(input.epic_number)} to an epic.`)
|
|
192
|
+
await apply_dependencies({ children: input.children, is_ordered: input.is_ordered })
|
|
193
|
+
console.info(`▶ Run the children with: ${git_epic_body.format_run_command(input.epic_number)}`)
|
|
194
|
+
|
|
195
|
+
return SUCCESS_EXIT_CODE
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async function check_epic(epic_number: number): Promise<number> {
|
|
199
|
+
const raw = await git_gh_command.issue_get_labels_and_body(String(epic_number))
|
|
200
|
+
const subject = git_epic_validate.parse_epic_subject(raw)
|
|
201
|
+
|
|
202
|
+
if (subject === undefined) {
|
|
203
|
+
console.error(`✖ Could not read issue #${String(epic_number)}.`)
|
|
204
|
+
|
|
205
|
+
return FAILURE_EXIT_CODE
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const results = git_epic_validate.validate_epic(subject)
|
|
209
|
+
|
|
210
|
+
console.info(git_epic_validate.format_check_report(subject.number, results))
|
|
211
|
+
|
|
212
|
+
return git_epic_validate.is_epic_valid(results) ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const git_epic_run = {
|
|
216
|
+
parse_created_number,
|
|
217
|
+
create_epic,
|
|
218
|
+
promote_epic,
|
|
219
|
+
check_epic,
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export { git_epic_run, EPIC_LABEL_COLOR, EPIC_LABEL_DESCRIPTION, FAILURE_EXIT_CODE }
|
|
223
|
+
export type { CreateEpicInput, PromoteEpicInput }
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { git_epic_parse } from './git-epic-parse'
|
|
2
|
+
|
|
3
|
+
// Locating a `## <Name>` section inside an epic body, as the shape every rewrite of one needs.
|
|
4
|
+
//
|
|
5
|
+
// It was `git-epic-add-body.ts`'s private half: that file finds the `Dependencies` section so a
|
|
6
|
+
// declaration is replaced inside it rather than wherever a declaration-shaped line happens to sit.
|
|
7
|
+
// `## Decisions` needs the identical search, and a second copy of it is the clone `CLAUDE.md`
|
|
8
|
+
// prohibits — the fence mask especially, since a heading inside a fenced block is an illustration and
|
|
9
|
+
// a copy that forgot it would append a decision into a quoted template (joshuafolkken/kit#1350).
|
|
10
|
+
//
|
|
11
|
+
// Nothing here writes. The two consumers decide what to do with a range; this decides where one is.
|
|
12
|
+
|
|
13
|
+
// A heading of any level, with its `#` run captured so the level can be compared. Read from the
|
|
14
|
+
// trimmed line, so an indented heading inside a list still counts as one.
|
|
15
|
+
const ANY_HEADING = /^(#{1,6})[ \t]/u
|
|
16
|
+
const HEADING_LEVEL_GROUP = 1
|
|
17
|
+
const NOT_A_HEADING = 0
|
|
18
|
+
|
|
19
|
+
interface BodyLines {
|
|
20
|
+
lines: ReadonlyArray<string>
|
|
21
|
+
// `false` for a fence line and everything between a pair of them. A heading or a declaration
|
|
22
|
+
// inside a fenced block is an illustration, and treating one as real would edit a quoted template.
|
|
23
|
+
mask: ReadonlyArray<boolean>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface SectionRange {
|
|
27
|
+
// The first line after the heading, and the first line of whatever follows the section.
|
|
28
|
+
start: number
|
|
29
|
+
end: number
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Accepts the body or the lines it was already split into: `git-epic-add-body.ts` holds both forms at
|
|
33
|
+
// different points of one rewrite, and `join`/`split` round-trip exactly, so one function serves both
|
|
34
|
+
// rather than the caller re-deriving a mask that has to agree with this one.
|
|
35
|
+
function to_body_lines(source: string | ReadonlyArray<string>): BodyLines {
|
|
36
|
+
const lines = typeof source === 'string' ? source.split('\n') : source
|
|
37
|
+
|
|
38
|
+
return { lines, mask: git_epic_parse.fence_mask(lines.join('\n')) }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function is_readable(input: BodyLines, index: number): boolean {
|
|
42
|
+
return input.mask[index] === true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function find_indices(input: BodyLines, is_wanted: (line: string) => boolean): Array<number> {
|
|
46
|
+
return input.lines
|
|
47
|
+
.map((line, index) => (is_readable(input, index) && is_wanted(line) ? index : -1))
|
|
48
|
+
.filter((index) => index !== -1)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// A line's heading level, or `0` for a line that is not a heading.
|
|
52
|
+
function heading_level(line: string): number {
|
|
53
|
+
return (ANY_HEADING.exec(line.trim())?.[HEADING_LEVEL_GROUP] ?? '').length
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Whether this line closes a section opened at `level`: a readable heading of the same level or a
|
|
57
|
+
// higher one. A deeper heading belongs to the section rather than ending it.
|
|
58
|
+
function is_section_end(input: BodyLines, index: number, level: number): boolean {
|
|
59
|
+
if (!is_readable(input, index)) return false
|
|
60
|
+
const found = heading_level(input.lines[index] ?? '')
|
|
61
|
+
|
|
62
|
+
return found !== NOT_A_HEADING && found <= level
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Where the named section runs: the lines after its heading, up to the next heading **of the same or a
|
|
66
|
+
// higher level**. Not "the next heading of any level" — `## Decisions` is written as one `###` entry per
|
|
67
|
+
// decision, the template the epic body documents, so ending at any heading would make the section one
|
|
68
|
+
// line long and place every appended record after its first entry (joshuafolkken/kit#1350). A `##`
|
|
69
|
+
// section running to the next `##` is what a reader of the body already takes it to mean.
|
|
70
|
+
//
|
|
71
|
+
// `undefined` is "the body has no such section", which is a different answer from an empty one — the
|
|
72
|
+
// caller creates the section in the first case and appends inside it in the second.
|
|
73
|
+
function find_section_range(input: BodyLines, heading: RegExp): SectionRange | undefined {
|
|
74
|
+
const [found] = find_indices(input, (line) => heading.test(line.trim()))
|
|
75
|
+
if (found === undefined) return undefined
|
|
76
|
+
|
|
77
|
+
const level = heading_level(input.lines[found] ?? '')
|
|
78
|
+
const start = found + 1
|
|
79
|
+
const next = input.lines
|
|
80
|
+
.slice(start)
|
|
81
|
+
.findIndex((_line, offset) => is_section_end(input, start + offset, level))
|
|
82
|
+
|
|
83
|
+
return { start, end: next === -1 ? input.lines.length : start + next }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function is_in_range(index: number, range: SectionRange): boolean {
|
|
87
|
+
return index >= range.start && index < range.end
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const git_epic_sections = {
|
|
91
|
+
to_body_lines,
|
|
92
|
+
find_indices,
|
|
93
|
+
find_section_range,
|
|
94
|
+
is_in_range,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { git_epic_sections }
|
|
98
|
+
export type { BodyLines, SectionRange }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { git_epic_parse } from './git-epic-parse'
|
|
2
|
+
import { to_issue_reference } from './git-epic-reference'
|
|
3
|
+
import { EPIC_LABEL } from './issue-labels'
|
|
4
|
+
|
|
5
|
+
// Whether an issue is an epic this repository's writers may edit, and why it is not when it is not.
|
|
6
|
+
//
|
|
7
|
+
// Both `josh epic --add` and `josh epic --remove` ask exactly this before they compute anything: the
|
|
8
|
+
// label, the absence of a cross-repository child, a task list to place rows in, and a declaration
|
|
9
|
+
// their edit can be relative to. It lives in one module rather than in each of them, because the two
|
|
10
|
+
// commands must refuse the same inputs for the same reasons — a second copy is where one comes to
|
|
11
|
+
// accept an epic the other refuses (joshuafolkken/kit#1712).
|
|
12
|
+
|
|
13
|
+
// The part of an epic these refusals read. Narrower than either command's own input on purpose: a
|
|
14
|
+
// shape check that could see the children being placed would invite conditions that belong to the
|
|
15
|
+
// caller.
|
|
16
|
+
interface EpicShapeSubject {
|
|
17
|
+
epic_number: number
|
|
18
|
+
body: string | undefined
|
|
19
|
+
labels: ReadonlyArray<string>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function missing_declaration_error(epic_number: number): string {
|
|
23
|
+
const check = `josh epic:check ${String(epic_number)}`
|
|
24
|
+
|
|
25
|
+
return `${to_issue_reference(epic_number)} has no unambiguous machine-readable \`Dependencies\` declaration; run \`${check}\` first.`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// What to do about a target that is not an epic. The refusal is deliberate — neither command ever
|
|
29
|
+
// promotes an issue on its own, because promotion rewrites someone's issue into a container and the
|
|
30
|
+
// choice between promoting and creating a new epic depends on what the target *is*, which only a
|
|
31
|
+
// reader of it knows (`.claude/skills/workflow-commands/split-assessment.md` → promote-or-create).
|
|
32
|
+
// Naming both arms is what keeps the refusal one command away from being actionable rather than a
|
|
33
|
+
// dead end, which is the whole point of `into <target>` (joshuafolkken/kit#985).
|
|
34
|
+
function promote_remedy(epic_number: number): string {
|
|
35
|
+
const promote = `josh epic --promote ${String(epic_number)} <N...>`
|
|
36
|
+
|
|
37
|
+
return `Promote it with \`${promote}\` when it is a request, a discussion or a container; create a new epic over both when it is itself one of the deliverables.`
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The label and the task list are checked separately from the declaration because they fail
|
|
41
|
+
// differently: without rows there is nowhere to put a new one, and without a declaration there is
|
|
42
|
+
// nothing for an edit to be relative to.
|
|
43
|
+
function find_epic_shape_error(subject: EpicShapeSubject, body: string): string | undefined {
|
|
44
|
+
const reference = to_issue_reference(subject.epic_number)
|
|
45
|
+
|
|
46
|
+
if (!subject.labels.includes(EPIC_LABEL)) {
|
|
47
|
+
return `${reference} does not carry the \`${EPIC_LABEL}\` label, so it is not an epic. ${promote_remedy(subject.epic_number)}`
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (git_epic_parse.has_external_task_list_entry(body)) {
|
|
51
|
+
return `${reference} tracks a child in another repository; editing the declared order of a cross-repository epic is joshuafolkken/kit#864's scope, not this command's.`
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function find_subject_error(
|
|
58
|
+
subject: EpicShapeSubject,
|
|
59
|
+
tracked: ReadonlyArray<number>,
|
|
60
|
+
): string | undefined {
|
|
61
|
+
const reference = to_issue_reference(subject.epic_number)
|
|
62
|
+
if (subject.body === undefined) return `Could not read the body of ${reference}.`
|
|
63
|
+
const shape_error = find_epic_shape_error(subject, subject.body)
|
|
64
|
+
if (shape_error !== undefined) return shape_error
|
|
65
|
+
|
|
66
|
+
if (tracked.length === 0) {
|
|
67
|
+
return `${reference} tracks no child as a \`- [ ] #N\` row; there is nowhere to add one.`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// A declaration an edit can be relative to: exactly one of the two machine-readable forms.
|
|
71
|
+
return git_epic_parse.has_machine_readable_declaration(subject.body)
|
|
72
|
+
? undefined
|
|
73
|
+
: missing_declaration_error(subject.epic_number)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const git_epic_shape = {
|
|
77
|
+
find_subject_error,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { git_epic_shape }
|
|
81
|
+
export type { EpicShapeSubject }
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { git_epic_parse, type DeclarationState } from './git-epic-parse'
|
|
2
|
+
import { EPIC_LABEL, has_label_name } from './issue-labels'
|
|
3
|
+
import { parse_json_object_safe } from './parse-json-array'
|
|
4
|
+
import { epic_subject_schema } from './schemas'
|
|
5
|
+
|
|
6
|
+
// The four requirements an epic has to satisfy are otherwise enforced only by an agent reading the
|
|
7
|
+
// procedure carefully, and three of the four fail silently: a missing label or a bare `#N` child
|
|
8
|
+
// list makes `git-epic-close.ts` skip the epic forever, and prose dependencies make the batch read
|
|
9
|
+
// as unordered so a skipped `--add-blocked-by` is never reported. Checking them here reuses
|
|
10
|
+
// `git-epic-parse.ts` rather than restating the patterns, so "what the auto-close can read" and
|
|
11
|
+
// "what this check accepts" are one definition instead of two that can drift.
|
|
12
|
+
|
|
13
|
+
interface EpicSubject {
|
|
14
|
+
number: number
|
|
15
|
+
// The epic's own state, as GitHub returned it (`OPEN` / `CLOSED`, casing unnormalized). Only
|
|
16
|
+
// `git-epic-add.ts` reads it — to refuse adding a child to a closed epic — so it is optional: a read
|
|
17
|
+
// that came back without the field leaves it undefined, which the refusal treats as "not confirmed
|
|
18
|
+
// closed" rather than blocking (joshuafolkken/kit#2337).
|
|
19
|
+
state?: string | undefined
|
|
20
|
+
labels: ReadonlyArray<string>
|
|
21
|
+
body: string | undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface CheckResult {
|
|
25
|
+
name: string
|
|
26
|
+
is_passing: boolean
|
|
27
|
+
detail: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The `number,labels,body` read's answer, as the shape every epic writer reads. It lives beside
|
|
31
|
+
// the checks because `EpicSubject` is defined here, and each command that wanted one had otherwise
|
|
32
|
+
// to restate the unwrapping (joshuafolkken/kit#890).
|
|
33
|
+
function parse_epic_subject(raw_json: string | undefined): EpicSubject | undefined {
|
|
34
|
+
if (raw_json === undefined) return undefined
|
|
35
|
+
|
|
36
|
+
const parsed = parse_json_object_safe(raw_json, epic_subject_schema)
|
|
37
|
+
if (parsed === undefined) return undefined
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
number: parsed.number,
|
|
41
|
+
state: parsed.state,
|
|
42
|
+
labels: (parsed.labels ?? []).map((label) => label.name),
|
|
43
|
+
body: parsed.body,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// The membership test is `has_label_name` rather than `Array.includes` because GitHub keeps the
|
|
48
|
+
// casing a label was created with and treats `Epic` and `epic` as one label. Compared literally, a
|
|
49
|
+
// repository that predates these scripts was told to *add* a label it already carries — and GitHub
|
|
50
|
+
// then refuses the addition as a duplicate, so the instruction could not be followed either.
|
|
51
|
+
function check_label(subject: EpicSubject): CheckResult {
|
|
52
|
+
const is_passing = has_label_name(subject.labels, EPIC_LABEL)
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
name: 'epic label',
|
|
56
|
+
is_passing,
|
|
57
|
+
detail: is_passing
|
|
58
|
+
? `the \`${EPIC_LABEL}\` label is applied`
|
|
59
|
+
: `add the \`${EPIC_LABEL}\` label — the auto-close only looks at labelled issues`,
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function format_children(children: ReadonlyArray<number>): string {
|
|
64
|
+
return children.map((child) => `#${String(child)}`).join(', ')
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function check_task_list(subject: EpicSubject): CheckResult {
|
|
68
|
+
const children = git_epic_parse.parse_task_list_issue_numbers(subject.body)
|
|
69
|
+
const is_passing = children.length > 0
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
name: 'child task list',
|
|
73
|
+
is_passing,
|
|
74
|
+
detail: is_passing
|
|
75
|
+
? `${String(children.length)} child issue(s) tracked: ${format_children(children)}`
|
|
76
|
+
: 'no `- [ ] #N` rows found — a bare `#N` link is not tracked and never auto-closes',
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function describe_dependencies(state: DeclarationState): string {
|
|
81
|
+
if (state.has_chain && state.has_none_literal) {
|
|
82
|
+
return 'a chain (`#N -> #M`) and the `None — ...` literal are both declared; they contradict each other'
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (state.has_chain) return 'an ordered chain (`#N -> #M`) is declared'
|
|
86
|
+
if (state.has_none_literal) return 'declared as an unordered batch'
|
|
87
|
+
|
|
88
|
+
return 'neither a line that is only `#N -> #M` nor the `None — ...` literal found; an arrow sharing its line with anything else is prose, and prose order is not machine-readable'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// An unordered batch is a legitimate state, so the absence of a chain is not a failure by itself.
|
|
92
|
+
// What this reports is the two states a reader cannot act on: neither form present, so "no order"
|
|
93
|
+
// and "the order was never written down" are indistinguishable, and both present, so the body says
|
|
94
|
+
// each of them. The literal is compared against the constant the generator emits, and the chain
|
|
95
|
+
// against the one the link reader parses, so no two of them can drift into disagreement.
|
|
96
|
+
function check_dependencies(subject: EpicSubject): CheckResult {
|
|
97
|
+
const state = git_epic_parse.read_declaration(subject.body)
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
name: 'dependencies section',
|
|
101
|
+
is_passing: git_epic_parse.is_declaration_readable(state),
|
|
102
|
+
detail: describe_dependencies(state),
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// A cross-repository child cannot be resolved without a different `--repo`, so the auto-close
|
|
107
|
+
// deliberately leaves such an epic open. Reporting it here is what turns "stayed open silently"
|
|
108
|
+
// into "was told to close it manually".
|
|
109
|
+
function check_external_children(subject: EpicSubject): CheckResult {
|
|
110
|
+
const has_external = git_epic_parse.has_external_task_list_entry(subject.body)
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
name: 'auto-close eligibility',
|
|
114
|
+
is_passing: !has_external,
|
|
115
|
+
detail: has_external
|
|
116
|
+
? 'tracks a child in another repository — this epic will not auto-close; close it manually'
|
|
117
|
+
: 'every tracked child is in this repository',
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function validate_epic(subject: EpicSubject): Array<CheckResult> {
|
|
122
|
+
return [
|
|
123
|
+
check_label(subject),
|
|
124
|
+
check_task_list(subject),
|
|
125
|
+
check_dependencies(subject),
|
|
126
|
+
check_external_children(subject),
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function is_epic_valid(results: ReadonlyArray<CheckResult>): boolean {
|
|
131
|
+
return results.every((result) => result.is_passing)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function format_check_line(result: CheckResult): string {
|
|
135
|
+
return `${result.is_passing ? '✔' : '✖'} ${result.name} — ${result.detail}`
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function format_check_report(epic_number: number, results: ReadonlyArray<CheckResult>): string {
|
|
139
|
+
const lines = results.map((result) => format_check_line(result))
|
|
140
|
+
const summary = is_epic_valid(results)
|
|
141
|
+
? `✅ Epic #${String(epic_number)} satisfies every requirement.`
|
|
142
|
+
: `❌ Epic #${String(epic_number)} does not satisfy every requirement.`
|
|
143
|
+
|
|
144
|
+
return [...lines, '', summary].join('\n')
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const git_epic_validate = {
|
|
148
|
+
parse_epic_subject,
|
|
149
|
+
validate_epic,
|
|
150
|
+
is_epic_valid,
|
|
151
|
+
format_check_report,
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { git_epic_validate }
|
|
155
|
+
export type { CheckResult, EpicSubject }
|