@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,84 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import { execaSync } from 'execa'
|
|
3
|
+
|
|
4
|
+
const SAFE_CHAIN_PKG = '@aikidosec/safe-chain'
|
|
5
|
+
const VERSION_RE = /@aikidosec\/safe-chain@([^\s"']+)/u
|
|
6
|
+
const NPM_TIMEOUT_MS = 30_000
|
|
7
|
+
|
|
8
|
+
interface PreinstallInfo {
|
|
9
|
+
content: string
|
|
10
|
+
current_version: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function extract_pinned_version(preinstall: string): string | undefined {
|
|
14
|
+
return VERSION_RE.exec(preinstall)?.[1]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fetch_latest_version(): string | undefined {
|
|
18
|
+
const result = execaSync('npm', ['view', SAFE_CHAIN_PKG, 'version'], {
|
|
19
|
+
reject: false,
|
|
20
|
+
timeout: NPM_TIMEOUT_MS,
|
|
21
|
+
})
|
|
22
|
+
if (result.exitCode !== 0 || !result.stdout) return undefined
|
|
23
|
+
|
|
24
|
+
return result.stdout.trim()
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function rewrite_version(content: string, current_version: string, next_version: string): string {
|
|
28
|
+
return content.replace(
|
|
29
|
+
`${SAFE_CHAIN_PKG}@${current_version}`,
|
|
30
|
+
() => `${SAFE_CHAIN_PKG}@${next_version}`,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function read_preinstall_info(package_json_path: string): PreinstallInfo | undefined {
|
|
35
|
+
const content = readFileSync(package_json_path, 'utf8')
|
|
36
|
+
const package_json = JSON.parse(content) as { scripts?: { preinstall?: string } }
|
|
37
|
+
const preinstall = package_json.scripts?.preinstall
|
|
38
|
+
if (!preinstall) return undefined
|
|
39
|
+
|
|
40
|
+
const current_version = extract_pinned_version(preinstall)
|
|
41
|
+
if (!current_version) return undefined
|
|
42
|
+
|
|
43
|
+
return { content, current_version }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function write_if_updated(
|
|
47
|
+
package_json_path: string,
|
|
48
|
+
content: string,
|
|
49
|
+
current: string,
|
|
50
|
+
latest: string,
|
|
51
|
+
): void {
|
|
52
|
+
if (current === latest) {
|
|
53
|
+
console.info(`\n✔ ${SAFE_CHAIN_PKG} preinstall already at ${latest}`)
|
|
54
|
+
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
console.info(`\n↑ Updating ${SAFE_CHAIN_PKG} preinstall: ${current} → ${latest}`)
|
|
59
|
+
writeFileSync(package_json_path, rewrite_version(content, current, latest), 'utf8')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function sync(package_json_path: string): void {
|
|
63
|
+
const info = read_preinstall_info(package_json_path)
|
|
64
|
+
if (!info) return
|
|
65
|
+
|
|
66
|
+
const latest = fetch_latest_version()
|
|
67
|
+
|
|
68
|
+
if (!latest) {
|
|
69
|
+
console.warn(`\n⚠ Could not fetch latest version of ${SAFE_CHAIN_PKG}; skipping`)
|
|
70
|
+
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
write_if_updated(package_json_path, info.content, info.current_version, latest)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const preinstall_version_update = {
|
|
78
|
+
sync,
|
|
79
|
+
extract_pinned_version,
|
|
80
|
+
fetch_latest_version,
|
|
81
|
+
rewrite_version,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { preinstall_version_update }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Release gate: every dependency range this package publishes must resolve for a consumer.
|
|
4
|
+
*
|
|
5
|
+
* Usage: tsx scripts/version/publishable-range-check.ts
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from 'node:fs'
|
|
8
|
+
import { fileURLToPath } from 'node:url'
|
|
9
|
+
import { execaSync } from 'execa'
|
|
10
|
+
import {
|
|
11
|
+
publishable_range,
|
|
12
|
+
type ProbeResult,
|
|
13
|
+
type PublishedRange,
|
|
14
|
+
type RangeProbe,
|
|
15
|
+
} from './publishable-range'
|
|
16
|
+
|
|
17
|
+
const PACKAGE_JSON_PATH = 'package.json'
|
|
18
|
+
const VIEW_TIMEOUT_MS = 30_000
|
|
19
|
+
const FAILURE_EXIT_CODE = 1
|
|
20
|
+
|
|
21
|
+
// A registry query rather than a direct fetch: safe-chain installs shims ahead of the package
|
|
22
|
+
// managers on PATH, so the answer comes back already filtered by the same minimum-age policy a
|
|
23
|
+
// consumer installs under. A plain fetch would read the unfiltered registry and pass a range no
|
|
24
|
+
// consumer can resolve — the exact blind spot this guard exists to close.
|
|
25
|
+
//
|
|
26
|
+
// `pnpm view` rather than `npm view` because npm refuses to run at all inside a project whose
|
|
27
|
+
// `devEngines.packageManager` names pnpm with `onFail: "error"`, failing every probe with
|
|
28
|
+
// EBADDEVENGINES instead of answering. Both are shimmed, so the filtered view is preserved.
|
|
29
|
+
function probe_range(name: string, range: string): ProbeResult {
|
|
30
|
+
const result = execaSync('pnpm', ['view', `${name}@${range}`, 'version'], {
|
|
31
|
+
reject: false,
|
|
32
|
+
timeout: VIEW_TIMEOUT_MS,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return { exit_code: result.exitCode ?? FAILURE_EXIT_CODE, stdout: result.stdout }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function report(violations: ReadonlyArray<PublishedRange>, total: number): number {
|
|
39
|
+
if (violations.length === 0) {
|
|
40
|
+
console.info(publishable_range.format_success(total))
|
|
41
|
+
|
|
42
|
+
return 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.error(publishable_range.format_failure(violations))
|
|
46
|
+
|
|
47
|
+
return FAILURE_EXIT_CODE
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function report_skipped(skipped: ReadonlyArray<PublishedRange>): void {
|
|
51
|
+
if (skipped.length === 0) return
|
|
52
|
+
|
|
53
|
+
console.info(publishable_range.format_skipped(skipped))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Returns the process exit code so the decision can be asserted without spawning a process. */
|
|
57
|
+
function check(package_json_content: string, probe: RangeProbe): number {
|
|
58
|
+
const ranges = publishable_range.read_published_ranges(package_json_content)
|
|
59
|
+
const { checked, skipped } = publishable_range.partition_registry_ranges(ranges)
|
|
60
|
+
|
|
61
|
+
report_skipped(skipped)
|
|
62
|
+
|
|
63
|
+
return report(publishable_range.find_unsatisfiable(checked, probe), checked.length)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function main(): void {
|
|
67
|
+
process.exit(check(readFileSync(PACKAGE_JSON_PATH, 'utf8'), probe_range))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main()
|
|
71
|
+
|
|
72
|
+
const publishable_range_check = { check, probe_range }
|
|
73
|
+
|
|
74
|
+
export { publishable_range_check }
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { package_with_deps_schema } from '#scripts/overrides/schemas'
|
|
2
|
+
import semver from 'semver'
|
|
3
|
+
|
|
4
|
+
// kit ships a `preinstall` hook that installs @aikidosec/safe-chain, whose minimum-age policy hides
|
|
5
|
+
// releases younger than its window from every install running behind it. A range whose floor sits
|
|
6
|
+
// inside that window has no satisfying version for a consumer, so `pnpm install` fails with
|
|
7
|
+
// ERR_PNPM_NO_MATCHING_VERSION naming a version that demonstrably exists and is tagged latest (#742).
|
|
8
|
+
//
|
|
9
|
+
// The check asks the registry through that same filtered view instead of modelling the policy:
|
|
10
|
+
// `pnpm view <name>@<range> version` prints no version and exits non-zero
|
|
11
|
+
// (ERR_PNPM_PACKAGE_NOT_FOUND) exactly when nothing visible satisfies the range. Modelling would
|
|
12
|
+
// mean guessing safe-chain's threshold, and `minimumReleaseAgeExclude` cannot stand in for it —
|
|
13
|
+
// that list governs pnpm's own `minimum-release-age`, and safe-chain has no knowledge of it, which
|
|
14
|
+
// is precisely what made the original failure surprising.
|
|
15
|
+
|
|
16
|
+
interface PublishedRange {
|
|
17
|
+
name: string
|
|
18
|
+
range: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface ProbeResult {
|
|
22
|
+
exit_code: number
|
|
23
|
+
stdout: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type RangeProbe = (name: string, range: string) => ProbeResult
|
|
27
|
+
|
|
28
|
+
interface RangePartition {
|
|
29
|
+
checked: Array<PublishedRange>
|
|
30
|
+
skipped: Array<PublishedRange>
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// A registry range is the only kind this guard can ask about. `workspace:*`, `catalog:`, `file:`,
|
|
34
|
+
// `link:` and git URLs resolve outside the registry entirely, so probing them would report a
|
|
35
|
+
// violation for a dependency that installs fine — and this runs in consumer repos too, where those
|
|
36
|
+
// protocols are ordinary. semver decides: anything it cannot read as a range is not a registry range.
|
|
37
|
+
function is_registry_range(range: string): boolean {
|
|
38
|
+
return semver.validRange(range) !== null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Only `dependencies` are installed by a consumer, so only they can break a consumer's install.
|
|
42
|
+
// devDependencies never reach one, and peer ranges are satisfied from the consumer's own tree.
|
|
43
|
+
function read_published_ranges(package_json_content: string): Array<PublishedRange> {
|
|
44
|
+
const parsed = package_with_deps_schema.parse(JSON.parse(package_json_content))
|
|
45
|
+
|
|
46
|
+
return Object.entries(parsed.dependencies ?? {}).map(([name, range]) => ({ name, range }))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function partition_registry_ranges(ranges: ReadonlyArray<PublishedRange>): RangePartition {
|
|
50
|
+
const partition: RangePartition = { checked: [], skipped: [] }
|
|
51
|
+
|
|
52
|
+
for (const entry of ranges) {
|
|
53
|
+
if (is_registry_range(entry.range)) partition.checked.push(entry)
|
|
54
|
+
else partition.skipped.push(entry)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return partition
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// A satisfied range is proven by an actual version on stdout, not merely by output existing:
|
|
61
|
+
// safe-chain appends its own "some package versions were suppressed" notice to stdout, so a query
|
|
62
|
+
// that answered nothing still comes back non-empty. Requiring a token semver can parse ignores that
|
|
63
|
+
// banner without having to match its text, which would rot the moment its wording changes.
|
|
64
|
+
//
|
|
65
|
+
// Fails closed otherwise: a probe that could not answer (network error, auth failure) counts as
|
|
66
|
+
// unsatisfiable rather than being waved through. This runs as a release gate, where a false stop
|
|
67
|
+
// costs one re-run and a false pass publishes a package nobody can install.
|
|
68
|
+
function is_satisfiable(result: ProbeResult): boolean {
|
|
69
|
+
if (result.exit_code !== 0) return false
|
|
70
|
+
|
|
71
|
+
return result.stdout.split(/\s+/u).some((token) => semver.valid(token) !== null)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function find_unsatisfiable(
|
|
75
|
+
ranges: ReadonlyArray<PublishedRange>,
|
|
76
|
+
probe: RangeProbe,
|
|
77
|
+
): Array<PublishedRange> {
|
|
78
|
+
return ranges.filter((entry) => !is_satisfiable(probe(entry.name, entry.range)))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function format_violation(violation: PublishedRange): string {
|
|
82
|
+
return ` ${violation.name}@${violation.range} — no visible version satisfies this range`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The remedy is spelled out because the failure reads as "this version does not exist" while the
|
|
86
|
+
// version does exist: without the explanation the obvious next step is to raise the floor further.
|
|
87
|
+
function format_failure(violations: ReadonlyArray<PublishedRange>): string {
|
|
88
|
+
return [
|
|
89
|
+
`\n✖ ${String(violations.length)} published dependency range(s) cannot be resolved:`,
|
|
90
|
+
...violations.map((violation) => format_violation(violation)),
|
|
91
|
+
'',
|
|
92
|
+
' A consumer re-resolving its lockfile installs these ranges and hits',
|
|
93
|
+
' ERR_PNPM_NO_MATCHING_VERSION. Lower each floor to a release that is already outside',
|
|
94
|
+
' the supply-chain minimum-age window — the caret still admits the newer version once',
|
|
95
|
+
' it ages in, so nothing is given up.',
|
|
96
|
+
].join('\n')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function format_success(count: number): string {
|
|
100
|
+
return `\n✔ ${String(count)} published dependency range(s) resolve against the registry.`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Printed rather than dropped in silence: a guard that quietly narrows its own coverage reports
|
|
104
|
+
// success for exactly the dependencies it never looked at.
|
|
105
|
+
function format_skipped(skipped: ReadonlyArray<PublishedRange>): string {
|
|
106
|
+
const list = skipped.map((entry) => `${entry.name}@${entry.range}`).join(', ')
|
|
107
|
+
|
|
108
|
+
return `\n⏭ Not checked — resolved outside the registry: ${list}`
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const publishable_range = {
|
|
112
|
+
read_published_ranges,
|
|
113
|
+
partition_registry_ranges,
|
|
114
|
+
is_registry_range,
|
|
115
|
+
is_satisfiable,
|
|
116
|
+
find_unsatisfiable,
|
|
117
|
+
format_failure,
|
|
118
|
+
format_skipped,
|
|
119
|
+
format_success,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { publishable_range }
|
|
123
|
+
export type { ProbeResult, PublishedRange, RangeProbe }
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import semver from 'semver'
|
|
4
|
+
import { z } from 'zod'
|
|
5
|
+
|
|
6
|
+
// The minimum-release-age quarantine (kit#768), applied natively instead of inherited from
|
|
7
|
+
// safe-chain's interception. safe-chain filters the registry only when the process tree was
|
|
8
|
+
// started through one of its six wrapped shell commands, so `josh latest` and
|
|
9
|
+
// `pnpm josh latest` used to resolve different "newest release" answers. These functions
|
|
10
|
+
// make the resolution deterministic: the policy comes from the repo-managed `.npmrc`, the
|
|
11
|
+
// publish timestamps from the registry, and the selection is a pure computation over both.
|
|
12
|
+
|
|
13
|
+
const MINIMUM_RELEASE_AGE_RE = /^minimum-release-age\s*=\s*(\d+)\s*$/mu
|
|
14
|
+
const NO_QUARANTINE_MINUTES = 0
|
|
15
|
+
const NPMRC_PATH = '.npmrc'
|
|
16
|
+
|
|
17
|
+
// A version → ISO publish date map, the shape both the registry and the GitHub Packages API are
|
|
18
|
+
// reduced to before the aged-version selection runs.
|
|
19
|
+
const release_times_schema = z.record(z.string(), z.string())
|
|
20
|
+
const MS_PER_MINUTE = 60_000
|
|
21
|
+
|
|
22
|
+
// The quarantine window in minutes from `.npmrc`; a missing or malformed entry means no
|
|
23
|
+
// quarantine, matching pnpm's own default for the setting.
|
|
24
|
+
function parse_minimum_release_age(npmrc_content: string): number {
|
|
25
|
+
const raw = MINIMUM_RELEASE_AGE_RE.exec(npmrc_content)?.[1]
|
|
26
|
+
|
|
27
|
+
return raw === undefined ? NO_QUARANTINE_MINUTES : Number(raw)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Stable releases only, on the requested major, published at or before the cutoff. The
|
|
31
|
+
// registry's `time` object also carries `created` / `modified` keys and prereleases; both
|
|
32
|
+
// fall out via the semver checks.
|
|
33
|
+
// An undefined major matches every line; a defined one pins the search to that major.
|
|
34
|
+
function is_on_major(version: string, major: string | undefined): boolean {
|
|
35
|
+
return major === undefined || String(semver.major(version)) === major
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function is_eligible(
|
|
39
|
+
version: string,
|
|
40
|
+
published_at: string,
|
|
41
|
+
major: string | undefined,
|
|
42
|
+
cutoff_ms: number,
|
|
43
|
+
): boolean {
|
|
44
|
+
if (
|
|
45
|
+
semver.valid(version) === null ||
|
|
46
|
+
semver.prerelease(version) !== null ||
|
|
47
|
+
!is_on_major(version, major)
|
|
48
|
+
) {
|
|
49
|
+
return false
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const published_ms = Date.parse(published_at)
|
|
53
|
+
|
|
54
|
+
return Number.isFinite(published_ms) && published_ms <= cutoff_ms
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// The newest release on the major that has aged past the quarantine window, or undefined
|
|
58
|
+
// when none qualifies. Pure: identical inputs give the identical answer regardless of how
|
|
59
|
+
// the surrounding process was launched.
|
|
60
|
+
// `major` pins the search to one major line — what `josh latest` needs, since corepack validates the
|
|
61
|
+
// resolved pnpm version against `devEngines`. Pass `undefined` to search every major, which is what
|
|
62
|
+
// an "is this installable at all" question wants: `pnpm add pkg@latest` resolves to the newest
|
|
63
|
+
// permitted release regardless of major (joshuafolkken/kit#808).
|
|
64
|
+
function select_aged_version(
|
|
65
|
+
times: Record<string, string>,
|
|
66
|
+
major: string | undefined,
|
|
67
|
+
minimum_age_minutes: number,
|
|
68
|
+
now_ms: number,
|
|
69
|
+
): string | undefined {
|
|
70
|
+
const cutoff_ms = now_ms - minimum_age_minutes * MS_PER_MINUTE
|
|
71
|
+
// cspell:ignore rcompare -- semver's reverse-compare API, newest first
|
|
72
|
+
const eligible = Object.entries(times)
|
|
73
|
+
.filter(([version, published_at]) => is_eligible(version, published_at, major, cutoff_ms))
|
|
74
|
+
.map(([version]) => version)
|
|
75
|
+
.toSorted(semver.rcompare)
|
|
76
|
+
|
|
77
|
+
return eligible[0]
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// The window declared in one `.npmrc`, or nothing when the file is absent, unreadable, or does not
|
|
81
|
+
// declare the setting. Distinguishing "not declared" from "declared as 0" is what lets an explicit
|
|
82
|
+
// `minimum-release-age=0` opt-out stop the walk instead of falling through to an ancestor's policy.
|
|
83
|
+
function read_declared_minimum_release_age(npmrc_path: string): number | undefined {
|
|
84
|
+
try {
|
|
85
|
+
const raw = MINIMUM_RELEASE_AGE_RE.exec(readFileSync(npmrc_path, 'utf8'))?.[1]
|
|
86
|
+
|
|
87
|
+
return raw === undefined ? undefined : Number(raw)
|
|
88
|
+
} catch {
|
|
89
|
+
return undefined
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// The quarantine window declared by one specific `.npmrc`, defaulting to the project's own. An
|
|
94
|
+
// absent, unreadable, or undeclared setting means no quarantine — the policy is advisory, and a
|
|
95
|
+
// project without one is not held back.
|
|
96
|
+
//
|
|
97
|
+
// Deliberately not the upward walk below: `josh latest` resolves this against the working directory
|
|
98
|
+
// it also writes `corepack use` into, and honouring a user-level policy there could freeze pnpm
|
|
99
|
+
// bumps in a project that declares none (joshuafolkken/kit#808).
|
|
100
|
+
function read_minimum_release_age(npmrc_path: string = NPMRC_PATH): number {
|
|
101
|
+
return read_declared_minimum_release_age(npmrc_path) ?? NO_QUARANTINE_MINUTES
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// The window declared by the nearest `.npmrc` at or above `start`, or nothing.
|
|
105
|
+
//
|
|
106
|
+
// Two reasons this walks rather than reading one path. `josh version` and `josh latest` both run
|
|
107
|
+
// from anywhere inside a project — and from outside one — so resolving against the working directory
|
|
108
|
+
// alone would silently read "no quarantine" in every subdirectory. And pnpm merges config per key
|
|
109
|
+
// across project, workspace and user levels, so a project `.npmrc` that only sets a registry must
|
|
110
|
+
// not mask a `~/.npmrc` carrying the policy (joshuafolkken/kit#808).
|
|
111
|
+
//
|
|
112
|
+
// `boundary` stops the walk at a known root. Production passes none — a user-level `~/.npmrc` is a
|
|
113
|
+
// legitimate source — while tests bound the search so it cannot depend on the machine's real home.
|
|
114
|
+
//
|
|
115
|
+
// Simplification: the walk visits every ancestor, whereas pnpm consults only the project, the
|
|
116
|
+
// workspace root, `~/.npmrc` and its global config. A stray `.npmrc` in an intermediate directory
|
|
117
|
+
// would therefore be honoured here and not by pnpm. The consequence is one informational `Held:`
|
|
118
|
+
// line — the value never suppresses a command — so the faithful four-level model is not worth its
|
|
119
|
+
// complexity here.
|
|
120
|
+
function find_declared_minimum_release_age(
|
|
121
|
+
start: string,
|
|
122
|
+
boundary: string | undefined,
|
|
123
|
+
): number | undefined {
|
|
124
|
+
const declared = read_declared_minimum_release_age(path.join(start, NPMRC_PATH))
|
|
125
|
+
if (declared !== undefined) return declared
|
|
126
|
+
if (start === boundary) return undefined
|
|
127
|
+
const parent = path.dirname(start)
|
|
128
|
+
|
|
129
|
+
return parent === start ? undefined : find_declared_minimum_release_age(parent, boundary)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The quarantine window resolved by walking up from a starting directory. An absent or undeclared
|
|
133
|
+
// policy means no quarantine — it is advisory, and a project without one is not held back.
|
|
134
|
+
function read_nearest_minimum_release_age(start: string, boundary?: string): number {
|
|
135
|
+
return find_declared_minimum_release_age(path.resolve(start), boundary) ?? NO_QUARANTINE_MINUTES
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const release_age = {
|
|
139
|
+
release_times_schema,
|
|
140
|
+
parse_minimum_release_age,
|
|
141
|
+
read_minimum_release_age,
|
|
142
|
+
read_nearest_minimum_release_age,
|
|
143
|
+
select_aged_version,
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export { release_age }
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import semver from 'semver'
|
|
2
|
+
import { release_age } from './release-age'
|
|
3
|
+
|
|
4
|
+
// A release-age hold: the local minimum-release-age policy withholds the newest release from
|
|
5
|
+
// *unpinned* resolution, so anything resolved without an explicit version stops one or more releases
|
|
6
|
+
// short of `latest`. Reporting that as a bare `⚠ → <latest>` is indistinguishable from an install the
|
|
7
|
+
// user forgot to upgrade — and it recurs after every successful upgrade, because the newest release
|
|
8
|
+
// is by definition the youngest (joshuafolkken/kit#808).
|
|
9
|
+
//
|
|
10
|
+
// **The window binds unpinned resolution only.** Measured on pnpm 11.22.0 with
|
|
11
|
+
// `minimum-release-age=1440` and a release published 3.5 h earlier:
|
|
12
|
+
//
|
|
13
|
+
// pnpm add pkg@1.80.0 -> 1.80.0 (pnpm records a `minimumReleaseAgeExclude` entry)
|
|
14
|
+
// pnpm add pkg -> 1.78.0 (the newest release past the window)
|
|
15
|
+
//
|
|
16
|
+
// So a pinned `Run:` hint always works and is never suppressed. What the window actually holds back
|
|
17
|
+
// is peer resolution — the mechanism behind an upstream's effective install (joshuafolkken/kit#698),
|
|
18
|
+
// which is why this explanation is attached there and nowhere else.
|
|
19
|
+
|
|
20
|
+
const MINUTES_PER_HOUR = 60
|
|
21
|
+
const MS_PER_MINUTE = 60_000
|
|
22
|
+
const HOLD_LABEL = 'Held:'
|
|
23
|
+
|
|
24
|
+
// Whether `latest` is itself inside the window — the precondition for a hold existing at all. Without
|
|
25
|
+
// this check the note fires whenever `select_aged_version` returns something other than `latest` for
|
|
26
|
+
// *any* reason: a prerelease `latest` (filtered as ineligible though published weeks ago) would be
|
|
27
|
+
// declared "inside the 24 h window" forever, and a `latest` that has aged out would produce the
|
|
28
|
+
// degenerate "an unpinned resolve lands on <latest>".
|
|
29
|
+
function is_latest_withheld(
|
|
30
|
+
times: Record<string, string>,
|
|
31
|
+
latest: string,
|
|
32
|
+
minimum_age_minutes: number,
|
|
33
|
+
now_ms: number,
|
|
34
|
+
): boolean {
|
|
35
|
+
const published_at = times[latest]
|
|
36
|
+
if (published_at === undefined) return false
|
|
37
|
+
const published_ms = Date.parse(published_at)
|
|
38
|
+
if (!Number.isFinite(published_ms)) return false
|
|
39
|
+
|
|
40
|
+
return published_ms > now_ms - minimum_age_minutes * MS_PER_MINUTE
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// The newest release the quarantine window permits, or nothing when there is no hold to explain:
|
|
44
|
+
// unavailable timestamps, a `latest` that has already aged out, or nothing aged out yet.
|
|
45
|
+
//
|
|
46
|
+
// Not scoped to `latest`'s major: a freshly published major is exactly when the previous line is the
|
|
47
|
+
// only thing an unpinned resolve can reach.
|
|
48
|
+
function resolve_installable(
|
|
49
|
+
times: Record<string, string> | undefined,
|
|
50
|
+
latest: string,
|
|
51
|
+
minimum_age_minutes: number,
|
|
52
|
+
now_ms: number,
|
|
53
|
+
): string | undefined {
|
|
54
|
+
if (times === undefined) return undefined
|
|
55
|
+
if (!is_latest_withheld(times, latest, minimum_age_minutes, now_ms)) return undefined
|
|
56
|
+
const installable = release_age.select_aged_version(times, undefined, minimum_age_minutes, now_ms)
|
|
57
|
+
|
|
58
|
+
return installable === latest ? undefined : installable
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Whether a target is behind `latest` only because the quarantine withheld it. The install must be
|
|
62
|
+
// behind `latest` (otherwise there is nothing to explain) and at least at the newest installable
|
|
63
|
+
// release (otherwise it is genuinely stale and the existing upgrade hint is the right answer).
|
|
64
|
+
//
|
|
65
|
+
// `gte`, not equality: an install can sit *ahead* of the newest installable release and still be
|
|
66
|
+
// behind `latest` — a version installed before the policy tightened, or one published between the
|
|
67
|
+
// page kit reads and `latest`. Treating those as stale would print a command the same policy
|
|
68
|
+
// refuses.
|
|
69
|
+
function is_at_or_above(version: string, installable: string): boolean {
|
|
70
|
+
// Unparseable versions cannot be ordered, so the comparison falls back to equality rather than
|
|
71
|
+
// guessing at a prerelease or a non-semver tag.
|
|
72
|
+
if (semver.valid(version) === null || semver.valid(installable) === null) {
|
|
73
|
+
return version === installable
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return semver.gte(version, installable)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function is_release_age_hold(
|
|
80
|
+
version: string | undefined,
|
|
81
|
+
latest: string,
|
|
82
|
+
installable: string | undefined,
|
|
83
|
+
): boolean {
|
|
84
|
+
if (version === undefined || installable === undefined || version === latest) return false
|
|
85
|
+
|
|
86
|
+
return is_at_or_above(version, installable)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Render the window in whole hours when it divides evenly, otherwise in minutes. The policy is
|
|
90
|
+
// written in minutes but read by humans in hours (1440 → 24 h), and printing "1440 minutes" buries
|
|
91
|
+
// the one number the reader needs to judge how long the hold lasts.
|
|
92
|
+
function format_window(minimum_age_minutes: number): string {
|
|
93
|
+
if (minimum_age_minutes % MINUTES_PER_HOUR !== 0) return `${String(minimum_age_minutes)} min`
|
|
94
|
+
|
|
95
|
+
return `${String(minimum_age_minutes / MINUTES_PER_HOUR)} h`
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// The explanation that accompanies a staleness marker no unpinned resolve can clear. Names the
|
|
99
|
+
// window so the reader can see the gap is a policy delay rather than a failed upgrade.
|
|
100
|
+
//
|
|
101
|
+
// The "lands on" clause is dropped when the install is already ahead of `installable`: naming a
|
|
102
|
+
// lower version beside a `⚠ → <latest>` marker reads as a downgrade instruction, when the point is
|
|
103
|
+
// simply that `latest` is not yet reachable.
|
|
104
|
+
function format_release_hold_note(
|
|
105
|
+
version: string,
|
|
106
|
+
latest: string,
|
|
107
|
+
installable: string,
|
|
108
|
+
minimum_age_minutes: number,
|
|
109
|
+
): string {
|
|
110
|
+
const window = format_window(minimum_age_minutes)
|
|
111
|
+
const head = `${HOLD_LABEL} ${latest} is inside the ${window} minimum-release-age window`
|
|
112
|
+
if (version !== installable) return `${head}; an unpinned resolve cannot reach it yet`
|
|
113
|
+
|
|
114
|
+
return `${head}; an unpinned resolve lands on ${installable}`
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// The note lines for one target, or nothing when the target is not on hold. Returned as an array so
|
|
118
|
+
// callers can splice it into a line list without a conditional at every call site.
|
|
119
|
+
function build_release_hold_notes(
|
|
120
|
+
version: string | undefined,
|
|
121
|
+
latest: string,
|
|
122
|
+
installable: string | undefined,
|
|
123
|
+
minimum_age_minutes: number,
|
|
124
|
+
): Array<string> {
|
|
125
|
+
if (version === undefined || installable === undefined) return []
|
|
126
|
+
if (!is_release_age_hold(version, latest, installable)) return []
|
|
127
|
+
|
|
128
|
+
return [format_release_hold_note(version, latest, installable, minimum_age_minutes)]
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const release_hold = {
|
|
132
|
+
HOLD_LABEL,
|
|
133
|
+
is_at_or_above,
|
|
134
|
+
is_latest_withheld,
|
|
135
|
+
resolve_installable,
|
|
136
|
+
is_release_age_hold,
|
|
137
|
+
format_window,
|
|
138
|
+
format_release_hold_note,
|
|
139
|
+
build_release_hold_notes,
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export { release_hold }
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { package_version_schema } from '#scripts/lib/schemas'
|
|
4
|
+
import { safe_json_parse } from './parse-json'
|
|
5
|
+
|
|
6
|
+
const PACKAGE_JSON = 'package.json'
|
|
7
|
+
// Scripts live two levels under the package root (scripts/<group>/<file>.ts), so the running
|
|
8
|
+
// binary's own package.json is reached by walking up twice from the script directory.
|
|
9
|
+
const SCRIPT_DEPTH_FROM_ROOT = ['..', '..'] as const
|
|
10
|
+
|
|
11
|
+
// The running binary is the single source of truth: resolve the package.json of the install that
|
|
12
|
+
// is actually executing (via import.meta.url's directory), mirroring how `init`/`sync` key off the
|
|
13
|
+
// package directory rather than `pnpm ls -g` or `<cwd>/node_modules`.
|
|
14
|
+
function resolve_self_package_path(self_directory: string): string {
|
|
15
|
+
return path.join(self_directory, ...SCRIPT_DEPTH_FROM_ROOT, PACKAGE_JSON)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Absolute directory of the running binary's package root — the path reported as the source of the
|
|
19
|
+
// version that actually ran.
|
|
20
|
+
function running_package_directory(self_directory: string): string {
|
|
21
|
+
return path.resolve(self_directory, ...SCRIPT_DEPTH_FROM_ROOT)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Read the version declared in the running binary's own package.json. Undefined only when the file
|
|
25
|
+
// is missing or malformed (should not happen for a real install, but kept total for safety).
|
|
26
|
+
function read_running_version(self_directory: string): string | undefined {
|
|
27
|
+
const package_path = resolve_self_package_path(self_directory)
|
|
28
|
+
if (!existsSync(package_path)) return undefined
|
|
29
|
+
const parsed = package_version_schema.safeParse(
|
|
30
|
+
safe_json_parse(readFileSync(package_path, 'utf8')),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return parsed.success ? parsed.data.version : undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const running_binary = {
|
|
37
|
+
resolve_self_package_path,
|
|
38
|
+
running_package_directory,
|
|
39
|
+
read_running_version,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { running_binary }
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// A package-name → currently-installed-version lookup, used to decide whether an upgrade command can
|
|
2
|
+
// still change anything. `undefined` means the package is not installed at the scope being checked.
|
|
3
|
+
type InstalledVersions = ReadonlyMap<string, string | undefined>
|
|
4
|
+
|
|
5
|
+
// One `<package>@<version>` specifier found inside a shell command.
|
|
6
|
+
interface VersionPin {
|
|
7
|
+
name: string
|
|
8
|
+
version: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// One whole `<package>@<version>` shell token, e.g. `@joshuafolkken/app-kit@2.0.0` (scoped) or
|
|
12
|
+
// `tsx@4.20.0` (unscoped). Applied to one token at a time and anchored at both ends, so the match is
|
|
13
|
+
// linear — scanning the full command string would instead re-backtrack from every start position.
|
|
14
|
+
// The version must begin with a digit so a dist-tag (`pkg@latest`) never matches: a dist-tag can
|
|
15
|
+
// always resolve to something newer, so a command carrying one is never provably a no-op.
|
|
16
|
+
const VERSION_PIN_PATTERN = /^(?<name>@[\w.-]+\/[\w.-]+|[\w.-]+)@(?<version>\d[\w.+-]*)$/u
|
|
17
|
+
const WHITESPACE_PATTERN = /\s+/u
|
|
18
|
+
|
|
19
|
+
// One shell token read as a version pin, or undefined when it is not one (a flag, a sub-command, a
|
|
20
|
+
// path, or a dist-tag specifier).
|
|
21
|
+
function parse_version_pin(token: string): VersionPin | undefined {
|
|
22
|
+
const { name, version } = VERSION_PIN_PATTERN.exec(token)?.groups ?? {}
|
|
23
|
+
if (name === undefined || version === undefined) return undefined
|
|
24
|
+
|
|
25
|
+
return { name, version }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Every exact version pin the command carries, in the order they appear.
|
|
29
|
+
function extract_version_pins(command: string): Array<VersionPin> {
|
|
30
|
+
return command.split(WHITESPACE_PATTERN).flatMap((token) => parse_version_pin(token) ?? [])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// An upgrade command provably cannot change anything when it pins at least one exact version and
|
|
34
|
+
// every version it pins is already installed — running it would leave the staleness it was meant to
|
|
35
|
+
// fix untouched (see #697, where `vu` → `v` looped forever on such a command).
|
|
36
|
+
//
|
|
37
|
+
// Only commands the consumer declared as pin-only reach this check. A command that forces a fresh
|
|
38
|
+
// resolve (e.g. `pnpm remove -g <pkg> && pnpm add -g <pkg>@<latest>`) genuinely changes the resolved
|
|
39
|
+
// dependency graph even though its pin is already installed, so consumers leave
|
|
40
|
+
// `is_global_upgrade_command_pinned` unset for those and the hint is never suppressed.
|
|
41
|
+
function is_no_op_upgrade_command(command: string, installed: InstalledVersions): boolean {
|
|
42
|
+
const pins = extract_version_pins(command)
|
|
43
|
+
if (pins.length === 0) return false
|
|
44
|
+
|
|
45
|
+
return pins.every((pin) => installed.get(pin.name) === pin.version)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type { InstalledVersions }
|
|
49
|
+
export { is_no_op_upgrade_command }
|