@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,166 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { repo_map_logic, type DiscoveredRepo, type RepoMap } from './repo-map-logic'
|
|
4
|
+
import { repo_origin } from './repo-origin'
|
|
5
|
+
|
|
6
|
+
// Finding which repositories sit next to this one, and where.
|
|
7
|
+
//
|
|
8
|
+
// Discovery is automatic by default rather than registered in a config file: on the machine this was
|
|
9
|
+
// written for, every first-party repository is a sibling of every other, so scanning the current
|
|
10
|
+
// repository's parent one level deep produces the same map from whichever of them the command runs
|
|
11
|
+
// in. `JOSH_REPO_PATHS` exists only for the exceptions (joshuafolkken/kit#869).
|
|
12
|
+
|
|
13
|
+
const GIT_DIRECTORY = '.git'
|
|
14
|
+
const GIT_CONFIG = 'config'
|
|
15
|
+
// A `.git` *file* points at the real git directory (`gitdir: …`), which is how worktrees and
|
|
16
|
+
// submodules are laid out. The pointer is relative to the work tree when it is not absolute.
|
|
17
|
+
const GITDIR_PREFIX = 'gitdir:'
|
|
18
|
+
// A linked worktree's git directory is `<main>/.git/worktrees/<name>`, which holds no `config` of
|
|
19
|
+
// its own — the shared one lives in the common directory that its `commondir` file names, relative
|
|
20
|
+
// to the worktree's git directory. A submodule's git directory has no `commondir` and holds its
|
|
21
|
+
// own `config`, which is why following the pointer alone appeared to work.
|
|
22
|
+
const COMMON_DIRECTORY_FILE = 'commondir'
|
|
23
|
+
const OVERRIDE_ENV_KEY = 'JOSH_REPO_PATHS'
|
|
24
|
+
|
|
25
|
+
// The directory a git directory's `config` actually lives in: itself, or the common directory a
|
|
26
|
+
// linked worktree points at.
|
|
27
|
+
function resolve_common_directory(git_directory: string): string {
|
|
28
|
+
const pointer = path.join(git_directory, COMMON_DIRECTORY_FILE)
|
|
29
|
+
if (!existsSync(pointer)) return git_directory
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
return path.resolve(git_directory, readFileSync(pointer, 'utf8').trim())
|
|
33
|
+
} catch {
|
|
34
|
+
return git_directory
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Where a `.git` file points. Relative pointers resolve against the work tree holding the file.
|
|
39
|
+
function follow_git_file(repository_path: string, git_file: string): string | undefined {
|
|
40
|
+
const pointer = readFileSync(git_file, 'utf8').trim()
|
|
41
|
+
if (!pointer.startsWith(GITDIR_PREFIX)) return undefined
|
|
42
|
+
|
|
43
|
+
return path.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim())
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The directory holding the `config` for a work tree: `.git` itself, or — through a `.git` file and
|
|
47
|
+
// then through `commondir` — the shared git directory a linked worktree borrows its remotes from.
|
|
48
|
+
function resolve_git_directory(repository_path: string): string | undefined {
|
|
49
|
+
const candidate = path.join(repository_path, GIT_DIRECTORY)
|
|
50
|
+
if (!existsSync(candidate)) return undefined
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
if (statSync(candidate).isDirectory()) return candidate
|
|
54
|
+
const linked = follow_git_file(repository_path, candidate)
|
|
55
|
+
|
|
56
|
+
return linked === undefined ? undefined : resolve_common_directory(linked)
|
|
57
|
+
} catch {
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The `origin` URL a work tree declares, or nothing when it has no `origin`, no readable config, or
|
|
63
|
+
// is not a work tree at all. Every failure reads as "no remote" so one unreadable sibling cannot
|
|
64
|
+
// fail a command whose contract is to report what it could find.
|
|
65
|
+
function read_origin_url(repository_path: string): string | undefined {
|
|
66
|
+
const git_directory = resolve_git_directory(repository_path)
|
|
67
|
+
if (git_directory === undefined) return undefined
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
return repo_origin.parse_origin_from_config(
|
|
71
|
+
readFileSync(path.join(git_directory, GIT_CONFIG), 'utf8'),
|
|
72
|
+
)
|
|
73
|
+
} catch {
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Every immediate child directory of `parent`, in name order. An unreadable parent yields nothing
|
|
79
|
+
// rather than throwing: `josh doctor` reports what it could find, and a permission error on the
|
|
80
|
+
// parent is not a broken install.
|
|
81
|
+
//
|
|
82
|
+
// Sorted because the map keeps the last entry for a repository, and two directories can hold the
|
|
83
|
+
// same one — the second checkout the override variable exists for. Left in `readdir` order, which
|
|
84
|
+
// checkout won would depend on the filesystem, so the same machine could answer differently after a
|
|
85
|
+
// directory was renamed.
|
|
86
|
+
function sibling_directories(parent: string): Array<string> {
|
|
87
|
+
try {
|
|
88
|
+
return readdirSync(parent, { withFileTypes: true })
|
|
89
|
+
.filter((entry) => entry.isDirectory())
|
|
90
|
+
.map((entry) => path.join(parent, entry.name))
|
|
91
|
+
.toSorted((left, right) => left.localeCompare(right))
|
|
92
|
+
} catch {
|
|
93
|
+
return []
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Every immediate child of `parent` that holds a git work tree, paired with its `origin`. One level
|
|
98
|
+
// only: a deeper walk would cross into `node_modules` and vendored checkouts, which are not
|
|
99
|
+
// repositories anyone dispatches work to.
|
|
100
|
+
function scan_siblings(parent: string): Array<DiscoveredRepo> {
|
|
101
|
+
return sibling_directories(parent).map((repository_path) => ({
|
|
102
|
+
path: repository_path,
|
|
103
|
+
origin_url: read_origin_url(repository_path),
|
|
104
|
+
}))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The owner half of a repository's own `origin`. Read locally rather than asked of `gh`, so the map
|
|
108
|
+
// is built without a network call and without an authenticated CLI.
|
|
109
|
+
function resolve_current_owner(repository_path: string): string | undefined {
|
|
110
|
+
const origin_url = read_origin_url(repository_path)
|
|
111
|
+
if (origin_url === undefined) return undefined
|
|
112
|
+
|
|
113
|
+
return repo_origin.parse_origin_url(origin_url)?.owner
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// The work tree a repository's siblings sit beside: the given path for an ordinary checkout, and the
|
|
117
|
+
// **main** work tree for a linked one. A linked work tree is parked wherever it was created — a lane
|
|
118
|
+
// lives under `.kit-lanes/`, whose only neighbors are that repository's other lanes — so taking the
|
|
119
|
+
// given path's parent as the place to look for siblings finds none of them. The common directory
|
|
120
|
+
// `resolve_git_directory` already follows is `<main>/.git`, so its parent is that main work tree.
|
|
121
|
+
//
|
|
122
|
+
// **Only when the resolved directory is itself a `.git`.** A submodule resolves to
|
|
123
|
+
// `<super>/.git/modules/<path>`, and a bare main repository to `<somewhere>/<name>.git`; neither has
|
|
124
|
+
// a work tree for a parent, so taking one would hand discovery a directory that is not a checkout at
|
|
125
|
+
// all — the very failure this function exists to close, moved somewhere else.
|
|
126
|
+
function main_worktree(repository_path: string): string {
|
|
127
|
+
const git_directory = resolve_git_directory(repository_path)
|
|
128
|
+
if (git_directory === undefined) return repository_path
|
|
129
|
+
if (path.basename(git_directory) !== GIT_DIRECTORY) return repository_path
|
|
130
|
+
|
|
131
|
+
return path.dirname(git_directory)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// The map for the repository at `repository_path`. Empty when that repository's own owner cannot be
|
|
135
|
+
// determined: without it there is nothing to compare siblings against, and a map built without the
|
|
136
|
+
// owner restriction is exactly what must never be produced.
|
|
137
|
+
//
|
|
138
|
+
// **Discovery is anchored on the main work tree, resolved here rather than by each caller.** A linked
|
|
139
|
+
// work tree — a lane — is parked among that repository's other lanes, so scanning *its* parent finds
|
|
140
|
+
// none of the siblings; `main_worktree` turns the given path into the main checkout, whose parent
|
|
141
|
+
// holds them. Every command that discovers repositories (`doctor`, `propagate`, `backlog:next`,
|
|
142
|
+
// `epic:next`, `clone:scan`) goes through here, so the anchor lives in one place instead of being
|
|
143
|
+
// re-applied at each call site. For an ordinary checkout, a submodule or a non-repository the
|
|
144
|
+
// resolution is a no-op (`main_worktree` returns the given path), so nothing but a lane is affected.
|
|
145
|
+
function discover_repositories(repository_path: string, environment = process.env): RepoMap {
|
|
146
|
+
const main = main_worktree(repository_path)
|
|
147
|
+
const current_owner = resolve_current_owner(main)
|
|
148
|
+
if (current_owner === undefined) return new Map<string, string>()
|
|
149
|
+
|
|
150
|
+
return repo_map_logic.build_repository_map(
|
|
151
|
+
scan_siblings(path.dirname(main)),
|
|
152
|
+
current_owner,
|
|
153
|
+
environment[OVERRIDE_ENV_KEY],
|
|
154
|
+
)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const repo_discovery = {
|
|
158
|
+
OVERRIDE_ENV_KEY,
|
|
159
|
+
main_worktree,
|
|
160
|
+
read_origin_url,
|
|
161
|
+
resolve_current_owner,
|
|
162
|
+
scan_siblings,
|
|
163
|
+
discover_repositories,
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { repo_discovery }
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { repo_origin, type RepoIdentity } from './repo-origin'
|
|
2
|
+
|
|
3
|
+
// Assembling the `owner/repo` → local path map from what the scan found.
|
|
4
|
+
//
|
|
5
|
+
// The owner restriction lives here, on the single path every entry travels, rather than in the
|
|
6
|
+
// scanner: an override that could re-enter the map behind the filter would be the hole the
|
|
7
|
+
// restriction exists to close. Discovered entries and overrides are both funnelled through
|
|
8
|
+
// `add_entry`, so there is exactly one place that decides what is allowed in
|
|
9
|
+
// (joshuafolkken/kit#869).
|
|
10
|
+
|
|
11
|
+
// One candidate the scan produced: a directory holding a git work tree, and the `origin` remote it
|
|
12
|
+
// declares. `origin_url` is undefined for a work tree with no `origin` at all.
|
|
13
|
+
interface DiscoveredRepo {
|
|
14
|
+
path: string
|
|
15
|
+
origin_url: string | undefined
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// `owner/repo` → absolute local path.
|
|
19
|
+
type RepoMap = ReadonlyMap<string, string>
|
|
20
|
+
|
|
21
|
+
const OVERRIDE_ENTRY_SEPARATOR = ','
|
|
22
|
+
const OVERRIDE_PAIR_SEPARATOR = '='
|
|
23
|
+
const OVERRIDE_PAIR_PARTS = 2
|
|
24
|
+
const KEY_INDEX = 0
|
|
25
|
+
const PATH_INDEX = 1
|
|
26
|
+
|
|
27
|
+
// Whether an identity belongs to the same owner as the repository the command is running in. This is
|
|
28
|
+
// the first-party test the AI documents define — owner equality, nothing else — and it is not
|
|
29
|
+
// configurable: a sibling directory belonging to another account or organization would otherwise be
|
|
30
|
+
// a repository this tooling could file issues against or push to.
|
|
31
|
+
function is_same_owner(identity: RepoIdentity, current_owner: string): boolean {
|
|
32
|
+
return identity.owner.toLowerCase() === current_owner.toLowerCase()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// The single gate. Anything reaching the map passes through here, so the owner restriction cannot be
|
|
36
|
+
// bypassed by supplying an entry from a different source.
|
|
37
|
+
function add_entry(
|
|
38
|
+
target: Map<string, string>,
|
|
39
|
+
origin_url: string | undefined,
|
|
40
|
+
repository_path: string,
|
|
41
|
+
current_owner: string,
|
|
42
|
+
): void {
|
|
43
|
+
if (origin_url === undefined) return
|
|
44
|
+
const identity = repo_origin.parse_origin_url(origin_url)
|
|
45
|
+
if (identity === undefined || !is_same_owner(identity, current_owner)) return
|
|
46
|
+
|
|
47
|
+
target.set(repo_origin.format_identity(identity), repository_path)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// One `owner/repo=/absolute/path` pair from the override variable. The key is re-parsed as a remote
|
|
51
|
+
// rather than trusted as written, so an override is held to the same normalization and the same
|
|
52
|
+
// owner restriction as a discovered entry.
|
|
53
|
+
function parse_override_entry(entry: string): DiscoveredRepo | undefined {
|
|
54
|
+
const parts = entry.split(OVERRIDE_PAIR_SEPARATOR).map((part) => part.trim())
|
|
55
|
+
if (parts.length !== OVERRIDE_PAIR_PARTS) return undefined
|
|
56
|
+
const key = parts[KEY_INDEX] ?? ''
|
|
57
|
+
const repository_path = parts[PATH_INDEX] ?? ''
|
|
58
|
+
if (repository_path === '') return undefined
|
|
59
|
+
|
|
60
|
+
return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key}` }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The override variable's entries, in order. Malformed entries are dropped rather than failing the
|
|
64
|
+
// command: `josh doctor` is what a user runs when something is already wrong, and the map it prints
|
|
65
|
+
// is what shows them the override did not take effect.
|
|
66
|
+
function parse_overrides(raw: string | undefined): Array<DiscoveredRepo> {
|
|
67
|
+
if (raw === undefined) return []
|
|
68
|
+
|
|
69
|
+
return raw
|
|
70
|
+
.split(OVERRIDE_ENTRY_SEPARATOR)
|
|
71
|
+
.map((entry) => parse_override_entry(entry))
|
|
72
|
+
.filter((entry): entry is DiscoveredRepo => entry !== undefined)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The map, from what the scan found plus whatever the override variable adds. Overrides are applied
|
|
76
|
+
// last so an explicit path wins over a discovered one — the escape hatch for a repository that is
|
|
77
|
+
// not a sibling, or one checked out more than once — but they win only *within* the owner
|
|
78
|
+
// restriction, never around it.
|
|
79
|
+
function build_repository_map(
|
|
80
|
+
discovered: ReadonlyArray<DiscoveredRepo>,
|
|
81
|
+
current_owner: string,
|
|
82
|
+
override_value?: string,
|
|
83
|
+
): RepoMap {
|
|
84
|
+
const result = new Map<string, string>()
|
|
85
|
+
|
|
86
|
+
for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner)
|
|
87
|
+
|
|
88
|
+
for (const entry of parse_overrides(override_value)) {
|
|
89
|
+
add_entry(result, entry.origin_url, entry.path, current_owner)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return result
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const repo_map_logic = {
|
|
96
|
+
is_same_owner,
|
|
97
|
+
parse_overrides,
|
|
98
|
+
build_repository_map,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export type { DiscoveredRepo, RepoMap }
|
|
102
|
+
export { repo_map_logic }
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Normalizing a git `origin` URL into the `owner/repo` that identifies the repository on GitHub.
|
|
2
|
+
//
|
|
3
|
+
// Kept separate from the map that consumes it (`repo-map-logic.ts`) because the shapes a remote can
|
|
4
|
+
// take are the part with real variety: a single machine's siblings were measured carrying SSH,
|
|
5
|
+
// an SSH host alias, HTTPS with embedded credentials and a trailing slash, and plain HTTPS — all
|
|
6
|
+
// four pointing at the same repository (joshuafolkken/kit#869).
|
|
7
|
+
|
|
8
|
+
// A repository's identity on GitHub. The `owner` half is what the discovery map filters on, so it is
|
|
9
|
+
// derived here from the remote and never from a directory name.
|
|
10
|
+
interface RepoIdentity {
|
|
11
|
+
owner: string
|
|
12
|
+
repo: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const GITHUB_HOST = 'github.com'
|
|
16
|
+
// An SSH host alias, as written in `~/.ssh/config` (`Host github-work`). Aliases are a local naming
|
|
17
|
+
// concept with no dots, and they exist only in the scp-like SSH form — see `is_github_ssh_host`.
|
|
18
|
+
const SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u
|
|
19
|
+
const GIT_SUFFIX = '.git'
|
|
20
|
+
const PATH_SEPARATOR = '/'
|
|
21
|
+
const USER_SEPARATOR = '@'
|
|
22
|
+
const HOST_SEPARATOR = ':'
|
|
23
|
+
const OWNER_INDEX = 0
|
|
24
|
+
const REPO_INDEX = 1
|
|
25
|
+
const REPO_PATH_SEGMENTS = 2
|
|
26
|
+
const NOT_FOUND = -1
|
|
27
|
+
const SECTION_PREFIX = '['
|
|
28
|
+
const ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u
|
|
29
|
+
const URL_KEY = 'url'
|
|
30
|
+
|
|
31
|
+
// Whether a URL's hostname is GitHub. Exact, with no alias spelling accepted: an alias is a name
|
|
32
|
+
// `~/.ssh/config` resolves, so `https://github-internal/owner/repo` is a real host of somebody
|
|
33
|
+
// else's and must not be read as GitHub.
|
|
34
|
+
function is_github_hostname(host: string): boolean {
|
|
35
|
+
return host.toLowerCase() === GITHUB_HOST
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Whether an SSH remote's host is GitHub: the canonical hostname, or a dotless alias for it as
|
|
39
|
+
// written in `~/.ssh/config` (`Host github-work`). A dotted host is a real hostname and has to match
|
|
40
|
+
// exactly, which is what keeps `github-enterprise.example.com` out.
|
|
41
|
+
function is_github_ssh_host(host: string): boolean {
|
|
42
|
+
const normalized = host.toLowerCase()
|
|
43
|
+
|
|
44
|
+
return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function strip_git_suffix(name: string): string {
|
|
48
|
+
return name.endsWith(GIT_SUFFIX) ? name.slice(0, -GIT_SUFFIX.length) : name
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// `owner/repo` from a remote's path. Empty segments are dropped, which absorbs a leading and a
|
|
52
|
+
// trailing slash without a backtracking pattern. Anything that is not exactly two segments is not a
|
|
53
|
+
// repository remote (a gist, a bare host, a nested path) and is rejected rather than guessed.
|
|
54
|
+
function to_identity(repository_path: string): RepoIdentity | undefined {
|
|
55
|
+
const segments = repository_path.split(PATH_SEPARATOR).filter((segment) => segment !== '')
|
|
56
|
+
if (segments.length !== REPO_PATH_SEGMENTS) return undefined
|
|
57
|
+
const owner = segments[OWNER_INDEX] ?? ''
|
|
58
|
+
const repo = strip_git_suffix(segments[REPO_INDEX] ?? '')
|
|
59
|
+
|
|
60
|
+
return repo === '' ? undefined : { owner, repo }
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// The `scp`-like SSH form: `git@github.com:owner/repo.git`, and its host-alias variant. Split by
|
|
64
|
+
// hand rather than matched: the pattern for this shape is an optional user part followed by a
|
|
65
|
+
// host — which backtracks super-linearly on a long non-matching remote.
|
|
66
|
+
function parse_scp_like(url: string): RepoIdentity | undefined {
|
|
67
|
+
const user_end = url.indexOf(USER_SEPARATOR)
|
|
68
|
+
const authority = user_end === NOT_FOUND ? url : url.slice(user_end + 1)
|
|
69
|
+
const host_end = authority.indexOf(HOST_SEPARATOR)
|
|
70
|
+
if (host_end === NOT_FOUND) return undefined
|
|
71
|
+
if (!is_github_ssh_host(authority.slice(0, host_end))) return undefined
|
|
72
|
+
|
|
73
|
+
return to_identity(authority.slice(host_end + 1))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Any URL form `URL` accepts: `https://user@github.com/owner/repo.git/`, `ssh://git@github.com/…`.
|
|
77
|
+
// Embedded credentials land in `username`/`password` and are dropped with the rest of the authority.
|
|
78
|
+
function parse_url_like(url: string): RepoIdentity | undefined {
|
|
79
|
+
try {
|
|
80
|
+
const parsed = new URL(url)
|
|
81
|
+
|
|
82
|
+
return is_github_hostname(parsed.hostname) ? to_identity(parsed.pathname) : undefined
|
|
83
|
+
} catch {
|
|
84
|
+
return undefined
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// `owner/repo` for a GitHub remote, or nothing for every other remote. Returning nothing is the
|
|
89
|
+
// exclusion the owner restriction depends on: a self-hosted or third-party host never reaches the
|
|
90
|
+
// owner comparison at all (joshuafolkken/kit#869).
|
|
91
|
+
function parse_origin_url(url: string): RepoIdentity | undefined {
|
|
92
|
+
const trimmed = url.trim()
|
|
93
|
+
if (trimmed === '') return undefined
|
|
94
|
+
|
|
95
|
+
return parse_url_like(trimmed) ?? parse_scp_like(trimmed)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function is_section_header(line: string): boolean {
|
|
99
|
+
return line.startsWith(SECTION_PREFIX)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// The lines belonging to the `[remote "origin"]` section, in order. A section runs until the next
|
|
103
|
+
// header, so a `url` declared under a different remote is never read as origin's.
|
|
104
|
+
function origin_section_lines(lines: ReadonlyArray<string>): Array<string> {
|
|
105
|
+
const start = lines.findIndex((line) => ORIGIN_SECTION.test(line))
|
|
106
|
+
if (start === NOT_FOUND) return []
|
|
107
|
+
const rest = lines.slice(start + 1)
|
|
108
|
+
const end = rest.findIndex((line) => is_section_header(line))
|
|
109
|
+
|
|
110
|
+
return end === NOT_FOUND ? rest : rest.slice(0, end)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// The value of a `key = value` entry, or nothing when the line declares a different key. Split on
|
|
114
|
+
// the first separator rather than matched, for the reason `parse_scp_like` is split by hand.
|
|
115
|
+
function entry_value(line: string, key: string): string | undefined {
|
|
116
|
+
const separator = line.indexOf('=')
|
|
117
|
+
if (separator === NOT_FOUND) return undefined
|
|
118
|
+
if (line.slice(0, separator).trim() !== key) return undefined
|
|
119
|
+
|
|
120
|
+
return line.slice(separator + 1).trim()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// The `url` of the `[remote "origin"]` section of a git config, or nothing when the work tree
|
|
124
|
+
// declares no `origin`. Parsed from the file rather than asked of `git`, because discovery reads one
|
|
125
|
+
// config per sibling directory and spawning a process for each would make `josh doctor` pay a
|
|
126
|
+
// process per unrelated repository sharing the parent directory.
|
|
127
|
+
function parse_origin_from_config(content: string): string | undefined {
|
|
128
|
+
const lines = content.split('\n').map((line) => line.trim())
|
|
129
|
+
|
|
130
|
+
return origin_section_lines(lines)
|
|
131
|
+
.map((line) => entry_value(line, URL_KEY))
|
|
132
|
+
.find((url) => url !== undefined)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// The `owner/repo` key a discovery map is keyed by. Lowercased, because GitHub resolves owner and
|
|
136
|
+
// repository names case-insensitively: two remotes spelling the same repository differently are the
|
|
137
|
+
// same repository, and keying by the spelling would put both in the map — where an override, which
|
|
138
|
+
// the caller applies last, would no longer replace the entry it was written to replace.
|
|
139
|
+
function format_identity(identity: RepoIdentity): string {
|
|
140
|
+
return `${identity.owner}${PATH_SEPARATOR}${identity.repo}`.toLowerCase()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const repo_origin = {
|
|
144
|
+
GITHUB_HOST,
|
|
145
|
+
is_github_hostname,
|
|
146
|
+
is_github_ssh_host,
|
|
147
|
+
parse_origin_from_config,
|
|
148
|
+
parse_origin_url,
|
|
149
|
+
format_identity,
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export type { RepoIdentity }
|
|
153
|
+
export { repo_origin }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { repo_party, type Party } from './repo-party'
|
|
4
|
+
|
|
5
|
+
// `josh repo:party [<owner/repo>]` — say whether a repository is first-party or third-party
|
|
6
|
+
// (joshuafolkken/kit#2122). A command rather than a paragraph, for the reason `josh latest:scope` is
|
|
7
|
+
// one: a rule an agent applies from memory is a rule an agent can talk itself out of, and this one is
|
|
8
|
+
// argued against at exactly the moment a workflow wants to write to another repository.
|
|
9
|
+
//
|
|
10
|
+
// The word alone on stdout so `$(pnpm josh repo:party o/r)` reads it, and the two owners it compared
|
|
11
|
+
// on stderr so a person sees why without a shell having to parse around it — the split
|
|
12
|
+
// `josh latest:scope` prints in.
|
|
13
|
+
|
|
14
|
+
const ARGV_OFFSET = 2
|
|
15
|
+
const USAGE = 'Usage: josh repo:party [<owner/repo>]'
|
|
16
|
+
const FAILURE_EXIT_CODE = 1
|
|
17
|
+
const FLAG_PREFIX = '-'
|
|
18
|
+
const NONE_ARGUMENT = 0
|
|
19
|
+
const ONE_ARGUMENT = 1
|
|
20
|
+
const UNREADABLE = '(unreadable)'
|
|
21
|
+
|
|
22
|
+
interface Decision {
|
|
23
|
+
party: Party
|
|
24
|
+
detail: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function owner_label(owner: string | undefined): string {
|
|
28
|
+
return owner ?? UNREADABLE
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// No argument targets the session's own repository, so both owners are the session's and the answer
|
|
32
|
+
// is `first-party` unless the session's remote cannot be read. The stderr line names the two owners
|
|
33
|
+
// the classification actually compared, whichever arm was taken.
|
|
34
|
+
function decide(owner_repo: string | undefined): Decision {
|
|
35
|
+
const session_owner = repo_party.current_owner()
|
|
36
|
+
const target = owner_repo === undefined ? session_owner : repo_party.target_owner(owner_repo)
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
party: repo_party.classify(session_owner, target),
|
|
40
|
+
detail: `session owner: ${owner_label(session_owner)} · target owner: ${owner_label(target)}`,
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function run(argv: ReadonlyArray<string>): number {
|
|
45
|
+
const positional = argv.filter((argument) => !argument.startsWith(FLAG_PREFIX))
|
|
46
|
+
|
|
47
|
+
if (positional.length !== NONE_ARGUMENT && positional.length !== ONE_ARGUMENT) {
|
|
48
|
+
console.error(USAGE)
|
|
49
|
+
|
|
50
|
+
return FAILURE_EXIT_CODE
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const decision = decide(positional[0])
|
|
54
|
+
|
|
55
|
+
console.info(decision.party)
|
|
56
|
+
console.error(decision.detail)
|
|
57
|
+
|
|
58
|
+
return 0
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function main(argv: ReadonlyArray<string>): void {
|
|
62
|
+
process.exitCode = run(argv)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const repo_party_cli = { USAGE, decide, main, run }
|
|
66
|
+
|
|
67
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET))
|
|
68
|
+
|
|
69
|
+
export { repo_party_cli }
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { repo_discovery } from './repo-discovery'
|
|
2
|
+
import { repo_origin } from './repo-origin'
|
|
3
|
+
|
|
4
|
+
// **First-party vs third-party, computed rather than judged** (joshuafolkken/kit#2122). `CLAUDE.md`
|
|
5
|
+
// and `upstream-interrupt.md` both declared the test mechanical — owner equality between the target
|
|
6
|
+
// repository and the session's — yet nothing computed it: three prose spots restated the manual
|
|
7
|
+
// `gh api … --jq .owner.login`, and whether an owner had actually been read was left to trust. This is
|
|
8
|
+
// the computation those documents describe, so the rule that refuses a third-party write and the
|
|
9
|
+
// `josh repo:party` oracle read one definition rather than two.
|
|
10
|
+
//
|
|
11
|
+
// **The owner comparison is case-insensitive**, because GitHub resolves owner names that way — the
|
|
12
|
+
// same reason `repo-origin.ts` lowercases the discovery key. Two spellings of one owner are one owner.
|
|
13
|
+
|
|
14
|
+
type Party = 'first-party' | 'third-party' | 'unknown'
|
|
15
|
+
|
|
16
|
+
const FIRST_PARTY: Party = 'first-party'
|
|
17
|
+
const THIRD_PARTY: Party = 'third-party'
|
|
18
|
+
const UNKNOWN: Party = 'unknown'
|
|
19
|
+
|
|
20
|
+
// `unknown` is not `third-party`. An owner that cannot be read — no `origin`, an unreadable config —
|
|
21
|
+
// is a "cannot decide", and reading it as third-party would refuse first-party writes whenever the
|
|
22
|
+
// session's own remote was momentarily unreadable. The caller decides what a `unknown` licenses;
|
|
23
|
+
// the deny rule treats it as "not proven third-party" and stays silent.
|
|
24
|
+
function classify(session_owner: string | undefined, target: string | undefined): Party {
|
|
25
|
+
if (session_owner === undefined || target === undefined) return UNKNOWN
|
|
26
|
+
|
|
27
|
+
return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// The owner half of a `owner/repo` argument, parsed through the remote-URL reader so a `.git` suffix
|
|
31
|
+
// and a malformed form (one segment, three segments) are handled by the one place that already knows
|
|
32
|
+
// them rather than by a second split here.
|
|
33
|
+
function target_owner(owner_repo: string): string | undefined {
|
|
34
|
+
return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`)?.owner
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The owner of the repository the session runs in, read locally from its `origin` — no network call
|
|
38
|
+
// and no authenticated CLI, so the guard that consults it stays synchronous.
|
|
39
|
+
function current_owner(repository_path: string = process.cwd()): string | undefined {
|
|
40
|
+
return repo_discovery.resolve_current_owner(repository_path)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const repo_party = { FIRST_PARTY, THIRD_PARTY, UNKNOWN, classify, current_owner, target_owner }
|
|
44
|
+
|
|
45
|
+
export type { Party }
|
|
46
|
+
export { repo_party }
|