@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,61 @@
|
|
|
1
|
+
// Shared, serialization-agnostic core for the config-merge library. Both the YAML (cspell
|
|
2
|
+
// `import`) and JSON (tsconfig `extends`) patchers compute their next list here so the
|
|
3
|
+
// ensure/remove semantics are single-sourced: ensure entries are prepended (preserving the
|
|
4
|
+
// established `[new, ...existing]` ordering), remove entries are dropped by exact string or
|
|
5
|
+
// pattern match, and `is_changed` reports whether the list actually differs from the input.
|
|
6
|
+
|
|
7
|
+
// A remove matcher: an exact string to drop, or a pattern every matching entry is dropped by.
|
|
8
|
+
type ListEntryMatcher = string | RegExp
|
|
9
|
+
|
|
10
|
+
interface ListPatch {
|
|
11
|
+
ensure?: ReadonlyArray<string>
|
|
12
|
+
remove?: ReadonlyArray<ListEntryMatcher>
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ListPatchResult {
|
|
16
|
+
next: ReadonlyArray<string>
|
|
17
|
+
is_changed: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function is_matching(entry: string, matchers: ReadonlyArray<ListEntryMatcher>): boolean {
|
|
21
|
+
return matchers.some((matcher) =>
|
|
22
|
+
typeof matcher === 'string' ? matcher === entry : matcher.test(entry),
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function apply_remove(
|
|
27
|
+
existing: ReadonlyArray<string>,
|
|
28
|
+
remove: ReadonlyArray<ListEntryMatcher> | undefined,
|
|
29
|
+
): ReadonlyArray<string> {
|
|
30
|
+
if (remove === undefined || remove.length === 0) return existing
|
|
31
|
+
|
|
32
|
+
return existing.filter((entry) => !is_matching(entry, remove))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function collect_additions(
|
|
36
|
+
kept: ReadonlyArray<string>,
|
|
37
|
+
ensure: ReadonlyArray<string> | undefined,
|
|
38
|
+
): ReadonlyArray<string> {
|
|
39
|
+
if (ensure === undefined) return []
|
|
40
|
+
|
|
41
|
+
return ensure.filter((entry) => !kept.includes(entry))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Drop `remove` matches, then prepend any `ensure` entry not already present. `is_changed` is true
|
|
45
|
+
// when an entry was added or removed, so a caller can return the original content untouched (and
|
|
46
|
+
// keep its comments/formatting) on a no-op — which also makes re-runs idempotent.
|
|
47
|
+
function apply_list_patch(existing: ReadonlyArray<string>, patch: ListPatch): ListPatchResult {
|
|
48
|
+
const kept = apply_remove(existing, patch.remove)
|
|
49
|
+
const additions = collect_additions(kept, patch.ensure)
|
|
50
|
+
const is_changed = additions.length > 0 || kept.length !== existing.length
|
|
51
|
+
|
|
52
|
+
return { next: [...additions, ...kept], is_changed }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const list_patch = {
|
|
56
|
+
is_matching,
|
|
57
|
+
apply_list_patch,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type { ListEntryMatcher, ListPatch, ListPatchResult }
|
|
61
|
+
export { list_patch }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { json_object_schema } from '#scripts/lib/schemas'
|
|
2
|
+
import strip_json_comments from 'strip-json-comments'
|
|
3
|
+
|
|
4
|
+
// Every managed JSON config kit reads (tsconfig.json, package.json, .vscode/*.json) may legally
|
|
5
|
+
// carry comments and trailing commas — TypeScript and VS Code both parse them as JSONC — so a plain
|
|
6
|
+
// `JSON.parse` would throw on files consumers hand-authored. Single-sourced here because the
|
|
7
|
+
// config-merge library and the init/sync merge helpers both need the exact same tolerant read.
|
|
8
|
+
function parse_jsonc(content: string): Record<string, unknown> {
|
|
9
|
+
const stripped = strip_json_comments(content, { trailingCommas: true })
|
|
10
|
+
|
|
11
|
+
return json_object_schema.parse(JSON.parse(stripped))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { parse_jsonc }
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
import { createScanner, findNodeAtLocation, getNodeValue, parseTree, type Node } from 'jsonc-parser'
|
|
2
|
+
import strip_json_comments from 'strip-json-comments'
|
|
3
|
+
import { json_format } from './json-format'
|
|
4
|
+
|
|
5
|
+
// Set or remove one top-level key while leaving every other byte of the document alone.
|
|
6
|
+
//
|
|
7
|
+
// The merges kit runs against a consumer's `tsconfig.json` / `.vscode/*.json` used to read with a
|
|
8
|
+
// tolerant JSONC parse and write the whole file back from the parsed object, which silently deleted
|
|
9
|
+
// the consumer's comments — including the `// Path aliases are handled by ...` block `sv create`
|
|
10
|
+
// ships. Editing text in place instead keeps comments, trailing commas, key order and any
|
|
11
|
+
// hand-formatting outside the one value being changed. See joshuafolkken/kit#798.
|
|
12
|
+
//
|
|
13
|
+
// jsonc-parser is used ONLY to locate text, never to produce it. Two independent reasons:
|
|
14
|
+
//
|
|
15
|
+
// 1. Its formatter breaks every array one element per line regardless of width — the layout
|
|
16
|
+
// prettier wants for `package.json`, and the opposite of what it wants for the files edited
|
|
17
|
+
// here, where the `json` printer keeps a short array inline. Letting it render would
|
|
18
|
+
// re-introduce joshuafolkken/kit#797 on a new axis.
|
|
19
|
+
// 2. `modify` with `formattingOptions` reformats a region around its edit, not just the edit —
|
|
20
|
+
// removing `compilerOptions` from a document also expanded the untouched `extends` array above
|
|
21
|
+
// it. Dropping `formattingOptions` avoids that but then places inserted keys with no newline or
|
|
22
|
+
// indent at all. Neither setting does what is wanted, so placement is computed here from node
|
|
23
|
+
// offsets, which is exact and touches nothing else.
|
|
24
|
+
|
|
25
|
+
const DOCUMENT_SUFFIX = '\n}\n'
|
|
26
|
+
const DEFAULT_INDENT = '\t'
|
|
27
|
+
const LEADING_BLANKS = /^[\t ]*/u
|
|
28
|
+
// Step back past the newline that ENDS the previous line, so the search finds the one before it.
|
|
29
|
+
const PREVIOUS_LINE_OFFSET = 2
|
|
30
|
+
const CRLF = '\r\n'
|
|
31
|
+
|
|
32
|
+
// Any scalar works — the probe entry is sliced away, only the comma it forces onto our line matters.
|
|
33
|
+
const COMMA_PROBE_VALUE = 0
|
|
34
|
+
|
|
35
|
+
interface TextRange {
|
|
36
|
+
offset: number
|
|
37
|
+
length: number
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The text `value` takes as a top-level key's value. Serializing a probe document and slicing the
|
|
41
|
+
// value out of it keeps prettier's inline-vs-broken decision — and its printWidth accounting,
|
|
42
|
+
// because the key sits at exactly the depth it will occupy in the real file.
|
|
43
|
+
//
|
|
44
|
+
// `has_trailing_comma` is not a detail: a key that is not last is followed by a comma, and that one
|
|
45
|
+
// column decides borderline lines. Measuring without it emitted a 101-column `extends` array inline
|
|
46
|
+
// that prettier then broke, failing the consumer's `prettier --check` on a file kit had just written.
|
|
47
|
+
function render_value(key: string, value: unknown, has_trailing_comma: boolean): string {
|
|
48
|
+
// A second key for the probe document, derived from the real one by appending a space so it can
|
|
49
|
+
// never equal it. A fixed sentinel would need an argument about why no config uses that name;
|
|
50
|
+
// this needs none, and a collision would corrupt the slice arithmetic silently.
|
|
51
|
+
const probe_key = `${key} `
|
|
52
|
+
const probe = has_trailing_comma
|
|
53
|
+
? { [key]: value, [probe_key]: COMMA_PROBE_VALUE }
|
|
54
|
+
: { [key]: value }
|
|
55
|
+
const document = json_format.format_json(probe)
|
|
56
|
+
const prefix = `{\n\t${JSON.stringify(key)}: `
|
|
57
|
+
const suffix = has_trailing_comma
|
|
58
|
+
? `,\n\t${JSON.stringify(probe_key)}: ${String(COMMA_PROBE_VALUE)}${DOCUMENT_SUFFIX}`
|
|
59
|
+
: DOCUMENT_SUFFIX
|
|
60
|
+
|
|
61
|
+
return document.slice(prefix.length, document.length - suffix.length)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function parse_root(content: string): Node | undefined {
|
|
65
|
+
const root = parseTree(content)
|
|
66
|
+
|
|
67
|
+
return root?.type === 'object' ? root : undefined
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function replace_range(content: string, range: TextRange, text: string): string {
|
|
71
|
+
return content.slice(0, range.offset) + text + content.slice(range.offset + range.length)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function insert_at(content: string, offset: number, text: string): string {
|
|
75
|
+
return replace_range(content, { offset, length: 0 }, text)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Re-indent a rendered value for a document that does not indent with tabs. `render_value` always
|
|
79
|
+
// emits tabs, since it goes through the kit-preset serializer, so splicing a multi-line value into a
|
|
80
|
+
// space-indented file produced mixed indentation that the consumer's own prettier then rewrote — the
|
|
81
|
+
// file kit had just written failed their format check. The value's first line carries no indent of
|
|
82
|
+
// its own, so only continuation lines are rewritten: one unit per tab of depth.
|
|
83
|
+
function render_indent(value_text: string, unit: string): string {
|
|
84
|
+
if (unit === DEFAULT_INDENT || unit.length === 0) return value_text
|
|
85
|
+
|
|
86
|
+
return value_text.replaceAll(/^\t+/gmu, (tabs) => unit.repeat(tabs.length))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// The line ending the document already uses, so text spliced into a CRLF checkout does not leave the
|
|
90
|
+
// file with mixed endings. The whole-file serializer this replaced always produced a uniform file.
|
|
91
|
+
function eol_of(content: string): string {
|
|
92
|
+
return content.includes(CRLF) ? CRLF : '\n'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Lay a rendered value out for THIS document: its indent unit and its line ending. `format_json`
|
|
96
|
+
// always emits tabs and LF, so a value that breaks across lines would otherwise arrive with both
|
|
97
|
+
// wrong in a space-indented or CRLF file — leaving mixed indentation or mixed endings in a file the
|
|
98
|
+
// consumer never touched.
|
|
99
|
+
function fit_value(content: string, value_text: string, indent: string): string {
|
|
100
|
+
const indented = render_indent(value_text, indent)
|
|
101
|
+
if (eol_of(content) === '\n') return indented
|
|
102
|
+
|
|
103
|
+
return indented.split('\n').join(CRLF)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// The whitespace opening the line `offset` sits on, so an inserted key lines up with its siblings
|
|
107
|
+
// whatever the document indents with.
|
|
108
|
+
function line_indent(content: string, offset: number): string {
|
|
109
|
+
const line_start = content.lastIndexOf('\n', offset - 1) + 1
|
|
110
|
+
|
|
111
|
+
return LEADING_BLANKS.exec(content.slice(line_start, offset))?.[0] ?? ''
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Index of the line's terminator, before the `\r` of a CRLF pair so text appended here does not land
|
|
115
|
+
// between the two characters and produce `\r\r\n`.
|
|
116
|
+
function line_end(content: string, offset: number): number {
|
|
117
|
+
const index = content.indexOf('\n', offset)
|
|
118
|
+
if (index === -1) return content.length
|
|
119
|
+
|
|
120
|
+
return index > offset && content[index - 1] === '\r' ? index - 1 : index
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function render_property(content: string, key: string, value_text: string, indent: string): string {
|
|
124
|
+
return `${JSON.stringify(key)}: ${fit_value(content, value_text, indent)}`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Where the new property's line starts: after the last property's line, but never past the object's
|
|
128
|
+
// own `}` — a single-line document has no newline before it, so the end-of-line search would
|
|
129
|
+
// otherwise run to the end of the file and insert outside the object.
|
|
130
|
+
function insertion_offset(content: string, root: Node, value_end: number): number {
|
|
131
|
+
return Math.min(line_end(content, value_end), root.offset + root.length - 1)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Offset of the separator comma after `offset`, or -1 when the next thing is not one. The scanner
|
|
135
|
+
// (with trivia ignored) skips whitespace AND comments, so a `,` written inside a comment is never
|
|
136
|
+
// mistaken for a separator; its position is read rather than its token kind, because `SyntaxKind` is
|
|
137
|
+
// an ambient const enum this project cannot import.
|
|
138
|
+
function separator_offset(content: string, offset: number, limit: number): number {
|
|
139
|
+
const scanner = createScanner(content, true)
|
|
140
|
+
|
|
141
|
+
scanner.setPosition(offset)
|
|
142
|
+
scanner.scan()
|
|
143
|
+
const at = scanner.getTokenOffset()
|
|
144
|
+
|
|
145
|
+
return at < limit && content[at] === ',' ? at : -1
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// JSONC allows a trailing comma after the last property, and `parse_jsonc` accepts one, so appending
|
|
149
|
+
// another would produce `,,` and leave a file nothing can read.
|
|
150
|
+
function has_separator_after(content: string, offset: number, limit: number): boolean {
|
|
151
|
+
return separator_offset(content, offset, limit) !== -1
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function property_key(property: Node): string | undefined {
|
|
155
|
+
const key: unknown = property.children?.[0]?.value
|
|
156
|
+
|
|
157
|
+
return typeof key === 'string' ? key : undefined
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function target_value_end(property: Node | undefined): number | undefined {
|
|
161
|
+
const value_node = property?.children?.[1]
|
|
162
|
+
|
|
163
|
+
return value_node === undefined ? undefined : value_node.offset + value_node.length
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Whether the span holds a comment. `strip_json_comments` blanks comments while preserving length
|
|
167
|
+
// and is string-aware, so a `//` inside a string value is not counted — a scanner-based check would
|
|
168
|
+
// need `SyntaxKind`, which is an ambient const enum this project cannot import.
|
|
169
|
+
function contains_comment(content: string, node: Node): boolean {
|
|
170
|
+
const text = content.slice(node.offset, node.offset + node.length)
|
|
171
|
+
|
|
172
|
+
return strip_json_comments(text) !== text
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Re-lay-out a property whose trailing comma has just appeared or disappeared. That one column
|
|
176
|
+
// decides borderline lines: gaining it can push an inlined value past printWidth, losing it can let a
|
|
177
|
+
// broken one fit again. Either way prettier would rewrite the line, in a file kit had just written.
|
|
178
|
+
//
|
|
179
|
+
// Skipped entirely when the value holds a comment. Re-rendering serializes the value back from its
|
|
180
|
+
// parsed form, which would delete that comment — the defect this module exists to fix, reappearing on
|
|
181
|
+
// its own repair path — and a value the consumer commented is one kit should not be re-laying-out.
|
|
182
|
+
function rebalanced_value(
|
|
183
|
+
content: string,
|
|
184
|
+
key: string,
|
|
185
|
+
value_node: Node,
|
|
186
|
+
has_trailing_comma: boolean,
|
|
187
|
+
): string | undefined {
|
|
188
|
+
if (contains_comment(content, value_node)) return undefined
|
|
189
|
+
const indent = line_indent(content, value_node.offset)
|
|
190
|
+
const rendered = fit_value(
|
|
191
|
+
content,
|
|
192
|
+
render_value(key, getNodeValue(value_node), has_trailing_comma),
|
|
193
|
+
indent,
|
|
194
|
+
)
|
|
195
|
+
const current = content.slice(value_node.offset, value_node.offset + value_node.length)
|
|
196
|
+
|
|
197
|
+
return rendered === current ? undefined : rendered
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function rebalance(content: string, property: Node, has_trailing_comma: boolean): string {
|
|
201
|
+
const key = property_key(property)
|
|
202
|
+
const value_node = property.children?.[1]
|
|
203
|
+
if (key === undefined || value_node === undefined) return content
|
|
204
|
+
const rendered = rebalanced_value(content, key, value_node, has_trailing_comma)
|
|
205
|
+
|
|
206
|
+
return rendered === undefined ? content : replace_range(content, value_node, rendered)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Append after the last property, mirroring the key order the whole-file serializer produced (a
|
|
210
|
+
// spread puts a new key last). An empty object has no sibling to copy, so it gets one tab.
|
|
211
|
+
//
|
|
212
|
+
// Two insertions rather than one: the comma goes right after the last value, but the new property
|
|
213
|
+
// goes after the END OF THAT LINE. Putting both at the value would slide the new key in front of a
|
|
214
|
+
// trailing `// ...` comment on that line, silently re-attaching the consumer's note to a key kit
|
|
215
|
+
// generated. Later offset first, so the earlier one stays valid.
|
|
216
|
+
function append_after(content: string, root: Node, last: Node, property: string): string {
|
|
217
|
+
const value_end = last.offset + last.length
|
|
218
|
+
const closing_brace = root.offset + root.length - 1
|
|
219
|
+
const separator = has_separator_after(content, value_end, closing_brace) ? '' : ','
|
|
220
|
+
const with_property = insert_at(content, insertion_offset(content, root, value_end), property)
|
|
221
|
+
|
|
222
|
+
return insert_at(with_property, value_end, separator)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Insert the first property of an otherwise empty object, just inside its closing brace rather than
|
|
226
|
+
// by rewriting the braces — a body holding nothing but a comment keeps that comment.
|
|
227
|
+
function insert_only_property(content: string, root: Node, property: string): string {
|
|
228
|
+
const closing_brace = root.offset + root.length - 1
|
|
229
|
+
const lead = content[closing_brace - 1] === '\n' ? '' : eol_of(content)
|
|
230
|
+
|
|
231
|
+
return insert_at(content, closing_brace, `${lead}${DEFAULT_INDENT}${property}${eol_of(content)}`)
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function insert_property(content: string, root: Node, key: string, value_text: string): string {
|
|
235
|
+
const last = root.children?.at(-1)
|
|
236
|
+
|
|
237
|
+
if (last === undefined) {
|
|
238
|
+
const only = render_property(content, key, value_text, DEFAULT_INDENT)
|
|
239
|
+
|
|
240
|
+
return insert_only_property(content, root, only)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const indent = line_indent(content, last.offset)
|
|
244
|
+
const property = `${eol_of(content)}${indent}${render_property(content, key, value_text, indent)}`
|
|
245
|
+
|
|
246
|
+
return rebalance(append_after(content, root, last, property), last, true)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// A comment closing a property's line annotates that property. `end` walks past one so a removed key
|
|
250
|
+
// takes its own note with it — and, applied to the PREVIOUS key's line, so the span does not start
|
|
251
|
+
// before that key's note and delete a comment belonging to a property that is staying.
|
|
252
|
+
// Only the `//` form is recognized; a `/* ... */` block above or beside a key is left in place.
|
|
253
|
+
function end_of_trailing_comment(content: string, end: number): number {
|
|
254
|
+
const stop = line_end(content, end)
|
|
255
|
+
|
|
256
|
+
return content.slice(end, stop).trimStart().startsWith('//') ? stop : end
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Walk back over whole-line `//` comments immediately above `line_start`. They document the key being
|
|
260
|
+
// removed, so they go with it; leaving them would re-attach the note to whichever key follows.
|
|
261
|
+
function start_of_leading_comments(content: string, line_start: number, floor: number): number {
|
|
262
|
+
let start = line_start
|
|
263
|
+
|
|
264
|
+
while (start > floor) {
|
|
265
|
+
const previous = content.lastIndexOf('\n', start - PREVIOUS_LINE_OFFSET) + 1
|
|
266
|
+
const is_comment_line = content.slice(previous, start).trimStart().startsWith('//')
|
|
267
|
+
|
|
268
|
+
if (!is_comment_line || previous < floor) return start
|
|
269
|
+
|
|
270
|
+
start = previous
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return start
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function end_of_line_break(content: string, offset: number): number {
|
|
277
|
+
if (content[offset] === '\r' && content[offset + 1] === '\n') return offset + PREVIOUS_LINE_OFFSET
|
|
278
|
+
|
|
279
|
+
return content[offset] === '\n' ? offset + 1 : offset
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// The text the removed property occupies: its own line when it has one (leading comment lines and
|
|
283
|
+
// trailing note included, so nothing is stranded or re-attributed), otherwise just the property.
|
|
284
|
+
function body_range(content: string, root: Node, target: Node, separator_limit: number): TextRange {
|
|
285
|
+
const value_end = target.offset + target.length
|
|
286
|
+
const comma = separator_limit === -1 ? -1 : separator_offset(content, value_end, separator_limit)
|
|
287
|
+
const end = end_of_trailing_comment(content, comma === -1 ? value_end : comma + 1)
|
|
288
|
+
const line_start = content.lastIndexOf('\n', target.offset - 1) + 1
|
|
289
|
+
const is_own_line = content.slice(line_start, target.offset).trim().length === 0
|
|
290
|
+
if (!is_own_line) return { offset: target.offset, length: end - target.offset }
|
|
291
|
+
const start = start_of_leading_comments(content, line_start, root.offset + 1)
|
|
292
|
+
|
|
293
|
+
return { offset: start, length: end_of_line_break(content, end) - start }
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Delete the property together with exactly one separator comma — never two, or the surviving keys stop
|
|
297
|
+
// being separated at all.
|
|
298
|
+
//
|
|
299
|
+
// While a next sibling exists the comma taken is the one AFTER the property, so the whole line goes
|
|
300
|
+
// as a unit and the comma still separating the keys on either side is the one that was already
|
|
301
|
+
// there. Only the last property has no comma after it; that case reaches back for the one before,
|
|
302
|
+
// as a SEPARATE span, because the previous key's own trailing note can sit between that comma and
|
|
303
|
+
// this property and a single span would delete a comment belonging to a property that is staying.
|
|
304
|
+
function ranges_for_last_property(
|
|
305
|
+
content: string,
|
|
306
|
+
root: Node,
|
|
307
|
+
previous: Node,
|
|
308
|
+
target: Node,
|
|
309
|
+
): ReadonlyArray<TextRange> {
|
|
310
|
+
const comma = separator_offset(content, previous.offset + previous.length, target.offset)
|
|
311
|
+
const body = body_range(content, root, target, -1)
|
|
312
|
+
|
|
313
|
+
return comma === -1 ? [body] : [{ offset: comma, length: 1 }, body]
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function removal_ranges(content: string, root: Node, index: number): ReadonlyArray<TextRange> {
|
|
317
|
+
const children = root.children ?? []
|
|
318
|
+
const target = children[index]
|
|
319
|
+
if (target === undefined) return []
|
|
320
|
+
const next = children[index + 1]
|
|
321
|
+
if (next !== undefined) return [body_range(content, root, target, next.offset)]
|
|
322
|
+
const previous = children[index - 1]
|
|
323
|
+
if (previous === undefined) return [{ offset: root.offset, length: root.length }]
|
|
324
|
+
|
|
325
|
+
return ranges_for_last_property(content, root, previous, target)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function property_index(root: Node, key: string): number {
|
|
329
|
+
return (root.children ?? []).findIndex((child) => child.children?.[0]?.value === key)
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// The single normalization these edits still perform. Preserving the document byte for byte would
|
|
333
|
+
// mean writing back a file with no final newline when the consumer's had none — git, POSIX tools and
|
|
334
|
+
// prettier all want one, and it is one byte at EOF rather than a reformat of anything the consumer
|
|
335
|
+
// wrote. Every managed config kit has ever written ended with exactly one.
|
|
336
|
+
function with_trailing_newline(content: string): string {
|
|
337
|
+
return content.endsWith('\n') ? content : `${content}\n`
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// True when a comma follows this key, i.e. it is not the last property in its object.
|
|
341
|
+
function is_followed_by_comma(content: string, root: Node, key: string): boolean {
|
|
342
|
+
const children = root.children ?? []
|
|
343
|
+
const index = property_index(root, key)
|
|
344
|
+
if (index < 0) return false
|
|
345
|
+
if (index < children.length - 1) return true
|
|
346
|
+
const value_end = target_value_end(children[index])
|
|
347
|
+
|
|
348
|
+
// The last property may still carry a JSONC trailing comma the consumer wrote.
|
|
349
|
+
return (
|
|
350
|
+
value_end !== undefined && has_separator_after(content, value_end, root.offset + root.length)
|
|
351
|
+
)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function set_json_key(content: string, key: string, value: unknown): string {
|
|
355
|
+
const root = parse_root(content)
|
|
356
|
+
if (root === undefined) return content
|
|
357
|
+
const existing = findNodeAtLocation(root, [key])
|
|
358
|
+
// An inserted key is appended last, so nothing follows it.
|
|
359
|
+
const value_text = render_value(
|
|
360
|
+
key,
|
|
361
|
+
value,
|
|
362
|
+
existing !== undefined && is_followed_by_comma(content, root, key),
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
if (existing === undefined) {
|
|
366
|
+
return with_trailing_newline(insert_property(content, root, key, value_text))
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
const indented = fit_value(content, value_text, line_indent(content, existing.offset))
|
|
370
|
+
|
|
371
|
+
return with_trailing_newline(replace_range(content, existing, indented))
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// The object a path's final segment lives in: the document root for a top-level key, otherwise the
|
|
375
|
+
// nested object addressed by everything before it.
|
|
376
|
+
function resolve_parent(content: string, path: ReadonlyArray<string>): Node | undefined {
|
|
377
|
+
const root = parse_root(content)
|
|
378
|
+
if (root === undefined) return undefined
|
|
379
|
+
const parent = path.length > 1 ? findNodeAtLocation(root, path.slice(0, -1)) : root
|
|
380
|
+
|
|
381
|
+
return parent?.type === 'object' ? parent : undefined
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Later spans first, so the offsets of the earlier ones stay valid. A span covering the whole object
|
|
385
|
+
// means its last property went, leaving `{}` behind; every other span simply disappears.
|
|
386
|
+
function cut_ranges(content: string, parent: Node, ranges: ReadonlyArray<TextRange>): string {
|
|
387
|
+
const ordered = ranges.toSorted((left, right) => right.offset - left.offset)
|
|
388
|
+
let next = content
|
|
389
|
+
|
|
390
|
+
for (const range of ordered) {
|
|
391
|
+
next = replace_range(next, range, range.offset === parent.offset ? '{}' : '')
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return next
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Removing the LAST property strips the comma from the one before it, which now ends the object. The
|
|
398
|
+
// insert path re-lays-out a property that GAINS a comma for the same reason: one column decides
|
|
399
|
+
// borderline lines, and here it is given back, so a value broken across lines may fit inline again.
|
|
400
|
+
function rebalance_new_last(content: string, path: ReadonlyArray<string>): string {
|
|
401
|
+
const parent = resolve_parent(content, path)
|
|
402
|
+
const last = parent?.children?.at(-1)
|
|
403
|
+
if (parent === undefined || last === undefined) return content
|
|
404
|
+
|
|
405
|
+
return rebalance(content, last, has_separator_after(content, parent.offset, parent.offset))
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Delete one property, addressed by a path so a key nested inside another object can go on its own.
|
|
409
|
+
// That granularity is the point: pruning two redundant entries out of `compilerOptions` by replacing
|
|
410
|
+
// the whole block would take the consumer's comments inside it along with them.
|
|
411
|
+
function cut_property(content: string, parent: Node, path: ReadonlyArray<string>): string {
|
|
412
|
+
const index = property_index(parent, path.at(-1) ?? '')
|
|
413
|
+
const ranges = removal_ranges(content, parent, index)
|
|
414
|
+
if (ranges.length === 0) return content
|
|
415
|
+
const cut = cut_ranges(content, parent, ranges)
|
|
416
|
+
const did_end_object = index === (parent.children ?? []).length - 1
|
|
417
|
+
|
|
418
|
+
return did_end_object ? rebalance_new_last(cut, path) : cut
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
function remove_json_path(content: string, path: ReadonlyArray<string>): string {
|
|
422
|
+
const parent = resolve_parent(content, path)
|
|
423
|
+
if (parent === undefined) return content
|
|
424
|
+
const next = cut_property(content, parent, path)
|
|
425
|
+
|
|
426
|
+
return next === content ? content : with_trailing_newline(next)
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
function remove_json_key(content: string, key: string): string {
|
|
430
|
+
return remove_json_path(content, [key])
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const patch_json_key = {
|
|
434
|
+
set_json_key,
|
|
435
|
+
remove_json_key,
|
|
436
|
+
remove_json_path,
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export { patch_json_key }
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { list_patch, type ListEntryMatcher } from './list-patch'
|
|
2
|
+
import { parse_jsonc } from './parse-jsonc'
|
|
3
|
+
import { patch_json_key } from './patch-json-key'
|
|
4
|
+
|
|
5
|
+
interface PatchJsonListOptions {
|
|
6
|
+
field: string
|
|
7
|
+
ensure?: ReadonlyArray<string>
|
|
8
|
+
remove?: ReadonlyArray<ListEntryMatcher>
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// A JSON list field may be authored as a bare string (tsconfig `extends` accepts `string` or
|
|
12
|
+
// `string[]`); normalize both forms — and an absent field — to an array for patching.
|
|
13
|
+
function normalize_list(value: unknown): ReadonlyArray<string> {
|
|
14
|
+
if (typeof value === 'string') return [value]
|
|
15
|
+
if (Array.isArray(value)) return value.map(String)
|
|
16
|
+
|
|
17
|
+
return []
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Ensure/remove the entries of one JSON list field, preserving every other key. A present field
|
|
21
|
+
// keeps its position; a new field is appended last. Returns the input unchanged when nothing is
|
|
22
|
+
// added or removed, so re-runs are idempotent. Only the field's own value is rewritten, so comments
|
|
23
|
+
// and formatting elsewhere in the document survive (joshuafolkken/kit#798).
|
|
24
|
+
function patch_json_list_field(content: string, options: PatchJsonListOptions): string {
|
|
25
|
+
const parsed = parse_jsonc(content)
|
|
26
|
+
const existing = normalize_list(parsed[options.field])
|
|
27
|
+
const { next, is_changed } = list_patch.apply_list_patch(existing, options)
|
|
28
|
+
if (!is_changed) return content
|
|
29
|
+
|
|
30
|
+
return patch_json_key.set_json_key(content, options.field, [...next])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const json_list = {
|
|
34
|
+
patch_json_list_field,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type { PatchJsonListOptions }
|
|
38
|
+
export { json_list }
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { string_array_schema } from '#scripts/lib/schemas'
|
|
2
|
+
import { yaml_document } from '#scripts/yaml/yaml-document'
|
|
3
|
+
import { dump, type DumpOptions } from 'js-yaml'
|
|
4
|
+
import { list_patch, type ListEntryMatcher } from './list-patch'
|
|
5
|
+
|
|
6
|
+
// Where a newly-created list field is placed when the field is absent. Existing fields are always
|
|
7
|
+
// rewritten in place, preserving their position among the other keys.
|
|
8
|
+
// - 'front' : the field becomes the first key (lefthook `extends` precedent)
|
|
9
|
+
// - 'end' : the field is appended after all existing keys
|
|
10
|
+
// - { after: key } : inserted right after `key`, falling back to 'end' when `key` is absent
|
|
11
|
+
// (cspell `import` precedent: placed after `version`)
|
|
12
|
+
type YamlFieldPosition = 'front' | 'end' | { after: string }
|
|
13
|
+
|
|
14
|
+
interface PatchYamlListOptions {
|
|
15
|
+
field: string
|
|
16
|
+
ensure?: ReadonlyArray<string>
|
|
17
|
+
remove?: ReadonlyArray<ListEntryMatcher>
|
|
18
|
+
position?: YamlFieldPosition
|
|
19
|
+
// Scalar quote style passed through to js-yaml `dump`, so a caller (cspell) can match the
|
|
20
|
+
// VSCode extension's double-quoted output. Omit for js-yaml's default quoting.
|
|
21
|
+
quote_style?: DumpOptions['quoteStyle']
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { parse_yaml } = yaml_document
|
|
25
|
+
|
|
26
|
+
// A YAML list field may be authored as a bare scalar (cspell `import` and lefthook `extends` both
|
|
27
|
+
// accept a string or a sequence); normalize a string to a single-element array — and an absent /
|
|
28
|
+
// non-list field to [] — so callers (and the dedup guards) see one shape. Mirrors the JSON path's
|
|
29
|
+
// normalize_list, and lets a patch merge into a scalar field instead of clobbering it.
|
|
30
|
+
function read_yaml_list_field(content: string, field: string): ReadonlyArray<string> {
|
|
31
|
+
const raw = parse_yaml(content)[field]
|
|
32
|
+
if (typeof raw === 'string') return [raw]
|
|
33
|
+
|
|
34
|
+
return Array.isArray(raw) ? string_array_schema.parse(raw) : []
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function replace_field(
|
|
38
|
+
parsed: Record<string, unknown>,
|
|
39
|
+
field: string,
|
|
40
|
+
value: ReadonlyArray<string>,
|
|
41
|
+
): Record<string, unknown> {
|
|
42
|
+
return Object.fromEntries(
|
|
43
|
+
Object.entries(parsed).map(([key, entry]) => [key, key === field ? [...value] : entry]),
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function insert_after(
|
|
48
|
+
parsed: Record<string, unknown>,
|
|
49
|
+
field: string,
|
|
50
|
+
value: ReadonlyArray<string>,
|
|
51
|
+
anchor: string,
|
|
52
|
+
): Record<string, unknown> {
|
|
53
|
+
const entries = Object.entries(parsed)
|
|
54
|
+
const index = entries.findIndex(([key]) => key === anchor)
|
|
55
|
+
if (index === -1) return { ...parsed, [field]: [...value] }
|
|
56
|
+
|
|
57
|
+
return Object.fromEntries([
|
|
58
|
+
...entries.slice(0, index + 1),
|
|
59
|
+
[field, [...value]],
|
|
60
|
+
...entries.slice(index + 1),
|
|
61
|
+
])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function insert_new_field(
|
|
65
|
+
parsed: Record<string, unknown>,
|
|
66
|
+
field: string,
|
|
67
|
+
value: ReadonlyArray<string>,
|
|
68
|
+
position: YamlFieldPosition,
|
|
69
|
+
): Record<string, unknown> {
|
|
70
|
+
if (position === 'front') return { [field]: [...value], ...parsed }
|
|
71
|
+
if (position === 'end') return { ...parsed, [field]: [...value] }
|
|
72
|
+
|
|
73
|
+
return insert_after(parsed, field, value, position.after)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function place_field(
|
|
77
|
+
parsed: Record<string, unknown>,
|
|
78
|
+
field: string,
|
|
79
|
+
value: ReadonlyArray<string>,
|
|
80
|
+
position: YamlFieldPosition,
|
|
81
|
+
): Record<string, unknown> {
|
|
82
|
+
if (Object.hasOwn(parsed, field)) return replace_field(parsed, field, value)
|
|
83
|
+
|
|
84
|
+
return insert_new_field(parsed, field, value, position)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Ensure/remove the entries of one YAML list field, preserving every other key and value. Returns
|
|
88
|
+
// the input unchanged (comments and formatting intact) when nothing is added or removed, which
|
|
89
|
+
// also makes re-runs idempotent. Comments are otherwise dropped — see the value-only decision.
|
|
90
|
+
function patch_yaml_list_field(content: string, options: PatchYamlListOptions): string {
|
|
91
|
+
const parsed = parse_yaml(content)
|
|
92
|
+
const existing = read_yaml_list_field(content, options.field)
|
|
93
|
+
const { next, is_changed } = list_patch.apply_list_patch(existing, options)
|
|
94
|
+
if (!is_changed) return content
|
|
95
|
+
|
|
96
|
+
const placed = place_field(parsed, options.field, next, options.position ?? 'front')
|
|
97
|
+
|
|
98
|
+
return dump(placed, options.quote_style === undefined ? {} : { quoteStyle: options.quote_style })
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const yaml_list = {
|
|
102
|
+
patch_yaml_list_field,
|
|
103
|
+
read_yaml_list_field,
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type { PatchYamlListOptions, YamlFieldPosition }
|
|
107
|
+
export { yaml_list }
|