@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,112 @@
|
|
|
1
|
+
// The difference between the issues an `in-progress` label says are running and the lanes that are
|
|
2
|
+
// actually open (joshuafolkken/kit#2235).
|
|
3
|
+
//
|
|
4
|
+
// `epic:next` counts lane occupancy from the `in-progress` label list; `lane:list` reads the work
|
|
5
|
+
// trees that are actually open. Nothing named the difference, so a session read hand-made signals —
|
|
6
|
+
// `ls` and a remote branch's existence — and reported two running issues as stranded. The two sets
|
|
7
|
+
// disagree in two directions, and the harm is asymmetric: a label with no lane silently shrinks the
|
|
8
|
+
// free-lane count, while a lane with no label lets another session claim the same issue and open a
|
|
9
|
+
// second pull request on the same branch.
|
|
10
|
+
//
|
|
11
|
+
// **The judgement is read from the two sets, never invented.** The classification is three-valued so
|
|
12
|
+
// an unreadable lane listing stays `unknown` rather than collapsing to `stopped` — reported as a dead
|
|
13
|
+
// lane, a live one would have its stale label cleared and its issue handed out again.
|
|
14
|
+
//
|
|
15
|
+
// **Nothing here writes a label.** Removing `in-progress` from a live run is exactly the mistake that
|
|
16
|
+
// opens a second pull request, so the repair is a person's — this module only names the difference.
|
|
17
|
+
|
|
18
|
+
// How a lane listing arrived: the open lanes' issue numbers, or that the listing could not be read.
|
|
19
|
+
type LaneRead = { kind: 'lanes'; issues: ReadonlyArray<number> } | { kind: 'unreadable' }
|
|
20
|
+
|
|
21
|
+
// The three liveness verdicts, named so the `lane:list` oracle vocabulary reads them from here rather
|
|
22
|
+
// than repeating the literals. `LIVE` is the silent norm; `STOPPED` and `UNKNOWN` lead the anomaly
|
|
23
|
+
// lines below so the token a reader greps for is the one this module classifies with.
|
|
24
|
+
const LIVE = 'live'
|
|
25
|
+
const STOPPED = 'stopped'
|
|
26
|
+
const UNKNOWN = 'unknown'
|
|
27
|
+
|
|
28
|
+
// Whether an `in-progress` issue's lane is open, stopped, or could not be determined. `unknown` is
|
|
29
|
+
// the answer when the lane listing itself could not be read — never `stopped`, which would report a
|
|
30
|
+
// running lane as dead.
|
|
31
|
+
type Liveness = typeof LIVE | typeof STOPPED | typeof UNKNOWN
|
|
32
|
+
|
|
33
|
+
interface LabelledIssue {
|
|
34
|
+
issue: number
|
|
35
|
+
liveness: Liveness
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface OccupancyReport {
|
|
39
|
+
// Every `in-progress` issue with its lane liveness. A `live` one is the ordinary case; a `stopped`
|
|
40
|
+
// or `unknown` one is the anomaly `describe` names.
|
|
41
|
+
labelled: ReadonlyArray<LabelledIssue>
|
|
42
|
+
// Open lanes whose issue carries no `in-progress` label — the reverse difference. Empty when the
|
|
43
|
+
// lane listing could not be read, since there is nothing to compare against.
|
|
44
|
+
lanes_without_label: ReadonlyArray<number>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function to_liveness(issue: number, lanes: LaneRead): Liveness {
|
|
48
|
+
if (lanes.kind === 'unreadable') return UNKNOWN
|
|
49
|
+
|
|
50
|
+
return lanes.issues.includes(issue) ? LIVE : STOPPED
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function to_lanes_without_label(
|
|
54
|
+
in_progress: ReadonlyArray<number>,
|
|
55
|
+
lanes: LaneRead,
|
|
56
|
+
): Array<number> {
|
|
57
|
+
if (lanes.kind === 'unreadable') return []
|
|
58
|
+
|
|
59
|
+
return lanes.issues.filter((issue) => !in_progress.includes(issue))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The two-directional difference between the `in-progress` issues and the open lanes. Pure: it reads
|
|
63
|
+
// the two sets and writes nothing, which is what keeps the label untouched.
|
|
64
|
+
function classify(in_progress: ReadonlyArray<number>, lanes: LaneRead): OccupancyReport {
|
|
65
|
+
return {
|
|
66
|
+
labelled: in_progress.map((issue) => ({ issue, liveness: to_liveness(issue, lanes) })),
|
|
67
|
+
lanes_without_label: to_lanes_without_label(in_progress, lanes),
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function stopped_line(issue: number): string {
|
|
72
|
+
return `⚠ ${STOPPED} #${String(issue)} — carries \`in-progress\` but no lane is open — a stale label. Remove it if the run is done (labels are a person's to change), or reopen the lane.`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function unknown_line(issue: number): string {
|
|
76
|
+
return `⚠ ${UNKNOWN} #${String(issue)} — carries \`in-progress\` but the lane listing could not be read, so whether its lane is live is unknown — do not treat it as stopped.`
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function without_label_line(issue: number): string {
|
|
80
|
+
return `⚠ a lane is open for #${String(issue)} but it carries no \`in-progress\` label — another session could claim the same issue. Apply the label or close the lane (a person's, never this command's).`
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function labelled_lines(labelled: ReadonlyArray<LabelledIssue>): Array<string> {
|
|
84
|
+
return labelled.flatMap((entry) => {
|
|
85
|
+
if (entry.liveness === 'stopped') return [stopped_line(entry.issue)]
|
|
86
|
+
if (entry.liveness === 'unknown') return [unknown_line(entry.issue)]
|
|
87
|
+
|
|
88
|
+
return []
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The anomalies as lines for standard error, or `undefined` when the two sets agree — the same shape
|
|
93
|
+
// `lane:list` follows for every explanation, so its standard output stays a token per line.
|
|
94
|
+
function describe(report: OccupancyReport): string | undefined {
|
|
95
|
+
const lines = [
|
|
96
|
+
...labelled_lines(report.labelled),
|
|
97
|
+
...report.lanes_without_label.map((issue) => without_label_line(issue)),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
return lines.length === 0 ? undefined : lines.join('\n')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const lane_occupancy = {
|
|
104
|
+
LIVE,
|
|
105
|
+
STOPPED,
|
|
106
|
+
UNKNOWN,
|
|
107
|
+
classify,
|
|
108
|
+
describe,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export { lane_occupancy }
|
|
112
|
+
export type { LabelledIssue, LaneRead, Liveness, OccupancyReport }
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { ENV_FILE_NAME } from '#ports'
|
|
4
|
+
import { git_worktree } from '#scripts/git/git-worktree'
|
|
5
|
+
import { lane_cache } from './lane-cache'
|
|
6
|
+
import { lane_environment } from './lane-environment'
|
|
7
|
+
import { lane_install, type InstallResult } from './lane-install'
|
|
8
|
+
import { lane_paths } from './lane-paths'
|
|
9
|
+
import { lane_registry, type LaneInfo } from './lane-registry'
|
|
10
|
+
import { lane_seed_policy } from './lane-seed'
|
|
11
|
+
import { lane_start_point } from './lane-start-point'
|
|
12
|
+
|
|
13
|
+
// Opening a lane: one linked work tree, one branch, one port seed, and the dependencies to run in it
|
|
14
|
+
// (joshuafolkken/kit#1490, joshuafolkken/kit#1554).
|
|
15
|
+
//
|
|
16
|
+
// **The reading side of a linked work tree already worked; only the creating side was missing.**
|
|
17
|
+
// `git_directories()` resolves the tree's own git directory, `run-hold.ts` keys its record on it and
|
|
18
|
+
// `repo-discovery.ts` follows a `.git` file pointer — so a lane opened here is guarded, discovered
|
|
19
|
+
// and checked by the layers that are already there. Nothing below re-implements any of that.
|
|
20
|
+
|
|
21
|
+
interface LanePlan {
|
|
22
|
+
lane: LaneInfo
|
|
23
|
+
environment_content: string
|
|
24
|
+
// The seat lock held across this lane's creation, released once its `.env` is on disk.
|
|
25
|
+
seat_lock: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface SeatReservation {
|
|
29
|
+
seat: number
|
|
30
|
+
lock: string
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type OpenOutcome =
|
|
34
|
+
{ kind: 'already-open'; lane: LaneInfo } | { kind: 'full' } | { kind: 'opened'; lane: LaneInfo }
|
|
35
|
+
|
|
36
|
+
const FULL_OUTCOME: OpenOutcome = { kind: 'full' }
|
|
37
|
+
|
|
38
|
+
// The seat a lane will take is claimed by exclusively creating its lock directory here, under the
|
|
39
|
+
// lanes root and clear of the lanes themselves (which are numbered, never dot-prefixed). The claim
|
|
40
|
+
// is what closes the gap between reading the free seats and writing the lane's `.env`: two
|
|
41
|
+
// `lane:open` runs that both saw seat 1 free cannot both create the same lock, so the loser steps to
|
|
42
|
+
// the next free seat (joshuafolkken/kit#1494). The lock is released once the lane's `.env` is on
|
|
43
|
+
// disk and the seat is discoverable — or on any failure — so only a hard crash mid-open can strand
|
|
44
|
+
// one, which removing the lanes-root `.seat-locks` directory clears.
|
|
45
|
+
const SEAT_LOCK_DIR = '.seat-locks'
|
|
46
|
+
const SEAT_LOCK_PREFIX = 'seat-'
|
|
47
|
+
|
|
48
|
+
// A root with no `.env` is the normal state of a fresh clone and of CI, and it means seed 0 — the
|
|
49
|
+
// same reading `ports/index.js` gives a missing file. The lane still gets a file, because the seed
|
|
50
|
+
// it is being given is the whole point.
|
|
51
|
+
function read_root_environment(repository_root: string): string {
|
|
52
|
+
const file = path.join(repository_root, ENV_FILE_NAME)
|
|
53
|
+
|
|
54
|
+
return existsSync(file) ? readFileSync(file, 'utf8') : ''
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function build_lane(
|
|
58
|
+
root: string,
|
|
59
|
+
issue: string,
|
|
60
|
+
seat: number,
|
|
61
|
+
environment_content: string,
|
|
62
|
+
): LaneInfo {
|
|
63
|
+
// The ports are resolved from the exact `.env` the lane will carry, through the one formula in
|
|
64
|
+
// `ports/index.js`, so the opened-lane confirmation prints the numbers the lane will actually run.
|
|
65
|
+
const port_pair = lane_environment.read_lane_ports(environment_content)
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
issue,
|
|
69
|
+
branch: lane_paths.lane_branch(issue),
|
|
70
|
+
directory: lane_paths.lane_directory(root, issue),
|
|
71
|
+
seat,
|
|
72
|
+
development_port: port_pair.development,
|
|
73
|
+
preview_port: port_pair.preview,
|
|
74
|
+
output: undefined,
|
|
75
|
+
is_stranded: false,
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function seat_lock_path(root: string, seat: number): string {
|
|
80
|
+
return path.join(root, SEAT_LOCK_DIR, `${SEAT_LOCK_PREFIX}${String(seat)}`)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Release the seat lock — idempotent (`force`), so calling it after the `.env` write and again in the
|
|
84
|
+
// `finally` that covers an earlier failure both land safely.
|
|
85
|
+
function release_seat_lock(lock: string): void {
|
|
86
|
+
rmSync(lock, { recursive: true, force: true })
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// How many opens are in flight right now, read straight off disk: each holds one seat lock from its
|
|
90
|
+
// seat claim until its `.env` is written, so the count of lock entries is the count of lanes still
|
|
91
|
+
// being created. A missing directory is none held — the normal state when no open is running.
|
|
92
|
+
function open_in_flight_count(root: string): number {
|
|
93
|
+
try {
|
|
94
|
+
return readdirSync(path.join(root, SEAT_LOCK_DIR)).filter((entry) =>
|
|
95
|
+
entry.startsWith(SEAT_LOCK_PREFIX),
|
|
96
|
+
).length
|
|
97
|
+
} catch {
|
|
98
|
+
return 0
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Claim `lock` by creating it exclusively — `false` when another open already holds it. The parent
|
|
103
|
+
// is ensured first (idempotent); the lock itself is a non-recursive `mkdirSync`, so an existing one
|
|
104
|
+
// throws rather than passing silently, which is what makes the claim atomic.
|
|
105
|
+
function claim_seat(lock: string): boolean {
|
|
106
|
+
mkdirSync(path.dirname(lock), { recursive: true })
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
mkdirSync(lock)
|
|
110
|
+
|
|
111
|
+
return true
|
|
112
|
+
} catch {
|
|
113
|
+
return false
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function reserve_seat(root: string, free: ReadonlyArray<number>): SeatReservation | undefined {
|
|
118
|
+
for (const seat of free) {
|
|
119
|
+
const lock = seat_lock_path(root, seat)
|
|
120
|
+
if (claim_seat(lock)) return { seat, lock }
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return undefined
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Refuse to allocate while a live lane's seat cannot be read — but a lane still being opened is not
|
|
128
|
+
* one of those.
|
|
129
|
+
*
|
|
130
|
+
* Skipping a broken lane would read its seat as free and hand its ports to the new one, which is a
|
|
131
|
+
* collision nothing reports until an E2E run fails somewhere else. Failing here names the lane and
|
|
132
|
+
* what to do about it.
|
|
133
|
+
*
|
|
134
|
+
* **A lane git already lists but whose `.env` is not yet on disk is mid-open, not broken**
|
|
135
|
+
* (joshuafolkken/kit#2147). It holds a seat lock from its seat claim until its `.env` write — the
|
|
136
|
+
* whole window in which it reads as unreadable — and that lock keeps its seat off this open's table
|
|
137
|
+
* (`reserve_seat` cannot claim a locked seat), so tolerating it here cannot cause a collision. The
|
|
138
|
+
* count of held locks is the count of opens in flight, so only the unreadable lanes beyond it are
|
|
139
|
+
* genuinely broken and stop the allocation. A lock stranded by a hard crash masks a broken lane the
|
|
140
|
+
* same way; removing the `.seat-locks` directory clears it.
|
|
141
|
+
*/
|
|
142
|
+
function guard_unreadable(root: string, lanes: ReadonlyArray<LaneInfo>): void {
|
|
143
|
+
const unreadable = lane_registry.unreadable_lanes(lanes)
|
|
144
|
+
|
|
145
|
+
if (unreadable.length <= open_in_flight_count(root)) return
|
|
146
|
+
|
|
147
|
+
const named = unreadable.map((lane) => `#${lane.issue} (${lane.directory})`).join(', ')
|
|
148
|
+
|
|
149
|
+
throw new Error(
|
|
150
|
+
`Cannot read the port seed of these open lanes, so a free seat cannot be chosen: ${named}. Restore each lane's ${ENV_FILE_NAME}, or close the lane with \`pnpm josh lane:close <issue-number>\`.`,
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Fail the open when the install failed, rather than handing back a lane nothing runs in.
|
|
156
|
+
*
|
|
157
|
+
* Reported as a success, the caller captures the directory and types the first `pnpm josh …` in it —
|
|
158
|
+
* which fails with `tsx: command not found`, the exact failure the install exists to remove, now
|
|
159
|
+
* with a success line printed above it (joshuafolkken/kit#1554). The work tree is left where it is
|
|
160
|
+
* because both ways out need it there: the install can be run again against it, or `lane:close` can
|
|
161
|
+
* take it away. The child's own output is carried along, since it is the only thing that says which
|
|
162
|
+
* of the two applies.
|
|
163
|
+
*/
|
|
164
|
+
function guard_install(lane: LaneInfo, result: InstallResult): void {
|
|
165
|
+
if (result.is_installed) return
|
|
166
|
+
|
|
167
|
+
throw new Error(
|
|
168
|
+
`Opened a lane for #${lane.issue} at ${lane.directory}, but installing its dependencies failed, so no \`pnpm josh …\` will run there. Finish it with \`pnpm --dir ${lane.directory} install --frozen-lockfile\`, or take it away with \`pnpm josh lane:close ${lane.issue}\`.\n${result.output}`,
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function build_plan(
|
|
173
|
+
repository_root: string,
|
|
174
|
+
root: string,
|
|
175
|
+
issue: string,
|
|
176
|
+
lanes: ReadonlyArray<LaneInfo>,
|
|
177
|
+
): LanePlan | undefined {
|
|
178
|
+
const root_content = read_root_environment(repository_root)
|
|
179
|
+
const free = lane_seed_policy.free_seats(lane_registry.used_seats(lanes))
|
|
180
|
+
const reservation = reserve_seat(root, free)
|
|
181
|
+
|
|
182
|
+
if (reservation === undefined) return undefined
|
|
183
|
+
|
|
184
|
+
const environment_content = lane_environment.lane_file_content(root_content, reservation.seat)
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
lane: build_lane(root, issue, reservation.seat, environment_content),
|
|
188
|
+
environment_content,
|
|
189
|
+
seat_lock: reservation.lock,
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// The `.env` is written straight after the work tree exists, because the seed is the reason the
|
|
194
|
+
// lane is being opened. Nothing else is recorded anywhere: that file *is* the record.
|
|
195
|
+
//
|
|
196
|
+
// The start point comes from `lane_start_point` rather than from the default branch's bare name:
|
|
197
|
+
// that name resolves to a local ref nothing advances, and the lane would start without the work
|
|
198
|
+
// merged just before it (joshuafolkken/kit#1535). **It answers `undefined` when a branch of this
|
|
199
|
+
// lane's name already exists**, which puts the work tree on that branch instead of creating one —
|
|
200
|
+
// the only route back to a child that was parked after pushing (joshuafolkken/kit#1627).
|
|
201
|
+
//
|
|
202
|
+
// **The install is the last step rather than a caller's, because a lane without it is unusable**
|
|
203
|
+
// (joshuafolkken/kit#1554). Leaving it to whoever opened the lane made it a step nothing enforced,
|
|
204
|
+
// and every lane opened without it failed on its first `pnpm josh …`. It runs after the `.env`
|
|
205
|
+
// rather than before, so a lane that fails here still carries the seat it was allocated and the
|
|
206
|
+
// failure is recoverable by re-running the install alone.
|
|
207
|
+
//
|
|
208
|
+
// **The gate's verification caches are seeded from the main checkout before the install**
|
|
209
|
+
// (joshuafolkken/kit#1849), so the lane's first `josh gate` is warm rather than cold. The pre-built
|
|
210
|
+
// hook bundles are seeded the same way (joshuafolkken/kit#2160): `dist/hooks/` is git-ignored, so a
|
|
211
|
+
// lane's work tree never carries it and every Claude Code hook drops to the slow `pnpm josh …`
|
|
212
|
+
// fallback without this copy. Both are best-effort and run after the `.env` write for the same reason
|
|
213
|
+
// the install does: a lane whose warming found nothing still carries its seat and is perfectly
|
|
214
|
+
// usable, cold first gate and fallback hooks and all.
|
|
215
|
+
async function materialize(plan: LanePlan, source_root: string): Promise<void> {
|
|
216
|
+
// The seat lock is released the moment the `.env` is on disk — from then the lane is readable and
|
|
217
|
+
// its seat discoverable, so nothing more holds the seat. It must **not** ride the multi-minute
|
|
218
|
+
// install: a lock outlasting the unreadable window would inflate `open_in_flight_count` and mask a
|
|
219
|
+
// genuinely broken lane (joshuafolkken/kit#2147). The `finally` covers a failure before the `.env`
|
|
220
|
+
// is written, where nothing was created that should hold it.
|
|
221
|
+
try {
|
|
222
|
+
mkdirSync(path.dirname(plan.lane.directory), { recursive: true })
|
|
223
|
+
|
|
224
|
+
const start_point = await lane_start_point.resolve_for_branch(plan.lane.branch)
|
|
225
|
+
|
|
226
|
+
await git_worktree.worktree_add(plan.lane.directory, plan.lane.branch, start_point)
|
|
227
|
+
writeFileSync(path.join(plan.lane.directory, ENV_FILE_NAME), plan.environment_content)
|
|
228
|
+
release_seat_lock(plan.seat_lock)
|
|
229
|
+
lane_cache.seed_caches(source_root, plan.lane.directory)
|
|
230
|
+
lane_cache.seed_hook_bundles(source_root, plan.lane.directory)
|
|
231
|
+
guard_install(plan.lane, await lane_install.install_dependencies(plan.lane.directory))
|
|
232
|
+
} finally {
|
|
233
|
+
release_seat_lock(plan.seat_lock)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Open the lane for `issue`, or say why it was not opened.
|
|
239
|
+
*
|
|
240
|
+
* A lane that is already open is never reopened — including a stranded one, whose registration git
|
|
241
|
+
* still holds and would refuse `worktree add` on. `lane:close` and `lane:prune` are the way out of
|
|
242
|
+
* both, and the refusal says so.
|
|
243
|
+
*/
|
|
244
|
+
async function open_lane(issue: string): Promise<OpenOutcome> {
|
|
245
|
+
// The main work tree's, never this one's: run from inside a lane, the current root would put the
|
|
246
|
+
// new lane under `<lane>/.<lane>-lanes` and read the lane's own seed as the root's — a lane
|
|
247
|
+
// `list_lanes` cannot see, on ports it never recorded (joshuafolkken/kit#1497).
|
|
248
|
+
const repository_root = await lane_registry.main_repository_root()
|
|
249
|
+
const lanes = await lane_registry.list_lanes()
|
|
250
|
+
const existing = lane_registry.find_lane(lanes, issue)
|
|
251
|
+
|
|
252
|
+
if (existing !== undefined) return { kind: 'already-open', lane: existing }
|
|
253
|
+
|
|
254
|
+
const root = lane_paths.lane_root(repository_root)
|
|
255
|
+
|
|
256
|
+
guard_unreadable(root, lanes)
|
|
257
|
+
|
|
258
|
+
const plan = build_plan(repository_root, root, issue, lanes)
|
|
259
|
+
|
|
260
|
+
if (plan === undefined) return FULL_OUTCOME
|
|
261
|
+
|
|
262
|
+
await materialize(plan, repository_root)
|
|
263
|
+
|
|
264
|
+
return { kind: 'opened', lane: plan.lane }
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const lane_open = {
|
|
268
|
+
build_plan,
|
|
269
|
+
guard_unreadable,
|
|
270
|
+
open_lane,
|
|
271
|
+
read_root_environment,
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export type { OpenOutcome }
|
|
275
|
+
export { lane_open }
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { ENV_FILE_NAME } from '#ports'
|
|
4
|
+
import type { AgentProfile } from '#scripts/agent/agent-role-profile'
|
|
5
|
+
import { run_liveness } from '#scripts/run/run-liveness'
|
|
6
|
+
import { lane_environment } from './lane-environment'
|
|
7
|
+
import { lane_registry, type LaneInfo } from './lane-registry'
|
|
8
|
+
|
|
9
|
+
// Where the delegated unit running a lane's child writes, recorded in the lane and read back from
|
|
10
|
+
// anywhere (joshuafolkken/kit#1713).
|
|
11
|
+
//
|
|
12
|
+
// **This is the one fact about an in-flight lane that only the dispatching session held.** The
|
|
13
|
+
// harness names a unit's output file after that session's own id and the unit's, and neither is
|
|
14
|
+
// written anywhere on disk — so a session that did not open the lane could not poll its child, and
|
|
15
|
+
// a hand-off had to drain the pool first: no new lane opened until every in-flight one had finished.
|
|
16
|
+
// Recorded here,
|
|
17
|
+
// `unit_output=$(pnpm josh lane:output <N>) && pnpm josh run:liveness <N> --output "$unit_output"`
|
|
18
|
+
// works from a session that has never seen the child, and the drain goes away. **The `&&` is not
|
|
19
|
+
// decoration**: a lane recording nothing prints `none` and exits non-zero, and a substitution written
|
|
20
|
+
// inside the argument would discard that exit status and hand `run:liveness` a relative path.
|
|
21
|
+
//
|
|
22
|
+
// **Nothing here writes a `.env` that was not already there.** A lane whose file cannot be read is
|
|
23
|
+
// refused rather than replaced: the same file carries the lane's port seat, and a fresh one holding
|
|
24
|
+
// only this record would put the lane back on the main work tree's ports.
|
|
25
|
+
|
|
26
|
+
type Refusal =
|
|
27
|
+
{ kind: 'no-lane' } | { kind: 'invalid'; reason: string } | { kind: 'unreadable'; lane: LaneInfo }
|
|
28
|
+
|
|
29
|
+
type RecordOutcome = Refusal | { kind: 'recorded'; lane: LaneInfo; output: string }
|
|
30
|
+
|
|
31
|
+
type ReadOutcome =
|
|
32
|
+
| { kind: 'no-lane' }
|
|
33
|
+
| { kind: 'none'; lane: LaneInfo }
|
|
34
|
+
| { kind: 'read'; lane: LaneInfo; output: string }
|
|
35
|
+
|
|
36
|
+
const NO_OUTPUT = 'This lane records no output path yet.'
|
|
37
|
+
// A quote would end the quoted assignment the record is written as, and a newline would split it
|
|
38
|
+
// into two lines — either way the file would say something other than what was handed in.
|
|
39
|
+
const FORBIDDEN_CHARACTERS = /["\n\r]/u
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Why this path cannot be recorded, or `undefined` when it can.
|
|
43
|
+
*
|
|
44
|
+
* **A path `run:liveness` could not read is refused here rather than there.** That command answers
|
|
45
|
+
* `undetermined` for one — an answer meaning "could not read" — so a lane recorded with it would
|
|
46
|
+
* poll as indeterminate for ever instead of the record being reported wrong. **The test is
|
|
47
|
+
* `run_liveness.to_safe_path` itself, never a second copy of its rules**: absolute, normalized, and
|
|
48
|
+
* confined to the home and temp directories, in both spellings of each. Restating half of that here
|
|
49
|
+
* is exactly how the two would come to disagree.
|
|
50
|
+
*/
|
|
51
|
+
function invalid_reason(output: string): string | undefined {
|
|
52
|
+
if (FORBIDDEN_CHARACTERS.test(output)) return 'the path cannot hold a quote or a line break'
|
|
53
|
+
|
|
54
|
+
return run_liveness.to_safe_path(output) === undefined
|
|
55
|
+
? 'the path has to be one `run:liveness` can read: absolute, and under the home or temp directory'
|
|
56
|
+
: undefined
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Record where this lane's unit writes, leaving everything else in its `.env` untouched. */
|
|
60
|
+
async function record_output(
|
|
61
|
+
issue: string,
|
|
62
|
+
output: string,
|
|
63
|
+
profile?: AgentProfile,
|
|
64
|
+
): Promise<RecordOutcome> {
|
|
65
|
+
const reason = invalid_reason(output)
|
|
66
|
+
|
|
67
|
+
if (reason !== undefined) return { kind: 'invalid', reason }
|
|
68
|
+
|
|
69
|
+
const lane = await lane_registry.find_open_lane(issue)
|
|
70
|
+
|
|
71
|
+
if (lane === undefined) return { kind: 'no-lane' }
|
|
72
|
+
|
|
73
|
+
const content = lane_registry.read_environment(lane.directory)
|
|
74
|
+
|
|
75
|
+
if (content === undefined) return { kind: 'unreadable', lane }
|
|
76
|
+
|
|
77
|
+
writeFileSync(
|
|
78
|
+
path.join(lane.directory, ENV_FILE_NAME),
|
|
79
|
+
lane_environment.with_lane_output(content, output, profile),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return { kind: 'recorded', lane, output }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The path this lane records, read through the registry every other lane reading goes through.
|
|
87
|
+
*
|
|
88
|
+
* The session asking is never assumed to be the one that opened the lane — that is the whole point:
|
|
89
|
+
* the answer comes from the lane's own `.env`, so it is the same answer in every session.
|
|
90
|
+
*/
|
|
91
|
+
async function read_output(issue: string): Promise<ReadOutcome> {
|
|
92
|
+
const lane = await lane_registry.find_open_lane(issue)
|
|
93
|
+
|
|
94
|
+
if (lane === undefined) return { kind: 'no-lane' }
|
|
95
|
+
|
|
96
|
+
const { output } = lane
|
|
97
|
+
|
|
98
|
+
if (output === undefined) return { kind: 'none', lane }
|
|
99
|
+
|
|
100
|
+
return { kind: 'read', lane, output }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function describe_refusal(refusal: Refusal, issue: string): string {
|
|
104
|
+
if (refusal.kind === 'invalid') {
|
|
105
|
+
return `That output path cannot be recorded: ${refusal.reason}. \`pnpm josh run:liveness\` reads only an absolute path, so a record it cannot use would be worse than none.`
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (refusal.kind === 'unreadable') {
|
|
109
|
+
return `The lane for #${issue} has a ${ENV_FILE_NAME} that cannot be read at ${refusal.lane.directory}. Fix it and run this again — writing a new one would drop the lane's port seat with it.`
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return `No lane is open for #${issue}. Run \`pnpm josh lane:list\` to see what is open.`
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const lane_output = {
|
|
116
|
+
NO_OUTPUT,
|
|
117
|
+
describe_refusal,
|
|
118
|
+
invalid_reason,
|
|
119
|
+
read_output,
|
|
120
|
+
record_output,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export type { ReadOutcome, RecordOutcome, Refusal }
|
|
124
|
+
export { lane_output }
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
// Where a lane lives on disk, and what its branch is called (joshuafolkken/kit#1490).
|
|
4
|
+
//
|
|
5
|
+
// **A lane is deliberately not nested inside the repository.** A linked work tree is a second full
|
|
6
|
+
// checkout, so putting it under the main one would hand every path-walking tool in the project a
|
|
7
|
+
// duplicate of itself: the lint run, the unit suite, the spell check and `git status` would each
|
|
8
|
+
// have to be taught to skip it, and one missed ignore rule turns a six-lane machine into six
|
|
9
|
+
// copies of the tree being checked. A hidden sibling directory of the repository root is outside
|
|
10
|
+
// every one of those walks by construction, and needs no ignore entry in kit or in any consumer
|
|
11
|
+
// `josh sync` reaches.
|
|
12
|
+
|
|
13
|
+
const LANE_ROOT_KEY = 'JOSH_LANE_ROOT'
|
|
14
|
+
const LANE_DIRECTORY_SUFFIX = '-lanes'
|
|
15
|
+
// **The issue number comes first because `pnpm josh git` will not commit from a branch that starts
|
|
16
|
+
// any other way** (joshuafolkken/kit#1497). Its `has_same_issue_prefix` reads `/^\d+-/`, so the
|
|
17
|
+
// original `lane/<N>` spelling made every lane a checkout nothing could be committed from — and
|
|
18
|
+
// switching the branch inside the lane is not the way round it, because `lane_registry` identifies a
|
|
19
|
+
// lane *by* this name: the moment it changes, the work tree drops out of `lane:list`, its seat is
|
|
20
|
+
// re-issued to the next lane, and two live lanes share the dev and preview ports lanes exist to keep
|
|
21
|
+
// apart. The name is therefore fixed at both ends at once rather than adapted at one of them.
|
|
22
|
+
const LANE_BRANCH_SUFFIX = '-lane'
|
|
23
|
+
|
|
24
|
+
type LaneEnvironment = Record<string, string | undefined>
|
|
25
|
+
|
|
26
|
+
// `.kit-lanes` beside `kit`, `.app-kit-lanes` beside `app-kit`. Named after the repository rather
|
|
27
|
+
// than shared between them, so two projects' lanes never contend for one directory.
|
|
28
|
+
function default_lane_root(repository_root: string): string {
|
|
29
|
+
const name = path.basename(repository_root)
|
|
30
|
+
|
|
31
|
+
return path.join(path.dirname(repository_root), `.${name}${LANE_DIRECTORY_SUFFIX}`)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// A blank override is the shape of "I have not set this", exactly as `PORT_SEED`'s is: `.env.example`
|
|
35
|
+
// ships keys with no value, so reading blank as a path would put every lane at the filesystem root.
|
|
36
|
+
function lane_root(repository_root: string, environment: LaneEnvironment = process.env): string {
|
|
37
|
+
const configured = environment[LANE_ROOT_KEY]?.trim() ?? ''
|
|
38
|
+
|
|
39
|
+
return configured.length === 0 ? default_lane_root(repository_root) : path.resolve(configured)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function lane_directory(root: string, issue: string): string {
|
|
43
|
+
return path.join(root, issue)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// A lane directory's own name is the issue number, so the number a checkout belongs to is readable
|
|
47
|
+
// from its path alone.
|
|
48
|
+
const LANE_ISSUE_PATTERN = /^\d+$/u
|
|
49
|
+
// Built from the suffix above rather than spelled again, so the two readings of a lane root cannot
|
|
50
|
+
// drift apart. `.kit-lanes` and `.app-kit-lanes` both match; a plain `lanes` does not, because
|
|
51
|
+
// `default_lane_root` always writes the leading dot.
|
|
52
|
+
const DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, 'u')
|
|
53
|
+
|
|
54
|
+
function is_lane_root(directory: string, environment: LaneEnvironment): boolean {
|
|
55
|
+
const configured = environment[LANE_ROOT_KEY]?.trim() ?? ''
|
|
56
|
+
|
|
57
|
+
if (configured.length > 0) return path.resolve(configured) === directory
|
|
58
|
+
|
|
59
|
+
return DEFAULT_LANE_ROOT_PATTERN.test(path.basename(directory))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// **The inverse of `lane_directory`, and the one lane test that needs no git.** `lane_registry`
|
|
63
|
+
// answers the same question authoritatively by parsing `git worktree list`, but that read is
|
|
64
|
+
// asynchronous and a `PreToolUse` guard is synchronous by contract — so a guard that has to know
|
|
65
|
+
// whether the checkout it is running in is a lane reads it off the path instead
|
|
66
|
+
// (joshuafolkken/kit#1864). It is deliberately the weaker of the two: it says the directory *sits
|
|
67
|
+
// where a lane sits*, never that a work tree is registered there, so a caller that needs the
|
|
68
|
+
// registration still goes through `lane_registry`.
|
|
69
|
+
function lane_issue_of(
|
|
70
|
+
directory: string,
|
|
71
|
+
environment: LaneEnvironment = process.env,
|
|
72
|
+
): string | undefined {
|
|
73
|
+
const resolved = path.resolve(directory)
|
|
74
|
+
const issue = path.basename(resolved)
|
|
75
|
+
|
|
76
|
+
if (!LANE_ISSUE_PATTERN.test(issue)) return undefined
|
|
77
|
+
|
|
78
|
+
return is_lane_root(path.dirname(resolved), environment) ? issue : undefined
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function lane_branch(issue: string): string {
|
|
82
|
+
return `${issue}${LANE_BRANCH_SUFFIX}`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const lane_paths = {
|
|
86
|
+
LANE_BRANCH_SUFFIX,
|
|
87
|
+
LANE_ROOT_KEY,
|
|
88
|
+
default_lane_root,
|
|
89
|
+
lane_branch,
|
|
90
|
+
lane_directory,
|
|
91
|
+
lane_issue_of,
|
|
92
|
+
lane_root,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export type { LaneEnvironment }
|
|
96
|
+
export { lane_paths }
|