@joshuafolkken/kit 1.1035.0 → 1.1094.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/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +21 -13
- package/.claude/skills/workflow-commands/background-commands.md +5 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
- package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +6 -4
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +3 -3
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- package/.claude/skills/workflow-commands/issue-comments.md +2 -2
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +44 -89
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +24 -4
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +42 -48
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
- package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
- package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
- package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
- package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
- package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +188 -509
- package/dist/josh.js +166 -225
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +412 -64
- package/eslint/rules/promise.js +5 -0
- package/package.json +13 -8
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +4 -4
- package/prompts/collaboration-workflow/rule-delivery.md +5 -36
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +36 -36
- package/prompts/collaboration-workflow.md +5 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +12 -4
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +2 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +15 -25
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +32 -22
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +6 -8
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +34 -17
- package/scripts/backlog/backlog-rank.ts +106 -0
- package/scripts/backlog/backlog-ready.ts +19 -3
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +47 -31
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +92 -11
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +0 -3
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +11 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +8 -9
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +13 -4
- package/scripts/document/lane-child-read-set.ts +1 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +5 -4
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +20 -30
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +37 -0
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +32 -30
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-command.ts +1 -1
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-execa-error.ts +6 -1
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +24 -6
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +4 -2
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +4 -9
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +36 -19
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +8 -2
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +52 -25
- package/scripts/init/start-steps.ts +42 -9
- package/scripts/init/start.ts +40 -10
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +37 -8
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +19 -3
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +2 -2
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +20 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/issue/issue-rank.ts +89 -0
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -102
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +10 -3
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +7 -1
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +33 -18
- package/scripts/lane/lane-close.ts +1 -3
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +21 -11
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/lane-report.ts +10 -4
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/lines-command.ts +0 -1
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +0 -2
- package/scripts/propagate/propagate-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -3
- package/scripts/propagate/propagate-steps.ts +19 -6
- package/scripts/propagate/propagate-targets.ts +13 -6
- package/scripts/propagate/propagate.ts +60 -46
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +1 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +48 -16
- package/scripts/review/review-brief-cli.ts +72 -8
- package/scripts/review/review-brief.ts +67 -9
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +1 -1
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +6 -2
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +1 -2
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +14 -8
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +13 -5
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +24 -8
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +143 -0
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +3 -3
- package/scripts/run/run-progress.ts +22 -10
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +27 -77
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +87 -0
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +23 -30
- package/scripts/run/run-ship-review.ts +20 -0
- package/scripts/run/run-ship-scoped.ts +45 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -5
- package/scripts/run/run-wake-describe.ts +19 -1
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +2 -3
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +97 -0
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-commands.ts +5 -4
- package/scripts/version/version-remote.ts +28 -14
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker,
|
|
3
3
|
run_issue_number
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-E54KGFEQ.js";
|
|
5
5
|
import {
|
|
6
6
|
PLATFORM_TEMP_ROOT,
|
|
7
7
|
cost_blocks,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
time_density_hook,
|
|
14
14
|
time_shell,
|
|
15
15
|
time_transcript_line
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-NKOG3XAV.js";
|
|
17
17
|
import {
|
|
18
18
|
ENV_FILE_NAME,
|
|
19
19
|
LANE_SEAT_KEY,
|
|
@@ -32,7 +32,6 @@ function is_josh_command(segment, names) {
|
|
|
32
32
|
return names.has(named.slice(time_shell.JOSH_PREFIX.length));
|
|
33
33
|
}
|
|
34
34
|
var shell_segments = {
|
|
35
|
-
SEGMENT_SEPARATOR,
|
|
36
35
|
is_josh_command,
|
|
37
36
|
segments_of
|
|
38
37
|
};
|
|
@@ -69,7 +68,7 @@ function bash_commands_of(line) {
|
|
|
69
68
|
function prior_bash_commands(tail) {
|
|
70
69
|
return tail.split("\n").flatMap((line) => bash_commands_of(line));
|
|
71
70
|
}
|
|
72
|
-
var tail_commands = {
|
|
71
|
+
var tail_commands = { is_bash_use, prior_bash_commands };
|
|
73
72
|
|
|
74
73
|
// scripts/rules/filing-cap.ts
|
|
75
74
|
var FILING_CAP = 10;
|
|
@@ -123,8 +122,6 @@ var filing_cap = {
|
|
|
123
122
|
FILING_CAP,
|
|
124
123
|
FILING_CAP_REASON,
|
|
125
124
|
ROW,
|
|
126
|
-
current_turn,
|
|
127
|
-
decide,
|
|
128
125
|
is_prompt_line,
|
|
129
126
|
prior_filing_count,
|
|
130
127
|
turn_filing_count
|
|
@@ -153,7 +150,7 @@ var git_utilities = {
|
|
|
153
150
|
};
|
|
154
151
|
|
|
155
152
|
// scripts/git/git-push-transport.ts
|
|
156
|
-
import { execa } from "execa";
|
|
153
|
+
import { execa as execa2 } from "execa";
|
|
157
154
|
|
|
158
155
|
// scripts/git/git-execa-error.ts
|
|
159
156
|
function get_exit_code(error) {
|
|
@@ -166,25 +163,20 @@ function has_timed_out(error) {
|
|
|
166
163
|
if (typeof error !== "object" || error === null || !("timedOut" in error)) return false;
|
|
167
164
|
return error.timedOut === true;
|
|
168
165
|
}
|
|
166
|
+
var TIMEOUT_EXIT_CODE = "timeout";
|
|
169
167
|
function create_spawn_error(command, exit_code) {
|
|
170
168
|
const exit_code_string = exit_code === void 0 ? "unknown" : String(exit_code);
|
|
171
169
|
const error_message = `git ${command} exited with code ${exit_code_string}`;
|
|
172
170
|
return new Error(error_message, { cause: { exit_code: exit_code_string } });
|
|
173
171
|
}
|
|
174
172
|
|
|
175
|
-
// scripts/git/git-
|
|
176
|
-
|
|
177
|
-
var PUSH_TIMEOUT_SECONDS = 120;
|
|
178
|
-
var PUSH_TIMEOUT_MS = PUSH_TIMEOUT_SECONDS * MS_PER_SECOND;
|
|
179
|
-
var PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`;
|
|
180
|
-
var PUSH_TIMEOUT_MESSAGE = "git push timed out";
|
|
181
|
-
var PUSH_TIMEOUT_EXIT_CODE = "timeout";
|
|
173
|
+
// scripts/git/git-ssh-keepalive.ts
|
|
174
|
+
import { execa } from "execa";
|
|
182
175
|
var SSH_KEEPALIVE_OPTIONS = "-o ServerAliveInterval=15 -o ServerAliveCountMax=3";
|
|
183
176
|
var SSH_COMMAND_VARIABLE = "GIT_SSH_COMMAND";
|
|
184
177
|
var SSH_LEGACY_VARIABLE = "GIT_SSH";
|
|
185
178
|
var KEEPALIVE_SSH_COMMAND = `ssh ${SSH_KEEPALIVE_OPTIONS}`;
|
|
186
179
|
var SSH_COMMAND_CONFIG_KEY = "core.sshCommand";
|
|
187
|
-
var PUSH_SUBCOMMAND = "push";
|
|
188
180
|
function to_environment_value(name) {
|
|
189
181
|
return process.env[name]?.trim() ?? "";
|
|
190
182
|
}
|
|
@@ -202,19 +194,33 @@ async function has_configured_ssh_command() {
|
|
|
202
194
|
return false;
|
|
203
195
|
}
|
|
204
196
|
}
|
|
205
|
-
async function
|
|
197
|
+
async function to_environment() {
|
|
206
198
|
const should_keep_alive = !await has_configured_ssh_command();
|
|
199
|
+
return should_keep_alive ? { [SSH_COMMAND_VARIABLE]: KEEPALIVE_SSH_COMMAND } : {};
|
|
200
|
+
}
|
|
201
|
+
var git_ssh_keepalive = {
|
|
202
|
+
to_environment
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// scripts/git/git-push-transport.ts
|
|
206
|
+
var MS_PER_SECOND = 1e3;
|
|
207
|
+
var PUSH_TIMEOUT_SECONDS = 120;
|
|
208
|
+
var PUSH_TIMEOUT_MS = PUSH_TIMEOUT_SECONDS * MS_PER_SECOND;
|
|
209
|
+
var PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`;
|
|
210
|
+
var PUSH_TIMEOUT_MESSAGE = "git push timed out";
|
|
211
|
+
var PUSH_SUBCOMMAND = "push";
|
|
212
|
+
async function to_push_options() {
|
|
207
213
|
return {
|
|
208
214
|
stdio: "inherit",
|
|
209
215
|
timeout: PUSH_TIMEOUT_MS,
|
|
210
|
-
env:
|
|
216
|
+
env: await git_ssh_keepalive.to_environment()
|
|
211
217
|
};
|
|
212
218
|
}
|
|
213
219
|
async function did_push_time_out(arguments_list) {
|
|
214
220
|
const git_command_bin = git_utilities.get_git_command_for_spawn();
|
|
215
221
|
const options = await to_push_options();
|
|
216
222
|
try {
|
|
217
|
-
await
|
|
223
|
+
await execa2(git_command_bin, [PUSH_SUBCOMMAND, ...arguments_list], options);
|
|
218
224
|
return false;
|
|
219
225
|
} catch (error) {
|
|
220
226
|
if (has_timed_out(error)) return true;
|
|
@@ -229,7 +235,7 @@ function to_retry_notice(arguments_list) {
|
|
|
229
235
|
}
|
|
230
236
|
function create_timeout_error(arguments_list) {
|
|
231
237
|
const message = `${PUSH_TIMEOUT_MESSAGE} twice (${PUSH_TIMEOUT_LABEL} each). Re-run it by hand: ${to_manual_command(arguments_list)}`;
|
|
232
|
-
return new Error(message, { cause: { exit_code:
|
|
238
|
+
return new Error(message, { cause: { exit_code: TIMEOUT_EXIT_CODE } });
|
|
233
239
|
}
|
|
234
240
|
async function push(arguments_list) {
|
|
235
241
|
if (!await did_push_time_out(arguments_list)) return;
|
|
@@ -242,23 +248,56 @@ var git_push_transport = {
|
|
|
242
248
|
};
|
|
243
249
|
|
|
244
250
|
// scripts/git/git-spawn.ts
|
|
245
|
-
import { execa as
|
|
251
|
+
import { execa as execa3 } from "execa";
|
|
246
252
|
async function read(arguments_) {
|
|
247
253
|
const git_cmd = git_utilities.get_git_command_for_spawn();
|
|
248
|
-
const { stdout } = await
|
|
254
|
+
const { stdout } = await execa3(git_cmd, arguments_);
|
|
249
255
|
return stdout.trimEnd();
|
|
250
256
|
}
|
|
257
|
+
var REMOTE_TIMEOUT_MS = PUSH_TIMEOUT_MS;
|
|
258
|
+
var MS_PER_SECOND2 = 1e3;
|
|
259
|
+
function to_remote_error(command, error, timeout_ms) {
|
|
260
|
+
if (!has_timed_out(error)) return create_spawn_error(command, get_exit_code(error));
|
|
261
|
+
const seconds = String(Math.round(timeout_ms / MS_PER_SECOND2));
|
|
262
|
+
return new Error(`git ${command} timed out after ${seconds}s`, {
|
|
263
|
+
cause: { exit_code: TIMEOUT_EXIT_CODE }
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async function spawn_remote(arguments_, options) {
|
|
267
|
+
const git_cmd = git_utilities.get_git_command_for_spawn();
|
|
268
|
+
try {
|
|
269
|
+
const { stdout } = await execa3(git_cmd, arguments_, options);
|
|
270
|
+
return typeof stdout === "string" ? stdout.trimEnd() : "";
|
|
271
|
+
} catch (error) {
|
|
272
|
+
throw to_remote_error(arguments_[0] ?? "", error, options.timeout);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async function read_remote(arguments_, timeout_ms = REMOTE_TIMEOUT_MS) {
|
|
276
|
+
return await spawn_remote(arguments_, {
|
|
277
|
+
timeout: timeout_ms,
|
|
278
|
+
env: await git_ssh_keepalive.to_environment()
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async function with_output_remote(command, arguments_list) {
|
|
282
|
+
await spawn_remote([command, ...arguments_list], {
|
|
283
|
+
stdio: "inherit",
|
|
284
|
+
timeout: REMOTE_TIMEOUT_MS,
|
|
285
|
+
env: await git_ssh_keepalive.to_environment()
|
|
286
|
+
});
|
|
287
|
+
}
|
|
251
288
|
async function with_output(command, arguments_list) {
|
|
252
289
|
const git_command_bin = git_utilities.get_git_command_for_spawn();
|
|
253
290
|
try {
|
|
254
|
-
await
|
|
291
|
+
await execa3(git_command_bin, [command, ...arguments_list], { stdio: "inherit" });
|
|
255
292
|
} catch (error) {
|
|
256
293
|
throw create_spawn_error(command, get_exit_code(error));
|
|
257
294
|
}
|
|
258
295
|
}
|
|
259
296
|
var git_spawn = {
|
|
260
297
|
read,
|
|
261
|
-
|
|
298
|
+
read_remote,
|
|
299
|
+
with_output,
|
|
300
|
+
with_output_remote
|
|
262
301
|
};
|
|
263
302
|
|
|
264
303
|
// scripts/git/git-command.ts
|
|
@@ -433,7 +472,7 @@ async function push2() {
|
|
|
433
472
|
}
|
|
434
473
|
}
|
|
435
474
|
async function pull_fast_forward() {
|
|
436
|
-
await git_spawn.
|
|
475
|
+
await git_spawn.with_output_remote("pull", ["--ff-only"]);
|
|
437
476
|
}
|
|
438
477
|
var SHORT_NAME_FORMAT = "--format=%(refname:short)";
|
|
439
478
|
var REMOTES_FLAG = "--remotes";
|
|
@@ -559,19 +598,20 @@ function hold_path(git_directory) {
|
|
|
559
598
|
return stamp_file.stamp_path(HOLD_PREFIX, git_directory);
|
|
560
599
|
}
|
|
561
600
|
async function worktree_directory() {
|
|
562
|
-
const
|
|
563
|
-
return
|
|
601
|
+
const directories2 = await git_command.git_directories();
|
|
602
|
+
return directories2[0];
|
|
564
603
|
}
|
|
565
604
|
async function is_linked_worktree() {
|
|
566
|
-
const
|
|
567
|
-
return
|
|
605
|
+
const directories2 = await git_command.git_directories();
|
|
606
|
+
return directories2[0] !== void 0 && directories2[0] !== directories2[1];
|
|
568
607
|
}
|
|
569
608
|
var run_hold_schema = z.object({
|
|
570
609
|
issue: z.string(),
|
|
571
610
|
taken_at: z.string(),
|
|
572
611
|
pid: z.number(),
|
|
573
612
|
is_fullrun: z.boolean().optional(),
|
|
574
|
-
is_halfrun_stop: z.boolean().optional()
|
|
613
|
+
is_halfrun_stop: z.boolean().optional(),
|
|
614
|
+
prrun_stop_head: z.string().optional()
|
|
575
615
|
});
|
|
576
616
|
function parse_hold(raw) {
|
|
577
617
|
try {
|
|
@@ -606,8 +646,12 @@ function write_hold(target, issue, now = /* @__PURE__ */ new Date()) {
|
|
|
606
646
|
function create_hold(target, issue, now = /* @__PURE__ */ new Date(), is_fullrun) {
|
|
607
647
|
return stamp_file.create_stamp(target, build_hold(issue, now, is_fullrun));
|
|
608
648
|
}
|
|
649
|
+
var HALFRUN_STOP_FIELDS = { is_halfrun_stop: true };
|
|
650
|
+
function create_stop_hold(target, issue, mark, now = /* @__PURE__ */ new Date()) {
|
|
651
|
+
return stamp_file.create_stamp(target, { ...build_hold(issue, now), ...mark });
|
|
652
|
+
}
|
|
609
653
|
function create_halfrun_stop_hold(target, issue, now = /* @__PURE__ */ new Date()) {
|
|
610
|
-
return
|
|
654
|
+
return create_stop_hold(target, issue, HALFRUN_STOP_FIELDS, now);
|
|
611
655
|
}
|
|
612
656
|
async function is_tree_dirty(directory) {
|
|
613
657
|
try {
|
|
@@ -663,8 +707,9 @@ var run_hold = {
|
|
|
663
707
|
UNNUMBERED_ISSUE,
|
|
664
708
|
classify,
|
|
665
709
|
create_halfrun_stop_hold,
|
|
710
|
+
create_stop_hold,
|
|
711
|
+
HALFRUN_STOP_FIELDS,
|
|
666
712
|
create_hold,
|
|
667
|
-
describe_holder,
|
|
668
713
|
foreign_release_message,
|
|
669
714
|
forced_release_message,
|
|
670
715
|
held_message,
|
|
@@ -673,7 +718,6 @@ var run_hold = {
|
|
|
673
718
|
is_own_hold,
|
|
674
719
|
is_tree_dirty,
|
|
675
720
|
own_release_command,
|
|
676
|
-
parse_hold,
|
|
677
721
|
race_message,
|
|
678
722
|
read_hold,
|
|
679
723
|
release_hold,
|
|
@@ -685,9 +729,6 @@ var run_hold = {
|
|
|
685
729
|
write_hold
|
|
686
730
|
};
|
|
687
731
|
|
|
688
|
-
// scripts/run/run-cut.ts
|
|
689
|
-
import { execFileSync } from "node:child_process";
|
|
690
|
-
|
|
691
732
|
// scripts/josh/agent-session-environment.ts
|
|
692
733
|
var SESSION_ID_KEY = "CLAUDE_CODE_SESSION_ID";
|
|
693
734
|
var PARENT_SESSION_KEYS = [
|
|
@@ -732,13 +773,13 @@ function is_declared(value) {
|
|
|
732
773
|
return value !== void 0 && value !== NO_HOST;
|
|
733
774
|
}
|
|
734
775
|
function loopback_proxy_keys(source, is_removed = is_loopback_proxy) {
|
|
735
|
-
const declared = PROXY_KEYS.filter((
|
|
736
|
-
const matched = declared.filter((
|
|
776
|
+
const declared = PROXY_KEYS.filter((key2) => is_declared(source[key2]));
|
|
777
|
+
const matched = declared.filter((key2) => is_removed(source[key2]));
|
|
737
778
|
const is_certificate_included = matched.length > 0 && matched.length === declared.length;
|
|
738
779
|
return is_certificate_included ? [...matched, PROXY_CERTIFICATE_KEY] : matched;
|
|
739
780
|
}
|
|
740
781
|
function to_removed(keys) {
|
|
741
|
-
return Object.fromEntries(keys.map((
|
|
782
|
+
return Object.fromEntries(keys.map((key2) => [key2, void 0]));
|
|
742
783
|
}
|
|
743
784
|
function removed_environment(source = process.env) {
|
|
744
785
|
return to_removed([...PARENT_SESSION_KEYS, ...loopback_proxy_keys(source)]);
|
|
@@ -840,55 +881,55 @@ function trimmed(value) {
|
|
|
840
881
|
const result = value?.trim();
|
|
841
882
|
return result === void 0 || result.length === EMPTY_LENGTH ? void 0 : result;
|
|
842
883
|
}
|
|
843
|
-
function override_value(role, field,
|
|
844
|
-
const
|
|
845
|
-
const value = trimmed(
|
|
846
|
-
if (value !== void 0) return { key, value };
|
|
847
|
-
if (role !== WORKER) return { key, value: void 0 };
|
|
884
|
+
function override_value(role, field, environment2) {
|
|
885
|
+
const key2 = ENV_KEYS[role][field];
|
|
886
|
+
const value = trimmed(environment2[key2]);
|
|
887
|
+
if (value !== void 0) return { key: key2, value };
|
|
888
|
+
if (role !== WORKER) return { key: key2, value: void 0 };
|
|
848
889
|
const legacy = LEGACY_WORKER_KEYS[field];
|
|
849
|
-
const legacy_value = trimmed(
|
|
850
|
-
return legacy_value === void 0 ? { key, value: void 0 } : { key: legacy, value: legacy_value };
|
|
890
|
+
const legacy_value = trimmed(environment2[legacy]);
|
|
891
|
+
return legacy_value === void 0 ? { key: key2, value: void 0 } : { key: legacy, value: legacy_value };
|
|
851
892
|
}
|
|
852
|
-
function model_override(role,
|
|
853
|
-
const
|
|
854
|
-
return provider === OPENAI_PROVIDER ? { key, value: void 0 } : override_value(role, "model",
|
|
893
|
+
function model_override(role, environment2, provider) {
|
|
894
|
+
const key2 = ENV_KEYS[role].model;
|
|
895
|
+
return provider === OPENAI_PROVIDER ? { key: key2, value: void 0 } : override_value(role, "model", environment2);
|
|
855
896
|
}
|
|
856
|
-
function rejection(
|
|
857
|
-
return { kind: "rejected", note: `${
|
|
897
|
+
function rejection(key2, value, expected) {
|
|
898
|
+
return { kind: "rejected", note: `${key2}=${value} ${expected}, so the agent was not started` };
|
|
858
899
|
}
|
|
859
900
|
function resolved_effort(override, fallback) {
|
|
860
901
|
const parsed = EFFORT_SCHEMA.safeParse(override.value ?? fallback);
|
|
861
902
|
return parsed.success ? { kind: "effort", effort: parsed.data } : rejection(override.key, override.value ?? "", "is not an allowed effort");
|
|
862
903
|
}
|
|
863
|
-
function has_session(
|
|
864
|
-
return keys.some((
|
|
904
|
+
function has_session(environment2, keys) {
|
|
905
|
+
return keys.some((key2) => trimmed(environment2[key2]) !== void 0);
|
|
865
906
|
}
|
|
866
907
|
function session_rejection(is_conflicting) {
|
|
867
908
|
const note = is_conflicting ? "both Codex and Claude Code sessions were detected" : "no Codex or Claude Code session was detected";
|
|
868
909
|
return { kind: "rejected", note };
|
|
869
910
|
}
|
|
870
911
|
var HANDED_PROVIDER_KEY = "JOSH_AGENT_PROVIDER";
|
|
871
|
-
function handed_provider(
|
|
872
|
-
const value = trimmed(
|
|
912
|
+
function handed_provider(environment2) {
|
|
913
|
+
const value = trimmed(environment2[HANDED_PROVIDER_KEY]);
|
|
873
914
|
if (value === void 0) return session_rejection(false);
|
|
874
915
|
const parsed = PROVIDER_SCHEMA.safeParse(value);
|
|
875
916
|
return parsed.success ? { kind: "provider", provider: parsed.data } : rejection(HANDED_PROVIDER_KEY, value, "is not an allowed provider");
|
|
876
917
|
}
|
|
877
|
-
function detected_provider(
|
|
878
|
-
const has_codex = has_session(
|
|
879
|
-
const has_claude = has_session(
|
|
918
|
+
function detected_provider(environment2) {
|
|
919
|
+
const has_codex = has_session(environment2, [CODEX_SESSION_KEY]);
|
|
920
|
+
const has_claude = has_session(environment2, agent_session_environment.PARENT_SESSION_KEYS);
|
|
880
921
|
if (has_codex === has_claude) return has_codex ? session_rejection(true) : void 0;
|
|
881
922
|
return { kind: "provider", provider: has_codex ? OPENAI_PROVIDER : ANTHROPIC_PROVIDER };
|
|
882
923
|
}
|
|
883
|
-
function resolve_provider(
|
|
884
|
-
return detected_provider(
|
|
924
|
+
function resolve_provider(environment2 = process.env) {
|
|
925
|
+
return detected_provider(environment2) ?? handed_provider(environment2);
|
|
885
926
|
}
|
|
886
|
-
function has_completion_callback(
|
|
887
|
-
const selected = resolve_provider(
|
|
927
|
+
function has_completion_callback(environment2 = process.env) {
|
|
928
|
+
const selected = resolve_provider(environment2);
|
|
888
929
|
return selected.kind !== "provider" || selected.provider !== OPENAI_PROVIDER;
|
|
889
930
|
}
|
|
890
|
-
function handoff_environment(
|
|
891
|
-
const selected = resolve_provider(
|
|
931
|
+
function handoff_environment(environment2 = process.env) {
|
|
932
|
+
const selected = resolve_provider(environment2);
|
|
892
933
|
return selected.kind === "provider" ? { [HANDED_PROVIDER_KEY]: selected.provider } : {};
|
|
893
934
|
}
|
|
894
935
|
function validate(profile, model_key) {
|
|
@@ -902,19 +943,19 @@ function phase_effort(role, phase, fallback) {
|
|
|
902
943
|
if (!parsed.success) return fallback;
|
|
903
944
|
return PHASE_EFFORT[role]?.[parsed.data] ?? fallback;
|
|
904
945
|
}
|
|
905
|
-
function overridden_effort(profile, phase,
|
|
906
|
-
const parsed = EFFORT_SCHEMA.safeParse(override_value(profile.role, "effort",
|
|
946
|
+
function overridden_effort(profile, phase, environment2) {
|
|
947
|
+
const parsed = EFFORT_SCHEMA.safeParse(override_value(profile.role, "effort", environment2).value);
|
|
907
948
|
return parsed.success ? parsed.data : phase_effort(profile.role, phase, profile.effort);
|
|
908
949
|
}
|
|
909
|
-
function with_phase_effort(profile, phase,
|
|
910
|
-
return { ...profile, effort: overridden_effort(profile, phase,
|
|
950
|
+
function with_phase_effort(profile, phase, environment2 = process.env) {
|
|
951
|
+
return { ...profile, effort: overridden_effort(profile, phase, environment2) };
|
|
911
952
|
}
|
|
912
|
-
function resolve(role,
|
|
913
|
-
const selected = resolve_provider(
|
|
953
|
+
function resolve(role, environment2 = process.env, phase) {
|
|
954
|
+
const selected = resolve_provider(environment2);
|
|
914
955
|
if (selected.kind === "rejected") return selected;
|
|
915
956
|
const defaults = PROVIDER_PROFILES[selected.provider][role];
|
|
916
|
-
const model = model_override(role,
|
|
917
|
-
const effort = override_value(role, "effort",
|
|
957
|
+
const model = model_override(role, environment2, selected.provider);
|
|
958
|
+
const effort = override_value(role, "effort", environment2);
|
|
918
959
|
const resolved = resolved_effort(effort, phase_effort(role, phase, defaults.effort));
|
|
919
960
|
if (resolved.kind === "rejected") return resolved;
|
|
920
961
|
const profile = {
|
|
@@ -934,17 +975,11 @@ function parse(value) {
|
|
|
934
975
|
}
|
|
935
976
|
var agent_role_profile = {
|
|
936
977
|
DEFAULT_PROFILES,
|
|
937
|
-
EFFORT_SCHEMA,
|
|
938
|
-
ENV_KEYS,
|
|
939
978
|
HANDED_PROVIDER_KEY,
|
|
940
979
|
IMPLEMENTATION_PHASE,
|
|
941
|
-
LEGACY_WORKER_KEYS,
|
|
942
980
|
MAX_VALUE_LENGTH,
|
|
943
981
|
OPENAI_PROFILES,
|
|
944
|
-
PHASE_EFFORT,
|
|
945
|
-
PHASE_SCHEMA,
|
|
946
982
|
PRE_GATE_PHASE,
|
|
947
|
-
PROVIDER_SCHEMA,
|
|
948
983
|
PROFILE_SCHEMA,
|
|
949
984
|
REVIEWER,
|
|
950
985
|
SCHEDULER,
|
|
@@ -954,7 +989,6 @@ var agent_role_profile = {
|
|
|
954
989
|
has_completion_callback,
|
|
955
990
|
is_safe_value,
|
|
956
991
|
parse,
|
|
957
|
-
phase_effort,
|
|
958
992
|
resolve,
|
|
959
993
|
resolve_provider,
|
|
960
994
|
with_phase_effort
|
|
@@ -1061,7 +1095,6 @@ function decide2(input) {
|
|
|
1061
1095
|
}
|
|
1062
1096
|
var backlog_budget = {
|
|
1063
1097
|
ANSWERS,
|
|
1064
|
-
ANSWER_STOP_REASONS,
|
|
1065
1098
|
BLOCKED_REASON,
|
|
1066
1099
|
DEFAULT_IDLE_MINUTES,
|
|
1067
1100
|
DEFAULT_IDLE_MS,
|
|
@@ -1076,7 +1109,6 @@ var backlog_budget = {
|
|
|
1076
1109
|
UNREADABLE_REASON,
|
|
1077
1110
|
WATCH_VERDICT,
|
|
1078
1111
|
WHOLE_RUN_BUDGET_HOURS,
|
|
1079
|
-
WHOLE_RUN_BUDGET_MINUTES,
|
|
1080
1112
|
WHOLE_RUN_BUDGET_MS,
|
|
1081
1113
|
WHOLE_RUN_REASON,
|
|
1082
1114
|
decide: decide2,
|
|
@@ -1162,7 +1194,6 @@ var cost_pricing = {
|
|
|
1162
1194
|
CACHE_WRITE_5M_MULTIPLIER,
|
|
1163
1195
|
CACHE_WRITE_1H_MULTIPLIER,
|
|
1164
1196
|
CACHE_READ_MULTIPLIER,
|
|
1165
|
-
MODEL_PRICES,
|
|
1166
1197
|
resolve_price,
|
|
1167
1198
|
estimate_cost,
|
|
1168
1199
|
estimate_composition,
|
|
@@ -1201,6 +1232,9 @@ var context_cut_payback = {
|
|
|
1201
1232
|
var CONTEXT_CUT_THRESHOLD = context_cut_payback.break_even_context();
|
|
1202
1233
|
var RECENT_REQUEST_WINDOW = 10;
|
|
1203
1234
|
|
|
1235
|
+
// scripts/git/git-common-directory.ts
|
|
1236
|
+
import { execFileSync } from "node:child_process";
|
|
1237
|
+
|
|
1204
1238
|
// scripts/git/git-location-environment.ts
|
|
1205
1239
|
var GIT_LOCATION_VARIABLES = [
|
|
1206
1240
|
"GIT_ALTERNATE_OBJECT_DIRECTORIES",
|
|
@@ -1230,6 +1264,197 @@ function clear_git_location_variables() {
|
|
|
1230
1264
|
}
|
|
1231
1265
|
var git_location_environment = { clear_git_location_variables, location_free_environment };
|
|
1232
1266
|
|
|
1267
|
+
// scripts/git/git-common-directory.ts
|
|
1268
|
+
var OWN_GIT_DIRECTORY = 0;
|
|
1269
|
+
var COMMON_GIT_DIRECTORY = 1;
|
|
1270
|
+
var PROBE_TIMEOUT_MS = 5e3;
|
|
1271
|
+
var answers = /* @__PURE__ */ new Map();
|
|
1272
|
+
function probe_environment(cwd) {
|
|
1273
|
+
if (cwd === void 0) return process.env;
|
|
1274
|
+
return { ...process.env, ...git_location_environment.location_free_environment() };
|
|
1275
|
+
}
|
|
1276
|
+
function cache_key(cwd) {
|
|
1277
|
+
if (cwd !== void 0) return `explicit\0${cwd}`;
|
|
1278
|
+
const locations = GIT_LOCATION_VARIABLES.map((name) => process.env[name] ?? "");
|
|
1279
|
+
return ["inherited", process.cwd(), ...locations].join("\0");
|
|
1280
|
+
}
|
|
1281
|
+
function read_directories(cwd) {
|
|
1282
|
+
try {
|
|
1283
|
+
const output = execFileSync(
|
|
1284
|
+
git_utilities.get_git_command_for_spawn(),
|
|
1285
|
+
[...git_command.GIT_DIRECTORY_ARGUMENTS],
|
|
1286
|
+
{
|
|
1287
|
+
cwd,
|
|
1288
|
+
env: probe_environment(cwd),
|
|
1289
|
+
encoding: "utf8",
|
|
1290
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
1291
|
+
timeout: PROBE_TIMEOUT_MS
|
|
1292
|
+
}
|
|
1293
|
+
);
|
|
1294
|
+
return output.split("\n").filter((line) => line !== "");
|
|
1295
|
+
} catch {
|
|
1296
|
+
return [];
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
function directories(cwd) {
|
|
1300
|
+
const key2 = cache_key(cwd);
|
|
1301
|
+
const known = answers.get(key2);
|
|
1302
|
+
if (known !== void 0) return known;
|
|
1303
|
+
const read2 = read_directories(cwd);
|
|
1304
|
+
if (read2.length > 0) answers.set(key2, read2);
|
|
1305
|
+
return read2;
|
|
1306
|
+
}
|
|
1307
|
+
function own(cwd) {
|
|
1308
|
+
return directories(cwd)[OWN_GIT_DIRECTORY];
|
|
1309
|
+
}
|
|
1310
|
+
function repository(cwd) {
|
|
1311
|
+
return directories(cwd)[COMMON_GIT_DIRECTORY];
|
|
1312
|
+
}
|
|
1313
|
+
function select_linked(found) {
|
|
1314
|
+
const own_directory = found[OWN_GIT_DIRECTORY];
|
|
1315
|
+
const common = found[COMMON_GIT_DIRECTORY];
|
|
1316
|
+
return own_directory !== void 0 && common !== void 0 && own_directory !== common ? common : void 0;
|
|
1317
|
+
}
|
|
1318
|
+
function resolve2(cwd) {
|
|
1319
|
+
return select_linked(directories(cwd));
|
|
1320
|
+
}
|
|
1321
|
+
var git_common_directory = { directories, own, repository, resolve: resolve2, select_linked };
|
|
1322
|
+
|
|
1323
|
+
// scripts/run/run-ship-stage.ts
|
|
1324
|
+
import { z as z3 } from "zod";
|
|
1325
|
+
var STAGE = {
|
|
1326
|
+
PREFLIGHT: "preflight",
|
|
1327
|
+
REVIEW: "review",
|
|
1328
|
+
GATE: "gate",
|
|
1329
|
+
COMMIT: "commit",
|
|
1330
|
+
ROUND_TWO: "round-2",
|
|
1331
|
+
FOLLOWUP: "followup",
|
|
1332
|
+
REPORT: "report"
|
|
1333
|
+
};
|
|
1334
|
+
var PHASE = {
|
|
1335
|
+
START: "start",
|
|
1336
|
+
DONE: "done",
|
|
1337
|
+
FAILED: "failed",
|
|
1338
|
+
SKIPPED: "skipped"
|
|
1339
|
+
};
|
|
1340
|
+
var RECORD_PREFIX = "josh-ship-stages-";
|
|
1341
|
+
var RECORD_SEPARATOR = "-";
|
|
1342
|
+
var SKIP_COMMIT_FLAG = "--skip-commit";
|
|
1343
|
+
var SKIP_PUSH_FLAG = "--skip-push";
|
|
1344
|
+
var record_schema = z3.object({ done: z3.array(z3.string()) });
|
|
1345
|
+
function record_path(repository2, issue) {
|
|
1346
|
+
return stamp_file.stamp_path(`${RECORD_PREFIX}${issue}${RECORD_SEPARATOR}`, repository2);
|
|
1347
|
+
}
|
|
1348
|
+
function parse_done(raw) {
|
|
1349
|
+
try {
|
|
1350
|
+
return new Set(record_schema.parse(JSON.parse(raw)).done);
|
|
1351
|
+
} catch {
|
|
1352
|
+
return /* @__PURE__ */ new Set();
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
function read_done(target) {
|
|
1356
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
1357
|
+
return raw === void 0 ? /* @__PURE__ */ new Set() : parse_done(raw);
|
|
1358
|
+
}
|
|
1359
|
+
function mark_done(target, stage) {
|
|
1360
|
+
const done = /* @__PURE__ */ new Set([...read_done(target), stage]);
|
|
1361
|
+
stamp_file.replace_stamp(target, { done: [...done] });
|
|
1362
|
+
}
|
|
1363
|
+
function clear(target) {
|
|
1364
|
+
stamp_file.remove_stamp(target);
|
|
1365
|
+
}
|
|
1366
|
+
function is_shipped(state) {
|
|
1367
|
+
return state.is_committed && state.is_pushed;
|
|
1368
|
+
}
|
|
1369
|
+
var DONE_BY = {
|
|
1370
|
+
// The preflight (joshuafolkken/kit#2946) asks what the commit stage would refuse on, so a commit is
|
|
1371
|
+
// its output as it is the gate's; a resumed commit stage still asks `git -y`'s own preflight.
|
|
1372
|
+
[STAGE.PREFLIGHT]: (_done, state) => state.is_merged || state.is_committed,
|
|
1373
|
+
// The `--review` round (joshuafolkken/kit#2427) precedes the commit, so a commit is its output as it
|
|
1374
|
+
// is the gate's. A record alone is not honored: before a commit the tree may have been edited since
|
|
1375
|
+
// the recorded round, and only a commit pins the tree that round read.
|
|
1376
|
+
[STAGE.REVIEW]: (_done, state) => state.is_merged || state.is_committed,
|
|
1377
|
+
[STAGE.GATE]: (_done, state) => state.is_merged || state.is_committed,
|
|
1378
|
+
[STAGE.COMMIT]: (done, state) => state.is_merged || done.has(STAGE.COMMIT) && is_shipped(state),
|
|
1379
|
+
// The round-2 pass (joshuafolkken/kit#2489) reads the pushed fix delta, so its record is honored only
|
|
1380
|
+
// while that push still stands — new work pushed on top reruns it.
|
|
1381
|
+
[STAGE.ROUND_TWO]: (done, state) => state.is_merged || done.has(STAGE.ROUND_TWO) && is_shipped(state),
|
|
1382
|
+
// A recorded followup still needs the shipped state: a record left by a merged ship whose report
|
|
1383
|
+
// failed must not pass over the followup of new, not-yet-pushed work on the same issue.
|
|
1384
|
+
[STAGE.FOLLOWUP]: (done, state) => state.is_merged || done.has(STAGE.FOLLOWUP) && is_shipped(state),
|
|
1385
|
+
[STAGE.REPORT]: (done) => done.has(STAGE.REPORT)
|
|
1386
|
+
};
|
|
1387
|
+
function is_done(stage, done, state, has_body = false) {
|
|
1388
|
+
if (has_body && stage === STAGE.COMMIT && !state.is_merged) return false;
|
|
1389
|
+
return DONE_BY[stage](done, state);
|
|
1390
|
+
}
|
|
1391
|
+
function commit_flags(state) {
|
|
1392
|
+
if (!state.is_committed) return [];
|
|
1393
|
+
return state.is_pushed ? [SKIP_COMMIT_FLAG, SKIP_PUSH_FLAG] : [SKIP_COMMIT_FLAG];
|
|
1394
|
+
}
|
|
1395
|
+
function event_text(issue, stage, phase) {
|
|
1396
|
+
return `#${issue} ${stage} ${phase}`;
|
|
1397
|
+
}
|
|
1398
|
+
var run_ship_stage = {
|
|
1399
|
+
PHASE,
|
|
1400
|
+
STAGE,
|
|
1401
|
+
clear,
|
|
1402
|
+
commit_flags,
|
|
1403
|
+
event_text,
|
|
1404
|
+
is_done,
|
|
1405
|
+
mark_done,
|
|
1406
|
+
read_done,
|
|
1407
|
+
record_path
|
|
1408
|
+
};
|
|
1409
|
+
|
|
1410
|
+
// scripts/run/run-ship-next.ts
|
|
1411
|
+
var { STAGE: STAGE2 } = run_ship_stage;
|
|
1412
|
+
var COMMAND = {
|
|
1413
|
+
LOG: "pnpm josh ship --log",
|
|
1414
|
+
DETACH: "pnpm josh ship --detach",
|
|
1415
|
+
DETACH_REVIEW: "pnpm josh ship --detach --review"
|
|
1416
|
+
};
|
|
1417
|
+
var ESCAPED_QUOTE = String.raw`'\''`;
|
|
1418
|
+
var BARE_WORD = /^[\w%+,./:=@-]+$/u;
|
|
1419
|
+
function quoted(title) {
|
|
1420
|
+
return `'${title.split("'").join(ESCAPED_QUOTE)}'`;
|
|
1421
|
+
}
|
|
1422
|
+
function shell_word(token) {
|
|
1423
|
+
return BARE_WORD.test(token) ? token : quoted(token);
|
|
1424
|
+
}
|
|
1425
|
+
function resume_of(args) {
|
|
1426
|
+
const cites = args.cites.flatMap((cite) => ["--cite", cite]);
|
|
1427
|
+
return {
|
|
1428
|
+
title: args.title,
|
|
1429
|
+
flags: [...args.notify, ...args.body, ...cites],
|
|
1430
|
+
is_review: args.is_review
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
function ship_command(command, resume) {
|
|
1434
|
+
const words = [...resume.flags, resume.title].map((token) => shell_word(token));
|
|
1435
|
+
return [command, ...words].join(" ");
|
|
1436
|
+
}
|
|
1437
|
+
function detach_again(resume) {
|
|
1438
|
+
return `leave the fix uncommitted and run \`${ship_command(COMMAND.DETACH, resume)}\`.`;
|
|
1439
|
+
}
|
|
1440
|
+
function detach_as_started(resume) {
|
|
1441
|
+
const command = resume.is_review ? COMMAND.DETACH_REVIEW : COMMAND.DETACH;
|
|
1442
|
+
return `leave the fix uncommitted and run \`${ship_command(command, resume)}\`.`;
|
|
1443
|
+
}
|
|
1444
|
+
var AFTER_FIX = {
|
|
1445
|
+
[STAGE2.PREFLIGHT]: detach_as_started,
|
|
1446
|
+
[STAGE2.REVIEW]: detach_as_started,
|
|
1447
|
+
[STAGE2.GATE]: detach_as_started,
|
|
1448
|
+
[STAGE2.COMMIT]: detach_as_started,
|
|
1449
|
+
[STAGE2.ROUND_TWO]: detach_again,
|
|
1450
|
+
[STAGE2.FOLLOWUP]: detach_again,
|
|
1451
|
+
[STAGE2.REPORT]: detach_again
|
|
1452
|
+
};
|
|
1453
|
+
function next_step(issue, stage, resume) {
|
|
1454
|
+
return `Read the stopped report with \`${COMMAND.LOG} ${issue}\`, fix the ${stage} failure, then ${AFTER_FIX[stage](resume)}`;
|
|
1455
|
+
}
|
|
1456
|
+
var run_ship_next = { COMMAND, next_step, quoted, resume_of };
|
|
1457
|
+
|
|
1233
1458
|
// scripts/lane/lane-child-invocation.ts
|
|
1234
1459
|
var CHILD_INVOCATION = "fullrun";
|
|
1235
1460
|
var RESUME_GUIDE = ".claude/skills/workflow-commands/pre-gate-cut.md";
|
|
@@ -1250,12 +1475,12 @@ function outage_resume_invocation(issue) {
|
|
|
1250
1475
|
const preamble = `Resuming the lane child for issue #${issue} after an API disconnection \u2014 your session was restored with its full context, so do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md). Continue the run from where it stopped: run \`pnpm josh run:step ${issue}\` to find the next action, redoing only the last step if it did not complete.`;
|
|
1251
1476
|
return `${preamble} ${child_invocation(issue)}`;
|
|
1252
1477
|
}
|
|
1253
|
-
function ship_stop_invocation(issue) {
|
|
1254
|
-
const
|
|
1255
|
-
|
|
1478
|
+
function ship_stop_invocation(issue, stop) {
|
|
1479
|
+
const opening = `Resuming the lane child for issue #${issue} after its detached ship supervisor stopped at a failed stage \u2014 do not re-read the workflow-commands entry documents (SKILL.md, fullrun.md).`;
|
|
1480
|
+
const next = stop === void 0 ? `Run \`pnpm josh run:step ${issue}\` and read the stopped report it names, fix what stopped the ship, then hand the region back per chain-rule.md.` : run_ship_next.next_step(issue, stop.stage, stop);
|
|
1481
|
+
return `${opening} ${next} Do not re-plan or re-implement what is already on the branch. ${child_invocation(issue)}`;
|
|
1256
1482
|
}
|
|
1257
1483
|
var lane_child_invocation = {
|
|
1258
|
-
CHILD_INVOCATION,
|
|
1259
1484
|
child_invocation,
|
|
1260
1485
|
outage_resume_invocation,
|
|
1261
1486
|
process_pattern,
|
|
@@ -1264,16 +1489,16 @@ var lane_child_invocation = {
|
|
|
1264
1489
|
};
|
|
1265
1490
|
|
|
1266
1491
|
// scripts/run/run-cut.ts
|
|
1267
|
-
import { z as
|
|
1492
|
+
import { z as z5 } from "zod";
|
|
1268
1493
|
|
|
1269
1494
|
// scripts/run/run-cut-handoff.ts
|
|
1270
1495
|
import { readFileSync } from "node:fs";
|
|
1271
|
-
import { z as
|
|
1272
|
-
var handoff_schema =
|
|
1273
|
-
instruction:
|
|
1274
|
-
completed:
|
|
1275
|
-
remaining:
|
|
1276
|
-
untouched:
|
|
1496
|
+
import { z as z4 } from "zod";
|
|
1497
|
+
var handoff_schema = z4.object({
|
|
1498
|
+
instruction: z4.string(),
|
|
1499
|
+
completed: z4.array(z4.string()),
|
|
1500
|
+
remaining: z4.array(z4.string()),
|
|
1501
|
+
untouched: z4.array(z4.string())
|
|
1277
1502
|
});
|
|
1278
1503
|
var COMPLETED_LABEL = "Completed";
|
|
1279
1504
|
var REMAINING_LABEL = "Remaining";
|
|
@@ -1312,10 +1537,10 @@ function load_handoff(handoff_path, max_bytes) {
|
|
|
1312
1537
|
}
|
|
1313
1538
|
return { kind: "ok", handoff };
|
|
1314
1539
|
}
|
|
1315
|
-
function describe_list(
|
|
1316
|
-
if (items.length === 0) return `${
|
|
1540
|
+
function describe_list(label2, items) {
|
|
1541
|
+
if (items.length === 0) return `${label2}: ${EMPTY_LIST_NOTE}`;
|
|
1317
1542
|
const bullets = items.map((item) => ` - ${item}`).join("\n");
|
|
1318
|
-
return `${
|
|
1543
|
+
return `${label2}:
|
|
1319
1544
|
${bullets}`;
|
|
1320
1545
|
}
|
|
1321
1546
|
function describe_handoff(handoff) {
|
|
@@ -1342,22 +1567,20 @@ var { PRE_GATE_PHASE: PRE_GATE_PHASE2, IMPLEMENTATION_PHASE: IMPLEMENTATION_PHAS
|
|
|
1342
1567
|
var IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD;
|
|
1343
1568
|
var CUT_MAX_AGE_MS = backlog_budget.WHOLE_RUN_BUDGET_MS;
|
|
1344
1569
|
var CUT_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS;
|
|
1345
|
-
var GIT_READ_TIMEOUT_MS = 5e3;
|
|
1346
|
-
var WORKTREE_DIRECTORY_INDEX = 0;
|
|
1347
1570
|
var END_COMMAND = "pnpm josh run:cut --end";
|
|
1348
1571
|
var READ_COMMAND = "pnpm josh run:cut --json";
|
|
1349
1572
|
var MAX_HANDOFF_BYTES = 8192;
|
|
1350
1573
|
var NONE_READ = { kind: "none" };
|
|
1351
1574
|
var UNREADABLE_READ2 = { kind: "unreadable" };
|
|
1352
|
-
var run_cut_schema =
|
|
1353
|
-
invocation:
|
|
1354
|
-
issue:
|
|
1355
|
-
branch:
|
|
1356
|
-
phase:
|
|
1357
|
-
cut_at:
|
|
1358
|
-
is_handed_off:
|
|
1575
|
+
var run_cut_schema = z5.object({
|
|
1576
|
+
invocation: z5.string(),
|
|
1577
|
+
issue: z5.string(),
|
|
1578
|
+
branch: z5.string(),
|
|
1579
|
+
phase: z5.string(),
|
|
1580
|
+
cut_at: z5.string(),
|
|
1581
|
+
is_handed_off: z5.boolean().optional(),
|
|
1359
1582
|
handoff: run_cut_handoff.handoff_schema.optional(),
|
|
1360
|
-
is_merge_relaunched:
|
|
1583
|
+
is_merge_relaunched: z5.boolean().optional()
|
|
1361
1584
|
});
|
|
1362
1585
|
function cut_path(git_directory) {
|
|
1363
1586
|
return stamp_file.stamp_path(CUT_PREFIX, git_directory);
|
|
@@ -1388,36 +1611,8 @@ function classify2(raw, now) {
|
|
|
1388
1611
|
function read_cut(target, now = /* @__PURE__ */ new Date()) {
|
|
1389
1612
|
return classify2(stamp_file.read_stamp_text(target), now);
|
|
1390
1613
|
}
|
|
1391
|
-
function git_directories_sync(cwd) {
|
|
1392
|
-
try {
|
|
1393
|
-
const output = execFileSync(
|
|
1394
|
-
git_utilities.get_git_command_for_spawn(),
|
|
1395
|
-
[...git_command.GIT_DIRECTORY_ARGUMENTS],
|
|
1396
|
-
// git's own diagnostics are discarded: a checkout it cannot describe is already the
|
|
1397
|
-
// `undefined` below, and a hook that let `fatal: not a git repository` through would print it
|
|
1398
|
-
// in front of a tool call that is about to be allowed.
|
|
1399
|
-
// A `PreToolUse` hook holds the tool call while it runs, so the read is bounded rather than
|
|
1400
|
-
// left to whatever git does.
|
|
1401
|
-
// `cwd` is set only by `lane_cut_sync`, which reads another lane's record from the parent.
|
|
1402
|
-
// With a `cwd`, the git location variables are cleared so it is what git answers for: a hook
|
|
1403
|
-
// exports `GIT_DIR`, which beats `cwd` and would name the hook's checkout instead
|
|
1404
|
-
// (joshuafolkken/kit#2515). Without one the environment is kept, so this read resolves the same
|
|
1405
|
-
// checkout as the asynchronous `git_directories` that writes the record.
|
|
1406
|
-
{
|
|
1407
|
-
cwd,
|
|
1408
|
-
env: cwd === void 0 ? process.env : { ...process.env, ...git_location_environment.location_free_environment() },
|
|
1409
|
-
encoding: "utf8",
|
|
1410
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
1411
|
-
timeout: GIT_READ_TIMEOUT_MS
|
|
1412
|
-
}
|
|
1413
|
-
);
|
|
1414
|
-
return output.split("\n").filter((line) => line !== "");
|
|
1415
|
-
} catch {
|
|
1416
|
-
return [];
|
|
1417
|
-
}
|
|
1418
|
-
}
|
|
1419
1614
|
function worktree_git_directory_sync() {
|
|
1420
|
-
return
|
|
1615
|
+
return git_common_directory.own();
|
|
1421
1616
|
}
|
|
1422
1617
|
function carried_cut_sync(now = /* @__PURE__ */ new Date(), directory = worktree_git_directory_sync()) {
|
|
1423
1618
|
if (directory === void 0) return void 0;
|
|
@@ -1425,7 +1620,7 @@ function carried_cut_sync(now = /* @__PURE__ */ new Date(), directory = worktree
|
|
|
1425
1620
|
return read2.kind === "carried" ? read2.cut : void 0;
|
|
1426
1621
|
}
|
|
1427
1622
|
function lane_cut_sync(lane_directory) {
|
|
1428
|
-
const directory =
|
|
1623
|
+
const directory = git_common_directory.own(lane_directory);
|
|
1429
1624
|
if (directory === void 0) return void 0;
|
|
1430
1625
|
const cut = carried_cut_sync(/* @__PURE__ */ new Date(), directory);
|
|
1431
1626
|
return cut === void 0 ? void 0 : { target: cut_path(directory), cut };
|
|
@@ -1616,7 +1811,7 @@ var run_tail = {
|
|
|
1616
1811
|
|
|
1617
1812
|
// scripts/rules/lane-background.ts
|
|
1618
1813
|
var LONG_RUNNING_COMMANDS = new Set(
|
|
1619
|
-
["gate", "git", "followup"].map((name) => `${time_shell.JOSH_PREFIX}${name}`)
|
|
1814
|
+
["gate", "git", "followup", "ship"].map((name) => `${time_shell.JOSH_PREFIX}${name}`)
|
|
1620
1815
|
);
|
|
1621
1816
|
var BACKGROUND_KEY2 = "run_in_background";
|
|
1622
1817
|
function is_backgrounded2(input) {
|
|
@@ -1637,8 +1832,8 @@ function unfinished_ids(tail, launched_ids) {
|
|
|
1637
1832
|
const lines = tail.split("\n").map((line) => time_transcript_line.parse_line(line));
|
|
1638
1833
|
const finished = new Set(lines.map((line) => line?.finished_background ?? ""));
|
|
1639
1834
|
const blocks = lines.flatMap((line) => line?.blocks ?? []);
|
|
1640
|
-
const
|
|
1641
|
-
return
|
|
1835
|
+
const launched2 = blocks.flatMap((block) => launched_ids(block));
|
|
1836
|
+
return launched2.filter((id) => id !== "" && !finished.has(id));
|
|
1642
1837
|
}
|
|
1643
1838
|
function pending_background_ids(tail) {
|
|
1644
1839
|
return unfinished_ids(tail, (block) => [block.background_id, block.agent_id]);
|
|
@@ -1646,7 +1841,7 @@ function pending_background_ids(tail) {
|
|
|
1646
1841
|
function pending_agent_ids(tail) {
|
|
1647
1842
|
return unfinished_ids(tail, (block) => [block.agent_id]);
|
|
1648
1843
|
}
|
|
1649
|
-
var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless `claude -p` process whose background Bash tasks are killed when the turn ends \u2014 so a backgrounded `josh gate` / `josh git` / `josh followup` never re-invokes you; it dies at `exit code 143` (joshuafolkken/kit#2704, measured on the #2606 child: implementation, review and live verification done, the run parked instead of merged). Hand the gate-to-merge region to the detached supervisor instead: `pnpm josh ship --detach --review "<title> #<N>"` (add `--cite <N>`), then end the turn on `launched` / `busy
|
|
1844
|
+
var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless `claude -p` process whose background Bash tasks are killed when the turn ends \u2014 so a backgrounded `josh gate` / `josh git` / `josh followup` / `josh ship` never re-invokes you; it dies at `exit code 143` (joshuafolkken/kit#2704, measured on the #2606 child: implementation, review and live verification done, the run parked instead of merged). Hand the gate-to-merge region to the detached supervisor instead: `pnpm josh ship --detach --review "<title> #<N>"` (add `--cite <N>`) issued in the foreground \u2014 its preflight runs in this process before the supervisor exists, so a backgrounded `ship` dies with the turn (joshuafolkken/kit#3027) \u2014 then end the turn on `launched` / `busy`. `.claude/skills/workflow-commands/chain-rule.md` step 0 is the single source. A single check you must read before continuing runs in the foreground within the tool timeout; the commit-push step does not \u2014 in a child it too belongs to the detached ship, in either spelling. This rule fires on every occurrence, not once per run.';
|
|
1650
1845
|
var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished \u2014 ending this headless turn kills it, and nothing re-invokes you afterwards (joshuafolkken/kit#2704). Do not send a notification and do not stop: wait for the task in the foreground and act on its result, or re-issue the work through `pnpm josh ship --detach`, whose supervisor outlives the turn (`.claude/skills/workflow-commands/chain-rule.md` step 0). Do not repeat your previous reply.";
|
|
1651
1846
|
var ROW2 = {
|
|
1652
1847
|
id: "lane-background",
|
|
@@ -1663,1713 +1858,2427 @@ var lane_background = {
|
|
|
1663
1858
|
pending_background_ids
|
|
1664
1859
|
};
|
|
1665
1860
|
|
|
1666
|
-
// scripts/
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
var
|
|
1673
|
-
var
|
|
1674
|
-
var
|
|
1675
|
-
var
|
|
1676
|
-
var
|
|
1677
|
-
var
|
|
1678
|
-
var
|
|
1679
|
-
var
|
|
1680
|
-
var
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
{
|
|
1696
|
-
|
|
1697
|
-
color: "0e8a16",
|
|
1698
|
-
description: "A child issue created by a split (split-assessment.md)"
|
|
1699
|
-
},
|
|
1700
|
-
{
|
|
1701
|
-
name: TIER_A_ROUTE_LABEL,
|
|
1702
|
-
color: "d93f0b",
|
|
1703
|
-
description: "Filed Tier A during implementation \u2014 an upstream defect or a prerequisite"
|
|
1704
|
-
}
|
|
1705
|
-
];
|
|
1706
|
-
var DEPTH_0_LABEL = "depth:0";
|
|
1707
|
-
var DEPTH_1_LABEL = "depth:1";
|
|
1708
|
-
var DEPTH_2_LABEL = "depth:2";
|
|
1709
|
-
var DEPTH_LABELS = [
|
|
1710
|
-
{
|
|
1711
|
-
name: DEPTH_0_LABEL,
|
|
1712
|
-
color: "0e8a16",
|
|
1713
|
-
description: "Depth 0 \u2014 what a consumer of this package touches (SKILL.md \xA72i)"
|
|
1714
|
-
},
|
|
1715
|
-
{
|
|
1716
|
-
name: DEPTH_1_LABEL,
|
|
1717
|
-
color: "fbc02d",
|
|
1718
|
-
description: "Depth 1 \u2014 the run orchestration that executes an Issue (SKILL.md \xA72i)"
|
|
1719
|
-
},
|
|
1720
|
-
{
|
|
1721
|
-
name: DEPTH_2_LABEL,
|
|
1722
|
-
color: "c5def5",
|
|
1723
|
-
description: "Depth 2 \u2014 what measures a run (SKILL.md \xA72i)"
|
|
1861
|
+
// scripts/josh/process-identity.ts
|
|
1862
|
+
import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
|
|
1863
|
+
import { randomUUID } from "node:crypto";
|
|
1864
|
+
import { readFileSync as readFileSync2, rmSync } from "node:fs";
|
|
1865
|
+
import { createServer } from "node:net";
|
|
1866
|
+
import path from "node:path";
|
|
1867
|
+
var PS_COMMAND = "/bin/ps";
|
|
1868
|
+
var FORMAT_FLAG = "-o";
|
|
1869
|
+
var START_TIME_FORMAT = "lstart=";
|
|
1870
|
+
var PID_FLAG = "-p";
|
|
1871
|
+
var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
|
|
1872
|
+
var PROBE_TIMEOUT_MS2 = 2e3;
|
|
1873
|
+
var LIVENESS_SIGNAL = 0;
|
|
1874
|
+
var LOWEST_REAL_PID = 1;
|
|
1875
|
+
var PROC_START_FIELD_INDEX = 19;
|
|
1876
|
+
var BEACON_SCHEME = "socket:";
|
|
1877
|
+
var BEACON_SUFFIX = ".sock";
|
|
1878
|
+
var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
|
|
1879
|
+
var BEACON_ID_LENGTH = 36;
|
|
1880
|
+
var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
|
|
1881
|
+
var WINDOWS_PLATFORM = "win32";
|
|
1882
|
+
var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
|
|
1883
|
+
var beacons = /* @__PURE__ */ new Map();
|
|
1884
|
+
var exit_cleanup = { is_registered: false };
|
|
1885
|
+
function is_live_pid(pid) {
|
|
1886
|
+
if (pid < LOWEST_REAL_PID) return false;
|
|
1887
|
+
try {
|
|
1888
|
+
process.kill(pid, LIVENESS_SIGNAL);
|
|
1889
|
+
return true;
|
|
1890
|
+
} catch {
|
|
1891
|
+
return false;
|
|
1724
1892
|
}
|
|
1725
|
-
];
|
|
1726
|
-
var WORKFLOW_LABELS = [
|
|
1727
|
-
{
|
|
1728
|
-
name: EPIC_LABEL,
|
|
1729
|
-
color: "5319e7",
|
|
1730
|
-
description: "Tracks a batch of child issues from one split"
|
|
1731
|
-
},
|
|
1732
|
-
{ name: IN_PROGRESS_LABEL, color: "0075ca", description: "Work is actively in progress" },
|
|
1733
|
-
{
|
|
1734
|
-
name: RUN_SOLO_LABEL,
|
|
1735
|
-
color: "b60205",
|
|
1736
|
-
description: "Runs alone in a backlogrun: nothing starts beside it"
|
|
1737
|
-
},
|
|
1738
|
-
{
|
|
1739
|
-
name: RUN_LANE_LABEL,
|
|
1740
|
-
color: "0e8a16",
|
|
1741
|
-
description: "Judged safe to run beside others in a backlogrun"
|
|
1742
|
-
},
|
|
1743
|
-
...FILING_ROUTE_LABELS,
|
|
1744
|
-
...DEPTH_LABELS
|
|
1745
|
-
];
|
|
1746
|
-
var BUGFIX_LABEL = "bugfix";
|
|
1747
|
-
var OTHER_CHANGE_LABEL = "other-change";
|
|
1748
|
-
var IGNORE_FOR_RELEASE_LABEL = "ignore-for-release";
|
|
1749
|
-
var RELEASE_CLASSIFICATION_NAMES = [
|
|
1750
|
-
BREAKING_CHANGE_LABEL,
|
|
1751
|
-
ENHANCEMENT_LABEL,
|
|
1752
|
-
BUGFIX_LABEL,
|
|
1753
|
-
OTHER_CHANGE_LABEL,
|
|
1754
|
-
IGNORE_FOR_RELEASE_LABEL
|
|
1755
|
-
];
|
|
1756
|
-
var RELEASE_CLASSIFICATION_METADATA = {
|
|
1757
|
-
[BREAKING_CHANGE_LABEL]: { color: "d93f0b", description: "Release: a breaking change (major)" },
|
|
1758
|
-
[ENHANCEMENT_LABEL]: { color: "84b6eb", description: "Release: a new feature (minor)" },
|
|
1759
|
-
[BUGFIX_LABEL]: { color: "d73a4a", description: "Release: a bug fix (patch)" },
|
|
1760
|
-
[OTHER_CHANGE_LABEL]: { color: "c2e0c6", description: "Release: any other change (patch)" },
|
|
1761
|
-
[IGNORE_FOR_RELEASE_LABEL]: { color: "cfd3d7", description: "Release: left out of the notes" }
|
|
1762
|
-
};
|
|
1763
|
-
var RELEASE_CLASSIFICATION_LABELS = RELEASE_CLASSIFICATION_NAMES.map((name) => ({ name, ...RELEASE_CLASSIFICATION_METADATA[name] }));
|
|
1764
|
-
var REPOSITORY_LABELS = [
|
|
1765
|
-
...WORKFLOW_LABELS,
|
|
1766
|
-
...RELEASE_CLASSIFICATION_LABELS
|
|
1767
|
-
];
|
|
1768
|
-
function has_any_label(labels, wanted) {
|
|
1769
|
-
return (labels ?? []).some((label) => wanted.has(label.name.toLowerCase()));
|
|
1770
|
-
}
|
|
1771
|
-
function label_name_of(labels, wanted) {
|
|
1772
|
-
const target = wanted.toLowerCase();
|
|
1773
|
-
return labels.find((label) => label.toLowerCase() === target);
|
|
1774
|
-
}
|
|
1775
|
-
function has_label_name(labels, wanted) {
|
|
1776
|
-
return label_name_of(labels, wanted) !== void 0;
|
|
1777
1893
|
}
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1894
|
+
function read_proc_start(pid) {
|
|
1895
|
+
try {
|
|
1896
|
+
const stat = readFileSync2(`/proc/${String(pid)}/stat`, "utf8");
|
|
1897
|
+
const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
|
|
1898
|
+
const start = fields[PROC_START_FIELD_INDEX];
|
|
1899
|
+
return start === void 0 ? void 0 : `proc:${start}`;
|
|
1900
|
+
} catch {
|
|
1901
|
+
return void 0;
|
|
1902
|
+
}
|
|
1786
1903
|
}
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1904
|
+
function read_ps_start(pid) {
|
|
1905
|
+
try {
|
|
1906
|
+
const printed = execFileSync2(
|
|
1907
|
+
PS_COMMAND,
|
|
1908
|
+
[FORMAT_FLAG, START_TIME_FORMAT, PID_FLAG, String(pid)],
|
|
1909
|
+
{
|
|
1910
|
+
encoding: "utf8",
|
|
1911
|
+
timeout: PROBE_TIMEOUT_MS2,
|
|
1912
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
1913
|
+
env: PROBE_ENVIRONMENT
|
|
1914
|
+
}
|
|
1915
|
+
).trim();
|
|
1916
|
+
return printed.length > 0 ? printed : void 0;
|
|
1917
|
+
} catch {
|
|
1918
|
+
return void 0;
|
|
1919
|
+
}
|
|
1790
1920
|
}
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1921
|
+
var START_PROBES = { read_proc_start, read_ps_start };
|
|
1922
|
+
function safe_probe(probe, pid) {
|
|
1923
|
+
try {
|
|
1924
|
+
return probe(pid);
|
|
1925
|
+
} catch {
|
|
1926
|
+
return void 0;
|
|
1927
|
+
}
|
|
1794
1928
|
}
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
"u"
|
|
1798
|
-
);
|
|
1799
|
-
function records_the_park(command) {
|
|
1800
|
-
return APPLIES_NEEDS_DECISION.test(command);
|
|
1929
|
+
function read_start(pid, probes = START_PROBES) {
|
|
1930
|
+
return safe_probe(probes.read_proc_start, pid) ?? safe_probe(probes.read_ps_start, pid);
|
|
1801
1931
|
}
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
records_the_park
|
|
1809
|
-
};
|
|
1810
|
-
|
|
1811
|
-
// scripts/discovery/repo-discovery.ts
|
|
1812
|
-
import { existsSync, readdirSync, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
1813
|
-
import path from "node:path";
|
|
1814
|
-
|
|
1815
|
-
// scripts/discovery/repo-origin.ts
|
|
1816
|
-
var GITHUB_HOST = "github.com";
|
|
1817
|
-
var SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u;
|
|
1818
|
-
var GIT_SUFFIX = ".git";
|
|
1819
|
-
var PATH_SEPARATOR2 = "/";
|
|
1820
|
-
var USER_SEPARATOR = "@";
|
|
1821
|
-
var HOST_SEPARATOR = ":";
|
|
1822
|
-
var OWNER_INDEX = 0;
|
|
1823
|
-
var REPO_INDEX = 1;
|
|
1824
|
-
var REPO_PATH_SEGMENTS = 2;
|
|
1825
|
-
var NOT_FOUND = -1;
|
|
1826
|
-
var SECTION_PREFIX = "[";
|
|
1827
|
-
var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
|
|
1828
|
-
var URL_KEY = "url";
|
|
1829
|
-
function is_github_hostname(host) {
|
|
1830
|
-
return host.toLowerCase() === GITHUB_HOST;
|
|
1932
|
+
function close_beacon(token) {
|
|
1933
|
+
const server = beacons.get(token);
|
|
1934
|
+
if (server === void 0) return;
|
|
1935
|
+
beacons.delete(token);
|
|
1936
|
+
server.close();
|
|
1937
|
+
rmSync(token.slice(BEACON_SCHEME.length), { force: true });
|
|
1831
1938
|
}
|
|
1832
|
-
function
|
|
1833
|
-
const
|
|
1834
|
-
return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized);
|
|
1939
|
+
function close_beacons() {
|
|
1940
|
+
for (const token of beacons.keys()) close_beacon(token);
|
|
1835
1941
|
}
|
|
1836
|
-
function
|
|
1837
|
-
|
|
1942
|
+
function ensure_exit_cleanup() {
|
|
1943
|
+
if (exit_cleanup.is_registered) return;
|
|
1944
|
+
exit_cleanup.is_registered = true;
|
|
1945
|
+
process.once("exit", close_beacons);
|
|
1838
1946
|
}
|
|
1839
|
-
function
|
|
1840
|
-
const segments = repository_path.split(PATH_SEPARATOR2).filter((segment) => segment !== "");
|
|
1841
|
-
if (segments.length !== REPO_PATH_SEGMENTS) return void 0;
|
|
1842
|
-
const owner = segments[OWNER_INDEX] ?? "";
|
|
1843
|
-
const repo = strip_git_suffix(segments[REPO_INDEX] ?? "");
|
|
1844
|
-
return repo === "" ? void 0 : { owner, repo };
|
|
1947
|
+
function ignore_beacon_error() {
|
|
1845
1948
|
}
|
|
1846
|
-
function
|
|
1847
|
-
|
|
1848
|
-
const authority = user_end === NOT_FOUND ? url : url.slice(user_end + 1);
|
|
1849
|
-
const host_end = authority.indexOf(HOST_SEPARATOR);
|
|
1850
|
-
if (host_end === NOT_FOUND) return void 0;
|
|
1851
|
-
if (!is_github_ssh_host(authority.slice(0, host_end))) return void 0;
|
|
1852
|
-
return to_identity(authority.slice(host_end + 1));
|
|
1949
|
+
function bind_beacon(target) {
|
|
1950
|
+
return createServer().on("error", ignore_beacon_error).listen(target);
|
|
1853
1951
|
}
|
|
1854
|
-
function
|
|
1952
|
+
function try_bind_beacon(bind, target) {
|
|
1855
1953
|
try {
|
|
1856
|
-
const
|
|
1857
|
-
return
|
|
1954
|
+
const server = bind(target);
|
|
1955
|
+
return server.listening ? server : void 0;
|
|
1858
1956
|
} catch {
|
|
1859
1957
|
return void 0;
|
|
1860
1958
|
}
|
|
1861
1959
|
}
|
|
1862
|
-
function
|
|
1863
|
-
const
|
|
1864
|
-
|
|
1865
|
-
|
|
1960
|
+
function open_beacon(bind = bind_beacon) {
|
|
1961
|
+
const target = path.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
|
|
1962
|
+
const token = `${BEACON_SCHEME}${target}`;
|
|
1963
|
+
const server = try_bind_beacon(bind, target);
|
|
1964
|
+
if (server === void 0) return void 0;
|
|
1965
|
+
server.unref();
|
|
1966
|
+
beacons.set(token, server);
|
|
1967
|
+
ensure_exit_cleanup();
|
|
1968
|
+
return token;
|
|
1866
1969
|
}
|
|
1867
|
-
function
|
|
1868
|
-
|
|
1970
|
+
function resolve_own_start(probes = START_PROBES, platform2 = process.platform) {
|
|
1971
|
+
const start = read_start(process.pid, probes);
|
|
1972
|
+
if (start !== void 0 || platform2 === WINDOWS_PLATFORM) return start;
|
|
1973
|
+
return open_beacon();
|
|
1869
1974
|
}
|
|
1870
|
-
function
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
const end = rest.findIndex((line) => is_section_header(line));
|
|
1875
|
-
return end === NOT_FOUND ? rest : rest.slice(0, end);
|
|
1975
|
+
function is_valid_beacon_name(name) {
|
|
1976
|
+
if (!name.startsWith(BEACON_PREFIX) || !name.endsWith(BEACON_SUFFIX)) return false;
|
|
1977
|
+
const id = name.slice(BEACON_PREFIX.length, -BEACON_SUFFIX.length);
|
|
1978
|
+
return id.length === BEACON_ID_LENGTH && BEACON_ID_PATTERN.test(id);
|
|
1876
1979
|
}
|
|
1877
|
-
function
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
if (
|
|
1881
|
-
return
|
|
1980
|
+
function beacon_target(token) {
|
|
1981
|
+
if (!token.startsWith(BEACON_SCHEME)) return void 0;
|
|
1982
|
+
const target = token.slice(BEACON_SCHEME.length);
|
|
1983
|
+
if (path.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
|
|
1984
|
+
return is_valid_beacon_name(path.basename(target)) ? target : void 0;
|
|
1882
1985
|
}
|
|
1883
|
-
function
|
|
1884
|
-
|
|
1885
|
-
|
|
1986
|
+
function is_live_beacon(target) {
|
|
1987
|
+
return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
|
|
1988
|
+
stdio: "ignore",
|
|
1989
|
+
timeout: PROBE_TIMEOUT_MS2
|
|
1990
|
+
}).status === 0;
|
|
1886
1991
|
}
|
|
1887
|
-
function
|
|
1888
|
-
|
|
1992
|
+
function has_matching_start(pid, recorded_start, read2) {
|
|
1993
|
+
const observed = read2(pid);
|
|
1994
|
+
return observed === void 0 ? void 0 : observed === recorded_start;
|
|
1889
1995
|
}
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
is_github_ssh_host,
|
|
1894
|
-
parse_origin_from_config,
|
|
1895
|
-
parse_origin_url,
|
|
1896
|
-
format_identity
|
|
1897
|
-
};
|
|
1898
|
-
|
|
1899
|
-
// scripts/discovery/repo-map-logic.ts
|
|
1900
|
-
var OVERRIDE_ENTRY_SEPARATOR = ",";
|
|
1901
|
-
var OVERRIDE_PAIR_SEPARATOR = "=";
|
|
1902
|
-
var OVERRIDE_PAIR_PARTS = 2;
|
|
1903
|
-
var KEY_INDEX = 0;
|
|
1904
|
-
var PATH_INDEX = 1;
|
|
1905
|
-
function is_same_owner(identity, current_owner2) {
|
|
1906
|
-
return identity.owner.toLowerCase() === current_owner2.toLowerCase();
|
|
1996
|
+
function matches_recorded_start(pid, recorded_start, read2) {
|
|
1997
|
+
const target = beacon_target(recorded_start);
|
|
1998
|
+
return target === void 0 ? has_matching_start(pid, recorded_start, read2) : is_live_beacon(target);
|
|
1907
1999
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
target.set(repo_origin.format_identity(identity), repository_path);
|
|
2000
|
+
var own_probe = /* @__PURE__ */ new Map();
|
|
2001
|
+
function own_start() {
|
|
2002
|
+
if (!own_probe.has(process.pid)) own_probe.set(process.pid, resolve_own_start());
|
|
2003
|
+
return own_probe.get(process.pid);
|
|
1913
2004
|
}
|
|
1914
|
-
function
|
|
1915
|
-
const
|
|
1916
|
-
|
|
1917
|
-
const key = parts[KEY_INDEX] ?? "";
|
|
1918
|
-
const repository_path = parts[PATH_INDEX] ?? "";
|
|
1919
|
-
if (repository_path === "") return void 0;
|
|
1920
|
-
return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key}` };
|
|
2005
|
+
function own_fields() {
|
|
2006
|
+
const start = own_start();
|
|
2007
|
+
return { pid: process.pid, ...start !== void 0 && { process_start: start } };
|
|
1921
2008
|
}
|
|
1922
|
-
function
|
|
1923
|
-
if (
|
|
1924
|
-
|
|
2009
|
+
function is_same_process(pid, recorded_start, read2 = read_start) {
|
|
2010
|
+
if (pid === void 0 || !is_live_pid(pid)) return false;
|
|
2011
|
+
if (recorded_start === void 0) return void 0;
|
|
2012
|
+
return matches_recorded_start(pid, recorded_start, read2);
|
|
1925
2013
|
}
|
|
1926
|
-
function
|
|
1927
|
-
|
|
1928
|
-
for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner2);
|
|
1929
|
-
for (const entry of parse_overrides(override_value2)) {
|
|
1930
|
-
add_entry(result, entry.origin_url, entry.path, current_owner2);
|
|
1931
|
-
}
|
|
1932
|
-
return result;
|
|
2014
|
+
function is_own_process(pid, recorded_start) {
|
|
2015
|
+
return pid === process.pid && recorded_start === own_start();
|
|
1933
2016
|
}
|
|
1934
|
-
var
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
2017
|
+
var process_identity = {
|
|
2018
|
+
close_beacon,
|
|
2019
|
+
is_live_pid,
|
|
2020
|
+
is_own_process,
|
|
2021
|
+
is_same_process,
|
|
2022
|
+
open_beacon,
|
|
2023
|
+
own_fields,
|
|
2024
|
+
own_start,
|
|
2025
|
+
read_start,
|
|
2026
|
+
resolve_own_start
|
|
1938
2027
|
};
|
|
1939
2028
|
|
|
1940
|
-
// scripts/
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
var
|
|
1945
|
-
var
|
|
1946
|
-
function
|
|
1947
|
-
|
|
1948
|
-
if (!existsSync(pointer)) return git_directory;
|
|
1949
|
-
try {
|
|
1950
|
-
return path.resolve(git_directory, readFileSync2(pointer, "utf8").trim());
|
|
1951
|
-
} catch {
|
|
1952
|
-
return git_directory;
|
|
1953
|
-
}
|
|
2029
|
+
// scripts/run/run-carry.ts
|
|
2030
|
+
import { z as z6 } from "zod";
|
|
2031
|
+
|
|
2032
|
+
// scripts/run/run-carry-streak.ts
|
|
2033
|
+
var NO_INCREMENT = 0;
|
|
2034
|
+
var OUTAGE_FOLD_WINDOW_MS = 12e4;
|
|
2035
|
+
function has_increment(value) {
|
|
2036
|
+
return (value ?? NO_INCREMENT) > NO_INCREMENT;
|
|
1954
2037
|
}
|
|
1955
|
-
function
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
return path.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim());
|
|
2038
|
+
function next_failures(carry, change) {
|
|
2039
|
+
if (has_increment(change.merged)) return NO_INCREMENT;
|
|
2040
|
+
return carry.failures + (change.failures ?? NO_INCREMENT);
|
|
1959
2041
|
}
|
|
1960
|
-
function
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
const linked = follow_git_file(repository_path, candidate);
|
|
1966
|
-
return linked === void 0 ? void 0 : resolve_common_directory(linked);
|
|
1967
|
-
} catch {
|
|
1968
|
-
return void 0;
|
|
1969
|
-
}
|
|
2042
|
+
function is_within_fold_window(last_outage_at, now) {
|
|
2043
|
+
if (last_outage_at === void 0) return false;
|
|
2044
|
+
const last = Date.parse(last_outage_at);
|
|
2045
|
+
if (Number.isNaN(last)) return false;
|
|
2046
|
+
return now.getTime() - last <= OUTAGE_FOLD_WINDOW_MS;
|
|
1970
2047
|
}
|
|
1971
|
-
function
|
|
1972
|
-
|
|
1973
|
-
if (git_directory === void 0) return void 0;
|
|
1974
|
-
try {
|
|
1975
|
-
return repo_origin.parse_origin_from_config(
|
|
1976
|
-
readFileSync2(path.join(git_directory, GIT_CONFIG), "utf8")
|
|
1977
|
-
);
|
|
1978
|
-
} catch {
|
|
1979
|
-
return void 0;
|
|
1980
|
-
}
|
|
2048
|
+
function folded_outage(carry) {
|
|
2049
|
+
return { outages: carry.outages, last_outage_at: carry.last_outage_at };
|
|
1981
2050
|
}
|
|
1982
|
-
function
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
} catch {
|
|
1986
|
-
return [];
|
|
1987
|
-
}
|
|
2051
|
+
function counted_outage(carry, change, now) {
|
|
2052
|
+
const outages = carry.outages + (change.outages ?? NO_INCREMENT);
|
|
2053
|
+
return { outages, last_outage_at: now.toISOString() };
|
|
1988
2054
|
}
|
|
1989
|
-
function
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
2055
|
+
function next_outage(carry, change, now) {
|
|
2056
|
+
if (has_increment(change.outages)) {
|
|
2057
|
+
return is_within_fold_window(carry.last_outage_at, now) ? folded_outage(carry) : counted_outage(carry, change, now);
|
|
2058
|
+
}
|
|
2059
|
+
const is_reachable = has_increment(change.merged) || has_increment(change.failures);
|
|
2060
|
+
return is_reachable ? { outages: NO_INCREMENT, last_outage_at: void 0 } : folded_outage(carry);
|
|
1994
2061
|
}
|
|
1995
|
-
function
|
|
1996
|
-
const
|
|
1997
|
-
|
|
1998
|
-
|
|
2062
|
+
function next_state(carry, change, now) {
|
|
2063
|
+
const outage = next_outage(carry, change, now);
|
|
2064
|
+
return {
|
|
2065
|
+
failures: next_failures(carry, change),
|
|
2066
|
+
outages: outage.outages,
|
|
2067
|
+
last_outage_at: outage.last_outage_at
|
|
2068
|
+
};
|
|
1999
2069
|
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2070
|
+
var run_carry_streak = { next_state };
|
|
2071
|
+
|
|
2072
|
+
// scripts/run/run-carry-change.ts
|
|
2073
|
+
var NO_INCREMENT2 = 0;
|
|
2074
|
+
function next_done(carry, done) {
|
|
2075
|
+
if (done === void 0) return carry.done;
|
|
2076
|
+
const current = carry.done ?? [];
|
|
2077
|
+
return current.includes(done) ? current : [...current, done];
|
|
2005
2078
|
}
|
|
2006
|
-
function
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
if (current_owner2 === void 0) return /* @__PURE__ */ new Map();
|
|
2010
|
-
return repo_map_logic.build_repository_map(
|
|
2011
|
-
scan_siblings(path.dirname(main2)),
|
|
2012
|
-
current_owner2,
|
|
2013
|
-
environment[OVERRIDE_ENV_KEY]
|
|
2014
|
-
);
|
|
2079
|
+
function next_merged_issues(carry, issue) {
|
|
2080
|
+
if (issue === void 0) return carry.merged_issues;
|
|
2081
|
+
return [...carry.merged_issues ?? [], issue];
|
|
2015
2082
|
}
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
read_origin_url,
|
|
2020
|
-
resolve_current_owner,
|
|
2021
|
-
scan_siblings,
|
|
2022
|
-
discover_repositories
|
|
2023
|
-
};
|
|
2024
|
-
|
|
2025
|
-
// scripts/discovery/repo-party.ts
|
|
2026
|
-
var FIRST_PARTY = "first-party";
|
|
2027
|
-
var THIRD_PARTY = "third-party";
|
|
2028
|
-
var UNKNOWN = "unknown";
|
|
2029
|
-
function classify3(session_owner, target) {
|
|
2030
|
-
if (session_owner === void 0 || target === void 0) return UNKNOWN;
|
|
2031
|
-
return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
|
|
2083
|
+
function is_duplicate_merge(carry, change) {
|
|
2084
|
+
const issue = change.merged_issue;
|
|
2085
|
+
return issue !== void 0 && carry.merged_issues?.includes(issue) === true;
|
|
2032
2086
|
}
|
|
2033
|
-
function
|
|
2034
|
-
|
|
2087
|
+
function next_counts(carry, change) {
|
|
2088
|
+
const cuts = change.cuts ?? NO_INCREMENT2;
|
|
2089
|
+
return {
|
|
2090
|
+
merged: carry.merged + (change.merged ?? NO_INCREMENT2),
|
|
2091
|
+
filed: carry.filed + (change.filed ?? NO_INCREMENT2),
|
|
2092
|
+
cuts: carry.cuts + cuts,
|
|
2093
|
+
is_handed_off: cuts > NO_INCREMENT2
|
|
2094
|
+
};
|
|
2035
2095
|
}
|
|
2036
|
-
function
|
|
2037
|
-
|
|
2096
|
+
function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
|
|
2097
|
+
if (is_duplicate_merge(carry, change)) return carry;
|
|
2098
|
+
const streak = run_carry_streak.next_state(carry, change, now);
|
|
2099
|
+
const next = {
|
|
2100
|
+
...carry,
|
|
2101
|
+
...next_counts(carry, change),
|
|
2102
|
+
merged_issues: next_merged_issues(carry, change.merged_issue),
|
|
2103
|
+
failures: streak.failures,
|
|
2104
|
+
outages: streak.outages,
|
|
2105
|
+
last_outage_at: streak.last_outage_at,
|
|
2106
|
+
done: next_done(carry, change.done),
|
|
2107
|
+
retrospective: change.retrospective === true || carry.retrospective
|
|
2108
|
+
};
|
|
2109
|
+
stamp_file.write_stamp(target, next);
|
|
2110
|
+
return next;
|
|
2038
2111
|
}
|
|
2039
|
-
var
|
|
2112
|
+
var run_carry_change = { apply_change };
|
|
2040
2113
|
|
|
2041
|
-
// scripts/
|
|
2042
|
-
import {
|
|
2043
|
-
import path3 from "node:path";
|
|
2114
|
+
// scripts/backlog/backlog-budget-cli.ts
|
|
2115
|
+
import { fileURLToPath } from "node:url";
|
|
2044
2116
|
|
|
2045
|
-
// scripts/git/
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
var ORIGIN_REMOTE = "origin";
|
|
2049
|
-
var HEADS_REF_PREFIX = "refs/heads/";
|
|
2050
|
-
function ls_remote_branch_arguments(branch_name) {
|
|
2051
|
-
return [LS_REMOTE_COMMAND, HEADS_FLAG, ORIGIN_REMOTE, `${HEADS_REF_PREFIX}${branch_name}`];
|
|
2117
|
+
// scripts/git/changed-paths.ts
|
|
2118
|
+
function to_paths(raw) {
|
|
2119
|
+
return raw.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
2052
2120
|
}
|
|
2121
|
+
async function read_changed_paths(is_staged) {
|
|
2122
|
+
if (is_staged) return to_paths(await git_command.diff_cached_names());
|
|
2123
|
+
const tracked = to_paths(await git_command.diff_main_names());
|
|
2124
|
+
const untracked = to_paths(await git_command.untracked_names());
|
|
2125
|
+
return [...tracked, ...untracked];
|
|
2126
|
+
}
|
|
2127
|
+
var changed_paths = { read_changed_paths, to_paths };
|
|
2053
2128
|
|
|
2054
|
-
// scripts/
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
import { readFileSync as readFileSync3, rmSync } from "node:fs";
|
|
2063
|
-
import { createServer } from "node:net";
|
|
2064
|
-
import path2 from "node:path";
|
|
2065
|
-
var PS_COMMAND = "/bin/ps";
|
|
2066
|
-
var FORMAT_FLAG = "-o";
|
|
2067
|
-
var START_TIME_FORMAT = "lstart=";
|
|
2068
|
-
var PID_FLAG = "-p";
|
|
2069
|
-
var PROBE_ENVIRONMENT = { TZ: "UTC", LC_ALL: "C" };
|
|
2070
|
-
var PROBE_TIMEOUT_MS = 2e3;
|
|
2071
|
-
var LIVENESS_SIGNAL = 0;
|
|
2072
|
-
var LOWEST_REAL_PID = 1;
|
|
2073
|
-
var PROC_START_FIELD_INDEX = 19;
|
|
2074
|
-
var BEACON_SCHEME = "socket:";
|
|
2075
|
-
var BEACON_SUFFIX = ".sock";
|
|
2076
|
-
var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
|
|
2077
|
-
var BEACON_ID_LENGTH = 36;
|
|
2078
|
-
var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
|
|
2079
|
-
var WINDOWS_PLATFORM = "win32";
|
|
2080
|
-
var SOCKET_PROBE_SOURCE = "const net=require('node:net');const socket=net.createConnection(process.argv[1]);socket.once('connect',()=>process.exit(0));socket.once('error',()=>process.exit(1));socket.setTimeout(1000,()=>process.exit(1));";
|
|
2081
|
-
var beacons = /* @__PURE__ */ new Map();
|
|
2082
|
-
var exit_cleanup = { is_registered: false };
|
|
2083
|
-
function is_live_pid(pid) {
|
|
2084
|
-
if (pid < LOWEST_REAL_PID) return false;
|
|
2085
|
-
try {
|
|
2086
|
-
process.kill(pid, LIVENESS_SIGNAL);
|
|
2087
|
-
return true;
|
|
2088
|
-
} catch {
|
|
2089
|
-
return false;
|
|
2090
|
-
}
|
|
2129
|
+
// scripts/josh/path-decision.ts
|
|
2130
|
+
var STAGED_FLAG = "--staged";
|
|
2131
|
+
var JSON_FLAG = "--json";
|
|
2132
|
+
var KNOWN_FLAGS = [STAGED_FLAG, JSON_FLAG];
|
|
2133
|
+
var FAILURE_EXIT_CODE = 1;
|
|
2134
|
+
var MAX_LISTED_PATHS = 5;
|
|
2135
|
+
function has_unknown_flag(argv, known) {
|
|
2136
|
+
return argv.some((argument) => !known.includes(argument));
|
|
2091
2137
|
}
|
|
2092
|
-
function
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2138
|
+
function parse_options(argv) {
|
|
2139
|
+
if (has_unknown_flag(argv, KNOWN_FLAGS)) return void 0;
|
|
2140
|
+
return { is_staged: argv.includes(STAGED_FLAG), is_json: argv.includes(JSON_FLAG) };
|
|
2141
|
+
}
|
|
2142
|
+
function format_path_list(paths) {
|
|
2143
|
+
const listed = paths.slice(0, MAX_LISTED_PATHS).join(", ");
|
|
2144
|
+
if (paths.length <= MAX_LISTED_PATHS) return listed;
|
|
2145
|
+
return `${listed}, +${String(paths.length - MAX_LISTED_PATHS)} more`;
|
|
2146
|
+
}
|
|
2147
|
+
function print_decision(key2, answer, reason, is_json) {
|
|
2148
|
+
if (is_json) {
|
|
2149
|
+
console.info(JSON.stringify({ [key2]: answer, reason }));
|
|
2150
|
+
return;
|
|
2100
2151
|
}
|
|
2152
|
+
console.info(answer);
|
|
2153
|
+
console.error(reason);
|
|
2101
2154
|
}
|
|
2102
|
-
function
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
{
|
|
2108
|
-
encoding: "utf8",
|
|
2109
|
-
timeout: PROBE_TIMEOUT_MS,
|
|
2110
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
2111
|
-
env: PROBE_ENVIRONMENT
|
|
2112
|
-
}
|
|
2113
|
-
).trim();
|
|
2114
|
-
return printed.length > 0 ? printed : void 0;
|
|
2115
|
-
} catch {
|
|
2116
|
-
return void 0;
|
|
2155
|
+
async function run_path_decision(argv, command) {
|
|
2156
|
+
const options = parse_options(argv);
|
|
2157
|
+
if (options === void 0) {
|
|
2158
|
+
console.error(command.usage);
|
|
2159
|
+
return FAILURE_EXIT_CODE;
|
|
2117
2160
|
}
|
|
2161
|
+
const paths = await changed_paths.read_changed_paths(options.is_staged);
|
|
2162
|
+
const answer = command.decide(paths);
|
|
2163
|
+
print_decision(command.key, answer, command.explain(paths, answer), options.is_json);
|
|
2164
|
+
return 0;
|
|
2118
2165
|
}
|
|
2119
|
-
var
|
|
2120
|
-
|
|
2166
|
+
var path_decision = {
|
|
2167
|
+
format_path_list,
|
|
2168
|
+
has_unknown_flag,
|
|
2169
|
+
JSON_FLAG,
|
|
2170
|
+
parse_options,
|
|
2171
|
+
print_decision,
|
|
2172
|
+
run_path_decision
|
|
2173
|
+
};
|
|
2174
|
+
|
|
2175
|
+
// scripts/lib/cli-flags.ts
|
|
2176
|
+
import { parseArgs } from "node:util";
|
|
2177
|
+
function refuse_unknown_flags(argv, known_flags, command) {
|
|
2178
|
+
const unknown = argv.filter((argument) => !known_flags.includes(argument));
|
|
2179
|
+
if (unknown.length === 0) return void 0;
|
|
2180
|
+
const usage = `Usage: josh ${command} [${known_flags.join("] [")}]`;
|
|
2181
|
+
return `Unknown argument(s): ${unknown.join(" ")}
|
|
2182
|
+
${usage}`;
|
|
2183
|
+
}
|
|
2184
|
+
function parse_or_undefined(config) {
|
|
2121
2185
|
try {
|
|
2122
|
-
return
|
|
2186
|
+
return parseArgs(config);
|
|
2123
2187
|
} catch {
|
|
2124
2188
|
return void 0;
|
|
2125
2189
|
}
|
|
2126
2190
|
}
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
}
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2191
|
+
var cli_flags = { refuse_unknown_flags, parse_or_undefined };
|
|
2192
|
+
|
|
2193
|
+
// scripts/backlog/backlog-budget-cli.ts
|
|
2194
|
+
var ARGV_OFFSET = 2;
|
|
2195
|
+
var SUCCESS_EXIT_CODE = 0;
|
|
2196
|
+
var FAILURE_EXIT_CODE2 = 1;
|
|
2197
|
+
var JSON_KEY = "budget";
|
|
2198
|
+
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]`;
|
|
2199
|
+
var OPTIONS = {
|
|
2200
|
+
active: { type: "string" },
|
|
2201
|
+
answer: { type: "string" },
|
|
2202
|
+
idle: { type: "string" },
|
|
2203
|
+
json: { type: "boolean" },
|
|
2204
|
+
max: { type: "string" },
|
|
2205
|
+
merged: { type: "string" },
|
|
2206
|
+
running: { type: "string" },
|
|
2207
|
+
started: { type: "string" }
|
|
2208
|
+
};
|
|
2209
|
+
function read_arguments(argv) {
|
|
2210
|
+
return cli_flags.parse_or_undefined({ args: [...argv], options: OPTIONS, strict: true })?.values;
|
|
2144
2211
|
}
|
|
2145
|
-
function
|
|
2212
|
+
function text_of(value) {
|
|
2213
|
+
return typeof value === "string" ? value : void 0;
|
|
2146
2214
|
}
|
|
2147
|
-
function
|
|
2148
|
-
return
|
|
2215
|
+
function to_answer(raw) {
|
|
2216
|
+
return backlog_budget.ANSWERS.find((answer) => answer === raw);
|
|
2149
2217
|
}
|
|
2150
|
-
function
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
} catch {
|
|
2155
|
-
return void 0;
|
|
2156
|
-
}
|
|
2218
|
+
function to_time_ms(raw) {
|
|
2219
|
+
if (raw === void 0) return void 0;
|
|
2220
|
+
const parsed = Date.parse(raw);
|
|
2221
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
2157
2222
|
}
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
const
|
|
2162
|
-
|
|
2163
|
-
server.unref();
|
|
2164
|
-
beacons.set(token, server);
|
|
2165
|
-
ensure_exit_cleanup();
|
|
2166
|
-
return token;
|
|
2223
|
+
var COUNT_PATTERN = /^\d+$/u;
|
|
2224
|
+
function to_count(raw) {
|
|
2225
|
+
if (raw === void 0 || !COUNT_PATTERN.test(raw)) return void 0;
|
|
2226
|
+
const parsed = Number(raw);
|
|
2227
|
+
return Number.isSafeInteger(parsed) ? parsed : void 0;
|
|
2167
2228
|
}
|
|
2168
|
-
function
|
|
2169
|
-
|
|
2170
|
-
if (start !== void 0 || platform2 === WINDOWS_PLATFORM) return start;
|
|
2171
|
-
return open_beacon();
|
|
2229
|
+
function is_readable(raw, parsed) {
|
|
2230
|
+
return raw === void 0 || parsed !== void 0;
|
|
2172
2231
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2232
|
+
var COUNT_NAMES = ["idle", "max", "merged", "running"];
|
|
2233
|
+
function counts_of(values) {
|
|
2234
|
+
return {
|
|
2235
|
+
idle: to_count(text_of(values.idle)),
|
|
2236
|
+
max: to_count(text_of(values.max)),
|
|
2237
|
+
merged: to_count(text_of(values.merged)),
|
|
2238
|
+
running: to_count(text_of(values.running))
|
|
2239
|
+
};
|
|
2177
2240
|
}
|
|
2178
|
-
function
|
|
2179
|
-
|
|
2180
|
-
const target = token.slice(BEACON_SCHEME.length);
|
|
2181
|
-
if (path2.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
|
|
2182
|
-
return is_valid_beacon_name(path2.basename(target)) ? target : void 0;
|
|
2241
|
+
function are_counts_readable(values, counts) {
|
|
2242
|
+
return COUNT_NAMES.every((name) => is_readable(text_of(values[name]), counts[name]));
|
|
2183
2243
|
}
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2244
|
+
var NO_IDLE_MINUTES = 0;
|
|
2245
|
+
function to_idle_ms(idle_minutes) {
|
|
2246
|
+
if (idle_minutes === void 0) return backlog_budget.DEFAULT_IDLE_MS;
|
|
2247
|
+
if (idle_minutes === NO_IDLE_MINUTES) return void 0;
|
|
2248
|
+
return idle_minutes * backlog_budget.MS_PER_MINUTE;
|
|
2189
2249
|
}
|
|
2190
|
-
function
|
|
2191
|
-
|
|
2192
|
-
return
|
|
2250
|
+
function is_watch_readable(values) {
|
|
2251
|
+
if (to_idle_ms(to_count(text_of(values.idle))) === void 0) return true;
|
|
2252
|
+
return text_of(values.active) !== void 0;
|
|
2193
2253
|
}
|
|
2194
|
-
function
|
|
2195
|
-
|
|
2196
|
-
return target === void 0 ? has_matching_start(pid, recorded_start, read2) : is_live_beacon(target);
|
|
2254
|
+
function are_values_readable(values) {
|
|
2255
|
+
return is_readable(text_of(values.active), to_time_ms(text_of(values.active))) && is_watch_readable(values) && are_counts_readable(values, counts_of(values));
|
|
2197
2256
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2257
|
+
function input_of(values, base) {
|
|
2258
|
+
const counts = counts_of(values);
|
|
2259
|
+
return {
|
|
2260
|
+
...base,
|
|
2261
|
+
active_at_ms: to_time_ms(text_of(values.active)) ?? base.started_at_ms,
|
|
2262
|
+
merged: counts.merged ?? 0,
|
|
2263
|
+
running: counts.running ?? 0,
|
|
2264
|
+
max_issues: counts.max,
|
|
2265
|
+
idle_budget_ms: to_idle_ms(counts.idle)
|
|
2266
|
+
};
|
|
2202
2267
|
}
|
|
2203
|
-
function
|
|
2204
|
-
const
|
|
2205
|
-
|
|
2268
|
+
function build_input(values, now_ms) {
|
|
2269
|
+
const answer = to_answer(text_of(values.answer));
|
|
2270
|
+
if (answer === void 0) return void 0;
|
|
2271
|
+
const started_at_ms = to_time_ms(text_of(values.started));
|
|
2272
|
+
if (started_at_ms === void 0) return void 0;
|
|
2273
|
+
if (!are_values_readable(values)) return void 0;
|
|
2274
|
+
return input_of(values, { answer, now_ms, started_at_ms });
|
|
2206
2275
|
}
|
|
2207
|
-
function
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
return matches_recorded_start(pid, recorded_start, read2);
|
|
2276
|
+
function refuse() {
|
|
2277
|
+
console.error(USAGE);
|
|
2278
|
+
return FAILURE_EXIT_CODE2;
|
|
2211
2279
|
}
|
|
2212
|
-
function
|
|
2213
|
-
|
|
2280
|
+
function run(argv, now_ms = Date.now()) {
|
|
2281
|
+
const values = read_arguments(argv);
|
|
2282
|
+
if (values === void 0) return refuse();
|
|
2283
|
+
const input = build_input(values, now_ms);
|
|
2284
|
+
if (input === void 0) return refuse();
|
|
2285
|
+
const { verdict, reason } = backlog_budget.decide(input);
|
|
2286
|
+
if (values.json === true) {
|
|
2287
|
+
console.info(
|
|
2288
|
+
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: backlog_budget.is_finish(input) })
|
|
2289
|
+
);
|
|
2290
|
+
return SUCCESS_EXIT_CODE;
|
|
2291
|
+
}
|
|
2292
|
+
path_decision.print_decision(JSON_KEY, verdict, reason, false);
|
|
2293
|
+
return SUCCESS_EXIT_CODE;
|
|
2214
2294
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2295
|
+
function main(argv) {
|
|
2296
|
+
process.exitCode = run(argv);
|
|
2297
|
+
}
|
|
2298
|
+
var backlog_budget_cli = {
|
|
2299
|
+
JSON_KEY,
|
|
2300
|
+
OPTIONS,
|
|
2301
|
+
SUCCESS_EXIT_CODE,
|
|
2302
|
+
USAGE,
|
|
2303
|
+
build_input,
|
|
2304
|
+
main,
|
|
2305
|
+
read_arguments,
|
|
2306
|
+
run,
|
|
2307
|
+
to_answer,
|
|
2308
|
+
to_count,
|
|
2309
|
+
to_time_ms
|
|
2225
2310
|
};
|
|
2311
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
|
|
2226
2312
|
|
|
2227
|
-
// scripts/
|
|
2228
|
-
|
|
2229
|
-
var
|
|
2230
|
-
var
|
|
2231
|
-
var
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2313
|
+
// scripts/run/run-invocation.ts
|
|
2314
|
+
var BACKLOG_COMMAND = "backlogrun";
|
|
2315
|
+
var KNOWN_FLAGS2 = ["--max", "--idle"];
|
|
2316
|
+
var ONLY_FLAG = "--only";
|
|
2317
|
+
var ISSUE_PREFIX = "#";
|
|
2318
|
+
var TOKEN_SEPARATOR = " ";
|
|
2319
|
+
var FIRST_TOKEN = 0;
|
|
2320
|
+
var FIRST_ARGUMENT_INDEX = 1;
|
|
2321
|
+
var VALUE_OFFSET = 1;
|
|
2322
|
+
var FLAG_PAIR_LENGTH = 2;
|
|
2323
|
+
var ONLY_STEP = 1;
|
|
2324
|
+
var EMPTY_LENGTH2 = 0;
|
|
2325
|
+
var NOT_FOUND = -1;
|
|
2326
|
+
function tokens_of(invocation) {
|
|
2327
|
+
return invocation.split(TOKEN_SEPARATOR).filter((token) => token.length > EMPTY_LENGTH2);
|
|
2241
2328
|
}
|
|
2242
|
-
function
|
|
2243
|
-
const
|
|
2244
|
-
const
|
|
2245
|
-
|
|
2329
|
+
function flag_token(token, raw) {
|
|
2330
|
+
const flag = KNOWN_FLAGS2.find((known) => known === token);
|
|
2331
|
+
const value = backlog_budget_cli.to_count(raw);
|
|
2332
|
+
if (flag === void 0 || value === void 0) return void 0;
|
|
2333
|
+
return `${flag} ${String(value)}`;
|
|
2246
2334
|
}
|
|
2247
|
-
function
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
}
|
|
2335
|
+
function read_flag(tokens, index) {
|
|
2336
|
+
const token = tokens[index] ?? "";
|
|
2337
|
+
if (token === ONLY_FLAG) return { part: ONLY_FLAG, advance: ONLY_STEP };
|
|
2338
|
+
const part = flag_token(token, tokens[index + VALUE_OFFSET]);
|
|
2339
|
+
return part === void 0 ? void 0 : { part, advance: FLAG_PAIR_LENGTH };
|
|
2253
2340
|
}
|
|
2254
|
-
function
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2341
|
+
function flag_tokens(tokens, start) {
|
|
2342
|
+
const rendered = [];
|
|
2343
|
+
let index = start;
|
|
2344
|
+
while (index < tokens.length) {
|
|
2345
|
+
const read2 = read_flag(tokens, index);
|
|
2346
|
+
if (read2 === void 0) return void 0;
|
|
2347
|
+
rendered.push(read2.part);
|
|
2348
|
+
index += read2.advance;
|
|
2259
2349
|
}
|
|
2350
|
+
return rendered;
|
|
2260
2351
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
return
|
|
2352
|
+
function issue_of(token) {
|
|
2353
|
+
if (!token.startsWith(ISSUE_PREFIX)) return void 0;
|
|
2354
|
+
const digits = token.slice(ISSUE_PREFIX.length);
|
|
2355
|
+
if (!run_issue_number.ISSUE_NUMBER_PATTERN.test(digits)) return void 0;
|
|
2356
|
+
const issue = Number(digits);
|
|
2357
|
+
return Number.isSafeInteger(issue) ? issue : void 0;
|
|
2267
2358
|
}
|
|
2268
|
-
function
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2359
|
+
function take_leading_prefixed(args) {
|
|
2360
|
+
const stop = args.findIndex((token) => !token.startsWith(ISSUE_PREFIX));
|
|
2361
|
+
return args.slice(FIRST_TOKEN, stop === NOT_FOUND ? args.length : stop);
|
|
2362
|
+
}
|
|
2363
|
+
function leading_issues(tokens) {
|
|
2364
|
+
const issues = [];
|
|
2365
|
+
const prefixed = take_leading_prefixed(tokens.slice(FIRST_ARGUMENT_INDEX));
|
|
2366
|
+
for (const token of prefixed) {
|
|
2367
|
+
const issue = issue_of(token);
|
|
2368
|
+
if (issue === void 0) return void 0;
|
|
2369
|
+
issues.push(issue);
|
|
2274
2370
|
}
|
|
2371
|
+
return issues;
|
|
2275
2372
|
}
|
|
2276
|
-
function
|
|
2277
|
-
return
|
|
2373
|
+
function issue_token(issue) {
|
|
2374
|
+
return `${ISSUE_PREFIX}${String(issue)}`;
|
|
2278
2375
|
}
|
|
2279
|
-
function
|
|
2280
|
-
return
|
|
2376
|
+
function joined(command, rendered) {
|
|
2377
|
+
return [command, ...rendered].join(TOKEN_SEPARATOR);
|
|
2281
2378
|
}
|
|
2282
|
-
function
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2379
|
+
function rebuilt_backlog(tokens) {
|
|
2380
|
+
const issues = leading_issues(tokens);
|
|
2381
|
+
if (issues === void 0) return void 0;
|
|
2382
|
+
const flags = flag_tokens(tokens, FIRST_ARGUMENT_INDEX + issues.length);
|
|
2383
|
+
if (flags === void 0) return void 0;
|
|
2384
|
+
return joined(BACKLOG_COMMAND, [...issues.map((issue) => issue_token(issue)), ...flags]);
|
|
2287
2385
|
}
|
|
2288
|
-
function
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
return
|
|
2386
|
+
function rebuild(invocation) {
|
|
2387
|
+
const tokens = tokens_of(invocation);
|
|
2388
|
+
if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
|
|
2389
|
+
return rebuilt_backlog(tokens);
|
|
2292
2390
|
}
|
|
2293
|
-
function
|
|
2294
|
-
const
|
|
2391
|
+
function issue_numbers(invocation) {
|
|
2392
|
+
const tokens = tokens_of(invocation);
|
|
2393
|
+
if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return void 0;
|
|
2394
|
+
const issues = leading_issues(tokens);
|
|
2395
|
+
if (issues === void 0 || issues.length === EMPTY_LENGTH2) return void 0;
|
|
2396
|
+
return issues;
|
|
2397
|
+
}
|
|
2398
|
+
function has_only(invocation) {
|
|
2399
|
+
const tokens = tokens_of(invocation);
|
|
2400
|
+
if (tokens[FIRST_TOKEN] !== BACKLOG_COMMAND) return false;
|
|
2401
|
+
return tokens.slice(FIRST_ARGUMENT_INDEX).includes(ONLY_FLAG);
|
|
2402
|
+
}
|
|
2403
|
+
var run_invocation = {
|
|
2404
|
+
has_only,
|
|
2405
|
+
issue_numbers,
|
|
2406
|
+
rebuild
|
|
2407
|
+
};
|
|
2408
|
+
|
|
2409
|
+
// scripts/run/run-carry.ts
|
|
2410
|
+
var CARRY_PREFIX = "josh-run-carry-";
|
|
2411
|
+
var REPOSITORY_DIRECTORY_INDEX = 1;
|
|
2412
|
+
var CARRY_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS;
|
|
2413
|
+
var CARRY_MAX_AGE_MS = backlog_budget.WHOLE_RUN_BUDGET_MS;
|
|
2414
|
+
var NO_INCREMENT3 = 0;
|
|
2415
|
+
var MAX_CUTS = 6;
|
|
2416
|
+
var END_COMMAND2 = "pnpm josh run:carry --end";
|
|
2417
|
+
var RESUME_COMMAND = "pnpm josh run:carry --resume";
|
|
2418
|
+
var READ_COMMAND2 = "pnpm josh run:carry --json";
|
|
2419
|
+
var OWNER_ARGUMENT = '--owner "$PPID"';
|
|
2420
|
+
var NONE_READ2 = { kind: "none" };
|
|
2421
|
+
var UNREADABLE_READ3 = { kind: "unreadable" };
|
|
2422
|
+
var NO_OWNER = {};
|
|
2423
|
+
var run_carry_schema = z6.object({
|
|
2424
|
+
invocation: z6.string(),
|
|
2425
|
+
started_at: z6.string(),
|
|
2426
|
+
merged: z6.number(),
|
|
2427
|
+
merged_issues: z6.array(z6.number()).optional(),
|
|
2428
|
+
filed: z6.number(),
|
|
2429
|
+
cuts: z6.number(),
|
|
2430
|
+
// Defaulted, so a record written before this field existed parses with a zero streak rather than
|
|
2431
|
+
// failing to read — the same backward-compatibility the optional owner fields below carry.
|
|
2432
|
+
failures: z6.number().default(0),
|
|
2433
|
+
// Defaulted for the same backward-compatibility as `failures` (joshuafolkken/kit#2240).
|
|
2434
|
+
outages: z6.number().default(0),
|
|
2435
|
+
// Optional, so a record written before the outage fold existed still parses (joshuafolkken/kit#2317).
|
|
2436
|
+
last_outage_at: z6.string().optional(),
|
|
2437
|
+
// Optional, so a record written by the previous shape still parses. Read as "no owner declared",
|
|
2438
|
+
// which is the not-provably-live answer rather than a live one.
|
|
2439
|
+
owner_pid: z6.number().optional(),
|
|
2440
|
+
owner_start: z6.string().optional(),
|
|
2441
|
+
is_handed_off: z6.boolean().optional(),
|
|
2442
|
+
done: z6.array(z6.number()).optional(),
|
|
2443
|
+
// Optional, so a record written before the retrospective existed still parses (joshuafolkken/kit#2328).
|
|
2444
|
+
retrospective: z6.boolean().optional()
|
|
2445
|
+
});
|
|
2446
|
+
function carry_path(git_directory) {
|
|
2447
|
+
return stamp_file.stamp_path(CARRY_PREFIX, git_directory);
|
|
2448
|
+
}
|
|
2449
|
+
async function repository_directory() {
|
|
2450
|
+
const directories2 = await git_command.git_directories();
|
|
2451
|
+
return directories2[REPOSITORY_DIRECTORY_INDEX];
|
|
2452
|
+
}
|
|
2453
|
+
function parse_carry(raw) {
|
|
2295
2454
|
try {
|
|
2296
|
-
|
|
2297
|
-
return
|
|
2455
|
+
const parsed = run_carry_schema.safeParse(JSON.parse(raw));
|
|
2456
|
+
return parsed.success ? parsed.data : void 0;
|
|
2298
2457
|
} catch {
|
|
2299
2458
|
return void 0;
|
|
2300
2459
|
}
|
|
2301
2460
|
}
|
|
2302
|
-
function
|
|
2303
|
-
const
|
|
2304
|
-
if (
|
|
2305
|
-
|
|
2306
|
-
if (aside === void 0) return;
|
|
2307
|
-
if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
|
|
2308
|
-
rmSync2(aside, { force: true });
|
|
2461
|
+
function is_expired2(carry, now) {
|
|
2462
|
+
const started = Date.parse(carry.started_at);
|
|
2463
|
+
if (Number.isNaN(started)) return true;
|
|
2464
|
+
return now.getTime() - started > CARRY_MAX_AGE_MS;
|
|
2309
2465
|
}
|
|
2310
|
-
function
|
|
2311
|
-
|
|
2312
|
-
|
|
2466
|
+
function classify3(raw, now) {
|
|
2467
|
+
if (raw === void 0) return NONE_READ2;
|
|
2468
|
+
const carry = parse_carry(raw);
|
|
2469
|
+
if (carry === void 0) return UNREADABLE_READ3;
|
|
2470
|
+
return { kind: is_expired2(carry, now) ? "expired" : "carried", carry };
|
|
2313
2471
|
}
|
|
2314
|
-
function
|
|
2315
|
-
|
|
2316
|
-
if (owner !== void 0 && process_identity.is_own_process(owner.pid, owner.process_start)) {
|
|
2317
|
-
stamp_file.remove_stamp(target);
|
|
2318
|
-
}
|
|
2472
|
+
function read_carry(target, now = /* @__PURE__ */ new Date()) {
|
|
2473
|
+
return classify3(stamp_file.read_stamp_text(target), now);
|
|
2319
2474
|
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
while (!claim(target)) {
|
|
2323
|
-
if (Date.now() >= deadline) return false;
|
|
2324
|
-
await sleep(POLL_INTERVAL_MS);
|
|
2325
|
-
}
|
|
2326
|
-
return true;
|
|
2475
|
+
function owner_of(pid, read2 = process_identity.read_start) {
|
|
2476
|
+
return { pid, start: read2(pid) };
|
|
2327
2477
|
}
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2478
|
+
function fresh_carry(invocation, owner, now) {
|
|
2479
|
+
return {
|
|
2480
|
+
invocation,
|
|
2481
|
+
started_at: now.toISOString(),
|
|
2482
|
+
merged: NO_INCREMENT3,
|
|
2483
|
+
filed: NO_INCREMENT3,
|
|
2484
|
+
cuts: NO_INCREMENT3,
|
|
2485
|
+
failures: NO_INCREMENT3,
|
|
2486
|
+
outages: NO_INCREMENT3,
|
|
2487
|
+
owner_pid: owner.pid,
|
|
2488
|
+
owner_start: owner.start
|
|
2489
|
+
};
|
|
2335
2490
|
}
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
var WORKTREE = "worktree";
|
|
2340
|
-
var WORKTREE_LOCK_PREFIX = "josh-worktree-lock-";
|
|
2341
|
-
var WORKTREE_LOCK_MAX_WAIT_MS = 12e4;
|
|
2342
|
-
async function locked(arguments_) {
|
|
2343
|
-
const target = repository_lock.lock_path(WORKTREE_LOCK_PREFIX);
|
|
2344
|
-
const output = await repository_lock.with_lock(
|
|
2345
|
-
async () => await git_spawn.read(arguments_),
|
|
2346
|
-
target,
|
|
2347
|
-
WORKTREE_LOCK_MAX_WAIT_MS
|
|
2348
|
-
);
|
|
2349
|
-
if (output === void 0) {
|
|
2350
|
-
throw new Error(
|
|
2351
|
-
`git ${arguments_.join(" ")}: timed out waiting for the work-tree lock ${target}`
|
|
2352
|
-
);
|
|
2353
|
-
}
|
|
2354
|
-
return output;
|
|
2491
|
+
function begin_carry(target, invocation, owner = NO_OWNER, now = /* @__PURE__ */ new Date()) {
|
|
2492
|
+
const carry = fresh_carry(invocation, owner, now);
|
|
2493
|
+
return stamp_file.create_stamp(target, carry) ? carry : void 0;
|
|
2355
2494
|
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2495
|
+
function replace_carry(target, invocation, owner = NO_OWNER, now = /* @__PURE__ */ new Date()) {
|
|
2496
|
+
stamp_file.remove_stamp(target);
|
|
2497
|
+
return begin_carry(target, invocation, owner, now);
|
|
2358
2498
|
}
|
|
2359
|
-
|
|
2360
|
-
const
|
|
2361
|
-
|
|
2499
|
+
function adopt_carry(target, carry, owner = NO_OWNER) {
|
|
2500
|
+
const next = {
|
|
2501
|
+
...carry,
|
|
2502
|
+
owner_pid: owner.pid,
|
|
2503
|
+
owner_start: owner.start,
|
|
2504
|
+
is_handed_off: false
|
|
2505
|
+
};
|
|
2506
|
+
stamp_file.remove_stamp(target);
|
|
2507
|
+
return stamp_file.create_stamp(target, next) ? next : void 0;
|
|
2362
2508
|
}
|
|
2363
|
-
|
|
2364
|
-
return
|
|
2509
|
+
function is_owner_live(carry) {
|
|
2510
|
+
return process_identity.is_same_process(carry.owner_pid, carry.owner_start) !== false;
|
|
2365
2511
|
}
|
|
2366
|
-
|
|
2367
|
-
return
|
|
2512
|
+
function is_owned_by(carry, owner) {
|
|
2513
|
+
return carry.owner_pid === owner.pid && carry.owner_start === owner.start;
|
|
2368
2514
|
}
|
|
2369
|
-
|
|
2370
|
-
return
|
|
2515
|
+
function is_foreign_live_owner(carry, owner) {
|
|
2516
|
+
return is_owner_live(carry) && !is_owned_by(carry, owner);
|
|
2371
2517
|
}
|
|
2372
|
-
|
|
2373
|
-
return
|
|
2518
|
+
function is_handed_off_to(carry, invocation) {
|
|
2519
|
+
return carry.is_handed_off === true && carry.invocation === invocation;
|
|
2374
2520
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2521
|
+
function classify_claim(carry, request) {
|
|
2522
|
+
if (is_handed_off_to(carry, request.invocation)) return "resume";
|
|
2523
|
+
if (is_foreign_live_owner(carry, request.owner)) return "busy";
|
|
2524
|
+
if (carry.invocation !== request.invocation) return "mismatch";
|
|
2525
|
+
return request.is_adoption ? "resume" : "standing";
|
|
2377
2526
|
}
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
ls_remote_branch,
|
|
2381
|
-
worktree_add,
|
|
2382
|
-
worktree_add_detached,
|
|
2383
|
-
worktree_list,
|
|
2384
|
-
worktree_prune,
|
|
2385
|
-
worktree_remove
|
|
2386
|
-
};
|
|
2387
|
-
|
|
2388
|
-
// scripts/lane/lane-environment.ts
|
|
2389
|
-
var LANE_OUTPUT_KEY = "JOSH_LANE_OUTPUT";
|
|
2390
|
-
var LANE_PROVIDER_KEY = "JOSH_LANE_AGENT_PROVIDER";
|
|
2391
|
-
var LANE_ROLE_KEY = "JOSH_LANE_AGENT_ROLE";
|
|
2392
|
-
var LANE_MODEL_KEY = "JOSH_LANE_AGENT_MODEL";
|
|
2393
|
-
var LANE_EFFORT_KEY = "JOSH_LANE_AGENT_EFFORT";
|
|
2394
|
-
var ASSIGNMENT_SEPARATOR = "=";
|
|
2395
|
-
var EXPORT_PREFIX = "export ";
|
|
2396
|
-
var QUOTE_CHARACTERS = /* @__PURE__ */ new Set(['"', "'"]);
|
|
2397
|
-
var MIN_QUOTED_LENGTH = 2;
|
|
2398
|
-
var FIRST_CHARACTER_END = 1;
|
|
2399
|
-
var LAST_CHARACTER_START = -1;
|
|
2400
|
-
function strip_export(line) {
|
|
2401
|
-
const trimmed2 = line.trimStart();
|
|
2402
|
-
return trimmed2.startsWith(EXPORT_PREFIX) ? trimmed2.slice(EXPORT_PREFIX.length).trimStart() : trimmed2;
|
|
2527
|
+
function is_count_refused(carry, owner) {
|
|
2528
|
+
return carry.is_handed_off === true || is_foreign_live_owner(carry, owner);
|
|
2403
2529
|
}
|
|
2404
|
-
function
|
|
2405
|
-
|
|
2406
|
-
if (!body.startsWith(key)) return false;
|
|
2407
|
-
return body.slice(key.length).trimStart().startsWith(ASSIGNMENT_SEPARATOR);
|
|
2530
|
+
function is_at_cut_cap(carry) {
|
|
2531
|
+
return carry.cuts >= MAX_CUTS;
|
|
2408
2532
|
}
|
|
2409
|
-
function
|
|
2410
|
-
|
|
2533
|
+
function end_carry(target) {
|
|
2534
|
+
stamp_file.remove_stamp(target);
|
|
2411
2535
|
}
|
|
2412
|
-
function
|
|
2413
|
-
|
|
2536
|
+
function retrospective_done_of(read2) {
|
|
2537
|
+
if (read2.kind !== "carried" && read2.kind !== "expired") return false;
|
|
2538
|
+
return read2.carry.retrospective === true;
|
|
2414
2539
|
}
|
|
2415
|
-
function
|
|
2416
|
-
|
|
2540
|
+
function remaining_of(carry) {
|
|
2541
|
+
if (carry === void 0) return void 0;
|
|
2542
|
+
const declared = run_invocation.issue_numbers(carry.invocation);
|
|
2543
|
+
if (declared === void 0) return void 0;
|
|
2544
|
+
const done = carry.done ?? [];
|
|
2545
|
+
return declared.filter((issue) => !done.includes(issue));
|
|
2417
2546
|
}
|
|
2418
|
-
function
|
|
2419
|
-
const
|
|
2420
|
-
return
|
|
2547
|
+
function done_note(carry) {
|
|
2548
|
+
const done = carry.done ?? [];
|
|
2549
|
+
return done.length === 0 ? "" : `, issues ${done.join(", ")} done`;
|
|
2421
2550
|
}
|
|
2422
|
-
function
|
|
2423
|
-
|
|
2424
|
-
if (!QUOTE_CHARACTERS.has(first)) return false;
|
|
2425
|
-
return raw.length >= MIN_QUOTED_LENGTH && raw.endsWith(first);
|
|
2551
|
+
function describe_carry(carry) {
|
|
2552
|
+
return `${carry.invocation} started ${carry.started_at}; ${String(carry.merged)} merged, ${String(carry.filed)} filed, ${String(carry.failures)} failed in a row, ${String(carry.outages)} outage(s) in a row, ${String(carry.cuts)} cut(s) crossed${done_note(carry)}`;
|
|
2426
2553
|
}
|
|
2427
|
-
function
|
|
2428
|
-
return
|
|
2554
|
+
function expired_message(carry) {
|
|
2555
|
+
return `The ${String(CARRY_MAX_AGE_HOURS)}-hour whole-run bound is spent: ${describe_carry(carry)}. Clear it with \`${END_COMMAND2}\`.`;
|
|
2429
2556
|
}
|
|
2430
|
-
function
|
|
2431
|
-
return
|
|
2557
|
+
function mismatch_message(carry, invocation) {
|
|
2558
|
+
return `A different invocation is carried here \u2014 ${describe_carry(carry)}. This one is \`${invocation}\`. End the standing record with \`${END_COMMAND2}\` once you know its run is over, then begin again.`;
|
|
2432
2559
|
}
|
|
2433
|
-
function
|
|
2434
|
-
|
|
2435
|
-
return line === void 0 ? void 0 : assignment_value(line);
|
|
2560
|
+
function busy_message2(carry) {
|
|
2561
|
+
return `A live run holds this budget \u2014 ${describe_carry(carry)}, owner pid ${String(carry.owner_pid)} still running. Nothing was established. Wait for that run, or end its record with \`${END_COMMAND2}\` once you know it is over.`;
|
|
2436
2562
|
}
|
|
2437
|
-
function
|
|
2438
|
-
return
|
|
2563
|
+
function standing_message(carry) {
|
|
2564
|
+
return `A run record is standing here that no cut handed off \u2014 ${describe_carry(carry)}. Nothing was established. Carry that budget with \`${RESUME_COMMAND} "${carry.invocation}" ${OWNER_ARGUMENT}\`, or discard it with \`${END_COMMAND2}\` and begin again.`;
|
|
2439
2565
|
}
|
|
2440
|
-
function
|
|
2441
|
-
|
|
2442
|
-
|
|
2566
|
+
function count_refused_message(carry) {
|
|
2567
|
+
if (carry.is_handed_off === true) {
|
|
2568
|
+
return `This budget was handed off at a cut and is waiting for its successor \u2014 ${describe_carry(carry)}. Nothing was counted; the cutting session must not advance a handed-off budget.`;
|
|
2569
|
+
}
|
|
2570
|
+
return `A live run owns this budget \u2014 ${describe_carry(carry)}, owner pid ${String(carry.owner_pid)} still running. Nothing was counted; only its owner advances the budget.`;
|
|
2443
2571
|
}
|
|
2444
|
-
function
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2572
|
+
function lost_message() {
|
|
2573
|
+
return `Another process established a run record here first, so nothing was established. Read it with \`${READ_COMMAND2}\`.`;
|
|
2574
|
+
}
|
|
2575
|
+
function nothing_to_resume_message() {
|
|
2576
|
+
return `Nothing is carried here, so there is no budget to resume. Begin one with \`pnpm josh run:carry --begin "<invocation>"\`.`;
|
|
2577
|
+
}
|
|
2578
|
+
function unreadable_message3() {
|
|
2579
|
+
return `A run record is here but could not be read; clear it with \`${END_COMMAND2}\` once you know no run is using it.`;
|
|
2580
|
+
}
|
|
2581
|
+
function unknown_message3() {
|
|
2582
|
+
return "This repository\u2019s git directory could not be read, so no run record was established.";
|
|
2583
|
+
}
|
|
2584
|
+
var run_carry = {
|
|
2585
|
+
CARRY_MAX_AGE_HOURS,
|
|
2586
|
+
CARRY_MAX_AGE_MS,
|
|
2587
|
+
END_COMMAND: END_COMMAND2,
|
|
2588
|
+
MAX_CUTS,
|
|
2589
|
+
NO_OWNER,
|
|
2590
|
+
RESUME_COMMAND,
|
|
2591
|
+
adopt_carry,
|
|
2592
|
+
apply_change: run_carry_change.apply_change,
|
|
2593
|
+
begin_carry,
|
|
2594
|
+
busy_message: busy_message2,
|
|
2595
|
+
carry_path,
|
|
2596
|
+
classify: classify3,
|
|
2597
|
+
classify_claim,
|
|
2598
|
+
count_refused_message,
|
|
2599
|
+
is_at_cut_cap,
|
|
2600
|
+
describe_carry,
|
|
2601
|
+
end_carry,
|
|
2602
|
+
expired_message,
|
|
2603
|
+
mismatch_message,
|
|
2604
|
+
fresh_carry,
|
|
2605
|
+
is_count_refused,
|
|
2606
|
+
is_expired: is_expired2,
|
|
2607
|
+
is_foreign_live_owner,
|
|
2608
|
+
is_owner_live,
|
|
2609
|
+
lost_message,
|
|
2610
|
+
nothing_to_resume_message,
|
|
2611
|
+
owner_of,
|
|
2612
|
+
parse_carry,
|
|
2613
|
+
read_carry,
|
|
2614
|
+
remaining_of,
|
|
2615
|
+
replace_carry,
|
|
2616
|
+
repository_directory,
|
|
2617
|
+
retrospective_done_of,
|
|
2618
|
+
standing_message,
|
|
2619
|
+
unknown_message: unknown_message3,
|
|
2620
|
+
unreadable_message: unreadable_message3
|
|
2621
|
+
};
|
|
2622
|
+
|
|
2623
|
+
// scripts/run/run-ship-detach.ts
|
|
2624
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
2625
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
2626
|
+
import { z as z8 } from "zod";
|
|
2627
|
+
|
|
2628
|
+
// scripts/run/detached-launch.ts
|
|
2629
|
+
import { spawn } from "node:child_process";
|
|
2630
|
+
import { closeSync, constants, openSync, writeSync } from "node:fs";
|
|
2631
|
+
|
|
2632
|
+
// scripts/agent/agent-launch-environment.ts
|
|
2633
|
+
import { existsSync, lstatSync, mkdirSync, readlinkSync, symlinkSync, unlinkSync } from "node:fs";
|
|
2634
|
+
import path3 from "node:path";
|
|
2635
|
+
|
|
2636
|
+
// scripts/gh/gh-cli-token.ts
|
|
2637
|
+
import { execaSync } from "execa";
|
|
2638
|
+
var GH_CLI_TIMEOUT_MS = 5e3;
|
|
2639
|
+
function get() {
|
|
2640
|
+
try {
|
|
2641
|
+
const { stdout } = execaSync("gh", ["auth", "token"], { timeout: GH_CLI_TIMEOUT_MS });
|
|
2642
|
+
const token = stdout.trim();
|
|
2643
|
+
return token.length > 0 ? token : void 0;
|
|
2644
|
+
} catch {
|
|
2645
|
+
return void 0;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
var gh_cli_token = { get };
|
|
2649
|
+
|
|
2650
|
+
// scripts/agent/codex-home-source.ts
|
|
2651
|
+
import os from "node:os";
|
|
2652
|
+
import path2 from "node:path";
|
|
2653
|
+
function default_home() {
|
|
2654
|
+
return path2.join(os.homedir(), ".codex");
|
|
2655
|
+
}
|
|
2656
|
+
var codex_home_source = { default_home };
|
|
2657
|
+
|
|
2658
|
+
// scripts/agent/agent-launch-environment.ts
|
|
2659
|
+
var OPENAI_PROVIDER2 = "openai";
|
|
2660
|
+
var REVIEWER_HOME = ["node_modules", ".cache", "josh", "openai", "reviewer-home"];
|
|
2661
|
+
var HOME_FILES = ["auth.json", "config.toml"];
|
|
2662
|
+
var PRIVATE_DIRECTORY_MODE = 448;
|
|
2663
|
+
function openai_environment() {
|
|
2664
|
+
const token = gh_cli_token.get();
|
|
2665
|
+
return token === void 0 ? { TMPDIR: PLATFORM_TEMP_ROOT } : { GH_TOKEN: token, TMPDIR: PLATFORM_TEMP_ROOT };
|
|
2666
|
+
}
|
|
2667
|
+
function remove_old_home_link(source, target) {
|
|
2668
|
+
const current = lstatSync(target, { throwIfNoEntry: false });
|
|
2669
|
+
if (current === void 0) return false;
|
|
2670
|
+
if (!current.isSymbolicLink()) throw new Error(`Reviewer home file is not a link: ${target}`);
|
|
2671
|
+
if (existsSync(source) && readlinkSync(target) === source) return true;
|
|
2672
|
+
unlinkSync(target);
|
|
2673
|
+
return false;
|
|
2674
|
+
}
|
|
2675
|
+
function link_home_file(source_home, target_home, name) {
|
|
2676
|
+
const source = path3.join(source_home, name);
|
|
2677
|
+
const target = path3.join(target_home, name);
|
|
2678
|
+
if (!remove_old_home_link(source, target) && existsSync(source)) symlinkSync(source, target);
|
|
2679
|
+
}
|
|
2680
|
+
function reviewer_home(cwd, environment2) {
|
|
2681
|
+
const source = environment2["CODEX_HOME"] ?? process.env["CODEX_HOME"] ?? codex_home_source.default_home();
|
|
2682
|
+
const target = path3.resolve(cwd, ...REVIEWER_HOME);
|
|
2683
|
+
mkdirSync(target, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
2684
|
+
for (const name of HOME_FILES) link_home_file(source, target, name);
|
|
2685
|
+
return target;
|
|
2686
|
+
}
|
|
2687
|
+
function build(cwd, profile, environment2 = {}) {
|
|
2688
|
+
if (profile?.provider !== OPENAI_PROVIDER2) return environment2;
|
|
2689
|
+
const base = { ...openai_environment(), ...environment2 };
|
|
2690
|
+
return profile.role === agent_role_profile.REVIEWER ? { ...base, CODEX_HOME: reviewer_home(cwd, environment2) } : base;
|
|
2691
|
+
}
|
|
2692
|
+
var agent_launch_environment = { build };
|
|
2693
|
+
|
|
2694
|
+
// scripts/run/detached-launch.ts
|
|
2695
|
+
var NO_PID_NOTE = "the process started without a pid";
|
|
2696
|
+
var UNSAFE_NOTE = "the wake command or its arguments contain characters that are not safe to execute";
|
|
2697
|
+
var { is_safe_value: is_safe_value2 } = agent_role_profile;
|
|
2698
|
+
function is_safe_argv(argv) {
|
|
2699
|
+
return is_safe_value2(argv.command) && argv.args.every((value) => is_safe_value2(value));
|
|
2700
|
+
}
|
|
2701
|
+
function note_of(error) {
|
|
2702
|
+
return error instanceof Error ? error.message : JSON.stringify(error);
|
|
2703
|
+
}
|
|
2704
|
+
function launched(pid) {
|
|
2705
|
+
return { kind: "launched", pid };
|
|
2706
|
+
}
|
|
2707
|
+
var LOG_FLAGS = constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW;
|
|
2708
|
+
var LOG_MODE = 384;
|
|
2709
|
+
function profile_suffix(profile) {
|
|
2710
|
+
return profile === void 0 ? "" : ` \xB7 ${agent_role_profile.describe(profile)}`;
|
|
2711
|
+
}
|
|
2712
|
+
function log_header(argv, profile) {
|
|
2713
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2714
|
+
return `
|
|
2715
|
+
=== ${stamp} \xB7 started by process ${String(process.pid)} \xB7 ${argv.command}${profile_suffix(profile)} ===
|
|
2716
|
+
`;
|
|
2717
|
+
}
|
|
2718
|
+
function opened_log(log_path2, on_error) {
|
|
2719
|
+
const descriptor = openSync(log_path2, LOG_FLAGS, LOG_MODE);
|
|
2720
|
+
if (!stamp_file.is_own_regular_file(log_path2)) {
|
|
2721
|
+
closeSync(descriptor);
|
|
2722
|
+
on_error(`${log_path2} is not this account's own file, so nothing is kept there`);
|
|
2723
|
+
return void 0;
|
|
2724
|
+
}
|
|
2725
|
+
return descriptor;
|
|
2726
|
+
}
|
|
2727
|
+
function stamped(descriptor, argv, profile, on_error) {
|
|
2728
|
+
if (descriptor === void 0) return;
|
|
2729
|
+
try {
|
|
2730
|
+
writeSync(descriptor, log_header(argv, profile));
|
|
2731
|
+
} catch (error) {
|
|
2732
|
+
on_error(`the session log could not be written: ${note_of(error)}`);
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
function open_log(log_path2, on_error) {
|
|
2736
|
+
if (log_path2 === void 0) return void 0;
|
|
2737
|
+
try {
|
|
2738
|
+
return opened_log(log_path2, on_error);
|
|
2739
|
+
} catch (error) {
|
|
2740
|
+
on_error(`the session log at ${log_path2} could not be opened: ${note_of(error)}`);
|
|
2741
|
+
return void 0;
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
function ensure_log(log_path2, on_error) {
|
|
2745
|
+
const descriptor = open_log(log_path2, on_error);
|
|
2746
|
+
if (descriptor !== void 0) closeSync(descriptor);
|
|
2747
|
+
}
|
|
2748
|
+
function spawn_options(cwd, log, environment2 = {}, is_detached = true) {
|
|
2449
2749
|
return {
|
|
2450
|
-
|
|
2451
|
-
|
|
2750
|
+
cwd,
|
|
2751
|
+
detached: is_detached,
|
|
2752
|
+
stdio: log === void 0 ? "ignore" : ["ignore", log, log],
|
|
2753
|
+
env: { ...process.env, ...agent_session_environment.removed_environment(), ...environment2 }
|
|
2452
2754
|
};
|
|
2453
2755
|
}
|
|
2454
|
-
function
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2756
|
+
function notify_spawn(pid, on_spawn, on_error) {
|
|
2757
|
+
if (pid === void 0) return;
|
|
2758
|
+
try {
|
|
2759
|
+
on_spawn(pid);
|
|
2760
|
+
} catch (error) {
|
|
2761
|
+
on_error(`the child state could not be recorded: ${note_of(error)}`);
|
|
2762
|
+
}
|
|
2458
2763
|
}
|
|
2459
|
-
function
|
|
2460
|
-
return
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2764
|
+
async function attached_spawn(request, log, on_error, on_spawn) {
|
|
2765
|
+
return await new Promise((resolve3) => {
|
|
2766
|
+
const environment2 = agent_launch_environment.build(request.cwd, request.profile, request.env);
|
|
2767
|
+
const child = spawn(
|
|
2768
|
+
request.argv.command,
|
|
2769
|
+
[...request.argv.args],
|
|
2770
|
+
spawn_options(request.cwd, log, environment2, false)
|
|
2771
|
+
);
|
|
2772
|
+
child.once("error", (error) => {
|
|
2773
|
+
on_error(note_of(error));
|
|
2774
|
+
resolve3({ kind: "failed", note: note_of(error) });
|
|
2775
|
+
});
|
|
2776
|
+
child.once("exit", (exit_code) => {
|
|
2777
|
+
resolve3({ kind: "completed", pid: child.pid ?? 0, exit_code });
|
|
2778
|
+
});
|
|
2779
|
+
notify_spawn(child.pid, on_spawn, on_error);
|
|
2465
2780
|
});
|
|
2466
2781
|
}
|
|
2467
|
-
function
|
|
2468
|
-
return lines.flatMap((entry, index) => {
|
|
2469
|
-
if (index === keep) return [assignment];
|
|
2470
|
-
return is_key_line(entry, key) ? [] : [entry];
|
|
2471
|
-
});
|
|
2782
|
+
function ignore_spawn(_pid) {
|
|
2472
2783
|
}
|
|
2473
|
-
function
|
|
2474
|
-
const
|
|
2475
|
-
const
|
|
2476
|
-
const
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2784
|
+
function spawned(request, log, on_error) {
|
|
2785
|
+
const { command, args } = request.argv;
|
|
2786
|
+
const environment2 = agent_launch_environment.build(request.cwd, request.profile, request.env);
|
|
2787
|
+
const child = spawn(command, [...args], spawn_options(request.cwd, log, environment2));
|
|
2788
|
+
child.on("error", (error) => {
|
|
2789
|
+
on_error(note_of(error));
|
|
2790
|
+
});
|
|
2791
|
+
child.unref();
|
|
2792
|
+
return child.pid === void 0 ? { kind: "failed", note: NO_PID_NOTE } : launched(child.pid);
|
|
2480
2793
|
}
|
|
2481
|
-
function
|
|
2482
|
-
|
|
2794
|
+
function launch(request, on_error) {
|
|
2795
|
+
if (!is_safe_argv(request.argv)) return { kind: "failed", note: UNSAFE_NOTE };
|
|
2796
|
+
const log = open_log(request.log_path, on_error);
|
|
2797
|
+
try {
|
|
2798
|
+
stamped(log, request.argv, request.profile, on_error);
|
|
2799
|
+
return spawned(request, log, on_error);
|
|
2800
|
+
} catch (error) {
|
|
2801
|
+
return { kind: "failed", note: note_of(error) };
|
|
2802
|
+
} finally {
|
|
2803
|
+
if (log !== void 0) closeSync(log);
|
|
2804
|
+
}
|
|
2483
2805
|
}
|
|
2484
|
-
function
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2806
|
+
async function launch_attached(request, on_error, on_spawn = ignore_spawn) {
|
|
2807
|
+
if (!is_safe_argv(request.argv)) return { kind: "failed", note: UNSAFE_NOTE };
|
|
2808
|
+
const log = open_log(request.log_path, on_error);
|
|
2809
|
+
try {
|
|
2810
|
+
stamped(log, request.argv, request.profile, on_error);
|
|
2811
|
+
return await attached_spawn(request, log, on_error, on_spawn);
|
|
2812
|
+
} catch (error) {
|
|
2813
|
+
return { kind: "failed", note: note_of(error) };
|
|
2814
|
+
} finally {
|
|
2815
|
+
if (log !== void 0) closeSync(log);
|
|
2816
|
+
}
|
|
2491
2817
|
}
|
|
2492
|
-
var
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
read_lane_profile,
|
|
2502
|
-
read_lane_ports,
|
|
2503
|
-
read_lane_seat,
|
|
2504
|
-
read_root_seed,
|
|
2505
|
-
with_lane_output
|
|
2818
|
+
var detached_launch = {
|
|
2819
|
+
UNSAFE_NOTE,
|
|
2820
|
+
ensure_log,
|
|
2821
|
+
is_safe_argv,
|
|
2822
|
+
is_safe_value: is_safe_value2,
|
|
2823
|
+
launch,
|
|
2824
|
+
launch_attached,
|
|
2825
|
+
log_header,
|
|
2826
|
+
note_of
|
|
2506
2827
|
};
|
|
2507
2828
|
|
|
2508
|
-
// scripts/
|
|
2509
|
-
|
|
2510
|
-
var
|
|
2511
|
-
var
|
|
2512
|
-
var
|
|
2513
|
-
|
|
2514
|
-
|
|
2829
|
+
// scripts/run/run-event-stream.ts
|
|
2830
|
+
import { z as z7 } from "zod";
|
|
2831
|
+
var EVENT_PREFIX = "josh-run-events-";
|
|
2832
|
+
var EVENT_SUFFIX = ".jsonl";
|
|
2833
|
+
var EVENT_CAP = 500;
|
|
2834
|
+
var FIRST_POSITION = 0;
|
|
2835
|
+
var POSITION_INCREMENT = 1;
|
|
2836
|
+
var LINE_SEPARATOR = "\n";
|
|
2837
|
+
var EVENT_KIND = {
|
|
2838
|
+
PLAN: "plan",
|
|
2839
|
+
CHILD_LAUNCH: "child-launch",
|
|
2840
|
+
MERGE: "merge",
|
|
2841
|
+
PARK: "park",
|
|
2842
|
+
SPLIT: "split",
|
|
2843
|
+
OUTAGE: "outage",
|
|
2844
|
+
CUT: "cut",
|
|
2845
|
+
// The backlog emptied while nothing of the run's own was in flight — the drain
|
|
2846
|
+
// (joshuafolkken/kit#2335). It marks the position at which the end-of-run retrospective is owed,
|
|
2847
|
+
// *before* the idle watch opens, so `run:step` fires the retrospective at the drain rather than after
|
|
2848
|
+
// the watch runs its course. It is not itself a stop: the run watches on once the retrospective has
|
|
2849
|
+
// run, and the real `STOP` follows when the watch expires.
|
|
2850
|
+
DRAIN: "drain",
|
|
2851
|
+
STOP: "stop",
|
|
2852
|
+
PR_OPENED: "pr-opened",
|
|
2853
|
+
REVIEW_ROUND: "review-round",
|
|
2854
|
+
// The end-of-run retrospective's result, recorded when the run marks the retrospective done
|
|
2855
|
+
// (joshuafolkken/kit#2342). A retrospective that files zero improvements and one that never ran look
|
|
2856
|
+
// the same from outside — no new Issue either way — so the result is put on the stream the report is
|
|
2857
|
+
// generated from: the issues filed (or that none were), and the candidates dropped with why. It is
|
|
2858
|
+
// emitted from the `run:carry --retrospective` close, so marking the retrospective done and recording
|
|
2859
|
+
// what it found are one action rather than two the run could do only one of.
|
|
2860
|
+
RETROSPECTIVE: "retrospective",
|
|
2861
|
+
// Ready backlog work is sitting undispatched while a lane is free and nothing has dispatched for a
|
|
2862
|
+
// while (joshuafolkken/kit#2359). Emitted once per stall episode by the stop-time detector, it is
|
|
2863
|
+
// both the dedup marker — `emit_once_since` refuses a second until a `CHILD_LAUNCH` intervenes
|
|
2864
|
+
// (joshuafolkken/kit#2464) — and the line a
|
|
2865
|
+
// terminal reader following the stream sees. `run:step` reads it as `backlog:next`, so a run that
|
|
2866
|
+
// stalled is pointed straight at dispatching the work rather than left waiting.
|
|
2867
|
+
STALL: "stall",
|
|
2868
|
+
// The run's own driver is gone: the cut handed the budget off, the owner has died, and no supervisor
|
|
2869
|
+
// is watching (joshuafolkken/kit#2375). Emitted once per strand episode by the stop-time detector,
|
|
2870
|
+
// exactly as `STALL` is — the newest-event dedup keeps a run polled every stop from notifying more
|
|
2871
|
+
// than once, and a terminal reader following the stream sees the line. The strand is the step before
|
|
2872
|
+
// the stall: a stalled run still has a driver that could dispatch, a stranded one has none.
|
|
2873
|
+
STRANDED: "stranded",
|
|
2874
|
+
// One `josh ship` stage starting, succeeding or failing (joshuafolkken/kit#2426). It is a trace of the
|
|
2875
|
+
// composite's progress rather than a position the run is at — the positions a ship leaves behind are
|
|
2876
|
+
// the closed issue its `followup` merges, or a detached supervisor's `SHIP_LAUNCH` / `SHIP_STOP` below
|
|
2877
|
+
// — so it is one of the `TRACE_KINDS` the last-event read skips.
|
|
2878
|
+
SHIP_STAGE: "ship-stage",
|
|
2879
|
+
// One progress watcher line — the `at … / next …` heartbeat `run:progress` prints
|
|
2880
|
+
// (joshuafolkken/kit#2437). Printed only to the watcher's own output, a headless successor's heartbeat
|
|
2881
|
+
// was buried in its log after a cut; on the stream it reaches the attached session's relay. It says
|
|
2882
|
+
// the run is alive rather than where it is, so it is a trace kind like `SHIP_STAGE`.
|
|
2883
|
+
HEARTBEAT: "heartbeat",
|
|
2884
|
+
// The post-implementation region handed to a detached `josh ship --detach` supervisor
|
|
2885
|
+
// (joshuafolkken/kit#2428). Unlike a stage trace it is a position: the agent has ended and the
|
|
2886
|
+
// supervisor carries the run, so `run:step` answers `wait` until it stops or the issue closes.
|
|
2887
|
+
SHIP_LAUNCH: "ship-launch",
|
|
2888
|
+
// The supervisor stopped at a failed stage — a red gate, a High/Medium review, a failed push, red CI
|
|
2889
|
+
// (joshuafolkken/kit#2428). The position that hands control back: `run:step` prints the command that
|
|
2890
|
+
// shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
|
|
2891
|
+
SHIP_STOP: "ship-stop"
|
|
2892
|
+
};
|
|
2893
|
+
var EVENT_KINDS = Object.values(EVENT_KIND);
|
|
2894
|
+
var TRACE_KINDS = /* @__PURE__ */ new Set([EVENT_KIND.SHIP_STAGE, EVENT_KIND.HEARTBEAT]);
|
|
2895
|
+
var event_schema = z7.object({
|
|
2896
|
+
pos: z7.number(),
|
|
2897
|
+
at: z7.string(),
|
|
2898
|
+
kind: z7.string(),
|
|
2899
|
+
text: z7.string()
|
|
2900
|
+
});
|
|
2901
|
+
function is_event_kind(value) {
|
|
2902
|
+
return EVENT_KINDS.includes(value);
|
|
2515
2903
|
}
|
|
2516
|
-
function
|
|
2517
|
-
|
|
2518
|
-
if (seat === void 0) return void 0;
|
|
2519
|
-
const port_pair = lane_environment.read_lane_ports(content);
|
|
2520
|
-
return { seat, development_port: port_pair.development, preview_port: port_pair.preview };
|
|
2904
|
+
function target_of(repository2) {
|
|
2905
|
+
return stamp_file.stamp_path(EVENT_PREFIX, repository2, EVENT_SUFFIX);
|
|
2521
2906
|
}
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
development_port: void 0,
|
|
2525
|
-
preview_port: void 0
|
|
2526
|
-
};
|
|
2527
|
-
function held_seat(content) {
|
|
2528
|
-
if (content === void 0) return EMPTY_SEAT;
|
|
2529
|
-
return seat_from_content(content) ?? EMPTY_SEAT;
|
|
2907
|
+
function is_present(event) {
|
|
2908
|
+
return event !== void 0;
|
|
2530
2909
|
}
|
|
2531
|
-
function
|
|
2532
|
-
return
|
|
2910
|
+
function parse_line(line) {
|
|
2911
|
+
return event_schema.safeParse(json_value.parse_or_undefined(line)).data;
|
|
2533
2912
|
}
|
|
2534
|
-
function
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
return
|
|
2913
|
+
function read_events(target) {
|
|
2914
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
2915
|
+
if (raw === void 0) return [];
|
|
2916
|
+
return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line(line)).filter(is_present);
|
|
2538
2917
|
}
|
|
2539
|
-
function
|
|
2540
|
-
return
|
|
2918
|
+
function last_position(events) {
|
|
2919
|
+
return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
|
|
2541
2920
|
}
|
|
2542
|
-
function
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2921
|
+
function serialize(events) {
|
|
2922
|
+
return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
|
|
2923
|
+
}
|
|
2924
|
+
function append(target, kind, text, at) {
|
|
2925
|
+
if (!is_event_kind(kind)) return { appended: false, position: FIRST_POSITION };
|
|
2926
|
+
const existing = read_events(target);
|
|
2927
|
+
const position = last_position(existing) + POSITION_INCREMENT;
|
|
2928
|
+
const bounded = [...existing, { pos: position, at, kind, text }].slice(-EVENT_CAP);
|
|
2929
|
+
stamp_file.write_text_stamp(target, serialize(bounded));
|
|
2930
|
+
return { appended: true, position };
|
|
2931
|
+
}
|
|
2932
|
+
function read_from(target, position) {
|
|
2933
|
+
const events = read_events(target);
|
|
2547
2934
|
return {
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
directory,
|
|
2551
|
-
seat: held.seat,
|
|
2552
|
-
development_port: held.development_port,
|
|
2553
|
-
preview_port: held.preview_port,
|
|
2554
|
-
output,
|
|
2555
|
-
profile,
|
|
2556
|
-
is_stranded
|
|
2935
|
+
events: events.filter((event) => event.pos > position),
|
|
2936
|
+
next_position: last_position(events)
|
|
2557
2937
|
};
|
|
2558
2938
|
}
|
|
2559
|
-
function
|
|
2560
|
-
return
|
|
2939
|
+
function read_last(target) {
|
|
2940
|
+
return read_events(target).findLast((event) => !TRACE_KINDS.has(event.kind));
|
|
2941
|
+
}
|
|
2942
|
+
function has_since(events, kind, reset_kind) {
|
|
2943
|
+
const reset_at = events.findLastIndex((event) => event.kind === reset_kind);
|
|
2944
|
+
return events.slice(reset_at + POSITION_INCREMENT).some((event) => event.kind === kind);
|
|
2945
|
+
}
|
|
2946
|
+
var FIELD_SEPARATOR = " \xB7 ";
|
|
2947
|
+
function format_event(event) {
|
|
2948
|
+
return [event.at, event.kind, event.text].join(FIELD_SEPARATOR);
|
|
2949
|
+
}
|
|
2950
|
+
var run_event_stream = {
|
|
2951
|
+
EVENT_CAP,
|
|
2952
|
+
EVENT_KIND,
|
|
2953
|
+
EVENT_KINDS,
|
|
2954
|
+
TRACE_KINDS,
|
|
2955
|
+
append,
|
|
2956
|
+
format_event,
|
|
2957
|
+
has_since,
|
|
2958
|
+
read_events,
|
|
2959
|
+
read_from,
|
|
2960
|
+
read_last,
|
|
2961
|
+
target_of
|
|
2962
|
+
};
|
|
2963
|
+
|
|
2964
|
+
// scripts/run/run-event-scope.ts
|
|
2965
|
+
var SINCE_SCOPE = "since";
|
|
2966
|
+
var UNKNOWN_SCOPE = "unknown";
|
|
2967
|
+
var UNKNOWN_EVENT_SCOPE = { kind: UNKNOWN_SCOPE };
|
|
2968
|
+
function moment_of(at) {
|
|
2969
|
+
const parsed = Date.parse(at);
|
|
2970
|
+
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
2561
2971
|
}
|
|
2562
|
-
function
|
|
2563
|
-
const
|
|
2564
|
-
|
|
2565
|
-
const branch2 = line_value(lines, BRANCH_PREFIX);
|
|
2566
|
-
const issue = branch_issue(branch2);
|
|
2567
|
-
if (directory === void 0 || branch2 === void 0 || issue === void 0) return void 0;
|
|
2568
|
-
if (!is_lane_directory(root, issue, directory)) return void 0;
|
|
2569
|
-
return build_lane(issue, branch2, directory, is_gone(directory));
|
|
2972
|
+
function is_within(event, floor) {
|
|
2973
|
+
const at = moment_of(event.at);
|
|
2974
|
+
return at !== void 0 && at >= floor;
|
|
2570
2975
|
}
|
|
2571
|
-
function
|
|
2572
|
-
|
|
2976
|
+
function scoped_events(events, scope) {
|
|
2977
|
+
if (scope.kind === UNKNOWN_SCOPE) return void 0;
|
|
2978
|
+
const floor = moment_of(scope.started_at);
|
|
2979
|
+
if (floor === void 0) return void 0;
|
|
2980
|
+
return events.filter((event) => is_within(event, floor));
|
|
2573
2981
|
}
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2982
|
+
function scope_of(read2) {
|
|
2983
|
+
if (read2.kind === "carried" || read2.kind === "expired") {
|
|
2984
|
+
return { kind: SINCE_SCOPE, started_at: read2.carry.started_at };
|
|
2985
|
+
}
|
|
2986
|
+
return UNKNOWN_EVENT_SCOPE;
|
|
2577
2987
|
}
|
|
2578
|
-
|
|
2579
|
-
return
|
|
2988
|
+
function last_scoped_event(events, scope) {
|
|
2989
|
+
return scoped_events(events, scope)?.findLast(
|
|
2990
|
+
(event) => !run_event_stream.TRACE_KINDS.has(event.kind)
|
|
2991
|
+
);
|
|
2580
2992
|
}
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2993
|
+
var SHIP_POSITION_KINDS = /* @__PURE__ */ new Set([
|
|
2994
|
+
run_event_stream.EVENT_KIND.SHIP_LAUNCH,
|
|
2995
|
+
run_event_stream.EVENT_KIND.SHIP_STOP
|
|
2996
|
+
]);
|
|
2997
|
+
var KIND = run_event_stream.EVENT_KIND;
|
|
2998
|
+
var BATCH_RECORD_KINDS = /* @__PURE__ */ new Set([
|
|
2999
|
+
KIND.CHILD_LAUNCH,
|
|
3000
|
+
KIND.PARK,
|
|
3001
|
+
KIND.SPLIT,
|
|
3002
|
+
KIND.RETROSPECTIVE,
|
|
3003
|
+
KIND.STRANDED
|
|
3004
|
+
]);
|
|
3005
|
+
var ISSUE_REFERENCE = /#(\d+)/u;
|
|
3006
|
+
function is_foreign_ship_event(event, issue) {
|
|
3007
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !event.text.startsWith(`#${issue} `);
|
|
3008
|
+
}
|
|
3009
|
+
function is_own_ship_event(event, issue) {
|
|
3010
|
+
return SHIP_POSITION_KINDS.has(event.kind) && !is_foreign_ship_event(event, issue);
|
|
3011
|
+
}
|
|
3012
|
+
function names_issue(event, issue) {
|
|
3013
|
+
return ISSUE_REFERENCE.exec(event.text)?.[1] === issue;
|
|
3014
|
+
}
|
|
3015
|
+
function is_lane_position(event, issue) {
|
|
3016
|
+
return !BATCH_RECORD_KINDS.has(event.kind) && names_issue(event, issue);
|
|
3017
|
+
}
|
|
3018
|
+
function since_own_launch(events, issue) {
|
|
3019
|
+
const launch3 = events.findLastIndex(
|
|
3020
|
+
(event) => event.kind === KIND.CHILD_LAUNCH && names_issue(event, issue)
|
|
3021
|
+
);
|
|
3022
|
+
return events.slice(launch3 + 1);
|
|
3023
|
+
}
|
|
3024
|
+
function is_foreign_event(event, issue, is_lane_child) {
|
|
3025
|
+
if (is_lane_child) return !is_lane_position(event, issue);
|
|
3026
|
+
return is_foreign_ship_event(event, issue);
|
|
3027
|
+
}
|
|
3028
|
+
function last_issue_event(events, scope, issue, is_lane_child) {
|
|
3029
|
+
const attempt = is_lane_child ? since_own_launch(events, issue) : events;
|
|
3030
|
+
const own2 = attempt.filter((event) => !is_foreign_event(event, issue, is_lane_child));
|
|
3031
|
+
if (scope.kind === SINCE_SCOPE) return last_scoped_event(own2, scope);
|
|
3032
|
+
return own2.findLast((event) => is_own_ship_event(event, issue));
|
|
3033
|
+
}
|
|
3034
|
+
var run_event_scope = {
|
|
3035
|
+
UNKNOWN_EVENT_SCOPE,
|
|
3036
|
+
last_issue_event,
|
|
3037
|
+
last_scoped_event,
|
|
3038
|
+
scope_of,
|
|
3039
|
+
scoped_events
|
|
3040
|
+
};
|
|
3041
|
+
|
|
3042
|
+
// scripts/run/run-event-stream-emit.ts
|
|
3043
|
+
function now_iso() {
|
|
3044
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
2586
3045
|
}
|
|
2587
|
-
function
|
|
2588
|
-
|
|
3046
|
+
async function stream_target() {
|
|
3047
|
+
const repository2 = await run_carry.repository_directory();
|
|
3048
|
+
return repository2 === void 0 ? void 0 : run_event_stream.target_of(repository2);
|
|
2589
3049
|
}
|
|
2590
|
-
function
|
|
2591
|
-
|
|
3050
|
+
async function emit(kind, text) {
|
|
3051
|
+
try {
|
|
3052
|
+
const target = await stream_target();
|
|
3053
|
+
if (target === void 0) return;
|
|
3054
|
+
run_event_stream.append(target, kind, text, now_iso());
|
|
3055
|
+
} catch {
|
|
3056
|
+
}
|
|
2592
3057
|
}
|
|
2593
|
-
function
|
|
2594
|
-
|
|
3058
|
+
async function emit_once(kind, text) {
|
|
3059
|
+
try {
|
|
3060
|
+
const target = await stream_target();
|
|
3061
|
+
if (target === void 0 || run_event_stream.read_last(target)?.kind === kind) return false;
|
|
3062
|
+
return run_event_stream.append(target, kind, text, now_iso()).appended;
|
|
3063
|
+
} catch {
|
|
3064
|
+
return false;
|
|
3065
|
+
}
|
|
2595
3066
|
}
|
|
2596
|
-
|
|
2597
|
-
|
|
3067
|
+
function invocation_events(repository2, target) {
|
|
3068
|
+
const events = run_event_stream.read_events(target);
|
|
3069
|
+
const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository2)));
|
|
3070
|
+
return run_event_scope.scoped_events(events, scope) ?? events;
|
|
2598
3071
|
}
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
3072
|
+
async function emit_once_since(kind, text, reset_kind) {
|
|
3073
|
+
try {
|
|
3074
|
+
const repository2 = await run_carry.repository_directory();
|
|
3075
|
+
if (repository2 === void 0) return false;
|
|
3076
|
+
const target = run_event_stream.target_of(repository2);
|
|
3077
|
+
if (run_event_stream.has_since(invocation_events(repository2, target), kind, reset_kind)) {
|
|
3078
|
+
return false;
|
|
3079
|
+
}
|
|
3080
|
+
return run_event_stream.append(target, kind, text, now_iso()).appended;
|
|
3081
|
+
} catch {
|
|
3082
|
+
return false;
|
|
3083
|
+
}
|
|
3084
|
+
}
|
|
3085
|
+
async function emit_heartbeat(line) {
|
|
3086
|
+
await emit(run_event_stream.EVENT_KIND.HEARTBEAT, line);
|
|
3087
|
+
}
|
|
3088
|
+
async function current_events() {
|
|
3089
|
+
try {
|
|
3090
|
+
const repository2 = await run_carry.repository_directory();
|
|
3091
|
+
if (repository2 === void 0) return [];
|
|
3092
|
+
const read2 = run_carry.read_carry(run_carry.carry_path(repository2));
|
|
3093
|
+
const scope = run_event_scope.scope_of(read2);
|
|
3094
|
+
const events = run_event_stream.read_events(run_event_stream.target_of(repository2));
|
|
3095
|
+
return run_event_scope.scoped_events(events, scope) ?? [];
|
|
3096
|
+
} catch {
|
|
3097
|
+
return [];
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
var run_event_stream_emit = {
|
|
3101
|
+
current_events,
|
|
3102
|
+
emit,
|
|
3103
|
+
emit_heartbeat,
|
|
3104
|
+
emit_once,
|
|
3105
|
+
emit_once_since,
|
|
3106
|
+
stream_target
|
|
2608
3107
|
};
|
|
2609
3108
|
|
|
2610
|
-
// scripts/
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
3109
|
+
// scripts/run/run-ship-detach.ts
|
|
3110
|
+
var LOG_PREFIX = "josh-ship-log-";
|
|
3111
|
+
var PID_PREFIX = "josh-ship-pid-";
|
|
3112
|
+
var BODY_PREFIX = "josh-ship-notify-";
|
|
3113
|
+
var KEY_SEPARATOR = "-";
|
|
3114
|
+
var LOG_SUFFIX = ".log";
|
|
3115
|
+
var BODY_SUFFIX = ".txt";
|
|
3116
|
+
var PNPM = "pnpm";
|
|
3117
|
+
var INLINE_NOTIFY = "--notify-message";
|
|
3118
|
+
var FILE_NOTIFY = "--notify-message-file";
|
|
3119
|
+
var NOTIFY_VALUE_INDEX = 1;
|
|
3120
|
+
var SUPERVISED_KEY = "JOSH_SHIP_SUPERVISED";
|
|
3121
|
+
var LAUNCH_ID_KEY = "JOSH_SHIP_LAUNCH_ID";
|
|
3122
|
+
var SUPERVISED_VALUE = "1";
|
|
3123
|
+
var LAUNCHED = "launched";
|
|
3124
|
+
var BUSY = "busy";
|
|
3125
|
+
var FAILED = "failed";
|
|
3126
|
+
var RESULT_PREFIX = "josh-ship-result-";
|
|
3127
|
+
var RECORD_POLL_MS = 25;
|
|
3128
|
+
var RECORD_WAIT_ATTEMPTS = 200;
|
|
3129
|
+
var CLAIM_WINDOW_MS = 12e4;
|
|
3130
|
+
var ship_record_schema = z8.object({
|
|
3131
|
+
pid: z8.number().int().positive().optional(),
|
|
3132
|
+
process_start: z8.string().optional(),
|
|
3133
|
+
launched_at: z8.number().optional(),
|
|
3134
|
+
launcher_pid: z8.number().int().positive().optional(),
|
|
3135
|
+
launcher_start: z8.string().optional(),
|
|
3136
|
+
launch_id: z8.string(),
|
|
3137
|
+
result: z8.enum(["success", "failed"]).optional()
|
|
3138
|
+
});
|
|
3139
|
+
var LAUNCH_MARK = " \xB7 started by process ";
|
|
3140
|
+
var HEADER_START = "\n";
|
|
3141
|
+
function key(prefix, request) {
|
|
3142
|
+
return stamp_file.stamp_path(`${prefix}${request.number}${KEY_SEPARATOR}`, request.repository);
|
|
2616
3143
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
const tracked = to_paths(await git_command.diff_main_names());
|
|
2620
|
-
const untracked = to_paths(await git_command.untracked_names());
|
|
2621
|
-
return [...tracked, ...untracked];
|
|
3144
|
+
function log_path(repository2, number) {
|
|
3145
|
+
return stamp_file.stamp_path(`${LOG_PREFIX}${number}${KEY_SEPARATOR}`, repository2, LOG_SUFFIX);
|
|
2622
3146
|
}
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
// scripts/josh/path-decision.ts
|
|
2626
|
-
var STAGED_FLAG = "--staged";
|
|
2627
|
-
var JSON_FLAG = "--json";
|
|
2628
|
-
var KNOWN_FLAGS = [STAGED_FLAG, JSON_FLAG];
|
|
2629
|
-
var FAILURE_EXIT_CODE = 1;
|
|
2630
|
-
var MAX_LISTED_PATHS = 5;
|
|
2631
|
-
function has_unknown_flag(argv, known) {
|
|
2632
|
-
return argv.some((argument) => !known.includes(argument));
|
|
3147
|
+
function result_path(repository2, number) {
|
|
3148
|
+
return stamp_file.stamp_path(`${RESULT_PREFIX}${number}${KEY_SEPARATOR}`, repository2);
|
|
2633
3149
|
}
|
|
2634
|
-
function
|
|
2635
|
-
|
|
2636
|
-
|
|
3150
|
+
function read_record(repository2, number) {
|
|
3151
|
+
try {
|
|
3152
|
+
const raw = stamp_file.read_stamp_text(result_path(repository2, number));
|
|
3153
|
+
if (raw === void 0) return void 0;
|
|
3154
|
+
const value = JSON.parse(raw);
|
|
3155
|
+
const parsed = ship_record_schema.safeParse(value);
|
|
3156
|
+
return parsed.success ? parsed.data : void 0;
|
|
3157
|
+
} catch {
|
|
3158
|
+
return void 0;
|
|
3159
|
+
}
|
|
2637
3160
|
}
|
|
2638
|
-
function
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
3161
|
+
function record_launch(request, pid, launch_id) {
|
|
3162
|
+
stamp_file.write_text_stamp(key(PID_PREFIX, request), String(pid));
|
|
3163
|
+
const process_start = process_identity.read_start(pid);
|
|
3164
|
+
stamp_file.replace_stamp(result_path(request.repository, request.number), {
|
|
3165
|
+
pid,
|
|
3166
|
+
launch_id,
|
|
3167
|
+
launched_at: Date.now(),
|
|
3168
|
+
...process_start !== void 0 && { process_start }
|
|
3169
|
+
});
|
|
2642
3170
|
}
|
|
2643
|
-
function
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
3171
|
+
function supervisor_environment(launch_id) {
|
|
3172
|
+
return {
|
|
3173
|
+
...agent_role_profile.handoff_environment(),
|
|
3174
|
+
[SUPERVISED_KEY]: SUPERVISED_VALUE,
|
|
3175
|
+
[LAUNCH_ID_KEY]: launch_id
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
function is_within_claim_window(record) {
|
|
3179
|
+
return record.launched_at !== void 0 && Date.now() - record.launched_at < CLAIM_WINDOW_MS;
|
|
3180
|
+
}
|
|
3181
|
+
function has_live_identity(pid, record) {
|
|
3182
|
+
if (record.process_start === void 0) {
|
|
3183
|
+
return is_within_claim_window(record) && process_identity.is_live_pid(pid);
|
|
2647
3184
|
}
|
|
2648
|
-
|
|
2649
|
-
console.error(reason);
|
|
3185
|
+
return process_identity.is_same_process(pid, record.process_start) !== false;
|
|
2650
3186
|
}
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
return FAILURE_EXIT_CODE;
|
|
3187
|
+
function result_of(record) {
|
|
3188
|
+
if (record.pid === void 0) {
|
|
3189
|
+
const is_launcher = process_identity.is_same_process(record.launcher_pid, record.launcher_start);
|
|
3190
|
+
return is_launcher === false ? "abnormal" : "running";
|
|
2656
3191
|
}
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
3192
|
+
if (has_live_identity(record.pid, record)) return "running";
|
|
3193
|
+
return record.result ?? "abnormal";
|
|
3194
|
+
}
|
|
3195
|
+
function read_result(repository2, number) {
|
|
3196
|
+
const record = read_record(repository2, number);
|
|
3197
|
+
return record === void 0 ? void 0 : { launch_id: record.launch_id, result: result_of(record) };
|
|
3198
|
+
}
|
|
3199
|
+
function current_record(repository2, number) {
|
|
3200
|
+
const record = read_record(repository2, number);
|
|
3201
|
+
return record?.launch_id === process.env[LAUNCH_ID_KEY] ? record : void 0;
|
|
3202
|
+
}
|
|
3203
|
+
function is_pending(record) {
|
|
3204
|
+
return record !== void 0 && record.pid === void 0;
|
|
3205
|
+
}
|
|
3206
|
+
async function ready_record(repository2, number) {
|
|
3207
|
+
let record = current_record(repository2, number);
|
|
3208
|
+
for (let attempt = 0; attempt < RECORD_WAIT_ATTEMPTS; attempt += 1) {
|
|
3209
|
+
if (!is_pending(record)) return record;
|
|
3210
|
+
await sleep(RECORD_POLL_MS);
|
|
3211
|
+
record = current_record(repository2, number);
|
|
3212
|
+
}
|
|
3213
|
+
return void 0;
|
|
3214
|
+
}
|
|
3215
|
+
async function update_record(repository2, number, fields) {
|
|
3216
|
+
const record = await ready_record(repository2, number);
|
|
3217
|
+
if (record === void 0) return;
|
|
3218
|
+
stamp_file.replace_stamp(result_path(repository2, number), { ...record, ...fields });
|
|
3219
|
+
}
|
|
3220
|
+
async function mark_result(repository2, number, code) {
|
|
3221
|
+
await update_record(repository2, number, { result: code === 0 ? "success" : "failed" });
|
|
3222
|
+
}
|
|
3223
|
+
async function claim_identity(repository2, number) {
|
|
3224
|
+
const own2 = process_identity.own_fields();
|
|
3225
|
+
if (own2.process_start === void 0) return;
|
|
3226
|
+
await update_record(repository2, number, own2);
|
|
3227
|
+
}
|
|
3228
|
+
function failed_launch(request, note) {
|
|
3229
|
+
stamp_file.remove_stamp(result_path(request.repository, request.number));
|
|
3230
|
+
return { verdict: FAILED, note };
|
|
3231
|
+
}
|
|
3232
|
+
function notify_arguments(request) {
|
|
3233
|
+
const [flag, value] = [request.notify[0], request.notify[NOTIFY_VALUE_INDEX]];
|
|
3234
|
+
if (flag !== INLINE_NOTIFY || value === void 0) return request.notify;
|
|
3235
|
+
const body_path = stamp_file.stamp_path(
|
|
3236
|
+
`${BODY_PREFIX}${request.number}${KEY_SEPARATOR}`,
|
|
3237
|
+
request.repository,
|
|
3238
|
+
BODY_SUFFIX
|
|
3239
|
+
);
|
|
3240
|
+
stamp_file.write_text_stamp(body_path, value);
|
|
3241
|
+
return [FILE_NOTIFY, body_path];
|
|
2661
3242
|
}
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
3243
|
+
function supervisor_argv(request) {
|
|
3244
|
+
const review = request.is_review ? ["--review"] : [];
|
|
3245
|
+
const cites = request.cites.flatMap((cite) => ["--cite", cite]);
|
|
3246
|
+
return {
|
|
3247
|
+
command: PNPM,
|
|
3248
|
+
args: [
|
|
3249
|
+
"josh",
|
|
3250
|
+
"ship",
|
|
3251
|
+
...review,
|
|
3252
|
+
...notify_arguments(request),
|
|
3253
|
+
...request.body,
|
|
3254
|
+
...cites,
|
|
3255
|
+
request.title
|
|
3256
|
+
]
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
function prepare_launch(request) {
|
|
3260
|
+
const launch_id = randomUUID2();
|
|
3261
|
+
const launcher = process_identity.own_fields();
|
|
3262
|
+
stamp_file.replace_stamp(result_path(request.repository, request.number), {
|
|
3263
|
+
launch_id,
|
|
3264
|
+
launcher_pid: launcher.pid,
|
|
3265
|
+
...launcher.process_start !== void 0 && { launcher_start: launcher.process_start }
|
|
3266
|
+
});
|
|
3267
|
+
return launch_id;
|
|
3268
|
+
}
|
|
3269
|
+
function launch2(request) {
|
|
3270
|
+
const notes = [];
|
|
3271
|
+
const log = log_path(request.repository, request.number);
|
|
3272
|
+
const launch_id = prepare_launch(request);
|
|
3273
|
+
const result = detached_launch.launch(
|
|
3274
|
+
{
|
|
3275
|
+
argv: supervisor_argv(request),
|
|
3276
|
+
cwd: request.cwd,
|
|
3277
|
+
log_path: log,
|
|
3278
|
+
// The provider travels as a mark because the launch strips the session keys that name it, and
|
|
3279
|
+
// `ship --review` resolves its reviewer from it (joshuafolkken/kit#2456).
|
|
3280
|
+
env: supervisor_environment(launch_id)
|
|
3281
|
+
},
|
|
3282
|
+
(note) => {
|
|
3283
|
+
notes.push(note);
|
|
3284
|
+
}
|
|
3285
|
+
);
|
|
3286
|
+
if (result.kind === "failed") return failed_launch(request, result.note);
|
|
3287
|
+
record_launch(request, result.pid, launch_id);
|
|
3288
|
+
return {
|
|
3289
|
+
verdict: LAUNCHED,
|
|
3290
|
+
note: [`supervisor ${String(result.pid)} \u2014 log: ${log}`, ...notes].join("\n")
|
|
3291
|
+
};
|
|
3292
|
+
}
|
|
3293
|
+
async function detach(request) {
|
|
3294
|
+
if (read_result(request.repository, request.number)?.result === "running") {
|
|
3295
|
+
return { verdict: BUSY, note: `a ship supervisor for #${request.number} is already running` };
|
|
3296
|
+
}
|
|
3297
|
+
const result = launch2(request);
|
|
3298
|
+
if (result.verdict === LAUNCHED) {
|
|
3299
|
+
await run_event_stream_emit.emit(
|
|
3300
|
+
run_event_stream.EVENT_KIND.SHIP_LAUNCH,
|
|
3301
|
+
`#${request.number} ship supervisor launched`
|
|
3302
|
+
);
|
|
3303
|
+
}
|
|
3304
|
+
return result;
|
|
3305
|
+
}
|
|
3306
|
+
function last_launch(text) {
|
|
3307
|
+
const mark = text.lastIndexOf(LAUNCH_MARK);
|
|
3308
|
+
if (mark === -1) return text;
|
|
3309
|
+
return text.slice(text.lastIndexOf(HEADER_START, mark) + HEADER_START.length);
|
|
3310
|
+
}
|
|
3311
|
+
function read_log(repository2, number) {
|
|
3312
|
+
const text = stamp_file.read_stamp_text(log_path(repository2, number));
|
|
3313
|
+
return text === void 0 ? void 0 : last_launch(text);
|
|
3314
|
+
}
|
|
3315
|
+
function is_supervised(source = process.env) {
|
|
3316
|
+
return source[SUPERVISED_KEY] === SUPERVISED_VALUE;
|
|
3317
|
+
}
|
|
3318
|
+
var run_ship_detach = {
|
|
3319
|
+
BUSY,
|
|
3320
|
+
FAILED,
|
|
3321
|
+
LAUNCHED,
|
|
3322
|
+
LAUNCH_ID_KEY,
|
|
3323
|
+
claim_identity,
|
|
3324
|
+
mark_result,
|
|
3325
|
+
read_result,
|
|
3326
|
+
SUPERVISED_KEY,
|
|
3327
|
+
detach,
|
|
3328
|
+
is_supervised,
|
|
3329
|
+
last_launch,
|
|
3330
|
+
log_path,
|
|
3331
|
+
read_log,
|
|
3332
|
+
supervisor_argv
|
|
2672
3333
|
};
|
|
2673
3334
|
|
|
2674
|
-
// scripts/
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
if (unknown.length === 0) return void 0;
|
|
2679
|
-
const usage = `Usage: josh ${command} [${known_flags.join("] [")}]`;
|
|
2680
|
-
return `Unknown argument(s): ${unknown.join(" ")}
|
|
2681
|
-
${usage}`;
|
|
3335
|
+
// scripts/lane/lane-handoff.ts
|
|
3336
|
+
function is_ship_running(issue, directory) {
|
|
3337
|
+
const repository2 = git_common_directory.repository(directory);
|
|
3338
|
+
return repository2 !== void 0 && run_ship_detach.read_result(repository2, issue)?.result === "running";
|
|
2682
3339
|
}
|
|
2683
|
-
function
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
return void 0;
|
|
2688
|
-
}
|
|
3340
|
+
function is_handed_off(directory, source = process.env) {
|
|
3341
|
+
const issue = lane_child_marker.marked_issue(source);
|
|
3342
|
+
if (issue === void 0 || !lane_child_marker.is_child_of(directory, source)) return false;
|
|
3343
|
+
return is_ship_running(issue, directory);
|
|
2689
3344
|
}
|
|
2690
|
-
var
|
|
3345
|
+
var lane_handoff = { is_handed_off, is_ship_running };
|
|
2691
3346
|
|
|
2692
|
-
// scripts/
|
|
2693
|
-
var
|
|
2694
|
-
var
|
|
2695
|
-
var
|
|
2696
|
-
var
|
|
2697
|
-
var
|
|
2698
|
-
var
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
3347
|
+
// scripts/issue/issue-labels.ts
|
|
3348
|
+
var EPIC_LABEL = "epic";
|
|
3349
|
+
var ENHANCEMENT_LABEL = "enhancement";
|
|
3350
|
+
var BREAKING_CHANGE_LABEL = "breaking-change";
|
|
3351
|
+
var IN_PROGRESS_LABEL = "in-progress";
|
|
3352
|
+
var PLANNED_LABEL = "run:planned";
|
|
3353
|
+
var NEEDS_DECISION_LABEL = "needs-decision";
|
|
3354
|
+
var RUN_SOLO_LABEL = "run:solo";
|
|
3355
|
+
var RUN_LANE_LABEL = "run:lane";
|
|
3356
|
+
var PRIORITY_HIGH_LABEL = "priority:high";
|
|
3357
|
+
var NEEDS_HUMAN_REVIEW_LABEL = "needs-human-review";
|
|
3358
|
+
var ALREADY_DONE_LABEL = "already-done";
|
|
3359
|
+
var INTERRUPT_ROUTE_LABEL = "route:interrupt";
|
|
3360
|
+
var REVIEW_CAP_ROUTE_LABEL = "route:review-cap";
|
|
3361
|
+
var SPLIT_ROUTE_LABEL = "route:split";
|
|
3362
|
+
var TIER_A_ROUTE_LABEL = "route:tier-a";
|
|
3363
|
+
var FILING_ROUTE_LABELS = [
|
|
3364
|
+
{
|
|
3365
|
+
name: INTERRUPT_ROUTE_LABEL,
|
|
3366
|
+
// Not `5319e7`, which is the `epic` label's purple: in a listing an interrupt would render as
|
|
3367
|
+
// an epic, and the two are read at a glance rather than by name.
|
|
3368
|
+
color: "1d76db",
|
|
3369
|
+
// Keyed to the tests rather than to severity. "A serious defect" is the self-assessment
|
|
3370
|
+
// `wip-cap.md` bans as a criterion, and this string is what a person reads in `gh label list`.
|
|
3371
|
+
description: "Filed past the WIP cap \u2014 meets one of the three interrupt tests (wip-cap.md)"
|
|
3372
|
+
},
|
|
3373
|
+
{
|
|
3374
|
+
name: REVIEW_CAP_ROUTE_LABEL,
|
|
3375
|
+
color: "eab308",
|
|
3376
|
+
description: "Filed by the review round cap's carry-forward (prompts/review.md \u2192 Review round cap)"
|
|
3377
|
+
},
|
|
3378
|
+
{
|
|
3379
|
+
name: SPLIT_ROUTE_LABEL,
|
|
3380
|
+
color: "0e8a16",
|
|
3381
|
+
description: "A child issue created by a split (split-assessment.md)"
|
|
3382
|
+
},
|
|
3383
|
+
{
|
|
3384
|
+
name: TIER_A_ROUTE_LABEL,
|
|
3385
|
+
color: "d93f0b",
|
|
3386
|
+
description: "Filed Tier A during implementation \u2014 an upstream defect or a prerequisite"
|
|
3387
|
+
}
|
|
3388
|
+
];
|
|
3389
|
+
var DEPTH_0_LABEL = "depth:0";
|
|
3390
|
+
var DEPTH_1_LABEL = "depth:1";
|
|
3391
|
+
var DEPTH_2_LABEL = "depth:2";
|
|
3392
|
+
var DEPTH_LABELS = [
|
|
3393
|
+
{
|
|
3394
|
+
name: DEPTH_0_LABEL,
|
|
3395
|
+
color: "0e8a16",
|
|
3396
|
+
description: "Depth 0 \u2014 what a consumer of this package touches (SKILL.md \xA72i)"
|
|
3397
|
+
},
|
|
3398
|
+
{
|
|
3399
|
+
name: DEPTH_1_LABEL,
|
|
3400
|
+
color: "fbc02d",
|
|
3401
|
+
description: "Depth 1 \u2014 the run orchestration that executes an Issue (SKILL.md \xA72i)"
|
|
3402
|
+
},
|
|
3403
|
+
{
|
|
3404
|
+
name: DEPTH_2_LABEL,
|
|
3405
|
+
color: "c5def5",
|
|
3406
|
+
description: "Depth 2 \u2014 what measures a run (SKILL.md \xA72i)"
|
|
3407
|
+
}
|
|
3408
|
+
];
|
|
3409
|
+
var WORKFLOW_LABELS = [
|
|
3410
|
+
{
|
|
3411
|
+
name: EPIC_LABEL,
|
|
3412
|
+
color: "5319e7",
|
|
3413
|
+
description: "Tracks a batch of child issues from one split"
|
|
3414
|
+
},
|
|
3415
|
+
{ name: IN_PROGRESS_LABEL, color: "0075ca", description: "Work is actively in progress" },
|
|
3416
|
+
{ name: PLANNED_LABEL, color: "c2e0c6", description: "kickoff posted the plan" },
|
|
3417
|
+
{
|
|
3418
|
+
name: RUN_SOLO_LABEL,
|
|
3419
|
+
color: "b60205",
|
|
3420
|
+
description: "Runs alone in a backlogrun: nothing starts beside it"
|
|
3421
|
+
},
|
|
3422
|
+
{
|
|
3423
|
+
name: RUN_LANE_LABEL,
|
|
3424
|
+
color: "0e8a16",
|
|
3425
|
+
description: "Judged safe to run beside others in a backlogrun"
|
|
3426
|
+
},
|
|
3427
|
+
{
|
|
3428
|
+
name: PRIORITY_HIGH_LABEL,
|
|
3429
|
+
color: "e99695",
|
|
3430
|
+
description: "Offered first in a backlogrun; only a person removes it"
|
|
3431
|
+
},
|
|
3432
|
+
...FILING_ROUTE_LABELS,
|
|
3433
|
+
...DEPTH_LABELS
|
|
3434
|
+
];
|
|
3435
|
+
var BUGFIX_LABEL = "bugfix";
|
|
3436
|
+
var OTHER_CHANGE_LABEL = "other-change";
|
|
3437
|
+
var IGNORE_FOR_RELEASE_LABEL = "ignore-for-release";
|
|
3438
|
+
var RELEASE_CLASSIFICATION_NAMES = [
|
|
3439
|
+
BREAKING_CHANGE_LABEL,
|
|
3440
|
+
ENHANCEMENT_LABEL,
|
|
3441
|
+
BUGFIX_LABEL,
|
|
3442
|
+
OTHER_CHANGE_LABEL,
|
|
3443
|
+
IGNORE_FOR_RELEASE_LABEL
|
|
3444
|
+
];
|
|
3445
|
+
var RELEASE_CLASSIFICATION_METADATA = {
|
|
3446
|
+
[BREAKING_CHANGE_LABEL]: { color: "d93f0b", description: "Release: a breaking change (major)" },
|
|
3447
|
+
[ENHANCEMENT_LABEL]: { color: "84b6eb", description: "Release: a new feature (minor)" },
|
|
3448
|
+
[BUGFIX_LABEL]: { color: "d73a4a", description: "Release: a bug fix (patch)" },
|
|
3449
|
+
[OTHER_CHANGE_LABEL]: { color: "c2e0c6", description: "Release: any other change (patch)" },
|
|
3450
|
+
[IGNORE_FOR_RELEASE_LABEL]: { color: "cfd3d7", description: "Release: left out of the notes" }
|
|
2707
3451
|
};
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
3452
|
+
var RELEASE_CLASSIFICATION_LABELS = RELEASE_CLASSIFICATION_NAMES.map((name) => ({ name, ...RELEASE_CLASSIFICATION_METADATA[name] }));
|
|
3453
|
+
var REPOSITORY_LABELS = [
|
|
3454
|
+
...WORKFLOW_LABELS,
|
|
3455
|
+
...RELEASE_CLASSIFICATION_LABELS
|
|
3456
|
+
];
|
|
3457
|
+
function has_any_label(labels, wanted) {
|
|
3458
|
+
return (labels ?? []).some((label2) => wanted.has(label2.name.toLowerCase()));
|
|
2713
3459
|
}
|
|
2714
|
-
function
|
|
2715
|
-
|
|
3460
|
+
function label_name_of(labels, wanted) {
|
|
3461
|
+
const target = wanted.toLowerCase();
|
|
3462
|
+
return labels.find((label2) => label2.toLowerCase() === target);
|
|
2716
3463
|
}
|
|
2717
|
-
function
|
|
2718
|
-
|
|
2719
|
-
const parsed = Date.parse(raw);
|
|
2720
|
-
return Number.isNaN(parsed) ? void 0 : parsed;
|
|
3464
|
+
function has_label_name(labels, wanted) {
|
|
3465
|
+
return label_name_of(labels, wanted) !== void 0;
|
|
2721
3466
|
}
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
3467
|
+
|
|
3468
|
+
// scripts/rules/lane-park.ts
|
|
3469
|
+
var NOTIFY_COMMANDS = /* @__PURE__ */ new Set(["notify"]);
|
|
3470
|
+
var CONFIRMATION_TASK_TYPE = /(?:^|\s)--task-type[=\s]+["']?confirmation\b/u;
|
|
3471
|
+
function is_confirmation_notify(command) {
|
|
3472
|
+
return shell_segments.segments_of(command).some(
|
|
3473
|
+
(segment) => shell_segments.is_josh_command(segment, NOTIFY_COMMANDS) && CONFIRMATION_TASK_TYPE.test(segment)
|
|
3474
|
+
);
|
|
2727
3475
|
}
|
|
2728
|
-
|
|
2729
|
-
|
|
3476
|
+
var NOTIFY_INVOCATION = /josh\s+(?:notify|nf)\b/u;
|
|
3477
|
+
function mentions_confirmation_notify(text) {
|
|
3478
|
+
return NOTIFY_INVOCATION.test(text) && CONFIRMATION_TASK_TYPE.test(text);
|
|
2730
3479
|
}
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
return {
|
|
2734
|
-
idle: to_count(text_of(values.idle)),
|
|
2735
|
-
max: to_count(text_of(values.max)),
|
|
2736
|
-
merged: to_count(text_of(values.merged)),
|
|
2737
|
-
running: to_count(text_of(values.running))
|
|
2738
|
-
};
|
|
3480
|
+
function is_parking_child(directory = process.cwd()) {
|
|
3481
|
+
return lane_child_marker.is_child_of(directory) && !lane_handoff.is_handed_off(directory);
|
|
2739
3482
|
}
|
|
2740
|
-
function
|
|
2741
|
-
|
|
3483
|
+
function is_unparked_stop(command, is_child = is_parking_child) {
|
|
3484
|
+
if (!is_confirmation_notify(command)) return false;
|
|
3485
|
+
return is_child();
|
|
2742
3486
|
}
|
|
2743
|
-
var
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
3487
|
+
var APPLIES_NEEDS_DECISION = new RegExp(
|
|
3488
|
+
String.raw`(?:labels\[\]=|--add-label[= ]'?)${NEEDS_DECISION_LABEL}\b`,
|
|
3489
|
+
"u"
|
|
3490
|
+
);
|
|
3491
|
+
function records_the_park(command) {
|
|
3492
|
+
return APPLIES_NEEDS_DECISION.test(command);
|
|
2748
3493
|
}
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
3494
|
+
var LANE_PARK_REASON = '\u26D4 lane child park: this session is a dispatched lane child, and a stop that waits on a person must leave the question on the Issue before it sends this Telegram \u2014 otherwise the parent finds an OPEN Issue with `in-progress` and no question, and a person cannot tell what to answer (joshuafolkken/kit#2034 measured this twice in one run). The child is the only process that knows the question, the options and whether it stashed, so it records the park itself rather than leaving the parent to guess from a log. Before you notify and stop: apply `needs-decision` and post a comment carrying the question, the options, and whether work was stashed \u2014 `gh api repos/{owner}/{repo}/issues/<N>/labels -f \'labels[]=needs-decision\'` then `pnpm josh issue:comment <N> --body-file <path>`. If this stop is a `needs-human-review` or `already-done` one, that label is already on the Issue and there is nothing to add. Then reissue this notify \u2014 it fires once per run and cannot repeat on the call in hand. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md` \u2192 "A lane child records its park before it stops", and the park itself is `backlogrun-park.md` \u2192 "park and continue".';
|
|
3495
|
+
var lane_park = {
|
|
3496
|
+
LANE_PARK_REASON,
|
|
3497
|
+
is_confirmation_notify,
|
|
3498
|
+
is_parking_child,
|
|
3499
|
+
is_unparked_stop,
|
|
3500
|
+
mentions_confirmation_notify,
|
|
3501
|
+
records_the_park
|
|
3502
|
+
};
|
|
3503
|
+
|
|
3504
|
+
// scripts/discovery/repo-discovery.ts
|
|
3505
|
+
import { existsSync as existsSync2, readdirSync, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
3506
|
+
import path4 from "node:path";
|
|
3507
|
+
|
|
3508
|
+
// scripts/discovery/repo-origin.ts
|
|
3509
|
+
var GITHUB_HOST = "github.com";
|
|
3510
|
+
var SSH_ALIAS_PATTERN = /^github(?:-\w+)*$/u;
|
|
3511
|
+
var GIT_SUFFIX = ".git";
|
|
3512
|
+
var PATH_SEPARATOR2 = "/";
|
|
3513
|
+
var USER_SEPARATOR = "@";
|
|
3514
|
+
var HOST_SEPARATOR = ":";
|
|
3515
|
+
var OWNER_INDEX = 0;
|
|
3516
|
+
var REPO_INDEX = 1;
|
|
3517
|
+
var REPO_PATH_SEGMENTS = 2;
|
|
3518
|
+
var NOT_FOUND2 = -1;
|
|
3519
|
+
var SECTION_PREFIX = "[";
|
|
3520
|
+
var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
|
|
3521
|
+
var URL_KEY = "url";
|
|
3522
|
+
function is_github_hostname(host) {
|
|
3523
|
+
return host.toLowerCase() === GITHUB_HOST;
|
|
2752
3524
|
}
|
|
2753
|
-
function
|
|
2754
|
-
|
|
3525
|
+
function is_github_ssh_host(host) {
|
|
3526
|
+
const normalized = host.toLowerCase();
|
|
3527
|
+
return is_github_hostname(normalized) || SSH_ALIAS_PATTERN.test(normalized);
|
|
2755
3528
|
}
|
|
2756
|
-
function
|
|
2757
|
-
|
|
2758
|
-
return {
|
|
2759
|
-
...base,
|
|
2760
|
-
active_at_ms: to_time_ms(text_of(values.active)) ?? base.started_at_ms,
|
|
2761
|
-
merged: counts.merged ?? 0,
|
|
2762
|
-
running: counts.running ?? 0,
|
|
2763
|
-
max_issues: counts.max,
|
|
2764
|
-
idle_budget_ms: to_idle_ms(counts.idle)
|
|
2765
|
-
};
|
|
3529
|
+
function strip_git_suffix(name) {
|
|
3530
|
+
return name.endsWith(GIT_SUFFIX) ? name.slice(0, -GIT_SUFFIX.length) : name;
|
|
2766
3531
|
}
|
|
2767
|
-
function
|
|
2768
|
-
const
|
|
2769
|
-
if (
|
|
2770
|
-
const
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
return input_of(values, { answer, now_ms, started_at_ms });
|
|
3532
|
+
function to_identity(repository_path) {
|
|
3533
|
+
const segments = repository_path.split(PATH_SEPARATOR2).filter((segment) => segment !== "");
|
|
3534
|
+
if (segments.length !== REPO_PATH_SEGMENTS) return void 0;
|
|
3535
|
+
const owner = segments[OWNER_INDEX] ?? "";
|
|
3536
|
+
const repo = strip_git_suffix(segments[REPO_INDEX] ?? "");
|
|
3537
|
+
return repo === "" ? void 0 : { owner, repo };
|
|
2774
3538
|
}
|
|
2775
|
-
function
|
|
2776
|
-
|
|
2777
|
-
|
|
3539
|
+
function parse_scp_like(url) {
|
|
3540
|
+
const user_end = url.indexOf(USER_SEPARATOR);
|
|
3541
|
+
const authority = user_end === NOT_FOUND2 ? url : url.slice(user_end + 1);
|
|
3542
|
+
const host_end = authority.indexOf(HOST_SEPARATOR);
|
|
3543
|
+
if (host_end === NOT_FOUND2) return void 0;
|
|
3544
|
+
if (!is_github_ssh_host(authority.slice(0, host_end))) return void 0;
|
|
3545
|
+
return to_identity(authority.slice(host_end + 1));
|
|
2778
3546
|
}
|
|
2779
|
-
function
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
if (values.json === true) {
|
|
2786
|
-
console.info(
|
|
2787
|
-
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: backlog_budget.is_finish(input) })
|
|
2788
|
-
);
|
|
2789
|
-
return SUCCESS_EXIT_CODE;
|
|
3547
|
+
function parse_url_like(url) {
|
|
3548
|
+
try {
|
|
3549
|
+
const parsed = new URL(url);
|
|
3550
|
+
return is_github_hostname(parsed.hostname) ? to_identity(parsed.pathname) : void 0;
|
|
3551
|
+
} catch {
|
|
3552
|
+
return void 0;
|
|
2790
3553
|
}
|
|
2791
|
-
path_decision.print_decision(JSON_KEY, verdict, reason, false);
|
|
2792
|
-
return SUCCESS_EXIT_CODE;
|
|
2793
3554
|
}
|
|
2794
|
-
function
|
|
2795
|
-
|
|
3555
|
+
function parse_origin_url(url) {
|
|
3556
|
+
const trimmed2 = url.trim();
|
|
3557
|
+
if (trimmed2 === "") return void 0;
|
|
3558
|
+
return parse_url_like(trimmed2) ?? parse_scp_like(trimmed2);
|
|
2796
3559
|
}
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
3560
|
+
function is_section_header(line) {
|
|
3561
|
+
return line.startsWith(SECTION_PREFIX);
|
|
3562
|
+
}
|
|
3563
|
+
function origin_section_lines(lines) {
|
|
3564
|
+
const start = lines.findIndex((line) => ORIGIN_SECTION.test(line));
|
|
3565
|
+
if (start === NOT_FOUND2) return [];
|
|
3566
|
+
const rest = lines.slice(start + 1);
|
|
3567
|
+
const end = rest.findIndex((line) => is_section_header(line));
|
|
3568
|
+
return end === NOT_FOUND2 ? rest : rest.slice(0, end);
|
|
3569
|
+
}
|
|
3570
|
+
function entry_value(line, key2) {
|
|
3571
|
+
const separator = line.indexOf("=");
|
|
3572
|
+
if (separator === NOT_FOUND2) return void 0;
|
|
3573
|
+
if (line.slice(0, separator).trim() !== key2) return void 0;
|
|
3574
|
+
return line.slice(separator + 1).trim();
|
|
3575
|
+
}
|
|
3576
|
+
function parse_origin_from_config(content) {
|
|
3577
|
+
const lines = content.split("\n").map((line) => line.trim());
|
|
3578
|
+
return origin_section_lines(lines).map((line) => entry_value(line, URL_KEY)).find((url) => url !== void 0);
|
|
3579
|
+
}
|
|
3580
|
+
function format_identity(identity) {
|
|
3581
|
+
return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
|
|
3582
|
+
}
|
|
3583
|
+
var repo_origin = {
|
|
3584
|
+
GITHUB_HOST,
|
|
3585
|
+
is_github_hostname,
|
|
3586
|
+
is_github_ssh_host,
|
|
3587
|
+
parse_origin_from_config,
|
|
3588
|
+
parse_origin_url,
|
|
3589
|
+
format_identity
|
|
2809
3590
|
};
|
|
2810
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) main(process.argv.slice(ARGV_OFFSET));
|
|
2811
3591
|
|
|
2812
|
-
// scripts/
|
|
2813
|
-
var
|
|
2814
|
-
var
|
|
2815
|
-
var
|
|
2816
|
-
var
|
|
2817
|
-
var
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
var VALUE_OFFSET = 1;
|
|
2821
|
-
var FLAG_PAIR_LENGTH = 2;
|
|
2822
|
-
var ONLY_STEP = 1;
|
|
2823
|
-
var EMPTY_LENGTH2 = 0;
|
|
2824
|
-
var NOT_FOUND2 = -1;
|
|
2825
|
-
function tokens_of(invocation) {
|
|
2826
|
-
return invocation.split(TOKEN_SEPARATOR).filter((token) => token.length > EMPTY_LENGTH2);
|
|
3592
|
+
// scripts/discovery/repo-map-logic.ts
|
|
3593
|
+
var OVERRIDE_ENTRY_SEPARATOR = ",";
|
|
3594
|
+
var OVERRIDE_PAIR_SEPARATOR = "=";
|
|
3595
|
+
var OVERRIDE_PAIR_PARTS = 2;
|
|
3596
|
+
var KEY_INDEX = 0;
|
|
3597
|
+
var PATH_INDEX = 1;
|
|
3598
|
+
function is_same_owner(identity, current_owner2) {
|
|
3599
|
+
return identity.owner.toLowerCase() === current_owner2.toLowerCase();
|
|
2827
3600
|
}
|
|
2828
|
-
function
|
|
2829
|
-
|
|
2830
|
-
const
|
|
2831
|
-
if (
|
|
2832
|
-
|
|
3601
|
+
function add_entry(target, origin_url, repository_path, current_owner2) {
|
|
3602
|
+
if (origin_url === void 0) return;
|
|
3603
|
+
const identity = repo_origin.parse_origin_url(origin_url);
|
|
3604
|
+
if (identity === void 0 || !is_same_owner(identity, current_owner2)) return;
|
|
3605
|
+
target.set(repo_origin.format_identity(identity), repository_path);
|
|
2833
3606
|
}
|
|
2834
|
-
function
|
|
2835
|
-
const
|
|
2836
|
-
if (
|
|
2837
|
-
const
|
|
2838
|
-
|
|
3607
|
+
function parse_override_entry(entry) {
|
|
3608
|
+
const parts = entry.split(OVERRIDE_PAIR_SEPARATOR).map((part) => part.trim());
|
|
3609
|
+
if (parts.length !== OVERRIDE_PAIR_PARTS) return void 0;
|
|
3610
|
+
const key2 = parts[KEY_INDEX] ?? "";
|
|
3611
|
+
const repository_path = parts[PATH_INDEX] ?? "";
|
|
3612
|
+
if (repository_path === "") return void 0;
|
|
3613
|
+
return { path: repository_path, origin_url: `https://${repo_origin.GITHUB_HOST}/${key2}` };
|
|
2839
3614
|
}
|
|
2840
|
-
function
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
3615
|
+
function parse_overrides(raw) {
|
|
3616
|
+
if (raw === void 0) return [];
|
|
3617
|
+
return raw.split(OVERRIDE_ENTRY_SEPARATOR).map((entry) => parse_override_entry(entry)).filter((entry) => entry !== void 0);
|
|
3618
|
+
}
|
|
3619
|
+
function build_repository_map(discovered, current_owner2, override_value2) {
|
|
3620
|
+
const result = /* @__PURE__ */ new Map();
|
|
3621
|
+
for (const entry of discovered) add_entry(result, entry.origin_url, entry.path, current_owner2);
|
|
3622
|
+
for (const entry of parse_overrides(override_value2)) {
|
|
3623
|
+
add_entry(result, entry.origin_url, entry.path, current_owner2);
|
|
2848
3624
|
}
|
|
2849
|
-
return
|
|
3625
|
+
return result;
|
|
2850
3626
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
3627
|
+
var repo_map_logic = {
|
|
3628
|
+
is_same_owner,
|
|
3629
|
+
build_repository_map
|
|
3630
|
+
};
|
|
3631
|
+
|
|
3632
|
+
// scripts/discovery/repo-discovery.ts
|
|
3633
|
+
var GIT_DIRECTORY = ".git";
|
|
3634
|
+
var GIT_CONFIG = "config";
|
|
3635
|
+
var GITDIR_PREFIX = "gitdir:";
|
|
3636
|
+
var COMMON_DIRECTORY_FILE = "commondir";
|
|
3637
|
+
var OVERRIDE_ENV_KEY = "JOSH_REPO_PATHS";
|
|
3638
|
+
function resolve_common_directory(git_directory) {
|
|
3639
|
+
const pointer = path4.join(git_directory, COMMON_DIRECTORY_FILE);
|
|
3640
|
+
if (!existsSync2(pointer)) return git_directory;
|
|
3641
|
+
try {
|
|
3642
|
+
return path4.resolve(git_directory, readFileSync3(pointer, "utf8").trim());
|
|
3643
|
+
} catch {
|
|
3644
|
+
return git_directory;
|
|
3645
|
+
}
|
|
2857
3646
|
}
|
|
2858
|
-
function
|
|
2859
|
-
const
|
|
2860
|
-
|
|
3647
|
+
function follow_git_file(repository_path, git_file) {
|
|
3648
|
+
const pointer = readFileSync3(git_file, "utf8").trim();
|
|
3649
|
+
if (!pointer.startsWith(GITDIR_PREFIX)) return void 0;
|
|
3650
|
+
return path4.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim());
|
|
2861
3651
|
}
|
|
2862
|
-
function
|
|
2863
|
-
const
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
3652
|
+
function resolve_git_directory(repository_path) {
|
|
3653
|
+
const candidate = path4.join(repository_path, GIT_DIRECTORY);
|
|
3654
|
+
if (!existsSync2(candidate)) return void 0;
|
|
3655
|
+
try {
|
|
3656
|
+
if (statSync(candidate).isDirectory()) return candidate;
|
|
3657
|
+
const linked = follow_git_file(repository_path, candidate);
|
|
3658
|
+
return linked === void 0 ? void 0 : resolve_common_directory(linked);
|
|
3659
|
+
} catch {
|
|
3660
|
+
return void 0;
|
|
2869
3661
|
}
|
|
2870
|
-
return issues;
|
|
2871
3662
|
}
|
|
2872
|
-
function
|
|
2873
|
-
|
|
3663
|
+
function read_origin_url(repository_path) {
|
|
3664
|
+
const git_directory = resolve_git_directory(repository_path);
|
|
3665
|
+
if (git_directory === void 0) return void 0;
|
|
3666
|
+
try {
|
|
3667
|
+
return repo_origin.parse_origin_from_config(
|
|
3668
|
+
readFileSync3(path4.join(git_directory, GIT_CONFIG), "utf8")
|
|
3669
|
+
);
|
|
3670
|
+
} catch {
|
|
3671
|
+
return void 0;
|
|
3672
|
+
}
|
|
2874
3673
|
}
|
|
2875
|
-
function
|
|
2876
|
-
|
|
3674
|
+
function sibling_directories(parent) {
|
|
3675
|
+
try {
|
|
3676
|
+
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path4.join(parent, entry.name)).toSorted((left, right) => left.localeCompare(right));
|
|
3677
|
+
} catch {
|
|
3678
|
+
return [];
|
|
3679
|
+
}
|
|
2877
3680
|
}
|
|
2878
|
-
function
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
return joined(BACKLOG_COMMAND, [...issues.map((issue) => issue_token(issue)), ...flags]);
|
|
3681
|
+
function scan_siblings(parent) {
|
|
3682
|
+
return sibling_directories(parent).map((repository_path) => ({
|
|
3683
|
+
path: repository_path,
|
|
3684
|
+
origin_url: read_origin_url(repository_path)
|
|
3685
|
+
}));
|
|
2884
3686
|
}
|
|
2885
|
-
function
|
|
2886
|
-
const
|
|
2887
|
-
if (
|
|
2888
|
-
return
|
|
3687
|
+
function resolve_current_owner(repository_path) {
|
|
3688
|
+
const origin_url = read_origin_url(repository_path);
|
|
3689
|
+
if (origin_url === void 0) return void 0;
|
|
3690
|
+
return repo_origin.parse_origin_url(origin_url)?.owner;
|
|
2889
3691
|
}
|
|
2890
|
-
function
|
|
2891
|
-
const
|
|
2892
|
-
if (
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
return issues;
|
|
3692
|
+
function main_worktree(repository_path) {
|
|
3693
|
+
const git_directory = resolve_git_directory(repository_path);
|
|
3694
|
+
if (git_directory === void 0) return repository_path;
|
|
3695
|
+
if (path4.basename(git_directory) !== GIT_DIRECTORY) return repository_path;
|
|
3696
|
+
return path4.dirname(git_directory);
|
|
2896
3697
|
}
|
|
2897
|
-
function
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2900
|
-
|
|
3698
|
+
function discover_repositories(repository_path, environment2 = process.env) {
|
|
3699
|
+
const main2 = main_worktree(repository_path);
|
|
3700
|
+
const current_owner2 = resolve_current_owner(main2);
|
|
3701
|
+
if (current_owner2 === void 0) return /* @__PURE__ */ new Map();
|
|
3702
|
+
return repo_map_logic.build_repository_map(
|
|
3703
|
+
scan_siblings(path4.dirname(main2)),
|
|
3704
|
+
current_owner2,
|
|
3705
|
+
environment2[OVERRIDE_ENV_KEY]
|
|
3706
|
+
);
|
|
2901
3707
|
}
|
|
2902
|
-
var
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
3708
|
+
var repo_discovery = {
|
|
3709
|
+
OVERRIDE_ENV_KEY,
|
|
3710
|
+
main_worktree,
|
|
3711
|
+
read_origin_url,
|
|
3712
|
+
resolve_current_owner,
|
|
3713
|
+
scan_siblings,
|
|
3714
|
+
discover_repositories
|
|
2906
3715
|
};
|
|
2907
3716
|
|
|
2908
|
-
// scripts/
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
return (value ?? NO_INCREMENT) > NO_INCREMENT;
|
|
3717
|
+
// scripts/discovery/repo-party.ts
|
|
3718
|
+
var FIRST_PARTY = "first-party";
|
|
3719
|
+
var THIRD_PARTY = "third-party";
|
|
3720
|
+
var UNKNOWN = "unknown";
|
|
3721
|
+
function classify4(session_owner, target) {
|
|
3722
|
+
if (session_owner === void 0 || target === void 0) return UNKNOWN;
|
|
3723
|
+
return session_owner.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
|
|
2916
3724
|
}
|
|
2917
|
-
function
|
|
2918
|
-
|
|
2919
|
-
return carry.failures + (change.failures ?? NO_INCREMENT);
|
|
3725
|
+
function target_owner(owner_repo) {
|
|
3726
|
+
return repo_origin.parse_origin_url(`https://${repo_origin.GITHUB_HOST}/${owner_repo}`)?.owner;
|
|
2920
3727
|
}
|
|
2921
|
-
function
|
|
2922
|
-
|
|
2923
|
-
const last = Date.parse(last_outage_at);
|
|
2924
|
-
if (Number.isNaN(last)) return false;
|
|
2925
|
-
return now.getTime() - last <= OUTAGE_FOLD_WINDOW_MS;
|
|
3728
|
+
function current_owner(repository_path = process.cwd()) {
|
|
3729
|
+
return repo_discovery.resolve_current_owner(repository_path);
|
|
2926
3730
|
}
|
|
2927
|
-
|
|
2928
|
-
|
|
3731
|
+
var repo_party = { FIRST_PARTY, THIRD_PARTY, UNKNOWN, classify: classify4, current_owner, target_owner };
|
|
3732
|
+
|
|
3733
|
+
// scripts/lane/lane-reap.ts
|
|
3734
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
3735
|
+
var PGREP_COMMAND = "pgrep";
|
|
3736
|
+
var MATCH_FULL_COMMAND_LINE = "-f";
|
|
3737
|
+
var CHILDREN_OF_FLAG = "-P";
|
|
3738
|
+
var PS_COMMAND2 = "/bin/ps";
|
|
3739
|
+
var PARENT_FORMAT = ["-o", "ppid=", "-p"];
|
|
3740
|
+
var TERMINATE_SIGNAL = "SIGTERM";
|
|
3741
|
+
var PROBE_TIMEOUT_MS3 = 2e3;
|
|
3742
|
+
var LOWEST_CHILD_PID = 2;
|
|
3743
|
+
function parse_pids(printed) {
|
|
3744
|
+
return printed.split("\n").map((line) => Number(line.trim())).filter((pid) => Number.isSafeInteger(pid) && pid >= LOWEST_CHILD_PID);
|
|
3745
|
+
}
|
|
3746
|
+
function run_probe(command, args) {
|
|
3747
|
+
try {
|
|
3748
|
+
return execFileSync3(command, [...args], {
|
|
3749
|
+
encoding: "utf8",
|
|
3750
|
+
timeout: PROBE_TIMEOUT_MS3,
|
|
3751
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
3752
|
+
});
|
|
3753
|
+
} catch {
|
|
3754
|
+
return "";
|
|
3755
|
+
}
|
|
2929
3756
|
}
|
|
2930
|
-
function
|
|
2931
|
-
|
|
2932
|
-
return { outages, last_outage_at: now.toISOString() };
|
|
3757
|
+
function parent_of(pid) {
|
|
3758
|
+
return parse_pids(run_probe(PS_COMMAND2, [...PARENT_FORMAT, String(pid)]))[0];
|
|
2933
3759
|
}
|
|
2934
|
-
function
|
|
2935
|
-
|
|
2936
|
-
|
|
3760
|
+
function terminate(pid) {
|
|
3761
|
+
try {
|
|
3762
|
+
process.kill(pid, TERMINATE_SIGNAL);
|
|
3763
|
+
return true;
|
|
3764
|
+
} catch {
|
|
3765
|
+
return false;
|
|
2937
3766
|
}
|
|
2938
|
-
const is_reachable = has_increment(change.merged) || has_increment(change.failures);
|
|
2939
|
-
return is_reachable ? { outages: NO_INCREMENT, last_outage_at: void 0 } : folded_outage(carry);
|
|
2940
|
-
}
|
|
2941
|
-
function next_state(carry, change, now) {
|
|
2942
|
-
const outage = next_outage(carry, change, now);
|
|
2943
|
-
return {
|
|
2944
|
-
failures: next_failures(carry, change),
|
|
2945
|
-
outages: outage.outages,
|
|
2946
|
-
last_outage_at: outage.last_outage_at
|
|
2947
|
-
};
|
|
2948
3767
|
}
|
|
2949
|
-
var
|
|
3768
|
+
var SYSTEM_PROBES = {
|
|
3769
|
+
matching: (pattern) => parse_pids(run_probe(PGREP_COMMAND, [MATCH_FULL_COMMAND_LINE, pattern])),
|
|
3770
|
+
children_of: (pid) => parse_pids(run_probe(PGREP_COMMAND, [CHILDREN_OF_FLAG, String(pid)])),
|
|
3771
|
+
parent_of,
|
|
3772
|
+
terminate
|
|
3773
|
+
};
|
|
3774
|
+
function ancestry_of(pid, probes) {
|
|
3775
|
+
const ancestry = /* @__PURE__ */ new Set([pid]);
|
|
3776
|
+
let current = probes.parent_of(pid);
|
|
3777
|
+
while (current !== void 0 && !ancestry.has(current)) {
|
|
3778
|
+
ancestry.add(current);
|
|
3779
|
+
current = probes.parent_of(current);
|
|
3780
|
+
}
|
|
3781
|
+
return ancestry;
|
|
3782
|
+
}
|
|
3783
|
+
function own_ancestry(probes = SYSTEM_PROBES) {
|
|
3784
|
+
return ancestry_of(process.pid, probes);
|
|
3785
|
+
}
|
|
3786
|
+
function tree_of(roots, probes) {
|
|
3787
|
+
const tree = [];
|
|
3788
|
+
const pending = [...roots];
|
|
3789
|
+
let next = pending.shift();
|
|
3790
|
+
while (next !== void 0) {
|
|
3791
|
+
if (!tree.includes(next)) {
|
|
3792
|
+
tree.push(next);
|
|
3793
|
+
pending.push(...probes.children_of(next));
|
|
3794
|
+
}
|
|
3795
|
+
next = pending.shift();
|
|
3796
|
+
}
|
|
3797
|
+
return tree;
|
|
3798
|
+
}
|
|
3799
|
+
function reap_child(issue, probes = SYSTEM_PROBES) {
|
|
3800
|
+
const own2 = own_ancestry(probes);
|
|
3801
|
+
const pattern = lane_child_invocation.process_pattern(issue);
|
|
3802
|
+
const roots = probes.matching(pattern).filter((pid) => !own2.has(pid));
|
|
3803
|
+
const doomed = tree_of(roots, probes).filter((pid) => !own2.has(pid));
|
|
3804
|
+
return doomed.filter((pid) => probes.terminate(pid));
|
|
3805
|
+
}
|
|
3806
|
+
var lane_reap = {
|
|
3807
|
+
own_ancestry,
|
|
3808
|
+
parse_pids,
|
|
3809
|
+
reap_child
|
|
3810
|
+
};
|
|
2950
3811
|
|
|
2951
|
-
// scripts/
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
}
|
|
2962
|
-
function is_duplicate_merge(carry, change) {
|
|
2963
|
-
const issue = change.merged_issue;
|
|
2964
|
-
return issue !== void 0 && carry.merged_issues?.includes(issue) === true;
|
|
2965
|
-
}
|
|
2966
|
-
function next_counts(carry, change) {
|
|
2967
|
-
const cuts = change.cuts ?? NO_INCREMENT2;
|
|
2968
|
-
return {
|
|
2969
|
-
merged: carry.merged + (change.merged ?? NO_INCREMENT2),
|
|
2970
|
-
filed: carry.filed + (change.filed ?? NO_INCREMENT2),
|
|
2971
|
-
cuts: carry.cuts + cuts,
|
|
2972
|
-
is_handed_off: cuts > NO_INCREMENT2
|
|
2973
|
-
};
|
|
2974
|
-
}
|
|
2975
|
-
function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
|
|
2976
|
-
if (is_duplicate_merge(carry, change)) return carry;
|
|
2977
|
-
const streak = run_carry_streak.next_state(carry, change, now);
|
|
2978
|
-
const next = {
|
|
2979
|
-
...carry,
|
|
2980
|
-
...next_counts(carry, change),
|
|
2981
|
-
merged_issues: next_merged_issues(carry, change.merged_issue),
|
|
2982
|
-
failures: streak.failures,
|
|
2983
|
-
outages: streak.outages,
|
|
2984
|
-
last_outage_at: streak.last_outage_at,
|
|
2985
|
-
done: next_done(carry, change.done),
|
|
2986
|
-
retrospective: change.retrospective === true || carry.retrospective
|
|
2987
|
-
};
|
|
2988
|
-
stamp_file.write_stamp(target, next);
|
|
2989
|
-
return next;
|
|
3812
|
+
// scripts/lane/lane-registry.ts
|
|
3813
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
3814
|
+
import path5 from "node:path";
|
|
3815
|
+
|
|
3816
|
+
// scripts/git/git-ls-remote.ts
|
|
3817
|
+
var LS_REMOTE_COMMAND = "ls-remote";
|
|
3818
|
+
var HEADS_FLAG = "--heads";
|
|
3819
|
+
var ORIGIN_REMOTE = "origin";
|
|
3820
|
+
var HEADS_REF_PREFIX = "refs/heads/";
|
|
3821
|
+
function ls_remote_branch_arguments(branch_name) {
|
|
3822
|
+
return [LS_REMOTE_COMMAND, HEADS_FLAG, ORIGIN_REMOTE, `${HEADS_REF_PREFIX}${branch_name}`];
|
|
2990
3823
|
}
|
|
2991
|
-
var run_carry_change = { apply_change };
|
|
2992
3824
|
|
|
2993
|
-
// scripts/
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
var
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
var
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
var NO_OWNER = {};
|
|
3007
|
-
var run_carry_schema = z5.object({
|
|
3008
|
-
invocation: z5.string(),
|
|
3009
|
-
started_at: z5.string(),
|
|
3010
|
-
merged: z5.number(),
|
|
3011
|
-
merged_issues: z5.array(z5.number()).optional(),
|
|
3012
|
-
filed: z5.number(),
|
|
3013
|
-
cuts: z5.number(),
|
|
3014
|
-
// Defaulted, so a record written before this field existed parses with a zero streak rather than
|
|
3015
|
-
// failing to read — the same backward-compatibility the optional owner fields below carry.
|
|
3016
|
-
failures: z5.number().default(0),
|
|
3017
|
-
// Defaulted for the same backward-compatibility as `failures` (joshuafolkken/kit#2240).
|
|
3018
|
-
outages: z5.number().default(0),
|
|
3019
|
-
// Optional, so a record written before the outage fold existed still parses (joshuafolkken/kit#2317).
|
|
3020
|
-
last_outage_at: z5.string().optional(),
|
|
3021
|
-
// Optional, so a record written by the previous shape still parses. Read as "no owner declared",
|
|
3022
|
-
// which is the not-provably-live answer rather than a live one.
|
|
3023
|
-
owner_pid: z5.number().optional(),
|
|
3024
|
-
owner_start: z5.string().optional(),
|
|
3025
|
-
is_handed_off: z5.boolean().optional(),
|
|
3026
|
-
done: z5.array(z5.number()).optional(),
|
|
3027
|
-
// Optional, so a record written before the retrospective existed still parses (joshuafolkken/kit#2328).
|
|
3028
|
-
retrospective: z5.boolean().optional()
|
|
3029
|
-
});
|
|
3030
|
-
function carry_path(git_directory) {
|
|
3031
|
-
return stamp_file.stamp_path(CARRY_PREFIX, git_directory);
|
|
3825
|
+
// scripts/git/repository-lock.ts
|
|
3826
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
3827
|
+
import { linkSync, renameSync, rmSync as rmSync2 } from "node:fs";
|
|
3828
|
+
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
3829
|
+
|
|
3830
|
+
// scripts/josh/process-owner.ts
|
|
3831
|
+
import { z as z9 } from "zod";
|
|
3832
|
+
var process_owner_schema = z9.object({ pid: z9.number(), process_start: z9.string().optional() });
|
|
3833
|
+
|
|
3834
|
+
// scripts/git/repository-lock.ts
|
|
3835
|
+
var POLL_INTERVAL_MS = 200;
|
|
3836
|
+
function lock_path(prefix, cwd) {
|
|
3837
|
+
return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd());
|
|
3032
3838
|
}
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3839
|
+
function parse_owner(raw) {
|
|
3840
|
+
if (raw === void 0) return void 0;
|
|
3841
|
+
const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw));
|
|
3842
|
+
return parsed.success ? parsed.data : void 0;
|
|
3036
3843
|
}
|
|
3037
|
-
function
|
|
3844
|
+
function read_owner(target) {
|
|
3845
|
+
return parse_owner(stamp_file.read_stamp_text(target));
|
|
3846
|
+
}
|
|
3847
|
+
function is_owner_gone(owner) {
|
|
3848
|
+
return process_identity.is_same_process(owner.pid, owner.process_start) === false;
|
|
3849
|
+
}
|
|
3850
|
+
function restore(aside, target) {
|
|
3038
3851
|
try {
|
|
3039
|
-
|
|
3040
|
-
|
|
3852
|
+
linkSync(aside, target);
|
|
3853
|
+
} catch {
|
|
3854
|
+
}
|
|
3855
|
+
}
|
|
3856
|
+
function stale_record(target, is_gone2) {
|
|
3857
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
3858
|
+
const owner = parse_owner(raw);
|
|
3859
|
+
return owner !== void 0 && is_gone2(owner) ? raw : void 0;
|
|
3860
|
+
}
|
|
3861
|
+
function move_aside(target) {
|
|
3862
|
+
const aside = `${target}.${String(process.pid)}.${randomUUID3()}`;
|
|
3863
|
+
try {
|
|
3864
|
+
renameSync(target, aside);
|
|
3865
|
+
return aside;
|
|
3041
3866
|
} catch {
|
|
3042
3867
|
return void 0;
|
|
3043
3868
|
}
|
|
3044
3869
|
}
|
|
3045
|
-
function
|
|
3046
|
-
const
|
|
3047
|
-
if (
|
|
3048
|
-
|
|
3870
|
+
function clear_stale(target, is_gone2 = is_owner_gone) {
|
|
3871
|
+
const raw = stale_record(target, is_gone2);
|
|
3872
|
+
if (raw === void 0) return;
|
|
3873
|
+
const aside = move_aside(target);
|
|
3874
|
+
if (aside === void 0) return;
|
|
3875
|
+
if (stamp_file.read_stamp_text(aside) !== raw) restore(aside, target);
|
|
3876
|
+
rmSync2(aside, { force: true });
|
|
3049
3877
|
}
|
|
3050
|
-
function
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
if (carry === void 0) return UNREADABLE_READ3;
|
|
3054
|
-
return { kind: is_expired2(carry, now) ? "expired" : "carried", carry };
|
|
3878
|
+
function claim(target) {
|
|
3879
|
+
clear_stale(target);
|
|
3880
|
+
return stamp_file.create_stamp(target, process_identity.own_fields());
|
|
3055
3881
|
}
|
|
3056
|
-
function
|
|
3057
|
-
|
|
3882
|
+
function release(target) {
|
|
3883
|
+
const owner = read_owner(target);
|
|
3884
|
+
if (owner !== void 0 && process_identity.is_own_process(owner.pid, owner.process_start)) {
|
|
3885
|
+
stamp_file.remove_stamp(target);
|
|
3886
|
+
}
|
|
3058
3887
|
}
|
|
3059
|
-
function
|
|
3060
|
-
|
|
3888
|
+
async function acquire(target, max_wait_ms) {
|
|
3889
|
+
const deadline = Date.now() + max_wait_ms;
|
|
3890
|
+
while (!claim(target)) {
|
|
3891
|
+
if (Date.now() >= deadline) return false;
|
|
3892
|
+
await sleep2(POLL_INTERVAL_MS);
|
|
3893
|
+
}
|
|
3894
|
+
return true;
|
|
3061
3895
|
}
|
|
3062
|
-
function
|
|
3063
|
-
return
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
failures: NO_INCREMENT3,
|
|
3070
|
-
outages: NO_INCREMENT3,
|
|
3071
|
-
owner_pid: owner.pid,
|
|
3072
|
-
owner_start: owner.start
|
|
3073
|
-
};
|
|
3896
|
+
async function with_lock(work, target, max_wait_ms) {
|
|
3897
|
+
if (!await acquire(target, max_wait_ms)) return void 0;
|
|
3898
|
+
try {
|
|
3899
|
+
return await work();
|
|
3900
|
+
} finally {
|
|
3901
|
+
release(target);
|
|
3902
|
+
}
|
|
3074
3903
|
}
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3904
|
+
var repository_lock = { clear_stale, lock_path, with_lock };
|
|
3905
|
+
|
|
3906
|
+
// scripts/git/git-worktree.ts
|
|
3907
|
+
var WORKTREE = "worktree";
|
|
3908
|
+
var WORKTREE_LOCK_PREFIX = "josh-worktree-lock-";
|
|
3909
|
+
var WORKTREE_LOCK_MAX_WAIT_MS = 12e4;
|
|
3910
|
+
async function locked(arguments_) {
|
|
3911
|
+
const target = repository_lock.lock_path(WORKTREE_LOCK_PREFIX);
|
|
3912
|
+
const output = await repository_lock.with_lock(
|
|
3913
|
+
async () => await git_spawn.read(arguments_),
|
|
3914
|
+
target,
|
|
3915
|
+
WORKTREE_LOCK_MAX_WAIT_MS
|
|
3916
|
+
);
|
|
3917
|
+
if (output === void 0) {
|
|
3918
|
+
throw new Error(
|
|
3919
|
+
`git ${arguments_.join(" ")}: timed out waiting for the work-tree lock ${target}`
|
|
3920
|
+
);
|
|
3921
|
+
}
|
|
3922
|
+
return output;
|
|
3078
3923
|
}
|
|
3079
|
-
function
|
|
3080
|
-
|
|
3081
|
-
return begin_carry(target, invocation, owner, now);
|
|
3924
|
+
async function worktree_list() {
|
|
3925
|
+
return await git_spawn.read([WORKTREE, "list", PORCELAIN_FLAG]);
|
|
3082
3926
|
}
|
|
3083
|
-
function
|
|
3084
|
-
const
|
|
3085
|
-
|
|
3086
|
-
owner_pid: owner.pid,
|
|
3087
|
-
owner_start: owner.start,
|
|
3088
|
-
is_handed_off: false
|
|
3089
|
-
};
|
|
3090
|
-
stamp_file.remove_stamp(target);
|
|
3091
|
-
return stamp_file.create_stamp(target, next) ? next : void 0;
|
|
3927
|
+
async function worktree_add(directory, branch_name, start_point) {
|
|
3928
|
+
const flags = start_point === void 0 ? ["add"] : ["add", "--no-track", "-b", branch_name];
|
|
3929
|
+
return await locked([WORKTREE, ...flags, directory, start_point ?? branch_name]);
|
|
3092
3930
|
}
|
|
3093
|
-
function
|
|
3094
|
-
return
|
|
3931
|
+
async function worktree_add_detached(directory, commit2) {
|
|
3932
|
+
return await locked([WORKTREE, "add", "--detach", directory, commit2]);
|
|
3095
3933
|
}
|
|
3096
|
-
function
|
|
3097
|
-
return
|
|
3934
|
+
async function worktree_remove(directory) {
|
|
3935
|
+
return await locked([WORKTREE, "remove", "--force", directory]);
|
|
3098
3936
|
}
|
|
3099
|
-
function
|
|
3100
|
-
return
|
|
3937
|
+
async function worktree_prune() {
|
|
3938
|
+
return await locked([WORKTREE, "prune"]);
|
|
3101
3939
|
}
|
|
3102
|
-
function
|
|
3103
|
-
return
|
|
3940
|
+
async function ls_remote_branch(branch_name) {
|
|
3941
|
+
return await git_spawn.read(ls_remote_branch_arguments(branch_name));
|
|
3104
3942
|
}
|
|
3105
|
-
function
|
|
3106
|
-
|
|
3107
|
-
if (is_foreign_live_owner(carry, request.owner)) return "busy";
|
|
3108
|
-
if (carry.invocation !== request.invocation) return "mismatch";
|
|
3109
|
-
return request.is_adoption ? "resume" : "standing";
|
|
3943
|
+
async function branch_delete(branch_name) {
|
|
3944
|
+
return await git_spawn.read(["branch", "-D", branch_name]);
|
|
3110
3945
|
}
|
|
3111
|
-
|
|
3112
|
-
|
|
3946
|
+
var git_worktree = {
|
|
3947
|
+
branch_delete,
|
|
3948
|
+
ls_remote_branch,
|
|
3949
|
+
worktree_add,
|
|
3950
|
+
worktree_add_detached,
|
|
3951
|
+
worktree_list,
|
|
3952
|
+
worktree_prune,
|
|
3953
|
+
worktree_remove
|
|
3954
|
+
};
|
|
3955
|
+
|
|
3956
|
+
// scripts/lane/lane-environment.ts
|
|
3957
|
+
var LANE_OUTPUT_KEY = "JOSH_LANE_OUTPUT";
|
|
3958
|
+
var LANE_PROVIDER_KEY = "JOSH_LANE_AGENT_PROVIDER";
|
|
3959
|
+
var LANE_ROLE_KEY = "JOSH_LANE_AGENT_ROLE";
|
|
3960
|
+
var LANE_MODEL_KEY = "JOSH_LANE_AGENT_MODEL";
|
|
3961
|
+
var LANE_EFFORT_KEY = "JOSH_LANE_AGENT_EFFORT";
|
|
3962
|
+
var ASSIGNMENT_SEPARATOR = "=";
|
|
3963
|
+
var EXPORT_PREFIX = "export ";
|
|
3964
|
+
var QUOTE_CHARACTERS = /* @__PURE__ */ new Set(['"', "'"]);
|
|
3965
|
+
var MIN_QUOTED_LENGTH = 2;
|
|
3966
|
+
var FIRST_CHARACTER_END = 1;
|
|
3967
|
+
var LAST_CHARACTER_START = -1;
|
|
3968
|
+
function strip_export(line) {
|
|
3969
|
+
const trimmed2 = line.trimStart();
|
|
3970
|
+
return trimmed2.startsWith(EXPORT_PREFIX) ? trimmed2.slice(EXPORT_PREFIX.length).trimStart() : trimmed2;
|
|
3113
3971
|
}
|
|
3114
|
-
function
|
|
3115
|
-
|
|
3972
|
+
function is_key_line(line, key2) {
|
|
3973
|
+
const body = strip_export(line);
|
|
3974
|
+
if (!body.startsWith(key2)) return false;
|
|
3975
|
+
return body.slice(key2.length).trimStart().startsWith(ASSIGNMENT_SEPARATOR);
|
|
3116
3976
|
}
|
|
3117
|
-
function
|
|
3118
|
-
|
|
3977
|
+
function is_seat_line(line) {
|
|
3978
|
+
return is_key_line(line, LANE_SEAT_KEY);
|
|
3119
3979
|
}
|
|
3120
|
-
function
|
|
3121
|
-
|
|
3122
|
-
return read2.carry.retrospective === true;
|
|
3980
|
+
function is_output_line(line) {
|
|
3981
|
+
return is_key_line(line, LANE_OUTPUT_KEY);
|
|
3123
3982
|
}
|
|
3124
|
-
function
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
if (declared === void 0) return void 0;
|
|
3128
|
-
const done = carry.done ?? [];
|
|
3129
|
-
return declared.filter((issue) => !done.includes(issue));
|
|
3983
|
+
function split_lines(content) {
|
|
3984
|
+
const trimmed2 = content.trimEnd();
|
|
3985
|
+
return trimmed2.length === 0 ? [] : trimmed2.split("\n");
|
|
3130
3986
|
}
|
|
3131
|
-
function
|
|
3132
|
-
const
|
|
3133
|
-
|
|
3987
|
+
function is_quoted(raw) {
|
|
3988
|
+
const first = raw.slice(0, FIRST_CHARACTER_END);
|
|
3989
|
+
if (!QUOTE_CHARACTERS.has(first)) return false;
|
|
3990
|
+
return raw.length >= MIN_QUOTED_LENGTH && raw.endsWith(first);
|
|
3134
3991
|
}
|
|
3135
|
-
function
|
|
3136
|
-
return
|
|
3992
|
+
function unquote(raw) {
|
|
3993
|
+
return is_quoted(raw) ? raw.slice(FIRST_CHARACTER_END, LAST_CHARACTER_START) : raw;
|
|
3137
3994
|
}
|
|
3138
|
-
function
|
|
3139
|
-
return
|
|
3995
|
+
function assignment_value(line) {
|
|
3996
|
+
return unquote(line.slice(line.indexOf(ASSIGNMENT_SEPARATOR) + FIRST_CHARACTER_END).trim());
|
|
3140
3997
|
}
|
|
3141
|
-
function
|
|
3142
|
-
|
|
3998
|
+
function read_assignment(content, key2) {
|
|
3999
|
+
const line = split_lines(content).findLast((entry) => is_key_line(entry, key2));
|
|
4000
|
+
return line === void 0 ? void 0 : assignment_value(line);
|
|
3143
4001
|
}
|
|
3144
|
-
function
|
|
3145
|
-
return
|
|
4002
|
+
function read_root_seed(content) {
|
|
4003
|
+
return ports.resolve_seed({ [PORT_SEED_KEY]: read_assignment(content, PORT_SEED_KEY) });
|
|
3146
4004
|
}
|
|
3147
|
-
function
|
|
3148
|
-
|
|
4005
|
+
function read_lane_seat(content) {
|
|
4006
|
+
const raw = read_assignment(content, LANE_SEAT_KEY);
|
|
4007
|
+
return raw === void 0 ? void 0 : ports.resolve_lane({ [LANE_SEAT_KEY]: raw });
|
|
4008
|
+
}
|
|
4009
|
+
function read_lane_ports(content) {
|
|
4010
|
+
const environment2 = {
|
|
4011
|
+
[PORT_SEED_KEY]: read_assignment(content, PORT_SEED_KEY),
|
|
4012
|
+
[LANE_SEAT_KEY]: read_assignment(content, LANE_SEAT_KEY)
|
|
4013
|
+
};
|
|
4014
|
+
return {
|
|
4015
|
+
development: ports.resolve_development_port(environment2),
|
|
4016
|
+
preview: ports.resolve_preview_port(environment2)
|
|
4017
|
+
};
|
|
4018
|
+
}
|
|
4019
|
+
function read_lane_output(content) {
|
|
4020
|
+
const line = split_lines(content).findLast((entry) => is_output_line(entry));
|
|
4021
|
+
const raw = line === void 0 ? void 0 : assignment_value(line);
|
|
4022
|
+
return raw === void 0 || raw.length === 0 ? void 0 : raw;
|
|
3149
4023
|
}
|
|
3150
|
-
function
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
4024
|
+
function read_lane_profile(content) {
|
|
4025
|
+
return agent_role_profile.parse({
|
|
4026
|
+
provider: read_assignment(content, LANE_PROVIDER_KEY),
|
|
4027
|
+
role: read_assignment(content, LANE_ROLE_KEY),
|
|
4028
|
+
model: read_assignment(content, LANE_MODEL_KEY),
|
|
4029
|
+
effort: read_assignment(content, LANE_EFFORT_KEY)
|
|
4030
|
+
});
|
|
3155
4031
|
}
|
|
3156
|
-
function
|
|
3157
|
-
return
|
|
4032
|
+
function replace_assignment(lines, keep, assignment, key2) {
|
|
4033
|
+
return lines.flatMap((entry, index) => {
|
|
4034
|
+
if (index === keep) return [assignment];
|
|
4035
|
+
return is_key_line(entry, key2) ? [] : [entry];
|
|
4036
|
+
});
|
|
3158
4037
|
}
|
|
3159
|
-
function
|
|
3160
|
-
|
|
4038
|
+
function upsert_assignment(content, key2, value) {
|
|
4039
|
+
const assignment = `${key2}${ASSIGNMENT_SEPARATOR}${value}`;
|
|
4040
|
+
const lines = split_lines(content);
|
|
4041
|
+
const last = lines.findLastIndex((entry) => is_key_line(entry, key2));
|
|
4042
|
+
const body = last === -1 ? [...lines, assignment] : replace_assignment(lines, last, assignment, key2);
|
|
4043
|
+
return `${body.join("\n")}
|
|
4044
|
+
`;
|
|
3161
4045
|
}
|
|
3162
|
-
function
|
|
3163
|
-
return
|
|
4046
|
+
function lane_file_content(root_content, seat) {
|
|
4047
|
+
return upsert_assignment(root_content, LANE_SEAT_KEY, String(seat));
|
|
3164
4048
|
}
|
|
3165
|
-
function
|
|
3166
|
-
|
|
4049
|
+
function with_lane_output(content, output, profile) {
|
|
4050
|
+
const recorded = upsert_assignment(content, LANE_OUTPUT_KEY, `"${output}"`);
|
|
4051
|
+
if (profile === void 0) return recorded;
|
|
4052
|
+
const with_provider = upsert_assignment(recorded, LANE_PROVIDER_KEY, profile.provider);
|
|
4053
|
+
const with_role = upsert_assignment(with_provider, LANE_ROLE_KEY, profile.role);
|
|
4054
|
+
const with_model = upsert_assignment(with_role, LANE_MODEL_KEY, profile.model);
|
|
4055
|
+
return upsert_assignment(with_model, LANE_EFFORT_KEY, profile.effort);
|
|
3167
4056
|
}
|
|
3168
|
-
var
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
begin_carry,
|
|
3178
|
-
busy_message: busy_message2,
|
|
3179
|
-
carry_path,
|
|
3180
|
-
classify: classify4,
|
|
3181
|
-
classify_claim,
|
|
3182
|
-
count_refused_message,
|
|
3183
|
-
is_at_cut_cap,
|
|
3184
|
-
describe_carry,
|
|
3185
|
-
end_carry,
|
|
3186
|
-
expired_message,
|
|
3187
|
-
mismatch_message,
|
|
3188
|
-
fresh_carry,
|
|
3189
|
-
is_count_refused,
|
|
3190
|
-
is_expired: is_expired2,
|
|
3191
|
-
is_foreign_live_owner,
|
|
3192
|
-
is_owner_live,
|
|
3193
|
-
lost_message,
|
|
3194
|
-
nothing_to_resume_message,
|
|
3195
|
-
owner_of,
|
|
3196
|
-
parse_carry,
|
|
3197
|
-
read_carry,
|
|
3198
|
-
remaining_of,
|
|
3199
|
-
replace_carry,
|
|
3200
|
-
repository_directory,
|
|
3201
|
-
retrospective_done_of,
|
|
3202
|
-
standing_message,
|
|
3203
|
-
unknown_message: unknown_message3,
|
|
3204
|
-
unreadable_message: unreadable_message3
|
|
4057
|
+
var lane_environment = {
|
|
4058
|
+
is_seat_line,
|
|
4059
|
+
lane_file_content,
|
|
4060
|
+
read_lane_output,
|
|
4061
|
+
read_lane_profile,
|
|
4062
|
+
read_lane_ports,
|
|
4063
|
+
read_lane_seat,
|
|
4064
|
+
read_root_seed,
|
|
4065
|
+
with_lane_output
|
|
3205
4066
|
};
|
|
3206
4067
|
|
|
3207
|
-
// scripts/
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
var
|
|
3211
|
-
var
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
var MS_PER_MINUTE2 = 6e4;
|
|
3215
|
-
var LOG_STALE_MINUTES = 90;
|
|
3216
|
-
var LOG_STALE_MS = LOG_STALE_MINUTES * MS_PER_MINUTE2;
|
|
3217
|
-
var BLOCK_SEPARATOR2 = "\n\n";
|
|
3218
|
-
var GIT_TIMEOUT_MS = 5e3;
|
|
3219
|
-
var GIT_DIRECTORY_ARGUMENTS2 = ["rev-parse", "--absolute-git-dir"];
|
|
3220
|
-
var report_stamp_schema = z6.object({ reported_at: z6.string(), line: z6.string().optional() });
|
|
3221
|
-
function parse_stamp(raw) {
|
|
3222
|
-
const parsed = report_stamp_schema.safeParse(JSON.parse(raw));
|
|
3223
|
-
if (!parsed.success) return void 0;
|
|
3224
|
-
const reported_at = Date.parse(parsed.data.reported_at);
|
|
3225
|
-
return Number.isNaN(reported_at) ? void 0 : reported_at;
|
|
3226
|
-
}
|
|
3227
|
-
function read_last_line(target) {
|
|
3228
|
-
const raw = stamp_file.read_stamp_text(target);
|
|
3229
|
-
if (raw === void 0) return void 0;
|
|
3230
|
-
try {
|
|
3231
|
-
return report_stamp_schema.safeParse(JSON.parse(raw)).data?.line;
|
|
3232
|
-
} catch {
|
|
3233
|
-
return void 0;
|
|
3234
|
-
}
|
|
4068
|
+
// scripts/lane/lane-registry.ts
|
|
4069
|
+
var WORKTREE_PREFIX = "worktree ";
|
|
4070
|
+
var BRANCH_PREFIX = "branch refs/heads/";
|
|
4071
|
+
var BLOCK_SEPARATOR = "\n\n";
|
|
4072
|
+
var ISSUE_PATTERN = /^[1-9]\d*$/u;
|
|
4073
|
+
function line_value(lines, prefix) {
|
|
4074
|
+
return lines.find((line) => line.startsWith(prefix))?.slice(prefix.length);
|
|
3235
4075
|
}
|
|
3236
|
-
function
|
|
3237
|
-
const
|
|
3238
|
-
if (
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
} catch {
|
|
3242
|
-
return void 0;
|
|
3243
|
-
}
|
|
4076
|
+
function seat_from_content(content) {
|
|
4077
|
+
const seat = lane_environment.read_lane_seat(content);
|
|
4078
|
+
if (seat === void 0) return void 0;
|
|
4079
|
+
const port_pair = lane_environment.read_lane_ports(content);
|
|
4080
|
+
return { seat, development_port: port_pair.development, preview_port: port_pair.preview };
|
|
3244
4081
|
}
|
|
3245
|
-
|
|
3246
|
-
|
|
4082
|
+
var EMPTY_SEAT = {
|
|
4083
|
+
seat: void 0,
|
|
4084
|
+
development_port: void 0,
|
|
4085
|
+
preview_port: void 0
|
|
4086
|
+
};
|
|
4087
|
+
function held_seat(content) {
|
|
4088
|
+
if (content === void 0) return EMPTY_SEAT;
|
|
4089
|
+
return seat_from_content(content) ?? EMPTY_SEAT;
|
|
3247
4090
|
}
|
|
3248
|
-
function
|
|
3249
|
-
|
|
3250
|
-
return previous_ms === void 0 || now_ms - previous_ms > LOG_STALE_MS;
|
|
4091
|
+
function read_environment(directory) {
|
|
4092
|
+
return file_reader.read_if_readable(path5.join(directory, ENV_FILE_NAME));
|
|
3251
4093
|
}
|
|
3252
|
-
function
|
|
3253
|
-
if (
|
|
3254
|
-
const
|
|
3255
|
-
|
|
3256
|
-
return raw.split(BLOCK_SEPARATOR2).map((block) => block.trimEnd()).filter((block) => block.length > 0);
|
|
4094
|
+
function branch_issue(branch2) {
|
|
4095
|
+
if (!branch2?.endsWith(lane_paths.LANE_BRANCH_SUFFIX)) return void 0;
|
|
4096
|
+
const issue = branch2.slice(0, -lane_paths.LANE_BRANCH_SUFFIX.length);
|
|
4097
|
+
return ISSUE_PATTERN.test(issue) ? issue : void 0;
|
|
3257
4098
|
}
|
|
3258
|
-
function
|
|
3259
|
-
|
|
3260
|
-
${line}`;
|
|
3261
|
-
const blocks = [...recent_blocks(log_target, is_fresh), block].slice(-LOG_KEEP);
|
|
3262
|
-
stamp_file.write_text_stamp(log_target, `${blocks.join(BLOCK_SEPARATOR2)}
|
|
3263
|
-
`);
|
|
4099
|
+
function is_gone(directory) {
|
|
4100
|
+
return !existsSync3(directory);
|
|
3264
4101
|
}
|
|
3265
|
-
function
|
|
3266
|
-
const
|
|
3267
|
-
const
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
4102
|
+
function build_lane(issue, branch2, directory, is_stranded) {
|
|
4103
|
+
const content = is_stranded ? void 0 : read_environment(directory);
|
|
4104
|
+
const held = held_seat(content);
|
|
4105
|
+
const output = content === void 0 ? void 0 : lane_environment.read_lane_output(content);
|
|
4106
|
+
const profile = content === void 0 ? void 0 : lane_environment.read_lane_profile(content);
|
|
4107
|
+
return {
|
|
4108
|
+
issue,
|
|
4109
|
+
branch: branch2,
|
|
4110
|
+
directory,
|
|
4111
|
+
seat: held.seat,
|
|
4112
|
+
development_port: held.development_port,
|
|
4113
|
+
preview_port: held.preview_port,
|
|
4114
|
+
output,
|
|
4115
|
+
profile,
|
|
4116
|
+
is_stranded
|
|
4117
|
+
};
|
|
3272
4118
|
}
|
|
3273
|
-
function
|
|
3274
|
-
return
|
|
4119
|
+
function is_lane_directory(root, issue, directory) {
|
|
4120
|
+
return directory === lane_paths.lane_directory(root, issue);
|
|
3275
4121
|
}
|
|
3276
|
-
function
|
|
3277
|
-
|
|
4122
|
+
function parse_block(block, root) {
|
|
4123
|
+
const lines = block.split("\n");
|
|
4124
|
+
const directory = line_value(lines, WORKTREE_PREFIX);
|
|
4125
|
+
const branch2 = line_value(lines, BRANCH_PREFIX);
|
|
4126
|
+
const issue = branch_issue(branch2);
|
|
4127
|
+
if (directory === void 0 || branch2 === void 0 || issue === void 0) return void 0;
|
|
4128
|
+
if (!is_lane_directory(root, issue, directory)) return void 0;
|
|
4129
|
+
return build_lane(issue, branch2, directory, is_gone(directory));
|
|
3278
4130
|
}
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
stamp_file.write_stamp(target, { alive: true, pinged_at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
4131
|
+
function is_lane(lane) {
|
|
4132
|
+
return lane !== void 0;
|
|
3282
4133
|
}
|
|
3283
|
-
function
|
|
3284
|
-
|
|
4134
|
+
async function worktree_blocks() {
|
|
4135
|
+
const listing = await git_worktree.worktree_list();
|
|
4136
|
+
return listing.split(BLOCK_SEPARATOR);
|
|
3285
4137
|
}
|
|
3286
|
-
function
|
|
3287
|
-
|
|
3288
|
-
if (!parsed.success || parsed.data.pinged_at === void 0) return void 0;
|
|
3289
|
-
const pinged_ms = Date.parse(parsed.data.pinged_at);
|
|
3290
|
-
return Number.isNaN(pinged_ms) ? void 0 : pinged_ms;
|
|
4138
|
+
async function main_repository_root() {
|
|
4139
|
+
return repo_discovery.main_worktree(await git_command.repository_root());
|
|
3291
4140
|
}
|
|
3292
|
-
function
|
|
3293
|
-
const
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
4141
|
+
async function list_lanes() {
|
|
4142
|
+
const root = lane_paths.lane_root(await main_repository_root());
|
|
4143
|
+
const blocks = await worktree_blocks();
|
|
4144
|
+
const lanes = blocks.map((block) => parse_block(block, root)).filter(is_lane);
|
|
4145
|
+
return lanes.toSorted((left, right) => Number(left.issue) - Number(right.issue));
|
|
4146
|
+
}
|
|
4147
|
+
async function has_lanes_in_flight() {
|
|
4148
|
+
const lanes = await list_lanes();
|
|
4149
|
+
return lanes.some((lane) => !lane.is_stranded);
|
|
3301
4150
|
}
|
|
3302
|
-
function
|
|
3303
|
-
return
|
|
4151
|
+
function used_seats(lanes) {
|
|
4152
|
+
return lanes.map((lane) => lane.seat).filter((seat) => seat !== void 0);
|
|
3304
4153
|
}
|
|
3305
|
-
function
|
|
3306
|
-
|
|
4154
|
+
function unreadable_lanes(lanes) {
|
|
4155
|
+
return lanes.filter((lane) => !lane.is_stranded && lane.seat === void 0);
|
|
3307
4156
|
}
|
|
3308
|
-
function
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
return target === void 0 ? void 0 : read_last_report(target);
|
|
3325
|
-
}
|
|
3326
|
-
var run_progress_clock = {
|
|
3327
|
-
LIFE_PREFIX,
|
|
3328
|
-
LOG_KEEP,
|
|
3329
|
-
LOG_STALE_MS,
|
|
3330
|
-
PROGRESS_PREFIX,
|
|
3331
|
-
append_line,
|
|
3332
|
-
begin_life,
|
|
3333
|
-
end_life,
|
|
3334
|
-
is_life_ended,
|
|
3335
|
-
is_life_fresh,
|
|
3336
|
-
life_target_of,
|
|
3337
|
-
log_path_of,
|
|
3338
|
-
mark,
|
|
3339
|
-
parse_stamp,
|
|
3340
|
-
ping_life,
|
|
3341
|
-
read_last_line,
|
|
3342
|
-
read_last_report,
|
|
3343
|
-
read_last_report_sync,
|
|
3344
|
-
stamp_target_of,
|
|
3345
|
-
stamp_target_sync
|
|
4157
|
+
function find_lane(lanes, issue) {
|
|
4158
|
+
return lanes.find((lane) => lane.issue === issue);
|
|
4159
|
+
}
|
|
4160
|
+
async function find_open_lane(issue) {
|
|
4161
|
+
return find_lane(await list_lanes(), issue);
|
|
4162
|
+
}
|
|
4163
|
+
var lane_registry = {
|
|
4164
|
+
find_lane,
|
|
4165
|
+
find_open_lane,
|
|
4166
|
+
has_lanes_in_flight,
|
|
4167
|
+
list_lanes,
|
|
4168
|
+
main_repository_root,
|
|
4169
|
+
parse_block,
|
|
4170
|
+
read_environment,
|
|
4171
|
+
unreadable_lanes,
|
|
4172
|
+
used_seats
|
|
3346
4173
|
};
|
|
3347
4174
|
|
|
3348
|
-
// scripts/run/run-
|
|
3349
|
-
var
|
|
3350
|
-
var
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
return
|
|
3359
|
-
}
|
|
3360
|
-
async function
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
4175
|
+
// scripts/run/run-headless.ts
|
|
4176
|
+
var HEADLESS_ENV_KEY = "JOSH_RUN_HEADLESS";
|
|
4177
|
+
var HEADLESS_VALUE = "1";
|
|
4178
|
+
function environment() {
|
|
4179
|
+
return { [HEADLESS_ENV_KEY]: HEADLESS_VALUE };
|
|
4180
|
+
}
|
|
4181
|
+
function is_headless(source = process.env) {
|
|
4182
|
+
return source[HEADLESS_ENV_KEY] === HEADLESS_VALUE;
|
|
4183
|
+
}
|
|
4184
|
+
function is_driving(read2) {
|
|
4185
|
+
return read2?.kind === "carried" && read2.carry.is_handed_off !== true;
|
|
4186
|
+
}
|
|
4187
|
+
async function read_carry_here() {
|
|
4188
|
+
const repository2 = await run_carry.repository_directory();
|
|
4189
|
+
return repository2 === void 0 ? void 0 : run_carry.read_carry(run_carry.carry_path(repository2));
|
|
4190
|
+
}
|
|
4191
|
+
async function must_keep_waiting(source = process.env) {
|
|
4192
|
+
const is_candidate2 = is_headless(source) && lane_child_marker.marked_issue(source) === void 0;
|
|
4193
|
+
if (!is_candidate2 || !await lane_registry.has_lanes_in_flight()) return false;
|
|
4194
|
+
return is_driving(await read_carry_here());
|
|
4195
|
+
}
|
|
4196
|
+
async function current_carry() {
|
|
4197
|
+
const read2 = await read_carry_here();
|
|
4198
|
+
return read2?.kind === "carried" ? read2.carry : void 0;
|
|
4199
|
+
}
|
|
4200
|
+
function is_owned_here(carry, ancestry) {
|
|
4201
|
+
return carry.owner_pid !== void 0 && ancestry().has(carry.owner_pid);
|
|
4202
|
+
}
|
|
4203
|
+
function driven_here(read2, ancestry) {
|
|
4204
|
+
if (read2?.kind !== "carried" || !is_driving(read2)) return void 0;
|
|
4205
|
+
return is_owned_here(read2.carry, ancestry) ? read2.carry : void 0;
|
|
4206
|
+
}
|
|
4207
|
+
async function driving_carry(source = process.env, ancestry = lane_reap.own_ancestry) {
|
|
4208
|
+
if (lane_child_marker.marked_issue(source) !== void 0) return void 0;
|
|
4209
|
+
return driven_here(await read_carry_here(), ancestry);
|
|
4210
|
+
}
|
|
4211
|
+
async function is_backlog_parent(source = process.env, ancestry = lane_reap.own_ancestry) {
|
|
4212
|
+
return await driving_carry(source, ancestry) !== void 0;
|
|
4213
|
+
}
|
|
4214
|
+
var run_headless = {
|
|
4215
|
+
HEADLESS_ENV_KEY,
|
|
4216
|
+
current_carry,
|
|
4217
|
+
driving_carry,
|
|
4218
|
+
environment,
|
|
4219
|
+
is_backlog_parent,
|
|
4220
|
+
is_headless,
|
|
4221
|
+
is_owned_here,
|
|
4222
|
+
must_keep_waiting
|
|
3370
4223
|
};
|
|
3371
4224
|
|
|
3372
|
-
// scripts/
|
|
4225
|
+
// scripts/issue/issue-cite.ts
|
|
4226
|
+
var GITHUB_URL_PREFIX = "https://github.com/";
|
|
4227
|
+
var ISSUE_PATH = "/issues/";
|
|
4228
|
+
var SUMMARY_SEPARATOR = " \u2014 ";
|
|
4229
|
+
var REPO_QUALIFIED = /^([^\s/#]+\/[^\s/#]+)#(\d+)$/u;
|
|
4230
|
+
var BARE_NUMBER = /^#?(\d+)$/u;
|
|
4231
|
+
function issue_url(slug, number) {
|
|
4232
|
+
return `${GITHUB_URL_PREFIX}${slug}${ISSUE_PATH}${number}`;
|
|
4233
|
+
}
|
|
4234
|
+
function citation_line(slug, number, summary) {
|
|
4235
|
+
return `[#${number}](${issue_url(slug, number)})${SUMMARY_SEPARATOR}${summary}`;
|
|
4236
|
+
}
|
|
4237
|
+
function citer(slug, titles) {
|
|
4238
|
+
return function cite(number) {
|
|
4239
|
+
if (slug === void 0) return `#${number}`;
|
|
4240
|
+
const title = titles.get(number);
|
|
4241
|
+
return title === void 0 ? `[#${number}](${issue_url(slug, number)})` : citation_line(slug, number, title);
|
|
4242
|
+
};
|
|
4243
|
+
}
|
|
4244
|
+
function qualified_target(token) {
|
|
4245
|
+
const match = REPO_QUALIFIED.exec(token);
|
|
4246
|
+
if (match === null) return void 0;
|
|
4247
|
+
const [, repo = "", number = ""] = match;
|
|
4248
|
+
return { number, repo };
|
|
4249
|
+
}
|
|
4250
|
+
function bare_target(token, default_repo) {
|
|
4251
|
+
const match = BARE_NUMBER.exec(token);
|
|
4252
|
+
if (match === null) return void 0;
|
|
4253
|
+
const [, number = ""] = match;
|
|
4254
|
+
return { number, repo: default_repo };
|
|
4255
|
+
}
|
|
4256
|
+
function parse_target(token, default_repo) {
|
|
4257
|
+
return qualified_target(token) ?? bare_target(token, default_repo);
|
|
4258
|
+
}
|
|
4259
|
+
function label(target) {
|
|
4260
|
+
return target.repo === void 0 ? `#${target.number}` : `${target.repo}#${target.number}`;
|
|
4261
|
+
}
|
|
4262
|
+
function missing_line(target) {
|
|
4263
|
+
return `\u2716 ${label(target)}: issue does not resolve \u2014 check the number and the repository`;
|
|
4264
|
+
}
|
|
4265
|
+
function unreadable_line(target) {
|
|
4266
|
+
return `\u2716 ${label(target)}: could not be read \u2014 a rate limit, expired auth, or a dropped connection`;
|
|
4267
|
+
}
|
|
4268
|
+
function no_repo_line(target) {
|
|
4269
|
+
return `\u2716 ${label(target)}: could not read this repository \u2014 check gh auth and the origin remote`;
|
|
4270
|
+
}
|
|
4271
|
+
var issue_cite = {
|
|
4272
|
+
citation_line,
|
|
4273
|
+
citer,
|
|
4274
|
+
issue_url,
|
|
4275
|
+
missing_line,
|
|
4276
|
+
no_repo_line,
|
|
4277
|
+
parse_target,
|
|
4278
|
+
unreadable_line
|
|
4279
|
+
};
|
|
4280
|
+
|
|
4281
|
+
// scripts/gh/git-gh-api-path.ts
|
|
3373
4282
|
var FULL_PAGE_QUERY = "?per_page=100";
|
|
3374
4283
|
function repo_api_path(repo) {
|
|
3375
4284
|
return `repos/${repo ?? "{owner}/{repo}"}`;
|
|
@@ -3431,6 +4340,36 @@ var git_gh_api_path = {
|
|
|
3431
4340
|
commit_status_api_path
|
|
3432
4341
|
};
|
|
3433
4342
|
|
|
4343
|
+
// scripts/lib/timeouts.ts
|
|
4344
|
+
var FETCH_TIMEOUT_MS = 1e4;
|
|
4345
|
+
var COMMAND_TIMEOUT_MS = 3e4;
|
|
4346
|
+
|
|
4347
|
+
// scripts/lib/error-message.ts
|
|
4348
|
+
function message_of(error) {
|
|
4349
|
+
return error instanceof Error ? error.message : String(error);
|
|
4350
|
+
}
|
|
4351
|
+
var error_text = { message_of };
|
|
4352
|
+
|
|
4353
|
+
// scripts/gh/git-gh-exec.ts
|
|
4354
|
+
import { execa as execa5, execaSync as execaSync2 } from "execa";
|
|
4355
|
+
|
|
4356
|
+
// scripts/gh/git-gh-check.ts
|
|
4357
|
+
import { execa as execa4 } from "execa";
|
|
4358
|
+
var GH_NOT_INSTALLED_MSG = "gh CLI is not installed. Install it from https://cli.github.com/";
|
|
4359
|
+
var gh_check = {};
|
|
4360
|
+
async function run_gh_check() {
|
|
4361
|
+
try {
|
|
4362
|
+
await execa4("gh", ["--version"], { timeout: COMMAND_TIMEOUT_MS });
|
|
4363
|
+
} catch {
|
|
4364
|
+
delete gh_check.promise;
|
|
4365
|
+
throw new Error(GH_NOT_INSTALLED_MSG);
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
async function check_gh_installed() {
|
|
4369
|
+
gh_check.promise ??= run_gh_check();
|
|
4370
|
+
await gh_check.promise;
|
|
4371
|
+
}
|
|
4372
|
+
|
|
3434
4373
|
// scripts/git/parse-json-array.ts
|
|
3435
4374
|
var MALFORMED_JSON = /* @__PURE__ */ Symbol("malformed-json");
|
|
3436
4375
|
function parse_json_loose(raw_json) {
|
|
@@ -3454,52 +4393,18 @@ function read_json_listing(raw_json, element_schema) {
|
|
|
3454
4393
|
return { kind: "unexpected_shape" };
|
|
3455
4394
|
}
|
|
3456
4395
|
}
|
|
3457
|
-
function parse_json_array_safe(raw_json, element_schema) {
|
|
3458
|
-
const value = parse_json_loose(raw_json);
|
|
3459
|
-
if (value === MALFORMED_JSON) return [];
|
|
3460
|
-
return element_schema.array().parse(value);
|
|
3461
|
-
}
|
|
3462
4396
|
function parse_json_object_safe(raw_json, schema) {
|
|
3463
4397
|
const value = parse_json_loose(raw_json);
|
|
3464
4398
|
if (value === MALFORMED_JSON) return void 0;
|
|
3465
4399
|
return schema.parse(value);
|
|
3466
4400
|
}
|
|
3467
4401
|
var parse_json = {
|
|
3468
|
-
|
|
3469
|
-
parse_json_array_or_undefined,
|
|
3470
|
-
parse_json_object_safe,
|
|
3471
|
-
read_json_listing
|
|
4402
|
+
parse_json_object_safe
|
|
3472
4403
|
};
|
|
3473
4404
|
|
|
3474
|
-
// scripts/
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
}
|
|
3478
|
-
var error_text = { message_of };
|
|
3479
|
-
|
|
3480
|
-
// scripts/git/git-gh-exec.ts
|
|
3481
|
-
import { execa as execa4, execaSync as execaSync2 } from "execa";
|
|
3482
|
-
|
|
3483
|
-
// scripts/git/git-gh-check.ts
|
|
3484
|
-
import { execa as execa3 } from "execa";
|
|
3485
|
-
var GH_NOT_INSTALLED_MSG = "gh CLI is not installed. Install it from https://cli.github.com/";
|
|
3486
|
-
var gh_check = {};
|
|
3487
|
-
async function run_gh_check() {
|
|
3488
|
-
try {
|
|
3489
|
-
await execa3("gh", ["--version"]);
|
|
3490
|
-
} catch {
|
|
3491
|
-
delete gh_check.promise;
|
|
3492
|
-
throw new Error(GH_NOT_INSTALLED_MSG);
|
|
3493
|
-
}
|
|
3494
|
-
}
|
|
3495
|
-
async function check_gh_installed() {
|
|
3496
|
-
gh_check.promise ??= run_gh_check();
|
|
3497
|
-
await gh_check.promise;
|
|
3498
|
-
}
|
|
3499
|
-
|
|
3500
|
-
// scripts/git/git-gh-failure.ts
|
|
3501
|
-
import { z as z7 } from "zod";
|
|
3502
|
-
var error_document_schema = z7.object({ status: z7.union([z7.string(), z7.number()]).optional() }).catch({});
|
|
4405
|
+
// scripts/gh/git-gh-failure.ts
|
|
4406
|
+
import { z as z10 } from "zod";
|
|
4407
|
+
var error_document_schema = z10.object({ status: z10.union([z10.string(), z10.number()]).optional() }).catch({});
|
|
3503
4408
|
var GH_FAILURE_FIELD = "gh_failure";
|
|
3504
4409
|
function has_gh_failure(error) {
|
|
3505
4410
|
return error instanceof Error && Object.hasOwn(error, GH_FAILURE_FIELD);
|
|
@@ -3526,7 +4431,7 @@ function failure_of(error) {
|
|
|
3526
4431
|
}
|
|
3527
4432
|
var gh_failure = { attach, classify_stdout, failure_of, parse_response_status };
|
|
3528
4433
|
|
|
3529
|
-
// scripts/
|
|
4434
|
+
// scripts/gh/git-gh-exec.ts
|
|
3530
4435
|
var BODY_FROM_STDIN = "-";
|
|
3531
4436
|
var GH_REQUEST_TIMEOUT_MS = 6e4;
|
|
3532
4437
|
function to_timeout_option(timeout_ms) {
|
|
@@ -3568,7 +4473,7 @@ async function exec_gh_command(arguments_, timeout_ms, cwd) {
|
|
|
3568
4473
|
await check_gh_installed();
|
|
3569
4474
|
const options = to_spawn_options(timeout_ms, cwd);
|
|
3570
4475
|
try {
|
|
3571
|
-
const { stdout } = await
|
|
4476
|
+
const { stdout } = await execa5("gh", arguments_, options);
|
|
3572
4477
|
return stdout.trimEnd();
|
|
3573
4478
|
} catch (error) {
|
|
3574
4479
|
throw to_gh_error(error);
|
|
@@ -3578,7 +4483,7 @@ async function exec_gh_command_with_stdin(input) {
|
|
|
3578
4483
|
await check_gh_installed();
|
|
3579
4484
|
const options = { input: input.stdin_body, ...to_spawn_options(input.timeout_ms, input.cwd) };
|
|
3580
4485
|
try {
|
|
3581
|
-
const { stdout } = await
|
|
4486
|
+
const { stdout } = await execa5("gh", input.args, options);
|
|
3582
4487
|
return stdout.trimEnd();
|
|
3583
4488
|
} catch (error) {
|
|
3584
4489
|
throw to_gh_error(error);
|
|
@@ -3592,20 +4497,20 @@ function parse_status_line(output) {
|
|
|
3592
4497
|
function status_of_failure(error) {
|
|
3593
4498
|
return has_stdout_field(error) ? parse_status_line(error.stdout) : void 0;
|
|
3594
4499
|
}
|
|
3595
|
-
async function exec_gh_api_status(
|
|
4500
|
+
async function exec_gh_api_status(path6, timeout_ms) {
|
|
3596
4501
|
const options = to_spawn_options(timeout_ms);
|
|
3597
4502
|
try {
|
|
3598
4503
|
await check_gh_installed();
|
|
3599
|
-
const { stdout } = await
|
|
4504
|
+
const { stdout } = await execa5("gh", ["api", "--include", "--silent", path6], options);
|
|
3600
4505
|
return parse_status_line(stdout);
|
|
3601
4506
|
} catch (error) {
|
|
3602
4507
|
return status_of_failure(error);
|
|
3603
4508
|
}
|
|
3604
4509
|
}
|
|
3605
|
-
function exec_gh_api_status_sync(
|
|
4510
|
+
function exec_gh_api_status_sync(path6, timeout_ms) {
|
|
3606
4511
|
const options = to_spawn_options(timeout_ms);
|
|
3607
4512
|
try {
|
|
3608
|
-
const { stdout } = execaSync2("gh", ["api", "--include", "--silent",
|
|
4513
|
+
const { stdout } = execaSync2("gh", ["api", "--include", "--silent", path6], options);
|
|
3609
4514
|
return parse_status_line(stdout);
|
|
3610
4515
|
} catch (error) {
|
|
3611
4516
|
return status_of_failure(error);
|
|
@@ -3677,7 +4582,9 @@ var git_gh_exec = {
|
|
|
3677
4582
|
export {
|
|
3678
4583
|
shell_segments,
|
|
3679
4584
|
bash_triggers,
|
|
3680
|
-
|
|
4585
|
+
issue_cite,
|
|
4586
|
+
git_command,
|
|
4587
|
+
git_common_directory,
|
|
3681
4588
|
tail_commands,
|
|
3682
4589
|
filing_cap,
|
|
3683
4590
|
CONTEXT_CUT_THRESHOLD,
|
|
@@ -3685,8 +4592,6 @@ export {
|
|
|
3685
4592
|
agent_session_environment,
|
|
3686
4593
|
agent_role_profile,
|
|
3687
4594
|
backlog_budget,
|
|
3688
|
-
git_command,
|
|
3689
|
-
lane_child_invocation,
|
|
3690
4595
|
run_hold,
|
|
3691
4596
|
run_cut,
|
|
3692
4597
|
run_tail,
|
|
@@ -3703,21 +4608,26 @@ export {
|
|
|
3703
4608
|
RELEASE_CLASSIFICATION_NAMES,
|
|
3704
4609
|
has_any_label,
|
|
3705
4610
|
has_label_name,
|
|
4611
|
+
process_identity,
|
|
4612
|
+
run_event_stream,
|
|
4613
|
+
run_invocation,
|
|
4614
|
+
run_carry,
|
|
4615
|
+
run_event_stream_emit,
|
|
4616
|
+
lane_handoff,
|
|
3706
4617
|
lane_park,
|
|
3707
4618
|
repo_origin,
|
|
3708
4619
|
repo_party,
|
|
4620
|
+
process_owner_schema,
|
|
4621
|
+
lane_registry,
|
|
4622
|
+
run_headless,
|
|
3709
4623
|
FULL_PAGE_QUERY,
|
|
3710
4624
|
git_gh_api_path,
|
|
3711
4625
|
error_text,
|
|
4626
|
+
FETCH_TIMEOUT_MS,
|
|
3712
4627
|
parse_json_array_or_undefined,
|
|
3713
4628
|
read_json_listing,
|
|
3714
4629
|
parse_json_object_safe,
|
|
3715
4630
|
gh_failure,
|
|
3716
4631
|
has_stderr_field,
|
|
3717
|
-
git_gh_exec
|
|
3718
|
-
process_identity,
|
|
3719
|
-
lane_registry,
|
|
3720
|
-
run_invocation,
|
|
3721
|
-
run_carry,
|
|
3722
|
-
run_watcher_guard
|
|
4632
|
+
git_gh_exec
|
|
3723
4633
|
};
|