@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,181 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { read_spawn_stdout } from '#scripts/lib/spawn-exit'
|
|
4
|
+
import { KIT_PACKAGE_NAME } from '#scripts/version/kit-descriptor'
|
|
5
|
+
import { safe_json_parse } from '#scripts/version/parse-json'
|
|
6
|
+
import { execaSync } from 'execa'
|
|
7
|
+
import { z } from 'zod'
|
|
8
|
+
|
|
9
|
+
// The consumer-setup checks `josh doctor` runs in a repository that installs kit (joshuafolkken/kit#1930).
|
|
10
|
+
// Each failure was a way the distribution went silently wrong: the plugin never installed so skills
|
|
11
|
+
// were missing, `core.hooksPath` set so lefthook installed nothing, the `CLAUDE.md` pointer resolving
|
|
12
|
+
// to a file that is not there before `pnpm install`, and secretlint not runnable so the pre-commit
|
|
13
|
+
// hook could not scan. Each check prints a one-line verdict; none of them fails the command.
|
|
14
|
+
|
|
15
|
+
const NODE_MODULES = 'node_modules'
|
|
16
|
+
const SETTINGS_PATH = path.join('.claude', 'settings.json')
|
|
17
|
+
const CLAUDE_MD = 'CLAUDE.md'
|
|
18
|
+
const PLUGIN_ID = 'kit@kit'
|
|
19
|
+
// The one line a consumer's CLAUDE.md is: an import of the packaged rules. kit's own CLAUDE.md is the
|
|
20
|
+
// full document, so this pointer is also what tells a consumer repository apart from kit itself.
|
|
21
|
+
const CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`
|
|
22
|
+
const SECRETLINT_BIN = path.join(NODE_MODULES, '.bin', 'secretlint')
|
|
23
|
+
const GIT_TIMEOUT_MS = 2000
|
|
24
|
+
|
|
25
|
+
const manifest_schema = z.object({
|
|
26
|
+
name: z.string().optional(),
|
|
27
|
+
dependencies: z.record(z.string(), z.string()).optional(),
|
|
28
|
+
devDependencies: z.record(z.string(), z.string()).optional(),
|
|
29
|
+
})
|
|
30
|
+
const settings_schema = z.object({
|
|
31
|
+
enabledPlugins: z.record(z.string(), z.boolean()).optional(),
|
|
32
|
+
})
|
|
33
|
+
type ManifestShape = z.infer<typeof manifest_schema>
|
|
34
|
+
const STATE_OK = 'ok'
|
|
35
|
+
const STATE_TARGET_MISSING = 'target-missing'
|
|
36
|
+
const STATE_MISSING = 'missing'
|
|
37
|
+
type ClaudeMdState = typeof STATE_OK | typeof STATE_TARGET_MISSING | typeof STATE_MISSING
|
|
38
|
+
|
|
39
|
+
function read_optional(file_path: string): string | undefined {
|
|
40
|
+
try {
|
|
41
|
+
return existsSync(file_path) ? readFileSync(file_path, 'utf8') : undefined
|
|
42
|
+
} catch {
|
|
43
|
+
return undefined
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function parse_manifest(root: string): ManifestShape | undefined {
|
|
48
|
+
const content = read_optional(path.join(root, 'package.json'))
|
|
49
|
+
if (content === undefined) return undefined
|
|
50
|
+
const parsed = manifest_schema.safeParse(safe_json_parse(content))
|
|
51
|
+
|
|
52
|
+
return parsed.success ? parsed.data : undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function lists_kit_dependency(manifest: ManifestShape | undefined): boolean {
|
|
56
|
+
if (manifest === undefined) return false
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
Object.hasOwn(manifest.dependencies ?? {}, KIT_PACKAGE_NAME) ||
|
|
60
|
+
Object.hasOwn(manifest.devDependencies ?? {}, KIT_PACKAGE_NAME)
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Whether this repository consumes kit rather than being kit itself. kit is excluded by its own
|
|
65
|
+
// package name; a consumer either declares the dependency or already has it installed, so a fresh
|
|
66
|
+
// clone before `pnpm install` (which declares it) still counts.
|
|
67
|
+
function is_kit_consumer(root: string): boolean {
|
|
68
|
+
const manifest = parse_manifest(root)
|
|
69
|
+
if (manifest?.name === KIT_PACKAGE_NAME) return false
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
lists_kit_dependency(manifest) || existsSync(path.join(root, NODE_MODULES, KIT_PACKAGE_NAME))
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function is_plugin_declared(root: string): boolean {
|
|
77
|
+
const content = read_optional(path.join(root, SETTINGS_PATH))
|
|
78
|
+
if (content === undefined) return false
|
|
79
|
+
const parsed = settings_schema.safeParse(safe_json_parse(content))
|
|
80
|
+
|
|
81
|
+
return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The value of `core.hooksPath`, or undefined when it is unset. A set value is what stops lefthook
|
|
85
|
+
// from installing kit's git hooks — the failure is silent but for one stderr line.
|
|
86
|
+
function configured_hooks_path(root: string): string | undefined {
|
|
87
|
+
const result = execaSync('git', ['-C', root, 'config', '--get', 'core.hooksPath'], {
|
|
88
|
+
reject: false,
|
|
89
|
+
timeout: GIT_TIMEOUT_MS,
|
|
90
|
+
})
|
|
91
|
+
const value = read_spawn_stdout(result).trim()
|
|
92
|
+
|
|
93
|
+
return value === '' ? undefined : value
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function claude_md_state(root: string): ClaudeMdState {
|
|
97
|
+
const content = read_optional(path.join(root, CLAUDE_MD))
|
|
98
|
+
if (content === undefined) return STATE_MISSING
|
|
99
|
+
if (!content.includes(CLAUDE_MD_POINTER)) return STATE_OK
|
|
100
|
+
|
|
101
|
+
return existsSync(path.join(root, NODE_MODULES, KIT_PACKAGE_NAME, 'dist', CLAUDE_MD))
|
|
102
|
+
? STATE_OK
|
|
103
|
+
: STATE_TARGET_MISSING
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function is_secretlint_runnable(root: string): boolean {
|
|
107
|
+
return existsSync(path.join(root, SECRETLINT_BIN))
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function status_line(is_ok: boolean, ok_text: string, warn_text: string): string {
|
|
111
|
+
return is_ok ? ` ✓ ${ok_text}` : ` ⚠ ${warn_text}`
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function plugin_line(is_declared: boolean): string {
|
|
115
|
+
return status_line(
|
|
116
|
+
is_declared,
|
|
117
|
+
`kit plugin declared (run \`claude plugin install ${PLUGIN_ID}\` once if skills are missing)`,
|
|
118
|
+
'kit plugin not declared in .claude/settings.json — run `pnpm josh sync`',
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function hooks_path_line(hooks_path: string | undefined): string {
|
|
123
|
+
return status_line(
|
|
124
|
+
hooks_path === undefined,
|
|
125
|
+
'git hooks install normally (core.hooksPath unset)',
|
|
126
|
+
`core.hooksPath is set (${hooks_path ?? ''}) — lefthook installs no git hooks; unset it`,
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function claude_md_line(state: ClaudeMdState): string {
|
|
131
|
+
if (state === STATE_OK) return ' ✓ CLAUDE.md resolves to the installed kit rules'
|
|
132
|
+
|
|
133
|
+
if (state === STATE_TARGET_MISSING) {
|
|
134
|
+
return ' ⚠ CLAUDE.md points at rules that are not installed — run `pnpm install`'
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return ' ⚠ CLAUDE.md is missing — run `pnpm josh init`'
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function secretlint_line(is_runnable: boolean): string {
|
|
141
|
+
return status_line(
|
|
142
|
+
is_runnable,
|
|
143
|
+
'secretlint is runnable',
|
|
144
|
+
'secretlint is not installed — run `pnpm install`',
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function consumer_setup_lines(root: string): ReadonlyArray<string> {
|
|
149
|
+
return [
|
|
150
|
+
plugin_line(is_plugin_declared(root)),
|
|
151
|
+
hooks_path_line(configured_hooks_path(root)),
|
|
152
|
+
claude_md_line(claude_md_state(root)),
|
|
153
|
+
secretlint_line(is_secretlint_runnable(root)),
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Printed only in a repository that consumes kit, so kit's own `josh doctor` stays quiet about it.
|
|
158
|
+
function report_consumer_setup(root: string): void {
|
|
159
|
+
if (!is_kit_consumer(root)) return
|
|
160
|
+
|
|
161
|
+
console.info('')
|
|
162
|
+
console.info('Consumer setup:')
|
|
163
|
+
for (const line of consumer_setup_lines(root)) console.info(line)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const doctor_consumer = {
|
|
167
|
+
claude_md_line,
|
|
168
|
+
claude_md_state,
|
|
169
|
+
configured_hooks_path,
|
|
170
|
+
consumer_setup_lines,
|
|
171
|
+
hooks_path_line,
|
|
172
|
+
is_kit_consumer,
|
|
173
|
+
is_plugin_declared,
|
|
174
|
+
is_secretlint_runnable,
|
|
175
|
+
plugin_line,
|
|
176
|
+
report_consumer_setup,
|
|
177
|
+
secretlint_line,
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export type { ClaudeMdState }
|
|
181
|
+
export { doctor_consumer }
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { read_spawn_stderr, read_spawn_stdout } from '#scripts/lib/spawn-exit'
|
|
4
|
+
import { execaSync } from 'execa'
|
|
5
|
+
import { doctor_logic } from './doctor-logic'
|
|
6
|
+
|
|
7
|
+
const JOSH_BIN = 'josh'
|
|
8
|
+
const GIT_TIMEOUT_MS = 2000
|
|
9
|
+
const NOT_A_REPOSITORY_MESSAGE = 'not a git repository'
|
|
10
|
+
const NPM_VERSION_UPDATES_DISABLED = 'open-pull-requests-limit: 0'
|
|
11
|
+
const DEPENDABOT_CONFIG_PATH = '.github/dependabot.yml'
|
|
12
|
+
const ECOSYSTEM_KEY = 'package-ecosystem:'
|
|
13
|
+
const NPM_ECOSYSTEM = 'npm'
|
|
14
|
+
const AUTO_MERGE_WORKFLOW_PATH = '.github/workflows/dependabot-auto-merge.yml'
|
|
15
|
+
// The command that needs the repository's "Allow auto-merge" setting, and the only thing in the
|
|
16
|
+
// workflow that does. Matching it rather than the filename is what keeps the report tied to the
|
|
17
|
+
// prerequisite: a file of that name which never calls `--auto` creates no prerequisite, and a
|
|
18
|
+
// consumer's own auto-merge workflow which does creates the same one kit's does
|
|
19
|
+
// (joshuafolkken/kit#834).
|
|
20
|
+
const AUTO_MERGE_COMMAND = 'gh pr merge --auto'
|
|
21
|
+
const YAML_COMMENT_PREFIX = '#'
|
|
22
|
+
|
|
23
|
+
// Resolve the `josh` that the shell would run — the first match on PATH, via the platform's
|
|
24
|
+
// lookup command (`where` on Windows, `which` elsewhere). Undefined when the lookup fails or
|
|
25
|
+
// prints nothing (no `josh` on PATH, e.g. inside the kit repo where only `pnpm josh` runs).
|
|
26
|
+
function resolve_path_josh(): string | undefined {
|
|
27
|
+
const lookup = doctor_logic.path_lookup_command(process.platform)
|
|
28
|
+
const result = execaSync(lookup, [JOSH_BIN], { reject: false })
|
|
29
|
+
|
|
30
|
+
return doctor_logic.first_path_line(read_spawn_stdout(result))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Resolve the pnpm-global `josh` bin path. Undefined when pnpm is missing or the global bin does
|
|
34
|
+
// not contain a `josh` (kit not installed globally). `pnpm bin -g` prepends a `[WARN]` line to
|
|
35
|
+
// stdout inside a project, so the bin directory is extracted via first_path_line.
|
|
36
|
+
function resolve_pnpm_global_josh(): string | undefined {
|
|
37
|
+
const result = execaSync('pnpm', ['bin', '-g'], { reject: false })
|
|
38
|
+
const bin_directory = doctor_logic.first_path_line(read_spawn_stdout(result))
|
|
39
|
+
if (bin_directory === undefined) return undefined
|
|
40
|
+
const candidate = path.join(bin_directory, JOSH_BIN)
|
|
41
|
+
|
|
42
|
+
return existsSync(candidate) ? candidate : undefined
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Whether the working directory is provably *outside* a git work tree. Purely local — no network,
|
|
46
|
+
// and it does not depend on `gh` being installed or authenticated, which is what makes it usable to
|
|
47
|
+
// decide whether a repository-scoped check applies at all (joshuafolkken/kit#805).
|
|
48
|
+
//
|
|
49
|
+
// An empty root from a successful run is not an answer, so it is undetermined rather than inside.
|
|
50
|
+
function classify_top_level(top_level: string): GitTopLevel {
|
|
51
|
+
return top_level === '' ? { state: 'undetermined' } : { state: 'inside', top_level }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Only `fatal: not a git repository` proves absence. Exit 128 alone does not: git returns it inside
|
|
55
|
+
// a repository for dubious ownership (`safe.directory`), a corrupt `.git`, or a broken config. An
|
|
56
|
+
// undefined exit code is a spawn failure or a timeout — git never answered at all.
|
|
57
|
+
function classify_git_failure(exit_code: number | undefined, stderr: string): GitTopLevel {
|
|
58
|
+
if (exit_code === undefined) return { state: 'undetermined' }
|
|
59
|
+
|
|
60
|
+
return { state: stderr.includes(NOT_A_REPOSITORY_MESSAGE) ? 'outside' : 'undetermined' }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The repository root, or a reason there is none. `--show-toplevel` is used rather than
|
|
64
|
+
// `--is-inside-work-tree` because the caller needs the root itself: the config file that decides
|
|
65
|
+
// applicability lives at a fixed path relative to it, and resolving that path against the working
|
|
66
|
+
// directory instead would skip the check in every subdirectory of a consumer repository.
|
|
67
|
+
//
|
|
68
|
+
// `outside` and `undetermined` are kept apart deliberately: only proof of absence may skip the
|
|
69
|
+
// caller's check, because reporting an unknown as a clean result is the false all-clear
|
|
70
|
+
// joshuafolkken/kit#805 exists to remove. See the two classifiers above for what proves what.
|
|
71
|
+
function resolve_git_top_level(): GitTopLevel {
|
|
72
|
+
const result = execaSync('git', ['rev-parse', '--show-toplevel'], {
|
|
73
|
+
reject: false,
|
|
74
|
+
timeout: GIT_TIMEOUT_MS,
|
|
75
|
+
// git translates its messages, so the match below would fail under any non-English locale and
|
|
76
|
+
// the spurious warning would come back. `C` pins the output this code was written against.
|
|
77
|
+
env: { LC_ALL: 'C', LANGUAGE: 'C' },
|
|
78
|
+
extendEnv: true,
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
if (result.exitCode === 0) return classify_top_level(read_spawn_stdout(result).trim())
|
|
82
|
+
|
|
83
|
+
return classify_git_failure(result.exitCode, read_spawn_stderr(result))
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Whether one line is the setting itself rather than prose about it. kit's own template explains the
|
|
87
|
+
// option in a comment containing the same literal, so a substring search over the file would match
|
|
88
|
+
// that comment — and any file that quotes it. The line must be indented (it sits under an `updates:`
|
|
89
|
+
// entry) and must be exactly the mapping, which a `#` comment never is. Scanned line by line rather
|
|
90
|
+
// than matched with an anchored regex, which backtracks super-linearly on this shape.
|
|
91
|
+
function is_version_updates_disabled_line(line: string): boolean {
|
|
92
|
+
if (!line.startsWith(' ') && !line.startsWith('\t')) return false
|
|
93
|
+
|
|
94
|
+
return line.trim() === NPM_VERSION_UPDATES_DISABLED
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// A Dependabot `updates:` entry begins with the ecosystem key; the limit must belong to the npm one.
|
|
98
|
+
function is_entry_start(line: string): boolean {
|
|
99
|
+
return line.trimStart().startsWith(`- ${ECOSYSTEM_KEY}`)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function is_npm_entry_start(line: string): boolean {
|
|
103
|
+
return is_entry_start(line) && line.includes(NPM_ECOSYSTEM)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// The lines belonging to the npm `updates:` entry, in order. An entry runs until the next one starts.
|
|
107
|
+
function npm_entry_lines(lines: ReadonlyArray<string>): Array<string> {
|
|
108
|
+
const start = lines.findIndex((line) => is_npm_entry_start(line))
|
|
109
|
+
if (start === -1) return []
|
|
110
|
+
const rest = lines.slice(start + 1)
|
|
111
|
+
const end = rest.findIndex((line) => is_entry_start(line))
|
|
112
|
+
|
|
113
|
+
return end === -1 ? rest : rest.slice(0, end)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Whether the npm entry disables version updates. Scoped to that entry rather than matched across
|
|
117
|
+
// the whole file: a project that sets the same limit on, say, its `docker` entry has not received
|
|
118
|
+
// kit's change and must not be warned about it.
|
|
119
|
+
function has_npm_version_updates_disabled(content: string): boolean {
|
|
120
|
+
return npm_entry_lines(content.split('\n')).some((line) => is_version_updates_disabled_line(line))
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// The nearest ancestor of `start` holding `relative_path`, or nothing. Searching upward rather than
|
|
124
|
+
// testing `start` alone is what keeps the check alive in a subdirectory when git could not report
|
|
125
|
+
// the repository root — a `safe.directory` refusal, for instance, which `classify_git_failure`
|
|
126
|
+
// deliberately routes to `undetermined` precisely so the check survives.
|
|
127
|
+
//
|
|
128
|
+
// `boundary` stops the walk at the repository root when one is known. Without it a repository nested
|
|
129
|
+
// under a kit consumer would inherit the parent's files and be warned about a prerequisite that
|
|
130
|
+
// belongs to a different project.
|
|
131
|
+
function find_project_file(
|
|
132
|
+
start: string,
|
|
133
|
+
relative_path: string,
|
|
134
|
+
boundary: string | undefined,
|
|
135
|
+
): string | undefined {
|
|
136
|
+
const candidate = path.join(start, relative_path)
|
|
137
|
+
if (existsSync(candidate)) return candidate
|
|
138
|
+
if (start === boundary) return undefined
|
|
139
|
+
const parent = path.dirname(start)
|
|
140
|
+
|
|
141
|
+
return parent === start ? undefined : find_project_file(parent, relative_path, boundary)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Whether a distributed artifact is present *and* carries the marker that creates the prerequisite.
|
|
145
|
+
// Existence alone is never enough: any project may ship a file of the same name, and warning there
|
|
146
|
+
// would advertise an enabling command for a repository that never consumed kit.
|
|
147
|
+
//
|
|
148
|
+
// The read is guarded even though existence was just checked: a permission error, a directory in the
|
|
149
|
+
// file's place, or a race between the two calls would otherwise throw out of `josh doctor` and abort
|
|
150
|
+
// a command whose whole contract is that this check never fails it. An unreadable file cannot prove
|
|
151
|
+
// the prerequisite applies, so it reads as absent.
|
|
152
|
+
function has_marked_project_file(
|
|
153
|
+
start: string,
|
|
154
|
+
relative_path: string,
|
|
155
|
+
boundary: string | undefined,
|
|
156
|
+
is_marked: (content: string) => boolean,
|
|
157
|
+
): boolean {
|
|
158
|
+
const file_path = find_project_file(start, relative_path, boundary)
|
|
159
|
+
if (file_path === undefined) return false
|
|
160
|
+
|
|
161
|
+
try {
|
|
162
|
+
return is_marked(readFileSync(file_path, 'utf8'))
|
|
163
|
+
} catch {
|
|
164
|
+
return false
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Whether the project has received kit's `.github/dependabot.yml`. The npm entry's
|
|
169
|
+
// `open-pull-requests-limit: 0` is what creates the prerequisite (joshuafolkken/kit#803), so that is
|
|
170
|
+
// what is matched.
|
|
171
|
+
function has_distributed_dependabot_config(start: string, boundary?: string): boolean {
|
|
172
|
+
return has_marked_project_file(start, DEPENDABOT_CONFIG_PATH, boundary, (content) =>
|
|
173
|
+
has_npm_version_updates_disabled(content),
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Whether one line runs the command rather than merely mentioning it. kit's own template explains
|
|
178
|
+
// the prerequisite in a comment containing the same literal, so a substring search over the file
|
|
179
|
+
// would match that comment — and any file that quotes it. The same distinction the npm
|
|
180
|
+
// version-updates check draws above, for the same reason.
|
|
181
|
+
function is_auto_merge_command_line(line: string): boolean {
|
|
182
|
+
const trimmed = line.trimStart()
|
|
183
|
+
|
|
184
|
+
return !trimmed.startsWith(YAML_COMMENT_PREFIX) && trimmed.includes(AUTO_MERGE_COMMAND)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Whether the project runs a Dependabot auto-merge workflow. `gh pr merge --auto` is what needs the
|
|
188
|
+
// repository's "Allow auto-merge" setting, so that is what is matched (joshuafolkken/kit#834).
|
|
189
|
+
function has_auto_merge_workflow(start: string, boundary?: string): boolean {
|
|
190
|
+
return has_marked_project_file(start, AUTO_MERGE_WORKFLOW_PATH, boundary, (content) =>
|
|
191
|
+
content.split('\n').some((line) => is_auto_merge_command_line(line)),
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Where a repository-scoped check stands: inside a repository (with its root), provably outside
|
|
196
|
+
// one, or unable to tell.
|
|
197
|
+
type GitTopLevel =
|
|
198
|
+
{ state: 'inside'; top_level: string } | { state: 'outside' } | { state: 'undetermined' }
|
|
199
|
+
|
|
200
|
+
const doctor_io = {
|
|
201
|
+
GIT_TIMEOUT_MS,
|
|
202
|
+
resolve_path_josh,
|
|
203
|
+
resolve_pnpm_global_josh,
|
|
204
|
+
has_distributed_dependabot_config,
|
|
205
|
+
has_auto_merge_workflow,
|
|
206
|
+
resolve_git_top_level,
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export type { GitTopLevel }
|
|
210
|
+
export { doctor_io }
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
const RECOVERY_COMMAND = 'josh doctor --fix'
|
|
4
|
+
const REPOSITORY_MAP_HEADING = 'Repositories (same owner, discovered next to this one):'
|
|
5
|
+
const NO_REPOSITORIES_FOUND = ' (none discovered — see JOSH_REPO_PATHS in docs/josh-commands.md)'
|
|
6
|
+
const GLOBAL_REINSTALL_COMMAND = 'pnpm add -g @joshuafolkken/kit'
|
|
7
|
+
// Markers identifying a `josh` on PATH that was generated by an old kit `postinstall`
|
|
8
|
+
// (pre-0.200.0 `install-bin.ts` wrote a shim referencing the kit package / tsx runner).
|
|
9
|
+
const KIT_SHIM_MARKERS: ReadonlyArray<string> = [
|
|
10
|
+
'@joshuafolkken/kit',
|
|
11
|
+
'@joshuafolkken+kit',
|
|
12
|
+
'install-bin',
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
type ReclaimAction = 'remove' | 'none'
|
|
16
|
+
|
|
17
|
+
interface ReclaimDecision {
|
|
18
|
+
action: ReclaimAction
|
|
19
|
+
target?: string
|
|
20
|
+
reason: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const NO_SHADOW_REASON = 'no PATH shadowing detected'
|
|
24
|
+
const NOT_KIT_SHIM_REASON =
|
|
25
|
+
'the shadowing binary is not a kit shim — remove it manually if it is unexpected'
|
|
26
|
+
const RECLAIM_REASON = 'reclaimed the global josh by removing the stale kit shim'
|
|
27
|
+
|
|
28
|
+
const WINDOWS_PLATFORM = 'win32'
|
|
29
|
+
// Absolute path on any platform: POSIX `/…`, Windows drive-letter `C:\…` / `C:/…`, or UNC `\\…`.
|
|
30
|
+
// Detecting absoluteness by shape (not `path.sep`) keeps parsing correct regardless of the host OS.
|
|
31
|
+
const ABSOLUTE_PATH_PATTERN = /^(?:\/|[a-zA-Z]:[/\\]|\\\\)/u
|
|
32
|
+
|
|
33
|
+
function normalize_path(target: string): string {
|
|
34
|
+
return path.resolve(target)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The cross-platform PATH-lookup command: `where` on Windows, `which` elsewhere.
|
|
38
|
+
function path_lookup_command(platform: string): string {
|
|
39
|
+
return platform === WINDOWS_PLATFORM ? 'where' : 'which'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Extract an absolute path from possibly noisy command output: `pnpm bin -g` prepends a
|
|
43
|
+
// `[WARN] Using --global …` line to stdout when run inside a project, and `where` may list several
|
|
44
|
+
// matches. Take the first line that looks like an absolute path (the effective one), skipping
|
|
45
|
+
// noise. Undefined when no such line is present.
|
|
46
|
+
function first_path_line(stdout: string): string | undefined {
|
|
47
|
+
return stdout
|
|
48
|
+
.split('\n')
|
|
49
|
+
.map((line) => line.trim())
|
|
50
|
+
.find((line) => ABSOLUTE_PATH_PATTERN.test(line))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// PATH shadowing: the `josh` first on PATH is not the pnpm-global install. Both paths must be known
|
|
54
|
+
// for a comparison — an undefined side means we cannot prove shadowing, so report false.
|
|
55
|
+
function is_shadowed(path_josh: string | undefined, global_josh: string | undefined): boolean {
|
|
56
|
+
if (path_josh === undefined || global_josh === undefined) return false
|
|
57
|
+
|
|
58
|
+
return normalize_path(path_josh) !== normalize_path(global_josh)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A reclaimable kit shim references the kit package or the removed install-bin script in its body.
|
|
62
|
+
function is_kit_shim(content: string): boolean {
|
|
63
|
+
return KIT_SHIM_MARKERS.some((marker) => content.includes(marker))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Decide whether `doctor --fix` may safely remove the shadowing binary. Only a confirmed kit shim
|
|
67
|
+
// is removed; any other shadowing binary is left untouched and reported for manual review.
|
|
68
|
+
function decide_reclaim(
|
|
69
|
+
path_josh: string | undefined,
|
|
70
|
+
global_josh: string | undefined,
|
|
71
|
+
shim_content: string,
|
|
72
|
+
): ReclaimDecision {
|
|
73
|
+
if (!is_shadowed(path_josh, global_josh)) return { action: 'none', reason: NO_SHADOW_REASON }
|
|
74
|
+
// is_shadowed already guarantees path_josh is defined; this narrows the type for the return.
|
|
75
|
+
if (path_josh === undefined) return { action: 'none', reason: NO_SHADOW_REASON }
|
|
76
|
+
if (!is_kit_shim(shim_content)) return { action: 'none', reason: NOT_KIT_SHIM_REASON }
|
|
77
|
+
|
|
78
|
+
return { action: 'remove', target: path_josh, reason: RECLAIM_REASON }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// The discovered map, as `josh doctor` prints it. Printing it is what makes a wrong map noticeable:
|
|
82
|
+
// the map decides which checkouts other commands write to, and a silent one would only be found by
|
|
83
|
+
// the write landing in the wrong place (joshuafolkken/kit#869).
|
|
84
|
+
function format_repository_map(map: ReadonlyMap<string, string>): string {
|
|
85
|
+
if (map.size === 0) return [REPOSITORY_MAP_HEADING, NO_REPOSITORIES_FOUND].join('\n')
|
|
86
|
+
const rows: Array<string> = []
|
|
87
|
+
|
|
88
|
+
for (const [key, repository_path] of map) rows.push(` ${key} ${repository_path}`)
|
|
89
|
+
const sorted = rows.toSorted((left, right) => left.localeCompare(right))
|
|
90
|
+
|
|
91
|
+
return [REPOSITORY_MAP_HEADING, ...sorted].join('\n')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function format_shadow_warning(path_josh: string, global_josh: string): string {
|
|
95
|
+
return [
|
|
96
|
+
"⚠ PATH shadowing: the 'josh' first on PATH is not the pnpm-global install.",
|
|
97
|
+
` On PATH: ${path_josh}`,
|
|
98
|
+
` pnpm global: ${global_josh}`,
|
|
99
|
+
` Recover: ${RECOVERY_COMMAND}`,
|
|
100
|
+
].join('\n')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const doctor_logic = {
|
|
104
|
+
RECOVERY_COMMAND,
|
|
105
|
+
GLOBAL_REINSTALL_COMMAND,
|
|
106
|
+
NO_SHADOW_REASON,
|
|
107
|
+
NOT_KIT_SHIM_REASON,
|
|
108
|
+
RECLAIM_REASON,
|
|
109
|
+
REPOSITORY_MAP_HEADING,
|
|
110
|
+
NO_REPOSITORIES_FOUND,
|
|
111
|
+
format_repository_map,
|
|
112
|
+
normalize_path,
|
|
113
|
+
path_lookup_command,
|
|
114
|
+
first_path_line,
|
|
115
|
+
is_shadowed,
|
|
116
|
+
is_kit_shim,
|
|
117
|
+
decide_reclaim,
|
|
118
|
+
format_shadow_warning,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export type { ReclaimAction, ReclaimDecision }
|
|
122
|
+
export { doctor_logic }
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { ENV_FILE_NAME, PORT_SEED_KEY, ports } from '#ports'
|
|
4
|
+
import { lane_environment } from '#scripts/lane/lane-environment'
|
|
5
|
+
|
|
6
|
+
// Each discovered repository's port seed and the dev / preview ports it resolves to, plus which
|
|
7
|
+
// repositories share a seed (joshuafolkken/kit#1494).
|
|
8
|
+
//
|
|
9
|
+
// The formula `seed × 10 + lane` makes distinct seeds occupy disjoint bands, but two repositories on
|
|
10
|
+
// the *same* seed still collide — as do the many that never set one and sit together on seed 0. That
|
|
11
|
+
// clash surfaces only as an E2E run failing to bind a port somewhere else, so `doctor` names it here
|
|
12
|
+
// instead. **`.env` is never rewritten**: the seed is a personal, per-machine setting, so the report
|
|
13
|
+
// points at the clash and a person resolves it.
|
|
14
|
+
|
|
15
|
+
const HEADING = 'Port seeds (dev / preview, and repositories sharing one):'
|
|
16
|
+
const UNREADABLE = 'PORT_SEED could not be read'
|
|
17
|
+
const ROW_INDENT = ' '
|
|
18
|
+
const COLUMN_SEPARATOR = ' '
|
|
19
|
+
const SHARED_PREFIX = ' ⚠ seed '
|
|
20
|
+
const SOLE_MEMBER = 1
|
|
21
|
+
|
|
22
|
+
interface RepoPorts {
|
|
23
|
+
name: string
|
|
24
|
+
// `undefined` when the repository's `.env` holds a malformed seed — reported rather than guessed.
|
|
25
|
+
seed: number | undefined
|
|
26
|
+
development: number | undefined
|
|
27
|
+
preview: number | undefined
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface SharedSeed {
|
|
31
|
+
seed: number
|
|
32
|
+
names: Array<string>
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// A repository is read at its main work tree (seat 0), so the ports reported are the ones it runs on
|
|
36
|
+
// without a lane open, computed from the seed alone — a root `.env` should carry no `JOSH_LANE_SEAT`,
|
|
37
|
+
// and honoring a stray one would move the reported ports off the main tree and hide a valid seed
|
|
38
|
+
// behind a malformed seat. A missing `.env` is the common case — the unset seed CI and un-migrated
|
|
39
|
+
// consumers use — and reads as seed 0; a malformed seed is caught and reported unreadable, naming
|
|
40
|
+
// the one key that is actually wrong.
|
|
41
|
+
function read_repository_ports(name: string, repository_path: string): RepoPorts {
|
|
42
|
+
const file = path.join(repository_path, ENV_FILE_NAME)
|
|
43
|
+
const content = existsSync(file) ? readFileSync(file, 'utf8') : ''
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const seed = lane_environment.read_root_seed(content)
|
|
47
|
+
const environment = { [PORT_SEED_KEY]: String(seed) }
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
name,
|
|
51
|
+
seed,
|
|
52
|
+
development: ports.resolve_development_port(environment),
|
|
53
|
+
preview: ports.resolve_preview_port(environment),
|
|
54
|
+
}
|
|
55
|
+
} catch {
|
|
56
|
+
return { name, seed: undefined, development: undefined, preview: undefined }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function format_row(entry: RepoPorts): string {
|
|
61
|
+
if (entry.seed === undefined) return `${ROW_INDENT}${entry.name}${COLUMN_SEPARATOR}${UNREADABLE}`
|
|
62
|
+
|
|
63
|
+
const columns = `seed ${String(entry.seed)}${COLUMN_SEPARATOR}dev ${String(entry.development)}${COLUMN_SEPARATOR}preview ${String(entry.preview)}`
|
|
64
|
+
|
|
65
|
+
return `${ROW_INDENT}${entry.name}${COLUMN_SEPARATOR}${columns}`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function group_by_seed(entries: ReadonlyArray<RepoPorts>): Map<number, Array<string>> {
|
|
69
|
+
const by_seed = new Map<number, Array<string>>()
|
|
70
|
+
|
|
71
|
+
for (const { name, seed } of entries) {
|
|
72
|
+
if (seed === undefined) continue
|
|
73
|
+
by_seed.set(seed, [...(by_seed.get(seed) ?? []), name])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return by_seed
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Only seeds held by more than one repository are a clash worth naming.
|
|
80
|
+
function shared_seeds(entries: ReadonlyArray<RepoPorts>): Array<SharedSeed> {
|
|
81
|
+
return [...group_by_seed(entries)]
|
|
82
|
+
.filter(([, names]) => names.length > SOLE_MEMBER)
|
|
83
|
+
.map(([seed, names]) => ({ seed, names }))
|
|
84
|
+
.toSorted((left, right) => left.seed - right.seed)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function format_shared(shared: ReadonlyArray<SharedSeed>): Array<string> {
|
|
88
|
+
return shared.map(
|
|
89
|
+
({ seed, names }) => `${SHARED_PREFIX}${String(seed)} is shared by: ${names.join(', ')}`,
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function format_port_report(entries: ReadonlyArray<RepoPorts>): string {
|
|
94
|
+
const rows = entries.map((entry) => format_row(entry))
|
|
95
|
+
const shared = format_shared(shared_seeds(entries))
|
|
96
|
+
|
|
97
|
+
return [HEADING, ...rows, ...shared].join('\n')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// The map is `owner/repo` → absolute path; the rows are sorted by name so the report is stable.
|
|
101
|
+
function report_port_seeds(map: ReadonlyMap<string, string>): string {
|
|
102
|
+
const entries = [...map]
|
|
103
|
+
.toSorted(([left], [right]) => left.localeCompare(right))
|
|
104
|
+
.map(([name, repository_path]) => read_repository_ports(name, repository_path))
|
|
105
|
+
|
|
106
|
+
return format_port_report(entries)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const doctor_ports = {
|
|
110
|
+
format_port_report,
|
|
111
|
+
read_repository_ports,
|
|
112
|
+
report_port_seeds,
|
|
113
|
+
shared_seeds,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type { RepoPorts as RepositoryPorts }
|
|
117
|
+
export { doctor_ports }
|