@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,1597 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import {
|
|
3
|
+
agent_role_profile,
|
|
4
|
+
backlog_budget,
|
|
5
|
+
filing_cap,
|
|
6
|
+
git_gh_api_path,
|
|
7
|
+
git_gh_exec,
|
|
8
|
+
lane_child_invocation,
|
|
9
|
+
lane_park,
|
|
10
|
+
lane_registry,
|
|
11
|
+
process_identity,
|
|
12
|
+
repo_party,
|
|
13
|
+
run_carry,
|
|
14
|
+
run_cut,
|
|
15
|
+
run_hold,
|
|
16
|
+
run_invocation,
|
|
17
|
+
run_watcher_guard
|
|
18
|
+
} from "./chunk-2XIGZQMQ.js";
|
|
19
|
+
import {
|
|
20
|
+
session_language
|
|
21
|
+
} from "./chunk-6V5OPIUU.js";
|
|
22
|
+
import {
|
|
23
|
+
hook_decision,
|
|
24
|
+
lane_child_marker
|
|
25
|
+
} from "./chunk-GXKKK23T.js";
|
|
26
|
+
import {
|
|
27
|
+
PROJECT_ROOT,
|
|
28
|
+
stamp_file,
|
|
29
|
+
time_density_hook,
|
|
30
|
+
time_hook_transcript
|
|
31
|
+
} from "./chunk-KABG6AEW.js";
|
|
32
|
+
import "./chunk-FXAKJKTB.js";
|
|
33
|
+
import "./chunk-SSX23SJ2.js";
|
|
34
|
+
|
|
35
|
+
// scripts/hooks/stop-guard.ts
|
|
36
|
+
import { text } from "node:stream/consumers";
|
|
37
|
+
import { fileURLToPath } from "node:url";
|
|
38
|
+
|
|
39
|
+
// scripts/josh/josh-run.ts
|
|
40
|
+
import { execa } from "execa";
|
|
41
|
+
var PNPM = "pnpm";
|
|
42
|
+
var JOSH = "josh";
|
|
43
|
+
var NONZERO_EXIT = 1;
|
|
44
|
+
var FORWARDED_STDERR = ["pipe", "inherit"];
|
|
45
|
+
async function josh_run(args, should_forward_stderr = false, timeout_ms) {
|
|
46
|
+
const result = await execa(PNPM, [JOSH, ...args], {
|
|
47
|
+
reject: false,
|
|
48
|
+
stderr: should_forward_stderr ? FORWARDED_STDERR : "pipe",
|
|
49
|
+
...timeout_ms !== void 0 && { timeout: timeout_ms }
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
code: result.exitCode ?? NONZERO_EXIT,
|
|
53
|
+
out: result.stdout.trim(),
|
|
54
|
+
err: result.stderr.trim()
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
var josh_command = { josh_run };
|
|
58
|
+
|
|
59
|
+
// scripts/lane/lane-capacity.ts
|
|
60
|
+
var DEFAULT_LANE_LIMIT = 6;
|
|
61
|
+
var LANE_LIMIT_KEY = "JOSH_LANE_LIMIT";
|
|
62
|
+
var POSITIVE_INTEGER = /^[1-9]\d*$/u;
|
|
63
|
+
var NO_LANES = 0;
|
|
64
|
+
function read_limit(raw) {
|
|
65
|
+
const trimmed = raw?.trim() ?? "";
|
|
66
|
+
if (trimmed === "") return { kind: "limit", limit: DEFAULT_LANE_LIMIT };
|
|
67
|
+
if (!POSITIVE_INTEGER.test(trimmed)) {
|
|
68
|
+
return {
|
|
69
|
+
kind: "problem",
|
|
70
|
+
problem: `${LANE_LIMIT_KEY} must be a positive integer, not "${trimmed}"`
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { kind: "limit", limit: Number(trimmed) };
|
|
74
|
+
}
|
|
75
|
+
function lane_limit(environment2 = process.env) {
|
|
76
|
+
return read_limit(environment2[LANE_LIMIT_KEY]);
|
|
77
|
+
}
|
|
78
|
+
function free_lanes(limit, occupied) {
|
|
79
|
+
return Math.max(NO_LANES, limit - occupied);
|
|
80
|
+
}
|
|
81
|
+
var lane_capacity = {
|
|
82
|
+
DEFAULT_LANE_LIMIT,
|
|
83
|
+
LANE_LIMIT_KEY,
|
|
84
|
+
read_limit,
|
|
85
|
+
lane_limit,
|
|
86
|
+
free_lanes
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// scripts/lane/lane-reap.ts
|
|
90
|
+
import { execFileSync } from "node:child_process";
|
|
91
|
+
var PGREP_COMMAND = "pgrep";
|
|
92
|
+
var MATCH_FULL_COMMAND_LINE = "-f";
|
|
93
|
+
var CHILDREN_OF_FLAG = "-P";
|
|
94
|
+
var PS_COMMAND = "/bin/ps";
|
|
95
|
+
var PARENT_FORMAT = ["-o", "ppid=", "-p"];
|
|
96
|
+
var TERMINATE_SIGNAL = "SIGTERM";
|
|
97
|
+
var PROBE_TIMEOUT_MS = 2e3;
|
|
98
|
+
var LOWEST_CHILD_PID = 2;
|
|
99
|
+
function parse_pids(printed) {
|
|
100
|
+
return printed.split("\n").map((line) => Number(line.trim())).filter((pid) => Number.isSafeInteger(pid) && pid >= LOWEST_CHILD_PID);
|
|
101
|
+
}
|
|
102
|
+
function run_probe(command, args) {
|
|
103
|
+
try {
|
|
104
|
+
return execFileSync(command, [...args], {
|
|
105
|
+
encoding: "utf8",
|
|
106
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
107
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
108
|
+
});
|
|
109
|
+
} catch {
|
|
110
|
+
return "";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function parent_of(pid) {
|
|
114
|
+
return parse_pids(run_probe(PS_COMMAND, [...PARENT_FORMAT, String(pid)]))[0];
|
|
115
|
+
}
|
|
116
|
+
function terminate(pid) {
|
|
117
|
+
try {
|
|
118
|
+
process.kill(pid, TERMINATE_SIGNAL);
|
|
119
|
+
return true;
|
|
120
|
+
} catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
var SYSTEM_PROBES = {
|
|
125
|
+
matching: (pattern) => parse_pids(run_probe(PGREP_COMMAND, [MATCH_FULL_COMMAND_LINE, pattern])),
|
|
126
|
+
children_of: (pid) => parse_pids(run_probe(PGREP_COMMAND, [CHILDREN_OF_FLAG, String(pid)])),
|
|
127
|
+
parent_of,
|
|
128
|
+
terminate
|
|
129
|
+
};
|
|
130
|
+
function ancestry_of(pid, probes) {
|
|
131
|
+
const ancestry = /* @__PURE__ */ new Set([pid]);
|
|
132
|
+
let current = probes.parent_of(pid);
|
|
133
|
+
while (current !== void 0 && !ancestry.has(current)) {
|
|
134
|
+
ancestry.add(current);
|
|
135
|
+
current = probes.parent_of(current);
|
|
136
|
+
}
|
|
137
|
+
return ancestry;
|
|
138
|
+
}
|
|
139
|
+
function own_ancestry(probes = SYSTEM_PROBES) {
|
|
140
|
+
return ancestry_of(process.pid, probes);
|
|
141
|
+
}
|
|
142
|
+
function tree_of(roots, probes) {
|
|
143
|
+
const tree = [];
|
|
144
|
+
const pending = [...roots];
|
|
145
|
+
let next = pending.shift();
|
|
146
|
+
while (next !== void 0) {
|
|
147
|
+
if (!tree.includes(next)) {
|
|
148
|
+
tree.push(next);
|
|
149
|
+
pending.push(...probes.children_of(next));
|
|
150
|
+
}
|
|
151
|
+
next = pending.shift();
|
|
152
|
+
}
|
|
153
|
+
return tree;
|
|
154
|
+
}
|
|
155
|
+
function reap_child(issue, probes = SYSTEM_PROBES) {
|
|
156
|
+
const own = own_ancestry(probes);
|
|
157
|
+
const pattern = lane_child_invocation.process_pattern(issue);
|
|
158
|
+
const roots = probes.matching(pattern).filter((pid) => !own.has(pid));
|
|
159
|
+
const doomed = tree_of(roots, probes).filter((pid) => !own.has(pid));
|
|
160
|
+
return doomed.filter((pid) => probes.terminate(pid));
|
|
161
|
+
}
|
|
162
|
+
var lane_reap = {
|
|
163
|
+
own_ancestry,
|
|
164
|
+
parse_pids,
|
|
165
|
+
reap_child
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// scripts/run/run-headless.ts
|
|
169
|
+
var HEADLESS_ENV_KEY = "JOSH_RUN_HEADLESS";
|
|
170
|
+
var HEADLESS_VALUE = "1";
|
|
171
|
+
function environment() {
|
|
172
|
+
return { [HEADLESS_ENV_KEY]: HEADLESS_VALUE };
|
|
173
|
+
}
|
|
174
|
+
function is_headless(source = process.env) {
|
|
175
|
+
return source[HEADLESS_ENV_KEY] === HEADLESS_VALUE;
|
|
176
|
+
}
|
|
177
|
+
function is_driving(read) {
|
|
178
|
+
return read?.kind === "carried" && read.carry.is_handed_off !== true;
|
|
179
|
+
}
|
|
180
|
+
async function read_carry_here() {
|
|
181
|
+
const repository = await run_carry.repository_directory();
|
|
182
|
+
return repository === void 0 ? void 0 : run_carry.read_carry(run_carry.carry_path(repository));
|
|
183
|
+
}
|
|
184
|
+
async function must_keep_waiting(source = process.env) {
|
|
185
|
+
const is_candidate = is_headless(source) && lane_child_marker.marked_issue(source) === void 0;
|
|
186
|
+
if (!is_candidate || !await run_watcher_guard.has_lanes_in_flight()) return false;
|
|
187
|
+
return is_driving(await read_carry_here());
|
|
188
|
+
}
|
|
189
|
+
async function current_carry() {
|
|
190
|
+
const read = await read_carry_here();
|
|
191
|
+
return read?.kind === "carried" ? read.carry : void 0;
|
|
192
|
+
}
|
|
193
|
+
function is_owned_here(carry, ancestry) {
|
|
194
|
+
return carry.owner_pid !== void 0 && ancestry().has(carry.owner_pid);
|
|
195
|
+
}
|
|
196
|
+
function is_driven_here(read, ancestry) {
|
|
197
|
+
if (read?.kind !== "carried" || !is_driving(read)) return false;
|
|
198
|
+
return is_owned_here(read.carry, ancestry);
|
|
199
|
+
}
|
|
200
|
+
async function is_backlog_parent(source = process.env, ancestry = lane_reap.own_ancestry) {
|
|
201
|
+
if (lane_child_marker.marked_issue(source) !== void 0) return false;
|
|
202
|
+
return is_driven_here(await read_carry_here(), ancestry);
|
|
203
|
+
}
|
|
204
|
+
var run_headless = {
|
|
205
|
+
HEADLESS_ENV_KEY,
|
|
206
|
+
current_carry,
|
|
207
|
+
environment,
|
|
208
|
+
is_backlog_parent,
|
|
209
|
+
is_headless,
|
|
210
|
+
must_keep_waiting
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// scripts/run/run-event-stream.ts
|
|
214
|
+
import { z } from "zod";
|
|
215
|
+
var EVENT_PREFIX = "josh-run-events-";
|
|
216
|
+
var EVENT_SUFFIX = ".jsonl";
|
|
217
|
+
var EVENT_CAP = 500;
|
|
218
|
+
var FIRST_POSITION = 0;
|
|
219
|
+
var POSITION_INCREMENT = 1;
|
|
220
|
+
var LINE_SEPARATOR = "\n";
|
|
221
|
+
var EVENT_KIND = {
|
|
222
|
+
PLAN: "plan",
|
|
223
|
+
CHILD_LAUNCH: "child-launch",
|
|
224
|
+
MERGE: "merge",
|
|
225
|
+
PARK: "park",
|
|
226
|
+
SPLIT: "split",
|
|
227
|
+
OUTAGE: "outage",
|
|
228
|
+
CUT: "cut",
|
|
229
|
+
// The backlog emptied while nothing of the run's own was in flight — the drain
|
|
230
|
+
// (joshuafolkken/kit#2335). It marks the position at which the end-of-run retrospective is owed,
|
|
231
|
+
// *before* the idle watch opens, so `run:step` fires the retrospective at the drain rather than after
|
|
232
|
+
// the watch runs its course. It is not itself a stop: the run watches on once the retrospective has
|
|
233
|
+
// run, and the real `STOP` follows when the watch expires.
|
|
234
|
+
DRAIN: "drain",
|
|
235
|
+
STOP: "stop",
|
|
236
|
+
PR_OPENED: "pr-opened",
|
|
237
|
+
REVIEW_ROUND: "review-round",
|
|
238
|
+
// The end-of-run retrospective's result, recorded when the run marks the retrospective done
|
|
239
|
+
// (joshuafolkken/kit#2342). A retrospective that files zero improvements and one that never ran look
|
|
240
|
+
// the same from outside — no new Issue either way — so the result is put on the stream the report is
|
|
241
|
+
// generated from: the issues filed (or that none were), and the candidates dropped with why. It is
|
|
242
|
+
// emitted from the `run:carry --retrospective` close, so marking the retrospective done and recording
|
|
243
|
+
// what it found are one action rather than two the run could do only one of.
|
|
244
|
+
RETROSPECTIVE: "retrospective",
|
|
245
|
+
// Ready backlog work is sitting undispatched while a lane is free and nothing has dispatched for a
|
|
246
|
+
// while (joshuafolkken/kit#2359). Emitted once per stall episode by the stop-time detector, it is
|
|
247
|
+
// both the dedup marker — `emit_once_since` refuses a second until a `CHILD_LAUNCH` intervenes
|
|
248
|
+
// (joshuafolkken/kit#2464) — and the line a
|
|
249
|
+
// terminal reader following the stream sees. `run:step` reads it as `backlog:next`, so a run that
|
|
250
|
+
// stalled is pointed straight at dispatching the work rather than left waiting.
|
|
251
|
+
STALL: "stall",
|
|
252
|
+
// The run's own driver is gone: the cut handed the budget off, the owner has died, and no supervisor
|
|
253
|
+
// is watching (joshuafolkken/kit#2375). Emitted once per strand episode by the stop-time detector,
|
|
254
|
+
// exactly as `STALL` is — the newest-event dedup keeps a run polled every stop from notifying more
|
|
255
|
+
// than once, and a terminal reader following the stream sees the line. The strand is the step before
|
|
256
|
+
// the stall: a stalled run still has a driver that could dispatch, a stranded one has none.
|
|
257
|
+
STRANDED: "stranded",
|
|
258
|
+
// One `josh ship` stage starting, succeeding or failing (joshuafolkken/kit#2426). It is a trace of the
|
|
259
|
+
// composite's progress rather than a position the run is at — the positions a ship leaves behind are
|
|
260
|
+
// the closed issue its `followup` merges, or a detached supervisor's `SHIP_LAUNCH` / `SHIP_STOP` below
|
|
261
|
+
// — so it is one of the `TRACE_KINDS` the last-event read skips.
|
|
262
|
+
SHIP_STAGE: "ship-stage",
|
|
263
|
+
// One progress watcher line — the `at … / next …` heartbeat `run:progress` prints
|
|
264
|
+
// (joshuafolkken/kit#2437). Printed only to the watcher's own output, a headless successor's heartbeat
|
|
265
|
+
// was buried in its log after a cut; on the stream it reaches the attached session's relay. It says
|
|
266
|
+
// the run is alive rather than where it is, so it is a trace kind like `SHIP_STAGE`.
|
|
267
|
+
HEARTBEAT: "heartbeat",
|
|
268
|
+
// The post-implementation region handed to a detached `josh ship --detach` supervisor
|
|
269
|
+
// (joshuafolkken/kit#2428). Unlike a stage trace it is a position: the agent has ended and the
|
|
270
|
+
// supervisor carries the run, so `run:step` answers `wait` until it stops or the issue closes.
|
|
271
|
+
SHIP_LAUNCH: "ship-launch",
|
|
272
|
+
// The supervisor stopped at a failed stage — a red gate, a High/Medium review, a failed push, red CI
|
|
273
|
+
// (joshuafolkken/kit#2428). The position that hands control back: `run:step` prints the command that
|
|
274
|
+
// shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
|
|
275
|
+
SHIP_STOP: "ship-stop"
|
|
276
|
+
};
|
|
277
|
+
var EVENT_KINDS = Object.values(EVENT_KIND);
|
|
278
|
+
var TRACE_KINDS = /* @__PURE__ */ new Set([EVENT_KIND.SHIP_STAGE, EVENT_KIND.HEARTBEAT]);
|
|
279
|
+
var event_schema = z.object({
|
|
280
|
+
pos: z.number(),
|
|
281
|
+
at: z.string(),
|
|
282
|
+
kind: z.string(),
|
|
283
|
+
text: z.string()
|
|
284
|
+
});
|
|
285
|
+
function is_event_kind(value) {
|
|
286
|
+
return EVENT_KINDS.includes(value);
|
|
287
|
+
}
|
|
288
|
+
function target_of(repository) {
|
|
289
|
+
return stamp_file.stamp_path(EVENT_PREFIX, repository, EVENT_SUFFIX);
|
|
290
|
+
}
|
|
291
|
+
function is_present(event) {
|
|
292
|
+
return event !== void 0;
|
|
293
|
+
}
|
|
294
|
+
function parse_line(line) {
|
|
295
|
+
try {
|
|
296
|
+
return event_schema.safeParse(JSON.parse(line)).data;
|
|
297
|
+
} catch {
|
|
298
|
+
return void 0;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function read_events(target) {
|
|
302
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
303
|
+
if (raw === void 0) return [];
|
|
304
|
+
return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line(line)).filter(is_present);
|
|
305
|
+
}
|
|
306
|
+
function last_position(events) {
|
|
307
|
+
return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
|
|
308
|
+
}
|
|
309
|
+
function serialize(events) {
|
|
310
|
+
return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
|
|
311
|
+
}
|
|
312
|
+
function append(target, kind, text2, at) {
|
|
313
|
+
if (!is_event_kind(kind)) return { appended: false, position: FIRST_POSITION };
|
|
314
|
+
const existing = read_events(target);
|
|
315
|
+
const position = last_position(existing) + POSITION_INCREMENT;
|
|
316
|
+
const bounded = [...existing, { pos: position, at, kind, text: text2 }].slice(-EVENT_CAP);
|
|
317
|
+
stamp_file.write_text_stamp(target, serialize(bounded));
|
|
318
|
+
return { appended: true, position };
|
|
319
|
+
}
|
|
320
|
+
function read_from(target, position) {
|
|
321
|
+
const events = read_events(target);
|
|
322
|
+
return {
|
|
323
|
+
events: events.filter((event) => event.pos > position),
|
|
324
|
+
next_position: last_position(events)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function read_last(target) {
|
|
328
|
+
return read_events(target).findLast((event) => !TRACE_KINDS.has(event.kind));
|
|
329
|
+
}
|
|
330
|
+
function has_since(events, kind, reset_kind) {
|
|
331
|
+
const reset_at = events.findLastIndex((event) => event.kind === reset_kind);
|
|
332
|
+
return events.slice(reset_at + POSITION_INCREMENT).some((event) => event.kind === kind);
|
|
333
|
+
}
|
|
334
|
+
var FIELD_SEPARATOR = " \xB7 ";
|
|
335
|
+
function format_event(event) {
|
|
336
|
+
return [event.at, event.kind, event.text].join(FIELD_SEPARATOR);
|
|
337
|
+
}
|
|
338
|
+
var run_event_stream = {
|
|
339
|
+
EVENT_CAP,
|
|
340
|
+
EVENT_KIND,
|
|
341
|
+
EVENT_KINDS,
|
|
342
|
+
EVENT_PREFIX,
|
|
343
|
+
EVENT_SUFFIX,
|
|
344
|
+
TRACE_KINDS,
|
|
345
|
+
append,
|
|
346
|
+
format_event,
|
|
347
|
+
has_since,
|
|
348
|
+
is_event_kind,
|
|
349
|
+
read_events,
|
|
350
|
+
read_from,
|
|
351
|
+
read_last,
|
|
352
|
+
target_of
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// scripts/backlog/backlog-stalled.ts
|
|
356
|
+
var STALL_THRESHOLD_MINUTES = 10;
|
|
357
|
+
var MS_PER_MINUTE = 6e4;
|
|
358
|
+
var STALL_THRESHOLD_MS = STALL_THRESHOLD_MINUTES * MS_PER_MINUTE;
|
|
359
|
+
var NONE = 0;
|
|
360
|
+
var STALLED = "stalled";
|
|
361
|
+
var OK = "ok";
|
|
362
|
+
var UNREADABLE = "unreadable";
|
|
363
|
+
function is_stalled(reading, threshold_ms) {
|
|
364
|
+
return reading.ready_count > NONE && reading.free_lanes > NONE && reading.dispatch_age_ms > threshold_ms;
|
|
365
|
+
}
|
|
366
|
+
function assess(reading, threshold_ms) {
|
|
367
|
+
if (reading === void 0) return UNREADABLE;
|
|
368
|
+
if (is_stalled(reading, threshold_ms)) return STALLED;
|
|
369
|
+
return OK;
|
|
370
|
+
}
|
|
371
|
+
function dispatch_reference_iso(events) {
|
|
372
|
+
const last_launch = events.findLast(
|
|
373
|
+
(event) => event.kind === run_event_stream.EVENT_KIND.CHILD_LAUNCH
|
|
374
|
+
);
|
|
375
|
+
return last_launch?.at ?? events[0]?.at;
|
|
376
|
+
}
|
|
377
|
+
function dispatch_age_ms(events, now_ms) {
|
|
378
|
+
const iso = dispatch_reference_iso(events);
|
|
379
|
+
if (iso === void 0) return void 0;
|
|
380
|
+
const at = Date.parse(iso);
|
|
381
|
+
return Number.isNaN(at) ? void 0 : now_ms - at;
|
|
382
|
+
}
|
|
383
|
+
function describe(reading) {
|
|
384
|
+
const minutes = Math.floor(reading.dispatch_age_ms / MS_PER_MINUTE);
|
|
385
|
+
return `${String(reading.ready_count)} ready, ${String(reading.free_lanes)} free lane(s), ${String(minutes)}m since the last dispatch`;
|
|
386
|
+
}
|
|
387
|
+
var NUMERIC_TOKEN = /^\d+$/u;
|
|
388
|
+
function ready_tokens(out) {
|
|
389
|
+
return out.split("\n").map((token) => token.trim()).filter((token) => NUMERIC_TOKEN.test(token));
|
|
390
|
+
}
|
|
391
|
+
function count_ready_tokens(out) {
|
|
392
|
+
return ready_tokens(out).length;
|
|
393
|
+
}
|
|
394
|
+
var backlog_stalled = {
|
|
395
|
+
STALLED,
|
|
396
|
+
OK,
|
|
397
|
+
UNREADABLE,
|
|
398
|
+
STALL_THRESHOLD_MS,
|
|
399
|
+
assess,
|
|
400
|
+
count_ready_tokens,
|
|
401
|
+
describe,
|
|
402
|
+
dispatch_age_ms,
|
|
403
|
+
is_stalled,
|
|
404
|
+
ready_tokens
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
// scripts/backlog/backlog-ready.ts
|
|
408
|
+
var NO_FREE = 0;
|
|
409
|
+
var NONE2 = 0;
|
|
410
|
+
async function free_lane_count() {
|
|
411
|
+
const limit = lane_capacity.lane_limit();
|
|
412
|
+
if (limit.kind !== "limit") return NO_FREE;
|
|
413
|
+
const lanes = await lane_registry.list_lanes();
|
|
414
|
+
const live = lanes.filter((lane) => !lane.is_stranded).length;
|
|
415
|
+
return lane_capacity.free_lanes(limit.limit, live);
|
|
416
|
+
}
|
|
417
|
+
function drains_pool(carry) {
|
|
418
|
+
return carry === void 0 || !run_invocation.has_only(carry.invocation);
|
|
419
|
+
}
|
|
420
|
+
async function read_backlog_next(timeout_ms) {
|
|
421
|
+
if (!drains_pool(await run_headless.current_carry())) return void 0;
|
|
422
|
+
return await josh_command.josh_run(["backlog:next"], timeout_ms === void 0, timeout_ms);
|
|
423
|
+
}
|
|
424
|
+
async function ready_issues() {
|
|
425
|
+
const result = await read_backlog_next();
|
|
426
|
+
return result === void 0 ? [] : backlog_stalled.ready_tokens(result.out);
|
|
427
|
+
}
|
|
428
|
+
var DEFAULT_PORTS = { free_lane_count, ready_issues };
|
|
429
|
+
async function read_ready(ports = DEFAULT_PORTS) {
|
|
430
|
+
const free_lanes2 = await ports.free_lane_count();
|
|
431
|
+
if (free_lanes2 <= NO_FREE) return { issues: [], free_lanes: free_lanes2 };
|
|
432
|
+
return { issues: await ports.ready_issues(), free_lanes: free_lanes2 };
|
|
433
|
+
}
|
|
434
|
+
function ready_line(reading) {
|
|
435
|
+
if (reading.issues.length === NONE2 || reading.free_lanes <= NO_FREE) return void 0;
|
|
436
|
+
const issues = reading.issues.map((issue) => `#${issue}`).join(" ");
|
|
437
|
+
return `ready ${issues} \xB7 free lanes ${String(reading.free_lanes)}`;
|
|
438
|
+
}
|
|
439
|
+
async function parent_ready_line(ports, is_parent) {
|
|
440
|
+
if (!await is_parent()) return void 0;
|
|
441
|
+
return ready_line(await read_ready(ports));
|
|
442
|
+
}
|
|
443
|
+
async function print_ready_line(ports = DEFAULT_PORTS, is_parent = run_headless.is_backlog_parent) {
|
|
444
|
+
try {
|
|
445
|
+
const line = await parent_ready_line(ports, is_parent);
|
|
446
|
+
if (line !== void 0) console.info(line);
|
|
447
|
+
} catch {
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
var OFFER_HINT = "\u21BB backlogrun parent: a child just entered an epic \u2014 run `pnpm josh backlog:offer` next, so a runnable filing is dispatched now rather than on the next wake.";
|
|
451
|
+
async function print_offer_hint(is_parent = run_headless.is_backlog_parent) {
|
|
452
|
+
try {
|
|
453
|
+
if (await is_parent()) console.info(OFFER_HINT);
|
|
454
|
+
} catch {
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
var backlog_ready = {
|
|
458
|
+
DEFAULT_PORTS,
|
|
459
|
+
OFFER_HINT,
|
|
460
|
+
read_backlog_next,
|
|
461
|
+
print_offer_hint,
|
|
462
|
+
free_lane_count,
|
|
463
|
+
drains_pool,
|
|
464
|
+
print_ready_line,
|
|
465
|
+
read_ready,
|
|
466
|
+
ready_issues,
|
|
467
|
+
ready_line
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
// scripts/gh/gh-spawn.ts
|
|
471
|
+
import { execaSync } from "execa";
|
|
472
|
+
function fetch_repo_name(timeout_ms) {
|
|
473
|
+
const result = execaSync("gh", ["api", git_gh_api_path.repo_api_path(), "--jq", ".full_name"], {
|
|
474
|
+
...git_gh_exec.direct_environment(),
|
|
475
|
+
cwd: PROJECT_ROOT,
|
|
476
|
+
reject: false,
|
|
477
|
+
...timeout_ms !== void 0 && { timeout: timeout_ms }
|
|
478
|
+
});
|
|
479
|
+
if (result.exitCode !== 0 || !result.stdout) return void 0;
|
|
480
|
+
return result.stdout.trim() || void 0;
|
|
481
|
+
}
|
|
482
|
+
function get_repo_name_with_owner() {
|
|
483
|
+
return fetch_repo_name(void 0);
|
|
484
|
+
}
|
|
485
|
+
function get_repo_name_with_owner_within(timeout_ms) {
|
|
486
|
+
return fetch_repo_name(timeout_ms);
|
|
487
|
+
}
|
|
488
|
+
var gh_spawn = { get_repo_name_with_owner, get_repo_name_with_owner_within };
|
|
489
|
+
|
|
490
|
+
// scripts/git/telegram-notify.ts
|
|
491
|
+
import { z as z2 } from "zod";
|
|
492
|
+
var TELEGRAM_API_BASE = "https://api.telegram.org";
|
|
493
|
+
var telegram_environment_schema = z2.object({
|
|
494
|
+
telegram_bot_token: z2.string().min(1, { message: "TELEGRAM_BOT_TOKEN is required" }),
|
|
495
|
+
telegram_chat_id: z2.string().min(1, { message: "TELEGRAM_CHAT_ID is required" })
|
|
496
|
+
});
|
|
497
|
+
var TASK_DEFINITIONS = {
|
|
498
|
+
planning: { icon: "\u{1F4CB}", label: "Planning" },
|
|
499
|
+
completion: { icon: "\u2705", label: "Completion" },
|
|
500
|
+
failure: { icon: "\u274C", label: "Failure" },
|
|
501
|
+
warning: { icon: "\u26A0\uFE0F", label: "Completed with a warning" },
|
|
502
|
+
kickoff_retry: { icon: "\u{1F504}", label: "Kickoff retry" },
|
|
503
|
+
confirmation: { icon: "\u23F8\uFE0F", label: "Confirmation required" },
|
|
504
|
+
stalled: { icon: "\u23F3", label: "Ready work is sitting undispatched" },
|
|
505
|
+
stranded: { icon: "\u{1F6A8}", label: "Run stranded \u2014 nobody is driving it" }
|
|
506
|
+
};
|
|
507
|
+
var NOT_CONFIGURED_PREFIX = "Telegram is not configured";
|
|
508
|
+
var SEND_FAILED_PREFIX = "Telegram notification failed";
|
|
509
|
+
var REDACTED = "<redacted>";
|
|
510
|
+
var UNKNOWN_ERROR_TEXT = "unknown error";
|
|
511
|
+
function parse_environment_string(value) {
|
|
512
|
+
return value?.trim() ?? "";
|
|
513
|
+
}
|
|
514
|
+
function join_cause(error) {
|
|
515
|
+
const { cause } = error;
|
|
516
|
+
if (!(cause instanceof Error) || cause.message.length === 0) return error.message;
|
|
517
|
+
return `${error.message}: ${cause.message}`;
|
|
518
|
+
}
|
|
519
|
+
function describe_non_error(error) {
|
|
520
|
+
return typeof error === "string" ? error : UNKNOWN_ERROR_TEXT;
|
|
521
|
+
}
|
|
522
|
+
function describe_error(error) {
|
|
523
|
+
if (error instanceof Error) return join_cause(error);
|
|
524
|
+
return describe_non_error(error);
|
|
525
|
+
}
|
|
526
|
+
function describe_symptom(error) {
|
|
527
|
+
return error instanceof Error ? error.message : describe_non_error(error);
|
|
528
|
+
}
|
|
529
|
+
function redact_credentials(text2, config) {
|
|
530
|
+
return text2.split(config.bot_token).join(REDACTED).split(config.chat_id).join(REDACTED);
|
|
531
|
+
}
|
|
532
|
+
function load_config() {
|
|
533
|
+
const result = telegram_environment_schema.safeParse({
|
|
534
|
+
telegram_bot_token: parse_environment_string(process.env["TELEGRAM_BOT_TOKEN"]),
|
|
535
|
+
telegram_chat_id: parse_environment_string(process.env["TELEGRAM_CHAT_ID"])
|
|
536
|
+
});
|
|
537
|
+
if (!result.success) {
|
|
538
|
+
const error_list = result.error.issues.map((issue) => issue.message).join(", ");
|
|
539
|
+
throw new Error(`${NOT_CONFIGURED_PREFIX}: ${error_list}`);
|
|
540
|
+
}
|
|
541
|
+
return { bot_token: result.data.telegram_bot_token, chat_id: result.data.telegram_chat_id };
|
|
542
|
+
}
|
|
543
|
+
function build_header(task_type, repo_name) {
|
|
544
|
+
const { icon, label: label2 } = TASK_DEFINITIONS[task_type];
|
|
545
|
+
if (repo_name === void 0 || repo_name.length === 0) return `${icon} ${label2}`;
|
|
546
|
+
return `${icon} ${repo_name}: ${label2}`;
|
|
547
|
+
}
|
|
548
|
+
function push_if_present(target, value) {
|
|
549
|
+
if (value !== void 0 && value.length > 0) target.push(value);
|
|
550
|
+
}
|
|
551
|
+
function build_title_block(input) {
|
|
552
|
+
const lines = [build_header(input.task_type, input.repo_name)];
|
|
553
|
+
push_if_present(lines, input.issue_title);
|
|
554
|
+
return lines.join("\n");
|
|
555
|
+
}
|
|
556
|
+
function append_url(parts, label2, value) {
|
|
557
|
+
if (value !== void 0 && value.length > 0) parts.push(`${label2}: ${value}`);
|
|
558
|
+
}
|
|
559
|
+
function build_url_parts(input) {
|
|
560
|
+
const parts = [];
|
|
561
|
+
append_url(parts, "Issue", input.issue_url);
|
|
562
|
+
append_url(parts, "PR", input.pr_url);
|
|
563
|
+
return parts;
|
|
564
|
+
}
|
|
565
|
+
function build_blocks(input) {
|
|
566
|
+
const blocks = [build_title_block(input)];
|
|
567
|
+
push_if_present(blocks, input.body);
|
|
568
|
+
blocks.push(...build_url_parts(input));
|
|
569
|
+
return blocks;
|
|
570
|
+
}
|
|
571
|
+
function build_text(input) {
|
|
572
|
+
return build_blocks(input).join("\n\n");
|
|
573
|
+
}
|
|
574
|
+
async function post_message(config, text2) {
|
|
575
|
+
const url = `${TELEGRAM_API_BASE}/bot${config.bot_token}/sendMessage`;
|
|
576
|
+
const response = await fetch(url, {
|
|
577
|
+
method: "POST",
|
|
578
|
+
headers: { "Content-Type": "application/json" },
|
|
579
|
+
body: JSON.stringify({ chat_id: config.chat_id, text: text2 })
|
|
580
|
+
});
|
|
581
|
+
if (!response.ok) {
|
|
582
|
+
throw new Error(`Telegram API error: ${String(response.status)} ${response.statusText}`);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function build_send_failure(error, config) {
|
|
586
|
+
const reason = redact_credentials(describe_error(error), config);
|
|
587
|
+
return new Error(`${SEND_FAILED_PREFIX}: ${reason}`, { cause: new Error(reason) });
|
|
588
|
+
}
|
|
589
|
+
async function send(input) {
|
|
590
|
+
const config = load_config();
|
|
591
|
+
const text2 = build_text(input);
|
|
592
|
+
try {
|
|
593
|
+
await post_message(config, text2);
|
|
594
|
+
} catch (error) {
|
|
595
|
+
throw build_send_failure(error, config);
|
|
596
|
+
}
|
|
597
|
+
console.info("\u{1F4F1} Telegram notification sent.");
|
|
598
|
+
}
|
|
599
|
+
function report_send_failure(error, recovery) {
|
|
600
|
+
console.error("");
|
|
601
|
+
console.error(`\u2757 ${describe_symptom(error)}`);
|
|
602
|
+
console.error(" Nobody was notified, and the run carried on.");
|
|
603
|
+
if (recovery !== void 0) console.error(` Recovery: ${recovery}`);
|
|
604
|
+
console.error("");
|
|
605
|
+
}
|
|
606
|
+
async function send_or_report(input, recovery) {
|
|
607
|
+
try {
|
|
608
|
+
await send(input);
|
|
609
|
+
return true;
|
|
610
|
+
} catch (error) {
|
|
611
|
+
report_send_failure(error, recovery);
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
var REPO_LOOKUP_TIMEOUT_MS = 5e3;
|
|
616
|
+
async function warn(input) {
|
|
617
|
+
return await send_or_report(
|
|
618
|
+
{
|
|
619
|
+
task_type: "warning",
|
|
620
|
+
repo_name: gh_spawn.get_repo_name_with_owner_within(REPO_LOOKUP_TIMEOUT_MS),
|
|
621
|
+
issue_title: input.issue_title,
|
|
622
|
+
body: input.body,
|
|
623
|
+
issue_url: void 0,
|
|
624
|
+
pr_url: void 0
|
|
625
|
+
},
|
|
626
|
+
input.recovery
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
async function confirm(input) {
|
|
630
|
+
return await send_or_report(
|
|
631
|
+
{
|
|
632
|
+
task_type: "confirmation",
|
|
633
|
+
repo_name: gh_spawn.get_repo_name_with_owner_within(REPO_LOOKUP_TIMEOUT_MS),
|
|
634
|
+
issue_title: input.issue_title,
|
|
635
|
+
body: input.body,
|
|
636
|
+
issue_url: void 0,
|
|
637
|
+
pr_url: void 0
|
|
638
|
+
},
|
|
639
|
+
input.recovery
|
|
640
|
+
);
|
|
641
|
+
}
|
|
642
|
+
async function stalled(input) {
|
|
643
|
+
return await send_or_report(
|
|
644
|
+
{
|
|
645
|
+
task_type: "stalled",
|
|
646
|
+
repo_name: gh_spawn.get_repo_name_with_owner_within(REPO_LOOKUP_TIMEOUT_MS),
|
|
647
|
+
issue_title: void 0,
|
|
648
|
+
body: input.body,
|
|
649
|
+
issue_url: void 0,
|
|
650
|
+
pr_url: void 0
|
|
651
|
+
},
|
|
652
|
+
input.recovery
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
async function stranded(input) {
|
|
656
|
+
return await send_or_report(
|
|
657
|
+
{
|
|
658
|
+
task_type: "stranded",
|
|
659
|
+
repo_name: gh_spawn.get_repo_name_with_owner_within(REPO_LOOKUP_TIMEOUT_MS),
|
|
660
|
+
issue_title: void 0,
|
|
661
|
+
body: input.body,
|
|
662
|
+
issue_url: void 0,
|
|
663
|
+
pr_url: void 0
|
|
664
|
+
},
|
|
665
|
+
input.recovery
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
var telegram_notify = {
|
|
669
|
+
REPO_LOOKUP_TIMEOUT_MS,
|
|
670
|
+
confirm,
|
|
671
|
+
send,
|
|
672
|
+
send_or_report,
|
|
673
|
+
stalled,
|
|
674
|
+
stranded,
|
|
675
|
+
warn
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
// scripts/run/run-event-scope.ts
|
|
679
|
+
var SINCE_SCOPE = "since";
|
|
680
|
+
var UNKNOWN_SCOPE = "unknown";
|
|
681
|
+
var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
|
|
682
|
+
function moment_of(at) {
|
|
683
|
+
const parsed = Date.parse(at);
|
|
684
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
685
|
+
}
|
|
686
|
+
function is_within(event, floor) {
|
|
687
|
+
const at = moment_of(event.at);
|
|
688
|
+
return at !== void 0 && at >= floor;
|
|
689
|
+
}
|
|
690
|
+
function scoped_events(events, scope) {
|
|
691
|
+
if (scope.kind === UNKNOWN_SCOPE) return void 0;
|
|
692
|
+
const floor = moment_of(scope.started_at);
|
|
693
|
+
if (floor === void 0) return void 0;
|
|
694
|
+
return events.filter((event) => is_within(event, floor));
|
|
695
|
+
}
|
|
696
|
+
function scope_of(read) {
|
|
697
|
+
if (read.kind === "carried" || read.kind === "expired") {
|
|
698
|
+
return { kind: SINCE_SCOPE, started_at: read.carry.started_at };
|
|
699
|
+
}
|
|
700
|
+
return UNKNOWN_EVENT_SCOPE;
|
|
701
|
+
}
|
|
702
|
+
function last_scoped_event(events, scope) {
|
|
703
|
+
return scoped_events(events, scope)?.findLast(
|
|
704
|
+
(event) => !run_event_stream.TRACE_KINDS.has(event.kind)
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
var SHIP_POSITION_KINDS = /* @__PURE__ */ new Set([
|
|
708
|
+
run_event_stream.EVENT_KIND.SHIP_LAUNCH,
|
|
709
|
+
run_event_stream.EVENT_KIND.SHIP_STOP
|
|
710
|
+
]);
|
|
711
|
+
function is_foreign_ship_event(event, issue) {
|
|
712
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`#${issue} `);
|
|
713
|
+
}
|
|
714
|
+
function is_own_ship_event(event, issue) {
|
|
715
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue);
|
|
716
|
+
}
|
|
717
|
+
function last_issue_event(events, scope, issue) {
|
|
718
|
+
const own = events.filter((event) => !is_foreign_ship_event(event, issue));
|
|
719
|
+
if (scope.kind === SINCE_SCOPE) return last_scoped_event(own, scope);
|
|
720
|
+
return own.findLast((event) => is_own_ship_event(event, issue));
|
|
721
|
+
}
|
|
722
|
+
var run_event_scope = {
|
|
723
|
+
UNKNOWN_EVENT_SCOPE,
|
|
724
|
+
last_issue_event,
|
|
725
|
+
last_scoped_event,
|
|
726
|
+
scope_of,
|
|
727
|
+
scoped_events
|
|
728
|
+
};
|
|
729
|
+
|
|
730
|
+
// scripts/run/run-event-stream-emit.ts
|
|
731
|
+
function now_iso() {
|
|
732
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
733
|
+
}
|
|
734
|
+
async function stream_target() {
|
|
735
|
+
const repository = await run_carry.repository_directory();
|
|
736
|
+
return repository === void 0 ? void 0 : run_event_stream.target_of(repository);
|
|
737
|
+
}
|
|
738
|
+
async function emit(kind, text2) {
|
|
739
|
+
try {
|
|
740
|
+
const target = await stream_target();
|
|
741
|
+
if (target === void 0) return;
|
|
742
|
+
run_event_stream.append(target, kind, text2, now_iso());
|
|
743
|
+
} catch {
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
async function emit_once(kind, text2) {
|
|
747
|
+
try {
|
|
748
|
+
const target = await stream_target();
|
|
749
|
+
if (target === void 0 || run_event_stream.read_last(target)?.kind === kind) return false;
|
|
750
|
+
return run_event_stream.append(target, kind, text2, now_iso()).appended;
|
|
751
|
+
} catch {
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
function invocation_events(repository, target) {
|
|
756
|
+
const events = run_event_stream.read_events(target);
|
|
757
|
+
const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository)));
|
|
758
|
+
return run_event_scope.scoped_events(events, scope) ?? events;
|
|
759
|
+
}
|
|
760
|
+
async function emit_once_since(kind, text2, reset_kind) {
|
|
761
|
+
try {
|
|
762
|
+
const repository = await run_carry.repository_directory();
|
|
763
|
+
if (repository === void 0) return false;
|
|
764
|
+
const target = run_event_stream.target_of(repository);
|
|
765
|
+
if (run_event_stream.has_since(invocation_events(repository, target), kind, reset_kind)) {
|
|
766
|
+
return false;
|
|
767
|
+
}
|
|
768
|
+
return run_event_stream.append(target, kind, text2, now_iso()).appended;
|
|
769
|
+
} catch {
|
|
770
|
+
return false;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
async function emit_heartbeat(line) {
|
|
774
|
+
await emit(run_event_stream.EVENT_KIND.HEARTBEAT, line);
|
|
775
|
+
}
|
|
776
|
+
async function current_events() {
|
|
777
|
+
try {
|
|
778
|
+
const repository = await run_carry.repository_directory();
|
|
779
|
+
if (repository === void 0) return [];
|
|
780
|
+
const read = run_carry.read_carry(run_carry.carry_path(repository));
|
|
781
|
+
const scope = run_event_scope.scope_of(read);
|
|
782
|
+
const events = run_event_stream.read_events(run_event_stream.target_of(repository));
|
|
783
|
+
return run_event_scope.scoped_events(events, scope) ?? [];
|
|
784
|
+
} catch {
|
|
785
|
+
return [];
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
var run_event_stream_emit = {
|
|
789
|
+
current_events,
|
|
790
|
+
emit,
|
|
791
|
+
emit_heartbeat,
|
|
792
|
+
emit_once,
|
|
793
|
+
emit_once_since,
|
|
794
|
+
stream_target
|
|
795
|
+
};
|
|
796
|
+
|
|
797
|
+
// scripts/backlog/backlog-stalled-detect.ts
|
|
798
|
+
var NO_FREE2 = 0;
|
|
799
|
+
var NO_READY = 0;
|
|
800
|
+
var NO_AGE = 0;
|
|
801
|
+
var STALL_RECOVERY = "Dispatch the ready work with `pnpm josh backlog:next`.";
|
|
802
|
+
function ready_count_of(ready) {
|
|
803
|
+
return async function() {
|
|
804
|
+
const issues = await ready.ready_issues();
|
|
805
|
+
return issues.length;
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
async function real_emit_stall(text2) {
|
|
809
|
+
const { STALL, CHILD_LAUNCH } = run_event_stream.EVENT_KIND;
|
|
810
|
+
return await run_event_stream_emit.emit_once_since(STALL, text2, CHILD_LAUNCH);
|
|
811
|
+
}
|
|
812
|
+
async function real_notify_stalled(body) {
|
|
813
|
+
return await telegram_notify.stalled({ body, recovery: STALL_RECOVERY });
|
|
814
|
+
}
|
|
815
|
+
function ports_over(ready) {
|
|
816
|
+
return {
|
|
817
|
+
resolve_target: run_event_stream_emit.stream_target,
|
|
818
|
+
read_events: run_event_stream.read_events,
|
|
819
|
+
now_ms: () => Date.now(),
|
|
820
|
+
free_lane_count: ready.free_lane_count,
|
|
821
|
+
ready_count: ready_count_of(ready),
|
|
822
|
+
emit_stall: real_emit_stall,
|
|
823
|
+
notify_stalled: real_notify_stalled
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
var DEFAULT_PORTS2 = ports_over(backlog_ready.DEFAULT_PORTS);
|
|
827
|
+
function ok_reading(dispatch_age_ms2) {
|
|
828
|
+
return { ready_count: NO_READY, free_lanes: NO_FREE2, dispatch_age_ms: dispatch_age_ms2 };
|
|
829
|
+
}
|
|
830
|
+
async function probe_reading(ports, dispatch_age_ms2) {
|
|
831
|
+
const free_lanes2 = await ports.free_lane_count();
|
|
832
|
+
if (free_lanes2 <= NO_FREE2) return { ready_count: NO_READY, free_lanes: free_lanes2, dispatch_age_ms: dispatch_age_ms2 };
|
|
833
|
+
return { ready_count: await ports.ready_count(), free_lanes: free_lanes2, dispatch_age_ms: dispatch_age_ms2 };
|
|
834
|
+
}
|
|
835
|
+
async function gather(ports, threshold_ms) {
|
|
836
|
+
const target = await ports.resolve_target();
|
|
837
|
+
if (target === void 0) return void 0;
|
|
838
|
+
const age = backlog_stalled.dispatch_age_ms(ports.read_events(target), ports.now_ms());
|
|
839
|
+
if (age === void 0) return ok_reading(NO_AGE);
|
|
840
|
+
if (age <= threshold_ms) return ok_reading(age);
|
|
841
|
+
return await probe_reading(ports, age);
|
|
842
|
+
}
|
|
843
|
+
async function report(ports, reading) {
|
|
844
|
+
const text2 = backlog_stalled.describe(reading);
|
|
845
|
+
if (await ports.emit_stall(text2)) await ports.notify_stalled(text2);
|
|
846
|
+
}
|
|
847
|
+
async function detect_and_report(ports = DEFAULT_PORTS2, threshold_ms = backlog_stalled.STALL_THRESHOLD_MS) {
|
|
848
|
+
const reading = await gather(ports, threshold_ms);
|
|
849
|
+
const verdict = backlog_stalled.assess(reading, threshold_ms);
|
|
850
|
+
if (reading !== void 0 && verdict === backlog_stalled.STALLED) await report(ports, reading);
|
|
851
|
+
return verdict;
|
|
852
|
+
}
|
|
853
|
+
async function run_stall_check(ready = backlog_ready.DEFAULT_PORTS) {
|
|
854
|
+
try {
|
|
855
|
+
await detect_and_report(ports_over(ready));
|
|
856
|
+
} catch {
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
var backlog_stalled_detect = { DEFAULT_PORTS: DEFAULT_PORTS2, detect_and_report, gather, report, run_stall_check };
|
|
860
|
+
|
|
861
|
+
// scripts/rules/stop-rules.ts
|
|
862
|
+
import { z as z3 } from "zod";
|
|
863
|
+
|
|
864
|
+
// scripts/issue/issue-cite.ts
|
|
865
|
+
var GITHUB_URL_PREFIX = "https://github.com/";
|
|
866
|
+
var ISSUE_PATH = "/issues/";
|
|
867
|
+
var SUMMARY_SEPARATOR = " \u2014 ";
|
|
868
|
+
var REPO_QUALIFIED = /^([^\s/#]+\/[^\s/#]+)#(\d+)$/u;
|
|
869
|
+
var BARE_NUMBER = /^#?(\d+)$/u;
|
|
870
|
+
function issue_url(slug, number) {
|
|
871
|
+
return `${GITHUB_URL_PREFIX}${slug}${ISSUE_PATH}${number}`;
|
|
872
|
+
}
|
|
873
|
+
function citation_line(slug, number, summary) {
|
|
874
|
+
return `[#${number}](${issue_url(slug, number)})${SUMMARY_SEPARATOR}${summary}`;
|
|
875
|
+
}
|
|
876
|
+
function qualified_target(token) {
|
|
877
|
+
const match = REPO_QUALIFIED.exec(token);
|
|
878
|
+
if (match === null) return void 0;
|
|
879
|
+
const [, repo = "", number = ""] = match;
|
|
880
|
+
return { number, repo };
|
|
881
|
+
}
|
|
882
|
+
function bare_target(token, default_repo) {
|
|
883
|
+
const match = BARE_NUMBER.exec(token);
|
|
884
|
+
if (match === null) return void 0;
|
|
885
|
+
const [, number = ""] = match;
|
|
886
|
+
return { number, repo: default_repo };
|
|
887
|
+
}
|
|
888
|
+
function parse_target(token, default_repo) {
|
|
889
|
+
return qualified_target(token) ?? bare_target(token, default_repo);
|
|
890
|
+
}
|
|
891
|
+
function label(target) {
|
|
892
|
+
return target.repo === void 0 ? `#${target.number}` : `${target.repo}#${target.number}`;
|
|
893
|
+
}
|
|
894
|
+
function missing_line(target) {
|
|
895
|
+
return `\u2716 ${label(target)}: issue does not resolve \u2014 check the number and the repository`;
|
|
896
|
+
}
|
|
897
|
+
function unreadable_line(target) {
|
|
898
|
+
return `\u2716 ${label(target)}: could not be read \u2014 a rate limit, expired auth, or a dropped connection`;
|
|
899
|
+
}
|
|
900
|
+
function no_repo_line(target) {
|
|
901
|
+
return `\u2716 ${label(target)}: could not read this repository \u2014 check gh auth and the origin remote`;
|
|
902
|
+
}
|
|
903
|
+
var issue_cite = {
|
|
904
|
+
SUMMARY_SEPARATOR,
|
|
905
|
+
citation_line,
|
|
906
|
+
issue_url,
|
|
907
|
+
label,
|
|
908
|
+
missing_line,
|
|
909
|
+
no_repo_line,
|
|
910
|
+
parse_target,
|
|
911
|
+
unreadable_line
|
|
912
|
+
};
|
|
913
|
+
|
|
914
|
+
// scripts/rules/issue-citation.ts
|
|
915
|
+
var ISSUE_NUMBER = /#\d+/gu;
|
|
916
|
+
var REFERENCE_BOUNDARY = /[\s#()[\]<>|]/u;
|
|
917
|
+
var OWNER_REPO = /^[^\s/#]+\/[^\s/#]+$/u;
|
|
918
|
+
var MARKDOWN_LINK = /\[([^[\]]*)\]\([^()]*\)/gu;
|
|
919
|
+
var FENCE_MARKER = /^\s*(?:`{3,}|~{3,})/u;
|
|
920
|
+
var QUOTE_LINE = /^\s*>/u;
|
|
921
|
+
var PR_PREFIX = /\b(?:pr|pull request)\s*$/iu;
|
|
922
|
+
var BACKTICK_PAIR = 2;
|
|
923
|
+
function text_span_covers(link, index) {
|
|
924
|
+
const start = (link.index ?? 0) + 1;
|
|
925
|
+
const end = start + (link[1] ?? "").length;
|
|
926
|
+
return index >= start && index < end;
|
|
927
|
+
}
|
|
928
|
+
function is_linked_at(line, index) {
|
|
929
|
+
for (const link of line.matchAll(MARKDOWN_LINK)) {
|
|
930
|
+
if (text_span_covers(link, index)) return true;
|
|
931
|
+
}
|
|
932
|
+
return false;
|
|
933
|
+
}
|
|
934
|
+
function repo_prefix(message, hash_index) {
|
|
935
|
+
let start = hash_index;
|
|
936
|
+
while (start > 0 && !REFERENCE_BOUNDARY.test(message.charAt(start - 1))) start -= 1;
|
|
937
|
+
const token = message.slice(start, hash_index);
|
|
938
|
+
return OWNER_REPO.test(token) ? token : "";
|
|
939
|
+
}
|
|
940
|
+
function is_inline_code_at(line, index) {
|
|
941
|
+
const backticks = line.slice(0, index).split("`").length - 1;
|
|
942
|
+
return backticks % BACKTICK_PAIR === 1;
|
|
943
|
+
}
|
|
944
|
+
function is_bare_at(line, index) {
|
|
945
|
+
if (is_linked_at(line, index) || is_inline_code_at(line, index)) return false;
|
|
946
|
+
return !PR_PREFIX.test(line.slice(0, index));
|
|
947
|
+
}
|
|
948
|
+
function line_references(line) {
|
|
949
|
+
const references = [];
|
|
950
|
+
for (const match of line.matchAll(ISSUE_NUMBER)) {
|
|
951
|
+
const { index } = match;
|
|
952
|
+
if (is_bare_at(line, index)) {
|
|
953
|
+
references.push({ index, prefix: repo_prefix(line, index), text: match[0] });
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return references;
|
|
957
|
+
}
|
|
958
|
+
function collect_line_references(line, found) {
|
|
959
|
+
for (const reference of line_references(line)) found.push(`${reference.prefix}${reference.text}`);
|
|
960
|
+
}
|
|
961
|
+
function lines_outside_fences(message) {
|
|
962
|
+
const lines = [];
|
|
963
|
+
let is_in_fence = false;
|
|
964
|
+
for (const line of message.split("\n")) {
|
|
965
|
+
if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
|
|
966
|
+
else if (!is_in_fence) lines.push(line);
|
|
967
|
+
}
|
|
968
|
+
return lines;
|
|
969
|
+
}
|
|
970
|
+
function prose_lines(message) {
|
|
971
|
+
return lines_outside_fences(message).filter((line) => !QUOTE_LINE.test(line));
|
|
972
|
+
}
|
|
973
|
+
function bare_references(message) {
|
|
974
|
+
const found = [];
|
|
975
|
+
for (const line of prose_lines(message)) collect_line_references(line, found);
|
|
976
|
+
return [...new Set(found)];
|
|
977
|
+
}
|
|
978
|
+
function has_bare_reference(message) {
|
|
979
|
+
return bare_references(message).length > 0;
|
|
980
|
+
}
|
|
981
|
+
function cite_argument(reference) {
|
|
982
|
+
return reference.startsWith("#") ? reference.slice(1) : reference;
|
|
983
|
+
}
|
|
984
|
+
function cite_arguments(references) {
|
|
985
|
+
return references.map((reference) => cite_argument(reference));
|
|
986
|
+
}
|
|
987
|
+
function reference_link(reference, default_slug) {
|
|
988
|
+
const slug = reference.prefix === "" ? default_slug : reference.prefix;
|
|
989
|
+
const number = reference.text.slice(1);
|
|
990
|
+
return `[${reference.prefix}${reference.text}](${issue_cite.issue_url(slug, number)})`;
|
|
991
|
+
}
|
|
992
|
+
function linkify_line(line, slug) {
|
|
993
|
+
let result = "";
|
|
994
|
+
let cursor = 0;
|
|
995
|
+
for (const reference of line_references(line)) {
|
|
996
|
+
const start = reference.index - reference.prefix.length;
|
|
997
|
+
result += line.slice(cursor, start) + reference_link(reference, slug);
|
|
998
|
+
cursor = reference.index + reference.text.length;
|
|
999
|
+
}
|
|
1000
|
+
return result + line.slice(cursor);
|
|
1001
|
+
}
|
|
1002
|
+
function rewrite_line(line, slug, is_in_fence) {
|
|
1003
|
+
if (is_in_fence || FENCE_MARKER.test(line) || QUOTE_LINE.test(line)) return line;
|
|
1004
|
+
return linkify_line(line, slug);
|
|
1005
|
+
}
|
|
1006
|
+
function linkify(message, slug) {
|
|
1007
|
+
const out = [];
|
|
1008
|
+
let is_in_fence = false;
|
|
1009
|
+
for (const line of message.split("\n")) {
|
|
1010
|
+
if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
|
|
1011
|
+
out.push(rewrite_line(line, slug, is_in_fence));
|
|
1012
|
+
}
|
|
1013
|
+
return out.join("\n");
|
|
1014
|
+
}
|
|
1015
|
+
var issue_citation = { bare_references, cite_arguments, has_bare_reference, linkify, prose_lines };
|
|
1016
|
+
|
|
1017
|
+
// scripts/rules/filing-offer.ts
|
|
1018
|
+
var OFFER_PATTERNS = [
|
|
1019
|
+
/起票(?:して)?(?:も)?(?:よければ|よろしければ|よいですか|良いですか|よろしいですか|いいですか)/u,
|
|
1020
|
+
/起票(?:しましょうか|しますか|するのが妥当|すべきだと|すべきと|を提案|をご提案)/u,
|
|
1021
|
+
/Issue\s*[化に](?:しましょうか|しますか|してよければ)/iu,
|
|
1022
|
+
/\b(?:shall|should)\s+I\s+(?:file|open|raise)\b/iu,
|
|
1023
|
+
/\b(?:want|like)\s+me\s+to\s+(?:file|open|raise)\b/iu,
|
|
1024
|
+
/\blet\s+me\s+know\s+if\s+you\s+(?:want|would\s+like)\s+(?:me\s+to\s+file|it\s+filed)\b/iu
|
|
1025
|
+
];
|
|
1026
|
+
var GITHUB_URL_OWNER = /github\.com\/([\w.-]+)\//gu;
|
|
1027
|
+
var OWNER_SEPARATOR = "/";
|
|
1028
|
+
function is_offer_line(line) {
|
|
1029
|
+
return OFFER_PATTERNS.some((pattern) => pattern.test(line));
|
|
1030
|
+
}
|
|
1031
|
+
function offers_filing(message) {
|
|
1032
|
+
return issue_citation.prose_lines(message).some((line) => is_offer_line(line));
|
|
1033
|
+
}
|
|
1034
|
+
function url_owners(message) {
|
|
1035
|
+
return [...message.matchAll(GITHUB_URL_OWNER)].map((match) => match[1] ?? "");
|
|
1036
|
+
}
|
|
1037
|
+
function qualified_owners(message) {
|
|
1038
|
+
return issue_citation.bare_references(message).filter((reference) => reference.includes(OWNER_SEPARATOR)).map((reference) => reference.split(OWNER_SEPARATOR)[0] ?? "");
|
|
1039
|
+
}
|
|
1040
|
+
function mentioned_owners(message) {
|
|
1041
|
+
return [...url_owners(message), ...qualified_owners(message)];
|
|
1042
|
+
}
|
|
1043
|
+
function is_first_party_target(message, session_owner) {
|
|
1044
|
+
if (session_owner === void 0) return false;
|
|
1045
|
+
return mentioned_owners(message).every(
|
|
1046
|
+
(owner) => repo_party.classify(session_owner, owner) === repo_party.FIRST_PARTY
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
var filing_offer = { is_first_party_target, mentioned_owners, offers_filing };
|
|
1050
|
+
|
|
1051
|
+
// scripts/rules/reply-language.ts
|
|
1052
|
+
var LATIN_SCRIPT = "Latn";
|
|
1053
|
+
var COMPOUND_SCRIPTS = {
|
|
1054
|
+
Jpan: ["Hira", "Kana", "Hani"],
|
|
1055
|
+
Kore: ["Hang", "Hani"],
|
|
1056
|
+
Hans: ["Hani"],
|
|
1057
|
+
Hant: ["Hani"]
|
|
1058
|
+
};
|
|
1059
|
+
var MIN_PROSE_LETTERS = 20;
|
|
1060
|
+
var MATCH_SHARE_FLOOR = 0.5;
|
|
1061
|
+
var MIN_VOTING_LETTERS = 8;
|
|
1062
|
+
var CODE_PATTERNS = [
|
|
1063
|
+
/```[\s\S]*?(?:```|$)/gu,
|
|
1064
|
+
/`[^`\n]*`/gu,
|
|
1065
|
+
/\]\([^)\s]*\)/gu,
|
|
1066
|
+
/https?:\/\/\S+/gu
|
|
1067
|
+
];
|
|
1068
|
+
var ASCII_RUN_PATTERN = /[!-~]+/gu;
|
|
1069
|
+
var LETTER_PATTERN = new RegExp("\\p{L}", "gu");
|
|
1070
|
+
var NON_LATIN_LETTER_PATTERN = new RegExp("(?![\\p{Script=Latn}\\p{Script=Common}\\p{Script=Inherited}])\\p{L}", "u");
|
|
1071
|
+
function script_of(lang) {
|
|
1072
|
+
try {
|
|
1073
|
+
return new Intl.Locale(lang).maximize().script;
|
|
1074
|
+
} catch {
|
|
1075
|
+
return void 0;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
function letter_pattern(script) {
|
|
1079
|
+
const scripts = COMPOUND_SCRIPTS[script] ?? [script];
|
|
1080
|
+
const classes = scripts.map((name) => String.raw`\p{Script=${name}}`).join("");
|
|
1081
|
+
try {
|
|
1082
|
+
return new RegExp(`[${classes}]`, "u");
|
|
1083
|
+
} catch {
|
|
1084
|
+
return void 0;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
function prose_of(message) {
|
|
1088
|
+
let text2 = message;
|
|
1089
|
+
for (const pattern of CODE_PATTERNS) text2 = text2.replaceAll(pattern, " ");
|
|
1090
|
+
return text2.replaceAll(ASCII_RUN_PATTERN, (run) => run.includes("/") ? " " : run);
|
|
1091
|
+
}
|
|
1092
|
+
function letter_count(text2) {
|
|
1093
|
+
return text2.match(LETTER_PATTERN)?.length ?? 0;
|
|
1094
|
+
}
|
|
1095
|
+
function is_line_in_script(line, script, pattern) {
|
|
1096
|
+
if (script === LATIN_SCRIPT) return !NON_LATIN_LETTER_PATTERN.test(line);
|
|
1097
|
+
return pattern.test(line);
|
|
1098
|
+
}
|
|
1099
|
+
function voting_lines(prose) {
|
|
1100
|
+
const lines = prose.split("\n").filter((line) => letter_count(line) > 0);
|
|
1101
|
+
const voting = lines.filter((line) => letter_count(line) >= MIN_VOTING_LETTERS);
|
|
1102
|
+
return voting.length > 0 ? voting : lines;
|
|
1103
|
+
}
|
|
1104
|
+
function matches_share(prose, script, pattern) {
|
|
1105
|
+
const lines = voting_lines(prose);
|
|
1106
|
+
const matched = lines.filter((line) => is_line_in_script(line, script, pattern));
|
|
1107
|
+
return matched.length / lines.length;
|
|
1108
|
+
}
|
|
1109
|
+
function is_mismatch(message, lang) {
|
|
1110
|
+
const script = script_of(lang);
|
|
1111
|
+
if (script === void 0) return false;
|
|
1112
|
+
const pattern = letter_pattern(script);
|
|
1113
|
+
if (pattern === void 0) return false;
|
|
1114
|
+
const prose = prose_of(message);
|
|
1115
|
+
if (letter_count(prose) < MIN_PROSE_LETTERS) return false;
|
|
1116
|
+
return matches_share(prose, script, pattern) < MATCH_SHARE_FLOOR;
|
|
1117
|
+
}
|
|
1118
|
+
var reply_language = { MIN_PROSE_LETTERS, is_mismatch, script_of };
|
|
1119
|
+
|
|
1120
|
+
// scripts/rules/stop-rules.ts
|
|
1121
|
+
var SWITCH_ENV_KEY = "JOSH_STOP_GUARD";
|
|
1122
|
+
var BLOCK_DECISION = "block";
|
|
1123
|
+
var stop_payload_schema = z3.object({
|
|
1124
|
+
transcript_path: z3.string().min(1),
|
|
1125
|
+
stop_hook_active: z3.boolean().nullish(),
|
|
1126
|
+
last_assistant_message: z3.string().nullish()
|
|
1127
|
+
});
|
|
1128
|
+
var NO_OUTCOME = { reason: void 0 };
|
|
1129
|
+
var STOP_NOTIFY_REASON = '\u26D4 mid-workflow stop notification: this working tree is still held by a run and no `confirmation` Telegram was sent this turn, so a person is being left to wait off-screen without knowing the run paused. `CLAUDE.md` \u2192 "Mid-workflow stop notification" requires `pnpm josh notify --task-type confirmation --issue-url "<url>" --body=$\'<reason>\'` before any mid-workflow pause. Send it, then end with a one-line confirmation that it was sent \u2014 do not repeat your previous reply. This fires only while the hold is held and no notify is on the transcript, and `stop_hook_active` lets a second stop through so a run is never wedged.';
|
|
1130
|
+
var HOLD_RELEASE_REASON = "\u26D4 working-tree hold not released: this working tree is clean but its `run:hold` record is still in place, so the next run here runs `git switch main && git pull` believing the tree is free while you hold it. `.claude/skills/workflow-commands/SKILL.md` \u2192 \xA72f: a stop that leaves the tree clean releases the hold with `pnpm josh run:release <N>` (bare for a `new` entry). A `halfrun` pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty \u2014 this row is silent there. Release it, then end with a one-line confirmation that it was released \u2014 do not repeat your previous reply.";
|
|
1131
|
+
var ISSUE_CITATION_REASON = "Session-facing output cites an Issue as a number-link so the reader can click through and see which repository it is (`CLAUDE.md`, `prompts/collaboration-workflow/issue-citation.md`).";
|
|
1132
|
+
function build_citation_reason(references) {
|
|
1133
|
+
const numbers = references.join(", ");
|
|
1134
|
+
const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(" ")}`;
|
|
1135
|
+
return `\u26D4 issue citation: your reply names an Issue as a bare \`#N\` (${numbers}). Run \`${command}\` to print the paste-ready citation lines, then print the corrected citation lines alone \u2014 do not repeat your previous reply. ${ISSUE_CITATION_REASON}`;
|
|
1136
|
+
}
|
|
1137
|
+
var FILING_OFFER_REASON = '\u26D4 filing offer: your reply offers to file an Issue instead of filing it. Filing into a first-party repository is Tier A \u2014 the trigger is the judgement that it is worth filing, not the run\'s progress (`.claude/skills/workflow-commands/SKILL.md` \u2192 \xA72i, `observation-filing.md`). Run `pnpm josh issue:scout "<title>"`, file it, run `pnpm josh epic:bundle <new>`, then end with the one-line citation of what was filed \u2014 do not repeat your previous reply. If it is not worth filing after all, say so in one line instead.';
|
|
1138
|
+
var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
|
|
1139
|
+
var HEADLESS_REFUSAL_CAP = 3;
|
|
1140
|
+
var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress'];
|
|
1141
|
+
var HEADLESS_WAIT_BODY = ' this is a `claude -p` `backlogrun` parent (`JOSH_RUN_HEADLESS`) with lanes still in flight, and ending this turn ends the process \u2014 its background waits are killed with it and the lanes are left without a parent. Wait in the foreground instead: run `pnpm josh lane:await <N...>` for the in-flight lanes (and `pnpm josh run:progress --wait` for the heartbeat) as foreground commands within the tool timeout, act on what they report, and continue the loop. End the turn only after `pnpm josh run:carry --cut` or `--end` (`backlogrun-progress.md` \u2192 "The parent keeps no clock of its own").';
|
|
1142
|
+
var HEADLESS_WAIT_REASON = `${HEADLESS_WAIT_MARKER}${HEADLESS_WAIT_BODY}`;
|
|
1143
|
+
var INDEX_COMMAND_PATTERN = /git (?:add|stage|rm --cached|restore --staged|restore -S)\b/u;
|
|
1144
|
+
var PERMISSION_PATTERN = /許可|承認|permission|approve|approval|authorization/iu;
|
|
1145
|
+
var LANE_INDEX_REASON = '\u26D4 lane index permission: this is a dispatched lane child (`JOSH_LANE_CHILD`) and your reply asks a person for permission to change the git index. A lane is a per-run work tree with no person\'s staging to protect, and the sanctioned commit flow is already authorized: remove any conflict markers, then run `pnpm josh git -y`, which stages and commits them \u2014 a conflicted merge included. This is Tier A (`.claude/skills/workflow-commands/chain-rule.md` \u2192 "origin/main is merged in before the gate"). Do it and continue the run \u2014 do not repeat your previous reply.';
|
|
1146
|
+
function asks_index_permission(message) {
|
|
1147
|
+
return INDEX_COMMAND_PATTERN.test(message) && PERMISSION_PATTERN.test(message);
|
|
1148
|
+
}
|
|
1149
|
+
function needs_index_route(context) {
|
|
1150
|
+
return context.lane_child && asks_index_permission(context.message);
|
|
1151
|
+
}
|
|
1152
|
+
function language_note(lang) {
|
|
1153
|
+
return `Write your reply in the session language (JOSH_SESSION_LANG: ${lang}); code, commands and identifiers stay as they are.`;
|
|
1154
|
+
}
|
|
1155
|
+
function build_language_reason(lang) {
|
|
1156
|
+
return `\u26D4 session language: your reply is not written in the session language (JOSH_SESSION_LANG: ${lang}). Rewrite it in that language and keep writing in it on the turns that follow, whatever language a notification, tool output or hook message was in (\`CLAUDE.md\` \u2192 "Output language").`;
|
|
1157
|
+
}
|
|
1158
|
+
function language_reason(context) {
|
|
1159
|
+
if (!reply_language.is_mismatch(context.message, context.session_lang)) return void 0;
|
|
1160
|
+
return build_language_reason(context.session_lang);
|
|
1161
|
+
}
|
|
1162
|
+
function needs_filing(context) {
|
|
1163
|
+
if (context.filed || !filing_offer.offers_filing(context.message)) return false;
|
|
1164
|
+
return filing_offer.is_first_party_target(context.message, context.session_owner);
|
|
1165
|
+
}
|
|
1166
|
+
function needs_notify(context) {
|
|
1167
|
+
return context.hold_present && !context.notified;
|
|
1168
|
+
}
|
|
1169
|
+
function needs_release(context) {
|
|
1170
|
+
return context.hold_present && context.tree_clean;
|
|
1171
|
+
}
|
|
1172
|
+
function citation_reason(message) {
|
|
1173
|
+
const references = issue_citation.bare_references(message);
|
|
1174
|
+
if (references.length === 0) return void 0;
|
|
1175
|
+
return build_citation_reason(references);
|
|
1176
|
+
}
|
|
1177
|
+
function reply_reason(context) {
|
|
1178
|
+
if (needs_filing(context)) return FILING_OFFER_REASON;
|
|
1179
|
+
return citation_reason(context.message) ?? language_reason(context);
|
|
1180
|
+
}
|
|
1181
|
+
function is_headless_held(context) {
|
|
1182
|
+
if (!context.headless_waiting) return false;
|
|
1183
|
+
return !context.stop_hook_active || context.headless_refusals < HEADLESS_REFUSAL_CAP;
|
|
1184
|
+
}
|
|
1185
|
+
function count_headless_refusals(tail) {
|
|
1186
|
+
const last_wait = Math.max(...HEADLESS_WAIT_CALLS.map((call) => tail.lastIndexOf(call)));
|
|
1187
|
+
return tail.slice(Math.max(last_wait, 0)).split(HEADLESS_WAIT_MARKER).length - 1;
|
|
1188
|
+
}
|
|
1189
|
+
function hold_reason(context) {
|
|
1190
|
+
if (needs_index_route(context)) return LANE_INDEX_REASON;
|
|
1191
|
+
if (needs_notify(context)) return STOP_NOTIFY_REASON;
|
|
1192
|
+
if (needs_release(context)) return HOLD_RELEASE_REASON;
|
|
1193
|
+
return void 0;
|
|
1194
|
+
}
|
|
1195
|
+
function block_reason(context) {
|
|
1196
|
+
if (is_headless_held(context)) return HEADLESS_WAIT_REASON;
|
|
1197
|
+
if (context.stop_hook_active || context.cut_pending) return void 0;
|
|
1198
|
+
return hold_reason(context) ?? reply_reason(context);
|
|
1199
|
+
}
|
|
1200
|
+
function stop_outcome(context) {
|
|
1201
|
+
return { reason: block_reason(context) };
|
|
1202
|
+
}
|
|
1203
|
+
function block_envelope(reason, lang) {
|
|
1204
|
+
return JSON.stringify({ decision: BLOCK_DECISION, reason: `${reason} ${language_note(lang)}` });
|
|
1205
|
+
}
|
|
1206
|
+
function parse_stop_payload(raw_payload) {
|
|
1207
|
+
const parsed = stop_payload_schema.safeParse(JSON.parse(raw_payload));
|
|
1208
|
+
return parsed.success ? parsed.data : void 0;
|
|
1209
|
+
}
|
|
1210
|
+
function is_enabled() {
|
|
1211
|
+
return hook_decision.is_switch_enabled(SWITCH_ENV_KEY);
|
|
1212
|
+
}
|
|
1213
|
+
var stop_rules = {
|
|
1214
|
+
FILING_OFFER_REASON,
|
|
1215
|
+
HEADLESS_REFUSAL_CAP,
|
|
1216
|
+
HEADLESS_WAIT_REASON,
|
|
1217
|
+
HOLD_RELEASE_REASON,
|
|
1218
|
+
ISSUE_CITATION_REASON,
|
|
1219
|
+
LANE_INDEX_REASON,
|
|
1220
|
+
NO_OUTCOME,
|
|
1221
|
+
STOP_NOTIFY_REASON,
|
|
1222
|
+
SWITCH_ENV_KEY,
|
|
1223
|
+
block_envelope,
|
|
1224
|
+
block_reason,
|
|
1225
|
+
build_language_reason,
|
|
1226
|
+
count_headless_refusals,
|
|
1227
|
+
is_enabled,
|
|
1228
|
+
parse_stop_payload,
|
|
1229
|
+
stop_outcome
|
|
1230
|
+
};
|
|
1231
|
+
|
|
1232
|
+
// scripts/run/run-stranded.ts
|
|
1233
|
+
var RECOVERY_COMMAND = "pnpm josh run:wake --start";
|
|
1234
|
+
var LIVE = "live";
|
|
1235
|
+
var GONE = "gone";
|
|
1236
|
+
var UNKNOWN = "unknown";
|
|
1237
|
+
var STRANDED = "stranded";
|
|
1238
|
+
var OK2 = "ok";
|
|
1239
|
+
function supervisor_liveness(wake, same_process = process_identity.is_same_process) {
|
|
1240
|
+
if (wake === void 0) return GONE;
|
|
1241
|
+
const is_same = same_process(wake.pid, wake.process_start);
|
|
1242
|
+
if (is_same === void 0) return UNKNOWN;
|
|
1243
|
+
return is_same ? LIVE : GONE;
|
|
1244
|
+
}
|
|
1245
|
+
function is_stranded(input) {
|
|
1246
|
+
if (input.read.kind !== "carried" || input.read.carry.is_handed_off !== true || input.is_owner_live) {
|
|
1247
|
+
return false;
|
|
1248
|
+
}
|
|
1249
|
+
return input.supervisor === GONE;
|
|
1250
|
+
}
|
|
1251
|
+
function describe2(carry) {
|
|
1252
|
+
return `Run stranded \u2014 ${run_carry.describe_carry(carry)}. The owner is gone, no cut successor claimed the budget, and no supervisor is watching.`;
|
|
1253
|
+
}
|
|
1254
|
+
function verdict_of(is_run_stranded) {
|
|
1255
|
+
return is_run_stranded ? STRANDED : OK2;
|
|
1256
|
+
}
|
|
1257
|
+
var run_stranded = {
|
|
1258
|
+
GONE,
|
|
1259
|
+
LIVE,
|
|
1260
|
+
OK: OK2,
|
|
1261
|
+
RECOVERY_COMMAND,
|
|
1262
|
+
STRANDED,
|
|
1263
|
+
UNKNOWN,
|
|
1264
|
+
describe: describe2,
|
|
1265
|
+
is_stranded,
|
|
1266
|
+
supervisor_liveness,
|
|
1267
|
+
verdict_of
|
|
1268
|
+
};
|
|
1269
|
+
|
|
1270
|
+
// scripts/run/run-wake.ts
|
|
1271
|
+
import { z as z4 } from "zod";
|
|
1272
|
+
var WAKE_PREFIX = "josh-run-wake-";
|
|
1273
|
+
var WAKE_LOG_PREFIX = "josh-run-wake-log-";
|
|
1274
|
+
var WAKE_LOG_SUFFIX = ".log";
|
|
1275
|
+
var WAKE_GRACE_MS = 6e5;
|
|
1276
|
+
var MAX_WAKE_ATTEMPTS = 3;
|
|
1277
|
+
var IDLE_CEILING_MS = backlog_budget.DEFAULT_IDLE_MS;
|
|
1278
|
+
var NO_WAKES = 0;
|
|
1279
|
+
var ONE_WAKE = 1;
|
|
1280
|
+
var WAKE_DECISION = { kind: "wake" };
|
|
1281
|
+
var IDLE_DECISION = { kind: "idle" };
|
|
1282
|
+
var WAIT_DECISION = { kind: "wait" };
|
|
1283
|
+
var PENDING_DECISION = { kind: "pending" };
|
|
1284
|
+
var HOLD_DECISION = { kind: "hold" };
|
|
1285
|
+
var FAILED_DECISION = { kind: "failed" };
|
|
1286
|
+
var STOP_REASONS = {
|
|
1287
|
+
none: "ended",
|
|
1288
|
+
expired: "expired",
|
|
1289
|
+
unreadable: "unreadable"
|
|
1290
|
+
};
|
|
1291
|
+
var run_wake_schema = z4.object({
|
|
1292
|
+
invocation: z4.string(),
|
|
1293
|
+
started_at: z4.string(),
|
|
1294
|
+
pid: z4.number(),
|
|
1295
|
+
process_start: z4.string().optional(),
|
|
1296
|
+
woke: z4.number(),
|
|
1297
|
+
woke_at: z4.string().optional(),
|
|
1298
|
+
// **Every optional field of `RunWake` has to be listed here.** `z.object` strips what it does not
|
|
1299
|
+
// declare, so a field added to the interface alone round-trips through disk as `undefined` — which
|
|
1300
|
+
// reads as "no attempt has been made yet" and would restart the retry count on every pass.
|
|
1301
|
+
attempts: z4.number().optional(),
|
|
1302
|
+
woke_pid: z4.number().optional(),
|
|
1303
|
+
held_at: z4.string().optional(),
|
|
1304
|
+
spawned: z4.array(z4.string()).optional(),
|
|
1305
|
+
idle_since: z4.string().optional(),
|
|
1306
|
+
profile: agent_role_profile.PROFILE_SCHEMA.optional()
|
|
1307
|
+
});
|
|
1308
|
+
function is_overdue(marked_at, now, limit_ms = WAKE_GRACE_MS) {
|
|
1309
|
+
const marked = Date.parse(marked_at);
|
|
1310
|
+
if (Number.isNaN(marked)) return true;
|
|
1311
|
+
return now.getTime() - marked > limit_ms;
|
|
1312
|
+
}
|
|
1313
|
+
function launch_or_idle(input) {
|
|
1314
|
+
if (input.has_work !== false) return WAKE_DECISION;
|
|
1315
|
+
if (input.idle_since === void 0) return IDLE_DECISION;
|
|
1316
|
+
return is_overdue(input.idle_since, input.now, IDLE_CEILING_MS) ? WAKE_DECISION : IDLE_DECISION;
|
|
1317
|
+
}
|
|
1318
|
+
function decide_launch(input) {
|
|
1319
|
+
if (input.woke_at === void 0) return launch_or_idle(input);
|
|
1320
|
+
if (!is_overdue(input.woke_at, input.now)) return PENDING_DECISION;
|
|
1321
|
+
return input.attempts < MAX_WAKE_ATTEMPTS ? launch_or_idle(input) : FAILED_DECISION;
|
|
1322
|
+
}
|
|
1323
|
+
function decide_not_handed_off(input) {
|
|
1324
|
+
if (input.is_owner_live) return WAIT_DECISION;
|
|
1325
|
+
return decide_launch(input);
|
|
1326
|
+
}
|
|
1327
|
+
function is_predecessor_exiting(input) {
|
|
1328
|
+
if (input.woke_at !== void 0 || !input.is_owner_live) return false;
|
|
1329
|
+
return input.held_at === void 0 || !is_overdue(input.held_at, input.now);
|
|
1330
|
+
}
|
|
1331
|
+
function decide(input) {
|
|
1332
|
+
if (input.read.kind !== "carried") return { kind: "stop", reason: STOP_REASONS[input.read.kind] };
|
|
1333
|
+
if (input.read.carry.is_handed_off !== true) return decide_not_handed_off(input);
|
|
1334
|
+
if (is_predecessor_exiting(input)) return HOLD_DECISION;
|
|
1335
|
+
return decide_launch(input);
|
|
1336
|
+
}
|
|
1337
|
+
function wake_path(git_directory) {
|
|
1338
|
+
return stamp_file.stamp_path(WAKE_PREFIX, git_directory);
|
|
1339
|
+
}
|
|
1340
|
+
function wake_log_path(git_directory) {
|
|
1341
|
+
return stamp_file.stamp_path(WAKE_LOG_PREFIX, git_directory, WAKE_LOG_SUFFIX);
|
|
1342
|
+
}
|
|
1343
|
+
function parse_wake(raw) {
|
|
1344
|
+
try {
|
|
1345
|
+
return run_wake_schema.parse(JSON.parse(raw));
|
|
1346
|
+
} catch {
|
|
1347
|
+
return void 0;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
function read_wake(target) {
|
|
1351
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
1352
|
+
return raw === void 0 ? void 0 : parse_wake(raw);
|
|
1353
|
+
}
|
|
1354
|
+
function write_wake(target, wake) {
|
|
1355
|
+
stamp_file.write_stamp(target, wake);
|
|
1356
|
+
}
|
|
1357
|
+
function remove_wake(target) {
|
|
1358
|
+
stamp_file.remove_stamp(target);
|
|
1359
|
+
}
|
|
1360
|
+
function fresh_wake(invocation, now, profile) {
|
|
1361
|
+
return {
|
|
1362
|
+
invocation,
|
|
1363
|
+
...profile && { profile },
|
|
1364
|
+
started_at: now.toISOString(),
|
|
1365
|
+
woke: NO_WAKES,
|
|
1366
|
+
...process_identity.own_fields()
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
function is_supervisor_live(wake) {
|
|
1370
|
+
return process_identity.is_same_process(wake.pid, wake.process_start) !== false;
|
|
1371
|
+
}
|
|
1372
|
+
function carried_state(existing, invocation) {
|
|
1373
|
+
if (existing?.invocation !== invocation) return { woke: NO_WAKES };
|
|
1374
|
+
return {
|
|
1375
|
+
woke: existing.woke,
|
|
1376
|
+
woke_at: existing.woke_at,
|
|
1377
|
+
attempts: existing.attempts,
|
|
1378
|
+
woke_pid: existing.woke_pid,
|
|
1379
|
+
held_at: existing.held_at,
|
|
1380
|
+
// **`spawned` carries across too, or a restart mid-run would lose the ids of every session it
|
|
1381
|
+
// already started** (joshuafolkken/kit#2407) — and `josh time --run`, reading the record after
|
|
1382
|
+
// the restart, would under-count the whiffs and read the loss as a saving.
|
|
1383
|
+
spawned: existing.spawned,
|
|
1384
|
+
// And `idle_since`, or a restart would slide the idle ceiling by the time already spent idle.
|
|
1385
|
+
idle_since: existing.idle_since,
|
|
1386
|
+
...existing.profile && { profile: existing.profile }
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
function is_held_by_live_supervisor(existing) {
|
|
1390
|
+
return existing !== void 0 && is_supervisor_live(existing);
|
|
1391
|
+
}
|
|
1392
|
+
function reclaim(target, wake) {
|
|
1393
|
+
if (is_held_by_live_supervisor(read_wake(target))) return void 0;
|
|
1394
|
+
remove_wake(target);
|
|
1395
|
+
return stamp_file.create_stamp(target, wake) ? wake : void 0;
|
|
1396
|
+
}
|
|
1397
|
+
function claim(target, invocation, now, profile) {
|
|
1398
|
+
const existing = read_wake(target);
|
|
1399
|
+
if (is_held_by_live_supervisor(existing)) return void 0;
|
|
1400
|
+
const wake = { ...fresh_wake(invocation, now, profile), ...carried_state(existing, invocation) };
|
|
1401
|
+
return stamp_file.create_stamp(target, wake) ? wake : reclaim(target, wake);
|
|
1402
|
+
}
|
|
1403
|
+
function count_wake(wake, now, pid, session_id) {
|
|
1404
|
+
const attempts = (wake.attempts ?? NO_WAKES) + ONE_WAKE;
|
|
1405
|
+
const spawned = [...wake.spawned ?? [], session_id];
|
|
1406
|
+
const woke_at = now.toISOString();
|
|
1407
|
+
return {
|
|
1408
|
+
...wake,
|
|
1409
|
+
attempts,
|
|
1410
|
+
spawned,
|
|
1411
|
+
woke_at,
|
|
1412
|
+
woke_pid: pid,
|
|
1413
|
+
held_at: void 0,
|
|
1414
|
+
idle_since: void 0
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
function mark_wait(wake, now) {
|
|
1418
|
+
return wake.held_at === void 0 ? { ...wake, held_at: now.toISOString() } : wake;
|
|
1419
|
+
}
|
|
1420
|
+
function mark_idle(wake, now) {
|
|
1421
|
+
return wake.idle_since === void 0 ? { ...wake, idle_since: now.toISOString() } : wake;
|
|
1422
|
+
}
|
|
1423
|
+
function count_claim(wake) {
|
|
1424
|
+
const woke = wake.woke_at === void 0 ? wake.woke : wake.woke + ONE_WAKE;
|
|
1425
|
+
return {
|
|
1426
|
+
...wake,
|
|
1427
|
+
woke,
|
|
1428
|
+
woke_at: void 0,
|
|
1429
|
+
attempts: void 0,
|
|
1430
|
+
held_at: void 0,
|
|
1431
|
+
idle_since: void 0
|
|
1432
|
+
};
|
|
1433
|
+
}
|
|
1434
|
+
function is_own_wake(wake) {
|
|
1435
|
+
return process_identity.is_own_process(wake.pid, wake.process_start);
|
|
1436
|
+
}
|
|
1437
|
+
function read_own_wake(target) {
|
|
1438
|
+
const wake = read_wake(target);
|
|
1439
|
+
return wake !== void 0 && is_own_wake(wake) ? wake : void 0;
|
|
1440
|
+
}
|
|
1441
|
+
function tidy_own_wake(target) {
|
|
1442
|
+
const wake = read_wake(target);
|
|
1443
|
+
if (wake === void 0) return "absent";
|
|
1444
|
+
if (!is_own_wake(wake)) return "superseded";
|
|
1445
|
+
remove_wake(target);
|
|
1446
|
+
return "removed";
|
|
1447
|
+
}
|
|
1448
|
+
function update_wake(target, wake) {
|
|
1449
|
+
if (read_own_wake(target) === void 0) return false;
|
|
1450
|
+
write_wake(target, wake);
|
|
1451
|
+
return true;
|
|
1452
|
+
}
|
|
1453
|
+
var run_wake = {
|
|
1454
|
+
IDLE_CEILING_MS,
|
|
1455
|
+
MAX_WAKE_ATTEMPTS,
|
|
1456
|
+
WAKE_GRACE_MS,
|
|
1457
|
+
WAKE_PREFIX,
|
|
1458
|
+
claim,
|
|
1459
|
+
count_claim,
|
|
1460
|
+
count_wake,
|
|
1461
|
+
decide,
|
|
1462
|
+
fresh_wake,
|
|
1463
|
+
is_supervisor_live,
|
|
1464
|
+
mark_idle,
|
|
1465
|
+
mark_wait,
|
|
1466
|
+
parse_wake,
|
|
1467
|
+
read_own_wake,
|
|
1468
|
+
read_wake,
|
|
1469
|
+
remove_wake,
|
|
1470
|
+
tidy_own_wake,
|
|
1471
|
+
update_wake,
|
|
1472
|
+
wake_log_path,
|
|
1473
|
+
wake_path,
|
|
1474
|
+
write_wake
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
// scripts/run/run-stranded-detect.ts
|
|
1478
|
+
var STRAND_RECOVERY = `Restart supervision with \`${run_stranded.RECOVERY_COMMAND}\` \u2014 it wakes a fresh successor to claim the budget; the cutting session must not resume it itself.`;
|
|
1479
|
+
async function real_resolve_targets() {
|
|
1480
|
+
const directory = await run_carry.repository_directory();
|
|
1481
|
+
if (directory === void 0) return void 0;
|
|
1482
|
+
return { carry: run_carry.carry_path(directory), wake: run_wake.wake_path(directory) };
|
|
1483
|
+
}
|
|
1484
|
+
async function real_emit_stranded(text2) {
|
|
1485
|
+
return await run_event_stream_emit.emit_once(run_event_stream.EVENT_KIND.STRANDED, text2);
|
|
1486
|
+
}
|
|
1487
|
+
async function real_notify_stranded(body) {
|
|
1488
|
+
return await telegram_notify.stranded({ body, recovery: STRAND_RECOVERY });
|
|
1489
|
+
}
|
|
1490
|
+
var DEFAULT_PORTS3 = {
|
|
1491
|
+
resolve_targets: real_resolve_targets,
|
|
1492
|
+
read_carry: (target) => run_carry.read_carry(target),
|
|
1493
|
+
is_owner_live: run_carry.is_owner_live,
|
|
1494
|
+
read_wake: (target) => run_wake.read_wake(target),
|
|
1495
|
+
supervisor_liveness: (wake) => run_stranded.supervisor_liveness(wake),
|
|
1496
|
+
emit_stranded: real_emit_stranded,
|
|
1497
|
+
notify_stranded: real_notify_stranded
|
|
1498
|
+
};
|
|
1499
|
+
async function gather2(ports) {
|
|
1500
|
+
const targets = await ports.resolve_targets();
|
|
1501
|
+
if (targets === void 0) return void 0;
|
|
1502
|
+
const read = ports.read_carry(targets.carry);
|
|
1503
|
+
if (read.kind !== "carried") return void 0;
|
|
1504
|
+
return {
|
|
1505
|
+
read,
|
|
1506
|
+
is_owner_live: ports.is_owner_live(read.carry),
|
|
1507
|
+
supervisor: ports.supervisor_liveness(ports.read_wake(targets.wake))
|
|
1508
|
+
};
|
|
1509
|
+
}
|
|
1510
|
+
async function report2(ports, input) {
|
|
1511
|
+
if (input.read.kind !== "carried") return;
|
|
1512
|
+
const text2 = run_stranded.describe(input.read.carry);
|
|
1513
|
+
if (await ports.emit_stranded(text2)) await ports.notify_stranded(text2);
|
|
1514
|
+
}
|
|
1515
|
+
async function detect_and_report2(ports = DEFAULT_PORTS3) {
|
|
1516
|
+
const input = await gather2(ports);
|
|
1517
|
+
if (input === void 0) return run_stranded.OK;
|
|
1518
|
+
const is_run_stranded = run_stranded.is_stranded(input);
|
|
1519
|
+
if (is_run_stranded) await report2(ports, input);
|
|
1520
|
+
return run_stranded.verdict_of(is_run_stranded);
|
|
1521
|
+
}
|
|
1522
|
+
async function run_stranded_check() {
|
|
1523
|
+
try {
|
|
1524
|
+
await detect_and_report2();
|
|
1525
|
+
} catch {
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
var run_stranded_detect = { DEFAULT_PORTS: DEFAULT_PORTS3, detect_and_report: detect_and_report2, gather: gather2, report: report2, run_stranded_check };
|
|
1529
|
+
|
|
1530
|
+
// scripts/hooks/stop-guard.ts
|
|
1531
|
+
async function is_hold_present() {
|
|
1532
|
+
const directory = await run_hold.worktree_directory();
|
|
1533
|
+
if (directory === void 0) return false;
|
|
1534
|
+
const read = run_hold.read_hold(run_hold.hold_path(directory));
|
|
1535
|
+
return read.kind === "held" || read.kind === "stale";
|
|
1536
|
+
}
|
|
1537
|
+
function transcript_tail(transcript_path) {
|
|
1538
|
+
const transcript = time_hook_transcript.transcript_of(transcript_path, void 0);
|
|
1539
|
+
return time_density_hook.read_tail(transcript);
|
|
1540
|
+
}
|
|
1541
|
+
function was_filed(tail) {
|
|
1542
|
+
return filing_cap.turn_filing_count(tail) > 0;
|
|
1543
|
+
}
|
|
1544
|
+
function session_lang() {
|
|
1545
|
+
return session_language.resolve_session_lang().lang;
|
|
1546
|
+
}
|
|
1547
|
+
async function build_context(transcript_path, payload_tail) {
|
|
1548
|
+
const tail = transcript_tail(transcript_path);
|
|
1549
|
+
return {
|
|
1550
|
+
hold_present: await is_hold_present(),
|
|
1551
|
+
tree_clean: !await run_hold.is_tree_dirty(),
|
|
1552
|
+
notified: lane_park.mentions_confirmation_notify(tail),
|
|
1553
|
+
message: payload_tail.message,
|
|
1554
|
+
stop_hook_active: payload_tail.stop_hook_active,
|
|
1555
|
+
cut_pending: run_cut.carried_cut_sync() !== void 0,
|
|
1556
|
+
filed: was_filed(tail),
|
|
1557
|
+
session_owner: repo_party.current_owner(),
|
|
1558
|
+
headless_waiting: await run_headless.must_keep_waiting(),
|
|
1559
|
+
headless_refusals: stop_rules.count_headless_refusals(tail),
|
|
1560
|
+
lane_child: lane_child_marker.is_child_of(process.cwd()),
|
|
1561
|
+
session_lang: session_lang()
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
async function stop_outcome_for_payload(raw_payload) {
|
|
1565
|
+
const payload = stop_rules.parse_stop_payload(raw_payload);
|
|
1566
|
+
if (payload === void 0 || !stop_rules.is_enabled()) return stop_rules.NO_OUTCOME;
|
|
1567
|
+
const context = await build_context(payload.transcript_path, {
|
|
1568
|
+
stop_hook_active: payload.stop_hook_active ?? false,
|
|
1569
|
+
message: payload.last_assistant_message ?? ""
|
|
1570
|
+
});
|
|
1571
|
+
return stop_rules.stop_outcome(context);
|
|
1572
|
+
}
|
|
1573
|
+
async function outcome_of(raw_payload) {
|
|
1574
|
+
try {
|
|
1575
|
+
return await stop_outcome_for_payload(raw_payload);
|
|
1576
|
+
} catch {
|
|
1577
|
+
return stop_rules.NO_OUTCOME;
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
async function write_stop_decision(raw_payload) {
|
|
1581
|
+
hook_decision.load_environment_file();
|
|
1582
|
+
await backlog_stalled_detect.run_stall_check(backlog_ready.DEFAULT_PORTS);
|
|
1583
|
+
await run_stranded_detect.run_stranded_check();
|
|
1584
|
+
const { reason } = await outcome_of(raw_payload);
|
|
1585
|
+
if (reason === void 0) return;
|
|
1586
|
+
process.stdout.write(`${stop_rules.block_envelope(reason, session_lang())}
|
|
1587
|
+
`);
|
|
1588
|
+
}
|
|
1589
|
+
var stop_guard = { outcome_of, stop_outcome_for_payload };
|
|
1590
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
1591
|
+
if (process.stdin.isTTY) hook_decision.report_no_payload("stop:guard");
|
|
1592
|
+
else await write_stop_decision(await text(process.stdin));
|
|
1593
|
+
}
|
|
1594
|
+
export {
|
|
1595
|
+
stop_guard,
|
|
1596
|
+
write_stop_decision
|
|
1597
|
+
};
|