@joshuafolkken/kit 1.1178.0 → 1.1240.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 +7 -3
- package/.claude/skills/workflow-commands/backlogrun-park.md +23 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +9 -4
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +21 -13
- 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 +10 -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 +2 -1
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +6 -1
- 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 +32 -31
- package/.github/workflows/dependabot-auto-merge.yml +13 -6
- package/.github/workflows/publish.yml +50 -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 +44 -38
- 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-G6KRCKEC.js → chunk-4TZVB44A.js} +496 -378
- package/dist/hooks/chunk-5VNDSNG3.js +12 -0
- package/dist/hooks/chunk-CDY4NFQG.js +15 -0
- package/dist/hooks/chunk-ELCN5LCH.js +135 -0
- package/dist/hooks/{chunk-VQLLNFNT.js → chunk-F3ELQ2AF.js} +3 -3
- package/dist/hooks/{chunk-I4XSL4TT.js → chunk-GPTFMK5E.js} +1 -1
- package/dist/hooks/{chunk-3V37IID6.js → chunk-JBBMAPC4.js} +23 -14
- package/dist/hooks/{chunk-UAGLLIGZ.js → chunk-KHGB5S3Y.js} +7 -6
- package/dist/hooks/{chunk-GDS5N2KB.js → chunk-KHX4U3BG.js} +735 -683
- package/dist/hooks/{chunk-VESKRQOF.js → chunk-KRBERBBI.js} +3 -3
- package/dist/hooks/{chunk-DO6NWWHU.js → chunk-QVSWU24O.js} +4 -4
- package/dist/hooks/{chunk-S6X6WYKR.js → chunk-WK2XSHSI.js} +1643 -923
- package/dist/hooks/{chunk-ZAL3NRGL.js → chunk-XZYKEM6J.js} +25 -10
- package/dist/hooks/{chunk-32GQTL4F.js → chunk-ZQGD4GBY.js} +4 -2
- 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 +203 -179
- 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 +66 -72
- package/dist/josh.js +1088 -78
- 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/issue-template.md +1 -0
- 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 +16 -5
- package/scripts/backlog/backlog-offer-cli.ts +6 -6
- package/scripts/backlog/backlog-offer.ts +1 -1
- package/scripts/backlog/backlog-plan-cli.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +57 -11
- package/scripts/backlog/backlog-ready.ts +1 -1
- 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/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/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-pr-followup-checks.ts +142 -0
- package/scripts/followup/git-pr-followup.ts +4 -129
- package/scripts/gate/core-admission.ts +162 -0
- package/scripts/gate/core-budget.ts +190 -68
- package/scripts/gate/gate-plan.ts +80 -7
- package/scripts/gate/gate-report.ts +28 -9
- package/scripts/gate/gate-skip.ts +38 -7
- package/scripts/gate/hook-gate-reuse.ts +12 -10
- package/scripts/gate/machine-capacity.ts +175 -0
- 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 +34 -10
- 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-pr-read.ts +64 -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 +1 -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 +7 -5
- 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 +2 -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/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/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 +10 -16
- 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/package-manager-pin.ts +35 -0
- 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 +32 -7
- 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 +72 -22
- package/scripts/issue/issue-file.ts +29 -1
- package/scripts/issue/issue-labels.ts +13 -0
- package/scripts/issue/issue-release-cli.ts +155 -0
- package/scripts/issue/issue-release.ts +58 -0
- 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 +14 -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 +18 -0
- package/scripts/josh/josh-commands-document.ts +1 -0
- package/scripts/josh/josh-commands-issue.ts +8 -1
- package/scripts/josh/josh-commands-lane.ts +24 -1
- package/scripts/josh/josh-commands-maintenance.ts +6 -6
- package/scripts/josh/josh-commands-run.ts +12 -7
- package/scripts/josh/josh-in-process.ts +28 -9
- package/scripts/josh/josh-logic.ts +34 -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 +12 -4
- 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 +15 -1
- package/scripts/lane/lane-ledger.ts +145 -0
- package/scripts/lane/lane-leftover.ts +44 -30
- 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-open.ts +5 -5
- package/scripts/lane/lane-paths.ts +13 -0
- package/scripts/lane/lane-reap.ts +1 -3
- package/scripts/lane/lane-registry.ts +11 -0
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-stats.ts +224 -0
- package/scripts/lane/lane-stray.ts +140 -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-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/release/github-release-environment.ts +1 -0
- package/scripts/release/github-release-runs.ts +115 -0
- package/scripts/release/github-release.ts +13 -67
- 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 +1 -1
- 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} +1 -1
- 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} +18 -5
- 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-render.ts → event/run-event-render.ts} +1 -0
- 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} +20 -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 +7 -4
- 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} +2 -2
- 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-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} +4 -3
- 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-steps.ts → ship/run-ship-steps.ts} +11 -12
- package/scripts/run/ship/run-ship-stop-text.ts +13 -0
- package/scripts/run/{run-ship-sync.ts → ship/run-ship-sync.ts} +25 -11
- 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} +25 -11
- package/scripts/run/{run-wake-describe.ts → wake/run-wake-describe.ts} +58 -7
- package/scripts/run/{run-wake-driver.ts → wake/run-wake-driver.ts} +59 -8
- 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} +13 -15
- 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} +16 -65
- 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/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/version/effective-upstream.ts +2 -20
- package/scripts/version/latest-corepack.ts +124 -93
- 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 +6 -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/git/{schemas.ts → git-schemas.ts} +0 -0
- /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-cut-report.ts → cut/run-cut-report.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-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-next.ts → ship/run-ship-next.ts} +0 -0
- /package/scripts/run/{run-ship-pre-detach.ts → ship/run-ship-pre-detach.ts} +0 -0
- /package/scripts/run/{run-ship-review.ts → ship/run-ship-review.ts} +0 -0
- /package/scripts/run/{run-ship-stage.ts → ship/run-ship-stage.ts} +0 -0
- /package/scripts/run/{run-ship.ts → ship/run-ship.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
|
@@ -29,6 +29,7 @@ const DELETE_METHOD = 'DELETE'
|
|
|
29
29
|
// object, so the same value is unwrapped out of it rather than the shape being changed.
|
|
30
30
|
const HTML_URL_FILTER = '.html_url'
|
|
31
31
|
const ID_FILTER = '.id'
|
|
32
|
+
const LABEL_NAMES_FILTER = '.[].name'
|
|
32
33
|
|
|
33
34
|
const LABELS_SEGMENT = '/labels'
|
|
34
35
|
const COMMENTS_SEGMENT = '/comments'
|
|
@@ -182,17 +183,60 @@ async function issue_create_with_label(input: {
|
|
|
182
183
|
)
|
|
183
184
|
}
|
|
184
185
|
|
|
186
|
+
// The outcome of applying one label, with the swallowed failure's gist kept for a caller that has to
|
|
187
|
+
// say why it refused (joshuafolkken/kit#3312).
|
|
188
|
+
type LabelWrite = { is_applied: true } | { is_applied: false; reason: string }
|
|
189
|
+
|
|
190
|
+
// The issue's label names, read back after a failed write. A read that itself fails answers
|
|
191
|
+
// `undefined`, which the caller treats as "not applied" — the write's own error is the reason then.
|
|
192
|
+
async function read_label_names(issue_number: string): Promise<Array<string> | undefined> {
|
|
193
|
+
try {
|
|
194
|
+
const raw = await git_gh_exec.exec_gh_api({
|
|
195
|
+
path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
|
|
196
|
+
should_paginate: true,
|
|
197
|
+
jq_filter: LABEL_NAMES_FILTER,
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
return raw.split('\n').map((name) => name.trim())
|
|
201
|
+
} catch (error) {
|
|
202
|
+
error_text.trace_swallowed('git_gh_issue_write.read_label_names', error)
|
|
203
|
+
|
|
204
|
+
return undefined
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// **A failed answer is not a failed write.** The POST is idempotent, and a timeout, a non-zero exit
|
|
209
|
+
// after the write or a secondary rate limit can each throw after the label landed — which refused a
|
|
210
|
+
// lane dispatch whose label was in fact applied (joshuafolkken/kit#3312). So a throw is confirmed by
|
|
211
|
+
// reading the labels back, and only a label that is really absent answers `is_applied: false`.
|
|
212
|
+
async function issue_apply_label(issue_number: string, label: string): Promise<LabelWrite> {
|
|
213
|
+
const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
await git_gh_exec.exec_gh_api({ path: labels_path, body: JSON.stringify({ labels: [label] }) })
|
|
217
|
+
|
|
218
|
+
return { is_applied: true }
|
|
219
|
+
} catch (error) {
|
|
220
|
+
const names = await read_label_names(issue_number)
|
|
221
|
+
|
|
222
|
+
if (names?.includes(label) === true) return { is_applied: true }
|
|
223
|
+
error_text.trace_swallowed('git_gh_issue_write.issue_apply_label', error)
|
|
224
|
+
|
|
225
|
+
// The first line is the gist: gh follows it with the response body, which a one-line refusal
|
|
226
|
+
// does not need.
|
|
227
|
+
const [gist = ''] = error_text.message_of(error).split('\n', 1)
|
|
228
|
+
|
|
229
|
+
return { is_applied: false, reason: gist }
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
185
233
|
// Applied after the body edit so a failure leaves an issue with the epic sections and no label,
|
|
186
234
|
// which `epic:check` reports — rather than a labelled issue with nothing to track. The caller checks
|
|
187
235
|
// the return: the label is what the auto-close filters on (joshuafolkken/kit#865).
|
|
188
236
|
async function issue_add_label(issue_number: string, label: string): Promise<boolean> {
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
|
|
193
|
-
body: JSON.stringify({ labels: [label] }),
|
|
194
|
-
}),
|
|
195
|
-
)
|
|
237
|
+
const write = await issue_apply_label(issue_number, label)
|
|
238
|
+
|
|
239
|
+
return write.is_applied
|
|
196
240
|
}
|
|
197
241
|
|
|
198
242
|
// The counterpart to the addition above, for a run taking its own marker back off
|
|
@@ -279,6 +323,7 @@ const git_gh_issue_write = {
|
|
|
279
323
|
label_ensure,
|
|
280
324
|
issue_create_request,
|
|
281
325
|
issue_create_with_label,
|
|
326
|
+
issue_apply_label,
|
|
282
327
|
issue_add_label,
|
|
283
328
|
issue_remove_label,
|
|
284
329
|
issue_add_blocked_by,
|
|
@@ -286,3 +331,4 @@ const git_gh_issue_write = {
|
|
|
286
331
|
}
|
|
287
332
|
|
|
288
333
|
export { git_gh_issue_write }
|
|
334
|
+
export type { LabelWrite }
|
|
@@ -89,9 +89,24 @@ interface PullMergeState {
|
|
|
89
89
|
type PullNumberRead =
|
|
90
90
|
{ kind: 'read'; pr_number: number } | { kind: 'missing' } | { kind: 'unreadable'; cause: unknown }
|
|
91
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
|
+
|
|
92
97
|
// The lookups still in flight, keyed the same way the resolved numbers are.
|
|
93
98
|
const pending_pr_number_by_branch = new Map<string, Promise<PullNumberRead>>()
|
|
94
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
|
+
|
|
95
110
|
async function fetch_pr_number_read(branch_name: string): Promise<PullNumberRead> {
|
|
96
111
|
try {
|
|
97
112
|
const pr_number = await fetch_pr_number(branch_name)
|
|
@@ -130,10 +145,11 @@ async function start_pr_number_read(branch_name: string): Promise<PullNumberRead
|
|
|
130
145
|
}
|
|
131
146
|
}
|
|
132
147
|
|
|
133
|
-
// Defined after the
|
|
148
|
+
// Defined after the maps it clears, so the memos are declared before anything reaches them.
|
|
134
149
|
function forget_pr_numbers(): void {
|
|
135
150
|
pr_number_by_branch.clear()
|
|
136
151
|
pending_pr_number_by_branch.clear()
|
|
152
|
+
pull_by_number.clear()
|
|
137
153
|
}
|
|
138
154
|
|
|
139
155
|
async function read_pr_number(branch_name: string): Promise<PullNumberRead> {
|
|
@@ -144,9 +160,9 @@ async function read_pr_number(branch_name: string): Promise<PullNumberRead> {
|
|
|
144
160
|
}
|
|
145
161
|
|
|
146
162
|
// `undefined` covers both "this branch has no pull request" and "the lookup failed", which is the
|
|
147
|
-
// distinction `gh pr view` never made either —
|
|
148
|
-
//
|
|
149
|
-
//
|
|
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.
|
|
150
166
|
async function resolve_pr_number(branch_name: string): Promise<number | undefined> {
|
|
151
167
|
const read = await read_pr_number(branch_name)
|
|
152
168
|
|
|
@@ -186,19 +202,43 @@ async function read_pull(pr_number: number): Promise<RestPull> {
|
|
|
186
202
|
return git_gh_pr_rest.parse_rest_pull(json)
|
|
187
203
|
}
|
|
188
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
|
+
|
|
189
219
|
// One pull request named by its branch: the resolution, then the detail read that carries
|
|
190
220
|
// `mergeable` and `mergeable_state`, which the lookup listing does not.
|
|
191
|
-
async function read_pull_of_branch(
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
194
227
|
|
|
195
228
|
try {
|
|
196
|
-
return await
|
|
197
|
-
} catch {
|
|
198
|
-
return
|
|
229
|
+
return { kind: 'read', pull: await read(number_read.pr_number) }
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return { kind: 'unreadable', cause: error }
|
|
199
232
|
}
|
|
200
233
|
}
|
|
201
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
|
+
|
|
202
242
|
// **`false` means the branch has no pull request, and nothing else.** This is the second half of
|
|
203
243
|
// joshuafolkken/kit#1048's distinction, on the caller that needs it most: `pr_exists` is not read for
|
|
204
244
|
// display, it decides whether `git-pr.ts` **opens** a pull request. Folding an unreadable lookup into
|
|
@@ -218,7 +258,7 @@ async function pr_get_number(branch_name: string): Promise<number | undefined> {
|
|
|
218
258
|
}
|
|
219
259
|
|
|
220
260
|
async function pr_get_url(branch_name: string): Promise<string | undefined> {
|
|
221
|
-
const pull = await
|
|
261
|
+
const pull = await read_pull_or_undefined(branch_name)
|
|
222
262
|
if (pull?.html_url === undefined) return undefined
|
|
223
263
|
|
|
224
264
|
return git_gh_helpers.parse_pr_state_string(pull.html_url)
|
|
@@ -229,9 +269,11 @@ async function pr_get_url(branch_name: string): Promise<string | undefined> {
|
|
|
229
269
|
// made on GitHub moves without touching the local branch. `undefined` covers both "no pull request"
|
|
230
270
|
// and "nothing could be read": `followup` then takes its ordinary path, whose merge step settles a
|
|
231
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).
|
|
232
273
|
async function pr_get_merge_state(branch_name: string): Promise<PullMergeState | undefined> {
|
|
233
|
-
const
|
|
234
|
-
if (
|
|
274
|
+
const read = await read_pull_of_branch(branch_name, read_pull)
|
|
275
|
+
if (read.kind !== 'read') return undefined
|
|
276
|
+
const { pull } = read
|
|
235
277
|
|
|
236
278
|
return {
|
|
237
279
|
is_merged: git_gh_pr_rest.is_merged(pull),
|
|
@@ -244,19 +286,22 @@ async function pr_get_merge_state(branch_name: string): Promise<PullMergeState |
|
|
|
244
286
|
// REST answers JSON null for a pull request with no body where `gh --json body` answered an empty
|
|
245
287
|
// string, and both used to arrive here as the empty answer this folds to `undefined`.
|
|
246
288
|
async function pr_get_body(branch_name: string): Promise<string | undefined> {
|
|
247
|
-
const pull = await
|
|
289
|
+
const pull = await read_pull_or_undefined(branch_name)
|
|
248
290
|
const body = pull?.body
|
|
249
291
|
|
|
250
292
|
return typeof body === 'string' && body.length > 0 ? body : undefined
|
|
251
293
|
}
|
|
252
294
|
|
|
253
|
-
// The empty string means "
|
|
254
|
-
//
|
|
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.
|
|
255
299
|
async function pr_view(branch_name: string): Promise<string> {
|
|
256
|
-
const
|
|
257
|
-
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 ''
|
|
258
303
|
|
|
259
|
-
return JSON.stringify(git_gh_pr_rest.to_pr_info(pull))
|
|
304
|
+
return JSON.stringify(git_gh_pr_rest.to_pr_info(read.pull))
|
|
260
305
|
}
|
|
261
306
|
|
|
262
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
|
}
|
|
@@ -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'
|
|
@@ -87,7 +87,9 @@ type ReviewDecisionPredicate = (snapshot: PrStateSnapshot) => boolean
|
|
|
87
87
|
|
|
88
88
|
// The conservative answer, and the one every evaluator that does not say gets: read it every poll,
|
|
89
89
|
// which is what all of them did before the predicate existed.
|
|
90
|
-
|
|
90
|
+
function should_always_read_review_decision(): boolean {
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
91
93
|
|
|
92
94
|
type PrStateFetcher = (
|
|
93
95
|
branch_name: string,
|
|
@@ -199,7 +201,7 @@ async function read_pr_state(
|
|
|
199
201
|
try {
|
|
200
202
|
const snapshot = await input.options.fetcher(
|
|
201
203
|
input.options.branch_name,
|
|
202
|
-
evaluator.should_read_review_decision ??
|
|
204
|
+
evaluator.should_read_review_decision ?? should_always_read_review_decision,
|
|
203
205
|
)
|
|
204
206
|
|
|
205
207
|
return { kind: 'read', snapshot }
|
|
@@ -297,7 +299,7 @@ async function wait_for_pr_success(options: WaitForPrSuccessOptions): Promise<Pr
|
|
|
297
299
|
// (joshuafolkken/kit#1043).
|
|
298
300
|
async function default_fetch_pr_state(
|
|
299
301
|
branch_name: string,
|
|
300
|
-
should_read_review_decision: ReviewDecisionPredicate =
|
|
302
|
+
should_read_review_decision: ReviewDecisionPredicate = should_always_read_review_decision,
|
|
301
303
|
): Promise<PrStateSnapshot> {
|
|
302
304
|
const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name)
|
|
303
305
|
const snapshot = parse_pr_state_snapshot(checks.snapshot_json)
|
|
@@ -385,7 +387,7 @@ export {
|
|
|
385
387
|
is_pr_checks_timeout,
|
|
386
388
|
default_fetch_pr_state,
|
|
387
389
|
MERGE_GATE_EVALUATOR,
|
|
388
|
-
|
|
390
|
+
should_always_read_review_decision,
|
|
389
391
|
}
|
|
390
392
|
export type { MergeProgress, PrStateFetcher, PrStateEvaluator, ReviewDecisionPredicate }
|
|
391
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
|
@@ -19,9 +19,7 @@ const UNTRACKED_FILES_FLAG = '--untracked-files=all'
|
|
|
19
19
|
const GIT_BINARY_KEY = 'JOSH_GIT_BINARY'
|
|
20
20
|
|
|
21
21
|
function get_git_command(): string {
|
|
22
|
-
if (platform() === 'win32')
|
|
23
|
-
return String.raw`"C:\Program Files\Git\cmd\git.exe"`
|
|
24
|
-
}
|
|
22
|
+
if (platform() === 'win32') return String.raw`"C:\Program Files\Git\cmd\git.exe"`
|
|
25
23
|
|
|
26
24
|
return GIT_COMMAND_UNIX
|
|
27
25
|
}
|
|
@@ -31,9 +29,7 @@ function get_git_command_for_spawn(): string {
|
|
|
31
29
|
|
|
32
30
|
if (binary !== undefined && binary !== '') return binary
|
|
33
31
|
|
|
34
|
-
if (platform() === 'win32')
|
|
35
|
-
return String.raw`C:\Program Files\Git\cmd\git.exe`
|
|
36
|
-
}
|
|
32
|
+
if (platform() === 'win32') return String.raw`C:\Program Files\Git\cmd\git.exe`
|
|
37
33
|
|
|
38
34
|
return GIT_COMMAND_UNIX
|
|
39
35
|
}
|