@joshuafolkken/kit 1.1514.0 → 1.1784.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/investigator.md +1 -1
- package/.claude/settings.json +5 -5
- package/.claude/skills/epic-commands/SKILL.md +26 -65
- package/.claude/skills/epic-commands/epic-bundle.md +3 -1
- package/.claude/skills/workflow-commands/SKILL.md +5 -5
- package/.claude/skills/workflow-commands/background-commands.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
- package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +13 -7
- package/.claude/skills/workflow-commands/delegation.md +6 -5
- package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
- package/.claude/skills/workflow-commands/followup.md +9 -31
- package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
- package/.claude/skills/workflow-commands/fullrun.md +2 -2
- package/.claude/skills/workflow-commands/halfrun.md +17 -25
- package/.claude/skills/workflow-commands/issue-comments.md +16 -12
- package/.claude/skills/workflow-commands/issue-scout.md +2 -2
- package/.claude/skills/workflow-commands/kickoff.md +24 -23
- package/.claude/skills/workflow-commands/latest-gate.md +7 -12
- package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
- package/.claude/skills/workflow-commands/observation-filing.md +4 -36
- package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
- package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
- package/.claude/skills/workflow-commands/prerequisite.md +10 -16
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +3 -7
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/split-assessment.md +13 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-node/action.yml +9 -0
- package/.github/actions/setup-pnpm/action.yml +1 -1
- package/.github/dependabot.yml +16 -0
- package/.github/release.yml +0 -2
- package/.github/workflows/ci.yml +120 -10
- package/.github/workflows/publish.yml +8 -1
- package/.github/workflows/sonar-qube.yml +1 -0
- package/.prettierignore +2 -0
- package/.vscode/tasks.json +1 -2
- package/CLAUDE.md +3 -7
- package/README.md +4 -2
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +3 -7
- package/dist/commands/document-read-cli.js +882 -0
- package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
- package/dist/commands/read-set-cli.js +1867 -0
- package/dist/commands/run-prep-main.js +21653 -0
- package/dist/commands/run-step-cli.js +23880 -0
- package/dist/config-merge/index.js +5 -1
- package/dist/hooks/audit-provision.js +20 -35
- package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
- package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
- package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
- package/dist/hooks/{chunk-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
- package/dist/hooks/chunk-TUIFS5E7.js +72 -0
- package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
- package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
- package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
- package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
- package/dist/hooks/codex-hook-adapter.js +10 -22
- package/dist/hooks/format-edited.js +5 -6
- package/dist/hooks/inputs.json +443 -317
- package/dist/hooks/pretool-guard.js +7 -25
- package/dist/hooks/session-lang.js +44 -51
- package/dist/hooks/stop-guard.js +7716 -2187
- package/dist/josh.js +6002 -3583
- package/dist/self-sync-guard/index.js +74 -10
- package/dist/version/index.js +115 -406
- package/eslint/base.js +1 -1
- package/lefthook/base.yml +3 -1
- package/package.json +10 -48
- package/pnpm-workspace.yaml +4 -2
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +1 -7
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +33 -16
- package/prompts/collaboration-workflow/lane-instructions.md +1 -2
- package/prompts/collaboration-workflow/measurement.md +37 -0
- package/prompts/collaboration-workflow/operating-rules.md +4 -6
- package/prompts/collaboration-workflow/output-bounds.md +2 -7
- package/prompts/collaboration-workflow/plan-comment.md +3 -42
- package/prompts/collaboration-workflow/principles.md +5 -0
- package/prompts/collaboration-workflow/report-format.md +31 -60
- package/prompts/collaboration-workflow/residency.md +2 -2
- package/prompts/collaboration-workflow/shell-body.md +6 -16
- package/prompts/collaboration-workflow/turn-batching.md +0 -2
- package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
- package/prompts/collaboration-workflow/wip-cap.md +1 -1
- package/prompts/collaboration-workflow.md +3 -7
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +41 -21
- package/prompts/testing-guide.md +8 -43
- package/scripts/agent/agent-event.ts +15 -15
- package/scripts/agent/agent-exit-record.ts +13 -1
- package/scripts/agent/api-auth.ts +41 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +14 -16
- package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
- package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
- package/scripts/auto-ok/auto-ok-judge.ts +13 -2
- package/scripts/auto-ok/auto-ok-main.ts +17 -0
- package/scripts/backlog/backlog-arrival.ts +14 -3
- package/scripts/backlog/backlog-budget-cli.ts +7 -33
- package/scripts/backlog/backlog-budget-main.ts +16 -0
- package/scripts/backlog/backlog-budget.ts +2 -3
- package/scripts/backlog/backlog-defect-priority.ts +4 -3
- package/scripts/backlog/backlog-drive-adopt.ts +67 -0
- package/scripts/backlog/backlog-drive-args.ts +4 -5
- package/scripts/backlog/backlog-drive-cli.ts +113 -28
- package/scripts/backlog/backlog-drive-hold.ts +162 -0
- package/scripts/backlog/backlog-drive-idle.ts +151 -0
- package/scripts/backlog/backlog-drive-judge.ts +25 -0
- package/scripts/backlog/backlog-drive-memory.ts +126 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
- package/scripts/backlog/backlog-drive-named.ts +53 -6
- package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
- package/scripts/backlog/backlog-drive-paused.ts +169 -0
- package/scripts/backlog/backlog-drive-restore.ts +30 -7
- package/scripts/backlog/backlog-drive-seats.ts +18 -8
- package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
- package/scripts/backlog/backlog-drive.ts +79 -75
- package/scripts/backlog/backlog-next-main.ts +16 -0
- package/scripts/backlog/backlog-next-shared.ts +73 -0
- package/scripts/backlog/backlog-next.ts +48 -16
- package/scripts/backlog/backlog-occupied.ts +52 -39
- package/scripts/backlog/backlog-offer-cli.ts +6 -21
- package/scripts/backlog/backlog-offer-exclude.ts +15 -0
- package/scripts/backlog/backlog-offer-main.ts +12 -0
- package/scripts/backlog/backlog-offer.ts +36 -3
- package/scripts/backlog/backlog-overlap.ts +22 -4
- package/scripts/backlog/backlog-plan-read.ts +6 -2
- package/scripts/backlog/backlog-plan.ts +18 -4
- package/scripts/backlog/backlog-pool.ts +10 -10
- package/scripts/backlog/backlog-rank.ts +10 -2
- package/scripts/backlog/backlog-ready.ts +112 -30
- package/scripts/backlog/backlog-stalled-detect.ts +109 -36
- package/scripts/backlog/backlog-stalled.ts +52 -16
- package/scripts/backlog/backlog-wait-cause.ts +86 -0
- package/scripts/backlog/backlog-waves.ts +39 -13
- package/scripts/backlog/backlogrun-args.ts +19 -7
- package/scripts/backlog/backlogrun-cli.ts +19 -5
- package/scripts/backlog/backlogrun-launch.ts +6 -0
- package/scripts/backlog/backlogrun-restart.ts +97 -0
- package/scripts/backlog/backlogrun-stop.ts +79 -7
- package/scripts/behavior/behavior-cli.ts +2 -2
- package/scripts/behavior/behavior-rules.ts +47 -24
- package/scripts/build/build-bin.ts +2 -16
- package/scripts/build/build-claude-md.ts +0 -7
- package/scripts/build/build-commands.ts +0 -13
- package/scripts/build/build-hooks.ts +49 -48
- package/scripts/build/hook-bundle-stamp.ts +29 -11
- package/scripts/build/local-bin.ts +1 -1
- package/scripts/cases/cases-cli.ts +25 -13
- package/scripts/cases/cases-interaction-scan.ts +134 -0
- package/scripts/cases/cases-interaction.ts +183 -0
- package/scripts/cases/cases-logic.ts +39 -6
- package/scripts/ci/pr-classification-main.ts +18 -0
- package/scripts/ci/pr-classification.ts +10 -17
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/cost-runtime/cost-blocks.ts +22 -37
- package/scripts/cost-runtime/cost-cli.ts +31 -14
- package/scripts/cost-runtime/cost-main.ts +12 -0
- package/scripts/cost-runtime/cost-transcript.ts +1 -0
- package/scripts/delegation/delegation-policy.ts +17 -4
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/investigation-guard.ts +0 -8
- package/scripts/delegation/investigation-reads.ts +3 -4
- package/scripts/dependabot/dependabot-cooldown.ts +194 -0
- package/scripts/discovery/repo-discovery.ts +24 -6
- package/scripts/doctor/doctor-consumer.ts +2 -5
- package/scripts/document/document-byte-budget.ts +8 -6
- package/scripts/document/document-scan.ts +1 -1
- package/scripts/document/document-section-cli.ts +0 -8
- package/scripts/document/document-section-main.ts +12 -0
- package/scripts/epic/epic-audit-cli.ts +12 -6
- package/scripts/epic/epic-bundle-apply.ts +137 -0
- package/scripts/epic/epic-bundle-cli.ts +32 -121
- package/scripts/epic/epic-bundle-format.ts +116 -0
- package/scripts/epic/epic-bundle-main.ts +17 -0
- package/scripts/epic/epic-busy.ts +5 -12
- package/scripts/epic/epic-classify.ts +24 -15
- package/scripts/epic/epic-cli-argv.ts +31 -0
- package/scripts/epic/epic-cli-decide.ts +42 -0
- package/scripts/epic/epic-cli.ts +6 -38
- package/scripts/epic/epic-close.ts +112 -55
- package/scripts/epic/epic-cross-repo.ts +4 -7
- package/scripts/epic/epic-decide.ts +119 -0
- package/scripts/epic/epic-decision.ts +9 -0
- package/scripts/epic/epic-fetch.ts +4 -0
- package/scripts/epic/epic-graph.ts +2 -0
- package/scripts/epic/epic-issue.ts +5 -1
- package/scripts/epic/epic-label-age.ts +1 -1
- package/scripts/epic/epic-lane-offer.ts +39 -4
- package/scripts/epic/epic-next-main.ts +24 -0
- package/scripts/epic/epic-next.ts +6 -24
- package/scripts/epic/epic-outside-blocker.ts +6 -2
- package/scripts/epic/epic-parse.ts +9 -3
- package/scripts/epic/epic-read.ts +1 -0
- package/scripts/epic/epic-reconcile.ts +39 -0
- package/scripts/epic/epic-run.ts +10 -1
- package/scripts/epic/epic-solo.ts +50 -14
- package/scripts/epic/epic.ts +41 -7
- package/scripts/exports/unused-members-cli.ts +2 -2
- package/scripts/followup/followup-checks-event.ts +8 -3
- package/scripts/followup/followup-coderabbit-wait.ts +82 -0
- package/scripts/followup/followup-review-gates.ts +81 -0
- package/scripts/followup/git-followup-stages.ts +13 -3
- package/scripts/followup/git-followup-workflow.ts +19 -66
- package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
- package/scripts/followup/git-pr-followup.ts +36 -8
- package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
- package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
- package/scripts/gate/busy-average.ts +58 -0
- package/scripts/gate/check-cpu.ts +60 -0
- package/scripts/gate/check-inputs.ts +39 -95
- package/scripts/gate/check-reuse.ts +33 -54
- package/scripts/gate/command-memory.ts +192 -0
- package/scripts/gate/core-admission.ts +218 -28
- package/scripts/gate/core-budget-timing.ts +37 -0
- package/scripts/gate/core-budget.ts +80 -98
- package/scripts/gate/core-wait-record.ts +48 -0
- package/scripts/gate/core-wait.ts +37 -5
- package/scripts/gate/core-weights.ts +86 -0
- package/scripts/gate/free-cores.ts +27 -4
- package/scripts/gate/gate-ledger.ts +32 -4
- package/scripts/gate/gate-plan.ts +41 -34
- package/scripts/gate/gate-report.ts +14 -2
- package/scripts/gate/gate-run-steps.ts +53 -8
- package/scripts/gate/gate-skip.ts +12 -2
- package/scripts/gate/gate-steps.ts +12 -1
- package/scripts/gate/input-fingerprint.ts +42 -0
- package/scripts/gate/machine-capacity.ts +65 -31
- package/scripts/gate/moved-paths.ts +67 -0
- package/scripts/gate/project-checks.ts +5 -12
- package/scripts/gate/scoped-green.ts +12 -8
- package/scripts/gate/since-green.ts +62 -0
- package/scripts/gate/toolchain-inputs.ts +115 -0
- package/scripts/gate/verification-gate.ts +27 -24
- package/scripts/gate/verification-inputs.ts +250 -0
- package/scripts/gh/gh-author-association.ts +96 -9
- package/scripts/gh/git-ai-review-scan.ts +4 -2
- package/scripts/gh/git-gh-api-path.ts +15 -0
- package/scripts/gh/git-gh-branch-rules.ts +73 -0
- package/scripts/gh/git-gh-conditional.ts +5 -2
- package/scripts/gh/git-gh-issue-read.ts +5 -1
- package/scripts/gh/git-gh-issue-write.ts +67 -29
- package/scripts/gh/git-gh-issue.ts +7 -3
- package/scripts/gh/git-gh-poll-read.ts +89 -0
- package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
- package/scripts/gh/git-gh-pr.ts +27 -15
- package/scripts/gh/git-pr-checks-eval.ts +39 -7
- package/scripts/gh/git-pr-checks-parse.ts +39 -9
- package/scripts/gh/git-pr-merge-checked.ts +80 -0
- package/scripts/git/base-tree.ts +19 -2
- package/scripts/git/changed-file-scope.ts +6 -4
- package/scripts/git/changed-paths.ts +18 -1
- package/scripts/git/git-diff-reads.ts +27 -2
- package/scripts/git/git-grep-hits.ts +85 -0
- package/scripts/git/git-location-environment.ts +1 -1
- package/scripts/git/git-merge-conflicts.ts +83 -0
- package/scripts/git/git-preflight.ts +37 -12
- package/scripts/git/git-push-transport.ts +1 -2
- package/scripts/git/git-schemas.ts +17 -7
- package/scripts/git/git-spawn.ts +1 -2
- package/scripts/git/git-status.ts +4 -4
- package/scripts/git/main-merge-main.ts +12 -0
- package/scripts/git/main-merge-regenerate.ts +2 -2
- package/scripts/git/main-merge.ts +25 -9
- package/scripts/git/main-sync-main.ts +12 -0
- package/scripts/git/main-sync.ts +0 -9
- package/scripts/git/stash/git-stash.ts +27 -4
- package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
- package/scripts/git/stash/stash-pop-cli.ts +6 -12
- package/scripts/git/stash/stash-pop-main.ts +12 -0
- package/scripts/git/stash/stash-push-cli.ts +76 -0
- package/scripts/git/stash/stash-push-main.ts +12 -0
- package/scripts/hooks/batch-guard.ts +0 -8
- package/scripts/hooks/check-commit-message-main.ts +8 -0
- package/scripts/hooks/check-commit-message.ts +4 -7
- package/scripts/hooks/format-edited-file.ts +8 -24
- package/scripts/hooks/pre-commit-lint.ts +30 -3
- package/scripts/hooks/pre-push-unit.ts +4 -2
- package/scripts/hooks/pretool-guard-cli.ts +1 -8
- package/scripts/hooks/pretool-guard.ts +32 -19
- package/scripts/hooks/reserved-run.ts +67 -9
- package/scripts/hooks/run-hook.sh +13 -4
- package/scripts/hooks/shell-rules-notice.ts +37 -0
- package/scripts/hooks/stop-actions.ts +2 -21
- package/scripts/hooks/stop-guard.ts +13 -9
- package/scripts/init/hook-command-rewrite.ts +19 -5
- package/scripts/init/hook-launch.ts +15 -17
- package/scripts/init/init-actions.ts +0 -6
- package/scripts/init/init-ai-copy.ts +10 -36
- package/scripts/init/init-bootstrap.ts +9 -8
- package/scripts/init/init-dry-run-report.ts +1 -1
- package/scripts/init/init-dry-run.ts +1 -1
- package/scripts/init/init-file-action.ts +7 -9
- package/scripts/init/init-logic-json-merge.ts +2 -2
- package/scripts/init/init-logic-migrate.ts +9 -82
- package/scripts/init/init-logic.ts +3 -2
- package/scripts/init/init-main.ts +12 -0
- package/scripts/init/init.ts +5 -12
- package/scripts/init/kit-development-versions.ts +3 -7
- package/scripts/init/kit-written-paths.ts +2 -2
- package/scripts/init/project-profile.ts +5 -4
- package/scripts/init/tsconfig-preset-migration.ts +2 -1
- package/scripts/init/vscode-tasks.ts +1 -1
- package/scripts/issue/defect-origin-cli.ts +106 -0
- package/scripts/issue/defect-origin-line.ts +60 -0
- package/scripts/issue/defect-origin-main.ts +11 -0
- package/scripts/issue/defect-origin.ts +114 -0
- package/scripts/issue/defect-rate-cli.ts +34 -78
- package/scripts/issue/defect-rate.ts +0 -16
- package/scripts/issue/defect-report-cli.ts +128 -0
- package/scripts/issue/defect-report-format.ts +56 -0
- package/scripts/issue/defect-report-main.ts +11 -0
- package/scripts/issue/defect-report.ts +160 -0
- package/scripts/issue/expected-effect-lint.ts +1 -0
- package/scripts/issue/issue-already-done-cli.ts +62 -0
- package/scripts/issue/issue-body-or-comment.ts +40 -0
- package/scripts/issue/issue-cite-cli.ts +0 -9
- package/scripts/issue/issue-cite-main.ts +12 -0
- package/scripts/issue/issue-classification.ts +12 -7
- package/scripts/issue/issue-comment-cli.ts +10 -24
- package/scripts/issue/issue-comment-main.ts +12 -0
- package/scripts/issue/issue-evidence-exit.ts +100 -0
- package/scripts/issue/issue-file-cli.ts +29 -7
- package/scripts/issue/issue-file.ts +19 -19
- package/scripts/issue/issue-fold-cli.ts +2 -11
- package/scripts/issue/issue-fold-main.ts +12 -0
- package/scripts/issue/issue-labels.ts +81 -90
- package/scripts/issue/issue-lint-cli.ts +2 -10
- package/scripts/issue/issue-lint-main.ts +12 -0
- package/scripts/issue/issue-measured-cli.ts +56 -0
- package/scripts/issue/issue-merged.ts +19 -2
- package/scripts/issue/issue-not-before-label.ts +135 -0
- package/scripts/issue/issue-not-before.ts +111 -0
- package/scripts/issue/issue-number-shape.ts +15 -1
- package/scripts/issue/issue-park.ts +28 -0
- package/scripts/issue/issue-plan-cli.ts +151 -0
- package/scripts/issue/issue-priority.ts +151 -0
- package/scripts/issue/issue-rank.ts +7 -1
- package/scripts/issue/issue-read-cli.ts +3 -10
- package/scripts/issue/issue-read-main.ts +12 -0
- package/scripts/issue/issue-read.ts +29 -5
- package/scripts/issue/issue-release-cli.ts +0 -10
- package/scripts/issue/issue-release-main.ts +13 -0
- package/scripts/issue/issue-release.ts +7 -12
- package/scripts/issue/issue-sample-gate.ts +192 -0
- package/scripts/issue/issue-sample-source.ts +76 -0
- package/scripts/issue/issue-scout-cli.ts +0 -11
- package/scripts/issue/issue-scout-main.ts +14 -0
- package/scripts/issue/issue-state-cli.ts +0 -10
- package/scripts/issue/issue-state-main.ts +12 -0
- package/scripts/issue/issue-watch-diff.ts +56 -15
- package/scripts/issue/issue-watch.ts +2 -1
- package/scripts/issue/issue-wip.ts +2 -7
- package/scripts/issue/measure-rerun-cli.ts +13 -8
- package/scripts/issue/plan-consumers-cli.ts +39 -0
- package/scripts/issue/plan-consumers-main.ts +11 -0
- package/scripts/issue/plan-consumers-section.ts +55 -0
- package/scripts/issue/plan-consumers.ts +127 -0
- package/scripts/josh/agent-session-environment.ts +1 -1
- package/scripts/josh/command-usage.ts +15 -43
- package/scripts/josh/file-map-stamp.ts +49 -16
- package/scripts/josh/hook-decision.ts +32 -20
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +12 -6
- package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
- package/scripts/josh/josh-commands-ai.ts +157 -158
- package/scripts/josh/josh-commands-backlog.ts +82 -16
- package/scripts/josh/josh-commands-clone.ts +1 -0
- package/scripts/josh/josh-commands-development.ts +111 -71
- package/scripts/josh/josh-commands-document.ts +43 -1
- package/scripts/josh/josh-commands-epic.ts +171 -0
- package/scripts/josh/josh-commands-hooks.ts +25 -2
- package/scripts/josh/josh-commands-issue-write.ts +181 -0
- package/scripts/josh/josh-commands-issue.ts +124 -24
- package/scripts/josh/josh-commands-lane.ts +103 -2
- package/scripts/josh/josh-commands-lint.ts +19 -8
- package/scripts/josh/josh-commands-maintenance.ts +112 -4
- package/scripts/josh/josh-commands-pause.ts +29 -0
- package/scripts/josh/josh-commands-progress.ts +87 -0
- package/scripts/josh/josh-commands-project.ts +138 -9
- package/scripts/josh/josh-commands-review.ts +124 -0
- package/scripts/josh/josh-commands-run.ts +211 -23
- package/scripts/josh/josh-commands-ship.ts +169 -0
- package/scripts/josh/josh-commands-split.ts +9 -0
- package/scripts/josh/josh-commands-versioning.ts +49 -2
- package/scripts/josh/josh-commands-workflow.ts +144 -6
- package/scripts/josh/josh-logic.ts +6 -13
- package/scripts/josh/package-directory.ts +2 -4
- package/scripts/josh/process-identity.ts +13 -4
- package/scripts/josh/session-language-cli.ts +4 -8
- package/scripts/josh/session-language-main.ts +13 -0
- package/scripts/josh/session-language.ts +6 -1
- package/scripts/josh/shared-cache.ts +90 -0
- package/scripts/josh/stamp-file.ts +9 -15
- package/scripts/lane/lane-await.ts +51 -12
- package/scripts/lane/lane-cache.ts +5 -30
- package/scripts/lane/lane-capacity.ts +14 -23
- package/scripts/lane/lane-check-stats.ts +62 -21
- package/scripts/lane/lane-child-invocation.ts +8 -0
- package/scripts/lane/lane-cli.ts +15 -5
- package/scripts/lane/lane-close.ts +86 -18
- package/scripts/lane/lane-core-wait-stats.ts +66 -0
- package/scripts/lane/lane-dispatch.ts +24 -3
- package/scripts/lane/lane-gap-stats.ts +156 -0
- package/scripts/lane/lane-handoff.ts +69 -1
- package/scripts/lane/lane-held-stats.ts +129 -0
- package/scripts/lane/lane-install.ts +4 -11
- package/scripts/lane/lane-launch-cli.ts +0 -9
- package/scripts/lane/lane-launch-main.ts +12 -0
- package/scripts/lane/lane-ledger-schema.ts +266 -0
- package/scripts/lane/lane-ledger.ts +92 -123
- package/scripts/lane/lane-limit-cli.ts +12 -1
- package/scripts/lane/lane-measure-cli.ts +57 -11
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-parked.ts +3 -3
- package/scripts/lane/lane-pause-cli.ts +130 -0
- package/scripts/lane/lane-pause.ts +158 -0
- package/scripts/lane/lane-process-table.ts +166 -0
- package/scripts/lane/lane-reap-settle.ts +124 -0
- package/scripts/lane/lane-reap.ts +50 -15
- package/scripts/lane/lane-registry.ts +24 -3
- package/scripts/lane/lane-residents.ts +162 -0
- package/scripts/lane/lane-restart.ts +22 -2
- package/scripts/lane/lane-round-two-stats.ts +49 -0
- package/scripts/lane/lane-sampler.ts +4 -0
- package/scripts/lane/lane-session-action.ts +19 -5
- package/scripts/lane/lane-session-broker.ts +102 -21
- package/scripts/lane/lane-snapshot-trace.ts +84 -0
- package/scripts/lane/lane-spans.ts +51 -0
- package/scripts/lane/lane-spent.ts +6 -3
- package/scripts/lane/lane-stage-stats.ts +7 -2
- package/scripts/lane/lane-state.ts +302 -0
- package/scripts/lane/lane-stats.ts +58 -4
- package/scripts/lane/lane-stop-stats.ts +113 -37
- package/scripts/lane/lane-test-related-stats.ts +127 -0
- package/scripts/lane/lane-transcript-calls.ts +145 -0
- package/scripts/lane/lane-transcript-stats.ts +168 -0
- package/scripts/lane/lane-vacant.ts +13 -3
- package/scripts/lane/lane-withdraw-cli.ts +5 -4
- package/scripts/lane/lane-withdraw.ts +50 -49
- package/scripts/lane/process-directories.ts +70 -0
- package/scripts/lane/process-lane-marks.ts +94 -0
- package/scripts/lib/atomic-write.ts +62 -0
- package/scripts/lib/buffered-process.ts +12 -5
- package/scripts/lib/cli-flags.ts +53 -0
- package/scripts/lib/figure-format.ts +63 -0
- package/scripts/lib/json-value.ts +9 -1
- package/scripts/lib/package-manifest.ts +35 -0
- package/scripts/lib/read-file.ts +3 -1
- package/scripts/lib/stamped-memo.ts +63 -0
- package/scripts/lib/stdout-on-stderr.ts +24 -0
- package/scripts/lib/timeouts.ts +9 -0
- package/scripts/lib/transcript-record.ts +91 -0
- package/scripts/lines/effective-limit.ts +1 -1
- package/scripts/lint/eslint-cache-dependencies.ts +145 -0
- package/scripts/lint/eslint-daemon.ts +265 -0
- package/scripts/lint/format.ts +11 -2
- package/scripts/lint/import-graph.ts +279 -0
- package/scripts/lint/lint-gate-scope.ts +102 -0
- package/scripts/lint/lint-parallel-main.ts +19 -0
- package/scripts/lint/lint-parallel.ts +62 -30
- package/scripts/lint/lint-related-scope.ts +30 -24
- package/scripts/lint/lint-related.ts +38 -6
- package/scripts/notify/confirmation-options.ts +1 -2
- package/scripts/notify/telegram-notify.ts +20 -20
- package/scripts/notify/telegram-test-logic.ts +0 -1
- package/scripts/notify/telegram-test-main.ts +8 -0
- package/scripts/notify/telegram-test.ts +2 -6
- package/scripts/observations/observation-ledger.ts +13 -0
- package/scripts/observations/observations-flush-landing.ts +5 -3
- package/scripts/observations/observations-flush.ts +6 -1
- package/scripts/overrides/overrides-check.ts +2 -5
- package/scripts/overrides/overrides-files.ts +2 -1
- package/scripts/overrides/overrides-logic.ts +3 -6
- package/scripts/package/verify-optional-eslint-install.ts +8 -6
- package/scripts/propagate/propagate-publish.ts +2 -7
- package/scripts/propagate/propagate-targets.ts +4 -12
- package/scripts/refactor/import-graph.ts +9 -7
- package/scripts/release/github-release-runs.ts +17 -6
- package/scripts/release/release-approval-prune.ts +18 -0
- package/scripts/release/release-history.ts +1 -3
- package/scripts/release/release-progress.ts +42 -22
- package/scripts/release/release-publish-run.ts +39 -0
- package/scripts/release/release-publish.ts +6 -6
- package/scripts/release/release-scope-cli.ts +0 -10
- package/scripts/release/release-scope-main.ts +12 -0
- package/scripts/repo/repo-setting.ts +3 -6
- package/scripts/repo/required-checks-logic.ts +6 -15
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/report/report-labels.ts +155 -0
- package/scripts/report/report-lint-cli.ts +3 -0
- package/scripts/report/report-lint.ts +85 -110
- package/scripts/report/report-template-cli.ts +59 -0
- package/scripts/report/report-template.ts +112 -0
- package/scripts/review/acceptance-map.ts +1 -0
- package/scripts/review/removed-tests-check.ts +86 -0
- package/scripts/review/removed-tests.ts +149 -0
- package/scripts/review/review-brief-cli.ts +81 -15
- package/scripts/review/review-brief-main.ts +12 -0
- package/scripts/review/review-brief.ts +31 -3
- package/scripts/review/review-code-tree.ts +10 -6
- package/scripts/review/review-comment-round.ts +26 -8
- package/scripts/review/review-finding-ledger.ts +30 -15
- package/scripts/review/review-interaction.ts +94 -0
- package/scripts/review/review-readers-scan.ts +163 -0
- package/scripts/review/review-record-cli.ts +69 -30
- package/scripts/review/review-record-main.ts +12 -0
- package/scripts/review/review-round-one-blobs.ts +221 -0
- package/scripts/review/review-round2-cli.ts +49 -12
- package/scripts/review/review-round2.ts +80 -12
- package/scripts/review/review-stamps.ts +19 -1
- package/scripts/review/review-stop-log.ts +96 -0
- package/scripts/review/review-stops-cli.ts +85 -0
- package/scripts/review/review-tree.ts +6 -17
- package/scripts/review/review-untouched-readers.ts +146 -0
- package/scripts/review/test-titles.ts +118 -0
- package/scripts/rules/agent-model.ts +8 -0
- package/scripts/rules/bash-triggers.ts +46 -3
- package/scripts/rules/decision-oracle-batch.ts +9 -1
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +80 -2
- package/scripts/rules/destructive-command.ts +8 -1
- package/scripts/rules/direct-filing.ts +10 -2
- package/scripts/rules/direct-issue-comment.ts +117 -0
- package/scripts/rules/direct-pr-create.ts +69 -3
- package/scripts/rules/early-heartbeat.ts +2 -1
- package/scripts/rules/file-body.ts +7 -0
- package/scripts/rules/filing-cap.ts +7 -0
- package/scripts/rules/git-argv.ts +72 -14
- package/scripts/rules/git-force.ts +12 -2
- package/scripts/rules/guard-remedy.ts +4 -0
- package/scripts/rules/implementation-cut-verdict.ts +1 -1
- package/scripts/rules/implementation-cut.ts +11 -3
- package/scripts/rules/index-guard.ts +8 -1
- package/scripts/rules/issue-comments.ts +9 -1
- package/scripts/rules/josh-git-bare.ts +7 -0
- package/scripts/rules/lane-background.ts +67 -25
- package/scripts/rules/lane-carry-conflict.ts +6 -0
- package/scripts/rules/lane-direct-tool.ts +74 -0
- package/scripts/rules/lane-interactive-ask.ts +9 -2
- package/scripts/rules/lane-park.ts +45 -23
- package/scripts/rules/lane-split-park.ts +10 -2
- package/scripts/rules/lane-switch-main.ts +7 -0
- package/scripts/rules/oracle-consulted.ts +10 -0
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/permission-guards.ts +3 -0
- package/scripts/rules/piped-verification.ts +1 -1
- package/scripts/rules/poll-loop.ts +7 -0
- package/scripts/rules/pr-merge.ts +123 -0
- package/scripts/rules/protected-files.ts +32 -5
- package/scripts/rules/raw-field-body.ts +6 -0
- package/scripts/rules/rule-body-guard.ts +8 -0
- package/scripts/rules/rule-list.ts +9 -28
- package/scripts/rules/rule-value-cache.ts +4 -9
- package/scripts/rules/rule-value-cli.ts +51 -32
- package/scripts/rules/rule-value.ts +1 -1
- package/scripts/rules/shell-segments.ts +35 -0
- package/scripts/rules/stop-rule-rows.ts +64 -0
- package/scripts/rules/stop-rules.ts +3 -4
- package/scripts/rules/test-declared-commit.ts +11 -1
- package/scripts/rules/third-party-write.ts +7 -0
- package/scripts/rules/timed-rerun.ts +69 -0
- package/scripts/rules/worktree-guard.ts +13 -3
- package/scripts/run/board/run-board-app-name.ts +23 -0
- package/scripts/run/board/run-board-cli.ts +65 -32
- package/scripts/run/board/run-board-earlier.ts +94 -0
- package/scripts/run/board/run-board-ending-reason.ts +67 -0
- package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
- package/scripts/run/board/run-board-estimate.ts +98 -0
- package/scripts/run/board/run-board-fit.ts +153 -36
- package/scripts/run/board/run-board-fold.ts +123 -0
- package/scripts/run/board/run-board-fresh.ts +2 -2
- package/scripts/run/board/run-board-gather-live.ts +29 -0
- package/scripts/run/board/run-board-gather-thread.ts +189 -0
- package/scripts/run/board/run-board-gather-worker.ts +29 -0
- package/scripts/run/board/run-board-gather.ts +187 -0
- package/scripts/run/board/run-board-github.ts +118 -38
- package/scripts/run/board/run-board-header.ts +82 -20
- package/scripts/run/board/run-board-keys.ts +58 -0
- package/scripts/run/board/run-board-kind.ts +20 -6
- package/scripts/run/board/run-board-labels.ts +116 -71
- package/scripts/run/board/run-board-lane-state.ts +109 -0
- package/scripts/run/board/run-board-lane-time.ts +122 -0
- package/scripts/run/board/run-board-layout.ts +239 -60
- package/scripts/run/board/run-board-length.ts +52 -0
- package/scripts/run/board/run-board-machine.ts +8 -4
- package/scripts/run/board/run-board-main.ts +12 -0
- package/scripts/run/board/run-board-notes.ts +52 -31
- package/scripts/run/board/run-board-now.ts +1 -1
- package/scripts/run/board/run-board-operation.ts +15 -33
- package/scripts/run/board/run-board-phase.ts +1 -1
- package/scripts/run/board/run-board-plan-shared.ts +115 -0
- package/scripts/run/board/run-board-plan.ts +55 -3
- package/scripts/run/board/run-board-planning.ts +45 -0
- package/scripts/run/board/run-board-priority.ts +44 -0
- package/scripts/run/board/run-board-process-groups.ts +195 -0
- package/scripts/run/board/run-board-read.ts +151 -27
- package/scripts/run/board/run-board-reason.ts +235 -51
- package/scripts/run/board/run-board-released.ts +35 -0
- package/scripts/run/board/run-board-render-checks.ts +39 -5
- package/scripts/run/board/run-board-render-condition.ts +96 -0
- package/scripts/run/board/run-board-render-drawn.ts +67 -0
- package/scripts/run/board/run-board-render-foot.ts +59 -0
- package/scripts/run/board/run-board-render-icon.ts +35 -0
- package/scripts/run/board/run-board-render-lanes.ts +145 -0
- package/scripts/run/board/run-board-render-lead.ts +80 -0
- package/scripts/run/board/run-board-render-legend.ts +117 -48
- package/scripts/run/board/run-board-render-notes.ts +156 -29
- package/scripts/run/board/run-board-render-processes.ts +196 -0
- package/scripts/run/board/run-board-render-section.ts +119 -0
- package/scripts/run/board/run-board-render-slot.ts +3 -36
- package/scripts/run/board/run-board-render-tail.ts +115 -48
- package/scripts/run/board/run-board-render-time.ts +56 -0
- package/scripts/run/board/run-board-render-title.ts +117 -24
- package/scripts/run/board/run-board-render-waits.ts +104 -20
- package/scripts/run/board/run-board-render.ts +207 -265
- package/scripts/run/board/run-board-roots.ts +54 -0
- package/scripts/run/board/run-board-row-yield.ts +9 -4
- package/scripts/run/board/run-board-setup.ts +1 -12
- package/scripts/run/board/run-board-snapshot.ts +111 -0
- package/scripts/run/board/run-board-spin.ts +2 -2
- package/scripts/run/board/run-board-state.ts +22 -33
- package/scripts/run/board/run-board-status.ts +147 -71
- package/scripts/run/board/run-board-thanks-read.ts +2 -2
- package/scripts/run/board/run-board-tick.ts +122 -107
- package/scripts/run/board/run-board-usage-board.ts +78 -0
- package/scripts/run/board/run-board-usage-lanes.ts +113 -0
- package/scripts/run/board/run-board-usage-listing.ts +93 -0
- package/scripts/run/board/run-board-usage-read.ts +120 -150
- package/scripts/run/board/run-board-usage-rusage.ts +19 -7
- package/scripts/run/board/run-board-usage-text.ts +139 -51
- package/scripts/run/board/run-board-usage-top.ts +102 -0
- package/scripts/run/board/run-board-usage.ts +89 -72
- package/scripts/run/board/run-board-usual.ts +20 -9
- package/scripts/run/carry/run-carry-args.ts +4 -7
- package/scripts/run/carry/run-carry-conversation.ts +1 -1
- package/scripts/run/carry/run-carry.ts +9 -4
- package/scripts/run/cut/run-cut-handoff.ts +2 -2
- package/scripts/run/event/run-event-cli.ts +1 -5
- package/scripts/run/event/run-event-filed.ts +12 -6
- package/scripts/run/event/run-event-follow.ts +2 -3
- package/scripts/run/event/run-event-render.ts +6 -10
- package/scripts/run/event/run-event-scope.ts +2 -2
- package/scripts/run/event/run-event-stream-emit.ts +82 -22
- package/scripts/run/event/run-event-stream.ts +34 -8
- package/scripts/run/hold/run-hold-adopt.ts +65 -0
- package/scripts/run/hold/run-hold-cli.ts +93 -22
- package/scripts/run/hold/run-hold-main.ts +12 -0
- package/scripts/run/hold/run-hold-member.ts +37 -0
- package/scripts/run/hold/run-stop-notify.ts +183 -0
- package/scripts/run/merge/run-merge-auth.ts +31 -0
- package/scripts/run/merge/run-merge-cli.ts +62 -48
- package/scripts/run/merge/run-merge-close.ts +74 -0
- package/scripts/run/merge/run-merge-collect.ts +6 -13
- package/scripts/run/merge/run-merge-driver.ts +71 -0
- package/scripts/run/merge/run-merge-main.ts +12 -0
- package/scripts/run/merge/run-merge-outcome.ts +23 -0
- package/scripts/run/merge/run-merge-restart.ts +39 -0
- package/scripts/run/merge/run-merge-ship.ts +20 -4
- package/scripts/run/merge/run-merge-signals.ts +33 -9
- package/scripts/run/merge/run-merge-steps.ts +120 -85
- package/scripts/run/merge/run-merge.ts +38 -37
- package/scripts/run/park/run-park-cli.ts +91 -0
- package/scripts/run/park/run-park.ts +88 -0
- package/scripts/run/park/run-stalled.ts +68 -0
- package/scripts/run/pause/run-pause-cli.ts +73 -0
- package/scripts/run/pause/run-pause.ts +251 -0
- package/scripts/run/progress/run-progress-cli.ts +4 -12
- package/scripts/run/progress/run-progress-clock.ts +1 -1
- package/scripts/run/progress/run-progress-config.ts +6 -14
- package/scripts/run/progress/run-progress-main.ts +12 -0
- package/scripts/run/progress/run-progress.ts +1 -4
- package/scripts/run/review/run-review.ts +2 -1
- package/scripts/run/run-ending.ts +1 -0
- package/scripts/run/run-invocation.ts +5 -6
- package/scripts/run/run-liveness-cli.ts +6 -8
- package/scripts/run/run-liveness.ts +60 -29
- package/scripts/run/run-next.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +2 -2
- package/scripts/run/run-preflight.ts +18 -3
- package/scripts/run/run-prep-cli.ts +1 -10
- package/scripts/run/run-prep-locate.ts +7 -50
- package/scripts/run/run-prep-main.ts +12 -0
- package/scripts/run/run-prep.ts +6 -0
- package/scripts/run/run-report-cli.ts +101 -13
- package/scripts/run/run-report-handoff.ts +114 -0
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +13 -0
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +1 -1
- package/scripts/run/ship/run-ship-args.ts +121 -0
- package/scripts/run/ship/run-ship-body-draft.ts +110 -0
- package/scripts/run/ship/run-ship-cli.ts +63 -140
- package/scripts/run/ship/run-ship-detach.ts +19 -8
- package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
- package/scripts/run/ship/run-ship-next.ts +18 -2
- package/scripts/run/ship/run-ship-overlap.ts +42 -5
- package/scripts/run/ship/run-ship-place.ts +96 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +81 -24
- package/scripts/run/ship/run-ship-preflight.ts +137 -32
- package/scripts/run/ship/run-ship-probe.ts +11 -3
- package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
- package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
- package/scripts/run/ship/run-ship-return.ts +107 -23
- package/scripts/run/ship/run-ship-review-steps.ts +105 -151
- package/scripts/run/ship/run-ship-review.ts +73 -6
- package/scripts/run/ship/run-ship-reviewer.ts +207 -0
- package/scripts/run/ship/run-ship-stage.ts +55 -6
- package/scripts/run/ship/run-ship-steps.ts +46 -15
- package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
- package/scripts/run/ship/run-ship-stop-text.ts +11 -6
- package/scripts/run/ship/run-ship-sync.ts +43 -6
- package/scripts/run/ship/run-ship.ts +30 -2
- package/scripts/run/tidy/run-tidy-cli.ts +0 -4
- package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
- package/scripts/run/tidy/run-tidy-main.ts +8 -0
- package/scripts/run/wake/run-wake-cli.ts +119 -100
- package/scripts/run/wake/run-wake-code.ts +83 -0
- package/scripts/run/wake/run-wake-driver.ts +19 -8
- package/scripts/run/wake/run-wake-loop.ts +34 -3
- package/scripts/run/wake/run-wake-main.ts +13 -0
- package/scripts/run/wake/run-wake-ports.ts +90 -0
- package/scripts/run/wake/run-wake-takeover.ts +66 -0
- package/scripts/run/wake/run-wake.ts +2 -1
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -1
- package/scripts/safe-chain/project-config.ts +3 -9
- package/scripts/security/security-audit-main.ts +8 -0
- package/scripts/security/security-audit-provision-logic.ts +0 -11
- package/scripts/security/security-audit-provision-main.ts +12 -0
- package/scripts/security/security-audit-provision.ts +11 -26
- package/scripts/security/security-audit.ts +6 -7
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
- package/scripts/split/split-assess-cli.ts +2 -2
- package/scripts/split/split-assess.ts +15 -0
- package/scripts/split/split-measure.ts +65 -0
- package/scripts/sync/claude-settings-merge.ts +8 -15
- package/scripts/sync/directory-copy-guard.ts +4 -9
- package/scripts/sync/file-content.ts +78 -8
- package/scripts/sync/sync-ai-files.ts +3 -5
- package/scripts/sync/sync-configs.ts +11 -23
- package/scripts/sync/sync-hook-safety.ts +4 -10
- package/scripts/sync/sync-main.ts +11 -0
- package/scripts/sync/sync.ts +25 -37
- package/scripts/test/test-declared-changed.ts +2 -2
- package/scripts/test/test-declared.ts +1 -1
- package/scripts/test/test-e2e-guard.ts +25 -1
- package/scripts/test/test-e2e-stamp.ts +38 -0
- package/scripts/test/test-pinned-logic.ts +145 -0
- package/scripts/test/test-pinned-main.ts +78 -0
- package/scripts/test/test-pinned.ts +100 -0
- package/scripts/test/test-read-map.ts +264 -0
- package/scripts/test/test-read-recording.ts +91 -0
- package/scripts/test/test-read-trace.ts +148 -0
- package/scripts/test/test-red-main.ts +12 -0
- package/scripts/test/test-red.ts +12 -30
- package/scripts/test/test-related-main.ts +18 -0
- package/scripts/test/test-related-record.ts +119 -0
- package/scripts/test/test-related-scope.ts +229 -43
- package/scripts/test/test-related.ts +300 -22
- package/scripts/test/test-unit-guard-main.ts +15 -0
- package/scripts/test/test-unit-guard.ts +42 -24
- package/scripts/test/unit-count-file.ts +37 -0
- package/scripts/test/unit-run-marker.ts +162 -0
- package/scripts/test/unit-setup-files.ts +51 -0
- package/scripts/test/unit-worker-share.ts +61 -149
- package/scripts/test/whole-suite-files.ts +63 -0
- package/scripts/time-runtime/time-background.ts +20 -2
- package/scripts/time-runtime/time-bundles.ts +4 -3
- package/scripts/time-runtime/time-density-hook.ts +8 -6
- package/scripts/time-runtime/time-followup-stage.ts +1 -3
- package/scripts/time-runtime/time-format.ts +5 -28
- package/scripts/time-runtime/time-markers.ts +10 -1
- package/scripts/time-runtime/time-shell.ts +97 -10
- package/scripts/time-runtime/time-transcript-line.ts +49 -62
- package/scripts/uninstall/uninstall.ts +1 -1
- package/scripts/version/bump-version-main.ts +12 -0
- package/scripts/version/bump-version.ts +25 -25
- package/scripts/version/effective-upstream.ts +6 -12
- package/scripts/version/latest-corepack.ts +17 -32
- package/scripts/version/latest-if-required-cli.ts +93 -0
- package/scripts/version/latest-lane-guard-main.ts +8 -0
- package/scripts/version/latest-lane-guard.ts +0 -4
- package/scripts/version/latest-scope-cli.ts +0 -9
- package/scripts/version/latest-scope-main.ts +12 -0
- package/scripts/version/latest-update.ts +5 -5
- package/scripts/version/npm-registry.ts +44 -6
- package/scripts/version/publishable-range-check.ts +5 -16
- package/scripts/version/release-age.ts +1 -1
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/release-window.ts +38 -0
- package/scripts/version/running-binary.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +3 -8
- package/scripts/version/version-targets.ts +6 -28
- package/templates/dependabot.yml +29 -0
- package/templates/gitignore +4 -1
- package/templates/pnpm-workspace.basic.yaml +1 -1
- package/templates/sonar-project.properties +3 -2
- package/templates/workflows/ci.yml +12 -4
- package/templates/workflows/github-release.yml +4 -0
- package/tsconfig.sonar.json +1 -1
- package/.ncurc.json +0 -3
- package/dist/hooks/batch-guard.js +0 -29
- package/dist/hooks/chunk-4KKD2UTK.js +0 -66
- package/dist/hooks/chunk-6TS2JD6D.js +0 -237
- package/dist/hooks/chunk-7DSBJVFH.js +0 -50
- package/dist/hooks/chunk-A65Y4YOR.js +0 -79
- package/dist/hooks/chunk-CDY4NFQG.js +0 -15
- package/dist/hooks/chunk-EFXE6C37.js +0 -81
- package/dist/hooks/chunk-GP4IEC4O.js +0 -20
- package/dist/hooks/chunk-JP45SOCJ.js +0 -56
- package/dist/hooks/chunk-LAOV7NLM.js +0 -45
- package/dist/hooks/chunk-M4HGZV7U.js +0 -83
- package/dist/hooks/chunk-PF2NZL2A.js +0 -131
- package/dist/hooks/chunk-PTICX4OL.js +0 -358
- package/dist/hooks/chunk-RT27QRJW.js +0 -6247
- package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
- package/dist/hooks/chunk-UPUZF3AN.js +0 -279
- package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
- package/dist/hooks/duplicate-read-guard.js +0 -30
- package/dist/hooks/investigation-guard.js +0 -29
- package/scripts/backlog/backlog-stalled-cli.ts +0 -30
- package/scripts/cost-runtime/cost-format.ts +0 -29
- package/scripts/init/basic-path-migration.ts +0 -24
- package/scripts/issue/issue-backlinks-cli.ts +0 -93
- package/scripts/josh/josh-commands-guard.ts +0 -38
- package/scripts/josh/josh-usage-automation.ts +0 -121
- package/scripts/josh/josh-usage-backlog.ts +0 -180
- package/scripts/josh/josh-usage-developer.ts +0 -230
- package/scripts/josh/josh-usage-hooks.ts +0 -38
- package/scripts/josh/josh-usage-issue.ts +0 -205
- package/scripts/josh/josh-usage-review.ts +0 -101
- package/scripts/josh/josh-usage-run.ts +0 -252
- package/scripts/josh/josh-usage-session.ts +0 -238
- package/scripts/josh/josh-usage-workflow.ts +0 -212
- package/scripts/lint/cross-file-recheck.ts +0 -155
- package/scripts/registry-migration/migrate-logic.ts +0 -237
- package/scripts/registry-migration/migrate.ts +0 -292
- package/scripts/registry-migration/user-npmrc.ts +0 -15
- package/scripts/rules/rule-guard.ts +0 -23
- package/scripts/rules/rule-registry-rows.ts +0 -292
- package/scripts/rules/rule-registry.ts +0 -112
- package/scripts/run/run-stranded-cli.ts +0 -27
|
@@ -36,7 +36,6 @@ const LABEL_NAMES_FILTER = '.[].name'
|
|
|
36
36
|
const LABELS_SEGMENT = '/labels'
|
|
37
37
|
const COMMENTS_SEGMENT = '/comments'
|
|
38
38
|
const CLOSED_STATE = 'closed'
|
|
39
|
-
const NOT_PLANNED_REASON = 'not_planned'
|
|
40
39
|
const COLOR_HASH = '#'
|
|
41
40
|
const UNPROCESSABLE_STATUS = 422
|
|
42
41
|
const ALREADY_EXISTS_CODE = 'already_exists'
|
|
@@ -57,21 +56,39 @@ async function did_write_succeed(write: () => Promise<unknown>): Promise<boolean
|
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
|
|
60
|
-
async function
|
|
59
|
+
async function issue_patch(
|
|
60
|
+
issue_number: string,
|
|
61
|
+
fields: Readonly<Record<string, string>>,
|
|
62
|
+
repo?: string,
|
|
63
|
+
): Promise<string> {
|
|
61
64
|
return await git_gh_exec.exec_gh_api({
|
|
62
|
-
path: git_gh_api_path.issue_api_path(issue_number),
|
|
65
|
+
path: git_gh_api_path.issue_api_path(issue_number, repo),
|
|
63
66
|
method: PATCH_METHOD,
|
|
64
|
-
body: JSON.stringify(
|
|
67
|
+
body: JSON.stringify(fields),
|
|
65
68
|
jq_filter: HTML_URL_FILTER,
|
|
66
69
|
})
|
|
67
70
|
}
|
|
68
71
|
|
|
72
|
+
// The optional `repo` (`owner/name`) on these writes addresses an issue in another repository; left
|
|
73
|
+
// out, the path keeps gh's `{owner}/{repo}` placeholder — the checkout's own repository.
|
|
74
|
+
async function issue_edit_body(issue_number: string, body: string, repo?: string): Promise<string> {
|
|
75
|
+
return await issue_patch(issue_number, { body }, repo)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function issue_edit_title(
|
|
79
|
+
issue_number: string,
|
|
80
|
+
title: string,
|
|
81
|
+
repo?: string,
|
|
82
|
+
): Promise<string> {
|
|
83
|
+
return await issue_patch(issue_number, { title }, repo)
|
|
84
|
+
}
|
|
85
|
+
|
|
69
86
|
// **Every comment josh posts carries `RUN_MARKER`**, an HTML comment GitHub does not render. A run
|
|
70
87
|
// posts under the person's own `gh` login, so the marker is the only thing that tells the issue watch
|
|
71
88
|
// (`issue-watch-diff.ts`) a run's comment from a person's update.
|
|
72
|
-
async function issue_comment(issue_number: string, body: string): Promise<string> {
|
|
89
|
+
async function issue_comment(issue_number: string, body: string, repo?: string): Promise<string> {
|
|
73
90
|
return await git_gh_exec.exec_gh_api({
|
|
74
|
-
path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
|
|
91
|
+
path: `${git_gh_api_path.issue_api_path(issue_number, repo)}${COMMENTS_SEGMENT}`,
|
|
75
92
|
body: JSON.stringify({ body: `${body}\n\n${issue_watch_diff.RUN_MARKER}` }),
|
|
76
93
|
jq_filter: HTML_URL_FILTER,
|
|
77
94
|
})
|
|
@@ -119,18 +136,6 @@ async function issue_close(issue_number: string, comment: string | undefined): P
|
|
|
119
136
|
return await close_with(issue_number, comment, { state: CLOSED_STATE })
|
|
120
137
|
}
|
|
121
138
|
|
|
122
|
-
// The same close as "not planned" — the reason `issue-merged.ts` reads as no merge, so a closed issue
|
|
123
|
-
// that was withdrawn is never taken for one whose work landed.
|
|
124
|
-
async function issue_close_not_planned(
|
|
125
|
-
issue_number: string,
|
|
126
|
-
comment: string | undefined,
|
|
127
|
-
): Promise<boolean> {
|
|
128
|
-
return await close_with(issue_number, comment, {
|
|
129
|
-
state: CLOSED_STATE,
|
|
130
|
-
state_reason: NOT_PLANNED_REASON,
|
|
131
|
-
})
|
|
132
|
-
}
|
|
133
|
-
|
|
134
139
|
// REST answers 422 `{"resource":"Label","code":"invalid","field":"color"}` for a color carrying a
|
|
135
140
|
// leading `#`. The one caller passes the hash form (`EPIC_LABEL_COLOR`), so dropping it here is what
|
|
136
141
|
// keeps that call site unchanged.
|
|
@@ -225,12 +230,16 @@ async function issue_create_with_label(input: {
|
|
|
225
230
|
// say why it refused.
|
|
226
231
|
type LabelWrite = { is_applied: true } | { is_applied: false; reason: string }
|
|
227
232
|
|
|
228
|
-
// The issue's label names, read back after a failed write
|
|
229
|
-
//
|
|
230
|
-
|
|
233
|
+
// The issue's label names, every page of them — read back after a failed write, and by a pull
|
|
234
|
+
// request's classification read. A read that itself fails answers `undefined`, which the write
|
|
235
|
+
// treats as "not applied" — its own error is the reason then.
|
|
236
|
+
async function read_label_names(
|
|
237
|
+
issue_number: string,
|
|
238
|
+
repo?: string,
|
|
239
|
+
): Promise<Array<string> | undefined> {
|
|
231
240
|
try {
|
|
232
241
|
const raw = await git_gh_exec.exec_gh_api({
|
|
233
|
-
path:
|
|
242
|
+
path: git_gh_api_path.issue_labels_api_path(issue_number, repo),
|
|
234
243
|
should_paginate: true,
|
|
235
244
|
jq_filter: LABEL_NAMES_FILTER,
|
|
236
245
|
})
|
|
@@ -247,15 +256,19 @@ async function read_label_names(issue_number: string): Promise<Array<string> | u
|
|
|
247
256
|
// after the write or a secondary rate limit can each throw after the label landed — which refused a
|
|
248
257
|
// lane dispatch whose label was in fact applied. So a throw is confirmed by
|
|
249
258
|
// reading the labels back, and only a label that is really absent answers `is_applied: false`.
|
|
250
|
-
async function issue_apply_label(
|
|
251
|
-
|
|
259
|
+
async function issue_apply_label(
|
|
260
|
+
issue_number: string,
|
|
261
|
+
label: string,
|
|
262
|
+
repo?: string,
|
|
263
|
+
): Promise<LabelWrite> {
|
|
264
|
+
const labels_path = git_gh_api_path.issue_labels_api_path(issue_number, repo)
|
|
252
265
|
|
|
253
266
|
try {
|
|
254
267
|
await git_gh_exec.exec_gh_api({ path: labels_path, body: JSON.stringify({ labels: [label] }) })
|
|
255
268
|
|
|
256
269
|
return { is_applied: true }
|
|
257
270
|
} catch (error) {
|
|
258
|
-
const names = await read_label_names(issue_number)
|
|
271
|
+
const names = await read_label_names(issue_number, repo)
|
|
259
272
|
|
|
260
273
|
if (names?.includes(label) === true) return { is_applied: true }
|
|
261
274
|
error_text.trace_swallowed('git_gh_issue_write.issue_apply_label', error)
|
|
@@ -271,8 +284,12 @@ async function issue_apply_label(issue_number: string, label: string): Promise<L
|
|
|
271
284
|
// Applied after the body edit so a failure leaves an issue with the epic sections and no label,
|
|
272
285
|
// which `epic:check` reports — rather than a labelled issue with nothing to track. The caller checks
|
|
273
286
|
// the return: the label is what the auto-close filters on.
|
|
274
|
-
async function issue_add_label(
|
|
275
|
-
|
|
287
|
+
async function issue_add_label(
|
|
288
|
+
issue_number: string,
|
|
289
|
+
label: string,
|
|
290
|
+
repo?: string,
|
|
291
|
+
): Promise<boolean> {
|
|
292
|
+
const write = await issue_apply_label(issue_number, label, repo)
|
|
276
293
|
|
|
277
294
|
return write.is_applied
|
|
278
295
|
}
|
|
@@ -287,7 +304,7 @@ async function issue_add_label(issue_number: string, label: string): Promise<boo
|
|
|
287
304
|
// a `false` swallowed here would reach that guard as a success and the step would be reported as
|
|
288
305
|
// done.
|
|
289
306
|
async function issue_remove_label(issue_number: string, label: string): Promise<void> {
|
|
290
|
-
const labels_path =
|
|
307
|
+
const labels_path = git_gh_api_path.issue_labels_api_path(issue_number)
|
|
291
308
|
|
|
292
309
|
await git_gh_exec.exec_gh_api({
|
|
293
310
|
path: `${labels_path}/${encodeURIComponent(label)}`,
|
|
@@ -295,6 +312,25 @@ async function issue_remove_label(issue_number: string, label: string): Promise<
|
|
|
295
312
|
})
|
|
296
313
|
}
|
|
297
314
|
|
|
315
|
+
// **The removal for a caller that wants the label gone, not removed by this call** — a release that
|
|
316
|
+
// may find the label already off. A failed DELETE is confirmed against the labels the issue carries,
|
|
317
|
+
// the read `issue_apply_label` confirms an addition with, so an absent label answers `true` and a
|
|
318
|
+
// failure that left the label on answers `false`.
|
|
319
|
+
async function issue_clear_label(issue_number: string, label: string): Promise<boolean> {
|
|
320
|
+
try {
|
|
321
|
+
await issue_remove_label(issue_number, label)
|
|
322
|
+
|
|
323
|
+
return true
|
|
324
|
+
} catch (error) {
|
|
325
|
+
const names = await read_label_names(issue_number)
|
|
326
|
+
|
|
327
|
+
if (names?.includes(label) === false) return true
|
|
328
|
+
error_text.trace_swallowed('git_gh_issue_write.issue_clear_label', error)
|
|
329
|
+
|
|
330
|
+
return false
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
298
334
|
// The blocker's **database id**, which is the only thing the dependencies endpoint accepts — and the
|
|
299
335
|
// reason this resolution exists rather than the issue number being sent straight through.
|
|
300
336
|
//
|
|
@@ -354,16 +390,18 @@ async function issue_remove_blocked_by(issue_number: string, blocker: string): P
|
|
|
354
390
|
|
|
355
391
|
const git_gh_issue_write = {
|
|
356
392
|
issue_edit_body,
|
|
393
|
+
issue_edit_title,
|
|
357
394
|
issue_comment,
|
|
358
395
|
issue_try_comment,
|
|
359
396
|
issue_close,
|
|
360
|
-
issue_close_not_planned,
|
|
361
397
|
label_ensure,
|
|
362
398
|
issue_create_request,
|
|
363
399
|
issue_create_with_label,
|
|
400
|
+
read_label_names,
|
|
364
401
|
issue_apply_label,
|
|
365
402
|
issue_add_label,
|
|
366
403
|
issue_remove_label,
|
|
404
|
+
issue_clear_label,
|
|
367
405
|
issue_add_blocked_by,
|
|
368
406
|
issue_remove_blocked_by,
|
|
369
407
|
}
|
|
@@ -4,6 +4,9 @@ import { BLOCKED_BY_COUNT_FIELD } from './git-gh-issue-rest'
|
|
|
4
4
|
import { git_gh_issue_write } from './git-gh-issue-write'
|
|
5
5
|
|
|
6
6
|
const NUMBER_AND_BODY_FIELDS = 'number,body'
|
|
7
|
+
// The label listing's fields. `stateReason` rides along on the same response: the epic auto-close
|
|
8
|
+
// reads `reopened` off it, so its sweep leaves an epic a person reopened to them (#4564).
|
|
9
|
+
const LABELLED_FIELDS = 'number,body,stateReason'
|
|
7
10
|
// The backlog scan's fields. The title rides along because the pre-filing scan compares titles
|
|
8
11
|
// and it costs nothing: the same listing request already carries it, so the
|
|
9
12
|
// two consumers share one read rather than each making their own.
|
|
@@ -111,7 +114,7 @@ async function issue_search_body(term: string, limit: number): Promise<IssueList
|
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
async function issue_list_by_label(label: string, limit: number): Promise<IssueListOutcome> {
|
|
114
|
-
return await issue_list({ json_fields:
|
|
117
|
+
return await issue_list({ json_fields: LABELLED_FIELDS, limit, label })
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
// The same filter with the fields the `auto-ok` pickup needs: it orders by
|
|
@@ -151,8 +154,9 @@ async function issue_list_by_label_in_repo(
|
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
// Every open issue with what `josh auto-ok:judge` judges it by — its labels and body — and `updatedAt`,
|
|
154
|
-
// so the backlog driver's resident check reads an issue's comments again only once it has moved
|
|
155
|
-
|
|
157
|
+
// so the backlog driver's resident check reads an issue's comments again only once it has moved; and
|
|
158
|
+
// `author_association` and `user`, so an issue a third party filed is never judged.
|
|
159
|
+
const JUDGEMENT_FIELDS = 'number,title,body,labels,updatedAt,author_association,user'
|
|
156
160
|
|
|
157
161
|
async function issue_list_open_for_judgement(limit: number): Promise<IssueListOutcome> {
|
|
158
162
|
return await issue_list({ json_fields: JUDGEMENT_FIELDS, limit })
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
2
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
3
|
+
import { z } from 'zod'
|
|
4
|
+
import { FULL_PAGE_QUERY } from './git-gh-api-path'
|
|
5
|
+
import { git_gh_conditional, type ConditionalRead } from './git-gh-conditional'
|
|
6
|
+
import { git_gh_exec } from './git-gh-exec'
|
|
7
|
+
|
|
8
|
+
// The merge gate's per-poll reads, each sent with the ETag of this process's previous answer
|
|
9
|
+
// (joshuafolkken/kit#4550).
|
|
10
|
+
//
|
|
11
|
+
// **Never a pull request's detail**: GitHub computes its `mergeable_state` lazily, under an unchanged
|
|
12
|
+
// ETag, so a 304 would keep a stale state (joshuafolkken/kit#4589).
|
|
13
|
+
//
|
|
14
|
+
// **`pnpm josh followup` reads the same pull request every 10 seconds** while its checks run, and
|
|
15
|
+
// every lane waiting on its merge does so at once. A `304 Not Modified` does not count against the
|
|
16
|
+
// rate limit, so a poll that finds nothing changed costs only its pull detail read.
|
|
17
|
+
//
|
|
18
|
+
// **A listing is read one page at a time only while it fits in one.** A listing longer than a page is
|
|
19
|
+
// read through `--paginate --slurp` as before; the conditional read cannot page, and a partial
|
|
20
|
+
// listing would drop checks from the verdict.
|
|
21
|
+
|
|
22
|
+
const UNREADABLE_POLL_MESSAGE = 'gh api could not read a merge-gate poll'
|
|
23
|
+
const PAGE_SIZE = 100
|
|
24
|
+
|
|
25
|
+
interface KeptAnswer {
|
|
26
|
+
etag: string
|
|
27
|
+
body: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const kept_by_path = new Map<string, KeptAnswer>()
|
|
31
|
+
|
|
32
|
+
const page_schema = z.object({ total_count: z.number() })
|
|
33
|
+
|
|
34
|
+
// gh's own failure rides along as the cause and in the message: the poll loop's warning prints the
|
|
35
|
+
// message alone, and a rate limit must read differently there from expired auth.
|
|
36
|
+
function unreadable(path: string, answer: ConditionalRead): Error {
|
|
37
|
+
const cause = answer.kind === 'unreadable' ? answer.cause : undefined
|
|
38
|
+
const reason = cause === undefined ? '' : `: ${error_text.message_of(cause)}`
|
|
39
|
+
|
|
40
|
+
return new Error(`${UNREADABLE_POLL_MESSAGE}: ${path}${reason}`, { cause })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function to_body(path: string, answer: ConditionalRead): string {
|
|
44
|
+
const previous = kept_by_path.get(path)
|
|
45
|
+
|
|
46
|
+
if (previous !== undefined && answer.kind === 'unchanged') return previous.body
|
|
47
|
+
if (answer.kind !== 'changed') throw unreadable(path, answer)
|
|
48
|
+
if (answer.etag !== undefined) kept_by_path.set(path, { etag: answer.etag, body: answer.body })
|
|
49
|
+
|
|
50
|
+
return answer.body
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// The answer for `path`, or the previous one where GitHub says it has not changed. A failure throws,
|
|
54
|
+
// the contract the unconditional read had.
|
|
55
|
+
async function read(path: string): Promise<string> {
|
|
56
|
+
const answer = await git_gh_conditional.read_conditional(path, kept_by_path.get(path)?.etag)
|
|
57
|
+
|
|
58
|
+
return to_body(path, answer)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A page that does not parse as a listing is not taken as the whole one: the full read answers it, and
|
|
62
|
+
// its own parser reports what it was.
|
|
63
|
+
function is_whole_listing(page: string): boolean {
|
|
64
|
+
const total = json_value.parse_with(page, page_schema)?.total_count
|
|
65
|
+
|
|
66
|
+
return total !== undefined && total <= PAGE_SIZE
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// A commit listing in the `--slurp` shape — an array of pages — however it was read.
|
|
70
|
+
async function read_object_pages(path: string): Promise<string> {
|
|
71
|
+
const full_path = `${path}${FULL_PAGE_QUERY}`
|
|
72
|
+
const page = await read(full_path)
|
|
73
|
+
|
|
74
|
+
if (is_whole_listing(page)) return `[${page}]`
|
|
75
|
+
|
|
76
|
+
return await git_gh_exec.exec_gh_api({
|
|
77
|
+
path: full_path,
|
|
78
|
+
should_paginate: true,
|
|
79
|
+
should_slurp: true,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function forget_poll_reads(): void {
|
|
84
|
+
kept_by_path.clear()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const git_gh_poll_read = { UNREADABLE_POLL_MESSAGE, forget_poll_reads, read, read_object_pages }
|
|
88
|
+
|
|
89
|
+
export { git_gh_poll_read }
|
|
@@ -17,8 +17,10 @@ import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
|
|
|
17
17
|
const GRAPHQL_PATH = 'graphql'
|
|
18
18
|
const OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`
|
|
19
19
|
const MISSING_NODE_ID_MESSAGE = 'gh api answered a pull request without a node_id'
|
|
20
|
+
// **`expectedHeadOid` binds the auto-merge to the commit the caller pushed** (#4036): GitHub then
|
|
21
|
+
// refuses it if the head has moved, rather than landing a commit nobody here pushed or checked.
|
|
20
22
|
const ENABLE_AUTO_MERGE_MUTATION =
|
|
21
|
-
'mutation($id: ID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE }) { clientMutationId } }'
|
|
23
|
+
'mutation($id: ID!, $head: GitObjectID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE, expectedHeadOid: $head }) { clientMutationId } }'
|
|
22
24
|
|
|
23
25
|
interface OpenPull {
|
|
24
26
|
number: number
|
|
@@ -26,13 +28,16 @@ interface OpenPull {
|
|
|
26
28
|
has_auto_merge: boolean
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
async function pr_enable_auto_merge(branch_name: string): Promise<void> {
|
|
31
|
+
async function pr_enable_auto_merge(branch_name: string, head_sha: string): Promise<void> {
|
|
30
32
|
const pull = await read_pull(await require_pr_number(branch_name))
|
|
31
33
|
if (pull.node_id === undefined) throw new Error(MISSING_NODE_ID_MESSAGE)
|
|
32
34
|
|
|
33
35
|
await git_gh_exec.exec_gh_api({
|
|
34
36
|
path: GRAPHQL_PATH,
|
|
35
|
-
body: JSON.stringify({
|
|
37
|
+
body: JSON.stringify({
|
|
38
|
+
query: ENABLE_AUTO_MERGE_MUTATION,
|
|
39
|
+
variables: { id: pull.node_id, head: head_sha },
|
|
40
|
+
}),
|
|
36
41
|
})
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -27,7 +27,7 @@ import { MERGED_STATE, to_gh_state } from './git-gh-rest-state'
|
|
|
27
27
|
// branch name that says nothing about which repository holds it. Named once
|
|
28
28
|
// because both sides of a pull request carry the same shape.
|
|
29
29
|
const rest_repo_schema = z.looseObject({ full_name: z.string().optional() }).nullish()
|
|
30
|
-
const rest_pull_side_schema = z.looseObject({ repo: rest_repo_schema })
|
|
30
|
+
const rest_pull_side_schema = z.looseObject({ ref: z.string().optional(), repo: rest_repo_schema })
|
|
31
31
|
|
|
32
32
|
type RestPullSide = z.infer<typeof rest_pull_side_schema>
|
|
33
33
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { FULL_PAGE_QUERY, git_gh_api_path } from './git-gh-api-path'
|
|
2
|
+
import { git_gh_branch_rules } from './git-gh-branch-rules'
|
|
2
3
|
import { git_gh_exec } from './git-gh-exec'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
4
|
+
import { git_gh_poll_read } from './git-gh-poll-read'
|
|
5
|
+
import { require_pr_number } from './git-gh-pr-read'
|
|
6
|
+
import { git_gh_pr_rest, type RestPull } from './git-gh-pr-rest'
|
|
5
7
|
import { git_gh_pr_review } from './git-gh-pr-review'
|
|
6
8
|
import { git_gh_pr_rollup } from './git-gh-pr-rollup'
|
|
7
9
|
import { to_gh_state } from './git-gh-rest-state'
|
|
@@ -19,17 +21,6 @@ import { to_gh_state } from './git-gh-rest-state'
|
|
|
19
21
|
|
|
20
22
|
const NO_HEAD_SHA_MESSAGE = 'gh api answered a pull request with no head commit'
|
|
21
23
|
|
|
22
|
-
// Both commit endpoints answer an *object* wrapping the listing, so `--paginate` alone would emit
|
|
23
|
-
// one document per page and `JSON.parse` would reject the pair; `--slurp` wraps the pages in one
|
|
24
|
-
// outer array instead (`git-gh-exec.ts` → `GhApiRequest`).
|
|
25
|
-
async function read_object_pages(path: string): Promise<string> {
|
|
26
|
-
return await git_gh_exec.exec_gh_api({
|
|
27
|
-
path: `${path}${FULL_PAGE_QUERY}`,
|
|
28
|
-
should_paginate: true,
|
|
29
|
-
should_slurp: true,
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
24
|
// The reviews endpoint answers a bare array, whose pages `gh` merges into one array on its own —
|
|
34
25
|
// slurping it would produce `[[…],[…]]`, which the listing schema then rejects.
|
|
35
26
|
async function read_array_pages(path: string): Promise<string> {
|
|
@@ -47,11 +38,12 @@ function read_head_sha(pull: RestPull): string {
|
|
|
47
38
|
}
|
|
48
39
|
|
|
49
40
|
// One pull request's rollup: the check runs and the status contexts, read from the head commit and
|
|
50
|
-
// merged back into the single array `gh` answered with.
|
|
41
|
+
// merged back into the single array `gh` answered with. Both endpoints answer an *object* wrapping the
|
|
42
|
+
// listing, so their pages arrive slurped into one outer array (`git-gh-poll-read.ts`).
|
|
51
43
|
async function read_status_check_rollup(commit_sha: string): Promise<Array<object>> {
|
|
52
44
|
const [check_runs_json, status_json] = await Promise.all([
|
|
53
|
-
read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
|
|
54
|
-
read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha)),
|
|
45
|
+
git_gh_poll_read.read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
|
|
46
|
+
git_gh_poll_read.read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha)),
|
|
55
47
|
])
|
|
56
48
|
|
|
57
49
|
return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json })
|
|
@@ -69,10 +61,24 @@ async function pr_get_review_decision(pr_number: number): Promise<string> {
|
|
|
69
61
|
// `git-pr-checks-eval.ts` compares strictly against: `MERGE_STATE_CLEAN` never matches a lower-case
|
|
70
62
|
// `clean`, which would also take every pull request out of the CodeRabbit non-blocking exemption
|
|
71
63
|
// keyed on `UNSTABLE`. The rule is shared with `to_pr_info` rather than written twice.
|
|
64
|
+
//
|
|
65
|
+
// **`headRefOid` is the commit the rollup was read from**, in `gh`'s spelling, so a merge can be bound
|
|
66
|
+
// to the head whose checks passed rather than to whatever the branch points at by then (#4036).
|
|
67
|
+
//
|
|
68
|
+
// **`requiredContexts` is the base branch's required checks** (`git-gh-branch-rules.ts`), which the
|
|
69
|
+
// merge gate reads to accept an `UNSTABLE` pull request held only by an optional check.
|
|
72
70
|
async function build_checks_fields(pull: RestPull): Promise<Record<string, unknown>> {
|
|
71
|
+
const head_sha = read_head_sha(pull)
|
|
72
|
+
const [rollup, required_contexts] = await Promise.all([
|
|
73
|
+
read_status_check_rollup(head_sha),
|
|
74
|
+
git_gh_branch_rules.read_required_contexts(pull.base?.ref),
|
|
75
|
+
])
|
|
76
|
+
|
|
73
77
|
return {
|
|
74
|
-
statusCheckRollup:
|
|
78
|
+
statusCheckRollup: rollup,
|
|
75
79
|
mergeStateStatus: to_gh_state(pull.mergeable_state),
|
|
80
|
+
headRefOid: head_sha,
|
|
81
|
+
requiredContexts: required_contexts,
|
|
76
82
|
}
|
|
77
83
|
}
|
|
78
84
|
|
|
@@ -81,12 +87,19 @@ interface ResolvedPull {
|
|
|
81
87
|
pull: RestPull
|
|
82
88
|
}
|
|
83
89
|
|
|
84
|
-
// The resolution and the detail read, which every path below needs
|
|
85
|
-
//
|
|
90
|
+
// The resolution and the detail read, which every path below needs. The branch → number memo in
|
|
91
|
+
// `git-gh-pr-read.ts` makes the first free after the first poll.
|
|
92
|
+
//
|
|
93
|
+
// **The detail is read without an ETag.** GitHub computes `mergeable_state` lazily and can change it
|
|
94
|
+
// under an unchanged ETag, so a 304 answered from the poll cache kept the gate reading a stale
|
|
95
|
+
// `blocked` on a pull request that had turned `clean` (joshuafolkken/kit#4589).
|
|
86
96
|
async function resolve_pull(branch_name: string): Promise<ResolvedPull> {
|
|
87
97
|
const pr_number = await require_pr_number(branch_name)
|
|
98
|
+
const json = await git_gh_exec.exec_gh_api({
|
|
99
|
+
path: git_gh_api_path.pull_api_path(String(pr_number)),
|
|
100
|
+
})
|
|
88
101
|
|
|
89
|
-
return { pr_number, pull:
|
|
102
|
+
return { pr_number, pull: git_gh_pr_rest.parse_rest_pull(json) }
|
|
90
103
|
}
|
|
91
104
|
|
|
92
105
|
// Everything the snapshot carries except the review decision: three requests rather than four.
|
package/scripts/gh/git-gh-pr.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { pr_classification, type ReleaseClassification } from '#scripts/ci/pr-classification'
|
|
2
2
|
import { git_command } from '#scripts/git/git-command'
|
|
3
3
|
import { poll } from '#scripts/lib/poll'
|
|
4
|
-
import { z } from 'zod'
|
|
5
4
|
import { git_gh_api_path } from './git-gh-api-path'
|
|
6
5
|
import { git_gh_exec } from './git-gh-exec'
|
|
6
|
+
import { gh_failure } from './git-gh-failure'
|
|
7
7
|
import { git_gh_helpers } from './git-gh-helpers'
|
|
8
8
|
import { git_gh_issue_write } from './git-gh-issue-write'
|
|
9
9
|
import { forget_pr_numbers, git_gh_pr_read, read_pull, require_pr_number } from './git-gh-pr-read'
|
|
@@ -49,25 +49,27 @@ const MERGE_UNCONFIRMED_MESSAGE =
|
|
|
49
49
|
'gh api could not read the pull request back after the merge request failed'
|
|
50
50
|
const MERGE_READ_BACK_ATTEMPTS = 3
|
|
51
51
|
const MERGE_READ_BACK_INTERVAL_MS = 1000
|
|
52
|
+
// `PUT pulls/{N}/merge` with a `sha` that is no longer the branch head.
|
|
53
|
+
const HEAD_MOVED_STATUS = 409
|
|
52
54
|
const PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u
|
|
53
|
-
const LABELS_SEGMENT = '/labels'
|
|
54
|
-
const PR_LABELS = z.array(z.object({ name: z.string() }))
|
|
55
55
|
|
|
56
|
+
// A pull request is an issue to the labels endpoint, so the write is the issue one: a failed answer
|
|
57
|
+
// is confirmed by reading the labels back before it is reported as a failed write.
|
|
56
58
|
async function add_pr_classification(number: string, label: ReleaseClassification): Promise<void> {
|
|
57
|
-
await
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
})
|
|
59
|
+
const write = await git_gh_issue_write.issue_apply_label(number, label)
|
|
60
|
+
|
|
61
|
+
if (!write.is_applied) throw new Error(write.reason)
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
// Labels that could not be read are not "no classification": answering that would add a second
|
|
65
|
+
// classification beside the one a person already put on the pull request.
|
|
63
66
|
async function pr_get_classification(
|
|
64
67
|
branch_name: string,
|
|
65
68
|
): Promise<ReleaseClassification | undefined> {
|
|
66
69
|
const number = await require_pr_number(branch_name)
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const names = PR_LABELS.parse(JSON.parse(response)).map((label) => label.name.toLowerCase())
|
|
70
|
+
const labels = await git_gh_issue_write.read_label_names(String(number))
|
|
71
|
+
if (labels === undefined) throw new Error(`Unreadable labels on branch ${branch_name}`)
|
|
72
|
+
const names = labels.map((name) => name.toLowerCase())
|
|
71
73
|
const selected = names.filter((name) => pr_classification.is_classification(name))
|
|
72
74
|
if (selected.length === 0) return undefined
|
|
73
75
|
|
|
@@ -166,16 +168,25 @@ async function pr_update_body(branch_name: string, body: string): Promise<void>
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
// A merge moves the remembered detail read's state, so it is cleared first.
|
|
169
|
-
|
|
171
|
+
//
|
|
172
|
+
// **`sha` binds the merge to the head the checks passed on** (#4036): without it GitHub merges
|
|
173
|
+
// whatever the branch points at, so a commit pushed after the gate went green would land unverified.
|
|
174
|
+
// A head that moved is answered 409 (`is_head_moved`).
|
|
175
|
+
async function put_merge(pr_number: number, head_sha: string): Promise<void> {
|
|
170
176
|
forget_pr_numbers()
|
|
171
177
|
await git_gh_exec.exec_gh_api({
|
|
172
178
|
path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
|
|
173
179
|
method: PUT_METHOD,
|
|
174
|
-
body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD }),
|
|
180
|
+
body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD, sha: head_sha }),
|
|
175
181
|
timeout_ms: MERGE_REQUEST_TIMEOUT_MS,
|
|
176
182
|
})
|
|
177
183
|
}
|
|
178
184
|
|
|
185
|
+
// GitHub's answer to a merge whose `sha` is no longer the branch head.
|
|
186
|
+
function is_head_moved(error: unknown): boolean {
|
|
187
|
+
return gh_failure.failure_of(error)?.status === HEAD_MOVED_STATUS
|
|
188
|
+
}
|
|
189
|
+
|
|
179
190
|
// `undefined` is "nobody read it", kept apart from the `false` that means "the pull request is not
|
|
180
191
|
// merged". Folding the two would report an unread state as a settled answer.
|
|
181
192
|
async function read_merge_state(pr_number: number): Promise<boolean | undefined> {
|
|
@@ -240,11 +251,11 @@ async function has_merge_landed(pr_number: number, merge_error: unknown): Promis
|
|
|
240
251
|
// made by hand between the failure and the read leaves `followup` with exactly the same work to
|
|
241
252
|
// finish. REST offers nothing that would tell the two apart without keeping the merge commit's SHA
|
|
242
253
|
// across a request that never answered.
|
|
243
|
-
async function pr_merge(branch_name: string): Promise<void> {
|
|
254
|
+
async function pr_merge(branch_name: string, head_sha: string): Promise<void> {
|
|
244
255
|
const pr_number = await require_pr_number(branch_name)
|
|
245
256
|
|
|
246
257
|
try {
|
|
247
|
-
await put_merge(pr_number)
|
|
258
|
+
await put_merge(pr_number, head_sha)
|
|
248
259
|
} catch (error) {
|
|
249
260
|
if (!(await has_merge_landed(pr_number, error))) throw error
|
|
250
261
|
}
|
|
@@ -259,6 +270,7 @@ const git_gh_pr = {
|
|
|
259
270
|
pr_comment,
|
|
260
271
|
pr_merge,
|
|
261
272
|
pr_update_body,
|
|
273
|
+
is_head_moved,
|
|
262
274
|
}
|
|
263
275
|
|
|
264
276
|
export { git_gh_pr, MERGE_COMMIT_METHOD, MERGE_REQUEST_TIMEOUT_MS, MERGE_UNCONFIRMED_MESSAGE }
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
CHECK_STATUS_FAIL,
|
|
3
3
|
CHECK_STATUS_MISSING,
|
|
4
4
|
CHECK_STATUS_PASS,
|
|
5
|
+
CHECK_STATUS_PENDING,
|
|
5
6
|
type PrStateSnapshot,
|
|
6
7
|
type RollupCheck,
|
|
7
8
|
} from './git-pr-checks-parse'
|
|
@@ -12,7 +13,7 @@ import {
|
|
|
12
13
|
// to restore the old behavior. Revert once the fresh-context review subagent replaces it.
|
|
13
14
|
const DEFAULT_REQUIRED_CHECKS = ['SonarQube']
|
|
14
15
|
// The single source of the check name every CodeRabbit exemption is keyed on — the merge gate's
|
|
15
|
-
// `
|
|
16
|
+
// `is_unstable_only_from_optional`, the look-ahead's `is_awaited_check`, and the fixtures the two
|
|
16
17
|
// are tested from. A second literal spelling of it anywhere is how one of them silently stops
|
|
17
18
|
// matching after CodeRabbit renames its context.
|
|
18
19
|
const CODERABBIT_CHECK_NAME = 'CodeRabbit'
|
|
@@ -131,15 +132,46 @@ function is_coderabbit_rate_limited(check: RollupCheck): boolean {
|
|
|
131
132
|
)
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
function matches_any(check_name: string, required_names: ReadonlyArray<string>): boolean {
|
|
136
|
+
return required_names.some((required) => is_required_match(check_name, required))
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// A check still running that the base branch's rules do not require — GitHub's default-setup
|
|
140
|
+
// `CodeQL`, which runs for about thirty minutes beside a six-minute CI (joshuafolkken/kit#4351).
|
|
141
|
+
// With no required context known nothing qualifies, so the gate waits for `CLEAN` as it always did.
|
|
142
|
+
function is_optional_pending(
|
|
143
|
+
check: RollupCheck,
|
|
144
|
+
required_contexts: ReadonlyArray<string>,
|
|
145
|
+
): boolean {
|
|
146
|
+
if (required_contexts.length === 0 || check.status !== CHECK_STATUS_PENDING) return false
|
|
147
|
+
|
|
148
|
+
return !matches_any(check.name, required_contexts)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function is_every_context_passing(
|
|
152
|
+
checks: ReadonlyArray<RollupCheck>,
|
|
153
|
+
contexts: ReadonlyArray<string>,
|
|
154
|
+
): boolean {
|
|
155
|
+
return contexts.every(
|
|
156
|
+
(context) => find_required_check(checks, context)?.status === CHECK_STATUS_PASS,
|
|
157
|
+
)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// GitHub reports UNSTABLE for a pull request whose required checks are green while a check outside
|
|
161
|
+
// them is pending or failing. Accept that state when every non-passing check is CodeRabbit's
|
|
162
|
+
// (temporary: CodeRabbit is not required) or an optional one still running, and every context the
|
|
163
|
+
// base branch requires has passed in the rollup itself — any other non-passing check keeps the gate
|
|
164
|
+
// strict. A failed optional check never reaches here: `collect_blocking_failures` ends the wait first.
|
|
165
|
+
function is_unstable_only_from_optional(snapshot: PrStateSnapshot): boolean {
|
|
138
166
|
if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false
|
|
167
|
+
const required_contexts = snapshot.required_contexts ?? []
|
|
139
168
|
const non_passing = snapshot.rollup.filter((check) => check.status !== CHECK_STATUS_PASS)
|
|
140
169
|
if (non_passing.length === 0) return false
|
|
170
|
+
const is_tolerated = non_passing.every(
|
|
171
|
+
(check) => is_coderabbit_check(check.name) || is_optional_pending(check, required_contexts),
|
|
172
|
+
)
|
|
141
173
|
|
|
142
|
-
return
|
|
174
|
+
return is_tolerated && is_every_context_passing(snapshot.rollup, required_contexts)
|
|
143
175
|
}
|
|
144
176
|
|
|
145
177
|
function is_required_check(check_name: string): boolean {
|
|
@@ -169,7 +201,7 @@ function collect_blocking_failures(snapshot: PrStateSnapshot): Array<string> {
|
|
|
169
201
|
function is_mergeable_state(snapshot: PrStateSnapshot): boolean {
|
|
170
202
|
if (is_merge_state_clean(snapshot.merge_state_status)) return true
|
|
171
203
|
|
|
172
|
-
return
|
|
204
|
+
return is_unstable_only_from_optional(snapshot)
|
|
173
205
|
}
|
|
174
206
|
|
|
175
207
|
// The wait's own error text: naming the checks that failed is what turns a red `followup` into
|