@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,171 @@
|
|
|
1
|
+
import { git_epic_parse, type DependencyLink } from './git-epic-parse'
|
|
2
|
+
import { format_replaced_relations } from './git-epic-reference'
|
|
3
|
+
import { git_epic_sections, type BodyLines, type SectionRange } from './git-epic-sections'
|
|
4
|
+
|
|
5
|
+
// Placing a decision record inside an epic body's `## Decisions` section.
|
|
6
|
+
//
|
|
7
|
+
// `epic-commands` requires an auto-decision to be written in **both** the epic's `## Decisions` and a
|
|
8
|
+
// comment on each child it applies to, and until now no command wrote the epic half — so a run had to
|
|
9
|
+
// read the body, edit it and `PATCH` it back by hand, which is the one operation `CLAUDE.md` forbids.
|
|
10
|
+
// Measured on runs #1333 and #1349, that repair-shaped detour is where the post-merge bookkeeping
|
|
11
|
+
// spends its round trips, and the two most recent filings skipped the epic half entirely rather than
|
|
12
|
+
// pay for it (joshuafolkken/kit#1350).
|
|
13
|
+
//
|
|
14
|
+
// So the record rides on the body edit `--add` already makes: no extra round trip, and the half that
|
|
15
|
+
// was being dropped is written by the command instead of by hand.
|
|
16
|
+
|
|
17
|
+
const DECISIONS_HEADING = '## Decisions'
|
|
18
|
+
const DECISIONS_HEADING_PATTERN = /^#{1,6}[ \t]+Decisions\b/u
|
|
19
|
+
const BLANK_LINE = ''
|
|
20
|
+
// Editors count from one; `find_indices` answers a zero-based index.
|
|
21
|
+
const FIRST_LINE_NUMBER = 1
|
|
22
|
+
|
|
23
|
+
// A record that says nothing is worse than no record: it satisfies the "was it written" question
|
|
24
|
+
// while leaving the reasoning unrecoverable. Refused before anything is written.
|
|
25
|
+
const EMPTY_RECORD =
|
|
26
|
+
'The decision record is empty; write the record before recording it, or leave `--decision-file` off.'
|
|
27
|
+
|
|
28
|
+
// **The offending line is named, never quoted.** The record is a file the caller handed over, and
|
|
29
|
+
// echoing a line of it into stderr puts arbitrary file content in the console — the leak SonarCloud's
|
|
30
|
+
// `tssecurity:S8689` reports for exactly this path on joshuafolkken/kit#1350. A line number is as
|
|
31
|
+
// actionable, since the author has the file open, and it carries nothing out of it.
|
|
32
|
+
function to_declaration_error(line_number: number): string {
|
|
33
|
+
return `Line ${String(line_number)} of the decision record is nothing but a dependency chain, which \`epic:next\` would read as part of the epic's dependency order; wrap it in backticks, fence it, or reword it.`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Whether the record can be written at all. The declaration check is the load-bearing one: a bare
|
|
37
|
+
// `#A -> #B` line anywhere in the body is parsed as a declaration, so a record quoting an order as a
|
|
38
|
+
// standalone line would silently add a dependency nobody declared — the failure mode
|
|
39
|
+
// joshuafolkken/kit#1253 documents, arriving by a second route.
|
|
40
|
+
//
|
|
41
|
+
// **It is judged exactly the way the merged body will be judged**: the predicate is the parser's own,
|
|
42
|
+
// and the lines are read through the same fence mask, so a record whose chain sits inside a fenced
|
|
43
|
+
// block — which the parser ignores once merged — is accepted rather than refused with advice to wrap in
|
|
44
|
+
// backticks that the fence has already given it.
|
|
45
|
+
function find_decision_error(record: string): string | undefined {
|
|
46
|
+
if (record.trim().length === 0) return EMPTY_RECORD
|
|
47
|
+
|
|
48
|
+
const input = git_epic_sections.to_body_lines(record)
|
|
49
|
+
const [found] = git_epic_sections.find_indices(input, (line) =>
|
|
50
|
+
git_epic_parse.is_declaration_line(line),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return found === undefined ? undefined : to_declaration_error(found + FIRST_LINE_NUMBER)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// The record as the lines it contributes, with a blank line in front so it never runs into whatever
|
|
57
|
+
// it is appended after. Trailing blanks are dropped rather than preserved: the record's own file
|
|
58
|
+
// almost always ends with a newline, and keeping it would grow the section by a blank line per entry.
|
|
59
|
+
function to_record_lines(record: string): Array<string> {
|
|
60
|
+
return [BLANK_LINE, ...record.trimEnd().split('\n')]
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// A body with no `## Decisions` section at all: the section is created at the end, which is where
|
|
64
|
+
// every epic that has one carries it (`epic --add --decision-file` writes it there, after `## Progress`).
|
|
65
|
+
function to_new_section(lines: ReadonlyArray<string>, record: string): Array<string> {
|
|
66
|
+
return [...lines, BLANK_LINE, DECISIONS_HEADING, ...to_record_lines(record)]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// The last line of the section that is not blank, as an offset into the whole body. Appending after
|
|
70
|
+
// it rather than at `range.end` keeps the blank line that separates the section from the next heading
|
|
71
|
+
// where it was, instead of pushing the record below it and outside the section.
|
|
72
|
+
function last_content_index(input: BodyLines, range: SectionRange): number {
|
|
73
|
+
const inside = input.lines.slice(range.start, range.end)
|
|
74
|
+
const offset = inside.findLastIndex((line) => line.trim().length > 0)
|
|
75
|
+
|
|
76
|
+
return offset === -1 ? range.start : range.start + offset + 1
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Append the record to the epic's `## Decisions` section, creating the section when there is none.
|
|
80
|
+
//
|
|
81
|
+
// The section's *end* rather than its start: the entries are a log, and a reader looking for the most
|
|
82
|
+
// recent decision reads down. Nothing else in the body moves.
|
|
83
|
+
function append_decision(body: string, record: string): string {
|
|
84
|
+
const input = git_epic_sections.to_body_lines(body)
|
|
85
|
+
const range = git_epic_sections.find_section_range(input, DECISIONS_HEADING_PATTERN)
|
|
86
|
+
if (range === undefined) return to_new_section(input.lines, record).join('\n')
|
|
87
|
+
|
|
88
|
+
const at = last_content_index(input, range)
|
|
89
|
+
|
|
90
|
+
return [...input.lines.slice(0, at), ...to_record_lines(record), ...input.lines.slice(at)].join(
|
|
91
|
+
'\n',
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// The record as it will actually be written, with the relations this insertion replaced appended to
|
|
96
|
+
// it (joshuafolkken/kit#1711).
|
|
97
|
+
//
|
|
98
|
+
// **A positioned `--add` discards the `blocked-by` relation the child already had, and until now the
|
|
99
|
+
// record said nothing about it.** On joshuafolkken/kit#1703 that overwrote a decision whose reasoning
|
|
100
|
+
// was written down, twice in four minutes, leaving the body's declaration, the native relations and
|
|
101
|
+
// the recorded decision disagreeing with one another. The record is the artifact read months later, so
|
|
102
|
+
// it is where what was replaced has to survive — the console line scrolls away.
|
|
103
|
+
//
|
|
104
|
+
// **The policy is to report, not to refuse.** Re-pointing a position is what joshuafolkken/kit#1701
|
|
105
|
+
// deliberately added, so refusing an invocation that carries no `--decision-file` would close a
|
|
106
|
+
// working route to force a record; naming what was dropped costs the caller nothing and loses nothing.
|
|
107
|
+
//
|
|
108
|
+
// `undefined` stays `undefined`: an insertion that records no decision gains none here, and an
|
|
109
|
+
// insertion that replaced nothing gains no line.
|
|
110
|
+
function append_replacements(
|
|
111
|
+
record: string | undefined,
|
|
112
|
+
links: ReadonlyArray<DependencyLink>,
|
|
113
|
+
): string | undefined {
|
|
114
|
+
if (record === undefined || links.length === 0) return record
|
|
115
|
+
|
|
116
|
+
return [record.trimEnd(), BLANK_LINE, format_replaced_relations(links)].join('\n')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// What happened to the child half of the record, phrased as a count for the reason the relation report
|
|
120
|
+
// is: the useful signal is whether every child now carries the reasoning, not which comment was
|
|
121
|
+
// refused. The epic half is never reported here — it rode on the body edit, so it landed or the
|
|
122
|
+
// insertion did not.
|
|
123
|
+
function format_decision_report(input: { total: number; failures: number }): string {
|
|
124
|
+
if (input.failures === 0) {
|
|
125
|
+
return `📝 Decision recorded on the epic and ${String(input.total)} child issue(s).`
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return `⚠️ ${String(input.failures)} of ${String(input.total)} child comment(s) could not be posted; the epic's \`${DECISIONS_HEADING}\` entry is intact.`
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// The heading a creation writes its reasoning under. Beside a pattern exactly as `DECISIONS_HEADING`
|
|
132
|
+
// is, and tied to `git_epic_body`'s own literal by a test that reads a body the builder produced
|
|
133
|
+
// rather than by a string comparison (joshuafolkken/kit#1712).
|
|
134
|
+
const RATIONALE_HEADING_PATTERN = /^#{1,6}[ \t]+Split rationale\b/u
|
|
135
|
+
|
|
136
|
+
function read_section(body: string, heading: RegExp): string {
|
|
137
|
+
const input = git_epic_sections.to_body_lines(body)
|
|
138
|
+
const range = git_epic_sections.find_section_range(input, heading)
|
|
139
|
+
if (range === undefined) return ''
|
|
140
|
+
|
|
141
|
+
return input.lines.slice(range.start, range.end).join('\n')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Every place the epic body itself records why something was decided: the `## Decisions` log an
|
|
145
|
+
// insertion or a removal appends to, **and** the `## Split rationale` a creation writes.
|
|
146
|
+
//
|
|
147
|
+
// Both, not just the first. `josh epic … --ordered` declares a whole chain and records its reasoning
|
|
148
|
+
// under `## Split rationale`, writing no `## Decisions` at all — so a reader that looked only at
|
|
149
|
+
// `## Decisions` would report every correctly-documented ordered epic as unjustified the moment it
|
|
150
|
+
// was created (joshuafolkken/kit#1712). It is this module's because the heading patterns are: a
|
|
151
|
+
// second reader with its own copies is one that comes to disagree with the writers about where a
|
|
152
|
+
// record goes.
|
|
153
|
+
function read_recorded_reasons(body: string | undefined): string {
|
|
154
|
+
if (body === undefined) return ''
|
|
155
|
+
|
|
156
|
+
return [
|
|
157
|
+
read_section(body, DECISIONS_HEADING_PATTERN),
|
|
158
|
+
read_section(body, RATIONALE_HEADING_PATTERN),
|
|
159
|
+
].join('\n')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const git_epic_decision = {
|
|
163
|
+
DECISIONS_HEADING,
|
|
164
|
+
append_decision,
|
|
165
|
+
append_replacements,
|
|
166
|
+
read_recorded_reasons,
|
|
167
|
+
find_decision_error,
|
|
168
|
+
format_decision_report,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export { git_epic_decision }
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
// An epic Issue tracks its children as a markdown task list (`- [ ] #101`). Only that syntax
|
|
2
|
+
// counts as tracked: GitHub auto-checks such an entry when the referenced Issue closes, whereas a
|
|
3
|
+
// bare `#101` reference produces a cross-link with no progress tracking.
|
|
4
|
+
//
|
|
5
|
+
// The source is shared by the whole-body scan and the single-line test rather than written twice: a
|
|
6
|
+
// rewriter has to recognize exactly the rows the reader counts, and two copies of this pattern would
|
|
7
|
+
// be two chances to disagree about what a tracked row is (joshuafolkken/kit#890).
|
|
8
|
+
const TASK_LIST_ISSUE_SOURCE = String.raw`^[ \t]*[-*+][ \t]+\[[ xX]\][ \t]+#(\d+)\b`
|
|
9
|
+
const TASK_LIST_ISSUE_PATTERN = new RegExp(TASK_LIST_ISSUE_SOURCE, 'gmu')
|
|
10
|
+
const TASK_LIST_LINE_PATTERN = new RegExp(TASK_LIST_ISSUE_SOURCE, 'u')
|
|
11
|
+
|
|
12
|
+
// A task list may also reference an Issue in another repository (`owner/repo#101`, or a full URL).
|
|
13
|
+
// Detecting one is what the auto-close used to bail on; joshuafolkken/kit#864 reads them instead,
|
|
14
|
+
// against their own repository, and the pattern below extracts which repository and which issue.
|
|
15
|
+
// `owner/repo#101` on its own. The row patterns below are built from this source, so what counts as
|
|
16
|
+
// a cross-repository reference has one definition — a second copy would let a form the task list
|
|
17
|
+
// accepts be refused where a person types it, or the reverse (joshuafolkken/kit#985).
|
|
18
|
+
const EXTERNAL_REFERENCE_SOURCE = String.raw`([\w.-]+)\/([\w.-]+)#(\d+)`
|
|
19
|
+
const EXTERNAL_REFERENCE_PATTERN = new RegExp(`^${EXTERNAL_REFERENCE_SOURCE}$`, 'u')
|
|
20
|
+
const TASK_LIST_ROW_SOURCE = String.raw`^[ \t]*[-*+][ \t]+\[[ xX]\][ \t]+`
|
|
21
|
+
const EXTERNAL_TASK_LIST_PATTERN = new RegExp(
|
|
22
|
+
String.raw`${TASK_LIST_ROW_SOURCE}(?:${EXTERNAL_REFERENCE_SOURCE}|https?:\/\/)`,
|
|
23
|
+
'mu',
|
|
24
|
+
)
|
|
25
|
+
// `- [ ] owner/repo#101`
|
|
26
|
+
const EXTERNAL_SHORTHAND_PATTERN = new RegExp(
|
|
27
|
+
String.raw`${TASK_LIST_ROW_SOURCE}${EXTERNAL_REFERENCE_SOURCE}\b`,
|
|
28
|
+
'gmu',
|
|
29
|
+
)
|
|
30
|
+
// `- [ ] https://github.com/owner/repo/issues/101`
|
|
31
|
+
const EXTERNAL_URL_PATTERN =
|
|
32
|
+
/^[ \t]*[-*+][ \t]+\[[ xX]\][ \t]+https?:\/\/github\.com\/([\w.-]+)\/([\w.-]+)\/issues\/(\d+)\b/gmu
|
|
33
|
+
|
|
34
|
+
// Fenced blocks are stripped before matching. An epic body may quote the body template itself, and
|
|
35
|
+
// its sample rows (`- [ ] #101 <title>`) are illustrations, not tracked children — counting them
|
|
36
|
+
// would attach a nonexistent Issue to the batch and keep the epic open forever.
|
|
37
|
+
const FENCE_LINE_PATTERN = /^[ \t]*(?:`{3,}|~{3,})/u
|
|
38
|
+
|
|
39
|
+
// A chain between two Issue references (`#101 -> #102`, or the arrow written as `→`), read for its
|
|
40
|
+
// links. `epic:next` compares what the body declares against the `blocked-by` relations actually
|
|
41
|
+
// recorded, and a body that says one order while the relations say another must stop the run rather
|
|
42
|
+
// than silently follow either (joshuafolkken/kit#860).
|
|
43
|
+
//
|
|
44
|
+
// Only a line that is *nothing but* a chain counts, optionally behind a list marker. Measured
|
|
45
|
+
// against joshuafolkken/kit#858, whose Dependencies section is followed by a prose line recommending
|
|
46
|
+
// an execution order — e.g. `recommended order: #869 -> #863 -> …`. Those arrows are a suggestion, not a
|
|
47
|
+
// declaration, and reading them as one reported four disagreements that did not exist.
|
|
48
|
+
const DECLARED_CHAIN_LINE = /^(?:[-*+][ \t]+)?#\d+(?:[ \t]*(?:->|→)[ \t]*#\d+)+$/u
|
|
49
|
+
const CHAIN_REFERENCE_PATTERN = /#(\d+)/gu
|
|
50
|
+
|
|
51
|
+
// The other half of a machine-readable `Dependencies` section: the exact sentence that declares a
|
|
52
|
+
// batch to have no order. It lives here, beside the chain patterns, because all of them are what a
|
|
53
|
+
// reader of the body is allowed to rely on — the generator imports this rather than restating it, so
|
|
54
|
+
// the text it writes and the text checked for are one string.
|
|
55
|
+
const UNORDERED_DEPENDENCIES = 'None — the children are independent; any execution order works.'
|
|
56
|
+
|
|
57
|
+
const CLOSED_STATE = 'CLOSED'
|
|
58
|
+
|
|
59
|
+
// Which lines a body predicate is allowed to read: `false` for a fence line and for everything
|
|
60
|
+
// between a pair of them. Returned as a mask rather than a filtered string because a rewriter has to
|
|
61
|
+
// put lines back where it found them, and it must skip exactly the lines the readers skip — two
|
|
62
|
+
// separate fence walks would be two chances to disagree (joshuafolkken/kit#890).
|
|
63
|
+
//
|
|
64
|
+
// Toggling on each fence line keeps this linear — a single regex spanning the block would backtrack.
|
|
65
|
+
// An unterminated fence swallows the rest of the body, which fails safe: fewer children means the
|
|
66
|
+
// epic is simply never matched, and it stays open for manual closing.
|
|
67
|
+
function fence_mask(body: string): Array<boolean> {
|
|
68
|
+
let is_inside_fence = false
|
|
69
|
+
|
|
70
|
+
return body.split('\n').map((line) => {
|
|
71
|
+
if (FENCE_LINE_PATTERN.test(line)) {
|
|
72
|
+
is_inside_fence = !is_inside_fence
|
|
73
|
+
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return !is_inside_fence
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function strip_fenced_blocks(body: string): string {
|
|
82
|
+
const mask = fence_mask(body)
|
|
83
|
+
|
|
84
|
+
return body
|
|
85
|
+
.split('\n')
|
|
86
|
+
.filter((_, index) => mask[index] === true)
|
|
87
|
+
.join('\n')
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function to_issue_number(match: RegExpMatchArray): number | undefined {
|
|
91
|
+
const [, raw] = match
|
|
92
|
+
if (raw === undefined) return undefined
|
|
93
|
+
|
|
94
|
+
const parsed = Number(raw)
|
|
95
|
+
|
|
96
|
+
return Number.isSafeInteger(parsed) ? parsed : undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parse_task_list_issue_numbers(body: string | undefined): Array<number> {
|
|
100
|
+
if (body === undefined) return []
|
|
101
|
+
|
|
102
|
+
const numbers = Array.from(strip_fenced_blocks(body).matchAll(TASK_LIST_ISSUE_PATTERN), (match) =>
|
|
103
|
+
to_issue_number(match),
|
|
104
|
+
).filter((value): value is number => value !== undefined)
|
|
105
|
+
|
|
106
|
+
return [...new Set(numbers)]
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Every body predicate must strip fenced blocks first, for the reason given on FENCE_LINE_PATTERN.
|
|
110
|
+
// The patterns are non-global, so `test` keeps no `lastIndex` state between calls.
|
|
111
|
+
function has_pattern_match(pattern: RegExp, body: string | undefined): boolean {
|
|
112
|
+
if (body === undefined) return false
|
|
113
|
+
|
|
114
|
+
return pattern.test(strip_fenced_blocks(body))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function has_external_task_list_entry(body: string | undefined): boolean {
|
|
118
|
+
return has_pattern_match(EXTERNAL_TASK_LIST_PATTERN, body)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// A child of this epic that lives in another repository.
|
|
122
|
+
interface ExternalChild {
|
|
123
|
+
repo: string
|
|
124
|
+
number: number
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const OWNER_GROUP = 1
|
|
128
|
+
const REPO_GROUP = 2
|
|
129
|
+
const EXTERNAL_NUMBER_GROUP = 3
|
|
130
|
+
|
|
131
|
+
function to_external_child(match: RegExpMatchArray): ExternalChild | undefined {
|
|
132
|
+
const owner = match[OWNER_GROUP]
|
|
133
|
+
const repo = match[REPO_GROUP]
|
|
134
|
+
if (owner === undefined || repo === undefined) return undefined
|
|
135
|
+
const parsed = Number(match[EXTERNAL_NUMBER_GROUP])
|
|
136
|
+
|
|
137
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) return undefined
|
|
138
|
+
|
|
139
|
+
return { repo: `${owner}/${repo}`, number: parsed }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// A bare `owner/repo#101`, as a person types it — the same shape the task-list rows carry, read
|
|
143
|
+
// from a command argument rather than from a body. It reuses `to_external_child` so the two cannot
|
|
144
|
+
// disagree about which owner and repository names are acceptable (joshuafolkken/kit#985).
|
|
145
|
+
function parse_external_reference(text: string): ExternalChild | undefined {
|
|
146
|
+
const match = EXTERNAL_REFERENCE_PATTERN.exec(text.trim())
|
|
147
|
+
if (match === null) return undefined
|
|
148
|
+
|
|
149
|
+
return to_external_child(match)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function match_external(body: string, pattern: RegExp): Array<ExternalChild> {
|
|
153
|
+
return Array.from(body.matchAll(pattern), (match) => to_external_child(match)).filter(
|
|
154
|
+
(child): child is ExternalChild => child !== undefined,
|
|
155
|
+
)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Every cross-repository child the task list tracks, in both spellings. Reported as `owner/repo`
|
|
159
|
+
// plus a number rather than a URL, which is the form the repository map takes and the form the
|
|
160
|
+
// read's REST path is built from (joshuafolkken/kit#864).
|
|
161
|
+
function parse_external_task_list_children(body: string | undefined): Array<ExternalChild> {
|
|
162
|
+
if (body === undefined) return []
|
|
163
|
+
const stripped = strip_fenced_blocks(body)
|
|
164
|
+
const found = [
|
|
165
|
+
...match_external(stripped, EXTERNAL_SHORTHAND_PATTERN),
|
|
166
|
+
...match_external(stripped, EXTERNAL_URL_PATTERN),
|
|
167
|
+
]
|
|
168
|
+
const seen = new Set<string>()
|
|
169
|
+
|
|
170
|
+
return found.filter((child) => {
|
|
171
|
+
const key = `${child.repo}#${String(child.number)}`
|
|
172
|
+
const is_new = !seen.has(key)
|
|
173
|
+
|
|
174
|
+
seen.add(key)
|
|
175
|
+
|
|
176
|
+
return is_new
|
|
177
|
+
})
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Whether one line is a tracked child row. Used by the rewriter to find where the rows end, so a
|
|
181
|
+
// new row lands beside the existing ones rather than at the bottom of the body.
|
|
182
|
+
function is_task_list_line(line: string): boolean {
|
|
183
|
+
return TASK_LIST_LINE_PATTERN.test(line)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Fenced blocks are stripped here for the same reason they are everywhere else: an epic body may
|
|
187
|
+
// quote the template, and a declaration inside that quote is an illustration, not a declaration.
|
|
188
|
+
function has_unordered_declaration(body: string | undefined): boolean {
|
|
189
|
+
if (body === undefined) return false
|
|
190
|
+
|
|
191
|
+
return strip_fenced_blocks(body).includes(UNORDERED_DEPENDENCIES)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Whether one line, on its own, is part of a machine-readable `Dependencies` declaration — a chain or
|
|
195
|
+
// the unordered sentence. It lives here beside the two patterns it tests rather than in either of the
|
|
196
|
+
// modules that rewrite a body, because both of them need it and a second copy is where one comes to
|
|
197
|
+
// disagree with the parser about what counts as a declaration (joshuafolkken/kit#1350).
|
|
198
|
+
function is_declaration_line(line: string): boolean {
|
|
199
|
+
const trimmed = line.trim()
|
|
200
|
+
|
|
201
|
+
return DECLARED_CHAIN_LINE.test(trimmed) || trimmed === UNORDERED_DEPENDENCIES
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// One declared link: `blocker` must finish before `blocked` starts.
|
|
205
|
+
interface DependencyLink {
|
|
206
|
+
blocker: number
|
|
207
|
+
blocked: number
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const REFERENCE_GROUP = 1
|
|
211
|
+
|
|
212
|
+
// The issue numbers of one chain line, in order.
|
|
213
|
+
function chain_references(line: string): Array<number> {
|
|
214
|
+
return Array.from(line.matchAll(CHAIN_REFERENCE_PATTERN), (match) =>
|
|
215
|
+
Number(match[REFERENCE_GROUP]),
|
|
216
|
+
).filter((value) => Number.isSafeInteger(value))
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// `#1 -> #2 -> #3` becomes two links; consecutive links share their middle reference.
|
|
220
|
+
function chain_links(references: ReadonlyArray<number>): Array<DependencyLink> {
|
|
221
|
+
return references
|
|
222
|
+
.slice(1)
|
|
223
|
+
.map((blocked, index) => ({ blocker: references[index] ?? blocked, blocked }))
|
|
224
|
+
.filter((link) => link.blocker !== link.blocked)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Every declared chain, one entry per chain line, each holding its references in the order written.
|
|
228
|
+
// Read at this granularity rather than as a flat link list because an insertion has to know *which*
|
|
229
|
+
// chain a target sits in: two disjoint chains and one branching chain produce the same links, and
|
|
230
|
+
// only the line structure tells them apart (joshuafolkken/kit#890).
|
|
231
|
+
//
|
|
232
|
+
// Fenced blocks are stripped first for the reason they are everywhere else: a quoted template's
|
|
233
|
+
// sample chain is an illustration.
|
|
234
|
+
function parse_dependency_chains(body: string | undefined): Array<Array<number>> {
|
|
235
|
+
if (body === undefined) return []
|
|
236
|
+
|
|
237
|
+
return strip_fenced_blocks(body)
|
|
238
|
+
.split('\n')
|
|
239
|
+
.map((line) => line.trim())
|
|
240
|
+
.filter((line) => DECLARED_CHAIN_LINE.test(line))
|
|
241
|
+
.map((line) => chain_references(line))
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Every link the body declares, in the order written. Flattened from the chains above rather than
|
|
245
|
+
// re-scanning the body, so "what a chain line is" has one definition.
|
|
246
|
+
function parse_dependency_links(body: string | undefined): Array<DependencyLink> {
|
|
247
|
+
return parse_dependency_chains(body).flatMap((references) => chain_links(references))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Whether the body declares an order at all — asked by `epic:check` and by the order-unrecorded
|
|
251
|
+
// warning, which need to tell "the order was never recorded" from "there is no order".
|
|
252
|
+
//
|
|
253
|
+
// Answered from the chains above rather than from a pattern of its own, because a second pattern is
|
|
254
|
+
// a second answer: until joshuafolkken/kit#1155 this scanned the whole body for a bare `#N -> #M`,
|
|
255
|
+
// so a rationale paragraph recommending an execution order made an epic declared
|
|
256
|
+
// `None — the children are independent` report as ordered, and `josh followup` then said the batch
|
|
257
|
+
// order was never recorded on every child's merge. The narrowing joshuafolkken/kit#858 applied to
|
|
258
|
+
// the link reader was the same judgement, and `epic --add` writes on that judgement too
|
|
259
|
+
// (`git-epic-add-body.ts` protects an arrow outside the `Dependencies` section as prose) — so the
|
|
260
|
+
// three readers of one body now recognize the same lines, instead of two patterns that could
|
|
261
|
+
// disagree about which line is a declaration. They still answer different questions of those lines:
|
|
262
|
+
// a self-loop (`#101 -> #101`) is a declaration here and yields no link, since `chain_links` drops
|
|
263
|
+
// an edge from an issue to itself.
|
|
264
|
+
function has_declared_dependency_chain(body: string | undefined): boolean {
|
|
265
|
+
return parse_dependency_chains(body).length > 0
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// What the body declares about order, as the two independent answers every reader of it needs. Read
|
|
269
|
+
// from the whole fence-stripped body rather than from the `Dependencies` section, because that is
|
|
270
|
+
// where `epic:next` reads its links from: a chain line left outside the section is followed by the
|
|
271
|
+
// run, so a check that could not see it would call such a body consistent.
|
|
272
|
+
interface DeclarationState {
|
|
273
|
+
has_chain: boolean
|
|
274
|
+
has_none_literal: boolean
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function read_declaration(body: string | undefined): DeclarationState {
|
|
278
|
+
return {
|
|
279
|
+
has_chain: has_declared_dependency_chain(body),
|
|
280
|
+
has_none_literal: has_unordered_declaration(body),
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Whether that declaration says something a machine can act on: exactly one of the two forms, never
|
|
285
|
+
// both. A body carrying a chain *and* the `None — ...` literal declares an order and declares that
|
|
286
|
+
// there is none, and `epic:check` used to pass it while reporting only the half that contradicts the
|
|
287
|
+
// other (joshuafolkken/kit#1155). Single-sourced here because `epic:check`, `epic --add` and
|
|
288
|
+
// `epic --promote` all mean this same question, and three copies of the disjunction were three
|
|
289
|
+
// chances to accept a body the check rejects.
|
|
290
|
+
function is_declaration_readable(state: DeclarationState): boolean {
|
|
291
|
+
return state.has_chain !== state.has_none_literal
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function has_machine_readable_declaration(body: string | undefined): boolean {
|
|
295
|
+
return is_declaration_readable(read_declaration(body))
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function has_child(children: ReadonlyArray<number>, issue_number: number): boolean {
|
|
299
|
+
return children.includes(issue_number)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// The Issue the merged PR just closed is treated as closed without querying it. GitHub applies the
|
|
303
|
+
// `closes #N` side effect asynchronously, so reading its state right after the merge is a race that
|
|
304
|
+
// would intermittently leave a finished epic open.
|
|
305
|
+
function is_state_closed(state: string | undefined): boolean {
|
|
306
|
+
return state?.toUpperCase() === CLOSED_STATE
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const git_epic_parse = {
|
|
310
|
+
fence_mask,
|
|
311
|
+
is_task_list_line,
|
|
312
|
+
is_declaration_line,
|
|
313
|
+
chain_links,
|
|
314
|
+
parse_dependency_chains,
|
|
315
|
+
parse_task_list_issue_numbers,
|
|
316
|
+
has_external_task_list_entry,
|
|
317
|
+
has_declared_dependency_chain,
|
|
318
|
+
has_unordered_declaration,
|
|
319
|
+
read_declaration,
|
|
320
|
+
is_declaration_readable,
|
|
321
|
+
has_machine_readable_declaration,
|
|
322
|
+
parse_dependency_links,
|
|
323
|
+
parse_external_task_list_children,
|
|
324
|
+
parse_external_reference,
|
|
325
|
+
has_child,
|
|
326
|
+
is_state_closed,
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export type { DeclarationState, DependencyLink, ExternalChild }
|
|
330
|
+
export {
|
|
331
|
+
git_epic_parse,
|
|
332
|
+
fence_mask,
|
|
333
|
+
is_task_list_line,
|
|
334
|
+
is_declaration_line,
|
|
335
|
+
chain_links,
|
|
336
|
+
parse_dependency_chains,
|
|
337
|
+
parse_task_list_issue_numbers,
|
|
338
|
+
has_external_task_list_entry,
|
|
339
|
+
has_declared_dependency_chain,
|
|
340
|
+
has_unordered_declaration,
|
|
341
|
+
read_declaration,
|
|
342
|
+
is_declaration_readable,
|
|
343
|
+
has_machine_readable_declaration,
|
|
344
|
+
parse_dependency_links,
|
|
345
|
+
parse_external_task_list_children,
|
|
346
|
+
parse_external_reference,
|
|
347
|
+
has_child,
|
|
348
|
+
is_state_closed,
|
|
349
|
+
UNORDERED_DEPENDENCIES,
|
|
350
|
+
DECLARED_CHAIN_LINE,
|
|
351
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { git_epic_body } from './git-epic-body'
|
|
2
|
+
import { git_epic_parse } from './git-epic-parse'
|
|
3
|
+
|
|
4
|
+
// Promoting an existing issue into an epic.
|
|
5
|
+
//
|
|
6
|
+
// The discussion that concluded "this is really several issues" is almost always *inside* an
|
|
7
|
+
// existing issue, and that discussion is usually the split rationale itself. Creating a separate
|
|
8
|
+
// epic leaves two issues tracking one topic, so the promotion appends the epic's sections to the
|
|
9
|
+
// body rather than replacing it (joshuafolkken/kit#865).
|
|
10
|
+
|
|
11
|
+
const EPIC_SECTION_MARKER = '## Progress'
|
|
12
|
+
const PROMOTED_HEADING = '## Split into children'
|
|
13
|
+
|
|
14
|
+
interface PromoteInput {
|
|
15
|
+
body: string | undefined
|
|
16
|
+
children: ReadonlyArray<number>
|
|
17
|
+
rationale: string
|
|
18
|
+
is_ordered: boolean
|
|
19
|
+
epic_number: number
|
|
20
|
+
origin?: string | undefined
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Whether appending the epic sections would leave the body tracking two sets of children.
|
|
24
|
+
//
|
|
25
|
+
// The signal is task-list rows, not the promoted heading: an issue created by `josh epic` already
|
|
26
|
+
// carries a task list without ever having been promoted, and appending to it would produce two task
|
|
27
|
+
// lists and two contradictory `## Dependencies` sections. A pre-existing row on an ordinary issue —
|
|
28
|
+
// someone's `- [x] #850` checklist — is the same hazard from the other direction, since the promoted
|
|
29
|
+
// body keeps everything that was there and every parser scans the whole thing.
|
|
30
|
+
//
|
|
31
|
+
// Detected from the body rather than the `epic` label, which can be applied by hand without any of
|
|
32
|
+
// the sections.
|
|
33
|
+
function has_conflicting_tracking(body: string | undefined): boolean {
|
|
34
|
+
if (body === undefined) return false
|
|
35
|
+
if (body.includes(PROMOTED_HEADING)) return true
|
|
36
|
+
|
|
37
|
+
return git_epic_parse.parse_task_list_issue_numbers(body).length > 0
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Why the promotion was refused, phrased as what was found rather than as a rule number.
|
|
41
|
+
function conflict_reason(body: string | undefined): string {
|
|
42
|
+
if (body?.includes(PROMOTED_HEADING) === true) return 'it already carries the epic sections'
|
|
43
|
+
const tracked = git_epic_parse.parse_task_list_issue_numbers(body)
|
|
44
|
+
const list = tracked.map((child) => `#${String(child)}`).join(', ')
|
|
45
|
+
|
|
46
|
+
return `its body already tracks ${list} as a task list, which would become a second child list`
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The promoted body: everything that was there, then the epic sections under one heading that says
|
|
50
|
+
// what happened. The original text is never rewritten — it is the record of why the split was made.
|
|
51
|
+
function build_promoted_body(input: PromoteInput): string {
|
|
52
|
+
const existing = (input.body ?? '').trimEnd()
|
|
53
|
+
const epic_sections = git_epic_body.build_epic_body({
|
|
54
|
+
children: input.children,
|
|
55
|
+
rationale: input.rationale,
|
|
56
|
+
is_ordered: input.is_ordered,
|
|
57
|
+
origin: input.origin,
|
|
58
|
+
epic_number: input.epic_number,
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
return [existing, '', PROMOTED_HEADING, '', epic_sections, ''].join('\n').trimStart()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Why the promoted body would not satisfy what `epic:check` reads — a task list of children and an
|
|
65
|
+
// unambiguous machine-readable `Dependencies` declaration — or `undefined` when it would. The label
|
|
66
|
+
// is applied separately by the caller.
|
|
67
|
+
//
|
|
68
|
+
// The two causes are named apart because they need different actions and only one of them is about
|
|
69
|
+
// the children: a declaration-shaped line already present in the issue being promoted is carried
|
|
70
|
+
// into the epic verbatim, and an unordered promotion then adds the `None — ...` literal beside it,
|
|
71
|
+
// so the body would declare an order and declare that there is none. Reported as "does not track
|
|
72
|
+
// every child", that state left nothing to act on (joshuafolkken/kit#1155).
|
|
73
|
+
function declaration_error(body: string): string | undefined {
|
|
74
|
+
const state = git_epic_parse.read_declaration(body)
|
|
75
|
+
if (git_epic_parse.is_declaration_readable(state)) return undefined
|
|
76
|
+
|
|
77
|
+
return state.has_chain
|
|
78
|
+
? 'The promoted body would declare an order and declare that there is none: the issue being promoted already carries a line that is only a chain (`#N -> #M`), and it contradicts the `Dependencies` section written for the epic. Reword that line first; nothing was written.'
|
|
79
|
+
: 'The promoted body would carry no machine-readable `Dependencies` declaration; nothing was written.'
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function find_tracking_error(body: string, children: ReadonlyArray<number>): string | undefined {
|
|
83
|
+
const tracked = git_epic_parse.parse_task_list_issue_numbers(body)
|
|
84
|
+
|
|
85
|
+
if (children.some((child) => !tracked.includes(child))) {
|
|
86
|
+
return 'The promoted body would not track every child; nothing was written.'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return declaration_error(body)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const git_epic_promote = {
|
|
93
|
+
EPIC_SECTION_MARKER,
|
|
94
|
+
PROMOTED_HEADING,
|
|
95
|
+
has_conflicting_tracking,
|
|
96
|
+
conflict_reason,
|
|
97
|
+
build_promoted_body,
|
|
98
|
+
find_tracking_error,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type { PromoteInput }
|
|
102
|
+
export { git_epic_promote }
|