@joshuafolkken/kit 1.1166.0 → 1.1229.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/.claude-plugin/plugin.json +1 -1
- package/.claude/settings.json +2 -2
- package/.claude/skills/dependency-update/SKILL.md +4 -8
- package/.claude/skills/epic-commands/SKILL.md +2 -2
- package/.claude/skills/epic-commands/epic-bundle.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +2 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +6 -4
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -5
- package/.claude/skills/workflow-commands/backlogrun-park.md +29 -9
- package/.claude/skills/workflow-commands/backlogrun-progress.md +7 -2
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +24 -15
- package/.claude/skills/workflow-commands/chain-rule.md +1 -1
- package/.claude/skills/workflow-commands/delegation.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +5 -0
- package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
- package/.claude/skills/workflow-commands/halfrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +10 -5
- package/.claude/skills/workflow-commands/prerequisite.md +2 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +1 -1
- package/.codex/hooks.json +2 -2
- package/.cursorrules +6 -41
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/auto-tag.yml +3 -4
- package/.github/workflows/ci.yml +47 -33
- package/.github/workflows/dependabot-auto-merge.yml +13 -6
- package/.github/workflows/publish.yml +48 -4
- package/.github/workflows/sonar-qube.yml +3 -0
- package/.pnpmfile.mjs +4 -3
- package/.prettierignore +8 -2
- package/CLAUDE.md +18 -20
- package/README.md +26 -19
- package/SECURITY.md +15 -1
- package/dist/CLAUDE.md +18 -20
- package/dist/commands/document-section-cli.js +734 -0
- package/dist/hooks/audit-provision.js +346 -0
- package/dist/hooks/batch-guard.js +5 -4
- package/dist/hooks/{chunk-DYAVAM6S.js → chunk-55HHG5PX.js} +1405 -631
- package/dist/hooks/{chunk-A6P7PN7P.js → chunk-5VMKCCC4.js} +25 -10
- package/dist/hooks/chunk-5VNDSNG3.js +12 -0
- package/dist/hooks/{chunk-5KTCMCOT.js → chunk-6HJJXRBX.js} +4 -2
- package/dist/hooks/chunk-CDY4NFQG.js +15 -0
- package/dist/hooks/chunk-ELCN5LCH.js +135 -0
- package/dist/hooks/{chunk-ENA7P5FB.js → chunk-F56MFS4B.js} +3 -3
- package/dist/hooks/{chunk-ANJ2WGFD.js → chunk-FIVDHQGT.js} +7 -6
- package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
- package/dist/hooks/{chunk-GU5MATVE.js → chunk-JUDKDCDP.js} +499 -389
- package/dist/hooks/{chunk-ZDZ555YH.js → chunk-NV2JRZZO.js} +743 -909
- package/dist/hooks/{chunk-V2BTOZHT.js → chunk-RNWHN5BP.js} +3 -3
- package/dist/hooks/{chunk-URJA6XY4.js → chunk-TQNPDZNH.js} +4 -4
- package/dist/hooks/{chunk-GYNGP7HI.js → chunk-VC3PZPZO.js} +1 -1
- package/dist/hooks/codex-hook-adapter.js +14 -12
- package/dist/hooks/duplicate-read-guard.js +6 -5
- package/dist/hooks/format-edited.js +4 -3
- package/dist/hooks/inputs.json +232 -210
- package/dist/hooks/investigation-guard.js +6 -5
- package/dist/hooks/pretool-guard.js +12 -10
- package/dist/hooks/session-lang.js +2 -4
- package/dist/hooks/stop-guard.js +81 -59
- package/dist/josh.js +872 -75
- package/dist/version/index.d.ts +7 -2
- package/dist/version/index.js +152 -75
- package/eslint/base.js +23 -1
- package/eslint/rules/code-quality.js +3 -0
- package/eslint/rules/early-return-one-liner.js +98 -0
- package/eslint/rules/unicorn.js +16 -1
- package/package.json +7 -6
- package/pnpm-workspace.yaml +9 -4
- package/prettier/basic.d.ts +3 -1
- package/prettier/index.d.ts +3 -1
- package/prettier/static.d.ts +3 -1
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +4 -4
- package/prompts/collaboration-workflow/glossary.md +1 -1
- package/prompts/collaboration-workflow/operating-rules.md +17 -9
- package/prompts/collaboration-workflow/overview.md +2 -2
- package/prompts/collaboration-workflow/principles.md +14 -12
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +6 -6
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +1 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +12 -2
- package/prompts/collaboration-workflow/wip-cap.md +10 -10
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +1 -1
- package/scripts/agent/agent-headless.ts +29 -0
- package/scripts/agent/agent-launch-environment.ts +6 -2
- package/scripts/agent/codex-agent-argv.ts +2 -1
- package/scripts/auto-ok/auto-ok-cli.ts +1 -1
- package/scripts/backlog/backlog-arrival.ts +3 -3
- package/scripts/backlog/backlog-budget.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +135 -0
- package/scripts/backlog/backlog-drive-cli.ts +11 -137
- package/scripts/backlog/backlog-drive-launch.ts +39 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +3 -5
- package/scripts/backlog/backlog-drive-named.ts +3 -3
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-owner.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +1 -1
- package/scripts/backlog/backlog-drive.ts +1 -1
- package/scripts/backlog/backlog-next.ts +31 -9
- package/scripts/backlog/backlog-offer-cli.ts +6 -6
- package/scripts/backlog/backlog-offer.ts +1 -1
- package/scripts/backlog/backlog-plan-cli.ts +7 -6
- package/scripts/backlog/backlog-pool.ts +57 -11
- package/scripts/backlog/backlog-rank.ts +18 -9
- package/scripts/backlog/backlog-ready.ts +1 -1
- package/scripts/backlog/backlog-restructure.ts +152 -0
- package/scripts/backlog/backlog-scope.ts +1 -1
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +1 -1
- package/scripts/backlog/backlog-waves.ts +15 -17
- package/scripts/build/build-codex-hooks.ts +3 -1
- package/scripts/build/build-commands.ts +66 -0
- package/scripts/build/build-hooks.ts +2 -1
- package/scripts/build/build-library.ts +12 -3
- package/scripts/build/build.ts +70 -0
- package/scripts/build/local-bin.ts +3 -13
- package/scripts/cost-runtime/context-cut-threshold.ts +1 -9
- package/scripts/cost-runtime/cost-verdict.ts +15 -28
- package/scripts/delegation/investigation-reads.ts +3 -1
- package/scripts/discovery/repo-origin.ts +5 -5
- package/scripts/doctor/doctor-consumer.ts +2 -2
- package/scripts/doctor/doctor-io.ts +2 -3
- package/scripts/document/capped-print-part.ts +30 -0
- package/scripts/document/capped-print.ts +3 -4
- package/scripts/document/document-byte-budget.ts +11 -2
- package/scripts/document/document-scan.ts +117 -0
- package/scripts/document/document-section.ts +143 -16
- package/scripts/document/entry-read-budget.ts +5 -3
- package/scripts/document/entry-read-set.ts +10 -89
- package/scripts/document/read-set-cost.ts +98 -0
- package/scripts/epic/epic-add-body.ts +1 -0
- package/scripts/epic/epic-audit-checks.ts +1 -1
- package/scripts/epic/epic-audit-rationale.ts +4 -3
- package/scripts/epic/epic-bundle-cli.ts +14 -3
- package/scripts/epic/epic-bundle-poll.ts +41 -0
- package/scripts/epic/epic-busy.ts +1 -1
- package/scripts/epic/epic-candidate-confirm.ts +3 -2
- package/scripts/epic/epic-classify.ts +1 -1
- package/scripts/epic/epic-cli-argv.ts +78 -46
- package/scripts/epic/epic-cli-remove.ts +11 -19
- package/scripts/epic/epic-cli.ts +74 -73
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +1 -1
- package/scripts/epic/epic-cross-repo.ts +5 -5
- package/scripts/epic/epic-graph.ts +1 -1
- package/scripts/epic/epic-index.ts +1 -1
- package/scripts/epic/epic-issue.ts +2 -6
- package/scripts/epic/epic-lane-offer.ts +2 -2
- package/scripts/epic/epic-next.ts +29 -42
- package/scripts/epic/epic-solo-stale.ts +1 -1
- package/scripts/epic/epic-triage.ts +8 -4
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/followup/git-followup-finish.ts +2 -2
- package/scripts/followup/git-followup-label.ts +2 -2
- package/scripts/followup/git-followup-merged.ts +2 -2
- package/scripts/followup/git-followup-stages.ts +9 -0
- package/scripts/followup/git-pr-followup-checks.ts +142 -0
- package/scripts/followup/git-pr-followup.ts +5 -130
- package/scripts/gate/core-budget.ts +69 -1
- package/scripts/gate/gate-plan.ts +47 -7
- package/scripts/gate/gate-skip.ts +38 -7
- package/scripts/gate/hook-gate-reuse.ts +12 -10
- package/scripts/gate/pre-commit-type-check.ts +4 -1
- package/scripts/gate/project-checks.ts +6 -9
- package/scripts/gate/type-check-step.ts +2 -3
- package/scripts/gate/verification-gate.ts +27 -8
- package/scripts/gh/git-gh-api-path.ts +2 -2
- package/scripts/gh/git-gh-issue-rest.ts +3 -3
- package/scripts/gh/git-gh-issue-write.ts +53 -7
- package/scripts/gh/git-gh-issue.ts +5 -3
- package/scripts/gh/git-gh-pr-read.ts +68 -19
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr.ts +5 -1
- package/scripts/gh/git-pr-ai-review.ts +1 -1
- package/scripts/gh/git-pr-checks-eval.ts +9 -3
- package/scripts/gh/git-pr-checks-parse.ts +1 -1
- package/scripts/gh/git-pr-checks-watch.ts +6 -5
- package/scripts/gh/git-pr-checks.ts +18 -6
- package/scripts/gh/git-pr-coderabbit.ts +1 -1
- package/scripts/gh/git-pr-error.ts +1 -3
- package/scripts/gh/git-pr.ts +9 -13
- package/scripts/gh/github-issue-url.ts +2 -2
- package/scripts/git/constants.ts +12 -6
- package/scripts/git/git-command.ts +20 -218
- package/scripts/git/git-diff-reads.ts +225 -0
- package/scripts/git/git-error.ts +4 -12
- package/scripts/git/git-pre-push-hook.ts +139 -0
- package/scripts/git/git-prompt.ts +2 -6
- package/scripts/git/{schemas.ts → git-schemas.ts} +2 -0
- package/scripts/git/git-spawn-sync.ts +3 -1
- package/scripts/git/git-spawn.ts +1 -1
- package/scripts/git/git-staging.ts +4 -6
- package/scripts/git/git-status.ts +3 -9
- package/scripts/git/main-merge.ts +57 -21
- package/scripts/hooks/codex-hook-adapter.ts +1 -1
- package/scripts/hooks/edited-cspell.ts +2 -4
- package/scripts/hooks/format-edited-file.ts +3 -12
- package/scripts/hooks/pre-push-unit.ts +31 -9
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/run-hook.sh +5 -4
- package/scripts/hooks/stop-guard.ts +5 -3
- package/scripts/init/init-actions.ts +0 -5
- package/scripts/init/init-ai-copy.ts +13 -2
- package/scripts/init/init-logic-json-merge.ts +19 -0
- package/scripts/init/init-logic-secretlint.ts +7 -7
- package/scripts/init/init-logic-workspace.ts +41 -2
- package/scripts/init/init-logic.ts +16 -26
- package/scripts/init/init.ts +5 -15
- package/scripts/init/initial-commit.ts +4 -4
- package/scripts/init/kit-development-versions.ts +40 -0
- package/scripts/init/kit-setup-state.ts +2 -2
- package/scripts/init/start-exec.ts +68 -19
- package/scripts/init/start-setup-pr.ts +9 -9
- package/scripts/init/start-steps.ts +6 -10
- package/scripts/issue/defect-rate-cli.ts +1 -1
- package/scripts/issue/git-next-issues.ts +1 -1
- package/scripts/issue/issue-auto-ok.ts +1 -1
- package/scripts/issue/issue-backlinks-cli.ts +2 -2
- package/scripts/issue/issue-backlinks.ts +9 -9
- package/scripts/issue/issue-comment-cli.ts +19 -13
- package/scripts/issue/issue-file-cli.ts +45 -18
- package/scripts/issue/issue-file.ts +24 -1
- package/scripts/issue/issue-scout-closed.ts +1 -1
- package/scripts/issue/issue-state-cli.ts +30 -74
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +11 -0
- package/scripts/josh/josh-commands-ai.ts +4 -4
- package/scripts/josh/josh-commands-backlog.ts +4 -1
- package/scripts/josh/josh-commands-development.ts +11 -1
- package/scripts/josh/josh-commands-document.ts +1 -0
- package/scripts/josh/josh-commands-lane.ts +22 -0
- package/scripts/josh/josh-commands-maintenance.ts +4 -4
- package/scripts/josh/josh-commands-run.ts +12 -7
- package/scripts/josh/josh-in-process.ts +28 -9
- package/scripts/josh/josh-logic.ts +33 -15
- package/scripts/josh/process-identity.ts +1 -3
- package/scripts/josh/session-language-cli.ts +3 -4
- package/scripts/lane/lane-await.ts +5 -1
- package/scripts/lane/lane-child-invocation.ts +2 -2
- package/scripts/lane/lane-cli.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +14 -10
- package/scripts/lane/lane-environment.ts +5 -1
- package/scripts/lane/lane-handoff.ts +1 -1
- package/scripts/lane/lane-install.ts +2 -13
- package/scripts/lane/lane-launch-cli.ts +35 -3
- package/scripts/lane/lane-ledger.ts +145 -0
- package/scripts/lane/lane-leftover.ts +1 -1
- package/scripts/lane/lane-load.ts +108 -0
- package/scripts/lane/lane-measure-cli.ts +149 -0
- package/scripts/lane/lane-occupancy.ts +3 -0
- package/scripts/lane/lane-reap.ts +1 -3
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-stats.ts +224 -0
- package/scripts/lane/lane-vacant.ts +36 -0
- package/scripts/lane/openai-lane-ship.ts +2 -2
- package/scripts/lane/openai-lane-supervisor-owner.ts +180 -0
- package/scripts/lane/openai-lane-supervisor.ts +7 -165
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +35 -0
- package/scripts/lib/animation-helpers.ts +2 -2
- package/scripts/lib/buffered-process.ts +3 -7
- package/scripts/lib/cli-flags.ts +71 -1
- package/scripts/lib/spawn-exit.ts +2 -2
- package/scripts/lib/timeouts.ts +35 -2
- package/scripts/lines/line-budget.ts +4 -6
- package/scripts/notify/telegram-notify.ts +26 -1
- package/scripts/notify/telegram-test.ts +6 -0
- package/scripts/observations/observation-ledger-line.ts +6 -6
- package/scripts/observations/observation-ledger-migrate.ts +55 -4
- package/scripts/observations/observation-ledger.ts +26 -7
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/propagate/propagate-git.ts +1 -1
- package/scripts/propagate/propagate-publish.ts +2 -2
- package/scripts/propagate/propagate-steps.ts +20 -15
- package/scripts/propagate/propagate.ts +36 -27
- package/scripts/refactor/import-graph.ts +18 -1
- package/scripts/refactor/refactor-lint.ts +4 -4
- package/scripts/repo/repository-labels.ts +2 -2
- package/scripts/repo/required-checks-logic.ts +1 -3
- package/scripts/review/live-evidence.ts +2 -4
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +1 -1
- package/scripts/review/review-findings-cli.ts +1 -3
- package/scripts/rules/decision-oracle-batch.ts +128 -0
- package/scripts/rules/decision-oracle-tokens.ts +21 -0
- package/scripts/rules/decision-oracle.ts +8 -120
- package/scripts/rules/delivered-rules.ts +26 -182
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/early-heartbeat.ts +3 -3
- package/scripts/rules/git-argv.ts +1 -1
- package/scripts/rules/git-force.ts +1 -1
- package/scripts/rules/implementation-cut.ts +2 -2
- package/scripts/rules/index-guard.ts +1 -1
- package/scripts/rules/issue-comments.ts +118 -0
- package/scripts/rules/{issue-fold.ts → issue-fold-rule.ts} +2 -2
- package/scripts/rules/lane-background.ts +2 -2
- package/scripts/rules/lane-park.ts +18 -0
- package/scripts/rules/lane-split-park.ts +128 -0
- package/scripts/rules/oracle-firing.ts +1 -1
- package/scripts/rules/poll-loop.ts +1 -1
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +59 -4
- package/scripts/rules/{run-tail.ts → run-tail-rule.ts} +2 -2
- package/scripts/rules/shell-body-trigger.ts +1 -1
- package/scripts/rules/stop-rules.ts +18 -7
- package/scripts/rules/test-declared-commit.ts +4 -4
- package/scripts/rules/wip-cap.ts +63 -0
- package/scripts/run/{run-carry-args.ts → carry/run-carry-args.ts} +37 -13
- package/scripts/run/{run-carry-change.ts → carry/run-carry-change.ts} +29 -7
- package/scripts/run/{run-carry-cli.ts → carry/run-carry-cli.ts} +4 -6
- package/scripts/run/{run-carry.ts → carry/run-carry.ts} +12 -6
- package/scripts/run/{run-cut-args.ts → cut/run-cut-args.ts} +1 -1
- package/scripts/run/{run-cut-cli.ts → cut/run-cut-cli.ts} +3 -3
- package/scripts/run/{run-cut-report.ts → cut/run-cut-report.ts} +2 -2
- package/scripts/run/{run-cut.ts → cut/run-cut.ts} +1 -1
- package/scripts/run/{run-entry-cli.ts → entry/run-entry-cli.ts} +11 -11
- package/scripts/run/{run-entry.ts → entry/run-entry.ts} +2 -2
- package/scripts/run/{run-event-scope.ts → event/run-event-scope.ts} +1 -1
- package/scripts/run/{run-event-stream-emit.ts → event/run-event-stream-emit.ts} +1 -1
- package/scripts/run/{run-event-stream.ts → event/run-event-stream.ts} +16 -2
- package/scripts/run/{run-hold-cli.ts → hold/run-hold-cli.ts} +5 -5
- package/scripts/run/{run-merge-cli.ts → merge/run-merge-cli.ts} +10 -5
- package/scripts/run/{run-merge-steps.ts → merge/run-merge-steps.ts} +53 -5
- package/scripts/run/{run-merge.ts → merge/run-merge.ts} +1 -1
- package/scripts/run/{run-progress-cli.ts → progress/run-progress-cli.ts} +1 -1
- package/scripts/run/{run-progress-config.ts → progress/run-progress-config.ts} +2 -17
- package/scripts/run/{run-progress-read.ts → progress/run-progress-read.ts} +5 -5
- package/scripts/run/{run-progress.ts → progress/run-progress.ts} +1 -1
- package/scripts/run/{run-review-steps.ts → review/run-review-steps.ts} +2 -3
- package/scripts/run/run-ending.ts +2 -2
- package/scripts/run/run-halfrun-resume.ts +6 -1
- package/scripts/run/run-headless.ts +1 -1
- package/scripts/run/run-invocation.ts +85 -84
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +1 -1
- package/scripts/run/run-preflight.ts +6 -6
- package/scripts/run/run-prep-cli.ts +1 -1
- package/scripts/run/run-prrun-resume.ts +1 -1
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +2 -2
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +3 -3
- package/scripts/run/run-step.ts +2 -2
- package/scripts/run/run-stop-notify.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +2 -2
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +5 -3
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/run/{run-ship-cli.ts → ship/run-ship-cli.ts} +29 -8
- package/scripts/run/{run-ship-detach.ts → ship/run-ship-detach.ts} +3 -3
- package/scripts/run/ship/run-ship-lock.ts +50 -0
- package/scripts/run/{run-ship-next.ts → ship/run-ship-next.ts} +13 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +66 -0
- package/scripts/run/{run-ship-preflight.ts → ship/run-ship-preflight.ts} +6 -2
- package/scripts/run/{run-ship-probe.ts → ship/run-ship-probe.ts} +2 -2
- package/scripts/run/{run-ship-return.ts → ship/run-ship-return.ts} +10 -6
- package/scripts/run/{run-ship-review-steps.ts → ship/run-ship-review-steps.ts} +3 -3
- package/scripts/run/{run-ship-scoped.ts → ship/run-ship-scoped.ts} +10 -1
- package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +13 -0
- package/scripts/run/{run-ship-steps.ts → ship/run-ship-steps.ts} +15 -8
- package/scripts/run/ship/run-ship-stop-text.ts +13 -0
- package/scripts/run/ship/run-ship-sync.ts +128 -0
- package/scripts/run/{run-ship.ts → ship/run-ship.ts} +6 -0
- package/scripts/run/{run-tidy-lanes.ts → tidy/run-tidy-lanes.ts} +1 -1
- package/scripts/run/{run-wake-cli.ts → wake/run-wake-cli.ts} +31 -9
- package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +3 -3
- package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +99 -17
- package/scripts/run/{run-wake-handoff.ts → wake/run-wake-handoff.ts} +1 -1
- package/scripts/run/{run-wake-loop.ts → wake/run-wake-loop.ts} +8 -2
- package/scripts/run/wake/run-wake-restart.ts +58 -0
- package/scripts/run/{run-wake-session.ts → wake/run-wake-session.ts} +3 -3
- package/scripts/run/{run-wake.ts → wake/run-wake.ts} +1 -1
- package/scripts/safe-chain/preinstall-command.ts +20 -21
- package/scripts/safe-chain/project-config.ts +19 -15
- package/scripts/sync/sync-ai-files.ts +1 -1
- package/scripts/sync/sync-configs.ts +2 -1
- package/scripts/sync/sync.ts +15 -2
- package/scripts/test/test-red-logic.ts +17 -2
- package/scripts/test/test-red.ts +8 -7
- package/scripts/test/unit-worker-share.ts +1 -0
- package/scripts/time-runtime/time-background.ts +5 -1
- package/scripts/time-runtime/time-instant.ts +3 -1
- package/scripts/time-runtime/time-spans.ts +6 -139
- package/scripts/time-runtime/time-tool-call.ts +160 -0
- package/scripts/time-runtime/time-transcript-line.ts +27 -1
- package/scripts/version/effective-upstream.ts +2 -20
- package/scripts/version/latest-corepack.ts +17 -17
- package/scripts/version/latest-regression.ts +1 -1
- package/scripts/version/latest-update.ts +4 -4
- package/scripts/version/npm-registry.ts +20 -5
- package/scripts/version/publishable-range-check.ts +2 -2
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +48 -38
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +40 -0
- package/scripts/version/upgrade-shell-command.ts +48 -8
- package/scripts/version/version-check-logic.ts +23 -14
- package/scripts/version/version-commands.ts +23 -11
- package/scripts/version/version-remote.ts +28 -13
- package/templates/pnpm-workspace.basic.yaml +4 -0
- package/templates/workflows/dependabot-auto-merge.yml +5 -5
- package/templates/workflows/github-release.yml +2 -0
- package/scripts/build/build-config-merge.ts +0 -27
- package/scripts/build/build-managed-marker.ts +0 -27
- package/scripts/build/build-self-sync-guard.ts +0 -27
- package/scripts/build/build-version.ts +0 -26
- package/scripts/version/preinstall-version-update.ts +0 -86
- /package/scripts/overrides/{schemas.ts → overrides-schemas.ts} +0 -0
- /package/scripts/run/{run-carry-conversation.ts → carry/run-carry-conversation.ts} +0 -0
- /package/scripts/run/{run-carry-reclaim.ts → carry/run-carry-reclaim.ts} +0 -0
- /package/scripts/run/{run-carry-stash.ts → carry/run-carry-stash.ts} +0 -0
- /package/scripts/run/{run-carry-streak.ts → carry/run-carry-streak.ts} +0 -0
- /package/scripts/run/{run-cut-handoff.ts → cut/run-cut-handoff.ts} +0 -0
- /package/scripts/run/{run-entry-stop.ts → entry/run-entry-stop.ts} +0 -0
- /package/scripts/run/{run-event-cli.ts → event/run-event-cli.ts} +0 -0
- /package/scripts/run/{run-event-follow.ts → event/run-event-follow.ts} +0 -0
- /package/scripts/run/{run-event-render.ts → event/run-event-render.ts} +0 -0
- /package/scripts/run/{run-event-watch.ts → event/run-event-watch.ts} +0 -0
- /package/scripts/run/{run-hold.ts → hold/run-hold.ts} +0 -0
- /package/scripts/run/{run-progress-args.ts → progress/run-progress-args.ts} +0 -0
- /package/scripts/run/{run-progress-clock.ts → progress/run-progress-clock.ts} +0 -0
- /package/scripts/run/{run-review-cli.ts → review/run-review-cli.ts} +0 -0
- /package/scripts/run/{run-review.ts → review/run-review.ts} +0 -0
- /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
- /package/scripts/run/{run-tidy-cli.ts → tidy/run-tidy-cli.ts} +0 -0
- /package/scripts/run/{run-tidy-stashes.ts → tidy/run-tidy-stashes.ts} +0 -0
- /package/scripts/run/{run-tidy.ts → tidy/run-tidy.ts} +0 -0
|
@@ -2,6 +2,7 @@ import { FULL_PAGE_QUERY, git_gh_api_path } from './git-gh-api-path'
|
|
|
2
2
|
import { git_gh_exec } from './git-gh-exec'
|
|
3
3
|
import { git_gh_helpers } from './git-gh-helpers'
|
|
4
4
|
import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
|
|
5
|
+
import { to_gh_state } from './git-gh-rest-state'
|
|
5
6
|
|
|
6
7
|
// Reading pull requests through REST, in the answers `gh pr view` used to give.
|
|
7
8
|
//
|
|
@@ -81,14 +82,31 @@ interface PullMergeState {
|
|
|
81
82
|
is_merged: boolean
|
|
82
83
|
merged_at: string | undefined
|
|
83
84
|
head_sha: string | undefined
|
|
85
|
+
// `josh ship` reads `DIRTY` here to re-merge a conflicting pull request (joshuafolkken/kit#3221).
|
|
86
|
+
merge_state_status: string | undefined
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
type PullNumberRead =
|
|
87
90
|
{ kind: 'read'; pr_number: number } | { kind: 'missing' } | { kind: 'unreadable'; cause: unknown }
|
|
88
91
|
|
|
92
|
+
// The branch-keyed detail read, in the same three answers. `missing` and `unreadable` are the
|
|
93
|
+
// resolution's own; `unreadable` also covers a resolved number whose detail read failed, which every
|
|
94
|
+
// branch-keyed reader used to fold into "no pull request" (joshuafolkken/kit#3263).
|
|
95
|
+
type PullRead = Exclude<PullNumberRead, { kind: 'read' }> | { kind: 'read'; pull: RestPull }
|
|
96
|
+
|
|
89
97
|
// The lookups still in flight, keyed the same way the resolved numbers are.
|
|
90
98
|
const pending_pr_number_by_branch = new Map<string, Promise<PullNumberRead>>()
|
|
91
99
|
|
|
100
|
+
// The detail reads, keyed by number and remembered for the life of the command
|
|
101
|
+
// (joshuafolkken/kit#3263). `josh followup` asks `pr_get_body` and `pr_get_url` in one tick — the
|
|
102
|
+
// same `GET /pulls/{N}` each time. The promise is stored, so readers in one tick share the request as
|
|
103
|
+
// well as its answer; a read that fails is dropped and re-tried, the rule the number memo holds.
|
|
104
|
+
// **Every write to a pull request clears it** through `forget_pr_numbers`, and the two state readers
|
|
105
|
+
// never read it: `pr_get_merge_state` answers where the pull request stands *now*, which `josh ship`
|
|
106
|
+
// asks again after every merge it pushes, and `pr_view` decides whether `josh git -y` writes onto the
|
|
107
|
+
// pull request — after a commit and a push its preflight read would otherwise outlast.
|
|
108
|
+
const pull_by_number = new Map<number, Promise<RestPull>>()
|
|
109
|
+
|
|
92
110
|
async function fetch_pr_number_read(branch_name: string): Promise<PullNumberRead> {
|
|
93
111
|
try {
|
|
94
112
|
const pr_number = await fetch_pr_number(branch_name)
|
|
@@ -127,10 +145,11 @@ async function start_pr_number_read(branch_name: string): Promise<PullNumberRead
|
|
|
127
145
|
}
|
|
128
146
|
}
|
|
129
147
|
|
|
130
|
-
// Defined after the
|
|
148
|
+
// Defined after the maps it clears, so the memos are declared before anything reaches them.
|
|
131
149
|
function forget_pr_numbers(): void {
|
|
132
150
|
pr_number_by_branch.clear()
|
|
133
151
|
pending_pr_number_by_branch.clear()
|
|
152
|
+
pull_by_number.clear()
|
|
134
153
|
}
|
|
135
154
|
|
|
136
155
|
async function read_pr_number(branch_name: string): Promise<PullNumberRead> {
|
|
@@ -141,9 +160,9 @@ async function read_pr_number(branch_name: string): Promise<PullNumberRead> {
|
|
|
141
160
|
}
|
|
142
161
|
|
|
143
162
|
// `undefined` covers both "this branch has no pull request" and "the lookup failed", which is the
|
|
144
|
-
// distinction `gh pr view` never made either —
|
|
145
|
-
//
|
|
146
|
-
//
|
|
163
|
+
// distinction `gh pr view` never made either — the *display* reads here fold them together on
|
|
164
|
+
// purpose: the comment readers answer `undefined` either way. The callers that act on the absence
|
|
165
|
+
// rather than displaying it — `require_pr_number`, `pr_exists` and `pr_view` — opt out.
|
|
147
166
|
async function resolve_pr_number(branch_name: string): Promise<number | undefined> {
|
|
148
167
|
const read = await read_pr_number(branch_name)
|
|
149
168
|
|
|
@@ -183,19 +202,43 @@ async function read_pull(pr_number: number): Promise<RestPull> {
|
|
|
183
202
|
return git_gh_pr_rest.parse_rest_pull(json)
|
|
184
203
|
}
|
|
185
204
|
|
|
205
|
+
// The identity check keeps a failure from evicting a read that `forget_pr_numbers` already replaced.
|
|
206
|
+
async function read_remembered_pull(pr_number: number): Promise<RestPull> {
|
|
207
|
+
const pending = pull_by_number.get(pr_number) ?? read_pull(pr_number)
|
|
208
|
+
|
|
209
|
+
pull_by_number.set(pr_number, pending)
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
return await pending
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (pull_by_number.get(pr_number) === pending) pull_by_number.delete(pr_number)
|
|
215
|
+
throw error
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
186
219
|
// One pull request named by its branch: the resolution, then the detail read that carries
|
|
187
220
|
// `mergeable` and `mergeable_state`, which the lookup listing does not.
|
|
188
|
-
async function read_pull_of_branch(
|
|
189
|
-
|
|
190
|
-
|
|
221
|
+
async function read_pull_of_branch(
|
|
222
|
+
branch_name: string,
|
|
223
|
+
read: (pr_number: number) => Promise<RestPull> = read_remembered_pull,
|
|
224
|
+
): Promise<PullRead> {
|
|
225
|
+
const number_read = await read_pr_number(branch_name)
|
|
226
|
+
if (number_read.kind !== 'read') return number_read
|
|
191
227
|
|
|
192
228
|
try {
|
|
193
|
-
return await
|
|
194
|
-
} catch {
|
|
195
|
-
return
|
|
229
|
+
return { kind: 'read', pull: await read(number_read.pr_number) }
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return { kind: 'unreadable', cause: error }
|
|
196
232
|
}
|
|
197
233
|
}
|
|
198
234
|
|
|
235
|
+
// The display readers' fold: "no pull request" and "nothing could be read" are one empty answer.
|
|
236
|
+
async function read_pull_or_undefined(branch_name: string): Promise<RestPull | undefined> {
|
|
237
|
+
const read = await read_pull_of_branch(branch_name)
|
|
238
|
+
|
|
239
|
+
return read.kind === 'read' ? read.pull : undefined
|
|
240
|
+
}
|
|
241
|
+
|
|
199
242
|
// **`false` means the branch has no pull request, and nothing else.** This is the second half of
|
|
200
243
|
// joshuafolkken/kit#1048's distinction, on the caller that needs it most: `pr_exists` is not read for
|
|
201
244
|
// display, it decides whether `git-pr.ts` **opens** a pull request. Folding an unreadable lookup into
|
|
@@ -215,7 +258,7 @@ async function pr_get_number(branch_name: string): Promise<number | undefined> {
|
|
|
215
258
|
}
|
|
216
259
|
|
|
217
260
|
async function pr_get_url(branch_name: string): Promise<string | undefined> {
|
|
218
|
-
const pull = await
|
|
261
|
+
const pull = await read_pull_or_undefined(branch_name)
|
|
219
262
|
if (pull?.html_url === undefined) return undefined
|
|
220
263
|
|
|
221
264
|
return git_gh_helpers.parse_pr_state_string(pull.html_url)
|
|
@@ -226,33 +269,39 @@ async function pr_get_url(branch_name: string): Promise<string | undefined> {
|
|
|
226
269
|
// made on GitHub moves without touching the local branch. `undefined` covers both "no pull request"
|
|
227
270
|
// and "nothing could be read": `followup` then takes its ordinary path, whose merge step settles a
|
|
228
271
|
// pull request that did merge after all (`pr_merge`), so an unread answer costs a wait, not a wrong tail.
|
|
272
|
+
// Read past the detail memo: `josh ship` asks it again after each merge it pushes (joshuafolkken/kit#3263).
|
|
229
273
|
async function pr_get_merge_state(branch_name: string): Promise<PullMergeState | undefined> {
|
|
230
|
-
const
|
|
231
|
-
if (
|
|
274
|
+
const read = await read_pull_of_branch(branch_name, read_pull)
|
|
275
|
+
if (read.kind !== 'read') return undefined
|
|
276
|
+
const { pull } = read
|
|
232
277
|
|
|
233
278
|
return {
|
|
234
279
|
is_merged: git_gh_pr_rest.is_merged(pull),
|
|
235
280
|
merged_at: pull.merged_at ?? undefined,
|
|
236
281
|
head_sha: pull.head?.sha,
|
|
282
|
+
merge_state_status: to_gh_state(pull.mergeable_state),
|
|
237
283
|
}
|
|
238
284
|
}
|
|
239
285
|
|
|
240
286
|
// REST answers JSON null for a pull request with no body where `gh --json body` answered an empty
|
|
241
287
|
// string, and both used to arrive here as the empty answer this folds to `undefined`.
|
|
242
288
|
async function pr_get_body(branch_name: string): Promise<string | undefined> {
|
|
243
|
-
const pull = await
|
|
289
|
+
const pull = await read_pull_or_undefined(branch_name)
|
|
244
290
|
const body = pull?.body
|
|
245
291
|
|
|
246
292
|
return typeof body === 'string' && body.length > 0 ? body : undefined
|
|
247
293
|
}
|
|
248
294
|
|
|
249
|
-
// The empty string means "
|
|
250
|
-
//
|
|
295
|
+
// The empty string means "this branch has no pull request", and nothing else. A read that failed
|
|
296
|
+
// throws, carrying gh's reason as the `cause`: `git-pr.ts` decides from this state whether the
|
|
297
|
+
// branch's pull request merged, and a rate limit answered as "no state" sent a merged pull request
|
|
298
|
+
// down the open one's path (joshuafolkken/kit#3263). Read past the detail memo, like the merge state.
|
|
251
299
|
async function pr_view(branch_name: string): Promise<string> {
|
|
252
|
-
const
|
|
253
|
-
if (
|
|
300
|
+
const read = await read_pull_of_branch(branch_name, read_pull)
|
|
301
|
+
if (read.kind === 'unreadable') throw to_unreadable_error(branch_name, read.cause)
|
|
302
|
+
if (read.kind === 'missing') return ''
|
|
254
303
|
|
|
255
|
-
return JSON.stringify(git_gh_pr_rest.to_pr_info(pull))
|
|
304
|
+
return JSON.stringify(git_gh_pr_rest.to_pr_info(read.pull))
|
|
256
305
|
}
|
|
257
306
|
|
|
258
307
|
// `undefined` when the listing could not be read — a failed request, or a PR whose number could not
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { rest_comment_schema } from '#scripts/git/git-schemas'
|
|
1
2
|
import {
|
|
2
3
|
parse_json_array_or_undefined,
|
|
3
4
|
parse_json_object_safe,
|
|
4
5
|
} from '#scripts/git/parse-json-array'
|
|
5
|
-
import { rest_comment_schema } from '#scripts/git/schemas'
|
|
6
6
|
import { z } from 'zod'
|
|
7
7
|
import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
|
|
8
8
|
|
package/scripts/gh/git-gh-pr.ts
CHANGED
|
@@ -152,10 +152,12 @@ async function pr_comment(branch_name: string, body: string): Promise<string> {
|
|
|
152
152
|
|
|
153
153
|
// Replaces the body of the branch's open pull request. `git -y` opens a pull request once, so a
|
|
154
154
|
// body supplied on a later run — the live-execution evidence `followup` gates the merge on
|
|
155
|
-
// (joshuafolkken/kit#2446) — reaches an already-open one only through this write.
|
|
155
|
+
// (joshuafolkken/kit#2446) — reaches an already-open one only through this write. The remembered
|
|
156
|
+
// detail read holds the old body, so it is cleared first (joshuafolkken/kit#3263).
|
|
156
157
|
async function pr_update_body(branch_name: string, body: string): Promise<void> {
|
|
157
158
|
const pr_number = await require_pr_number(branch_name)
|
|
158
159
|
|
|
160
|
+
forget_pr_numbers()
|
|
159
161
|
await git_gh_exec.exec_gh_api({
|
|
160
162
|
path: git_gh_api_path.pull_api_path(String(pr_number)),
|
|
161
163
|
method: PATCH_METHOD,
|
|
@@ -163,7 +165,9 @@ async function pr_update_body(branch_name: string, body: string): Promise<void>
|
|
|
163
165
|
})
|
|
164
166
|
}
|
|
165
167
|
|
|
168
|
+
// A merge moves the remembered detail read's state, so it is cleared first (joshuafolkken/kit#3263).
|
|
166
169
|
async function put_merge(pr_number: number): Promise<void> {
|
|
170
|
+
forget_pr_numbers()
|
|
167
171
|
await git_gh_exec.exec_gh_api({
|
|
168
172
|
path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
|
|
169
173
|
method: PUT_METHOD,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// cspell:words coderabbit coderabbitai
|
|
2
|
+
import { ai_review_pull_comment_schema } from '#scripts/git/git-schemas'
|
|
2
3
|
import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
|
|
3
|
-
import { ai_review_pull_comment_schema } from '#scripts/git/schemas'
|
|
4
4
|
import {
|
|
5
5
|
classify_ai_review_comments,
|
|
6
6
|
type ClassifiedFinding,
|
|
@@ -191,9 +191,7 @@ function evaluate_pr_state(snapshot: PrStateSnapshot): PrEvaluation {
|
|
|
191
191
|
|
|
192
192
|
if (failure !== undefined) return failure
|
|
193
193
|
|
|
194
|
-
if (is_mergeable_state(snapshot) && is_every_required_passing(statuses))
|
|
195
|
-
return 'success'
|
|
196
|
-
}
|
|
194
|
+
if (is_mergeable_state(snapshot) && is_every_required_passing(statuses)) return 'success'
|
|
197
195
|
|
|
198
196
|
return 'pending'
|
|
199
197
|
}
|
|
@@ -240,7 +238,14 @@ function is_auto_merge_blocked(snapshot: PrStateSnapshot): boolean {
|
|
|
240
238
|
)
|
|
241
239
|
}
|
|
242
240
|
|
|
241
|
+
// A failed wait whose cause is a merge conflict (joshuafolkken/kit#3221), so `followup` names its last
|
|
242
|
+
// lap `conflict` rather than `interrupted` and the cause is read from the stage block, not looked up.
|
|
243
|
+
class PrConflictError extends Error {
|
|
244
|
+
override name = 'PrConflictError'
|
|
245
|
+
}
|
|
246
|
+
|
|
243
247
|
export {
|
|
248
|
+
PrConflictError,
|
|
244
249
|
evaluate_pr_state,
|
|
245
250
|
is_auto_merge_blocked,
|
|
246
251
|
is_review_decision_decisive,
|
|
@@ -251,5 +256,6 @@ export {
|
|
|
251
256
|
REQUIRED_CHECKS,
|
|
252
257
|
CODERABBIT_CHECK_NAME,
|
|
253
258
|
is_required_check,
|
|
259
|
+
is_merge_conflict,
|
|
254
260
|
}
|
|
255
261
|
export type { PrEvaluation }
|
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
SECONDS_TO_MS,
|
|
8
8
|
wait_for_pr_success,
|
|
9
9
|
type PrStateEvaluator,
|
|
10
|
-
type ReviewDecisionPredicate,
|
|
11
10
|
} from './git-pr-checks'
|
|
12
11
|
import { is_coderabbit_check, is_required_check, type PrEvaluation } from './git-pr-checks-eval'
|
|
13
12
|
import {
|
|
@@ -116,12 +115,14 @@ function describe_checks_failure(snapshot: PrStateSnapshot): string {
|
|
|
116
115
|
// **The watch never reads `review_decision`**, so the poll must not spend a request fetching it. It
|
|
117
116
|
// is the same difference `evaluate_checks_settled` is written for, said to the fetcher instead of to
|
|
118
117
|
// the verdict: three requests a poll rather than four (joshuafolkken/kit#1043).
|
|
119
|
-
|
|
118
|
+
function should_never_read_review_decision(): boolean {
|
|
119
|
+
return false
|
|
120
|
+
}
|
|
120
121
|
|
|
121
122
|
const CHECKS_SETTLED_EVALUATOR: PrStateEvaluator = {
|
|
122
123
|
evaluate: evaluate_checks_settled,
|
|
123
124
|
describe: describe_checks_failure,
|
|
124
|
-
should_read_review_decision:
|
|
125
|
+
should_read_review_decision: should_never_read_review_decision,
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
async function watch_until_settled(branch_name: string): Promise<void> {
|
|
@@ -145,7 +146,7 @@ async function watch_until_settled(branch_name: string): Promise<void> {
|
|
|
145
146
|
// from failing on the first read: two minutes is the grace, and an empty rollup at the end of them
|
|
146
147
|
// is the answer `gh` gave immediately.
|
|
147
148
|
async function fail_when_no_checks(branch_name: string): Promise<void> {
|
|
148
|
-
const snapshot = await default_fetch_pr_state(branch_name,
|
|
149
|
+
const snapshot = await default_fetch_pr_state(branch_name, should_never_read_review_decision)
|
|
149
150
|
if (snapshot.rollup.length === 0) throw new Error(NO_CHECKS_MESSAGE)
|
|
150
151
|
}
|
|
151
152
|
|
|
@@ -173,7 +174,7 @@ export {
|
|
|
173
174
|
git_pr_checks_watch,
|
|
174
175
|
fail_when_no_checks,
|
|
175
176
|
CHECKS_SETTLED_EVALUATOR,
|
|
176
|
-
|
|
177
|
+
should_never_read_review_decision,
|
|
177
178
|
evaluate_checks_settled,
|
|
178
179
|
is_awaited_check,
|
|
179
180
|
describe_checks_failure,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { package_name_schema } from '#scripts/git/schemas'
|
|
1
|
+
import { package_name_schema } from '#scripts/git/git-schemas'
|
|
2
2
|
import { poll } from '#scripts/lib/poll'
|
|
3
3
|
import { git_gh_pr_auto_merge } from './git-gh-pr-auto-merge'
|
|
4
4
|
import { git_gh_pr_snapshot } from './git-gh-pr-snapshot'
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
describe_pr_failure,
|
|
7
7
|
evaluate_pr_state,
|
|
8
8
|
is_auto_merge_blocked,
|
|
9
|
+
is_merge_conflict,
|
|
9
10
|
is_review_decision_decisive,
|
|
11
|
+
PrConflictError,
|
|
10
12
|
type PrEvaluation,
|
|
11
13
|
} from './git-pr-checks-eval'
|
|
12
14
|
import { parse_pr_state_snapshot, read_string, type PrStateSnapshot } from './git-pr-checks-parse'
|
|
@@ -85,7 +87,9 @@ type ReviewDecisionPredicate = (snapshot: PrStateSnapshot) => boolean
|
|
|
85
87
|
|
|
86
88
|
// The conservative answer, and the one every evaluator that does not say gets: read it every poll,
|
|
87
89
|
// which is what all of them did before the predicate existed.
|
|
88
|
-
|
|
90
|
+
function should_always_read_review_decision(): boolean {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
89
93
|
|
|
90
94
|
type PrStateFetcher = (
|
|
91
95
|
branch_name: string,
|
|
@@ -142,6 +146,12 @@ function advance_stable_count(previous: number, state: PrEvaluation): number {
|
|
|
142
146
|
return state === 'success' ? previous + 1 : 0
|
|
143
147
|
}
|
|
144
148
|
|
|
149
|
+
function failure_error(message: string, snapshot: PrStateSnapshot): Error {
|
|
150
|
+
return is_merge_conflict(snapshot.merge_state_status)
|
|
151
|
+
? new PrConflictError(message)
|
|
152
|
+
: new Error(message)
|
|
153
|
+
}
|
|
154
|
+
|
|
145
155
|
function classify_poll_result(input: {
|
|
146
156
|
snapshot: PrStateSnapshot
|
|
147
157
|
stable_count: number
|
|
@@ -150,7 +160,9 @@ function classify_poll_result(input: {
|
|
|
150
160
|
}): { is_done: boolean; next_stable_count: number } {
|
|
151
161
|
const state = input.evaluator.evaluate(input.snapshot)
|
|
152
162
|
|
|
153
|
-
if (state === 'failure')
|
|
163
|
+
if (state === 'failure') {
|
|
164
|
+
throw failure_error(input.evaluator.describe(input.snapshot), input.snapshot)
|
|
165
|
+
}
|
|
154
166
|
|
|
155
167
|
const next_stable_count = advance_stable_count(input.stable_count, state)
|
|
156
168
|
|
|
@@ -189,7 +201,7 @@ async function read_pr_state(
|
|
|
189
201
|
try {
|
|
190
202
|
const snapshot = await input.options.fetcher(
|
|
191
203
|
input.options.branch_name,
|
|
192
|
-
evaluator.should_read_review_decision ??
|
|
204
|
+
evaluator.should_read_review_decision ?? should_always_read_review_decision,
|
|
193
205
|
)
|
|
194
206
|
|
|
195
207
|
return { kind: 'read', snapshot }
|
|
@@ -287,7 +299,7 @@ async function wait_for_pr_success(options: WaitForPrSuccessOptions): Promise<Pr
|
|
|
287
299
|
// (joshuafolkken/kit#1043).
|
|
288
300
|
async function default_fetch_pr_state(
|
|
289
301
|
branch_name: string,
|
|
290
|
-
should_read_review_decision: ReviewDecisionPredicate =
|
|
302
|
+
should_read_review_decision: ReviewDecisionPredicate = should_always_read_review_decision,
|
|
291
303
|
): Promise<PrStateSnapshot> {
|
|
292
304
|
const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name)
|
|
293
305
|
const snapshot = parse_pr_state_snapshot(checks.snapshot_json)
|
|
@@ -375,7 +387,7 @@ export {
|
|
|
375
387
|
is_pr_checks_timeout,
|
|
376
388
|
default_fetch_pr_state,
|
|
377
389
|
MERGE_GATE_EVALUATOR,
|
|
378
|
-
|
|
390
|
+
should_always_read_review_decision,
|
|
379
391
|
}
|
|
380
392
|
export type { MergeProgress, PrStateFetcher, PrStateEvaluator, ReviewDecisionPredicate }
|
|
381
393
|
export {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { pull_comment_schema } from '#scripts/git/git-schemas'
|
|
1
2
|
import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
|
|
2
|
-
import { pull_comment_schema } from '#scripts/git/schemas'
|
|
3
3
|
import { git_gh_command } from './git-gh-command'
|
|
4
4
|
import { has_ignore_reason } from './git-pr-ai-review'
|
|
5
5
|
|
|
@@ -8,9 +8,7 @@ function has_error_cause(error: Error): boolean {
|
|
|
8
8
|
|
|
9
9
|
function is_pr_already_exists_error(error: unknown): boolean {
|
|
10
10
|
if (error instanceof Error) {
|
|
11
|
-
if (is_pr_already_exists_message(error.message))
|
|
12
|
-
return true
|
|
13
|
-
}
|
|
11
|
+
if (is_pr_already_exists_message(error.message)) return true
|
|
14
12
|
|
|
15
13
|
return has_error_cause(error)
|
|
16
14
|
}
|
package/scripts/gh/git-pr.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { pr_classification, type ReleaseClassification } from '#scripts/ci/pr-classification'
|
|
2
2
|
import type { IssueInfo } from '#scripts/git/git-issue'
|
|
3
|
-
import { pr_info_schema } from '#scripts/git/schemas'
|
|
3
|
+
import { pr_info_schema } from '#scripts/git/git-schemas'
|
|
4
4
|
import { animation_helpers, type AnimationOptions } from '#scripts/lib/animation-helpers'
|
|
5
5
|
import { git_gh_command } from './git-gh-command'
|
|
6
6
|
import { git_pr_error } from './git-pr-error'
|
|
@@ -98,18 +98,14 @@ function parse_pr_state(pr_info_json: string): string | undefined {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
// A read that failed throws rather than answering `undefined`: "no state" is read as "not merged",
|
|
102
|
+
// which would write onto a pull request that already merged (joshuafolkken/kit#3263).
|
|
103
|
+
async function get_pr_state(branch_name: string): Promise<string | undefined> {
|
|
104
|
+
const pr_info_json = await git_gh_command.pr_view(branch_name)
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
return undefined
|
|
107
|
-
}
|
|
106
|
+
if (pr_info_json.length === 0) return undefined
|
|
108
107
|
|
|
109
|
-
|
|
110
|
-
} catch {
|
|
111
|
-
return undefined
|
|
112
|
-
}
|
|
108
|
+
return parse_pr_state(pr_info_json)
|
|
113
109
|
}
|
|
114
110
|
|
|
115
111
|
function is_pr_state_merged(pr_state: string | undefined): boolean {
|
|
@@ -137,7 +133,7 @@ async function handle_existing_pr(
|
|
|
137
133
|
branch_name: string,
|
|
138
134
|
options: { label: ReleaseClassification; should_replace_body: boolean },
|
|
139
135
|
): Promise<void> {
|
|
140
|
-
const pr_state_result = await
|
|
136
|
+
const pr_state_result = await get_pr_state(branch_name)
|
|
141
137
|
|
|
142
138
|
if (is_pr_state_merged(pr_state_result)) {
|
|
143
139
|
git_pr_messages.display_merged_pr_message()
|
|
@@ -181,7 +177,7 @@ function build_body(issue_info: IssueInfo, extra_body?: string): string {
|
|
|
181
177
|
|
|
182
178
|
async function existing_pr_label(branch_name: string): Promise<ReleaseClassification | undefined> {
|
|
183
179
|
if (!(await git_gh_command.pr_exists(branch_name))) return undefined
|
|
184
|
-
if (is_pr_state_merged(await
|
|
180
|
+
if (is_pr_state_merged(await get_pr_state(branch_name))) return undefined
|
|
185
181
|
|
|
186
182
|
return await git_gh_command.pr_get_classification(branch_name)
|
|
187
183
|
}
|
|
@@ -75,8 +75,8 @@ function build_target(match: RegExpExecArray): ParsedUrl {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
function parse_with(pattern: RegExp, url: string | undefined): ParsedUrl | undefined {
|
|
79
|
-
const match = pattern.exec(url
|
|
78
|
+
function parse_with(pattern: RegExp, url: string | undefined = ''): ParsedUrl | undefined {
|
|
79
|
+
const match = pattern.exec(url)
|
|
80
80
|
if (match === null) return undefined
|
|
81
81
|
|
|
82
82
|
return build_target(match)
|
package/scripts/git/constants.ts
CHANGED
|
@@ -12,19 +12,24 @@ const PORCELAIN_FLAG = '--porcelain'
|
|
|
12
12
|
// The untracked-files mode every porcelain status reading passes (`git-command.ts` carries why it is
|
|
13
13
|
// passed and why it is `all`), shared so another module's own reading cannot drift from it.
|
|
14
14
|
const UNTRACKED_FILES_FLAG = '--untracked-files=all'
|
|
15
|
+
// The git binary a spawn runs in place of the platform's own (joshuafolkken/kit#3234). The spawn path
|
|
16
|
+
// is absolute, so a `git` placed in front on `PATH` never stands in for it: the unit suite's network
|
|
17
|
+
// guard shimmed `git` that way, and `josh ship`'s tests fetched and merged the default branch into the
|
|
18
|
+
// checkout they ran in without the guard ever seeing the call. The guard names its shim here instead.
|
|
19
|
+
const GIT_BINARY_KEY = 'JOSH_GIT_BINARY'
|
|
15
20
|
|
|
16
21
|
function get_git_command(): string {
|
|
17
|
-
if (platform() === 'win32')
|
|
18
|
-
return String.raw`"C:\Program Files\Git\cmd\git.exe"`
|
|
19
|
-
}
|
|
22
|
+
if (platform() === 'win32') return String.raw`"C:\Program Files\Git\cmd\git.exe"`
|
|
20
23
|
|
|
21
24
|
return GIT_COMMAND_UNIX
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
function get_git_command_for_spawn(): string {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
const binary = process.env[GIT_BINARY_KEY]
|
|
29
|
+
|
|
30
|
+
if (binary !== undefined && binary !== '') return binary
|
|
31
|
+
|
|
32
|
+
if (platform() === 'win32') return String.raw`C:\Program Files\Git\cmd\git.exe`
|
|
28
33
|
|
|
29
34
|
return GIT_COMMAND_UNIX
|
|
30
35
|
}
|
|
@@ -35,6 +40,7 @@ const git_utilities = {
|
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export {
|
|
43
|
+
GIT_BINARY_KEY,
|
|
38
44
|
REQUIRED_STATUS_LENGTH,
|
|
39
45
|
STAGED_STATUS_INDEX,
|
|
40
46
|
UNTRACKED_FILE_PREFIX,
|