@joshuafolkken/kit 1.1471.0 → 1.1784.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/agents/investigator.md +1 -1
- package/.claude/settings.json +6 -6
- package/.claude/skills/epic-commands/SKILL.md +26 -77
- package/.claude/skills/epic-commands/epic-bundle.md +12 -6
- package/.claude/skills/epic-commands/execution-waves.md +1 -2
- package/.claude/skills/verify-ui/SKILL.md +1 -2
- package/.claude/skills/workflow-commands/SKILL.md +12 -14
- package/.claude/skills/workflow-commands/background-commands.md +8 -12
- package/.claude/skills/workflow-commands/backlogrun-child.md +13 -18
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +23 -28
- package/.claude/skills/workflow-commands/backlogrun-park.md +16 -31
- package/.claude/skills/workflow-commands/backlogrun-progress.md +12 -21
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +12 -12
- package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -20
- package/.claude/skills/workflow-commands/backlogrun.md +32 -51
- package/.claude/skills/workflow-commands/chain-rule.md +18 -11
- package/.claude/skills/workflow-commands/delegation.md +13 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +10 -12
- package/.claude/skills/workflow-commands/followup.md +10 -35
- package/.claude/skills/workflow-commands/fullrun-steps.md +38 -49
- package/.claude/skills/workflow-commands/fullrun.md +6 -8
- package/.claude/skills/workflow-commands/halfrun.md +20 -32
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +19 -15
- package/.claude/skills/workflow-commands/issue-scout.md +5 -4
- package/.claude/skills/workflow-commands/kickoff.md +24 -23
- package/.claude/skills/workflow-commands/latest-gate.md +9 -18
- package/.claude/skills/workflow-commands/needs-human-review.md +11 -19
- package/.claude/skills/workflow-commands/observation-filing.md +4 -50
- package/.claude/skills/workflow-commands/observation-ledger.md +5 -10
- package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -44
- package/.claude/skills/workflow-commands/prerequisite.md +11 -18
- package/.claude/skills/workflow-commands/progress-watcher.md +3 -8
- package/.claude/skills/workflow-commands/prrun.md +6 -12
- package/.claude/skills/workflow-commands/retrospective.md +5 -5
- package/.claude/skills/workflow-commands/split-assessment.md +14 -4
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +11 -13
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +10 -1
- package/.github/actions/setup-pnpm/action.yml +1 -1
- package/.github/dependabot.yml +16 -0
- package/.github/release.yml +0 -2
- package/.github/workflows/ci.yml +121 -11
- package/.github/workflows/publish.yml +10 -3
- package/.github/workflows/sonar-qube.yml +1 -0
- package/.prettierignore +2 -0
- package/.vscode/tasks.json +1 -2
- package/CLAUDE.md +4 -8
- package/README.md +4 -2
- package/SECURITY.md +1 -1
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +4 -8
- package/dist/commands/document-read-cli.js +882 -0
- package/dist/commands/{document-section-cli.js → document-section-main.js} +137 -62
- package/dist/commands/read-set-cli.js +1867 -0
- package/dist/commands/run-prep-main.js +21653 -0
- package/dist/commands/run-step-cli.js +23880 -0
- package/dist/config-merge/index.js +5 -1
- package/dist/hooks/audit-provision.js +20 -35
- package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
- package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
- package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
- package/dist/hooks/{chunk-AS74OU3D.js → chunk-PT5R6UJD.js} +4582 -2118
- package/dist/hooks/chunk-TUIFS5E7.js +72 -0
- package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
- package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-WR2KQAYZ.js} +1863 -382
- package/dist/hooks/{chunk-KC5AK2GF.js → chunk-XGBNSWEI.js} +248 -46
- package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
- package/dist/hooks/codex-hook-adapter.js +10 -19
- package/dist/hooks/format-edited.js +5 -5
- package/dist/hooks/inputs.json +436 -257
- package/dist/hooks/pretool-guard.js +7 -22
- package/dist/hooks/session-lang.js +380 -42
- package/dist/hooks/stop-guard.js +8711 -782
- package/dist/josh.js +5263 -997
- package/dist/self-sync-guard/index.js +74 -10
- package/dist/version/index.js +115 -406
- package/eslint/base.js +1 -1
- package/lefthook/base.yml +8 -4
- package/package.json +17 -53
- package/pnpm-workspace.yaml +4 -2
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +1 -9
- package/prompts/collaboration-workflow/gh-rest.md +1 -2
- package/prompts/collaboration-workflow/issue-citation.md +2 -4
- package/prompts/collaboration-workflow/issue-template.md +42 -17
- package/prompts/collaboration-workflow/lane-instructions.md +34 -0
- package/prompts/collaboration-workflow/measurement.md +37 -0
- package/prompts/collaboration-workflow/operating-rules.md +6 -12
- package/prompts/collaboration-workflow/output-bounds.md +4 -9
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/plan-comment.md +3 -42
- package/prompts/collaboration-workflow/principles.md +19 -8
- package/prompts/collaboration-workflow/report-format.md +37 -57
- package/prompts/collaboration-workflow/residency.md +12 -8
- package/prompts/collaboration-workflow/rule-delivery.md +3 -11
- package/prompts/collaboration-workflow/shell-body.md +8 -18
- package/prompts/collaboration-workflow/turn-batching.md +4 -6
- package/prompts/collaboration-workflow/upstream-interrupt.md +16 -6
- package/prompts/collaboration-workflow/wip-cap.md +7 -7
- package/prompts/collaboration-workflow.md +4 -7
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +45 -26
- package/prompts/testing-guide.md +10 -45
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-event.ts +15 -15
- package/scripts/agent/agent-exit-record.ts +13 -1
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/api-auth.ts +41 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +2 -0
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/auto-ok/auto-ok-cli.ts +14 -16
- package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
- package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
- package/scripts/auto-ok/auto-ok-judge.ts +13 -2
- package/scripts/auto-ok/auto-ok-main.ts +17 -0
- package/scripts/backlog/backlog-arrival.ts +14 -3
- package/scripts/backlog/backlog-budget-cli.ts +7 -33
- package/scripts/backlog/backlog-budget-main.ts +16 -0
- package/scripts/backlog/backlog-budget.ts +6 -7
- package/scripts/backlog/backlog-defect-priority.ts +4 -3
- package/scripts/backlog/backlog-drive-adopt.ts +67 -0
- package/scripts/backlog/backlog-drive-args.ts +4 -5
- package/scripts/backlog/backlog-drive-cli.ts +113 -28
- package/scripts/backlog/backlog-drive-hold.ts +162 -0
- package/scripts/backlog/backlog-drive-idle.ts +151 -0
- package/scripts/backlog/backlog-drive-judge.ts +25 -0
- package/scripts/backlog/backlog-drive-memory.ts +126 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
- package/scripts/backlog/backlog-drive-named.ts +54 -7
- package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
- package/scripts/backlog/backlog-drive-paused.ts +169 -0
- package/scripts/backlog/backlog-drive-restore.ts +39 -8
- package/scripts/backlog/backlog-drive-seats.ts +18 -8
- package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
- package/scripts/backlog/backlog-drive.ts +79 -75
- package/scripts/backlog/backlog-next-main.ts +16 -0
- package/scripts/backlog/backlog-next-shared.ts +73 -0
- package/scripts/backlog/backlog-next.ts +48 -16
- package/scripts/backlog/backlog-occupied.ts +69 -0
- package/scripts/backlog/backlog-offer-cli.ts +6 -21
- package/scripts/backlog/backlog-offer-exclude.ts +15 -0
- package/scripts/backlog/backlog-offer-main.ts +12 -0
- package/scripts/backlog/backlog-offer.ts +36 -3
- package/scripts/backlog/backlog-overlap.ts +22 -4
- package/scripts/backlog/backlog-plan-read.ts +6 -2
- package/scripts/backlog/backlog-plan.ts +18 -4
- package/scripts/backlog/backlog-pool.ts +10 -10
- package/scripts/backlog/backlog-rank.ts +10 -2
- package/scripts/backlog/backlog-ready.ts +137 -18
- package/scripts/backlog/backlog-stalled-detect.ts +109 -36
- package/scripts/backlog/backlog-stalled.ts +52 -16
- package/scripts/backlog/backlog-wait-cause.ts +86 -0
- package/scripts/backlog/backlog-waves.ts +39 -13
- package/scripts/backlog/backlogrun-args.ts +19 -7
- package/scripts/backlog/backlogrun-cli.ts +19 -5
- package/scripts/backlog/backlogrun-launch.ts +6 -0
- package/scripts/backlog/backlogrun-restart.ts +97 -0
- package/scripts/backlog/backlogrun-stop.ts +79 -7
- package/scripts/behavior/behavior-cli.ts +2 -2
- package/scripts/behavior/behavior-rules.ts +47 -24
- package/scripts/build/build-bin.ts +2 -16
- package/scripts/build/build-claude-md.ts +0 -7
- package/scripts/build/build-commands.ts +0 -13
- package/scripts/build/build-hooks.ts +49 -48
- package/scripts/build/hook-bundle-stamp.ts +29 -11
- package/scripts/build/local-bin.ts +1 -1
- package/scripts/cases/cases-cli.ts +25 -13
- package/scripts/cases/cases-interaction-scan.ts +134 -0
- package/scripts/cases/cases-interaction.ts +183 -0
- package/scripts/cases/cases-logic.ts +39 -6
- package/scripts/ci/pr-classification-main.ts +18 -0
- package/scripts/ci/pr-classification.ts +10 -17
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/cost-runtime/cost-blocks.ts +22 -37
- package/scripts/cost-runtime/cost-cli.ts +31 -14
- package/scripts/cost-runtime/cost-main.ts +12 -0
- package/scripts/cost-runtime/cost-transcript.ts +1 -0
- package/scripts/delegation/delegation-policy.ts +17 -4
- package/scripts/delegation/duplicate-read-guard.ts +2 -10
- package/scripts/delegation/investigation-guard.ts +15 -73
- package/scripts/delegation/investigation-reads.ts +3 -5
- package/scripts/dependabot/dependabot-cooldown.ts +194 -0
- package/scripts/discovery/repo-discovery.ts +24 -6
- package/scripts/doctor/doctor-consumer.ts +2 -5
- package/scripts/document/document-byte-budget.ts +9 -6
- package/scripts/document/document-scan.ts +1 -1
- package/scripts/document/document-section-cli.ts +17 -13
- package/scripts/document/document-section-main.ts +12 -0
- package/scripts/document/entry-read-budget.ts +2 -2
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-cli.ts +12 -6
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-apply.ts +137 -0
- package/scripts/epic/epic-bundle-cli.ts +32 -121
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-format.ts +116 -0
- package/scripts/epic/epic-bundle-main.ts +17 -0
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/epic/epic-busy.ts +5 -12
- package/scripts/epic/epic-classify.ts +24 -15
- package/scripts/epic/epic-cli-argv.ts +31 -0
- package/scripts/epic/epic-cli-decide.ts +42 -0
- package/scripts/epic/epic-cli.ts +6 -38
- package/scripts/epic/epic-close.ts +112 -55
- package/scripts/epic/epic-cross-repo.ts +4 -7
- package/scripts/epic/epic-decide.ts +119 -0
- package/scripts/epic/epic-decision.ts +9 -0
- package/scripts/epic/epic-fetch.ts +4 -0
- package/scripts/epic/epic-graph.ts +2 -0
- package/scripts/epic/epic-issue.ts +5 -1
- package/scripts/epic/epic-label-age.ts +1 -1
- package/scripts/epic/epic-lane-offer.ts +39 -4
- package/scripts/epic/epic-next-main.ts +24 -0
- package/scripts/epic/epic-next.ts +6 -24
- package/scripts/epic/epic-outside-blocker.ts +6 -2
- package/scripts/epic/epic-parse.ts +9 -3
- package/scripts/epic/epic-read.ts +1 -0
- package/scripts/epic/epic-reconcile.ts +39 -0
- package/scripts/epic/epic-run.ts +10 -1
- package/scripts/epic/epic-solo.ts +50 -14
- package/scripts/epic/epic.ts +41 -7
- package/scripts/exports/unused-members-cli.ts +2 -2
- package/scripts/followup/followup-checks-event.ts +8 -3
- package/scripts/followup/followup-coderabbit-wait.ts +82 -0
- package/scripts/followup/followup-review-gates.ts +81 -0
- package/scripts/followup/git-followup-stages.ts +13 -3
- package/scripts/followup/git-followup-workflow.ts +31 -60
- package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
- package/scripts/followup/git-pr-followup.ts +36 -8
- package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
- package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
- package/scripts/gate/busy-average.ts +58 -0
- package/scripts/gate/check-cpu.ts +60 -0
- package/scripts/gate/check-inputs.ts +73 -0
- package/scripts/gate/check-reuse.ts +141 -0
- package/scripts/gate/command-memory.ts +192 -0
- package/scripts/gate/core-admission.ts +218 -28
- package/scripts/gate/core-budget-timing.ts +37 -0
- package/scripts/gate/core-budget.ts +150 -119
- package/scripts/gate/core-wait-record.ts +48 -0
- package/scripts/gate/core-wait.ts +162 -0
- package/scripts/gate/core-weights.ts +86 -0
- package/scripts/gate/free-cores.ts +72 -0
- package/scripts/gate/gate-ledger.ts +49 -7
- package/scripts/gate/gate-plan.ts +44 -15
- package/scripts/gate/gate-report.ts +29 -4
- package/scripts/gate/gate-run-steps.ts +195 -0
- package/scripts/gate/gate-skip.ts +12 -2
- package/scripts/gate/gate-steps.ts +12 -1
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/input-fingerprint.ts +42 -0
- package/scripts/gate/machine-capacity.ts +124 -31
- package/scripts/gate/moved-paths.ts +67 -0
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/project-checks.ts +5 -12
- package/scripts/gate/scoped-green.ts +12 -8
- package/scripts/gate/since-green.ts +62 -0
- package/scripts/gate/toolchain-inputs.ts +115 -0
- package/scripts/gate/verification-gate.ts +65 -129
- package/scripts/gate/verification-inputs.ts +250 -0
- package/scripts/gh/gh-author-association.ts +96 -9
- package/scripts/gh/git-ai-review-scan.ts +4 -2
- package/scripts/gh/git-gh-api-path.ts +15 -0
- package/scripts/gh/git-gh-branch-rules.ts +73 -0
- package/scripts/gh/git-gh-conditional.ts +5 -2
- package/scripts/gh/git-gh-issue-read.ts +5 -1
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +77 -17
- package/scripts/gh/git-gh-issue.ts +7 -3
- package/scripts/gh/git-gh-poll-read.ts +89 -0
- package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
- package/scripts/gh/git-gh-pr.ts +27 -15
- package/scripts/gh/git-pr-checks-eval.ts +39 -7
- package/scripts/gh/git-pr-checks-parse.ts +39 -9
- package/scripts/gh/git-pr-merge-checked.ts +80 -0
- package/scripts/gh/git-pr.ts +13 -1
- package/scripts/git/base-tree.ts +19 -2
- package/scripts/git/changed-file-scope.ts +6 -4
- package/scripts/git/changed-paths.ts +18 -1
- package/scripts/git/git-diff-reads.ts +27 -2
- package/scripts/git/git-grep-hits.ts +85 -0
- package/scripts/git/git-location-environment.ts +1 -1
- package/scripts/git/git-merge-conflicts.ts +83 -0
- package/scripts/git/git-preflight.ts +37 -12
- package/scripts/git/git-push-transport.ts +1 -2
- package/scripts/git/git-schemas.ts +17 -7
- package/scripts/git/git-spawn.ts +1 -2
- package/scripts/git/git-status.ts +4 -4
- package/scripts/git/main-merge-main.ts +12 -0
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +39 -14
- package/scripts/git/main-sync-main.ts +12 -0
- package/scripts/git/main-sync.ts +0 -9
- package/scripts/git/stash/git-stash.ts +27 -4
- package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
- package/scripts/git/stash/stash-pop-cli.ts +6 -12
- package/scripts/git/stash/stash-pop-main.ts +12 -0
- package/scripts/git/stash/stash-push-cli.ts +76 -0
- package/scripts/git/stash/stash-push-main.ts +12 -0
- package/scripts/hooks/batch-guard.ts +5 -16
- package/scripts/hooks/check-commit-message-main.ts +8 -0
- package/scripts/hooks/check-commit-message.ts +4 -7
- package/scripts/hooks/format-edited-file.ts +8 -24
- package/scripts/hooks/pre-commit-lint.ts +118 -0
- package/scripts/hooks/pre-push-unit.ts +4 -2
- package/scripts/hooks/pretool-guard-cli.ts +1 -8
- package/scripts/hooks/pretool-guard.ts +57 -69
- package/scripts/hooks/reserved-run.ts +67 -8
- package/scripts/hooks/run-hook.sh +18 -11
- package/scripts/hooks/shell-rules-notice.ts +37 -0
- package/scripts/hooks/stop-actions.ts +185 -0
- package/scripts/hooks/stop-guard.ts +72 -27
- package/scripts/init/hook-command-rewrite.ts +19 -5
- package/scripts/init/hook-launch.ts +15 -12
- package/scripts/init/init-actions.ts +0 -6
- package/scripts/init/init-ai-copy.ts +10 -36
- package/scripts/init/init-bootstrap.ts +9 -8
- package/scripts/init/init-dry-run-report.ts +1 -1
- package/scripts/init/init-dry-run.ts +1 -1
- package/scripts/init/init-file-action.ts +7 -9
- package/scripts/init/init-logic-json-merge.ts +2 -2
- package/scripts/init/init-logic-migrate.ts +9 -82
- package/scripts/init/init-logic.ts +3 -2
- package/scripts/init/init-main.ts +12 -0
- package/scripts/init/init.ts +5 -12
- package/scripts/init/kit-development-versions.ts +3 -7
- package/scripts/init/kit-written-paths.ts +2 -2
- package/scripts/init/project-profile.ts +5 -4
- package/scripts/init/tsconfig-preset-migration.ts +2 -1
- package/scripts/init/vscode-tasks.ts +1 -1
- package/scripts/issue/defect-origin-cli.ts +106 -0
- package/scripts/issue/defect-origin-line.ts +60 -0
- package/scripts/issue/defect-origin-main.ts +11 -0
- package/scripts/issue/defect-origin.ts +114 -0
- package/scripts/issue/defect-rate-cli.ts +34 -78
- package/scripts/issue/defect-rate.ts +0 -16
- package/scripts/issue/defect-report-cli.ts +128 -0
- package/scripts/issue/defect-report-format.ts +56 -0
- package/scripts/issue/defect-report-main.ts +11 -0
- package/scripts/issue/defect-report.ts +160 -0
- package/scripts/issue/expected-effect-lint.ts +60 -0
- package/scripts/issue/issue-already-done-cli.ts +62 -0
- package/scripts/issue/issue-body-or-comment.ts +40 -0
- package/scripts/issue/issue-cite-cli.ts +33 -22
- package/scripts/issue/issue-cite-main.ts +12 -0
- package/scripts/issue/issue-classification.ts +13 -8
- package/scripts/issue/issue-comment-cli.ts +10 -24
- package/scripts/issue/issue-comment-main.ts +12 -0
- package/scripts/issue/issue-evidence-exit.ts +100 -0
- package/scripts/issue/issue-file-cli.ts +29 -7
- package/scripts/issue/issue-file.ts +19 -19
- package/scripts/issue/issue-fold-cli.ts +2 -11
- package/scripts/issue/issue-fold-main.ts +12 -0
- package/scripts/issue/issue-labels.ts +81 -90
- package/scripts/issue/issue-lint-cli.ts +7 -13
- package/scripts/issue/issue-lint-main.ts +12 -0
- package/scripts/issue/issue-measured-cli.ts +56 -0
- package/scripts/issue/issue-merged.ts +19 -2
- package/scripts/issue/issue-not-before-label.ts +135 -0
- package/scripts/issue/issue-not-before.ts +111 -0
- package/scripts/issue/issue-number-shape.ts +15 -1
- package/scripts/issue/issue-park.ts +28 -0
- package/scripts/issue/issue-plan-cli.ts +151 -0
- package/scripts/issue/issue-priority.ts +151 -0
- package/scripts/issue/issue-rank.ts +7 -1
- package/scripts/issue/issue-read-cli.ts +3 -10
- package/scripts/issue/issue-read-main.ts +12 -0
- package/scripts/issue/issue-read.ts +29 -5
- package/scripts/issue/issue-release-cli.ts +0 -10
- package/scripts/issue/issue-release-main.ts +13 -0
- package/scripts/issue/issue-release.ts +7 -12
- package/scripts/issue/issue-sample-gate.ts +192 -0
- package/scripts/issue/issue-sample-source.ts +76 -0
- package/scripts/issue/issue-scout-cli.ts +19 -25
- package/scripts/issue/issue-scout-main.ts +14 -0
- package/scripts/issue/issue-state-cli.ts +0 -10
- package/scripts/issue/issue-state-main.ts +12 -0
- package/scripts/issue/issue-watch-diff.ts +56 -15
- package/scripts/issue/issue-watch.ts +2 -1
- package/scripts/issue/issue-wip.ts +2 -7
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/issue/measure-rerun-cli.ts +13 -8
- package/scripts/issue/plan-consumers-cli.ts +39 -0
- package/scripts/issue/plan-consumers-main.ts +11 -0
- package/scripts/issue/plan-consumers-section.ts +55 -0
- package/scripts/issue/plan-consumers.ts +127 -0
- package/scripts/josh/agent-session-environment.ts +1 -1
- package/scripts/josh/command-usage.ts +82 -0
- package/scripts/josh/file-map-stamp.ts +49 -16
- package/scripts/josh/hook-decision.ts +32 -20
- package/scripts/josh/josh-command-map.ts +6 -1
- package/scripts/josh/josh-command-types.ts +65 -13
- package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
- package/scripts/josh/josh-commands-ai.ts +169 -157
- package/scripts/josh/josh-commands-backlog.ts +82 -16
- package/scripts/josh/josh-commands-clone.ts +1 -0
- package/scripts/josh/josh-commands-development.ts +111 -71
- package/scripts/josh/josh-commands-document.ts +43 -1
- package/scripts/josh/josh-commands-epic.ts +171 -0
- package/scripts/josh/josh-commands-hooks.ts +31 -2
- package/scripts/josh/josh-commands-issue-write.ts +181 -0
- package/scripts/josh/josh-commands-issue.ts +124 -24
- package/scripts/josh/josh-commands-lane.ts +112 -2
- package/scripts/josh/josh-commands-lint.ts +19 -8
- package/scripts/josh/josh-commands-maintenance.ts +112 -4
- package/scripts/josh/josh-commands-pause.ts +29 -0
- package/scripts/josh/josh-commands-progress.ts +87 -0
- package/scripts/josh/josh-commands-project.ts +138 -9
- package/scripts/josh/josh-commands-review.ts +124 -0
- package/scripts/josh/josh-commands-run.ts +211 -23
- package/scripts/josh/josh-commands-ship.ts +169 -0
- package/scripts/josh/josh-commands-split.ts +9 -0
- package/scripts/josh/josh-commands-versioning.ts +49 -2
- package/scripts/josh/josh-commands-workflow.ts +149 -6
- package/scripts/josh/josh-logic.ts +11 -27
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +18 -0
- package/scripts/josh/process-identity.ts +13 -4
- package/scripts/josh/session-language-cli.ts +4 -8
- package/scripts/josh/session-language-main.ts +13 -0
- package/scripts/josh/session-language.ts +6 -1
- package/scripts/josh/shared-cache.ts +90 -0
- package/scripts/josh/stamp-file.ts +9 -15
- package/scripts/lane/lane-await.ts +51 -12
- package/scripts/lane/lane-cache.ts +5 -30
- package/scripts/lane/lane-capacity.ts +19 -22
- package/scripts/lane/lane-check-stats.ts +97 -0
- package/scripts/lane/lane-child-invocation.ts +43 -4
- package/scripts/lane/lane-cli.ts +15 -5
- package/scripts/lane/lane-close.ts +86 -18
- package/scripts/lane/lane-core-wait-stats.ts +66 -0
- package/scripts/lane/lane-dispatch.ts +27 -6
- package/scripts/lane/lane-gap-stats.ts +156 -0
- package/scripts/lane/lane-guard-policy.ts +2 -2
- package/scripts/lane/lane-handoff.ts +76 -1
- package/scripts/lane/lane-held-stats.ts +129 -0
- package/scripts/lane/lane-install.ts +16 -15
- package/scripts/lane/lane-launch-cli.ts +0 -9
- package/scripts/lane/lane-launch-main.ts +12 -0
- package/scripts/lane/lane-ledger-schema.ts +266 -0
- package/scripts/lane/lane-ledger.ts +108 -97
- package/scripts/lane/lane-limit-cli.ts +19 -9
- package/scripts/lane/lane-measure-cli.ts +58 -10
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-parked.ts +3 -3
- package/scripts/lane/lane-pause-cli.ts +130 -0
- package/scripts/lane/lane-pause.ts +158 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-process-table.ts +166 -0
- package/scripts/lane/lane-reap-settle.ts +124 -0
- package/scripts/lane/lane-reap.ts +50 -15
- package/scripts/lane/lane-registry.ts +33 -10
- package/scripts/lane/lane-residents.ts +162 -0
- package/scripts/lane/lane-restart.ts +26 -27
- package/scripts/lane/lane-round-two-stats.ts +49 -0
- package/scripts/lane/lane-sampler.ts +4 -0
- package/scripts/lane/lane-session-action.ts +160 -0
- package/scripts/lane/lane-session-broker.ts +134 -134
- package/scripts/lane/lane-snapshot-trace.ts +84 -0
- package/scripts/lane/lane-spans.ts +51 -0
- package/scripts/lane/lane-spent.ts +6 -3
- package/scripts/lane/lane-stage-stats.ts +7 -2
- package/scripts/lane/lane-state.ts +302 -0
- package/scripts/lane/lane-stats.ts +58 -4
- package/scripts/lane/lane-stop-stats.ts +113 -37
- package/scripts/lane/lane-test-related-stats.ts +127 -0
- package/scripts/lane/lane-transcript-calls.ts +145 -0
- package/scripts/lane/lane-transcript-stats.ts +168 -0
- package/scripts/lane/lane-vacant.ts +13 -3
- package/scripts/lane/lane-withdraw-cli.ts +72 -0
- package/scripts/lane/lane-withdraw.ts +183 -0
- package/scripts/lane/process-directories.ts +70 -0
- package/scripts/lane/process-lane-marks.ts +94 -0
- package/scripts/lib/atomic-write.ts +62 -0
- package/scripts/lib/buffered-process.ts +12 -5
- package/scripts/lib/cli-flags.ts +53 -0
- package/scripts/lib/figure-format.ts +63 -0
- package/scripts/lib/json-value.ts +9 -1
- package/scripts/lib/package-manifest.ts +35 -0
- package/scripts/lib/read-file.ts +3 -1
- package/scripts/lib/stamped-memo.ts +63 -0
- package/scripts/lib/stdout-on-stderr.ts +24 -0
- package/scripts/lib/timeouts.ts +9 -0
- package/scripts/lib/transcript-record.ts +91 -0
- package/scripts/lines/effective-limit.ts +1 -1
- package/scripts/lint/eslint-cache-dependencies.ts +145 -0
- package/scripts/lint/eslint-daemon.ts +265 -0
- package/scripts/lint/format.ts +14 -5
- package/scripts/lint/import-graph.ts +279 -0
- package/scripts/lint/lint-gate-scope.ts +102 -0
- package/scripts/lint/lint-parallel-main.ts +19 -0
- package/scripts/lint/lint-parallel.ts +72 -33
- package/scripts/lint/lint-related-scope.ts +33 -24
- package/scripts/lint/lint-related.ts +38 -6
- package/scripts/notify/confirmation-options.ts +1 -2
- package/scripts/notify/telegram-notify.ts +20 -20
- package/scripts/notify/telegram-test-logic.ts +0 -1
- package/scripts/notify/telegram-test-main.ts +8 -0
- package/scripts/notify/telegram-test.ts +12 -11
- package/scripts/observations/observation-ledger.ts +13 -0
- package/scripts/observations/observations-flush-landing.ts +5 -3
- package/scripts/observations/observations-flush.ts +6 -1
- package/scripts/overrides/overrides-check.ts +2 -5
- package/scripts/overrides/overrides-files.ts +2 -1
- package/scripts/overrides/overrides-logic.ts +3 -6
- package/scripts/package/verify-optional-eslint-install.ts +8 -6
- package/scripts/propagate/propagate-publish.ts +2 -7
- package/scripts/propagate/propagate-targets.ts +4 -12
- package/scripts/refactor/import-graph.ts +9 -7
- package/scripts/release/github-release-runs.ts +17 -6
- package/scripts/release/release-approval-prune.ts +18 -0
- package/scripts/release/release-history.ts +1 -3
- package/scripts/release/release-progress.ts +42 -22
- package/scripts/release/release-publish-run.ts +39 -0
- package/scripts/release/release-publish.ts +6 -6
- package/scripts/release/release-scope-cli.ts +0 -10
- package/scripts/release/release-scope-main.ts +12 -0
- package/scripts/repo/repo-setting.ts +3 -6
- package/scripts/repo/required-checks-logic.ts +6 -15
- package/scripts/report/report-format-reference.ts +4 -0
- package/scripts/report/report-labels.ts +155 -0
- package/scripts/report/report-lint-cli.ts +3 -0
- package/scripts/report/report-lint.ts +85 -110
- package/scripts/report/report-template-cli.ts +59 -0
- package/scripts/report/report-template.ts +112 -0
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +206 -0
- package/scripts/review/removed-tests-check.ts +86 -0
- package/scripts/review/removed-tests.ts +149 -0
- package/scripts/review/review-brief-cli.ts +82 -16
- package/scripts/review/review-brief-main.ts +12 -0
- package/scripts/review/review-brief.ts +31 -3
- package/scripts/review/review-code-tree.ts +10 -6
- package/scripts/review/review-comment-round.ts +26 -8
- package/scripts/review/review-finding-ledger.ts +30 -15
- package/scripts/review/review-interaction.ts +94 -0
- package/scripts/review/review-readers-scan.ts +163 -0
- package/scripts/review/review-record-cli.ts +69 -30
- package/scripts/review/review-record-main.ts +12 -0
- package/scripts/review/review-round-one-blobs.ts +221 -0
- package/scripts/review/review-round2-cli.ts +49 -12
- package/scripts/review/review-round2.ts +80 -12
- package/scripts/review/review-stamps.ts +19 -1
- package/scripts/review/review-stop-log.ts +96 -0
- package/scripts/review/review-stops-cli.ts +85 -0
- package/scripts/review/review-tree.ts +6 -17
- package/scripts/review/review-untouched-readers.ts +146 -0
- package/scripts/review/test-titles.ts +118 -0
- package/scripts/rules/agent-model.ts +67 -0
- package/scripts/rules/bash-triggers.ts +46 -3
- package/scripts/rules/decision-oracle-batch.ts +9 -1
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +90 -3
- package/scripts/rules/destructive-command.ts +8 -1
- package/scripts/rules/direct-filing.ts +10 -2
- package/scripts/rules/direct-issue-comment.ts +117 -0
- package/scripts/rules/direct-pr-create.ts +69 -3
- package/scripts/rules/early-heartbeat.ts +2 -1
- package/scripts/rules/file-body.ts +7 -0
- package/scripts/rules/filing-cap.ts +8 -0
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/git-argv.ts +72 -14
- package/scripts/rules/git-force.ts +12 -2
- package/scripts/rules/guard-remedy.ts +121 -0
- package/scripts/rules/implementation-cut-verdict.ts +1 -1
- package/scripts/rules/implementation-cut.ts +11 -3
- package/scripts/rules/index-guard.ts +8 -1
- package/scripts/rules/issue-comments.ts +76 -7
- package/scripts/rules/josh-git-bare.ts +7 -0
- package/scripts/rules/lane-background.ts +67 -25
- package/scripts/rules/lane-carry-conflict.ts +6 -0
- package/scripts/rules/lane-direct-tool.ts +74 -0
- package/scripts/rules/lane-interactive-ask.ts +9 -2
- package/scripts/rules/lane-park.ts +45 -23
- package/scripts/rules/lane-split-park.ts +10 -2
- package/scripts/rules/lane-switch-main.ts +7 -0
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-consulted.ts +10 -0
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/permission-guards.ts +3 -0
- package/scripts/rules/piped-verification.ts +4 -2
- package/scripts/rules/poll-loop.ts +7 -0
- package/scripts/rules/pr-merge.ts +123 -0
- package/scripts/rules/protected-files.ts +32 -5
- package/scripts/rules/raw-field-body.ts +6 -0
- package/scripts/rules/rule-body-guard.ts +8 -0
- package/scripts/rules/rule-list.ts +12 -28
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value-cache.ts +4 -9
- package/scripts/rules/rule-value-cli.ts +51 -32
- package/scripts/rules/rule-value.ts +8 -2
- package/scripts/rules/shell-segments.ts +50 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rule-rows.ts +64 -0
- package/scripts/rules/stop-rules.ts +150 -51
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/rules/test-declared-commit.ts +11 -1
- package/scripts/rules/third-party-write.ts +7 -0
- package/scripts/rules/timed-rerun.ts +69 -0
- package/scripts/rules/worktree-guard.ts +13 -3
- package/scripts/run/board/run-board-app-name.ts +23 -0
- package/scripts/run/board/run-board-cli.ts +65 -30
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-earlier.ts +94 -0
- package/scripts/run/board/run-board-ending-reason.ts +67 -0
- package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
- package/scripts/run/board/run-board-estimate.ts +98 -0
- package/scripts/run/board/run-board-fit.ts +153 -36
- package/scripts/run/board/run-board-fold.ts +123 -0
- package/scripts/run/board/run-board-fresh.ts +2 -2
- package/scripts/run/board/run-board-gather-live.ts +29 -0
- package/scripts/run/board/run-board-gather-thread.ts +189 -0
- package/scripts/run/board/run-board-gather-worker.ts +29 -0
- package/scripts/run/board/run-board-gather.ts +187 -0
- package/scripts/run/board/run-board-github.ts +119 -31
- package/scripts/run/board/run-board-header.ts +86 -21
- package/scripts/run/board/run-board-keys.ts +58 -0
- package/scripts/run/board/run-board-kind.ts +20 -6
- package/scripts/run/board/run-board-labels.ts +118 -71
- package/scripts/run/board/run-board-lane-state.ts +109 -0
- package/scripts/run/board/run-board-lane-time.ts +122 -0
- package/scripts/run/board/run-board-layout.ts +240 -61
- package/scripts/run/board/run-board-length.ts +52 -0
- package/scripts/run/board/run-board-machine.ts +8 -4
- package/scripts/run/board/run-board-main.ts +12 -0
- package/scripts/run/board/run-board-notes.ts +52 -31
- package/scripts/run/board/run-board-now.ts +1 -1
- package/scripts/run/board/run-board-operation.ts +15 -33
- package/scripts/run/board/run-board-phase.ts +1 -1
- package/scripts/run/board/run-board-plan-shared.ts +115 -0
- package/scripts/run/board/run-board-plan.ts +55 -3
- package/scripts/run/board/run-board-planning.ts +45 -0
- package/scripts/run/board/run-board-priority.ts +44 -0
- package/scripts/run/board/run-board-process-groups.ts +195 -0
- package/scripts/run/board/run-board-read.ts +153 -13
- package/scripts/run/board/run-board-reason.ts +238 -45
- package/scripts/run/board/run-board-released.ts +35 -0
- package/scripts/run/board/run-board-render-checks.ts +39 -5
- package/scripts/run/board/run-board-render-condition.ts +96 -0
- package/scripts/run/board/run-board-render-drawn.ts +67 -0
- package/scripts/run/board/run-board-render-foot.ts +59 -0
- package/scripts/run/board/run-board-render-icon.ts +35 -0
- package/scripts/run/board/run-board-render-lanes.ts +145 -0
- package/scripts/run/board/run-board-render-lead.ts +80 -0
- package/scripts/run/board/run-board-render-legend.ts +117 -47
- package/scripts/run/board/run-board-render-notes.ts +156 -29
- package/scripts/run/board/run-board-render-processes.ts +196 -0
- package/scripts/run/board/run-board-render-section.ts +119 -0
- package/scripts/run/board/run-board-render-slot.ts +3 -36
- package/scripts/run/board/run-board-render-tail.ts +115 -48
- package/scripts/run/board/run-board-render-time.ts +56 -0
- package/scripts/run/board/run-board-render-title.ts +117 -24
- package/scripts/run/board/run-board-render-waits.ts +125 -0
- package/scripts/run/board/run-board-render.ts +206 -259
- package/scripts/run/board/run-board-roots.ts +54 -0
- package/scripts/run/board/run-board-row-yield.ts +10 -4
- package/scripts/run/board/run-board-setup.ts +1 -12
- package/scripts/run/board/run-board-snapshot.ts +111 -0
- package/scripts/run/board/run-board-spin.ts +2 -2
- package/scripts/run/board/run-board-state.ts +23 -29
- package/scripts/run/board/run-board-status.ts +206 -79
- package/scripts/run/board/run-board-thanks-read.ts +2 -2
- package/scripts/run/board/run-board-tick.ts +123 -104
- package/scripts/run/board/run-board-usage-board.ts +78 -0
- package/scripts/run/board/run-board-usage-lanes.ts +113 -0
- package/scripts/run/board/run-board-usage-listing.ts +93 -0
- package/scripts/run/board/run-board-usage-read.ts +120 -150
- package/scripts/run/board/run-board-usage-rusage.ts +19 -7
- package/scripts/run/board/run-board-usage-text.ts +139 -51
- package/scripts/run/board/run-board-usage-top.ts +102 -0
- package/scripts/run/board/run-board-usage.ts +89 -72
- package/scripts/run/board/run-board-usual.ts +20 -9
- package/scripts/run/carry/run-carry-args.ts +4 -7
- package/scripts/run/carry/run-carry-conversation.ts +1 -1
- package/scripts/run/carry/run-carry.ts +9 -4
- package/scripts/run/cut/run-cut-cli.ts +3 -2
- package/scripts/run/cut/run-cut-handoff.ts +2 -2
- package/scripts/run/cut/run-cut-report.ts +16 -0
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-cli.ts +1 -5
- package/scripts/run/event/run-event-filed.ts +12 -6
- package/scripts/run/event/run-event-follow.ts +2 -3
- package/scripts/run/event/run-event-render.ts +7 -10
- package/scripts/run/event/run-event-scope.ts +20 -2
- package/scripts/run/event/run-event-stream-emit.ts +78 -11
- package/scripts/run/event/run-event-stream.ts +37 -7
- package/scripts/run/hold/run-hold-adopt.ts +65 -0
- package/scripts/run/hold/run-hold-cli.ts +93 -22
- package/scripts/run/hold/run-hold-main.ts +12 -0
- package/scripts/run/hold/run-hold-member.ts +37 -0
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +7 -1
- package/scripts/run/hold/run-stop-notify.ts +183 -0
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-auth.ts +31 -0
- package/scripts/run/merge/run-merge-cli.ts +72 -107
- package/scripts/run/merge/run-merge-close.ts +74 -0
- package/scripts/run/merge/run-merge-collect.ts +6 -13
- package/scripts/run/merge/run-merge-driver.ts +71 -0
- package/scripts/run/merge/run-merge-main.ts +12 -0
- package/scripts/run/merge/run-merge-outcome.ts +23 -0
- package/scripts/run/merge/run-merge-restart.ts +39 -0
- package/scripts/run/merge/run-merge-ship.ts +20 -4
- package/scripts/run/merge/run-merge-signals.ts +123 -0
- package/scripts/run/merge/run-merge-steps.ts +128 -83
- package/scripts/run/merge/run-merge.ts +53 -40
- package/scripts/run/park/run-park-cli.ts +91 -0
- package/scripts/run/park/run-park.ts +88 -0
- package/scripts/run/park/run-stalled.ts +68 -0
- package/scripts/run/pause/run-pause-cli.ts +73 -0
- package/scripts/run/pause/run-pause.ts +251 -0
- package/scripts/run/progress/run-progress-cli.ts +4 -12
- package/scripts/run/progress/run-progress-clock.ts +1 -1
- package/scripts/run/progress/run-progress-config.ts +6 -14
- package/scripts/run/progress/run-progress-main.ts +12 -0
- package/scripts/run/progress/run-progress.ts +1 -4
- package/scripts/run/review/run-review.ts +2 -1
- package/scripts/run/run-ending.ts +1 -0
- package/scripts/run/run-invocation.ts +5 -6
- package/scripts/run/run-liveness-cli.ts +6 -8
- package/scripts/run/run-liveness.ts +61 -30
- package/scripts/run/run-next.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +2 -2
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-preflight.ts +18 -3
- package/scripts/run/run-prep-cli.ts +1 -10
- package/scripts/run/run-prep-locate.ts +7 -50
- package/scripts/run/run-prep-main.ts +12 -0
- package/scripts/run/run-prep.ts +6 -0
- package/scripts/run/run-report-cli.ts +101 -13
- package/scripts/run/run-report-handoff.ts +114 -0
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +13 -0
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +1 -1
- package/scripts/run/ship/run-ship-args.ts +121 -0
- package/scripts/run/ship/run-ship-body-draft.ts +110 -0
- package/scripts/run/ship/run-ship-cli.ts +67 -151
- package/scripts/run/ship/run-ship-detach.ts +27 -7
- package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
- package/scripts/run/ship/run-ship-next.ts +27 -3
- package/scripts/run/ship/run-ship-overlap.ts +232 -0
- package/scripts/run/ship/run-ship-place.ts +96 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +102 -27
- package/scripts/run/ship/run-ship-preflight.ts +161 -30
- package/scripts/run/ship/run-ship-probe.ts +11 -3
- package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
- package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
- package/scripts/run/ship/run-ship-return.ts +123 -15
- package/scripts/run/ship/run-ship-review-steps.ts +105 -149
- package/scripts/run/ship/run-ship-review.ts +73 -6
- package/scripts/run/ship/run-ship-reviewer.ts +207 -0
- package/scripts/run/ship/run-ship-stage.ts +55 -6
- package/scripts/run/ship/run-ship-steps.ts +46 -15
- package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-stop-text.ts +11 -6
- package/scripts/run/ship/run-ship-sync.ts +57 -12
- package/scripts/run/ship/run-ship.ts +30 -2
- package/scripts/run/tidy/run-tidy-cli.ts +0 -4
- package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
- package/scripts/run/tidy/run-tidy-main.ts +8 -0
- package/scripts/run/wake/run-wake-cli.ts +119 -100
- package/scripts/run/wake/run-wake-code.ts +83 -0
- package/scripts/run/wake/run-wake-driver.ts +19 -8
- package/scripts/run/wake/run-wake-loop.ts +34 -3
- package/scripts/run/wake/run-wake-main.ts +13 -0
- package/scripts/run/wake/run-wake-ports.ts +90 -0
- package/scripts/run/wake/run-wake-takeover.ts +66 -0
- package/scripts/run/wake/run-wake.ts +2 -1
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -1
- package/scripts/safe-chain/project-config.ts +3 -9
- package/scripts/security/security-audit-main.ts +8 -0
- package/scripts/security/security-audit-provision-logic.ts +0 -11
- package/scripts/security/security-audit-provision-main.ts +12 -0
- package/scripts/security/security-audit-provision.ts +11 -26
- package/scripts/security/security-audit.ts +6 -7
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
- package/scripts/split/split-assess-cli.ts +2 -2
- package/scripts/split/split-assess.ts +15 -0
- package/scripts/split/split-measure.ts +65 -0
- package/scripts/sync/claude-settings-merge.ts +8 -15
- package/scripts/sync/directory-copy-guard.ts +4 -9
- package/scripts/sync/file-content.ts +78 -8
- package/scripts/sync/sync-ai-files.ts +3 -5
- package/scripts/sync/sync-configs.ts +11 -23
- package/scripts/sync/sync-hook-safety.ts +4 -10
- package/scripts/sync/sync-main.ts +11 -0
- package/scripts/sync/sync.ts +25 -37
- package/scripts/test/test-declared-changed.ts +2 -2
- package/scripts/test/test-declared.ts +1 -1
- package/scripts/test/test-e2e-guard.ts +55 -6
- package/scripts/test/test-e2e-stamp.ts +38 -0
- package/scripts/test/test-pinned-logic.ts +145 -0
- package/scripts/test/test-pinned-main.ts +78 -0
- package/scripts/test/test-pinned.ts +100 -0
- package/scripts/test/test-read-map.ts +264 -0
- package/scripts/test/test-read-recording.ts +91 -0
- package/scripts/test/test-read-trace.ts +148 -0
- package/scripts/test/test-red-main.ts +12 -0
- package/scripts/test/test-red.ts +12 -30
- package/scripts/test/test-related-main.ts +18 -0
- package/scripts/test/test-related-record.ts +119 -0
- package/scripts/test/test-related-scope.ts +229 -43
- package/scripts/test/test-related.ts +300 -22
- package/scripts/test/test-unit-guard-main.ts +15 -0
- package/scripts/test/test-unit-guard.ts +54 -21
- package/scripts/test/unit-count-file.ts +37 -0
- package/scripts/test/unit-run-marker.ts +162 -0
- package/scripts/test/unit-setup-files.ts +51 -0
- package/scripts/test/unit-worker-share.ts +71 -137
- package/scripts/test/whole-suite-files.ts +63 -0
- package/scripts/time-runtime/time-background.ts +20 -2
- package/scripts/time-runtime/time-bundles.ts +4 -3
- package/scripts/time-runtime/time-density-hook.ts +8 -6
- package/scripts/time-runtime/time-followup-stage.ts +1 -3
- package/scripts/time-runtime/time-format.ts +5 -28
- package/scripts/time-runtime/time-markers.ts +10 -1
- package/scripts/time-runtime/time-shell.ts +126 -14
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/scripts/time-runtime/time-transcript-line.ts +49 -62
- package/scripts/uninstall/uninstall.ts +1 -1
- package/scripts/version/bump-version-main.ts +12 -0
- package/scripts/version/bump-version.ts +25 -25
- package/scripts/version/effective-upstream.ts +6 -12
- package/scripts/version/latest-corepack.ts +17 -32
- package/scripts/version/latest-if-required-cli.ts +93 -0
- package/scripts/version/latest-lane-guard-main.ts +8 -0
- package/scripts/version/latest-lane-guard.ts +0 -4
- package/scripts/version/latest-scope-cli.ts +0 -9
- package/scripts/version/latest-scope-main.ts +12 -0
- package/scripts/version/latest-update.ts +5 -5
- package/scripts/version/npm-registry.ts +44 -6
- package/scripts/version/publishable-range-check.ts +5 -16
- package/scripts/version/release-age.ts +1 -1
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/release-window.ts +38 -0
- package/scripts/version/running-binary.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +3 -8
- package/scripts/version/version-targets.ts +6 -28
- package/templates/dependabot.yml +29 -0
- package/templates/gitignore +10 -3
- package/templates/pnpm-workspace.basic.yaml +1 -1
- package/templates/sonar-project.properties +3 -2
- package/templates/workflows/ci.yml +12 -4
- package/templates/workflows/github-release.yml +4 -0
- package/tsconfig.sonar.json +1 -1
- package/.ncurc.json +0 -3
- package/dist/hooks/batch-guard.js +0 -29
- package/dist/hooks/chunk-43ZHT22P.js +0 -3495
- package/dist/hooks/chunk-CDY4NFQG.js +0 -15
- package/dist/hooks/chunk-EUMACUK2.js +0 -2038
- package/dist/hooks/chunk-H5HVWYXK.js +0 -359
- package/dist/hooks/chunk-IIGFYXKC.js +0 -7104
- package/dist/hooks/chunk-IX6TTTI6.js +0 -95
- package/dist/hooks/chunk-J47HU5H5.js +0 -237
- package/dist/hooks/chunk-K4EOONYM.js +0 -45
- package/dist/hooks/chunk-K4LMBQC2.js +0 -68
- package/dist/hooks/chunk-SHGPANFB.js +0 -56
- package/dist/hooks/chunk-YHBZAJSV.js +0 -79
- package/dist/hooks/chunk-YYPI7SJZ.js +0 -131
- package/dist/hooks/duplicate-read-guard.js +0 -30
- package/dist/hooks/investigation-guard.js +0 -32
- package/scripts/backlog/backlog-stalled-cli.ts +0 -30
- package/scripts/cost-runtime/cost-format.ts +0 -29
- package/scripts/init/basic-path-migration.ts +0 -24
- package/scripts/issue/issue-backlinks-cli.ts +0 -93
- package/scripts/josh/josh-commands-guard.ts +0 -38
- package/scripts/lint/cross-file-recheck.ts +0 -155
- package/scripts/registry-migration/migrate-logic.ts +0 -237
- package/scripts/registry-migration/migrate.ts +0 -292
- package/scripts/registry-migration/user-npmrc.ts +0 -15
- package/scripts/rules/rule-guard.ts +0 -23
- package/scripts/rules/rule-registry-rows.ts +0 -282
- package/scripts/rules/rule-registry.ts +0 -109
- package/scripts/run/run-stranded-cli.ts +0 -27
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GIT_TIMEOUT_MS,
|
|
3
|
+
MS_PER_MINUTE,
|
|
4
|
+
MS_PER_SECOND,
|
|
3
5
|
PLATFORM_TEMP_ROOT,
|
|
4
6
|
PROBE_TIMEOUT_MS,
|
|
5
7
|
SUITE_TIMEOUT_MS,
|
|
8
|
+
error_text,
|
|
6
9
|
stamp_file
|
|
7
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AZX4FGQ3.js";
|
|
8
11
|
|
|
9
12
|
// scripts/lib/json-value.ts
|
|
10
|
-
function parse_or_undefined(
|
|
13
|
+
function parse_or_undefined(text2) {
|
|
11
14
|
try {
|
|
12
|
-
return JSON.parse(
|
|
15
|
+
return JSON.parse(text2);
|
|
13
16
|
} catch {
|
|
14
17
|
return void 0;
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
|
-
function parse_with(
|
|
18
|
-
const value = parse_or_undefined(
|
|
20
|
+
function parse_with(text2, schema) {
|
|
21
|
+
const value = parse_or_undefined(text2);
|
|
19
22
|
if (value === void 0) return void 0;
|
|
20
23
|
const parsed = schema.safeParse(value);
|
|
21
24
|
return parsed.success ? parsed.data : void 0;
|
|
22
25
|
}
|
|
26
|
+
function parse_array(text2) {
|
|
27
|
+
const value = parse_or_undefined(text2);
|
|
28
|
+
return Array.isArray(value) ? value : void 0;
|
|
29
|
+
}
|
|
23
30
|
function is_record(value) {
|
|
24
31
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25
32
|
}
|
|
26
|
-
var json_value = { parse_or_undefined, parse_with, is_record };
|
|
33
|
+
var json_value = { parse_or_undefined, parse_with, parse_array, is_record };
|
|
27
34
|
|
|
28
35
|
// scripts/git/constants.ts
|
|
29
36
|
import { platform } from "node:os";
|
|
@@ -104,7 +111,6 @@ var git_ssh_keepalive = {
|
|
|
104
111
|
};
|
|
105
112
|
|
|
106
113
|
// scripts/git/git-push-transport.ts
|
|
107
|
-
var MS_PER_SECOND = 1e3;
|
|
108
114
|
var PUSH_TIMEOUT_SECONDS = 120;
|
|
109
115
|
var PUSH_TIMEOUT_MS = PUSH_TIMEOUT_SECONDS * MS_PER_SECOND;
|
|
110
116
|
var PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`;
|
|
@@ -155,10 +161,9 @@ async function read(arguments_, timeout_ms = GIT_TIMEOUT_MS) {
|
|
|
155
161
|
return stdout.trimEnd();
|
|
156
162
|
}
|
|
157
163
|
var REMOTE_TIMEOUT_MS = PUSH_TIMEOUT_MS;
|
|
158
|
-
var MS_PER_SECOND2 = 1e3;
|
|
159
164
|
function to_budget_error(command, error, timeout_ms) {
|
|
160
165
|
if (!has_timed_out(error)) return create_spawn_error(command, get_exit_code(error));
|
|
161
|
-
const seconds = String(Math.round(timeout_ms /
|
|
166
|
+
const seconds = String(Math.round(timeout_ms / MS_PER_SECOND));
|
|
162
167
|
return new Error(`git ${command} timed out after ${seconds}s`, {
|
|
163
168
|
cause: { exit_code: TIMEOUT_EXIT_CODE }
|
|
164
169
|
});
|
|
@@ -220,9 +225,9 @@ async function get_default_branch() {
|
|
|
220
225
|
}
|
|
221
226
|
}
|
|
222
227
|
var MERGE_BASE_COMMAND = "merge-base";
|
|
223
|
-
async function reference_exists(
|
|
228
|
+
async function reference_exists(reference2) {
|
|
224
229
|
try {
|
|
225
|
-
await git_spawn.read(["rev-parse", "--verify", "--quiet",
|
|
230
|
+
await git_spawn.read(["rev-parse", "--verify", "--quiet", reference2]);
|
|
226
231
|
return true;
|
|
227
232
|
} catch {
|
|
228
233
|
return false;
|
|
@@ -250,17 +255,32 @@ var NO_RENAME_DETECTION = "--no-renames";
|
|
|
250
255
|
async function change_base_commit() {
|
|
251
256
|
return await git_spawn.read(["rev-parse", await change_base()]);
|
|
252
257
|
}
|
|
253
|
-
async function
|
|
258
|
+
async function diff_names_since(commit2) {
|
|
254
259
|
return await git_spawn.read([
|
|
255
260
|
...NO_PATH_QUOTING,
|
|
256
261
|
"diff",
|
|
257
262
|
NAME_ONLY_FLAG,
|
|
258
263
|
NO_RELATIVE_PATHS,
|
|
259
264
|
NO_RENAME_DETECTION,
|
|
260
|
-
|
|
265
|
+
commit2,
|
|
261
266
|
"--"
|
|
262
267
|
]);
|
|
263
268
|
}
|
|
269
|
+
async function tree_names_at(commit2, paths) {
|
|
270
|
+
return await git_spawn.read([
|
|
271
|
+
...NO_PATH_QUOTING,
|
|
272
|
+
"ls-tree",
|
|
273
|
+
"-r",
|
|
274
|
+
NAME_ONLY_FLAG,
|
|
275
|
+
"--full-tree",
|
|
276
|
+
commit2,
|
|
277
|
+
"--",
|
|
278
|
+
...paths
|
|
279
|
+
]);
|
|
280
|
+
}
|
|
281
|
+
async function diff_main_names() {
|
|
282
|
+
return await diff_names_since(await change_base());
|
|
283
|
+
}
|
|
264
284
|
async function diff_cached_names() {
|
|
265
285
|
return await git_spawn.read([
|
|
266
286
|
...NO_PATH_QUOTING,
|
|
@@ -303,7 +323,9 @@ var git_diff_reads = {
|
|
|
303
323
|
diff_main,
|
|
304
324
|
diff_main_names,
|
|
305
325
|
diff_main_numstat,
|
|
326
|
+
diff_names_since,
|
|
306
327
|
get_default_branch,
|
|
328
|
+
tree_names_at,
|
|
307
329
|
untracked_names
|
|
308
330
|
};
|
|
309
331
|
|
|
@@ -339,9 +361,9 @@ async function read_push_references() {
|
|
|
339
361
|
return { branch: branch2, local_oid, remote_oid: await read_remote_oid(branch2) };
|
|
340
362
|
}
|
|
341
363
|
function to_stdin_line(references) {
|
|
342
|
-
const
|
|
364
|
+
const reference2 = `refs/heads/${references.branch}`;
|
|
343
365
|
const remote_oid = references.remote_oid ?? ZERO_DIGIT.repeat(references.local_oid.length);
|
|
344
|
-
return `${
|
|
366
|
+
return `${reference2} ${references.local_oid} ${reference2} ${remote_oid}
|
|
345
367
|
`;
|
|
346
368
|
}
|
|
347
369
|
function to_hook_run_arguments(stdin_path, hook_name) {
|
|
@@ -792,10 +814,10 @@ function beacon_target(token) {
|
|
|
792
814
|
if (path2.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
|
|
793
815
|
return is_valid_beacon_name(path2.basename(target)) ? target : void 0;
|
|
794
816
|
}
|
|
795
|
-
function run_socket_probe(target) {
|
|
817
|
+
function run_socket_probe(target, kill_after_ms = PROBE_TIMEOUT_MS) {
|
|
796
818
|
return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
|
|
797
819
|
stdio: "ignore",
|
|
798
|
-
timeout:
|
|
820
|
+
timeout: kill_after_ms
|
|
799
821
|
}).status ?? void 0;
|
|
800
822
|
}
|
|
801
823
|
function is_live_beacon(target, probe = run_socket_probe) {
|
|
@@ -834,6 +856,9 @@ function is_own_process(pid, recorded_start) {
|
|
|
834
856
|
return pid === process.pid && recorded_start === own_start();
|
|
835
857
|
}
|
|
836
858
|
var process_identity = {
|
|
859
|
+
PROBE_ENVIRONMENT,
|
|
860
|
+
START_PROBES,
|
|
861
|
+
START_TIME_FORMAT,
|
|
837
862
|
close_beacon,
|
|
838
863
|
is_live_beacon,
|
|
839
864
|
is_live_pid,
|
|
@@ -845,68 +870,29 @@ var process_identity = {
|
|
|
845
870
|
own_fields,
|
|
846
871
|
own_start,
|
|
847
872
|
read_start,
|
|
848
|
-
resolve_own_start
|
|
873
|
+
resolve_own_start,
|
|
874
|
+
run_socket_probe
|
|
849
875
|
};
|
|
850
876
|
|
|
851
|
-
// scripts/
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
return raw.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
877
|
+
// scripts/issue/issue-number-shape.ts
|
|
878
|
+
var ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u;
|
|
879
|
+
var BAD_ISSUE_MESSAGE = "Not an issue number: ";
|
|
880
|
+
function is_issue_number(value) {
|
|
881
|
+
return ISSUE_NUMBER_PATTERN.test(value);
|
|
857
882
|
}
|
|
858
|
-
|
|
859
|
-
if (
|
|
860
|
-
const tracked = to_paths(await git_command.diff_main_names());
|
|
861
|
-
const untracked = to_paths(await git_command.untracked_names());
|
|
862
|
-
return [...tracked, ...untracked];
|
|
883
|
+
function require_issue_number(issue2) {
|
|
884
|
+
if (!is_issue_number(issue2)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue2}`);
|
|
863
885
|
}
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
var
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
}
|
|
875
|
-
function parse_options(argv) {
|
|
876
|
-
if (has_unknown_flag(argv, KNOWN_FLAGS)) return void 0;
|
|
877
|
-
return { is_staged: argv.includes(STAGED_FLAG), is_json: argv.includes(JSON_FLAG) };
|
|
878
|
-
}
|
|
879
|
-
function format_path_list(paths) {
|
|
880
|
-
const listed = paths.slice(0, MAX_LISTED_PATHS).join(", ");
|
|
881
|
-
if (paths.length <= MAX_LISTED_PATHS) return listed;
|
|
882
|
-
return `${listed}, +${String(paths.length - MAX_LISTED_PATHS)} more`;
|
|
883
|
-
}
|
|
884
|
-
function print_decision(key, answer, reason, is_json) {
|
|
885
|
-
if (is_json) {
|
|
886
|
-
console.info(JSON.stringify({ [key]: answer, reason }));
|
|
887
|
-
return;
|
|
888
|
-
}
|
|
889
|
-
console.info(answer);
|
|
890
|
-
console.error(reason);
|
|
891
|
-
}
|
|
892
|
-
async function run_path_decision(argv, command) {
|
|
893
|
-
const options = parse_options(argv);
|
|
894
|
-
if (options === void 0) {
|
|
895
|
-
console.error(command.usage);
|
|
896
|
-
return FAILURE_EXIT_CODE;
|
|
897
|
-
}
|
|
898
|
-
const paths = await changed_paths.read_changed_paths(options.is_staged);
|
|
899
|
-
const answer = command.decide(paths);
|
|
900
|
-
print_decision(command.key, answer, command.explain(paths, answer), options.is_json);
|
|
901
|
-
return 0;
|
|
902
|
-
}
|
|
903
|
-
var path_decision = {
|
|
904
|
-
format_path_list,
|
|
905
|
-
has_unknown_flag,
|
|
906
|
-
JSON_FLAG,
|
|
907
|
-
parse_options,
|
|
908
|
-
print_decision,
|
|
909
|
-
run_path_decision
|
|
886
|
+
function single_of(positionals) {
|
|
887
|
+
const [issue_number, ...rest] = positionals;
|
|
888
|
+
const is_single = rest.length === 0 && issue_number !== void 0;
|
|
889
|
+
return is_single && ISSUE_NUMBER_PATTERN.test(issue_number) ? issue_number : void 0;
|
|
890
|
+
}
|
|
891
|
+
var issue_number_shape = {
|
|
892
|
+
ISSUE_NUMBER_PATTERN,
|
|
893
|
+
is_issue_number,
|
|
894
|
+
require_issue_number,
|
|
895
|
+
single_of
|
|
910
896
|
};
|
|
911
897
|
|
|
912
898
|
// scripts/lib/cli-flags.ts
|
|
@@ -981,7 +967,30 @@ function attach_values(argv, flags) {
|
|
|
981
967
|
for (const argument of argv) attach_one(attached, argument, flags);
|
|
982
968
|
return attached;
|
|
983
969
|
}
|
|
970
|
+
var COUNT_PATTERN = /^\d+$/u;
|
|
971
|
+
var POSITIVE_PATTERN = /^[1-9]\d*$/u;
|
|
972
|
+
function to_integer(raw, pattern) {
|
|
973
|
+
if (raw === void 0 || !pattern.test(raw)) return void 0;
|
|
974
|
+
const parsed = Number(raw);
|
|
975
|
+
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
976
|
+
}
|
|
977
|
+
function to_count(raw) {
|
|
978
|
+
return to_integer(raw, COUNT_PATTERN);
|
|
979
|
+
}
|
|
980
|
+
function to_positive(raw) {
|
|
981
|
+
return to_integer(raw, POSITIVE_PATTERN);
|
|
982
|
+
}
|
|
983
|
+
function read_positive_setting(raw, name, fallback) {
|
|
984
|
+
const trimmed = raw?.trim() ?? "";
|
|
985
|
+
if (trimmed === "") return { kind: "limit", limit: fallback };
|
|
986
|
+
const limit = to_positive(trimmed);
|
|
987
|
+
if (limit !== void 0) return { kind: "limit", limit };
|
|
988
|
+
return { kind: "problem", problem: `${name} must be a positive integer, not "${trimmed}"` };
|
|
989
|
+
}
|
|
984
990
|
var cli_flags = {
|
|
991
|
+
to_count,
|
|
992
|
+
to_positive,
|
|
993
|
+
read_positive_setting,
|
|
985
994
|
attach_values,
|
|
986
995
|
usage_line,
|
|
987
996
|
refuse_unknown_flags,
|
|
@@ -995,258 +1004,11 @@ var cli_flags = {
|
|
|
995
1004
|
is_value_unusable
|
|
996
1005
|
};
|
|
997
1006
|
|
|
998
|
-
// scripts/backlog/backlog-budget.ts
|
|
999
|
-
var MS_PER_MINUTE = 6e4;
|
|
1000
|
-
var MINUTES_PER_HOUR = 60;
|
|
1001
|
-
var IDLE_WAIT_HOURS = 8;
|
|
1002
|
-
var DEFAULT_IDLE_MINUTES = IDLE_WAIT_HOURS * MINUTES_PER_HOUR;
|
|
1003
|
-
var DEFAULT_IDLE_MS = DEFAULT_IDLE_MINUTES * MS_PER_MINUTE;
|
|
1004
|
-
var OFFER_INTERVAL_SECONDS = 60;
|
|
1005
|
-
var MS_PER_SECOND3 = 1e3;
|
|
1006
|
-
var OFFER_INTERVAL_MS = OFFER_INTERVAL_SECONDS * MS_PER_SECOND3;
|
|
1007
|
-
var RUN_VERDICT = "run";
|
|
1008
|
-
var WATCH_VERDICT = "watch";
|
|
1009
|
-
var STOP_VERDICT = "stop";
|
|
1010
|
-
var TRIAGE_VERDICT = "triage";
|
|
1011
|
-
var ANSWERS = ["blocked", "candidates", "exhausted", "parked", "unreadable", "untriaged"];
|
|
1012
|
-
var BLOCKED_REASON = "Everything opted in is blocked or already running, so waiting can still change the answer. Poll again at the polling interval.";
|
|
1013
|
-
var TRIAGE_REASON = "An opted-in candidate carries neither `run:solo` nor `run:lane`, so nothing starts until it is judged. Read each issue named above, record its order and one of the two labels with a comment, then ask again.";
|
|
1014
|
-
var EMPTY_BACKLOG = "The backlog is empty";
|
|
1015
|
-
var WAITING_ON = {
|
|
1016
|
-
exhausted: EMPTY_BACKLOG,
|
|
1017
|
-
parked: "Nothing opted in can proceed without a person",
|
|
1018
|
-
unreadable: "The backlog listing could not be read"
|
|
1019
|
-
};
|
|
1020
|
-
function waiting_on(answer) {
|
|
1021
|
-
return WAITING_ON[answer] ?? EMPTY_BACKLOG;
|
|
1022
|
-
}
|
|
1023
|
-
function no_idle_watch_reason(answer) {
|
|
1024
|
-
return `${waiting_on(answer)} and the idle watch was turned off with \`--idle 0\`, so the run finishes here.`;
|
|
1025
|
-
}
|
|
1026
|
-
function to_minutes(duration_ms) {
|
|
1027
|
-
return String(Math.ceil(duration_ms / MS_PER_MINUTE));
|
|
1028
|
-
}
|
|
1029
|
-
function max_reached_reason(merged, max_issues) {
|
|
1030
|
-
return `This run's maximum of ${String(max_issues)} is reached, with ${String(merged)} merged. Report what was done, including how many were picked up during an idle watch, and finish.`;
|
|
1031
|
-
}
|
|
1032
|
-
function draining_reason(running, reason) {
|
|
1033
|
-
return `Start nothing more and poll until the running children merge (running: ${String(running)}). Then report and finish \u2014 ${reason}`;
|
|
1034
|
-
}
|
|
1035
|
-
function idle_expired_reason(answer, idle_budget_ms) {
|
|
1036
|
-
return `${waiting_on(answer)}, and stayed so for the whole ${to_minutes(idle_budget_ms)}-minute idle watch. Report what was done, including how many were picked up during the watch, and finish.`;
|
|
1037
|
-
}
|
|
1038
|
-
function idle_watch_reason(answer, left_ms) {
|
|
1039
|
-
return `${waiting_on(answer)} and the idle watch has about ${to_minutes(left_ms)} minutes left. Release the working tree, ask again in ${String(OFFER_INTERVAL_SECONDS)} seconds, and restart the watch the moment a candidate appears.`;
|
|
1040
|
-
}
|
|
1041
|
-
function running_watch_reason(answer, running, left_ms) {
|
|
1042
|
-
return `${waiting_on(answer)} and the idle watch has about ${to_minutes(left_ms)} minutes left, with ${String(running)} still running. Keep the working tree until they merge and poll at the polling interval \u2014 the watch is running down meanwhile.`;
|
|
1043
|
-
}
|
|
1044
|
-
function watching_reason(input, left_ms) {
|
|
1045
|
-
if (input.running === 0) return idle_watch_reason(input.answer, left_ms);
|
|
1046
|
-
return running_watch_reason(input.answer, input.running, left_ms);
|
|
1047
|
-
}
|
|
1048
|
-
function taken_by(input) {
|
|
1049
|
-
return input.merged + input.running;
|
|
1050
|
-
}
|
|
1051
|
-
function run_reason(input) {
|
|
1052
|
-
const { max_issues } = input;
|
|
1053
|
-
if (max_issues === void 0) return "No maximum was given, so start every issue offered.";
|
|
1054
|
-
return `Start at most ${String(max_issues - taken_by(input))} more: this run's maximum is ${String(max_issues)}, with ${String(input.merged)} merged and ${String(input.running)} running.`;
|
|
1055
|
-
}
|
|
1056
|
-
function stopping(input, reason) {
|
|
1057
|
-
if (input.running === 0) return { verdict: STOP_VERDICT, reason };
|
|
1058
|
-
return { verdict: WATCH_VERDICT, reason: draining_reason(input.running, reason) };
|
|
1059
|
-
}
|
|
1060
|
-
function max_decision(input) {
|
|
1061
|
-
const { max_issues } = input;
|
|
1062
|
-
if (max_issues === void 0 || taken_by(input) < max_issues) return void 0;
|
|
1063
|
-
return stopping(input, max_reached_reason(input.merged, max_issues));
|
|
1064
|
-
}
|
|
1065
|
-
function idle_decision(input) {
|
|
1066
|
-
const { idle_budget_ms } = input;
|
|
1067
|
-
if (idle_budget_ms === void 0) return stopping(input, no_idle_watch_reason(input.answer));
|
|
1068
|
-
const left_ms = idle_budget_ms - (input.now_ms - input.active_at_ms);
|
|
1069
|
-
if (left_ms > 0) return { verdict: WATCH_VERDICT, reason: watching_reason(input, left_ms) };
|
|
1070
|
-
return stopping(input, idle_expired_reason(input.answer, idle_budget_ms));
|
|
1071
|
-
}
|
|
1072
|
-
function is_finish(input) {
|
|
1073
|
-
return input.answer === "exhausted" && max_decision(input) === void 0;
|
|
1074
|
-
}
|
|
1075
|
-
var FIXED_DECISIONS = {
|
|
1076
|
-
blocked: { verdict: WATCH_VERDICT, reason: BLOCKED_REASON },
|
|
1077
|
-
untriaged: { verdict: TRIAGE_VERDICT, reason: TRIAGE_REASON }
|
|
1078
|
-
};
|
|
1079
|
-
function answer_decision(input) {
|
|
1080
|
-
if (input.answer === "candidates") return { verdict: RUN_VERDICT, reason: run_reason(input) };
|
|
1081
|
-
return FIXED_DECISIONS[input.answer] ?? idle_decision(input);
|
|
1082
|
-
}
|
|
1083
|
-
function decide(input) {
|
|
1084
|
-
return max_decision(input) ?? answer_decision(input);
|
|
1085
|
-
}
|
|
1086
|
-
var backlog_budget = {
|
|
1087
|
-
ANSWERS,
|
|
1088
|
-
BLOCKED_REASON,
|
|
1089
|
-
DEFAULT_IDLE_MINUTES,
|
|
1090
|
-
DEFAULT_IDLE_MS,
|
|
1091
|
-
IDLE_WAIT_HOURS,
|
|
1092
|
-
MS_PER_MINUTE,
|
|
1093
|
-
OFFER_INTERVAL_MS,
|
|
1094
|
-
RUN_VERDICT,
|
|
1095
|
-
STOP_VERDICT,
|
|
1096
|
-
TRIAGE_REASON,
|
|
1097
|
-
TRIAGE_VERDICT,
|
|
1098
|
-
WAITING_ON,
|
|
1099
|
-
WATCH_VERDICT,
|
|
1100
|
-
decide,
|
|
1101
|
-
draining_reason,
|
|
1102
|
-
idle_expired_reason,
|
|
1103
|
-
idle_watch_reason,
|
|
1104
|
-
is_finish,
|
|
1105
|
-
max_reached_reason,
|
|
1106
|
-
no_idle_watch_reason,
|
|
1107
|
-
run_reason,
|
|
1108
|
-
running_watch_reason,
|
|
1109
|
-
taken_by
|
|
1110
|
-
};
|
|
1111
|
-
|
|
1112
|
-
// scripts/backlog/backlog-budget-cli.ts
|
|
1113
|
-
var ARGV_OFFSET = 2;
|
|
1114
|
-
var SUCCESS_EXIT_CODE2 = 0;
|
|
1115
|
-
var FAILURE_EXIT_CODE2 = 1;
|
|
1116
|
-
var JSON_KEY = "budget";
|
|
1117
|
-
var USAGE = `Usage: josh backlog:budget --answer <${backlog_budget.ANSWERS.join("|")}> --started <ISO-8601> [--active <ISO-8601>, required unless the watch is off] [--merged <count>] [--running <count>] [--max <count>] [--idle <minutes>, 0 to turn the watch off] [--json]`;
|
|
1118
|
-
var OPTIONS = {
|
|
1119
|
-
active: { type: "string" },
|
|
1120
|
-
answer: { type: "string" },
|
|
1121
|
-
idle: { type: "string" },
|
|
1122
|
-
json: { type: "boolean" },
|
|
1123
|
-
max: { type: "string" },
|
|
1124
|
-
merged: { type: "string" },
|
|
1125
|
-
running: { type: "string" },
|
|
1126
|
-
started: { type: "string" }
|
|
1127
|
-
};
|
|
1128
|
-
function read_arguments(argv) {
|
|
1129
|
-
return cli_flags.values_of(argv, OPTIONS);
|
|
1130
|
-
}
|
|
1131
|
-
function to_answer(raw) {
|
|
1132
|
-
return backlog_budget.ANSWERS.find((answer) => answer === raw);
|
|
1133
|
-
}
|
|
1134
|
-
function to_time_ms(raw) {
|
|
1135
|
-
if (raw === void 0) return void 0;
|
|
1136
|
-
const parsed = Date.parse(raw);
|
|
1137
|
-
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
1138
|
-
}
|
|
1139
|
-
var COUNT_PATTERN = /^\d+$/u;
|
|
1140
|
-
function to_count(raw) {
|
|
1141
|
-
if (raw === void 0 || !COUNT_PATTERN.test(raw)) return void 0;
|
|
1142
|
-
const parsed = Number(raw);
|
|
1143
|
-
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
1144
|
-
}
|
|
1145
|
-
function is_readable(raw, parsed) {
|
|
1146
|
-
return raw === void 0 || parsed !== void 0;
|
|
1147
|
-
}
|
|
1148
|
-
var COUNT_NAMES = ["idle", "max", "merged", "running"];
|
|
1149
|
-
function counts_of(values) {
|
|
1150
|
-
return {
|
|
1151
|
-
idle: to_count(cli_flags.string_of(values.idle)),
|
|
1152
|
-
max: to_count(cli_flags.string_of(values.max)),
|
|
1153
|
-
merged: to_count(cli_flags.string_of(values.merged)),
|
|
1154
|
-
running: to_count(cli_flags.string_of(values.running))
|
|
1155
|
-
};
|
|
1156
|
-
}
|
|
1157
|
-
function are_counts_readable(values, counts) {
|
|
1158
|
-
return COUNT_NAMES.every((name) => is_readable(cli_flags.string_of(values[name]), counts[name]));
|
|
1159
|
-
}
|
|
1160
|
-
var NO_IDLE_MINUTES = 0;
|
|
1161
|
-
function to_idle_ms(idle_minutes) {
|
|
1162
|
-
if (idle_minutes === void 0) return backlog_budget.DEFAULT_IDLE_MS;
|
|
1163
|
-
if (idle_minutes === NO_IDLE_MINUTES) return void 0;
|
|
1164
|
-
return idle_minutes * backlog_budget.MS_PER_MINUTE;
|
|
1165
|
-
}
|
|
1166
|
-
function is_watch_readable(values) {
|
|
1167
|
-
if (to_idle_ms(to_count(cli_flags.string_of(values.idle))) === void 0) return true;
|
|
1168
|
-
return cli_flags.string_of(values.active) !== void 0;
|
|
1169
|
-
}
|
|
1170
|
-
function are_values_readable(values) {
|
|
1171
|
-
return is_readable(
|
|
1172
|
-
cli_flags.string_of(values.active),
|
|
1173
|
-
to_time_ms(cli_flags.string_of(values.active))
|
|
1174
|
-
) && is_watch_readable(values) && are_counts_readable(values, counts_of(values));
|
|
1175
|
-
}
|
|
1176
|
-
function input_of(values, base) {
|
|
1177
|
-
const counts = counts_of(values);
|
|
1178
|
-
return {
|
|
1179
|
-
...base,
|
|
1180
|
-
active_at_ms: to_time_ms(cli_flags.string_of(values.active)) ?? base.started_at_ms,
|
|
1181
|
-
merged: counts.merged ?? 0,
|
|
1182
|
-
running: counts.running ?? 0,
|
|
1183
|
-
max_issues: counts.max,
|
|
1184
|
-
idle_budget_ms: to_idle_ms(counts.idle)
|
|
1185
|
-
};
|
|
1186
|
-
}
|
|
1187
|
-
function build_input(values, now_ms) {
|
|
1188
|
-
const answer = to_answer(cli_flags.string_of(values.answer));
|
|
1189
|
-
if (answer === void 0) return void 0;
|
|
1190
|
-
const started_at_ms = to_time_ms(cli_flags.string_of(values.started));
|
|
1191
|
-
if (started_at_ms === void 0 || !are_values_readable(values)) return void 0;
|
|
1192
|
-
return input_of(values, { answer, now_ms, started_at_ms });
|
|
1193
|
-
}
|
|
1194
|
-
function print_json(input, decision) {
|
|
1195
|
-
const { verdict, reason } = decision;
|
|
1196
|
-
const is_finish2 = backlog_budget.is_finish(input);
|
|
1197
|
-
console.info(JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: is_finish2 }));
|
|
1198
|
-
}
|
|
1199
|
-
function refuse() {
|
|
1200
|
-
console.error(USAGE);
|
|
1201
|
-
return FAILURE_EXIT_CODE2;
|
|
1202
|
-
}
|
|
1203
|
-
function run3(argv, now_ms = Date.now()) {
|
|
1204
|
-
const values = read_arguments(argv);
|
|
1205
|
-
if (values === void 0) return refuse();
|
|
1206
|
-
const input = build_input(values, now_ms);
|
|
1207
|
-
if (input === void 0) return refuse();
|
|
1208
|
-
const decision = backlog_budget.decide(input);
|
|
1209
|
-
if (values.json === true) {
|
|
1210
|
-
print_json(input, decision);
|
|
1211
|
-
return SUCCESS_EXIT_CODE2;
|
|
1212
|
-
}
|
|
1213
|
-
path_decision.print_decision(JSON_KEY, decision.verdict, decision.reason, false);
|
|
1214
|
-
return SUCCESS_EXIT_CODE2;
|
|
1215
|
-
}
|
|
1216
|
-
function main(argv) {
|
|
1217
|
-
process.exitCode = run3(argv);
|
|
1218
|
-
}
|
|
1219
|
-
var backlog_budget_cli = {
|
|
1220
|
-
JSON_KEY,
|
|
1221
|
-
OPTIONS,
|
|
1222
|
-
SUCCESS_EXIT_CODE: SUCCESS_EXIT_CODE2,
|
|
1223
|
-
USAGE,
|
|
1224
|
-
build_input,
|
|
1225
|
-
main,
|
|
1226
|
-
read_arguments,
|
|
1227
|
-
run: run3,
|
|
1228
|
-
to_answer,
|
|
1229
|
-
to_count,
|
|
1230
|
-
to_time_ms
|
|
1231
|
-
};
|
|
1232
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
|
|
1233
|
-
|
|
1234
|
-
// scripts/issue/issue-number-shape.ts
|
|
1235
|
-
var ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u;
|
|
1236
|
-
var BAD_ISSUE_MESSAGE = "Not an issue number: ";
|
|
1237
|
-
function is_issue_number(value) {
|
|
1238
|
-
return ISSUE_NUMBER_PATTERN.test(value);
|
|
1239
|
-
}
|
|
1240
|
-
function require_issue_number(issue) {
|
|
1241
|
-
if (!is_issue_number(issue)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue}`);
|
|
1242
|
-
}
|
|
1243
|
-
var issue_number_shape = { ISSUE_NUMBER_PATTERN, is_issue_number, require_issue_number };
|
|
1244
|
-
|
|
1245
1007
|
// scripts/run/run-invocation.ts
|
|
1246
1008
|
var BACKLOG_COMMAND = "backlogrun";
|
|
1247
|
-
var
|
|
1009
|
+
var KNOWN_FLAGS = ["--max", "--idle"];
|
|
1248
1010
|
var ONLY_FLAG = "--only";
|
|
1249
|
-
var
|
|
1011
|
+
var OPTIONS = {
|
|
1250
1012
|
max: { type: "string" },
|
|
1251
1013
|
idle: { type: "string" },
|
|
1252
1014
|
only: { type: "boolean" }
|
|
@@ -1263,8 +1025,8 @@ function tokens_of(invocation) {
|
|
|
1263
1025
|
}
|
|
1264
1026
|
function render_option(token) {
|
|
1265
1027
|
if (token.name === cli_flags.option_name(ONLY_FLAG)) return ONLY_FLAG;
|
|
1266
|
-
const flag =
|
|
1267
|
-
const value =
|
|
1028
|
+
const flag = KNOWN_FLAGS.find((known) => cli_flags.option_name(known) === token.name);
|
|
1029
|
+
const value = cli_flags.to_count(token.value);
|
|
1268
1030
|
if (flag === void 0 || value === void 0) return void 0;
|
|
1269
1031
|
return `${flag} ${String(value)}`;
|
|
1270
1032
|
}
|
|
@@ -1281,15 +1043,15 @@ function issue_of(token) {
|
|
|
1281
1043
|
if (!token.startsWith(ISSUE_PREFIX)) return void 0;
|
|
1282
1044
|
const digits = token.slice(ISSUE_PREFIX.length);
|
|
1283
1045
|
if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(digits)) return void 0;
|
|
1284
|
-
const
|
|
1285
|
-
return Number.isSafeInteger(
|
|
1046
|
+
const issue2 = Number(digits);
|
|
1047
|
+
return Number.isSafeInteger(issue2) ? issue2 : void 0;
|
|
1286
1048
|
}
|
|
1287
1049
|
function issues_of(tokens) {
|
|
1288
1050
|
const issues = [];
|
|
1289
1051
|
for (const token of tokens) {
|
|
1290
|
-
const
|
|
1291
|
-
if (
|
|
1292
|
-
issues.push(
|
|
1052
|
+
const issue2 = issue_of(token.value ?? "");
|
|
1053
|
+
if (issue2 === void 0) return void 0;
|
|
1054
|
+
issues.push(issue2);
|
|
1293
1055
|
}
|
|
1294
1056
|
return issues;
|
|
1295
1057
|
}
|
|
@@ -1298,7 +1060,7 @@ function argument_tokens(invocation) {
|
|
|
1298
1060
|
if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
|
|
1299
1061
|
return cli_flags.parse_or_undefined({
|
|
1300
1062
|
args: tokens.slice(FIRST_ARGUMENT_INDEX),
|
|
1301
|
-
options:
|
|
1063
|
+
options: OPTIONS,
|
|
1302
1064
|
allowPositionals: true,
|
|
1303
1065
|
tokens: true
|
|
1304
1066
|
})?.tokens;
|
|
@@ -1313,8 +1075,8 @@ function parse(invocation) {
|
|
|
1313
1075
|
if (issues === void 0 || flags === void 0) return void 0;
|
|
1314
1076
|
return { issues, flags };
|
|
1315
1077
|
}
|
|
1316
|
-
function issue_token(
|
|
1317
|
-
return `${ISSUE_PREFIX}${String(
|
|
1078
|
+
function issue_token(issue2) {
|
|
1079
|
+
return `${ISSUE_PREFIX}${String(issue2)}`;
|
|
1318
1080
|
}
|
|
1319
1081
|
function joined(command, rendered) {
|
|
1320
1082
|
return [command, ...rendered].join(TOKEN_SEPARATOR);
|
|
@@ -1323,7 +1085,7 @@ function rebuild(invocation) {
|
|
|
1323
1085
|
const parsed = parse(invocation);
|
|
1324
1086
|
if (parsed === void 0) return void 0;
|
|
1325
1087
|
return joined(BACKLOG_COMMAND, [
|
|
1326
|
-
...parsed.issues.map((
|
|
1088
|
+
...parsed.issues.map((issue2) => issue_token(issue2)),
|
|
1327
1089
|
...parsed.flags
|
|
1328
1090
|
]);
|
|
1329
1091
|
}
|
|
@@ -1353,7 +1115,7 @@ function issues_of2(added, is_priority) {
|
|
|
1353
1115
|
}
|
|
1354
1116
|
function ordered(declared, added = []) {
|
|
1355
1117
|
const sequence = [...issues_of2(added, true), ...declared, ...issues_of2(added, false)];
|
|
1356
|
-
return sequence.filter((
|
|
1118
|
+
return sequence.filter((issue2, index) => sequence.indexOf(issue2) === index);
|
|
1357
1119
|
}
|
|
1358
1120
|
function next_added(carry, additions) {
|
|
1359
1121
|
const next = [...carry.added ?? []];
|
|
@@ -1416,14 +1178,14 @@ function next_done(carry, done) {
|
|
|
1416
1178
|
const current = carry.done ?? [];
|
|
1417
1179
|
return current.includes(done) ? current : [...current, done];
|
|
1418
1180
|
}
|
|
1419
|
-
function next_merged_issues(carry,
|
|
1420
|
-
if (
|
|
1181
|
+
function next_merged_issues(carry, issue2) {
|
|
1182
|
+
if (issue2 === void 0) return carry.merged_issues;
|
|
1421
1183
|
const current = carry.merged_issues ?? [];
|
|
1422
|
-
return current.includes(
|
|
1184
|
+
return current.includes(issue2) ? current : [...current, issue2];
|
|
1423
1185
|
}
|
|
1424
1186
|
function is_duplicate_merge(carry, change) {
|
|
1425
|
-
const
|
|
1426
|
-
return
|
|
1187
|
+
const issue2 = change.merged_issue;
|
|
1188
|
+
return issue2 !== void 0 && carry.merged_issues?.includes(issue2) === true;
|
|
1427
1189
|
}
|
|
1428
1190
|
function has_other_change(change) {
|
|
1429
1191
|
const amounts = [change.filed, change.cuts, change.failures, change.outages];
|
|
@@ -1484,8 +1246,8 @@ function lane_root(repository_root2, environment = process.env) {
|
|
|
1484
1246
|
const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
|
|
1485
1247
|
return configured.length === 0 ? default_lane_root(repository_root2) : path3.resolve(configured);
|
|
1486
1248
|
}
|
|
1487
|
-
function lane_directory(root,
|
|
1488
|
-
return path3.join(root,
|
|
1249
|
+
function lane_directory(root, issue2) {
|
|
1250
|
+
return path3.join(root, issue2);
|
|
1489
1251
|
}
|
|
1490
1252
|
var DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, "u");
|
|
1491
1253
|
function is_lane_root(directory, environment) {
|
|
@@ -1495,12 +1257,12 @@ function is_lane_root(directory, environment) {
|
|
|
1495
1257
|
}
|
|
1496
1258
|
function lane_issue_of(directory, environment = process.env) {
|
|
1497
1259
|
const resolved = path3.resolve(directory);
|
|
1498
|
-
const
|
|
1499
|
-
if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(
|
|
1500
|
-
return is_lane_root(path3.dirname(resolved), environment) ?
|
|
1260
|
+
const issue2 = path3.basename(resolved);
|
|
1261
|
+
if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue2)) return void 0;
|
|
1262
|
+
return is_lane_root(path3.dirname(resolved), environment) ? issue2 : void 0;
|
|
1501
1263
|
}
|
|
1502
|
-
function lane_branch(
|
|
1503
|
-
return `${
|
|
1264
|
+
function lane_branch(issue2) {
|
|
1265
|
+
return `${issue2}${LANE_BRANCH_SUFFIX}`;
|
|
1504
1266
|
}
|
|
1505
1267
|
var SEAT_LOCK_DIR = ".seat-locks";
|
|
1506
1268
|
function is_lane_entry(name) {
|
|
@@ -1524,25 +1286,25 @@ var ABSENT_CODE = "ENOENT";
|
|
|
1524
1286
|
function is_absent(error) {
|
|
1525
1287
|
return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
|
|
1526
1288
|
}
|
|
1527
|
-
function read_optional(
|
|
1289
|
+
function read_optional(path11) {
|
|
1528
1290
|
try {
|
|
1529
|
-
return readFileSync2(
|
|
1291
|
+
return readFileSync2(path11, "utf8");
|
|
1530
1292
|
} catch (error) {
|
|
1531
1293
|
if (is_absent(error)) return void 0;
|
|
1532
1294
|
throw error;
|
|
1533
1295
|
}
|
|
1534
1296
|
}
|
|
1535
|
-
function read_file_or_empty(
|
|
1536
|
-
return read_optional(
|
|
1297
|
+
function read_file_or_empty(path11) {
|
|
1298
|
+
return read_optional(path11) ?? "";
|
|
1537
1299
|
}
|
|
1538
|
-
function read_if_readable(
|
|
1300
|
+
function read_if_readable(path11) {
|
|
1539
1301
|
try {
|
|
1540
|
-
return readFileSync2(
|
|
1302
|
+
return readFileSync2(path11, "utf8");
|
|
1541
1303
|
} catch {
|
|
1542
1304
|
return void 0;
|
|
1543
1305
|
}
|
|
1544
1306
|
}
|
|
1545
|
-
var file_reader = { read_optional, read_file_or_empty, read_if_readable };
|
|
1307
|
+
var file_reader = { is_absent, read_optional, read_file_or_empty, read_if_readable };
|
|
1546
1308
|
|
|
1547
1309
|
// scripts/time-runtime/time-instant.ts
|
|
1548
1310
|
function parse_instant(raw) {
|
|
@@ -1734,9 +1496,9 @@ function lane_transcript_directories(main_cwd, home) {
|
|
|
1734
1496
|
).map((name) => path4.join(projects, name));
|
|
1735
1497
|
}
|
|
1736
1498
|
function transcript_directories(cwd, home = homedir()) {
|
|
1737
|
-
const
|
|
1499
|
+
const own2 = transcript_directory(cwd, home);
|
|
1738
1500
|
const lanes = session_cwd(cwd) === cwd ? lane_transcript_directories(cwd, home) : [];
|
|
1739
|
-
return [.../* @__PURE__ */ new Set([
|
|
1501
|
+
return [.../* @__PURE__ */ new Set([own2, ...lanes])];
|
|
1740
1502
|
}
|
|
1741
1503
|
var OWN_DEPTH = 0;
|
|
1742
1504
|
function home_directory() {
|
|
@@ -1797,9 +1559,9 @@ function list_sessions(directory) {
|
|
|
1797
1559
|
(left, right) => right.modified_ms - left.modified_ms
|
|
1798
1560
|
);
|
|
1799
1561
|
}
|
|
1800
|
-
function list_sessions_across(
|
|
1562
|
+
function list_sessions_across(directories2) {
|
|
1801
1563
|
const seen = /* @__PURE__ */ new Set();
|
|
1802
|
-
const merged =
|
|
1564
|
+
const merged = directories2.flatMap((directory) => list_sessions(directory));
|
|
1803
1565
|
const newest_first = merged.toSorted((left, right) => right.modified_ms - left.modified_ms);
|
|
1804
1566
|
const kept = [];
|
|
1805
1567
|
for (const file of newest_first) {
|
|
@@ -1863,8 +1625,8 @@ function directory_exists(directory) {
|
|
|
1863
1625
|
return false;
|
|
1864
1626
|
}
|
|
1865
1627
|
}
|
|
1866
|
-
function searched_directories(
|
|
1867
|
-
return
|
|
1628
|
+
function searched_directories(directories2) {
|
|
1629
|
+
return directories2.map((directory) => ({
|
|
1868
1630
|
path: directory,
|
|
1869
1631
|
exists: directory_exists(directory)
|
|
1870
1632
|
}));
|
|
@@ -1890,6 +1652,7 @@ var cost_transcript = {
|
|
|
1890
1652
|
transcript_directory,
|
|
1891
1653
|
transcript_directories,
|
|
1892
1654
|
session_cwd,
|
|
1655
|
+
lane_transcript_directories,
|
|
1893
1656
|
unit_directory,
|
|
1894
1657
|
list_sessions,
|
|
1895
1658
|
list_sessions_across,
|
|
@@ -2009,11 +1772,11 @@ var own_session = {
|
|
|
2009
1772
|
|
|
2010
1773
|
// scripts/run/carry/run-carry-conversation.ts
|
|
2011
1774
|
var CONVERSATION_QUIET_MS = 6e5;
|
|
2012
|
-
function own_transcript(environment = process.env,
|
|
1775
|
+
function own_transcript(environment = process.env, directories2 = cost_transcript.transcript_directories(process.cwd())) {
|
|
2013
1776
|
const session_id = own_session.session_id_of(environment);
|
|
2014
1777
|
if (session_id === void 0) return void 0;
|
|
2015
1778
|
const name = `${session_id}${cost_transcript.TRANSCRIPT_EXTENSION}`;
|
|
2016
|
-
return
|
|
1779
|
+
return directories2.map((directory) => path5.join(directory, name)).find((file) => existsSync(file));
|
|
2017
1780
|
}
|
|
2018
1781
|
function modified_ms(transcript) {
|
|
2019
1782
|
try {
|
|
@@ -2084,8 +1847,8 @@ function carry_path(git_directory) {
|
|
|
2084
1847
|
return stamp_file.stamp_path(CARRY_PREFIX, git_directory);
|
|
2085
1848
|
}
|
|
2086
1849
|
async function repository_directory() {
|
|
2087
|
-
const
|
|
2088
|
-
return
|
|
1850
|
+
const directories2 = await git_command.git_directories();
|
|
1851
|
+
return directories2[REPOSITORY_DIRECTORY_INDEX];
|
|
2089
1852
|
}
|
|
2090
1853
|
function parse_carry(raw) {
|
|
2091
1854
|
return json_value.parse_with(raw, run_carry_schema);
|
|
@@ -2135,9 +1898,9 @@ function adopt_carry(target, carry, owner = NO_OWNER) {
|
|
|
2135
1898
|
stamp_file.remove_stamp(target);
|
|
2136
1899
|
return stamp_file.create_stamp(target, next) ? next : void 0;
|
|
2137
1900
|
}
|
|
2138
|
-
function is_owner_live(carry, now = /* @__PURE__ */ new Date()) {
|
|
2139
|
-
if (
|
|
2140
|
-
return run_carry_conversation.is_conversation_live(carry, now);
|
|
1901
|
+
function is_owner_live(carry, now = /* @__PURE__ */ new Date(), same_process = process_identity.is_same_process) {
|
|
1902
|
+
if (same_process(carry.owner_pid, carry.owner_start) !== false) return true;
|
|
1903
|
+
return carry.is_owner_headless !== true && run_carry_conversation.is_conversation_live(carry, now);
|
|
2141
1904
|
}
|
|
2142
1905
|
function is_owned_by(carry, owner) {
|
|
2143
1906
|
if (run_carry_conversation.is_same_conversation(carry, owner)) return true;
|
|
@@ -2177,7 +1940,7 @@ function remaining_of(carry) {
|
|
|
2177
1940
|
const declared = run_invocation.issue_numbers(carry.invocation);
|
|
2178
1941
|
if (declared === void 0) return void 0;
|
|
2179
1942
|
const done = carry.done ?? [];
|
|
2180
|
-
return run_carry_added.ordered(declared, carry.added).filter((
|
|
1943
|
+
return run_carry_added.ordered(declared, carry.added).filter((issue2) => !done.includes(issue2));
|
|
2181
1944
|
}
|
|
2182
1945
|
function done_note(carry) {
|
|
2183
1946
|
const done = carry.done ?? [];
|
|
@@ -2336,38 +2099,1756 @@ var ports = {
|
|
|
2336
2099
|
resolve_preview_port
|
|
2337
2100
|
};
|
|
2338
2101
|
|
|
2339
|
-
// scripts/
|
|
2102
|
+
// scripts/issue/issue-cite.ts
|
|
2103
|
+
var GITHUB_URL_PREFIX = "https://github.com/";
|
|
2104
|
+
var ISSUE_PATH = "/issues/";
|
|
2105
|
+
var SUMMARY_SEPARATOR = " \u2014 ";
|
|
2106
|
+
var REPO_QUALIFIED = /^([^\s/#]+\/[^\s/#]+)#(\d+)$/u;
|
|
2107
|
+
var BARE_NUMBER = /^#?(\d+)$/u;
|
|
2108
|
+
function plain(number, repo = "") {
|
|
2109
|
+
return `${repo}#${String(number)}`;
|
|
2110
|
+
}
|
|
2111
|
+
function issue_url(slug, number) {
|
|
2112
|
+
return `${GITHUB_URL_PREFIX}${slug}${ISSUE_PATH}${number}`;
|
|
2113
|
+
}
|
|
2114
|
+
function citation_line(slug, number, summary) {
|
|
2115
|
+
return `[${plain(number)}](${issue_url(slug, number)})${SUMMARY_SEPARATOR}${summary}`;
|
|
2116
|
+
}
|
|
2117
|
+
function reference(slug, number, title) {
|
|
2118
|
+
if (slug === void 0) return plain(number);
|
|
2119
|
+
return title === void 0 ? `[${plain(number)}](${issue_url(slug, number)})` : citation_line(slug, number, title);
|
|
2120
|
+
}
|
|
2121
|
+
function citer(slug, titles) {
|
|
2122
|
+
return function cite(number) {
|
|
2123
|
+
return reference(slug, number, titles.get(number));
|
|
2124
|
+
};
|
|
2125
|
+
}
|
|
2126
|
+
function qualified_target(token) {
|
|
2127
|
+
const match = REPO_QUALIFIED.exec(token);
|
|
2128
|
+
if (match === null) return void 0;
|
|
2129
|
+
const [, repo = "", number = ""] = match;
|
|
2130
|
+
return { number, repo };
|
|
2131
|
+
}
|
|
2132
|
+
function bare_target(token, default_repo) {
|
|
2133
|
+
const match = BARE_NUMBER.exec(token);
|
|
2134
|
+
if (match === null) return void 0;
|
|
2135
|
+
const [, number = ""] = match;
|
|
2136
|
+
return { number, repo: default_repo };
|
|
2137
|
+
}
|
|
2138
|
+
function parse_target(token, default_repo) {
|
|
2139
|
+
return qualified_target(token) ?? bare_target(token, default_repo);
|
|
2140
|
+
}
|
|
2141
|
+
function label(target) {
|
|
2142
|
+
return plain(target.number, target.repo);
|
|
2143
|
+
}
|
|
2144
|
+
function missing_line(target) {
|
|
2145
|
+
return `\u2716 ${label(target)}: issue does not resolve \u2014 check the number and the repository`;
|
|
2146
|
+
}
|
|
2147
|
+
function unreadable_line(target) {
|
|
2148
|
+
return `\u2716 ${label(target)}: could not be read \u2014 a rate limit, expired auth, or a dropped connection`;
|
|
2149
|
+
}
|
|
2150
|
+
function no_repo_line(target) {
|
|
2151
|
+
return `\u2716 ${label(target)}: could not read this repository \u2014 check gh auth and the origin remote`;
|
|
2152
|
+
}
|
|
2153
|
+
var issue_cite = {
|
|
2154
|
+
citation_line,
|
|
2155
|
+
citer,
|
|
2156
|
+
issue_url,
|
|
2157
|
+
missing_line,
|
|
2158
|
+
no_repo_line,
|
|
2159
|
+
parse_target,
|
|
2160
|
+
plain,
|
|
2161
|
+
reference,
|
|
2162
|
+
unreadable_line
|
|
2163
|
+
};
|
|
2164
|
+
|
|
2165
|
+
// scripts/git/git-common-directory.ts
|
|
2166
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
2167
|
+
var OWN_GIT_DIRECTORY = 0;
|
|
2168
|
+
var COMMON_GIT_DIRECTORY = 1;
|
|
2169
|
+
var PROBE_TIMEOUT_MS2 = 5e3;
|
|
2170
|
+
var answers = /* @__PURE__ */ new Map();
|
|
2171
|
+
function probe_environment(cwd) {
|
|
2172
|
+
if (cwd === void 0) return process.env;
|
|
2173
|
+
return { ...process.env, ...git_location_environment.location_free_environment() };
|
|
2174
|
+
}
|
|
2175
|
+
function cache_key(cwd) {
|
|
2176
|
+
if (cwd !== void 0) return `explicit\0${cwd}`;
|
|
2177
|
+
const locations = GIT_LOCATION_VARIABLES.map((name) => process.env[name] ?? "");
|
|
2178
|
+
return ["inherited", process.cwd(), ...locations].join("\0");
|
|
2179
|
+
}
|
|
2180
|
+
function read_directories(cwd) {
|
|
2181
|
+
try {
|
|
2182
|
+
const output = execFileSync2(
|
|
2183
|
+
git_utilities.get_git_command_for_spawn(),
|
|
2184
|
+
[...git_command.GIT_DIRECTORY_ARGUMENTS],
|
|
2185
|
+
{
|
|
2186
|
+
cwd,
|
|
2187
|
+
env: probe_environment(cwd),
|
|
2188
|
+
encoding: "utf8",
|
|
2189
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
2190
|
+
timeout: PROBE_TIMEOUT_MS2
|
|
2191
|
+
}
|
|
2192
|
+
);
|
|
2193
|
+
return output.split("\n").filter((line) => line !== "");
|
|
2194
|
+
} catch {
|
|
2195
|
+
return [];
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
function directories(cwd) {
|
|
2199
|
+
const key = cache_key(cwd);
|
|
2200
|
+
const known = answers.get(key);
|
|
2201
|
+
if (known !== void 0) return known;
|
|
2202
|
+
const read3 = read_directories(cwd);
|
|
2203
|
+
if (read3.length > 0) answers.set(key, read3);
|
|
2204
|
+
return read3;
|
|
2205
|
+
}
|
|
2206
|
+
function own(cwd) {
|
|
2207
|
+
return directories(cwd)[OWN_GIT_DIRECTORY];
|
|
2208
|
+
}
|
|
2209
|
+
function repository(cwd) {
|
|
2210
|
+
return directories(cwd)[COMMON_GIT_DIRECTORY];
|
|
2211
|
+
}
|
|
2212
|
+
function select_linked(found) {
|
|
2213
|
+
const own_directory = found[OWN_GIT_DIRECTORY];
|
|
2214
|
+
const common = found[COMMON_GIT_DIRECTORY];
|
|
2215
|
+
return own_directory === void 0 || common === void 0 || own_directory === common ? void 0 : common;
|
|
2216
|
+
}
|
|
2217
|
+
function resolve(cwd) {
|
|
2218
|
+
return select_linked(directories(cwd));
|
|
2219
|
+
}
|
|
2220
|
+
var git_common_directory = { directories, own, repository, resolve, select_linked };
|
|
2221
|
+
|
|
2222
|
+
// scripts/run/ship/run-ship-stage.ts
|
|
2340
2223
|
import { z as z3 } from "zod";
|
|
2341
|
-
var
|
|
2224
|
+
var STAGE = {
|
|
2225
|
+
PREFLIGHT: "preflight",
|
|
2226
|
+
REVIEW: "review",
|
|
2227
|
+
GATE: "gate",
|
|
2228
|
+
SYNC: "sync",
|
|
2229
|
+
COMMIT: "commit",
|
|
2230
|
+
ROUND_TWO: "round-2",
|
|
2231
|
+
FOLLOWUP: "followup",
|
|
2232
|
+
REPORT: "report"
|
|
2233
|
+
};
|
|
2234
|
+
var PHASE = {
|
|
2235
|
+
START: "start",
|
|
2236
|
+
DONE: "done",
|
|
2237
|
+
FAILED: "failed",
|
|
2238
|
+
SKIPPED: "skipped"
|
|
2239
|
+
};
|
|
2240
|
+
var RECORD_PREFIX = "josh-ship-stages-";
|
|
2241
|
+
var RECORD_SEPARATOR = "-";
|
|
2242
|
+
var SKIP_COMMIT_FLAG = "--skip-commit";
|
|
2243
|
+
var SKIP_PUSH_FLAG = "--skip-push";
|
|
2244
|
+
var WORD_SEPARATOR = " ";
|
|
2245
|
+
var STARTED_SEPARATOR = ",";
|
|
2246
|
+
var STARTED_INDEX = 3;
|
|
2247
|
+
var WORD_COUNT = STARTED_INDEX + 1;
|
|
2248
|
+
var record_schema = z3.object({
|
|
2249
|
+
done: z3.array(z3.string()),
|
|
2250
|
+
started: z3.array(z3.string()).default([]),
|
|
2251
|
+
is_merge_waiting: z3.boolean().default(false),
|
|
2252
|
+
is_place_waiting: z3.boolean().default(false)
|
|
2253
|
+
});
|
|
2254
|
+
var EMPTY_RECORD = {
|
|
2255
|
+
done: [],
|
|
2256
|
+
started: [],
|
|
2257
|
+
is_merge_waiting: false,
|
|
2258
|
+
is_place_waiting: false
|
|
2259
|
+
};
|
|
2260
|
+
function record_path(repository2, issue2) {
|
|
2261
|
+
return stamp_file.stamp_path(`${RECORD_PREFIX}${issue2}${RECORD_SEPARATOR}`, repository2);
|
|
2262
|
+
}
|
|
2263
|
+
function parse_record(raw) {
|
|
2264
|
+
return json_value.parse_with(raw, record_schema) ?? EMPTY_RECORD;
|
|
2265
|
+
}
|
|
2266
|
+
function read_record(target) {
|
|
2267
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
2268
|
+
return raw === void 0 ? EMPTY_RECORD : parse_record(raw);
|
|
2269
|
+
}
|
|
2270
|
+
function read_done(target) {
|
|
2271
|
+
return new Set(read_record(target).done);
|
|
2272
|
+
}
|
|
2273
|
+
function mark_done(target, stage) {
|
|
2274
|
+
const record = read_record(target);
|
|
2275
|
+
stamp_file.replace_stamp(target, { ...record, done: [.../* @__PURE__ */ new Set([...record.done, stage])] });
|
|
2276
|
+
}
|
|
2277
|
+
function read_started(target) {
|
|
2278
|
+
return read_record(target).started;
|
|
2279
|
+
}
|
|
2280
|
+
function mark_started(target, stage) {
|
|
2281
|
+
const record = read_record(target);
|
|
2282
|
+
stamp_file.replace_stamp(target, { ...record, started: [.../* @__PURE__ */ new Set([...record.started, stage])] });
|
|
2283
|
+
}
|
|
2284
|
+
function end_attempt(target) {
|
|
2285
|
+
stamp_file.replace_stamp(target, { ...read_record(target), started: [], is_merge_waiting: false });
|
|
2286
|
+
}
|
|
2287
|
+
function read_merge_waiting(target) {
|
|
2288
|
+
return read_record(target).is_merge_waiting;
|
|
2289
|
+
}
|
|
2290
|
+
function mark_merge_waiting(target, is_merge_waiting) {
|
|
2291
|
+
stamp_file.replace_stamp(target, { ...read_record(target), is_merge_waiting });
|
|
2292
|
+
}
|
|
2293
|
+
function read_place_waiting(target) {
|
|
2294
|
+
return read_record(target).is_place_waiting;
|
|
2295
|
+
}
|
|
2296
|
+
function mark_place_waiting(target, is_place_waiting) {
|
|
2297
|
+
stamp_file.replace_stamp(target, { ...read_record(target), is_place_waiting });
|
|
2298
|
+
}
|
|
2299
|
+
function clear_waits(target) {
|
|
2300
|
+
stamp_file.replace_stamp(target, {
|
|
2301
|
+
...read_record(target),
|
|
2302
|
+
is_merge_waiting: false,
|
|
2303
|
+
is_place_waiting: false
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
function clear(target) {
|
|
2307
|
+
stamp_file.remove_stamp(target);
|
|
2308
|
+
}
|
|
2309
|
+
function is_shipped(state) {
|
|
2310
|
+
return state.is_committed && state.is_pushed;
|
|
2311
|
+
}
|
|
2312
|
+
var DONE_BY = {
|
|
2313
|
+
// The preflight asks what the commit stage would refuse on, so a commit is
|
|
2314
|
+
// its output as it is the gate's; a resumed commit stage still asks `git -y`'s own preflight.
|
|
2315
|
+
[STAGE.PREFLIGHT]: (_done, state) => state.is_merged || state.is_committed,
|
|
2316
|
+
// The `--review` round precedes the commit, so a commit is its output as it
|
|
2317
|
+
// is the gate's. A record alone is not honored: before a commit the tree may have been edited since
|
|
2318
|
+
// the recorded round, and only a commit pins the tree that round read — unless the issue changed since.
|
|
2319
|
+
[STAGE.REVIEW]: (_done, state) => state.is_merged || state.is_committed && state.is_review_stale !== true,
|
|
2320
|
+
[STAGE.GATE]: (_done, state) => state.is_merged || state.is_committed,
|
|
2321
|
+
// The merge of the default branch before the commit: once committed, a
|
|
2322
|
+
// conflicting pull request is the followup's to merge again.
|
|
2323
|
+
[STAGE.SYNC]: (_done, state) => state.is_merged || state.is_committed,
|
|
2324
|
+
[STAGE.COMMIT]: (done, state) => state.is_merged || done.has(STAGE.COMMIT) && is_shipped(state),
|
|
2325
|
+
// The round-2 pass reads the pushed fix delta, so its record is honored only
|
|
2326
|
+
// while that push still stands — new work pushed on top reruns it.
|
|
2327
|
+
[STAGE.ROUND_TWO]: (done, state) => state.is_merged || done.has(STAGE.ROUND_TWO) && is_shipped(state),
|
|
2328
|
+
// A recorded followup still needs the shipped state: a record left by a merged ship whose report
|
|
2329
|
+
// failed must not pass over the followup of new, not-yet-pushed work on the same issue.
|
|
2330
|
+
[STAGE.FOLLOWUP]: (done, state) => state.is_merged || done.has(STAGE.FOLLOWUP) && is_shipped(state),
|
|
2331
|
+
[STAGE.REPORT]: (done) => done.has(STAGE.REPORT)
|
|
2332
|
+
};
|
|
2333
|
+
function is_done(stage, done, state, has_body = false) {
|
|
2334
|
+
if (has_body && stage === STAGE.COMMIT && !state.is_merged) return false;
|
|
2335
|
+
return DONE_BY[stage](done, state);
|
|
2336
|
+
}
|
|
2337
|
+
function commit_flags(state) {
|
|
2338
|
+
if (!state.is_committed) return [];
|
|
2339
|
+
return state.is_pushed ? [SKIP_COMMIT_FLAG, SKIP_PUSH_FLAG] : [SKIP_COMMIT_FLAG];
|
|
2340
|
+
}
|
|
2341
|
+
function event_text(issue2, stage, phase, started = []) {
|
|
2342
|
+
const words = [issue_cite.plain(issue2), stage, phase];
|
|
2343
|
+
const listed = [...new Set(started)].join(STARTED_SEPARATOR);
|
|
2344
|
+
const full = started.length > 0 ? [...words, listed] : words;
|
|
2345
|
+
return full.join(WORD_SEPARATOR);
|
|
2346
|
+
}
|
|
2347
|
+
function started_of(text2) {
|
|
2348
|
+
return text2.split(WORD_SEPARATOR, WORD_COUNT)[STARTED_INDEX]?.split(STARTED_SEPARATOR);
|
|
2349
|
+
}
|
|
2350
|
+
var CONFLICT = "conflict";
|
|
2351
|
+
function stop_reason(stage, conflicts = []) {
|
|
2352
|
+
return conflicts.length > 0 ? CONFLICT : stage;
|
|
2353
|
+
}
|
|
2354
|
+
var run_ship_stage = {
|
|
2355
|
+
CONFLICT,
|
|
2356
|
+
PHASE,
|
|
2357
|
+
STAGE,
|
|
2358
|
+
clear,
|
|
2359
|
+
clear_waits,
|
|
2360
|
+
commit_flags,
|
|
2361
|
+
end_attempt,
|
|
2362
|
+
event_text,
|
|
2363
|
+
is_done,
|
|
2364
|
+
mark_done,
|
|
2365
|
+
mark_merge_waiting,
|
|
2366
|
+
mark_place_waiting,
|
|
2367
|
+
mark_started,
|
|
2368
|
+
read_done,
|
|
2369
|
+
read_merge_waiting,
|
|
2370
|
+
read_place_waiting,
|
|
2371
|
+
read_started,
|
|
2372
|
+
record_path,
|
|
2373
|
+
started_of,
|
|
2374
|
+
stop_reason
|
|
2375
|
+
};
|
|
2376
|
+
|
|
2377
|
+
// scripts/git/repository-lock.ts
|
|
2378
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2379
|
+
import { linkSync, renameSync, rmSync as rmSync2 } from "node:fs";
|
|
2380
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
2381
|
+
|
|
2382
|
+
// scripts/josh/process-owner.ts
|
|
2383
|
+
import { z as z4 } from "zod";
|
|
2384
|
+
var process_owner_schema = z4.object({ pid: z4.number(), process_start: z4.string().optional() });
|
|
2385
|
+
|
|
2386
|
+
// scripts/git/repository-lock.ts
|
|
2387
|
+
var POLL_INTERVAL_MS = 200;
|
|
2388
|
+
var SYNC_POLL_INTERVAL_MS = 10;
|
|
2389
|
+
var SLEEP_CELL = new Int32Array(new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT));
|
|
2390
|
+
function lock_path(prefix, cwd) {
|
|
2391
|
+
return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd());
|
|
2392
|
+
}
|
|
2393
|
+
function parse_owner(raw) {
|
|
2394
|
+
if (raw === void 0) return void 0;
|
|
2395
|
+
const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
|
|
2396
|
+
return parsed.success ? parsed.data : void 0;
|
|
2397
|
+
}
|
|
2398
|
+
function read_owner(target) {
|
|
2399
|
+
return parse_owner(stamp_file.read_stamp_text(target));
|
|
2400
|
+
}
|
|
2401
|
+
function is_owner_gone(owner) {
|
|
2402
|
+
return process_identity.is_same_process(owner.pid, owner.process_start) === false;
|
|
2403
|
+
}
|
|
2404
|
+
function restore(aside, target) {
|
|
2405
|
+
try {
|
|
2406
|
+
linkSync(aside, target);
|
|
2407
|
+
} catch {
|
|
2408
|
+
}
|
|
2409
|
+
}
|
|
2410
|
+
function stale_record(target, is_gone) {
|
|
2411
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
2412
|
+
const owner = parse_owner(raw);
|
|
2413
|
+
return owner !== void 0 && is_gone(owner) ? raw : void 0;
|
|
2414
|
+
}
|
|
2415
|
+
function move_aside(target) {
|
|
2416
|
+
const aside = `${target}.${String(process.pid)}.${randomUUID2()}`;
|
|
2417
|
+
try {
|
|
2418
|
+
renameSync(target, aside);
|
|
2419
|
+
return aside;
|
|
2420
|
+
} catch {
|
|
2421
|
+
return void 0;
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
function clear_stale(target, is_gone = is_owner_gone) {
|
|
2425
|
+
const raw = stale_record(target, is_gone);
|
|
2426
|
+
if (raw === void 0) return;
|
|
2427
|
+
const aside = move_aside(target);
|
|
2428
|
+
if (aside === void 0) return;
|
|
2429
|
+
if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
|
|
2430
|
+
rmSync2(aside, { force: true });
|
|
2431
|
+
}
|
|
2432
|
+
function claim(target) {
|
|
2433
|
+
clear_stale(target);
|
|
2434
|
+
return stamp_file.create_stamp(target, process_identity.own_fields());
|
|
2435
|
+
}
|
|
2436
|
+
function release(target) {
|
|
2437
|
+
const owner = read_owner(target);
|
|
2438
|
+
if (owner !== void 0 && process_identity.is_own_process(owner.pid, owner.process_start)) {
|
|
2439
|
+
stamp_file.remove_stamp(target);
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
async function acquire(target, max_wait_ms) {
|
|
2443
|
+
const deadline = Date.now() + max_wait_ms;
|
|
2444
|
+
while (!claim(target)) {
|
|
2445
|
+
if (Date.now() >= deadline) return false;
|
|
2446
|
+
await sleep(POLL_INTERVAL_MS);
|
|
2447
|
+
}
|
|
2448
|
+
return true;
|
|
2449
|
+
}
|
|
2450
|
+
function sleep_sync(ms) {
|
|
2451
|
+
Atomics.wait(SLEEP_CELL, 0, 0, ms);
|
|
2452
|
+
}
|
|
2453
|
+
function acquire_sync(target, max_wait_ms) {
|
|
2454
|
+
const deadline = Date.now() + max_wait_ms;
|
|
2455
|
+
while (!claim(target)) {
|
|
2456
|
+
if (Date.now() >= deadline) return false;
|
|
2457
|
+
sleep_sync(SYNC_POLL_INTERVAL_MS);
|
|
2458
|
+
}
|
|
2459
|
+
return true;
|
|
2460
|
+
}
|
|
2461
|
+
async function with_lock(work, target, max_wait_ms) {
|
|
2462
|
+
if (!await acquire(target, max_wait_ms)) return void 0;
|
|
2463
|
+
try {
|
|
2464
|
+
return await work();
|
|
2465
|
+
} finally {
|
|
2466
|
+
release(target);
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
function with_lock_sync(work, target, max_wait_ms) {
|
|
2470
|
+
if (!acquire_sync(target, max_wait_ms)) return void 0;
|
|
2471
|
+
try {
|
|
2472
|
+
return work();
|
|
2473
|
+
} finally {
|
|
2474
|
+
release(target);
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
var repository_lock = { clear_stale, lock_path, with_lock, with_lock_sync };
|
|
2478
|
+
|
|
2479
|
+
// scripts/run/event/run-event-stream.ts
|
|
2480
|
+
import { z as z5 } from "zod";
|
|
2481
|
+
var EVENT_PREFIX = "josh-run-events-";
|
|
2482
|
+
var EVENT_SUFFIX = ".jsonl";
|
|
2483
|
+
var EVENT_CAP = 15e3;
|
|
2484
|
+
var FIRST_POSITION = 0;
|
|
2485
|
+
var POSITION_INCREMENT = 1;
|
|
2486
|
+
var LINE_SEPARATOR = "\n";
|
|
2487
|
+
var WORD_SEPARATOR2 = " ";
|
|
2488
|
+
var STAGE_PHASE_INDEX = 2;
|
|
2489
|
+
var LOCK_SUFFIX = ".lock";
|
|
2490
|
+
var LOCK_WAIT_MS = 5e3;
|
|
2491
|
+
var EVENT_KIND = {
|
|
2492
|
+
PLAN: "plan",
|
|
2493
|
+
CHILD_LAUNCH: "child-launch",
|
|
2494
|
+
MERGE: "merge",
|
|
2495
|
+
PARK: "park",
|
|
2496
|
+
SPLIT: "split",
|
|
2497
|
+
OUTAGE: "outage",
|
|
2498
|
+
CUT: "cut",
|
|
2499
|
+
// A fresh session adopted an implementation cut — `run:cut --resume` answered `resume-impl`. The
|
|
2500
|
+
// resume clears the cut record, so without this the `cut` would stay the newest position and
|
|
2501
|
+
// `run:step` would keep answering the resume command it had just run.
|
|
2502
|
+
RESUME: "resume",
|
|
2503
|
+
// A person stopped a running lane child and re-dispatched its issue in a fresh session
|
|
2504
|
+
// (`lane:restart`). It follows the fresh dispatch's `CHILD_LAUNCH`, so it is a launch to the parent and
|
|
2505
|
+
// the board, and — like that launch — a batch record a lane child never reads as its own position.
|
|
2506
|
+
RESTART: "restart",
|
|
2507
|
+
// A person withdrew a lane child — stopped it and left its issue open for the next run (`lane:withdraw`).
|
|
2508
|
+
// It is written before the stop, so `run:merge` settles the child as withdrawn whatever GitHub says
|
|
2509
|
+
// by the time the parent collects it, and counts it as neither a merge, a failure nor an outage.
|
|
2510
|
+
WITHDRAW: "withdraw",
|
|
2511
|
+
// The backlog emptied while nothing of the run's own was in flight — the drain. It marks the position
|
|
2512
|
+
// at which the end-of-run retrospective is owed, *before* the idle watch opens, so `run:step` fires
|
|
2513
|
+
// the retrospective at the drain rather than after the watch runs its course. It is not itself a
|
|
2514
|
+
// stop: the run watches on once the retrospective has run, and the real `STOP` follows when the watch
|
|
2515
|
+
// expires.
|
|
2516
|
+
DRAIN: "drain",
|
|
2517
|
+
STOP: "stop",
|
|
2518
|
+
PR_OPENED: "pr-opened",
|
|
2519
|
+
REVIEW_ROUND: "review-round",
|
|
2520
|
+
// The end-of-run retrospective's result, recorded when the run marks the retrospective done. A
|
|
2521
|
+
// retrospective that files zero improvements and one that never ran look
|
|
2522
|
+
// the same from outside — no new Issue either way — so the result is put on the stream the report is
|
|
2523
|
+
// generated from: the issues filed (or that none were), and the candidates dropped with why. It is
|
|
2524
|
+
// emitted from the `run:carry --retrospective` close, so marking the retrospective done and recording
|
|
2525
|
+
// what it found are one action rather than two the run could do only one of.
|
|
2526
|
+
RETROSPECTIVE: "retrospective",
|
|
2527
|
+
// Ready backlog work is sitting undispatched while a lane is free and nothing has dispatched for a
|
|
2528
|
+
// while. Emitted once per stall episode by the stop-time detector, it is both the dedup marker —
|
|
2529
|
+
// `emit_once_since` refuses a second until a `CHILD_LAUNCH` intervenes — and the line a terminal
|
|
2530
|
+
// reader following the stream sees. `run:step` reads it as `backlog:next`, so a run that
|
|
2531
|
+
// stalled is pointed straight at dispatching the work rather than left waiting.
|
|
2532
|
+
STALL: "stall",
|
|
2533
|
+
// The run's own driver is gone: the cut handed the budget off, the owner has died, and no supervisor
|
|
2534
|
+
// is watching. Emitted once per strand episode by the stop-time detector — or by the `run:wake`
|
|
2535
|
+
// supervisor as it fails, leaves that state behind and has warned of it —
|
|
2536
|
+
// exactly as `STALL` is — the newest-event dedup keeps a run polled every stop from notifying more
|
|
2537
|
+
// than once, and a terminal reader following the stream sees the line. The strand is the step before
|
|
2538
|
+
// the stall: a stalled run still has a driver that could dispatch, a stranded one has none.
|
|
2539
|
+
STRANDED: "stranded",
|
|
2540
|
+
// One `josh ship` stage starting, succeeding or failing. It is a trace of the
|
|
2541
|
+
// composite's progress rather than a position the run is at — the positions a ship leaves behind are
|
|
2542
|
+
// the closed issue its `followup` merges, or a detached supervisor's `SHIP_LAUNCH` / `SHIP_STOP` below
|
|
2543
|
+
// — so it is one of the `TRACE_KINDS` the last-event read skips.
|
|
2544
|
+
SHIP_STAGE: "ship-stage",
|
|
2545
|
+
// One progress watcher line — the `at … / next …` heartbeat `run:progress` prints. Printed only to
|
|
2546
|
+
// the watcher's own output, a headless successor's heartbeat would be buried in its log after a cut;
|
|
2547
|
+
// on the stream it reaches the attached session's relay. It says
|
|
2548
|
+
// the run is alive rather than where it is, so it is a trace kind like `SHIP_STAGE`.
|
|
2549
|
+
HEARTBEAT: "heartbeat",
|
|
2550
|
+
// The post-implementation region handed to a detached `josh ship --detach` supervisor. Unlike a stage
|
|
2551
|
+
// trace it is a position: the agent has ended and the
|
|
2552
|
+
// supervisor carries the run, so `run:step` answers `wait` until it stops or the issue closes.
|
|
2553
|
+
SHIP_LAUNCH: "ship-launch",
|
|
2554
|
+
// The supervisor stopped at a failed stage — a red gate, a High/Medium review, a failed push, red CI
|
|
2555
|
+
// The position that hands control back: `run:step` prints the command that
|
|
2556
|
+
// shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
|
|
2557
|
+
SHIP_STOP: "ship-stop",
|
|
2558
|
+
// An Issue the run filed on its way, written by `issue:file`, so a run started from the command line
|
|
2559
|
+
// still surfaces what it found — `run:board`'s findings section reads it.
|
|
2560
|
+
FILED: "filed",
|
|
2561
|
+
// A one-line observation short of an Issue, written with `run:event --append note` and shown in the
|
|
2562
|
+
// same section.
|
|
2563
|
+
NOTE: "note",
|
|
2564
|
+
// A lane child reached a phase no other event marks — its first implementation edit, written by the
|
|
2565
|
+
// PreToolUse hook — so `run:board` draws how far the child has got. A trace,
|
|
2566
|
+
// like `SHIP_STAGE`: it says where the child's work is, not where the run is.
|
|
2567
|
+
LANE_PHASE: "lane-phase",
|
|
2568
|
+
// An issue `run:add` put into the live run. The parent's `--wait` watcher
|
|
2569
|
+
// ends on it, so the issue takes the next free lane without waiting out the arrival probe's minute. A
|
|
2570
|
+
// trace: it says what the run was handed, not where the run is.
|
|
2571
|
+
ADD: "add",
|
|
2572
|
+
// `josh lane:limit` raised a live run's lane limit. The `--wait` watcher's
|
|
2573
|
+
// arrival probe reads it as a wake: the lanes a raise frees are new room for a pool its baseline
|
|
2574
|
+
// already holds. A trace: it says the run gained room, not where the run is.
|
|
2575
|
+
LANE_LIMIT: "lane-limit",
|
|
2576
|
+
// One stage of the run's start — the session starting, the plan, the hand-off to the supervisor, a
|
|
2577
|
+
// lane opening (`run-event-setup.ts`). `run:board` draws it while the run stands at it, so the
|
|
2578
|
+
// minutes before one read as work rather than as a run that has stopped. A trace: it says the run is
|
|
2579
|
+
// getting ready, not where the run is.
|
|
2580
|
+
SETUP: "setup",
|
|
2581
|
+
// A child's pull request checks as `josh followup` last polled them — the CI counts and CodeRabbit's
|
|
2582
|
+
// state (`run-event-checks.ts`), written only when they change, so `run:board` draws a child waiting
|
|
2583
|
+
// in followup without asking GitHub (joshuafolkken/kit#3770). A trace: it says how the checks stand,
|
|
2584
|
+
// not where the run is.
|
|
2585
|
+
PR_CHECKS: "pr-checks",
|
|
2586
|
+
// `backlog:drive` reached a watch with no child running and nothing to dispatch — the point a person's
|
|
2587
|
+
// hand is wanted. Emitted once per idle episode (`emit_once_since_with`, reset by `CHILD_LAUNCH`), it
|
|
2588
|
+
// is the dedup marker for the one idle Telegram. A trace: a drain's retrospective is read off the
|
|
2589
|
+
// position beneath it, so the marker must not stand over it.
|
|
2590
|
+
IDLE_NOTICE: "idle-notice",
|
|
2591
|
+
// A person paused or resumed a lane child (`lane:pause` / `lane:resume`), so who halted a lane and
|
|
2592
|
+
// when is on the stream rather than only in a shell history (joshuafolkken/kit#4268). A trace: it
|
|
2593
|
+
// says what a lane's processes were told, not where the run is.
|
|
2594
|
+
LANE_STATE: "lane-state",
|
|
2595
|
+
// `backlog:drive` found nothing of the run in flight and only paused lanes left, paused past the
|
|
2596
|
+
// silent window (joshuafolkken/kit#4270). Emitted once per pause episode (`emit_once_since_with`,
|
|
2597
|
+
// reset by `LANE_STATE`), it is the dedup marker for the one paused-lane Telegram. A trace.
|
|
2598
|
+
PAUSED_NOTICE: "paused-notice"
|
|
2599
|
+
};
|
|
2600
|
+
var EVENT_KINDS = Object.values(EVENT_KIND);
|
|
2601
|
+
var TRACE_KINDS = /* @__PURE__ */ new Set([
|
|
2602
|
+
EVENT_KIND.SHIP_STAGE,
|
|
2603
|
+
EVENT_KIND.HEARTBEAT,
|
|
2604
|
+
EVENT_KIND.FILED,
|
|
2605
|
+
EVENT_KIND.NOTE,
|
|
2606
|
+
EVENT_KIND.LANE_PHASE,
|
|
2607
|
+
EVENT_KIND.ADD,
|
|
2608
|
+
EVENT_KIND.LANE_LIMIT,
|
|
2609
|
+
EVENT_KIND.SETUP,
|
|
2610
|
+
EVENT_KIND.PR_CHECKS,
|
|
2611
|
+
EVENT_KIND.IDLE_NOTICE,
|
|
2612
|
+
EVENT_KIND.LANE_STATE,
|
|
2613
|
+
EVENT_KIND.PAUSED_NOTICE
|
|
2614
|
+
]);
|
|
2615
|
+
var DISPOSABLE_KINDS = /* @__PURE__ */ new Set([
|
|
2616
|
+
EVENT_KIND.SHIP_STAGE,
|
|
2617
|
+
EVENT_KIND.HEARTBEAT,
|
|
2618
|
+
EVENT_KIND.SETUP,
|
|
2619
|
+
EVENT_KIND.PR_CHECKS
|
|
2620
|
+
]);
|
|
2621
|
+
var event_schema = z5.object({
|
|
2622
|
+
pos: z5.number(),
|
|
2623
|
+
at: z5.string(),
|
|
2624
|
+
kind: z5.string(),
|
|
2625
|
+
text: z5.string(),
|
|
2626
|
+
// The child's time on a lane, recorded once by the writer of an ending (joshuafolkken/kit#4481), so a
|
|
2627
|
+
// reader never has to find its launch again. An event written before it has none.
|
|
2628
|
+
elapsed_ms: z5.number().optional()
|
|
2629
|
+
});
|
|
2630
|
+
function is_event_kind(value) {
|
|
2631
|
+
return EVENT_KINDS.includes(value);
|
|
2632
|
+
}
|
|
2633
|
+
function target_of(repository2) {
|
|
2634
|
+
return stamp_file.stamp_path(EVENT_PREFIX, repository2, EVENT_SUFFIX);
|
|
2635
|
+
}
|
|
2636
|
+
function is_present(event) {
|
|
2637
|
+
return event !== void 0;
|
|
2638
|
+
}
|
|
2639
|
+
function parse_line2(line) {
|
|
2640
|
+
return event_schema.safeParse(json_value.parse_or_undefined(line)).data;
|
|
2641
|
+
}
|
|
2642
|
+
function read_lines(target) {
|
|
2643
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
2644
|
+
if (raw === void 0) return [];
|
|
2645
|
+
return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line2(line)).filter(is_present);
|
|
2646
|
+
}
|
|
2647
|
+
function read_events(target) {
|
|
2648
|
+
return read_lines(target).filter((event) => is_event_kind(event.kind));
|
|
2649
|
+
}
|
|
2650
|
+
function last_position(events) {
|
|
2651
|
+
return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
|
|
2652
|
+
}
|
|
2653
|
+
function issue_of2(event) {
|
|
2654
|
+
return event.text.split(WORD_SEPARATOR2)[FIRST_POSITION] ?? "";
|
|
2655
|
+
}
|
|
2656
|
+
function newest_by_issue(events, kind) {
|
|
2657
|
+
const newest = /* @__PURE__ */ new Map();
|
|
2658
|
+
for (const event of events) {
|
|
2659
|
+
if (event.kind === kind) newest.set(issue_of2(event), event);
|
|
2660
|
+
}
|
|
2661
|
+
return new Set(newest.values());
|
|
2662
|
+
}
|
|
2663
|
+
function is_stage_start(event) {
|
|
2664
|
+
if (event.kind !== EVENT_KIND.SHIP_STAGE) return false;
|
|
2665
|
+
return event.text.split(WORD_SEPARATOR2)[STAGE_PHASE_INDEX] === run_ship_stage.PHASE.START;
|
|
2666
|
+
}
|
|
2667
|
+
function drawn_lines(events) {
|
|
2668
|
+
const setup = events.findLast((event) => event.kind === EVENT_KIND.SETUP);
|
|
2669
|
+
return /* @__PURE__ */ new Set([
|
|
2670
|
+
...newest_by_issue(events, EVENT_KIND.SHIP_STAGE),
|
|
2671
|
+
...newest_by_issue(events, EVENT_KIND.PR_CHECKS),
|
|
2672
|
+
...setup === void 0 ? [] : [setup]
|
|
2673
|
+
]);
|
|
2674
|
+
}
|
|
2675
|
+
function droppable(events) {
|
|
2676
|
+
const kept = drawn_lines(events);
|
|
2677
|
+
const disposable = events.filter((event) => DISPOSABLE_KINDS.has(event.kind) && !kept.has(event));
|
|
2678
|
+
return [
|
|
2679
|
+
...disposable.filter((event) => !is_stage_start(event)),
|
|
2680
|
+
...disposable.filter((event) => is_stage_start(event))
|
|
2681
|
+
];
|
|
2682
|
+
}
|
|
2683
|
+
function bounded(events) {
|
|
2684
|
+
const excess = events.length - EVENT_CAP;
|
|
2685
|
+
if (excess <= 0) return events;
|
|
2686
|
+
const dropped = new Set(droppable(events).slice(0, excess));
|
|
2687
|
+
return events.filter((event) => !dropped.has(event)).slice(-EVENT_CAP);
|
|
2688
|
+
}
|
|
2689
|
+
function serialize(events) {
|
|
2690
|
+
return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
|
|
2691
|
+
}
|
|
2692
|
+
function append_held(target, event) {
|
|
2693
|
+
const position = last_position(read_lines(target)) + POSITION_INCREMENT;
|
|
2694
|
+
const events = bounded([...read_events(target), { pos: position, ...event }]);
|
|
2695
|
+
stamp_file.replace_text_stamp(target, serialize(events));
|
|
2696
|
+
return position;
|
|
2697
|
+
}
|
|
2698
|
+
function append_event(target, event) {
|
|
2699
|
+
if (!is_event_kind(event.kind)) return { appended: false, position: FIRST_POSITION };
|
|
2700
|
+
const lock = `${target}${LOCK_SUFFIX}`;
|
|
2701
|
+
const position = repository_lock.with_lock_sync(
|
|
2702
|
+
() => append_held(target, event),
|
|
2703
|
+
lock,
|
|
2704
|
+
LOCK_WAIT_MS
|
|
2705
|
+
);
|
|
2706
|
+
if (position === void 0) {
|
|
2707
|
+
const message = `run event stream: gave up waiting for the lock at ${lock}`;
|
|
2708
|
+
process.stderr.write(`${message}
|
|
2709
|
+
`);
|
|
2710
|
+
throw new Error(message);
|
|
2711
|
+
}
|
|
2712
|
+
return { appended: true, position };
|
|
2713
|
+
}
|
|
2714
|
+
function append(target, kind, text2, at) {
|
|
2715
|
+
return append_event(target, { at, kind, text: text2 });
|
|
2716
|
+
}
|
|
2717
|
+
function read_from(target, position) {
|
|
2718
|
+
const events = read_events(target);
|
|
2719
|
+
return {
|
|
2720
|
+
events: events.filter((event) => event.pos > position),
|
|
2721
|
+
next_position: last_position(events)
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
function read_last(target) {
|
|
2725
|
+
return read_events(target).findLast((event) => !TRACE_KINDS.has(event.kind));
|
|
2726
|
+
}
|
|
2727
|
+
function has_since(events, kind, reset_kind) {
|
|
2728
|
+
const reset_at = events.findLastIndex((event) => event.kind === reset_kind);
|
|
2729
|
+
return events.slice(reset_at + POSITION_INCREMENT).some((event) => event.kind === kind);
|
|
2730
|
+
}
|
|
2731
|
+
var FIELD_SEPARATOR = " \xB7 ";
|
|
2732
|
+
function format_event(event) {
|
|
2733
|
+
return [event.at, event.kind, event.text].join(FIELD_SEPARATOR);
|
|
2734
|
+
}
|
|
2735
|
+
var run_event_stream = {
|
|
2736
|
+
EVENT_CAP,
|
|
2737
|
+
EVENT_KIND,
|
|
2738
|
+
EVENT_KINDS,
|
|
2739
|
+
TRACE_KINDS,
|
|
2740
|
+
append,
|
|
2741
|
+
append_event,
|
|
2742
|
+
format_event,
|
|
2743
|
+
has_since,
|
|
2744
|
+
is_stage_start,
|
|
2745
|
+
read_events,
|
|
2746
|
+
read_from,
|
|
2747
|
+
read_last,
|
|
2748
|
+
target_of
|
|
2749
|
+
};
|
|
2750
|
+
|
|
2751
|
+
// scripts/discovery/repo-origin.ts
|
|
2752
|
+
var GITHUB_HOST = "github.com";
|
|
2753
|
+
var SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u;
|
|
2754
|
+
var GIT_SUFFIX = ".git";
|
|
2755
|
+
var PATH_SEPARATOR2 = "/";
|
|
2756
|
+
var USER_SEPARATOR = "@";
|
|
2757
|
+
var HOST_SEPARATOR = ":";
|
|
2758
|
+
var OWNER_INDEX = 0;
|
|
2759
|
+
var REPO_INDEX = 1;
|
|
2760
|
+
var REPO_PATH_SEGMENTS = 2;
|
|
2761
|
+
var NOT_FOUND4 = -1;
|
|
2762
|
+
var SECTION_PREFIX = "[";
|
|
2763
|
+
var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
|
|
2764
|
+
var REMOTE_SECTION = /^\[remote\s+"[^"]+"\]$/u;
|
|
2765
|
+
var URL_KEY = "url";
|
|
2766
|
+
function is_github_hostname(host) {
|
|
2767
|
+
return host.toLowerCase() === GITHUB_HOST;
|
|
2768
|
+
}
|
|
2769
|
+
function is_github_ssh_host(host) {
|
|
2770
|
+
const normalized = host.toLowerCase();
|
|
2771
|
+
return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized);
|
|
2772
|
+
}
|
|
2773
|
+
function strip_git_suffix(name) {
|
|
2774
|
+
return name.endsWith(GIT_SUFFIX) ? name.slice(0, -GIT_SUFFIX.length) : name;
|
|
2775
|
+
}
|
|
2776
|
+
function to_identity(repository_path) {
|
|
2777
|
+
const segments = repository_path.split(PATH_SEPARATOR2).filter((segment) => segment !== "");
|
|
2778
|
+
if (segments.length !== REPO_PATH_SEGMENTS) return void 0;
|
|
2779
|
+
const owner = segments[OWNER_INDEX] ?? "";
|
|
2780
|
+
const repo = strip_git_suffix(segments[REPO_INDEX] ?? "");
|
|
2781
|
+
return repo === "" ? void 0 : { owner, repo };
|
|
2782
|
+
}
|
|
2783
|
+
function parse_scp_like(url) {
|
|
2784
|
+
const user_end = url.indexOf(USER_SEPARATOR);
|
|
2785
|
+
const authority = user_end === NOT_FOUND4 ? url : url.slice(user_end + 1);
|
|
2786
|
+
const host_end = authority.indexOf(HOST_SEPARATOR);
|
|
2787
|
+
if (host_end === NOT_FOUND4 || !is_github_ssh_host(authority.slice(0, host_end))) return void 0;
|
|
2788
|
+
return to_identity(authority.slice(host_end + 1));
|
|
2789
|
+
}
|
|
2790
|
+
function parse_url_like(url) {
|
|
2791
|
+
try {
|
|
2792
|
+
const parsed = new URL(url);
|
|
2793
|
+
return is_github_hostname(parsed.hostname) ? to_identity(parsed.pathname) : void 0;
|
|
2794
|
+
} catch {
|
|
2795
|
+
return void 0;
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
function parse_origin_url(url) {
|
|
2799
|
+
const trimmed = url.trim();
|
|
2800
|
+
if (trimmed === "") return void 0;
|
|
2801
|
+
return parse_url_like(trimmed) ?? parse_scp_like(trimmed);
|
|
2802
|
+
}
|
|
2803
|
+
function is_section_header(line) {
|
|
2804
|
+
return line.startsWith(SECTION_PREFIX);
|
|
2805
|
+
}
|
|
2806
|
+
function origin_section_lines(lines) {
|
|
2807
|
+
const start = lines.findIndex((line) => ORIGIN_SECTION.test(line));
|
|
2808
|
+
if (start === NOT_FOUND4) return [];
|
|
2809
|
+
const rest = lines.slice(start + 1);
|
|
2810
|
+
const end = rest.findIndex((line) => is_section_header(line));
|
|
2811
|
+
return end === NOT_FOUND4 ? rest : rest.slice(0, end);
|
|
2812
|
+
}
|
|
2813
|
+
function url_value(line) {
|
|
2814
|
+
const separator = line.indexOf("=");
|
|
2815
|
+
if (separator === NOT_FOUND4 || line.slice(0, separator).trim() !== URL_KEY) return void 0;
|
|
2816
|
+
return line.slice(separator + 1).trim();
|
|
2817
|
+
}
|
|
2818
|
+
function parse_origin_from_config(content) {
|
|
2819
|
+
const lines = content.split("\n").map((line) => line.trim());
|
|
2820
|
+
return origin_section_lines(lines).map((line) => url_value(line)).find((url) => url !== void 0);
|
|
2821
|
+
}
|
|
2822
|
+
function section_groups(lines) {
|
|
2823
|
+
const groups = [];
|
|
2824
|
+
for (const line of lines) {
|
|
2825
|
+
if (is_section_header(line)) groups.push([line]);
|
|
2826
|
+
else groups.at(-1)?.push(line);
|
|
2827
|
+
}
|
|
2828
|
+
return groups;
|
|
2829
|
+
}
|
|
2830
|
+
function parse_remote_urls_from_config(content) {
|
|
2831
|
+
const lines = content.split("\n").map((line) => line.trim());
|
|
2832
|
+
return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => url_value(line))).filter((url) => url !== void 0);
|
|
2833
|
+
}
|
|
2834
|
+
function format_identity(identity) {
|
|
2835
|
+
return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
|
|
2836
|
+
}
|
|
2837
|
+
var repo_origin = {
|
|
2838
|
+
GITHUB_HOST,
|
|
2839
|
+
is_github_hostname,
|
|
2840
|
+
is_github_ssh_host,
|
|
2841
|
+
parse_origin_from_config,
|
|
2842
|
+
parse_origin_url,
|
|
2843
|
+
parse_remote_urls_from_config,
|
|
2844
|
+
format_identity
|
|
2845
|
+
};
|
|
2846
|
+
|
|
2847
|
+
// scripts/discovery/repo-discovery.ts
|
|
2848
|
+
import { existsSync as existsSync3, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync3 } from "node:fs";
|
|
2849
|
+
import path7 from "node:path";
|
|
2850
|
+
|
|
2851
|
+
// scripts/lib/stamped-memo.ts
|
|
2852
|
+
import { lstatSync } from "node:fs";
|
|
2853
|
+
var NO_STAMP = "";
|
|
2854
|
+
var STAMP_SEPARATOR = ":";
|
|
2855
|
+
function create() {
|
|
2856
|
+
const answers2 = /* @__PURE__ */ new Map();
|
|
2857
|
+
return {
|
|
2858
|
+
of(key, stamp, compute) {
|
|
2859
|
+
const known = answers2.get(key);
|
|
2860
|
+
if (known?.stamp === stamp) return known.value;
|
|
2861
|
+
const value = compute();
|
|
2862
|
+
answers2.set(key, { stamp, value });
|
|
2863
|
+
return value;
|
|
2864
|
+
},
|
|
2865
|
+
keep(keys) {
|
|
2866
|
+
for (const key of answers2.keys()) if (!keys.has(key)) answers2.delete(key);
|
|
2867
|
+
}
|
|
2868
|
+
};
|
|
2869
|
+
}
|
|
2870
|
+
function file_stamp(file) {
|
|
2871
|
+
try {
|
|
2872
|
+
const status2 = lstatSync(file);
|
|
2873
|
+
return [status2.ino, status2.mtimeMs, status2.ctimeMs, status2.size].join(STAMP_SEPARATOR);
|
|
2874
|
+
} catch {
|
|
2875
|
+
return NO_STAMP;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
var stamped_memo = { NO_STAMP, create, file_stamp };
|
|
2879
|
+
|
|
2880
|
+
// scripts/discovery/repo-map-logic.ts
|
|
2881
|
+
var OVERRIDE_ENTRY_SEPARATOR = ",";
|
|
2882
|
+
var OVERRIDE_PAIR_SEPARATOR = "=";
|
|
2883
|
+
var OVERRIDE_PAIR_PARTS = 2;
|
|
2884
|
+
var KEY_INDEX = 0;
|
|
2885
|
+
var PATH_INDEX = 1;
|
|
2886
|
+
function is_same_owner(identity, current_owner) {
|
|
2887
|
+
return identity.owner.toLowerCase() === current_owner.toLowerCase();
|
|
2888
|
+
}
|
|
2889
|
+
function add_entry(target, origin_url2, repository_path, current_owner) {
|
|
2890
|
+
if (origin_url2 === void 0) return;
|
|
2891
|
+
const identity = repo_origin.parse_origin_url(origin_url2);
|
|
2892
|
+
if (identity === void 0 || !is_same_owner(identity, current_owner)) return;
|
|
2893
|
+
target.set(repo_origin.format_identity(identity), repository_path);
|
|
2894
|
+
}
|
|
2895
|
+
function parse_override_entry(entry) {
|
|
2896
|
+
const parts = entry.split(OVERRIDE_PAIR_SEPARATOR).map((part) => part.trim());
|
|
2897
|
+
if (parts.length !== OVERRIDE_PAIR_PARTS) return void 0;
|
|
2898
|
+
const key = parts[KEY_INDEX] ?? "";
|
|
2899
|
+
const repository_path = parts[PATH_INDEX] ?? "";
|
|
2900
|
+
if (repository_path === "") return void 0;
|
|
2901
|
+
return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key}` };
|
|
2902
|
+
}
|
|
2903
|
+
function parse_overrides(raw) {
|
|
2904
|
+
if (raw === void 0) return [];
|
|
2905
|
+
return raw.split(OVERRIDE_ENTRY_SEPARATOR).map((entry) => parse_override_entry(entry)).filter((entry) => entry !== void 0);
|
|
2906
|
+
}
|
|
2907
|
+
function build_repository_map(discovered, current_owner, override_value) {
|
|
2908
|
+
const result = /* @__PURE__ */ new Map();
|
|
2909
|
+
for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner);
|
|
2910
|
+
for (const entry of parse_overrides(override_value)) {
|
|
2911
|
+
add_entry(result, entry.origin_url, entry.path, current_owner);
|
|
2912
|
+
}
|
|
2913
|
+
return result;
|
|
2914
|
+
}
|
|
2915
|
+
var repo_map_logic = {
|
|
2916
|
+
is_same_owner,
|
|
2917
|
+
build_repository_map
|
|
2918
|
+
};
|
|
2919
|
+
|
|
2920
|
+
// scripts/discovery/repo-discovery.ts
|
|
2921
|
+
var GIT_DIRECTORY = ".git";
|
|
2922
|
+
var GIT_CONFIG = "config";
|
|
2923
|
+
var GITDIR_PREFIX2 = "gitdir:";
|
|
2924
|
+
var COMMON_DIRECTORY_FILE = "commondir";
|
|
2925
|
+
var OVERRIDE_ENV_KEY = "JOSH_REPO_PATHS";
|
|
2926
|
+
function resolve_common_directory(git_directory) {
|
|
2927
|
+
const pointer = path7.join(git_directory, COMMON_DIRECTORY_FILE);
|
|
2928
|
+
if (!existsSync3(pointer)) return git_directory;
|
|
2929
|
+
try {
|
|
2930
|
+
return path7.resolve(git_directory, readFileSync4(pointer, "utf8").trim());
|
|
2931
|
+
} catch {
|
|
2932
|
+
return git_directory;
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
function follow_git_file(repository_path, git_file) {
|
|
2936
|
+
const pointer = readFileSync4(git_file, "utf8").trim();
|
|
2937
|
+
if (!pointer.startsWith(GITDIR_PREFIX2)) return void 0;
|
|
2938
|
+
return path7.resolve(repository_path, pointer.slice(GITDIR_PREFIX2.length).trim());
|
|
2939
|
+
}
|
|
2940
|
+
function resolve_git_directory(repository_path) {
|
|
2941
|
+
const candidate = path7.join(repository_path, GIT_DIRECTORY);
|
|
2942
|
+
if (!existsSync3(candidate)) return void 0;
|
|
2943
|
+
try {
|
|
2944
|
+
if (statSync3(candidate).isDirectory()) return candidate;
|
|
2945
|
+
const linked = follow_git_file(repository_path, candidate);
|
|
2946
|
+
return linked === void 0 ? void 0 : resolve_common_directory(linked);
|
|
2947
|
+
} catch {
|
|
2948
|
+
return void 0;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
function read_text(file) {
|
|
2952
|
+
try {
|
|
2953
|
+
return readFileSync4(file, "utf8");
|
|
2954
|
+
} catch {
|
|
2955
|
+
return void 0;
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
var git_directories2 = stamped_memo.create();
|
|
2959
|
+
var configs = stamped_memo.create();
|
|
2960
|
+
function read_config(repository_path) {
|
|
2961
|
+
const git_entry = path7.join(repository_path, GIT_DIRECTORY);
|
|
2962
|
+
const git_directory = git_directories2.of(
|
|
2963
|
+
repository_path,
|
|
2964
|
+
stamped_memo.file_stamp(git_entry),
|
|
2965
|
+
() => resolve_git_directory(repository_path)
|
|
2966
|
+
);
|
|
2967
|
+
if (git_directory === void 0) return void 0;
|
|
2968
|
+
const config = path7.join(git_directory, GIT_CONFIG);
|
|
2969
|
+
return configs.of(config, stamped_memo.file_stamp(config), () => read_text(config));
|
|
2970
|
+
}
|
|
2971
|
+
function read_origin_url(repository_path) {
|
|
2972
|
+
const config = read_config(repository_path);
|
|
2973
|
+
return config === void 0 ? void 0 : repo_origin.parse_origin_from_config(config);
|
|
2974
|
+
}
|
|
2975
|
+
function read_remote_urls(repository_path) {
|
|
2976
|
+
const config = read_config(repository_path);
|
|
2977
|
+
return config === void 0 ? [] : repo_origin.parse_remote_urls_from_config(config);
|
|
2978
|
+
}
|
|
2979
|
+
function sibling_directories(parent) {
|
|
2980
|
+
try {
|
|
2981
|
+
return readdirSync2(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path7.join(parent, entry.name)).toSorted((left, right) => left.localeCompare(right));
|
|
2982
|
+
} catch {
|
|
2983
|
+
return [];
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
function scan_siblings(parent) {
|
|
2987
|
+
return sibling_directories(parent).map((repository_path) => ({
|
|
2988
|
+
path: repository_path,
|
|
2989
|
+
origin_url: read_origin_url(repository_path)
|
|
2990
|
+
}));
|
|
2991
|
+
}
|
|
2992
|
+
function resolve_current_owner(repository_path) {
|
|
2993
|
+
const origin_url2 = read_origin_url(repository_path);
|
|
2994
|
+
if (origin_url2 === void 0) return void 0;
|
|
2995
|
+
return repo_origin.parse_origin_url(origin_url2)?.owner;
|
|
2996
|
+
}
|
|
2997
|
+
function main_worktree(repository_path) {
|
|
2998
|
+
const git_directory = resolve_git_directory(repository_path);
|
|
2999
|
+
if (git_directory === void 0 || path7.basename(git_directory) !== GIT_DIRECTORY) {
|
|
3000
|
+
return repository_path;
|
|
3001
|
+
}
|
|
3002
|
+
return path7.dirname(git_directory);
|
|
3003
|
+
}
|
|
3004
|
+
function discover_repositories(repository_path, environment = process.env) {
|
|
3005
|
+
const main = main_worktree(repository_path);
|
|
3006
|
+
const current_owner = resolve_current_owner(main);
|
|
3007
|
+
if (current_owner === void 0) return /* @__PURE__ */ new Map();
|
|
3008
|
+
return repo_map_logic.build_repository_map(
|
|
3009
|
+
scan_siblings(path7.dirname(main)),
|
|
3010
|
+
current_owner,
|
|
3011
|
+
environment[OVERRIDE_ENV_KEY]
|
|
3012
|
+
);
|
|
3013
|
+
}
|
|
3014
|
+
var repo_discovery = {
|
|
3015
|
+
OVERRIDE_ENV_KEY,
|
|
3016
|
+
main_worktree,
|
|
3017
|
+
read_origin_url,
|
|
3018
|
+
read_remote_urls,
|
|
3019
|
+
resolve_current_owner,
|
|
3020
|
+
scan_siblings,
|
|
3021
|
+
discover_repositories
|
|
3022
|
+
};
|
|
3023
|
+
|
|
3024
|
+
// scripts/rules/issue-citation.ts
|
|
3025
|
+
var ISSUE_NUMBER = /#\d+/gu;
|
|
3026
|
+
var REFERENCE_BOUNDARY = /[\s#()[\]<>|]/u;
|
|
3027
|
+
var OWNER_REPO = /^[^\s/#]+\/[^\s/#]+$/u;
|
|
3028
|
+
var MARKDOWN_LINK = /\[[^[\]]*\]\([^()]*\)/gu;
|
|
3029
|
+
var NUMBER_CONTINUATION = /^(?:\w|-[a-z])/iu;
|
|
3030
|
+
var CONTINUATION_WIDTH = 2;
|
|
3031
|
+
var GLUED_LEAD = /[&./]/u;
|
|
3032
|
+
var FENCE_MARKER = /^\s*(?:`{3,}|~{3,})/u;
|
|
3033
|
+
var QUOTE_LINE = /^\s*>/u;
|
|
3034
|
+
var PR_PREFIX = /\b(?:pr|pull request)\s*$/iu;
|
|
3035
|
+
var BACKTICK_PAIR = 2;
|
|
3036
|
+
function link_covers(link, index) {
|
|
3037
|
+
const start = link.index ?? 0;
|
|
3038
|
+
return index >= start && index < start + link[0].length;
|
|
3039
|
+
}
|
|
3040
|
+
function is_linked_at(line, index) {
|
|
3041
|
+
for (const link of line.matchAll(MARKDOWN_LINK)) {
|
|
3042
|
+
if (link_covers(link, index)) return true;
|
|
3043
|
+
}
|
|
3044
|
+
return false;
|
|
3045
|
+
}
|
|
3046
|
+
function lead_token(message, hash_index) {
|
|
3047
|
+
let start = hash_index;
|
|
3048
|
+
while (start > 0 && !REFERENCE_BOUNDARY.test(message.charAt(start - 1))) start -= 1;
|
|
3049
|
+
return message.slice(start, hash_index);
|
|
3050
|
+
}
|
|
3051
|
+
function repo_prefix(message, hash_index) {
|
|
3052
|
+
const token = lead_token(message, hash_index);
|
|
3053
|
+
return OWNER_REPO.test(token) ? token : "";
|
|
3054
|
+
}
|
|
3055
|
+
function is_inline_code_at(line, index) {
|
|
3056
|
+
const backticks = line.slice(0, index).split("`").length - 1;
|
|
3057
|
+
return backticks % BACKTICK_PAIR === 1;
|
|
3058
|
+
}
|
|
3059
|
+
function is_bare_at(line, index) {
|
|
3060
|
+
if (is_linked_at(line, index) || is_inline_code_at(line, index)) return false;
|
|
3061
|
+
return !PR_PREFIX.test(line.slice(0, index));
|
|
3062
|
+
}
|
|
3063
|
+
function is_glued(line, reference2) {
|
|
3064
|
+
const end = reference2.index + reference2.text.length;
|
|
3065
|
+
if (NUMBER_CONTINUATION.test(line.slice(end, end + CONTINUATION_WIDTH))) return true;
|
|
3066
|
+
return reference2.prefix === "" && GLUED_LEAD.test(lead_token(line, reference2.index));
|
|
3067
|
+
}
|
|
3068
|
+
function line_references(line) {
|
|
3069
|
+
const references = [];
|
|
3070
|
+
for (const match of line.matchAll(ISSUE_NUMBER)) {
|
|
3071
|
+
const reference2 = { index: match.index, prefix: repo_prefix(line, match.index), text: match[0] };
|
|
3072
|
+
if (!is_glued(line, reference2) && is_bare_at(line, match.index)) references.push(reference2);
|
|
3073
|
+
}
|
|
3074
|
+
return references;
|
|
3075
|
+
}
|
|
3076
|
+
function collect_line_references(line, found) {
|
|
3077
|
+
for (const reference2 of line_references(line)) found.push(`${reference2.prefix}${reference2.text}`);
|
|
3078
|
+
}
|
|
3079
|
+
function lines_outside_fences(message) {
|
|
3080
|
+
const lines = [];
|
|
3081
|
+
let is_in_fence = false;
|
|
3082
|
+
for (const line of message.split("\n")) {
|
|
3083
|
+
if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
|
|
3084
|
+
else if (!is_in_fence) lines.push(line);
|
|
3085
|
+
}
|
|
3086
|
+
return lines;
|
|
3087
|
+
}
|
|
3088
|
+
function prose_lines(message) {
|
|
3089
|
+
return lines_outside_fences(message).filter((line) => !QUOTE_LINE.test(line));
|
|
3090
|
+
}
|
|
3091
|
+
function bare_references(message) {
|
|
3092
|
+
const found = [];
|
|
3093
|
+
for (const line of prose_lines(message)) collect_line_references(line, found);
|
|
3094
|
+
return [...new Set(found)];
|
|
3095
|
+
}
|
|
3096
|
+
function prompt_references(prompt) {
|
|
3097
|
+
const found = /* @__PURE__ */ new Set();
|
|
3098
|
+
for (const match of prompt.matchAll(ISSUE_NUMBER)) {
|
|
3099
|
+
found.add(repo_prefix(prompt, match.index) + match[0]);
|
|
3100
|
+
}
|
|
3101
|
+
return found;
|
|
3102
|
+
}
|
|
3103
|
+
function unquoted_references(message, prompt) {
|
|
3104
|
+
const quoted = prompt_references(prompt);
|
|
3105
|
+
return bare_references(message).filter((reference2) => !quoted.has(reference2));
|
|
3106
|
+
}
|
|
3107
|
+
function has_bare_reference(message) {
|
|
3108
|
+
return bare_references(message).length > 0;
|
|
3109
|
+
}
|
|
3110
|
+
function cite_argument(reference2) {
|
|
3111
|
+
return reference2.startsWith("#") ? reference2.slice(1) : reference2;
|
|
3112
|
+
}
|
|
3113
|
+
function cite_arguments(references) {
|
|
3114
|
+
return references.map((reference2) => cite_argument(reference2));
|
|
3115
|
+
}
|
|
3116
|
+
function reference_link(reference2, default_slug) {
|
|
3117
|
+
const slug = reference2.prefix === "" ? default_slug : reference2.prefix;
|
|
3118
|
+
const number = reference2.text.slice(1);
|
|
3119
|
+
return `[${reference2.prefix}${reference2.text}](${issue_cite.issue_url(slug, number)})`;
|
|
3120
|
+
}
|
|
3121
|
+
function linkify_line(line, slug) {
|
|
3122
|
+
let result = "";
|
|
3123
|
+
let cursor = 0;
|
|
3124
|
+
for (const reference2 of line_references(line)) {
|
|
3125
|
+
const start = reference2.index - reference2.prefix.length;
|
|
3126
|
+
result += line.slice(cursor, start) + reference_link(reference2, slug);
|
|
3127
|
+
cursor = reference2.index + reference2.text.length;
|
|
3128
|
+
}
|
|
3129
|
+
return result + line.slice(cursor);
|
|
3130
|
+
}
|
|
3131
|
+
function rewrite_line(line, slug, is_in_fence) {
|
|
3132
|
+
if (is_in_fence || FENCE_MARKER.test(line) || QUOTE_LINE.test(line)) return line;
|
|
3133
|
+
return linkify_line(line, slug);
|
|
3134
|
+
}
|
|
3135
|
+
function linkify(message, slug) {
|
|
3136
|
+
const out = [];
|
|
3137
|
+
let is_in_fence = false;
|
|
3138
|
+
for (const line of message.split("\n")) {
|
|
3139
|
+
if (FENCE_MARKER.test(line)) is_in_fence = !is_in_fence;
|
|
3140
|
+
out.push(rewrite_line(line, slug, is_in_fence));
|
|
3141
|
+
}
|
|
3142
|
+
return out.join("\n");
|
|
3143
|
+
}
|
|
3144
|
+
var issue_citation = {
|
|
3145
|
+
bare_references,
|
|
3146
|
+
cite_arguments,
|
|
3147
|
+
has_bare_reference,
|
|
3148
|
+
linkify,
|
|
3149
|
+
prose_lines,
|
|
3150
|
+
unquoted_references
|
|
3151
|
+
};
|
|
3152
|
+
|
|
3153
|
+
// scripts/issue/session-cite.ts
|
|
3154
|
+
function session_repo() {
|
|
3155
|
+
const url = repo_discovery.read_origin_url(process.cwd());
|
|
3156
|
+
const identity = url === void 0 ? void 0 : repo_origin.parse_origin_url(url);
|
|
3157
|
+
return identity === void 0 ? void 0 : `${identity.owner}/${identity.repo}`;
|
|
3158
|
+
}
|
|
3159
|
+
function issue(number, title, repo = session_repo()) {
|
|
3160
|
+
return issue_cite.reference(repo, String(number), title);
|
|
3161
|
+
}
|
|
3162
|
+
function text(message) {
|
|
3163
|
+
const repo = session_repo();
|
|
3164
|
+
return repo === void 0 ? message : issue_citation.linkify(message, repo);
|
|
3165
|
+
}
|
|
3166
|
+
var session_cite = {
|
|
3167
|
+
issue,
|
|
3168
|
+
session_repo,
|
|
3169
|
+
text
|
|
3170
|
+
};
|
|
3171
|
+
|
|
3172
|
+
// scripts/lane/lane-state.ts
|
|
3173
|
+
import { readdirSync as readdirSync3 } from "node:fs";
|
|
3174
|
+
import path8 from "node:path";
|
|
3175
|
+
|
|
3176
|
+
// scripts/lib/figure-format.ts
|
|
3177
|
+
var USD_DECIMALS = 4;
|
|
3178
|
+
var PERCENT_SCALE = 100;
|
|
3179
|
+
var PERCENT_DECIMALS = 1;
|
|
3180
|
+
var MINUTE_DECIMALS = 1;
|
|
3181
|
+
var CLOCK_WIDTH = 2;
|
|
3182
|
+
var CLOCK_PAD = "0";
|
|
3183
|
+
function format_usd(usd, decimals = USD_DECIMALS) {
|
|
3184
|
+
return `$${usd.toFixed(decimals)}`;
|
|
3185
|
+
}
|
|
3186
|
+
function format_tokens(count) {
|
|
3187
|
+
return count.toLocaleString("en-US");
|
|
3188
|
+
}
|
|
3189
|
+
function format_share(part, whole) {
|
|
3190
|
+
if (whole === 0) return "n/a";
|
|
3191
|
+
return `${(part / whole * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`;
|
|
3192
|
+
}
|
|
3193
|
+
function format_minutes(duration_ms) {
|
|
3194
|
+
return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`;
|
|
3195
|
+
}
|
|
3196
|
+
function two_digits(value) {
|
|
3197
|
+
return String(value).padStart(CLOCK_WIDTH, CLOCK_PAD);
|
|
3198
|
+
}
|
|
3199
|
+
function clock_of(ms) {
|
|
3200
|
+
const date = new Date(ms);
|
|
3201
|
+
return [date.getHours(), date.getMinutes(), date.getSeconds()].map((value) => two_digits(value)).join(":");
|
|
3202
|
+
}
|
|
3203
|
+
function minute_of(ms) {
|
|
3204
|
+
const date = new Date(ms);
|
|
3205
|
+
return [date.getHours(), date.getMinutes()].map((value) => two_digits(value)).join(":");
|
|
3206
|
+
}
|
|
3207
|
+
var figure_format = {
|
|
3208
|
+
format_usd,
|
|
3209
|
+
format_tokens,
|
|
3210
|
+
format_share,
|
|
3211
|
+
format_minutes,
|
|
3212
|
+
two_digits,
|
|
3213
|
+
clock_of,
|
|
3214
|
+
minute_of
|
|
3215
|
+
};
|
|
3216
|
+
|
|
3217
|
+
// scripts/lane/lane-state.ts
|
|
3218
|
+
import { z as z6 } from "zod";
|
|
3219
|
+
var STATE_PREFIX = "josh-lane-state-";
|
|
3220
|
+
var STATE_SUFFIX = ".json";
|
|
3221
|
+
var LOCK_SUFFIX2 = ".lock";
|
|
3222
|
+
var LOCK_WAIT_MS2 = 5e3;
|
|
3223
|
+
var LANE_STATES = ["open", "running", "paused", "ended"];
|
|
3224
|
+
var NO_STATE_HINT = "no lane state \u2014 counted in use";
|
|
3225
|
+
var lane_run_schema = z6.object({ started_at: z6.string(), owner_pid: z6.number().optional() });
|
|
3226
|
+
var stuck_schema = z6.object({ pid: z6.number(), reason: z6.string() });
|
|
3227
|
+
var lane_state_schema = z6.object({
|
|
3228
|
+
issue: z6.string(),
|
|
3229
|
+
run: lane_run_schema.optional(),
|
|
3230
|
+
state: z6.enum(LANE_STATES),
|
|
3231
|
+
launched_at: z6.string().optional(),
|
|
3232
|
+
changed_at: z6.string(),
|
|
3233
|
+
changed_by: z6.string(),
|
|
3234
|
+
stuck: z6.array(stuck_schema).optional()
|
|
3235
|
+
});
|
|
3236
|
+
var TRANSITIONS = {
|
|
3237
|
+
open: ["open", "running", "ended"],
|
|
3238
|
+
running: ["running", "paused", "ended"],
|
|
3239
|
+
paused: ["paused", "running", "ended"],
|
|
3240
|
+
ended: ["ended", "open"]
|
|
3241
|
+
};
|
|
3242
|
+
function state_path(directory, issue2) {
|
|
3243
|
+
return stamp_file.stamp_path(STATE_PREFIX, directory, `-${issue2}${STATE_SUFFIX}`);
|
|
3244
|
+
}
|
|
3245
|
+
function is_allowed(from, to) {
|
|
3246
|
+
return from === void 0 || TRANSITIONS[from].includes(to);
|
|
3247
|
+
}
|
|
3248
|
+
function read_record2(directory, issue2) {
|
|
3249
|
+
const raw = stamp_file.read_stamp_text(state_path(directory, issue2));
|
|
3250
|
+
return raw === void 0 ? void 0 : json_value.parse_with(raw, lane_state_schema);
|
|
3251
|
+
}
|
|
3252
|
+
function write_record(directory, record) {
|
|
3253
|
+
stamp_file.replace_stamp(state_path(directory, record.issue), record);
|
|
3254
|
+
}
|
|
3255
|
+
function current_run(directory) {
|
|
3256
|
+
const carried = run_carry.read_carry(run_carry.carry_path(directory));
|
|
3257
|
+
if (carried.kind !== "carried") return void 0;
|
|
3258
|
+
return { started_at: carried.carry.started_at, owner_pid: carried.carry.owner_pid };
|
|
3259
|
+
}
|
|
3260
|
+
function launch_fields(change, directory, now) {
|
|
3261
|
+
if (change.is_launch !== true) return {};
|
|
3262
|
+
return { run: current_run(directory), launched_at: now.toISOString() };
|
|
3263
|
+
}
|
|
3264
|
+
function next_record(change, previous, directory, now) {
|
|
3265
|
+
return {
|
|
3266
|
+
// An open starts a fresh life: a reopened lane keeps nothing of the run that launched it before.
|
|
3267
|
+
...change.state !== "open" && previous,
|
|
3268
|
+
issue: change.issue,
|
|
3269
|
+
state: change.state,
|
|
3270
|
+
changed_at: now.toISOString(),
|
|
3271
|
+
changed_by: change.command,
|
|
3272
|
+
...launch_fields(change, directory, now)
|
|
3273
|
+
};
|
|
3274
|
+
}
|
|
3275
|
+
function apply_held(change, directory, now) {
|
|
3276
|
+
const previous = read_record2(directory, change.issue);
|
|
3277
|
+
if (!is_allowed(previous?.state, change.state)) {
|
|
3278
|
+
return { kind: "skipped", reason: `no ${previous?.state ?? ""} \u2192 ${change.state} transition` };
|
|
3279
|
+
}
|
|
3280
|
+
const record = next_record(change, previous, directory, now);
|
|
3281
|
+
write_record(directory, record);
|
|
3282
|
+
return { kind: "written", record };
|
|
3283
|
+
}
|
|
3284
|
+
var NO_DIRECTORY = { kind: "skipped", reason: "no git directory" };
|
|
3285
|
+
function locked(directory, issue2, held) {
|
|
3286
|
+
const lock = `${state_path(directory, issue2)}${LOCK_SUFFIX2}`;
|
|
3287
|
+
const outcome = repository_lock.with_lock_sync(held, lock, LOCK_WAIT_MS2);
|
|
3288
|
+
return outcome ?? { kind: "skipped", reason: `gave up waiting for the lock at ${lock}` };
|
|
3289
|
+
}
|
|
3290
|
+
function apply(change, directory, now) {
|
|
3291
|
+
return locked(directory, change.issue, () => apply_held(change, directory, now));
|
|
3292
|
+
}
|
|
3293
|
+
function warn(change, reason) {
|
|
3294
|
+
console.warn(
|
|
3295
|
+
`${change.command} ${session_cite.issue(change.issue)}: lane state not recorded \u2014 ${reason}`
|
|
3296
|
+
);
|
|
3297
|
+
}
|
|
3298
|
+
async function resolve_directory(directory) {
|
|
3299
|
+
return directory ?? await run_carry.repository_directory();
|
|
3300
|
+
}
|
|
3301
|
+
async function outcome_of(change, options) {
|
|
3302
|
+
const directory = await resolve_directory(options.directory);
|
|
3303
|
+
if (directory === void 0) return NO_DIRECTORY;
|
|
3304
|
+
return apply(change, directory, options.now ?? /* @__PURE__ */ new Date());
|
|
3305
|
+
}
|
|
3306
|
+
async function settled_outcome(change, options) {
|
|
3307
|
+
try {
|
|
3308
|
+
return await outcome_of(change, options);
|
|
3309
|
+
} catch (error) {
|
|
3310
|
+
return { kind: "skipped", reason: error instanceof Error ? error.message : String(error) };
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
async function record_change(change, options = {}) {
|
|
3314
|
+
const outcome = await settled_outcome(change, options);
|
|
3315
|
+
if (outcome.kind === "skipped") warn(change, outcome.reason);
|
|
3316
|
+
return outcome;
|
|
3317
|
+
}
|
|
3318
|
+
async function read_state(issue2, directory) {
|
|
3319
|
+
const root = await resolve_directory(directory);
|
|
3320
|
+
return root === void 0 ? void 0 : read_record2(root, issue2);
|
|
3321
|
+
}
|
|
3322
|
+
function recorded_issues(directory) {
|
|
3323
|
+
const empty = state_path(directory, "");
|
|
3324
|
+
const head = path8.basename(empty).slice(0, -STATE_SUFFIX.length);
|
|
3325
|
+
return readdirSync3(path8.dirname(empty)).filter((name) => name.startsWith(head) && name.endsWith(STATE_SUFFIX)).map((name) => name.slice(head.length, -STATE_SUFFIX.length)).filter((issue2) => issue2.length > 0);
|
|
3326
|
+
}
|
|
3327
|
+
async function read_records(directory) {
|
|
3328
|
+
const root = await resolve_directory(directory);
|
|
3329
|
+
if (root === void 0) return [];
|
|
3330
|
+
const records = recorded_issues(root).map((issue2) => read_record2(root, issue2));
|
|
3331
|
+
return records.filter((record) => record !== void 0);
|
|
3332
|
+
}
|
|
3333
|
+
function stuck_held(issue2, stuck, directory) {
|
|
3334
|
+
const previous = read_record2(directory, issue2);
|
|
3335
|
+
if (previous === void 0) return { kind: "skipped", reason: "no record" };
|
|
3336
|
+
const record = { ...previous, stuck };
|
|
3337
|
+
write_record(directory, record);
|
|
3338
|
+
return { kind: "written", record };
|
|
3339
|
+
}
|
|
3340
|
+
async function record_stuck(issue2, stuck, directory) {
|
|
3341
|
+
const root = await resolve_directory(directory);
|
|
3342
|
+
if (root === void 0) return NO_DIRECTORY;
|
|
3343
|
+
return locked(root, issue2, () => stuck_held(issue2, stuck, root));
|
|
3344
|
+
}
|
|
3345
|
+
async function read_states(issues, directory) {
|
|
3346
|
+
const root = await resolve_directory(directory);
|
|
3347
|
+
if (root === void 0) return /* @__PURE__ */ new Map();
|
|
3348
|
+
const read3 = issues.map((issue2) => [
|
|
3349
|
+
issue2,
|
|
3350
|
+
read_record2(root, issue2)
|
|
3351
|
+
]);
|
|
3352
|
+
return new Map(read3.filter((entry) => entry[1] !== void 0));
|
|
3353
|
+
}
|
|
3354
|
+
function paused_text(since_ms, changed_by) {
|
|
3355
|
+
return `paused since ${figure_format.minute_of(since_ms)} by ${changed_by}`;
|
|
3356
|
+
}
|
|
3357
|
+
function paused_note(record) {
|
|
3358
|
+
if (record?.state !== "paused") return void 0;
|
|
3359
|
+
return paused_text(Date.parse(record.changed_at), record.changed_by);
|
|
3360
|
+
}
|
|
3361
|
+
var lane_state = {
|
|
3362
|
+
LANE_STATES,
|
|
3363
|
+
NO_STATE_HINT,
|
|
3364
|
+
is_allowed,
|
|
3365
|
+
paused_note,
|
|
3366
|
+
paused_text,
|
|
3367
|
+
read_records,
|
|
3368
|
+
read_state,
|
|
3369
|
+
read_states,
|
|
3370
|
+
record_change,
|
|
3371
|
+
record_stuck,
|
|
3372
|
+
state_path
|
|
3373
|
+
};
|
|
3374
|
+
|
|
3375
|
+
// scripts/run/event/run-event-scope.ts
|
|
3376
|
+
var SINCE_SCOPE = "since";
|
|
3377
|
+
var UNKNOWN_SCOPE = "unknown";
|
|
3378
|
+
var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
|
|
3379
|
+
function moment_of(at) {
|
|
3380
|
+
const parsed = Date.parse(at);
|
|
3381
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
3382
|
+
}
|
|
3383
|
+
function is_within(event, floor) {
|
|
3384
|
+
const at = moment_of(event.at);
|
|
3385
|
+
return at !== void 0 && at >= floor;
|
|
3386
|
+
}
|
|
3387
|
+
function scoped_events(events, scope) {
|
|
3388
|
+
if (scope.kind === UNKNOWN_SCOPE) return void 0;
|
|
3389
|
+
const floor = moment_of(scope.started_at);
|
|
3390
|
+
if (floor === void 0) return void 0;
|
|
3391
|
+
return events.filter((event) => is_within(event, floor));
|
|
3392
|
+
}
|
|
3393
|
+
function scope_of(read3) {
|
|
3394
|
+
if (read3.kind !== "carried") return UNKNOWN_EVENT_SCOPE;
|
|
3395
|
+
return { kind: SINCE_SCOPE, started_at: read3.carry.started_at };
|
|
3396
|
+
}
|
|
3397
|
+
function last_scoped_event(events, scope) {
|
|
3398
|
+
return scoped_events(events, scope)?.findLast(
|
|
3399
|
+
(event) => !run_event_stream.TRACE_KINDS.has(event.kind)
|
|
3400
|
+
);
|
|
3401
|
+
}
|
|
3402
|
+
var SHIP_POSITION_KINDS = /* @__PURE__ */ new Set([
|
|
3403
|
+
run_event_stream.EVENT_KIND.SHIP_LAUNCH,
|
|
3404
|
+
run_event_stream.EVENT_KIND.SHIP_STOP
|
|
3405
|
+
]);
|
|
3406
|
+
var KIND = run_event_stream.EVENT_KIND;
|
|
3407
|
+
var BATCH_RECORD_KINDS = /* @__PURE__ */ new Set([
|
|
3408
|
+
KIND.CHILD_LAUNCH,
|
|
3409
|
+
KIND.RESTART,
|
|
3410
|
+
KIND.WITHDRAW,
|
|
3411
|
+
KIND.PARK,
|
|
3412
|
+
KIND.SPLIT,
|
|
3413
|
+
KIND.RETROSPECTIVE,
|
|
3414
|
+
KIND.STRANDED
|
|
3415
|
+
]);
|
|
3416
|
+
var ISSUE_REFERENCE = /#(\d+)/u;
|
|
3417
|
+
function is_foreign_ship_event(event, issue2) {
|
|
3418
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`${issue_cite.plain(issue2)} `);
|
|
3419
|
+
}
|
|
3420
|
+
function is_own_ship_event(event, issue2) {
|
|
3421
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue2);
|
|
3422
|
+
}
|
|
3423
|
+
function issue_named(event) {
|
|
3424
|
+
return ISSUE_REFERENCE.exec(event.text)?.[1];
|
|
3425
|
+
}
|
|
3426
|
+
function names_issue(event, issue2) {
|
|
3427
|
+
return issue_named(event) === issue2;
|
|
3428
|
+
}
|
|
3429
|
+
function is_lane_position(event, issue2) {
|
|
3430
|
+
return !BATCH_RECORD_KINDS.has(event.kind) && names_issue(event, issue2);
|
|
3431
|
+
}
|
|
3432
|
+
function since_own_launch(events, issue2) {
|
|
3433
|
+
const launch = events.findLastIndex(
|
|
3434
|
+
(event) => event.kind === KIND.CHILD_LAUNCH && names_issue(event, issue2)
|
|
3435
|
+
);
|
|
3436
|
+
return events.slice(launch + 1);
|
|
3437
|
+
}
|
|
3438
|
+
function is_foreign_event(event, issue2, is_lane_child) {
|
|
3439
|
+
if (is_lane_child) return !is_lane_position(event, issue2);
|
|
3440
|
+
return is_foreign_ship_event(event, issue2);
|
|
3441
|
+
}
|
|
3442
|
+
function last_issue_event(events, scope, issue2, is_lane_child) {
|
|
3443
|
+
const attempt = is_lane_child ? since_own_launch(events, issue2) : events;
|
|
3444
|
+
const own2 = attempt.filter((event) => !is_foreign_event(event, issue2, is_lane_child));
|
|
3445
|
+
if (scope.kind === SINCE_SCOPE) return last_scoped_event(own2, scope);
|
|
3446
|
+
return own2.findLast((event) => is_own_ship_event(event, issue2));
|
|
3447
|
+
}
|
|
3448
|
+
var LAUNCH_OR_SETTLE_KINDS = /* @__PURE__ */ new Set([
|
|
3449
|
+
KIND.CHILD_LAUNCH,
|
|
3450
|
+
KIND.MERGE,
|
|
3451
|
+
KIND.PARK,
|
|
3452
|
+
KIND.SPLIT,
|
|
3453
|
+
KIND.WITHDRAW
|
|
3454
|
+
]);
|
|
3455
|
+
function is_merge_owed(events, scope, issue2) {
|
|
3456
|
+
const newest = (scoped_events(events, scope) ?? []).findLast(
|
|
3457
|
+
(event) => LAUNCH_OR_SETTLE_KINDS.has(event.kind) && names_issue(event, issue2)
|
|
3458
|
+
);
|
|
3459
|
+
return newest?.kind === KIND.CHILD_LAUNCH;
|
|
3460
|
+
}
|
|
3461
|
+
function is_launch_or_withdrawal(event, issue2) {
|
|
3462
|
+
const is_kind = event.kind === KIND.CHILD_LAUNCH || event.kind === KIND.WITHDRAW;
|
|
3463
|
+
return is_kind && names_issue(event, issue2);
|
|
3464
|
+
}
|
|
3465
|
+
function is_withdrawn(events, issue2) {
|
|
3466
|
+
const newest = events.findLast((event) => is_launch_or_withdrawal(event, issue2));
|
|
3467
|
+
return newest?.kind === KIND.WITHDRAW;
|
|
3468
|
+
}
|
|
3469
|
+
var run_event_scope = {
|
|
3470
|
+
UNKNOWN_EVENT_SCOPE,
|
|
3471
|
+
is_merge_owed,
|
|
3472
|
+
is_withdrawn,
|
|
3473
|
+
issue_named,
|
|
3474
|
+
last_issue_event,
|
|
3475
|
+
last_scoped_event,
|
|
3476
|
+
moment_of,
|
|
3477
|
+
scope_of,
|
|
3478
|
+
scoped_events,
|
|
3479
|
+
since_own_launch
|
|
3480
|
+
};
|
|
3481
|
+
|
|
3482
|
+
// scripts/lane/lane-spans.ts
|
|
3483
|
+
function next_start_ms(starts, issue2, from_ms) {
|
|
3484
|
+
const later = starts.filter((other) => other.issue === issue2 && other.at_ms > from_ms);
|
|
3485
|
+
return Math.min(...later.map((other) => other.at_ms));
|
|
3486
|
+
}
|
|
3487
|
+
function issue_spans(pair) {
|
|
3488
|
+
return pair.starts.map((start) => {
|
|
3489
|
+
const until_ms = next_start_ms(pair.bounds, start.issue, start.at_ms);
|
|
3490
|
+
return {
|
|
3491
|
+
from_ms: start.at_ms,
|
|
3492
|
+
end_ms: pair.ends.find(
|
|
3493
|
+
(end) => end.issue === start.issue && end.at_ms >= start.at_ms && end.at_ms < until_ms
|
|
3494
|
+
)?.at_ms
|
|
3495
|
+
};
|
|
3496
|
+
});
|
|
3497
|
+
}
|
|
3498
|
+
var lane_spans = { issue_spans };
|
|
3499
|
+
|
|
3500
|
+
// scripts/run/board/run-board-lane-time.ts
|
|
3501
|
+
var KIND2 = run_event_stream.EVENT_KIND;
|
|
3502
|
+
var LAUNCH_KINDS = /* @__PURE__ */ new Set([KIND2.CHILD_LAUNCH, KIND2.RESTART]);
|
|
3503
|
+
var OFF_LANE_KINDS = /* @__PURE__ */ new Set([
|
|
3504
|
+
KIND2.MERGE,
|
|
3505
|
+
KIND2.PARK,
|
|
3506
|
+
KIND2.WITHDRAW,
|
|
3507
|
+
KIND2.OUTAGE,
|
|
3508
|
+
KIND2.SPLIT,
|
|
3509
|
+
KIND2.STOP
|
|
3510
|
+
]);
|
|
3511
|
+
function moments_of(events, kinds) {
|
|
3512
|
+
return events.filter((event) => kinds.has(event.kind)).map((event) => ({
|
|
3513
|
+
issue: Number(run_event_scope.issue_named(event)),
|
|
3514
|
+
at_ms: Date.parse(event.at)
|
|
3515
|
+
}));
|
|
3516
|
+
}
|
|
3517
|
+
function spans_of(events) {
|
|
3518
|
+
const launches = moments_of(events, LAUNCH_KINDS);
|
|
3519
|
+
const ends = moments_of(events, OFF_LANE_KINDS);
|
|
3520
|
+
const issues = new Set(launches.map((launch) => launch.issue));
|
|
3521
|
+
return new Map(
|
|
3522
|
+
[...issues].map((issue2) => {
|
|
3523
|
+
const starts = launches.filter((launch) => launch.issue === issue2);
|
|
3524
|
+
return [issue2, lane_spans.issue_spans({ starts, bounds: starts, ends })];
|
|
3525
|
+
})
|
|
3526
|
+
);
|
|
3527
|
+
}
|
|
3528
|
+
function span_ms(span, until_ms, end_ms) {
|
|
3529
|
+
return Math.max(0, Math.min(span.end_ms ?? until_ms, end_ms) - span.from_ms);
|
|
3530
|
+
}
|
|
3531
|
+
function in_lane_ms(spans, end_ms) {
|
|
3532
|
+
return spans.reduce(
|
|
3533
|
+
(total, span, index) => total + span_ms(span, spans[index + 1]?.from_ms ?? end_ms, end_ms),
|
|
3534
|
+
0
|
|
3535
|
+
);
|
|
3536
|
+
}
|
|
3537
|
+
function elapsed_of(spans, started_ms, ended_ms) {
|
|
3538
|
+
return spans.length === 0 ? ended_ms - started_ms : in_lane_ms(spans, ended_ms);
|
|
3539
|
+
}
|
|
3540
|
+
function launched_ms(record) {
|
|
3541
|
+
const launched_at = record?.launched_at;
|
|
3542
|
+
return launched_at === void 0 ? void 0 : Date.parse(launched_at);
|
|
3543
|
+
}
|
|
3544
|
+
function counted_from(run3, started_ms) {
|
|
3545
|
+
return run3 === void 0 ? started_ms : Date.parse(run3.started_at);
|
|
3546
|
+
}
|
|
3547
|
+
function is_ended(spans) {
|
|
3548
|
+
return spans.at(-1)?.end_ms !== void 0;
|
|
3549
|
+
}
|
|
3550
|
+
function ending_elapsed(read3) {
|
|
3551
|
+
const started_ms = launched_ms(read3.record);
|
|
3552
|
+
if (started_ms === void 0) return void 0;
|
|
3553
|
+
const from_ms = counted_from(read3.record?.run, started_ms);
|
|
3554
|
+
const spans = (spans_of(read3.events).get(read3.issue) ?? []).filter(
|
|
3555
|
+
(span) => span.from_ms >= from_ms
|
|
3556
|
+
);
|
|
3557
|
+
return is_ended(spans) ? void 0 : elapsed_of(spans, started_ms, read3.ended_ms);
|
|
3558
|
+
}
|
|
3559
|
+
var run_board_lane_time = {
|
|
3560
|
+
LAUNCH_KINDS,
|
|
3561
|
+
OFF_LANE_KINDS,
|
|
3562
|
+
elapsed_of,
|
|
3563
|
+
ending_elapsed,
|
|
3564
|
+
in_lane_ms,
|
|
3565
|
+
spans_of
|
|
3566
|
+
};
|
|
3567
|
+
|
|
3568
|
+
// scripts/run/event/run-event-stream-emit.ts
|
|
3569
|
+
function now_iso() {
|
|
3570
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
3571
|
+
}
|
|
3572
|
+
async function stream_target() {
|
|
3573
|
+
const repository2 = await run_carry.repository_directory();
|
|
3574
|
+
return repository2 === void 0 ? void 0 : run_event_stream.target_of(repository2);
|
|
3575
|
+
}
|
|
3576
|
+
async function lane_record(issue2) {
|
|
3577
|
+
try {
|
|
3578
|
+
return await lane_state.read_state(issue2);
|
|
3579
|
+
} catch (error) {
|
|
3580
|
+
error_text.trace_swallowed("run_event_stream_emit.lane_record", error);
|
|
3581
|
+
return void 0;
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
async function ending_fields(target, event) {
|
|
3585
|
+
const issue2 = run_event_scope.issue_named(event);
|
|
3586
|
+
if (issue2 === void 0 || !run_board_lane_time.OFF_LANE_KINDS.has(event.kind)) return {};
|
|
3587
|
+
const elapsed_ms = run_board_lane_time.ending_elapsed({
|
|
3588
|
+
events: run_event_stream.read_events(target),
|
|
3589
|
+
issue: Number(issue2),
|
|
3590
|
+
record: await lane_record(issue2),
|
|
3591
|
+
ended_ms: Date.parse(event.at)
|
|
3592
|
+
});
|
|
3593
|
+
return elapsed_ms === void 0 ? {} : { elapsed_ms };
|
|
3594
|
+
}
|
|
3595
|
+
async function append_at(target, kind, text2, at) {
|
|
3596
|
+
const event = { kind, text: text2, at: at.toISOString() };
|
|
3597
|
+
return run_event_stream.append_event(target, {
|
|
3598
|
+
...event,
|
|
3599
|
+
...await ending_fields(target, event)
|
|
3600
|
+
});
|
|
3601
|
+
}
|
|
3602
|
+
async function emit(kind, text2, at = /* @__PURE__ */ new Date()) {
|
|
3603
|
+
try {
|
|
3604
|
+
const target = await stream_target();
|
|
3605
|
+
if (target === void 0) return;
|
|
3606
|
+
await append_at(target, kind, text2, at);
|
|
3607
|
+
} catch {
|
|
3608
|
+
}
|
|
3609
|
+
}
|
|
3610
|
+
async function emit_once(kind, text2) {
|
|
3611
|
+
try {
|
|
3612
|
+
const target = await stream_target();
|
|
3613
|
+
if (target === void 0 || run_event_stream.read_last(target)?.kind === kind) return false;
|
|
3614
|
+
return run_event_stream.append(target, kind, text2, now_iso()).appended;
|
|
3615
|
+
} catch (error) {
|
|
3616
|
+
error_text.trace_swallowed("run_event_stream_emit.emit_once", error);
|
|
3617
|
+
return false;
|
|
3618
|
+
}
|
|
3619
|
+
}
|
|
3620
|
+
function invocation_events(repository2, target) {
|
|
3621
|
+
const events = run_event_stream.read_events(target);
|
|
3622
|
+
const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository2)));
|
|
3623
|
+
return run_event_scope.scoped_events(events, scope) ?? events;
|
|
3624
|
+
}
|
|
3625
|
+
async function emit_once_since_with(kind, reset_kind, compose) {
|
|
3626
|
+
try {
|
|
3627
|
+
const repository2 = await run_carry.repository_directory();
|
|
3628
|
+
if (repository2 === void 0) return void 0;
|
|
3629
|
+
const target = run_event_stream.target_of(repository2);
|
|
3630
|
+
if (run_event_stream.has_since(invocation_events(repository2, target), kind, reset_kind)) {
|
|
3631
|
+
return void 0;
|
|
3632
|
+
}
|
|
3633
|
+
const text2 = await compose();
|
|
3634
|
+
return run_event_stream.append(target, kind, text2, now_iso()).appended ? text2 : void 0;
|
|
3635
|
+
} catch (error) {
|
|
3636
|
+
error_text.trace_swallowed("run_event_stream_emit.emit_once_since", error);
|
|
3637
|
+
return void 0;
|
|
3638
|
+
}
|
|
3639
|
+
}
|
|
3640
|
+
async function emit_once_since(kind, text2, reset_kind) {
|
|
3641
|
+
const appended = await emit_once_since_with(kind, reset_kind, async () => text2);
|
|
3642
|
+
return appended !== void 0;
|
|
3643
|
+
}
|
|
3644
|
+
async function emit_heartbeat(line) {
|
|
3645
|
+
await emit(run_event_stream.EVENT_KIND.HEARTBEAT, line);
|
|
3646
|
+
}
|
|
3647
|
+
async function current_events() {
|
|
3648
|
+
try {
|
|
3649
|
+
const repository2 = await run_carry.repository_directory();
|
|
3650
|
+
if (repository2 === void 0) return [];
|
|
3651
|
+
const read3 = run_carry.read_carry(run_carry.carry_path(repository2));
|
|
3652
|
+
const scope = run_event_scope.scope_of(read3);
|
|
3653
|
+
const events = run_event_stream.read_events(run_event_stream.target_of(repository2));
|
|
3654
|
+
return run_event_scope.scoped_events(events, scope) ?? [];
|
|
3655
|
+
} catch {
|
|
3656
|
+
return [];
|
|
3657
|
+
}
|
|
3658
|
+
}
|
|
3659
|
+
async function invocation_or_all_events() {
|
|
3660
|
+
try {
|
|
3661
|
+
const repository2 = await run_carry.repository_directory();
|
|
3662
|
+
return repository2 === void 0 ? [] : invocation_events(repository2, run_event_stream.target_of(repository2));
|
|
3663
|
+
} catch {
|
|
3664
|
+
return [];
|
|
3665
|
+
}
|
|
3666
|
+
}
|
|
3667
|
+
async function all_events() {
|
|
3668
|
+
try {
|
|
3669
|
+
const target = await stream_target();
|
|
3670
|
+
return target === void 0 ? [] : run_event_stream.read_events(target);
|
|
3671
|
+
} catch {
|
|
3672
|
+
return [];
|
|
3673
|
+
}
|
|
3674
|
+
}
|
|
3675
|
+
var run_event_stream_emit = {
|
|
3676
|
+
all_events,
|
|
3677
|
+
append_at,
|
|
3678
|
+
current_events,
|
|
3679
|
+
emit,
|
|
3680
|
+
emit_heartbeat,
|
|
3681
|
+
emit_once,
|
|
3682
|
+
emit_once_since,
|
|
3683
|
+
emit_once_since_with,
|
|
3684
|
+
invocation_or_all_events,
|
|
3685
|
+
stream_target
|
|
3686
|
+
};
|
|
3687
|
+
|
|
3688
|
+
// scripts/lib/ancestor-directories.ts
|
|
3689
|
+
import path9 from "node:path";
|
|
3690
|
+
var MAX_DEPTH = 64;
|
|
3691
|
+
function list(start_directory) {
|
|
3692
|
+
const directories2 = [];
|
|
3693
|
+
let current = path9.resolve(start_directory);
|
|
3694
|
+
while (directories2.length < MAX_DEPTH && !directories2.includes(current)) {
|
|
3695
|
+
directories2.push(current);
|
|
3696
|
+
current = path9.dirname(current);
|
|
3697
|
+
}
|
|
3698
|
+
return directories2;
|
|
3699
|
+
}
|
|
3700
|
+
function nearest(start_directory, is_match) {
|
|
3701
|
+
return list(start_directory).find((directory) => is_match(directory));
|
|
3702
|
+
}
|
|
3703
|
+
var ancestor_directories = { list, nearest };
|
|
3704
|
+
|
|
3705
|
+
// scripts/lib/package-manifest.ts
|
|
3706
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
3707
|
+
import path10 from "node:path";
|
|
3708
|
+
var PACKAGE_JSON = "package.json";
|
|
3709
|
+
function manifest_path(directory) {
|
|
3710
|
+
return path10.join(directory, PACKAGE_JSON);
|
|
3711
|
+
}
|
|
3712
|
+
function read_manifest(directory, schema) {
|
|
3713
|
+
const text2 = readFileSync5(manifest_path(directory), "utf8");
|
|
3714
|
+
return schema.parse(JSON.parse(text2));
|
|
3715
|
+
}
|
|
3716
|
+
function read_manifest_if_valid(directory, schema) {
|
|
3717
|
+
const text2 = file_reader.read_if_readable(manifest_path(directory));
|
|
3718
|
+
if (text2 === void 0) return void 0;
|
|
3719
|
+
return json_value.parse_with(text2, schema);
|
|
3720
|
+
}
|
|
3721
|
+
var package_manifest = { manifest_path, read_manifest, read_manifest_if_valid };
|
|
3722
|
+
|
|
3723
|
+
// scripts/git/git-schemas.ts
|
|
3724
|
+
import { z as z7 } from "zod";
|
|
3725
|
+
var package_name_schema = z7.object({ name: z7.string().min(1) });
|
|
3726
|
+
var rollup_item_schema = z7.looseObject({
|
|
3727
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
|
|
3728
|
+
__typename: z7.string().nullish(),
|
|
3729
|
+
state: z7.string().nullish(),
|
|
3730
|
+
status: z7.string().nullish(),
|
|
3731
|
+
conclusion: z7.string().nullish(),
|
|
3732
|
+
name: z7.string().nullish(),
|
|
3733
|
+
context: z7.string().nullish(),
|
|
3734
|
+
description: z7.string().nullish()
|
|
3735
|
+
});
|
|
3736
|
+
var pr_raw_schema = z7.object({
|
|
3737
|
+
statusCheckRollup: z7.array(rollup_item_schema).optional(),
|
|
3738
|
+
// The base branch's required status check contexts, read from its rules — empty where none are
|
|
3739
|
+
// set or they could not be read (`git-gh-branch-rules.ts`).
|
|
3740
|
+
requiredContexts: z7.array(z7.string()).optional(),
|
|
3741
|
+
mergeStateStatus: z7.string().optional(),
|
|
3742
|
+
reviewDecision: z7.string().optional(),
|
|
3743
|
+
headRefOid: z7.string().optional()
|
|
3744
|
+
});
|
|
3745
|
+
var pull_comment_schema = z7.object({
|
|
3746
|
+
body: z7.string().optional(),
|
|
3747
|
+
html_url: z7.string().optional(),
|
|
3748
|
+
user: z7.object({ login: z7.string().optional() }).optional()
|
|
3749
|
+
});
|
|
3750
|
+
var ai_review_pull_comment_schema = z7.object({
|
|
3751
|
+
body: z7.string().optional(),
|
|
3752
|
+
url: z7.string().optional(),
|
|
3753
|
+
author: z7.object({ login: z7.string().optional() }).optional()
|
|
3754
|
+
});
|
|
3755
|
+
var pr_info_schema = z7.object({
|
|
3756
|
+
mergeable: z7.union([z7.boolean(), z7.string()]).nullable().optional(),
|
|
3757
|
+
mergeStateStatus: z7.string().nullable().optional(),
|
|
3758
|
+
state: z7.string().optional()
|
|
3759
|
+
});
|
|
3760
|
+
var epic_issue_schema = z7.object({
|
|
3761
|
+
number: z7.number(),
|
|
3762
|
+
body: z7.string().optional(),
|
|
3763
|
+
// REST answers null for an issue never closed and `reopened` for one a person reopened.
|
|
3764
|
+
stateReason: z7.string().nullish()
|
|
3765
|
+
});
|
|
3766
|
+
var blocking_issue_schema = z7.object({
|
|
3767
|
+
number: z7.number(),
|
|
3768
|
+
state: z7.string().optional(),
|
|
3769
|
+
repository_url: z7.string().optional()
|
|
3770
|
+
});
|
|
3771
|
+
var blocked_by_schema = z7.object({
|
|
3772
|
+
nodes: z7.array(blocking_issue_schema).default([]),
|
|
3773
|
+
totalCount: z7.number().optional()
|
|
3774
|
+
}).optional();
|
|
3775
|
+
var epic_child_schema = z7.object({
|
|
3776
|
+
state: z7.string().optional(),
|
|
3777
|
+
blockedBy: blocked_by_schema
|
|
3778
|
+
});
|
|
3779
|
+
var rest_comment_schema = z7.looseObject({
|
|
3780
|
+
body: z7.string().nullish(),
|
|
3781
|
+
html_url: z7.string().optional(),
|
|
3782
|
+
user: z7.looseObject({ login: z7.string().optional() }).nullish()
|
|
3783
|
+
});
|
|
3784
|
+
var issue_label_schema = z7.object({ name: z7.string() });
|
|
3785
|
+
var epic_subject_schema = z7.object({
|
|
3786
|
+
number: z7.number(),
|
|
3787
|
+
state: z7.string().optional(),
|
|
3788
|
+
labels: z7.array(issue_label_schema).optional(),
|
|
3789
|
+
body: z7.string().optional()
|
|
3790
|
+
});
|
|
3791
|
+
var open_issue_schema = z7.object({
|
|
3792
|
+
number: z7.number(),
|
|
3793
|
+
title: z7.string(),
|
|
3794
|
+
labels: z7.array(issue_label_schema).optional(),
|
|
3795
|
+
createdAt: z7.string(),
|
|
3796
|
+
blockedBy: blocked_by_schema,
|
|
3797
|
+
// Present only on the pickup listing, which reads it for the paths each issue declares.
|
|
3798
|
+
body: z7.string().optional()
|
|
3799
|
+
});
|
|
2342
3800
|
|
|
2343
3801
|
export {
|
|
2344
3802
|
json_value,
|
|
2345
|
-
|
|
2346
|
-
LANE_SEAT_KEY,
|
|
2347
|
-
ENV_FILE_NAME,
|
|
2348
|
-
ports,
|
|
3803
|
+
file_reader,
|
|
2349
3804
|
process_identity,
|
|
2350
3805
|
process_owner_schema,
|
|
3806
|
+
issue_number_shape,
|
|
3807
|
+
lane_paths,
|
|
3808
|
+
stamped_memo,
|
|
2351
3809
|
PORCELAIN_FLAG,
|
|
2352
3810
|
UNTRACKED_FILES_FLAG,
|
|
2353
|
-
|
|
3811
|
+
get_exit_code,
|
|
2354
3812
|
has_timed_out,
|
|
2355
3813
|
git_spawn,
|
|
2356
3814
|
git_diff_reads,
|
|
2357
3815
|
GIT_LOCATION_VARIABLES,
|
|
2358
|
-
git_location_environment,
|
|
2359
3816
|
git_spawn_sync,
|
|
2360
3817
|
git_command,
|
|
2361
3818
|
cli_flags,
|
|
2362
|
-
backlog_budget,
|
|
2363
|
-
issue_number_shape,
|
|
2364
3819
|
run_invocation,
|
|
2365
|
-
lane_paths,
|
|
2366
|
-
file_reader,
|
|
2367
3820
|
time_instant,
|
|
2368
3821
|
cost_usage,
|
|
2369
3822
|
cost_transcript,
|
|
2370
3823
|
agent_session_environment,
|
|
2371
3824
|
own_session,
|
|
2372
|
-
run_carry
|
|
3825
|
+
run_carry,
|
|
3826
|
+
PORT_SEED_KEY,
|
|
3827
|
+
LANE_SEAT_KEY,
|
|
3828
|
+
ENV_FILE_NAME,
|
|
3829
|
+
ports,
|
|
3830
|
+
figure_format,
|
|
3831
|
+
pr_raw_schema,
|
|
3832
|
+
epic_issue_schema,
|
|
3833
|
+
blocking_issue_schema,
|
|
3834
|
+
blocked_by_schema,
|
|
3835
|
+
rest_comment_schema,
|
|
3836
|
+
issue_label_schema,
|
|
3837
|
+
open_issue_schema,
|
|
3838
|
+
issue_cite,
|
|
3839
|
+
git_common_directory,
|
|
3840
|
+
repository_lock,
|
|
3841
|
+
run_ship_stage,
|
|
3842
|
+
run_event_stream,
|
|
3843
|
+
repo_origin,
|
|
3844
|
+
repo_map_logic,
|
|
3845
|
+
repo_discovery,
|
|
3846
|
+
issue_citation,
|
|
3847
|
+
session_cite,
|
|
3848
|
+
lane_state,
|
|
3849
|
+
run_event_scope,
|
|
3850
|
+
run_event_stream_emit,
|
|
3851
|
+
ancestor_directories,
|
|
3852
|
+
PACKAGE_JSON,
|
|
3853
|
+
package_manifest
|
|
2373
3854
|
};
|