@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,6 +1,12 @@
|
|
|
1
1
|
import { execa } from 'execa'
|
|
2
2
|
import { git_utilities } from './constants'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
create_spawn_error,
|
|
5
|
+
get_exit_code,
|
|
6
|
+
has_timed_out,
|
|
7
|
+
TIMEOUT_EXIT_CODE,
|
|
8
|
+
} from './git-execa-error'
|
|
9
|
+
import { git_ssh_keepalive } from './git-ssh-keepalive'
|
|
4
10
|
|
|
5
11
|
const MS_PER_SECOND = 1000
|
|
6
12
|
|
|
@@ -33,65 +39,10 @@ const PUSH_TIMEOUT_LABEL = `${String(PUSH_TIMEOUT_SECONDS)}s`
|
|
|
33
39
|
// said no" are different diagnoses, and only the first one is worth retrying.
|
|
34
40
|
const PUSH_TIMEOUT_MESSAGE = 'git push timed out'
|
|
35
41
|
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
// against '128', which this can never equal, so a timed-out bare push is never mistaken for a
|
|
39
|
-
// missing upstream and retried as `--set-upstream`.
|
|
40
|
-
const PUSH_TIMEOUT_EXIT_CODE = 'timeout'
|
|
41
|
-
|
|
42
|
-
// SSH's own liveness probe: three unanswered checks 15 seconds apart, so a connection that dies
|
|
43
|
-
// mid-transfer is noticed in about 45 seconds instead of waiting on the TCP default. The budget
|
|
44
|
-
// above bounds the damage either way; this is what makes the common case fail in seconds rather
|
|
45
|
-
// than sit out the whole budget.
|
|
46
|
-
const SSH_KEEPALIVE_OPTIONS = '-o ServerAliveInterval=15 -o ServerAliveCountMax=3'
|
|
47
|
-
const SSH_COMMAND_VARIABLE = 'GIT_SSH_COMMAND'
|
|
48
|
-
const SSH_LEGACY_VARIABLE = 'GIT_SSH'
|
|
49
|
-
const KEEPALIVE_SSH_COMMAND = `ssh ${SSH_KEEPALIVE_OPTIONS}`
|
|
50
|
-
const SSH_COMMAND_CONFIG_KEY = 'core.sshCommand'
|
|
42
|
+
// `TIMEOUT_EXIT_CODE` is never '128', which `is_upstream_not_set_error` compares against, so a
|
|
43
|
+
// timed-out bare push is never mistaken for a missing upstream and retried as `--set-upstream`.
|
|
51
44
|
const PUSH_SUBCOMMAND = 'push'
|
|
52
45
|
|
|
53
|
-
// Whatever already decides how ssh is invoked, or an empty string when nothing does. git reads three
|
|
54
|
-
// sources in this order — `GIT_SSH_COMMAND`, `core.sshCommand`, then the legacy `GIT_SSH` — and the
|
|
55
|
-
// last one has to be asked as well precisely because it loses: setting `GIT_SSH_COMMAND` on top of a
|
|
56
|
-
// `GIT_SSH=plink.exe` outranks it, so the push would run an ssh binary the user did not choose.
|
|
57
|
-
function to_environment_value(name: string): string {
|
|
58
|
-
return process.env[name]?.trim() ?? ''
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function to_configured_ssh_command(): string {
|
|
62
|
-
const from_command = to_environment_value(SSH_COMMAND_VARIABLE)
|
|
63
|
-
|
|
64
|
-
return from_command === '' ? to_environment_value(SSH_LEGACY_VARIABLE) : from_command
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Whether any of those three sources answered. **A hit means hands off entirely.**
|
|
68
|
-
//
|
|
69
|
-
// Appending the options to a command someone else chose is not safe, because they are OpenSSH's:
|
|
70
|
-
// `plink` and `TortoiseGitPlink` are supported ssh commands on the platform `get_git_command_for_spawn`
|
|
71
|
-
// goes out of its way to handle, and a wrapper script with a fixed argument list is common on any
|
|
72
|
-
// platform — each of them exits on a usage error rather than pushing. Setting the variable while
|
|
73
|
-
// `core.sshCommand` is configured is the same mistake from the other side: the environment wins, so
|
|
74
|
-
// a per-repository key would be silently replaced by a plain `ssh`.
|
|
75
|
-
//
|
|
76
|
-
// What those users lose is the keepalive, not the fix: the budget above still bounds their push, and
|
|
77
|
-
// `ServerAliveInterval` belongs in their own ssh config where it applies to every tool they run.
|
|
78
|
-
async function has_configured_ssh_command(): Promise<boolean> {
|
|
79
|
-
if (to_configured_ssh_command() !== '') return true
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
const git_command_bin = git_utilities.get_git_command_for_spawn()
|
|
83
|
-
// execa runs the binary directly with an argument array and no `shell` option, so CLI
|
|
84
|
-
// args cannot break out of a shell sandbox; the git command and args are internally
|
|
85
|
-
// controlled, never untrusted input. tssecurity:S8705 is a false positive here.
|
|
86
|
-
const { stdout } = await execa(git_command_bin, ['config', '--get', SSH_COMMAND_CONFIG_KEY]) // NOSONAR
|
|
87
|
-
|
|
88
|
-
return stdout.trim() !== ''
|
|
89
|
-
} catch {
|
|
90
|
-
// `git config --get` exits 1 when the key is unset, which is the answer rather than a failure.
|
|
91
|
-
return false
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
46
|
interface PushOptions {
|
|
96
47
|
stdio: 'inherit'
|
|
97
48
|
timeout: number
|
|
@@ -99,12 +50,10 @@ interface PushOptions {
|
|
|
99
50
|
}
|
|
100
51
|
|
|
101
52
|
async function to_push_options(): Promise<PushOptions> {
|
|
102
|
-
const should_keep_alive = !(await has_configured_ssh_command())
|
|
103
|
-
|
|
104
53
|
return {
|
|
105
54
|
stdio: 'inherit',
|
|
106
55
|
timeout: PUSH_TIMEOUT_MS,
|
|
107
|
-
env:
|
|
56
|
+
env: await git_ssh_keepalive.to_environment(),
|
|
108
57
|
}
|
|
109
58
|
}
|
|
110
59
|
|
|
@@ -142,7 +91,7 @@ function to_retry_notice(arguments_list: Array<string>): string {
|
|
|
142
91
|
function create_timeout_error(arguments_list: Array<string>): Error {
|
|
143
92
|
const message = `${PUSH_TIMEOUT_MESSAGE} twice (${PUSH_TIMEOUT_LABEL} each). Re-run it by hand: ${to_manual_command(arguments_list)}`
|
|
144
93
|
|
|
145
|
-
return new Error(message, { cause: { exit_code:
|
|
94
|
+
return new Error(message, { cause: { exit_code: TIMEOUT_EXIT_CODE } })
|
|
146
95
|
}
|
|
147
96
|
|
|
148
97
|
// One push, bounded and retried once — and **only** on a timeout. A push the remote rejected (a
|
|
@@ -164,10 +113,4 @@ const git_push_transport = {
|
|
|
164
113
|
}
|
|
165
114
|
|
|
166
115
|
export { git_push_transport }
|
|
167
|
-
export {
|
|
168
|
-
KEEPALIVE_SSH_COMMAND,
|
|
169
|
-
PUSH_TIMEOUT_MESSAGE,
|
|
170
|
-
PUSH_TIMEOUT_MS,
|
|
171
|
-
SSH_COMMAND_VARIABLE,
|
|
172
|
-
SSH_LEGACY_VARIABLE,
|
|
173
|
-
}
|
|
116
|
+
export { PUSH_TIMEOUT_MESSAGE, PUSH_TIMEOUT_MS }
|
package/scripts/git/git-push.ts
CHANGED
package/scripts/git/git-spawn.ts
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { execa } from 'execa'
|
|
2
2
|
import { git_utilities } from './constants'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
create_spawn_error,
|
|
5
|
+
get_exit_code,
|
|
6
|
+
has_timed_out,
|
|
7
|
+
TIMEOUT_EXIT_CODE,
|
|
8
|
+
} from './git-execa-error'
|
|
9
|
+
import { PUSH_TIMEOUT_MS } from './git-push-transport'
|
|
10
|
+
import { git_ssh_keepalive } from './git-ssh-keepalive'
|
|
4
11
|
|
|
5
12
|
// The one place the ordinary git commands are spawned from (joshuafolkken/kit#1640). It sits in a
|
|
6
13
|
// module of its own rather than inside `git-command.ts` so that a second command module —
|
|
@@ -9,8 +16,8 @@ import { create_spawn_error, get_exit_code } from './git-execa-error'
|
|
|
9
16
|
// `CLAUDE.md` prohibits, so a new caller imports this one instead of growing its own.
|
|
10
17
|
//
|
|
11
18
|
// **`git-push-transport.ts` is the one deliberate exception among the command modules** and is not a
|
|
12
|
-
// second helper of this kind: a push needs a
|
|
13
|
-
//
|
|
19
|
+
// second helper of this kind: a push needs a transport-fault retry that no other command has, so it
|
|
20
|
+
// spawns git itself. The timeout it carries is shared here by `read_remote` / `with_output_remote`. Those two files are the spawn sites of the ordinary command
|
|
14
21
|
// modules — the claim stops there. Other parts of this package spawn git for their own purposes
|
|
15
22
|
// (`scripts/run/run-progress-clock.ts`, `scripts/propagate/propagate-git.ts`,
|
|
16
23
|
// `scripts/doctor/doctor-io.ts`, `scripts/git/git-fixture-workspace.ts`), and an audit of how the git
|
|
@@ -26,6 +33,73 @@ async function read(arguments_: Array<string>): Promise<string> {
|
|
|
26
33
|
return stdout.trimEnd()
|
|
27
34
|
}
|
|
28
35
|
|
|
36
|
+
// The budget for a git call that talks to the remote — `fetch` and `pull` (joshuafolkken/kit#2942).
|
|
37
|
+
// `read` and `with_output` wait without end, and a `git fetch --prune` under `josh main:sync` sat on
|
|
38
|
+
// a dead ssh connection for 37 minutes, stalling the unattended backlog driver whose merge step runs
|
|
39
|
+
// it. The push's budget is reused rather than a second number chosen: both transfer objects over the
|
|
40
|
+
// same transport, and that one is already read off what a healthy transfer costs here.
|
|
41
|
+
const REMOTE_TIMEOUT_MS = PUSH_TIMEOUT_MS
|
|
42
|
+
const MS_PER_SECOND = 1000
|
|
43
|
+
|
|
44
|
+
// A budget kill is reported as a timeout, never as whatever the killed process printed first, and
|
|
45
|
+
// `cause` carries the same `TIMEOUT_EXIT_CODE` a timed-out push does. Unlike the push it is not
|
|
46
|
+
// retried here: what the issue needed is that the wait ends, and a failure then surfaces to the
|
|
47
|
+
// caller — `run:merge` raises a failed `main:sync` — instead of a second budget doubling the wait.
|
|
48
|
+
function to_remote_error(command: string, error: unknown, timeout_ms: number): Error {
|
|
49
|
+
if (!has_timed_out(error)) return create_spawn_error(command, get_exit_code(error))
|
|
50
|
+
|
|
51
|
+
const seconds = String(Math.round(timeout_ms / MS_PER_SECOND))
|
|
52
|
+
|
|
53
|
+
return new Error(`git ${command} timed out after ${seconds}s`, {
|
|
54
|
+
cause: { exit_code: TIMEOUT_EXIT_CODE },
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface RemoteOptions {
|
|
59
|
+
stdio?: 'inherit'
|
|
60
|
+
timeout: number
|
|
61
|
+
env: Record<string, string>
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// One remote call, bounded and kept alive. execa kills git on the budget; the ssh keepalive is what
|
|
65
|
+
// makes ssh — which git does not kill with itself — exit on a dead connection as well.
|
|
66
|
+
async function spawn_remote(arguments_: Array<string>, options: RemoteOptions): Promise<string> {
|
|
67
|
+
const git_cmd = git_utilities.get_git_command_for_spawn()
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// execa runs the binary directly with an argument array and no `shell` option, so CLI
|
|
71
|
+
// args cannot break out of a shell sandbox; the git command and args are internally
|
|
72
|
+
// controlled, never untrusted input. tssecurity:S8705 is a false positive here.
|
|
73
|
+
const { stdout } = await execa(git_cmd, arguments_, options) // NOSONAR
|
|
74
|
+
|
|
75
|
+
return typeof stdout === 'string' ? stdout.trimEnd() : ''
|
|
76
|
+
} catch (error) {
|
|
77
|
+
throw to_remote_error(arguments_[0] ?? '', error, options.timeout)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// `read` for a call that reaches the remote. The budget is a parameter only so a test can hold it to
|
|
82
|
+
// seconds; every production caller takes the default.
|
|
83
|
+
async function read_remote(
|
|
84
|
+
arguments_: Array<string>,
|
|
85
|
+
timeout_ms: number = REMOTE_TIMEOUT_MS,
|
|
86
|
+
): Promise<string> {
|
|
87
|
+
return await spawn_remote(arguments_, {
|
|
88
|
+
timeout: timeout_ms,
|
|
89
|
+
env: await git_ssh_keepalive.to_environment(),
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// `with_output` for a call that reaches the remote — the output stays on the terminal, as a pull's
|
|
94
|
+
// progress and a credential prompt need.
|
|
95
|
+
async function with_output_remote(command: string, arguments_list: Array<string>): Promise<void> {
|
|
96
|
+
await spawn_remote([command, ...arguments_list], {
|
|
97
|
+
stdio: 'inherit',
|
|
98
|
+
timeout: REMOTE_TIMEOUT_MS,
|
|
99
|
+
env: await git_ssh_keepalive.to_environment(),
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
|
|
29
103
|
async function with_output(command: string, arguments_list: Array<string>): Promise<void> {
|
|
30
104
|
const git_command_bin = git_utilities.get_git_command_for_spawn()
|
|
31
105
|
|
|
@@ -41,7 +115,9 @@ async function with_output(command: string, arguments_list: Array<string>): Prom
|
|
|
41
115
|
|
|
42
116
|
const git_spawn = {
|
|
43
117
|
read,
|
|
118
|
+
read_remote,
|
|
44
119
|
with_output,
|
|
120
|
+
with_output_remote,
|
|
45
121
|
}
|
|
46
122
|
|
|
47
123
|
export { git_spawn }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { execa } from 'execa'
|
|
2
|
+
import { git_utilities } from './constants'
|
|
3
|
+
|
|
4
|
+
// The ssh environment every git network call runs under (joshuafolkken/kit#2942). It began inside
|
|
5
|
+
// `git-push-transport.ts` as the push's own (joshuafolkken/kit#1251), and moved here when the fetch
|
|
6
|
+
// and pull of `josh main:sync` turned out to need the same thing: a dead connection under a `git
|
|
7
|
+
// fetch` was waited on for 37 minutes, stalling the unattended backlog driver behind it.
|
|
8
|
+
//
|
|
9
|
+
// SSH's own liveness probe: three unanswered checks 15 seconds apart, so a connection that dies
|
|
10
|
+
// mid-transfer is noticed in about 45 seconds instead of waiting on the TCP default. The caller's
|
|
11
|
+
// timeout bounds the damage either way; this is what makes the common case fail in seconds rather
|
|
12
|
+
// than sit out the whole budget — and, because ssh exits on its own, it is also what leaves no ssh
|
|
13
|
+
// behind: git does not kill its transport child when it is itself killed on a timeout.
|
|
14
|
+
const SSH_KEEPALIVE_OPTIONS = '-o ServerAliveInterval=15 -o ServerAliveCountMax=3'
|
|
15
|
+
const SSH_COMMAND_VARIABLE = 'GIT_SSH_COMMAND'
|
|
16
|
+
const SSH_LEGACY_VARIABLE = 'GIT_SSH'
|
|
17
|
+
const KEEPALIVE_SSH_COMMAND = `ssh ${SSH_KEEPALIVE_OPTIONS}`
|
|
18
|
+
const SSH_COMMAND_CONFIG_KEY = 'core.sshCommand'
|
|
19
|
+
|
|
20
|
+
// Whatever already decides how ssh is invoked, or an empty string when nothing does. git reads three
|
|
21
|
+
// sources in this order — `GIT_SSH_COMMAND`, `core.sshCommand`, then the legacy `GIT_SSH` — and the
|
|
22
|
+
// last one has to be asked as well precisely because it loses: setting `GIT_SSH_COMMAND` on top of a
|
|
23
|
+
// `GIT_SSH=plink.exe` outranks it, so git would run an ssh binary the user did not choose.
|
|
24
|
+
function to_environment_value(name: string): string {
|
|
25
|
+
return process.env[name]?.trim() ?? ''
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function to_configured_ssh_command(): string {
|
|
29
|
+
const from_command = to_environment_value(SSH_COMMAND_VARIABLE)
|
|
30
|
+
|
|
31
|
+
return from_command === '' ? to_environment_value(SSH_LEGACY_VARIABLE) : from_command
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Whether any of those three sources answered. **A hit means hands off entirely.**
|
|
35
|
+
//
|
|
36
|
+
// Appending the options to a command someone else chose is not safe, because they are OpenSSH's:
|
|
37
|
+
// `plink` and `TortoiseGitPlink` are supported ssh commands on the platform `get_git_command_for_spawn`
|
|
38
|
+
// goes out of its way to handle, and a wrapper script with a fixed argument list is common on any
|
|
39
|
+
// platform — each of them exits on a usage error rather than connecting. Setting the variable while
|
|
40
|
+
// `core.sshCommand` is configured is the same mistake from the other side: the environment wins, so
|
|
41
|
+
// a per-repository key would be silently replaced by a plain `ssh`.
|
|
42
|
+
//
|
|
43
|
+
// What those users lose is the keepalive, not the fix: the caller's timeout still bounds the call,
|
|
44
|
+
// and `ServerAliveInterval` belongs in their own ssh config where it applies to every tool they run.
|
|
45
|
+
async function has_configured_ssh_command(): Promise<boolean> {
|
|
46
|
+
if (to_configured_ssh_command() !== '') return true
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
const git_command_bin = git_utilities.get_git_command_for_spawn()
|
|
50
|
+
// execa runs the binary directly with an argument array and no `shell` option, so CLI
|
|
51
|
+
// args cannot break out of a shell sandbox; the git command and args are internally
|
|
52
|
+
// controlled, never untrusted input. tssecurity:S8705 is a false positive here.
|
|
53
|
+
const { stdout } = await execa(git_command_bin, ['config', '--get', SSH_COMMAND_CONFIG_KEY]) // NOSONAR
|
|
54
|
+
|
|
55
|
+
return stdout.trim() !== ''
|
|
56
|
+
} catch {
|
|
57
|
+
// `git config --get` exits 1 when the key is unset, which is the answer rather than a failure.
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The `env` a git network spawn passes to execa: the keepalive command, or nothing at all.
|
|
63
|
+
async function to_environment(): Promise<Record<string, string>> {
|
|
64
|
+
const should_keep_alive = !(await has_configured_ssh_command())
|
|
65
|
+
|
|
66
|
+
return should_keep_alive ? { [SSH_COMMAND_VARIABLE]: KEEPALIVE_SSH_COMMAND } : {}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const git_ssh_keepalive = {
|
|
70
|
+
to_environment,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { git_ssh_keepalive }
|
|
74
|
+
export { KEEPALIVE_SSH_COMMAND, SSH_COMMAND_VARIABLE, SSH_LEGACY_VARIABLE }
|
|
@@ -62,6 +62,7 @@ async function stage_untracked_files(files: ReadonlyArray<string>): Promise<void
|
|
|
62
62
|
if (files.length === 0) return
|
|
63
63
|
|
|
64
64
|
for (const file of files) {
|
|
65
|
+
// eslint-disable-next-line no-await-in-loop -- git add holds the index lock, so two at once fail
|
|
65
66
|
await git_command.add_path(file)
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { animation_helpers, type AnimationOptions } from '
|
|
1
|
+
import { animation_helpers, type AnimationOptions } from '#scripts/lib/animation-helpers'
|
|
2
2
|
import { REQUIRED_STATUS_LENGTH, STAGED_STATUS_INDEX, UNTRACKED_FILE_PREFIX } from './constants'
|
|
3
3
|
import { git_command } from './git-command'
|
|
4
4
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { parseArgs } from 'node:util'
|
|
3
|
+
import { git_pr } from '#scripts/gh/git-pr'
|
|
3
4
|
import { cli_body } from '#scripts/josh/cli-body'
|
|
4
5
|
import { test_red_commit } from '#scripts/test/test-red-commit'
|
|
5
6
|
import { git_branch } from './git-branch'
|
|
6
7
|
import { git_commit } from './git-commit'
|
|
7
8
|
import { git_error } from './git-error'
|
|
8
9
|
import { git_issue, type IssueInfo } from './git-issue'
|
|
9
|
-
import { git_pr } from './git-pr'
|
|
10
10
|
import { git_preflight } from './git-preflight'
|
|
11
11
|
import { git_prompt, type WorkflowConfirmations } from './git-prompt'
|
|
12
12
|
import { git_push } from './git-push'
|
|
@@ -89,6 +89,7 @@ async function delete_each(names: ReadonlyArray<string>): Promise<PruneResult> {
|
|
|
89
89
|
|
|
90
90
|
for (const name of names) {
|
|
91
91
|
try {
|
|
92
|
+
// eslint-disable-next-line no-await-in-loop -- branch deletions write the same refs, one at a time
|
|
92
93
|
await git_spawn.read(['branch', '-d', name])
|
|
93
94
|
result.deleted.push(name)
|
|
94
95
|
} catch {
|
|
@@ -100,9 +101,10 @@ async function delete_each(names: ReadonlyArray<string>): Promise<PruneResult> {
|
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
// `fetch --prune` first, because `[gone]` is read from the remote-tracking refs and those outlive the
|
|
103
|
-
// remote branch until something prunes them.
|
|
104
|
+
// remote branch until something prunes them. The fetch is the one call here that reaches the remote,
|
|
105
|
+
// so it is the one bounded (joshuafolkken/kit#2942).
|
|
104
106
|
async function prune(default_branch: string): Promise<PruneResult> {
|
|
105
|
-
await git_spawn.
|
|
107
|
+
await git_spawn.read_remote(['fetch', '--prune'])
|
|
106
108
|
|
|
107
109
|
return await delete_each(await read_candidates(default_branch))
|
|
108
110
|
}
|
|
@@ -114,7 +114,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
114
114
|
process.exitCode = await run(argv)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const main_merge = {
|
|
117
|
+
const main_merge = { run }
|
|
118
118
|
|
|
119
119
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
120
120
|
|
package/scripts/git/main-sync.ts
CHANGED
|
@@ -70,9 +70,27 @@ async function prune_quietly(default_branch: string): Promise<void> {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
// **The local default branch is fast-forwarded before it is checked out** (joshuafolkken/kit#2979).
|
|
74
|
+
// A run's ledger file is committed on its feature branch and merged; a line appended afterwards leaves
|
|
75
|
+
// it dirty, and git refuses to check out a stale default branch that lacks the file — so `run:tail`'s
|
|
76
|
+
// sync failed exactly when the flush after it had work. Once fast-forwarded, the default branch holds
|
|
77
|
+
// the committed file and the checkout carries the dirty lines over (the same step the flush takes,
|
|
78
|
+
// joshuafolkken/kit#2462). Skipped on the default branch, where `fetch` refuses to update the checked-out
|
|
79
|
+
// ref; a refusal elsewhere — a local default ahead of origin — is left to the checkout and pull to judge.
|
|
80
|
+
async function fast_forward_quietly(default_branch: string): Promise<void> {
|
|
81
|
+
if ((await git_command.branch()) === default_branch) return
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
await git_command.fast_forward_local(default_branch)
|
|
85
|
+
} catch {
|
|
86
|
+
// The checkout and `pull --ff-only` below decide, exactly as before this step existed.
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
async function synchronize(): Promise<number> {
|
|
74
91
|
const default_branch = await git_command.get_default_branch()
|
|
75
92
|
|
|
93
|
+
await fast_forward_quietly(default_branch)
|
|
76
94
|
await git_command.checkout(default_branch)
|
|
77
95
|
await git_command.pull_fast_forward()
|
|
78
96
|
await prune_quietly(default_branch)
|
|
@@ -115,7 +133,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
115
133
|
process.exitCode = await run(argv)
|
|
116
134
|
}
|
|
117
135
|
|
|
118
|
-
const main_sync = {
|
|
136
|
+
const main_sync = { run }
|
|
119
137
|
|
|
120
138
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
121
139
|
|
|
@@ -2,7 +2,9 @@ import { randomUUID } from 'node:crypto'
|
|
|
2
2
|
import { linkSync, renameSync, rmSync } from 'node:fs'
|
|
3
3
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
4
4
|
import { process_identity } from '#scripts/josh/process-identity'
|
|
5
|
+
import { process_owner_schema, type ProcessOwner } from '#scripts/josh/process-owner'
|
|
5
6
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
7
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
6
8
|
import { git_common_directory } from './git-common-directory'
|
|
7
9
|
|
|
8
10
|
// One holder at a time per repository, for work that every work tree of that repository shares
|
|
@@ -14,32 +16,29 @@ import { git_common_directory } from './git-common-directory'
|
|
|
14
16
|
|
|
15
17
|
const POLL_INTERVAL_MS = 200
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
pid: number
|
|
19
|
-
process_start?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
type IsGone = (owner: LockOwner) => boolean
|
|
19
|
+
type IsGone = (owner: ProcessOwner) => boolean
|
|
23
20
|
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
// Without a `cwd` the read keeps the inherited git location variables, as every other git call of the
|
|
22
|
+
// running process does; an explicit `cwd` clears them so that directory is the one answered for.
|
|
23
|
+
function lock_path(prefix: string, cwd?: string): string {
|
|
24
|
+
return stamp_file.stamp_path(prefix, git_common_directory.repository(cwd) ?? cwd ?? process.cwd())
|
|
26
25
|
}
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
// A record that is not JSON, or is JSON of any other shape — `null`, an array, an object with no
|
|
28
|
+
// numeric `pid` — is unreadable rather than an owner, so it is never judged and never cleared.
|
|
29
|
+
function parse_owner(raw: string | undefined): ProcessOwner | undefined {
|
|
29
30
|
if (raw === undefined) return undefined
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return undefined
|
|
35
|
-
}
|
|
32
|
+
const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw))
|
|
33
|
+
|
|
34
|
+
return parsed.success ? parsed.data : undefined
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
function read_owner(target: string):
|
|
37
|
+
function read_owner(target: string): ProcessOwner | undefined {
|
|
39
38
|
return parse_owner(stamp_file.read_stamp_text(target))
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
function is_owner_gone(owner:
|
|
41
|
+
function is_owner_gone(owner: ProcessOwner): boolean {
|
|
43
42
|
return process_identity.is_same_process(owner.pid, owner.process_start) === false
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -111,6 +110,7 @@ async function acquire(target: string, max_wait_ms: number): Promise<boolean> {
|
|
|
111
110
|
|
|
112
111
|
while (!claim(target)) {
|
|
113
112
|
if (Date.now() >= deadline) return false
|
|
113
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
114
114
|
await sleep(POLL_INTERVAL_MS)
|
|
115
115
|
}
|
|
116
116
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { git_spawn } from '
|
|
1
|
+
import { git_spawn } from '#scripts/git/git-spawn'
|
|
2
2
|
|
|
3
3
|
// The one place a sanctioned `git stash pop` is targeted by its message rather than its stack
|
|
4
4
|
// position (joshuafolkken/kit#2050). The stash is a single repository-wide stack shared by every
|
|
@@ -47,7 +47,7 @@ function to_request(parsed: ParsedValues): Request | undefined {
|
|
|
47
47
|
return { message, dir: parsed.values.dir }
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const stash_pop_args = { USAGE,
|
|
50
|
+
const stash_pop_args = { USAGE, read_arguments, to_request }
|
|
51
51
|
|
|
52
52
|
export type { Request }
|
|
53
53
|
export { stash_pop_args }
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { repository_lock } from '
|
|
1
|
+
import { repository_lock } from '#scripts/git/repository-lock'
|
|
2
2
|
|
|
3
3
|
// One stash sweep at a time per repository (joshuafolkken/kit#2701). The stash is a single stack every
|
|
4
4
|
// work tree shares, and a `backlogrun` runs one sweep per lane seat at once: two sweeps that each
|
|
@@ -11,7 +11,7 @@ const LOCK_PREFIX = 'josh-stash-sweep-lock-'
|
|
|
11
11
|
// wait; the cap only bounds a holder that hung, and a sweep that gives up keeps its entries.
|
|
12
12
|
const MAX_WAIT_MS = 30_000
|
|
13
13
|
|
|
14
|
-
function lock_path(cwd
|
|
14
|
+
function lock_path(cwd?: string): string {
|
|
15
15
|
return repository_lock.lock_path(LOCK_PREFIX, cwd)
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -25,6 +25,6 @@ async function with_lock<T>(
|
|
|
25
25
|
return await repository_lock.with_lock(work, target, max_wait_ms)
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const stash_sweep_lock = { clear_stale: repository_lock.clear_stale,
|
|
28
|
+
const stash_sweep_lock = { clear_stale: repository_lock.clear_stale, with_lock }
|
|
29
29
|
|
|
30
30
|
export { stash_sweep_lock }
|
|
@@ -122,7 +122,7 @@ async function spelling_diagnostics(
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const edited_cspell = { format_unknown_words,
|
|
125
|
+
const edited_cspell = { format_unknown_words, spelling_diagnostics }
|
|
126
126
|
|
|
127
127
|
export type { CspellRunner }
|
|
128
128
|
export { edited_cspell, MAX_DIAGNOSTIC_CHARS }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { text } from 'node:stream/consumers'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
import { report_no_payload, run_hook } from './format-edited-file'
|
|
5
|
+
|
|
6
|
+
// The `PostToolUse` hook's entry, kept apart from `format-edited-file.ts` for the reason
|
|
7
|
+
// `pretool-guard-cli.ts` gives (joshuafolkken/kit#2922): `codex-hook-adapter.ts` imports that module,
|
|
8
|
+
// so a self-invoke left in it lands in a shared chunk and the bundled hook never runs.
|
|
9
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
10
|
+
if (process.stdin.isTTY) {
|
|
11
|
+
report_no_payload()
|
|
12
|
+
} else {
|
|
13
|
+
await run_hook(await text(process.stdin))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { existsSync } from 'node:fs'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { text } from 'node:stream/consumers'
|
|
5
4
|
import { fileURLToPath } from 'node:url'
|
|
6
5
|
import { resolve_local_bin, resolve_package_bin } from '#scripts/build/local-bin'
|
|
7
6
|
import { ESLINT_EDIT_CACHE_FLAGS } from '#scripts/josh/josh-command-types'
|
|
@@ -328,6 +327,7 @@ async function run_command(command: FormatCommand, project_root: string): Promis
|
|
|
328
327
|
let outcome: CommandOutcome = { exit_code: 0, stdout: '' }
|
|
329
328
|
|
|
330
329
|
for (const invocation of resolve_invocations(command, project_root)) {
|
|
330
|
+
// eslint-disable-next-line no-await-in-loop -- a fallback route runs only when the previous one failed to start
|
|
331
331
|
outcome = await spawn_invocation(invocation, project_root)
|
|
332
332
|
if (!is_start_failure(outcome)) return outcome
|
|
333
333
|
}
|
|
@@ -375,6 +375,7 @@ async function collect_unfixed(
|
|
|
375
375
|
|
|
376
376
|
for (const command of plan) {
|
|
377
377
|
try {
|
|
378
|
+
// eslint-disable-next-line no-await-in-loop -- formatters rewrite the same file, in plan order
|
|
378
379
|
unfixed = eslint_unfixed(command, await runner(command, project_root)) ?? unfixed
|
|
379
380
|
} catch {
|
|
380
381
|
// One formatter failing to start is not a reason to skip the next: prettier runs last, and
|
|
@@ -482,14 +483,6 @@ async function run_hook(payload: string): Promise<void> {
|
|
|
482
483
|
if (context !== undefined) process.stdout.write(`${build_envelope(context)}\n`)
|
|
483
484
|
}
|
|
484
485
|
|
|
485
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
486
|
-
if (process.stdin.isTTY) {
|
|
487
|
-
report_no_payload()
|
|
488
|
-
} else {
|
|
489
|
-
await run_hook(await text(process.stdin))
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
486
|
export {
|
|
494
487
|
build_envelope,
|
|
495
488
|
compose_context,
|
|
@@ -501,7 +494,9 @@ export {
|
|
|
501
494
|
plan_commands,
|
|
502
495
|
plan_daemon_restart,
|
|
503
496
|
relative_to_root,
|
|
497
|
+
report_no_payload,
|
|
504
498
|
resolve_invocations,
|
|
499
|
+
run_hook,
|
|
505
500
|
select_invocation,
|
|
506
501
|
ESLINT_DAEMON,
|
|
507
502
|
MAX_DIAGNOSTIC_CHARS,
|