@joshuafolkken/kit 1.1784.0 → 1.2116.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/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +60 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +386 -360
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +16 -9
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// **The gate's check names, in a module that imports nothing** (joshuafolkken/kit#5177). Most readers of
|
|
2
|
+
// `gate-plan.ts` wanted only these strings, and importing the plan for them tied every such reader into
|
|
3
|
+
// the plan's own imports — so a change to the plan reached most of the test suite. The plan builds its
|
|
4
|
+
// checks from these; a reader that needs only a name imports this leaf.
|
|
5
|
+
|
|
6
|
+
const LINT_LABEL = 'lint'
|
|
7
|
+
const TYPE_CHECK_LABEL = 'check'
|
|
8
|
+
// The `josh` command the gate's type check runs, shared with `check:related` so the scoped check runs the same one.
|
|
9
|
+
const TYPE_CHECK_TARGET = 'check'
|
|
10
|
+
const SPELL_CHECK_LABEL = 'cspell'
|
|
11
|
+
const SPELL_CHECK_TARGET = 'cspell:dot'
|
|
12
|
+
const UNIT_LABEL = 'test:unit'
|
|
13
|
+
const UNIT_TARGET = 'test:related'
|
|
14
|
+
// **The gate's unit leg runs the whole suite for a changed file every test imports**
|
|
15
|
+
// (joshuafolkken/kit#5122), which every other `josh test:related` narrows to its direct importers.
|
|
16
|
+
const KEEP_WHOLE_SUITE_FLAG = '--keep-whole-suite'
|
|
17
|
+
const BEHAVIOR_LABEL = 'behavior'
|
|
18
|
+
const METRICS_LABEL = 'metrics'
|
|
19
|
+
const EXPORTS_LABEL = 'exports'
|
|
20
|
+
const LOCKFILE_LABEL = 'lockfile'
|
|
21
|
+
|
|
22
|
+
// The checks whose warnings must survive the green record: eslint (the `lint` step) and svelte-check
|
|
23
|
+
// (the `check` step) both exit 0 while reporting per-tree warnings a developer needs to see again, so
|
|
24
|
+
// reusing a record taken from such a run would hide them. Every other step's
|
|
25
|
+
// warning-shaped output — a Vite config deprecation printed by `test:unit`, say — is not a per-tree
|
|
26
|
+
// finding and repeats every run, so it must not withhold the record. `has_checker_warning` narrows
|
|
27
|
+
// the withholding path down to these.
|
|
28
|
+
const WARNING_CHECKER_LABELS: ReadonlyArray<string> = [LINT_LABEL, TYPE_CHECK_LABEL]
|
|
29
|
+
|
|
30
|
+
const gate_labels = {
|
|
31
|
+
BEHAVIOR_LABEL,
|
|
32
|
+
EXPORTS_LABEL,
|
|
33
|
+
KEEP_WHOLE_SUITE_FLAG,
|
|
34
|
+
LINT_LABEL,
|
|
35
|
+
LOCKFILE_LABEL,
|
|
36
|
+
METRICS_LABEL,
|
|
37
|
+
SPELL_CHECK_LABEL,
|
|
38
|
+
SPELL_CHECK_TARGET,
|
|
39
|
+
TYPE_CHECK_LABEL,
|
|
40
|
+
TYPE_CHECK_TARGET,
|
|
41
|
+
UNIT_LABEL,
|
|
42
|
+
UNIT_TARGET,
|
|
43
|
+
WARNING_CHECKER_LABELS,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { gate_labels }
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { process_identity } from '#scripts/josh/process-identity'
|
|
2
|
-
import {
|
|
2
|
+
import type { GateCheckRecord } from '#scripts/lane/lane-ledger-schema'
|
|
3
|
+
import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
|
|
4
|
+
import { lane_paths } from '#scripts/lane/lane-paths'
|
|
3
5
|
import { related_scope } from '#scripts/test/test-related-scope'
|
|
4
6
|
import { core_admission } from './core-admission'
|
|
5
7
|
import { core_budget } from './core-budget'
|
|
6
|
-
import {
|
|
8
|
+
import { gate_labels } from './gate-labels'
|
|
7
9
|
import { gate_report, type GateStepResult } from './gate-report'
|
|
8
10
|
import { machine_capacity } from './machine-capacity'
|
|
9
11
|
|
|
@@ -96,7 +98,7 @@ async function start(ledger_path: string | undefined): Promise<GateLedgerStart>
|
|
|
96
98
|
// The unit leg's own facts: the whole-suite fallback it took, or the since-green no-op that ran no
|
|
97
99
|
// test (joshuafolkken/kit#4457) — the two `josh lane:stats` must not time as an ordinary run.
|
|
98
100
|
function unit_facts(result: GateStepResult): Pick<GateCheckRecord, 'fallback' | 'is_unmoved'> {
|
|
99
|
-
if (result.label !==
|
|
101
|
+
if (result.label !== gate_labels.UNIT_LABEL) return {}
|
|
100
102
|
|
|
101
103
|
return {
|
|
102
104
|
fallback: related_scope.fallback_kind(result.output),
|
|
@@ -120,7 +122,12 @@ function check_records(results: ReadonlyArray<GateStepResult>): Array<GateCheckR
|
|
|
120
122
|
async function record_reused(ledger_path: string | undefined, elapsed_ms: number): Promise<void> {
|
|
121
123
|
if (ledger_path === undefined) return
|
|
122
124
|
|
|
123
|
-
await
|
|
125
|
+
await lane_ledger_write.record_gate(ledger_path, {
|
|
126
|
+
elapsed_ms,
|
|
127
|
+
is_passed: true,
|
|
128
|
+
is_reused: true,
|
|
129
|
+
issue: lane_paths.issue_here(),
|
|
130
|
+
})
|
|
124
131
|
}
|
|
125
132
|
|
|
126
133
|
// The caller measures the elapsed time before this, so the end's reading is never part of it.
|
|
@@ -133,14 +140,15 @@ async function record(
|
|
|
133
140
|
|
|
134
141
|
if (begun.ledger_path === undefined) return
|
|
135
142
|
|
|
136
|
-
const unit_ms = results.find((result) => result.label ===
|
|
143
|
+
const unit_ms = results.find((result) => result.label === gate_labels.UNIT_LABEL)?.elapsed_ms
|
|
137
144
|
const external_cores = peak([...begun.readings, await read_external_cores()])
|
|
138
145
|
|
|
139
|
-
await
|
|
146
|
+
await lane_ledger_write.record_gate(begun.ledger_path, {
|
|
140
147
|
...outcome,
|
|
141
148
|
unit_ms,
|
|
142
149
|
external_cores,
|
|
143
150
|
checks: check_records(results),
|
|
151
|
+
issue: lane_paths.issue_here(),
|
|
144
152
|
})
|
|
145
153
|
}
|
|
146
154
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { availableParallelism } from 'node:os'
|
|
2
2
|
import { josh_verdict } from '#scripts/josh/josh-verdict'
|
|
3
3
|
import { unit_worker_share } from '#scripts/test/unit-worker-share'
|
|
4
|
-
import {
|
|
4
|
+
import { core_weights } from './core-weights'
|
|
5
|
+
import { gate_labels } from './gate-labels'
|
|
5
6
|
|
|
6
7
|
// How many of the gate's checks run at once, and how wide the one elastic check may fan out —
|
|
7
8
|
// both derived from the machine rather than fixed at four.
|
|
@@ -36,7 +37,7 @@ interface GateCheck {
|
|
|
36
37
|
// The unit suite reserves nothing: it sizes its own pool from the machine, so it is capped
|
|
37
38
|
// instead of reserved, and counting it here would reserve cores against itself.
|
|
38
39
|
reserved_cores: number
|
|
39
|
-
// The memory this check holds while it runs, `
|
|
40
|
+
// The memory this check holds while it runs, `core_weights.MEMORY_MB`'s measured peak; none declared is
|
|
40
41
|
// none waited for. The unit suite's is per worker, so it is derived instead.
|
|
41
42
|
memory_mb?: number
|
|
42
43
|
// A check whose `josh` command is kit-only, so a consumer's gate leaves it out rather than running
|
|
@@ -46,21 +47,20 @@ interface GateCheck {
|
|
|
46
47
|
is_kit_only?: boolean
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const WARNING_CHECKER_LABELS: ReadonlyArray<string> = [LINT_LABEL, TYPE_CHECK_LABEL]
|
|
50
|
+
const {
|
|
51
|
+
BEHAVIOR_LABEL,
|
|
52
|
+
EXPORTS_LABEL,
|
|
53
|
+
KEEP_WHOLE_SUITE_FLAG,
|
|
54
|
+
LINT_LABEL,
|
|
55
|
+
LOCKFILE_LABEL,
|
|
56
|
+
METRICS_LABEL,
|
|
57
|
+
SPELL_CHECK_LABEL,
|
|
58
|
+
SPELL_CHECK_TARGET,
|
|
59
|
+
TYPE_CHECK_LABEL,
|
|
60
|
+
TYPE_CHECK_TARGET,
|
|
61
|
+
UNIT_LABEL,
|
|
62
|
+
UNIT_TARGET,
|
|
63
|
+
} = gate_labels
|
|
64
64
|
|
|
65
65
|
// The checks that do not fan out across every core, in the order their output is printed. They are
|
|
66
66
|
// named apart from the unit suite because CI runs them on their own runner:
|
|
@@ -74,14 +74,14 @@ const WARNING_CHECKER_LABELS: ReadonlyArray<string> = [LINT_LABEL, TYPE_CHECK_LA
|
|
|
74
74
|
// `--no-unit` set stays "the whole gate minus the unit suite", and a CI runner — which has no recorded
|
|
75
75
|
// transcripts — runs it as a trivial green rather than skipping it.
|
|
76
76
|
//
|
|
77
|
-
// **The three reserving weights are `
|
|
77
|
+
// **The three reserving weights are `core_weights.CORE_WEIGHTS`**, the same
|
|
78
78
|
// numbers the `josh lint`, `josh check` and `josh cspell:dot` commands claim when run directly.
|
|
79
79
|
//
|
|
80
80
|
// **The two zero weights are measured, and they stay zero.** These are warm runs on the 11-core
|
|
81
81
|
// machine. `behavior` took 0.6s of wall for 0.7s of CPU, which
|
|
82
82
|
// is node starting up. `exports:unused` took 5.5s of wall for 9.0s of CPU, about 1.6 cores. Rounded
|
|
83
83
|
// up, that would be two cores, but a reservation lasts the whole gate's plan, not the check's five
|
|
84
|
-
// seconds. It would raise `RESERVED_CORES` from
|
|
84
|
+
// seconds. It would raise `RESERVED_CORES` from 5 to 7 and cut the solo unit cap from 6 workers to 4
|
|
85
85
|
// for the full length of the unit suite, to cover a burst that ends before lint does. Nothing has measured
|
|
86
86
|
// that trade, so the measured shape stays.
|
|
87
87
|
const STATIC_CHECKS: ReadonlyArray<GateCheck> = [
|
|
@@ -91,20 +91,20 @@ const STATIC_CHECKS: ReadonlyArray<GateCheck> = [
|
|
|
91
91
|
label: LINT_LABEL,
|
|
92
92
|
target: 'lint',
|
|
93
93
|
args: ['--changed'],
|
|
94
|
-
reserved_cores:
|
|
95
|
-
memory_mb:
|
|
94
|
+
reserved_cores: core_weights.CORE_WEIGHTS.lint,
|
|
95
|
+
memory_mb: core_weights.MEMORY_MB.lint,
|
|
96
96
|
},
|
|
97
97
|
{
|
|
98
98
|
label: TYPE_CHECK_LABEL,
|
|
99
|
-
target:
|
|
100
|
-
reserved_cores:
|
|
101
|
-
memory_mb:
|
|
99
|
+
target: TYPE_CHECK_TARGET,
|
|
100
|
+
reserved_cores: core_weights.CORE_WEIGHTS.type_check,
|
|
101
|
+
memory_mb: core_weights.MEMORY_MB.type_check,
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
|
-
label:
|
|
105
|
-
target:
|
|
106
|
-
reserved_cores:
|
|
107
|
-
memory_mb:
|
|
104
|
+
label: SPELL_CHECK_LABEL,
|
|
105
|
+
target: SPELL_CHECK_TARGET,
|
|
106
|
+
reserved_cores: core_weights.CORE_WEIGHTS.spell_check,
|
|
107
|
+
memory_mb: core_weights.MEMORY_MB.spell_check,
|
|
108
108
|
},
|
|
109
109
|
{ label: BEHAVIOR_LABEL, target: BEHAVIOR_LABEL, reserved_cores: 0 },
|
|
110
110
|
// **The unused-member check reserves no core**: it builds one TypeScript
|
|
@@ -121,13 +121,13 @@ const STATIC_CHECKS: ReadonlyArray<GateCheck> = [
|
|
|
121
121
|
target: METRICS_LABEL,
|
|
122
122
|
args: ['--no-startup'],
|
|
123
123
|
reserved_cores: 0,
|
|
124
|
-
memory_mb:
|
|
124
|
+
memory_mb: core_weights.MEMORY_MB.metrics,
|
|
125
125
|
is_kit_only: true,
|
|
126
126
|
},
|
|
127
127
|
// The lockfile policy check is network-bound and usually instant: it verifies only when the
|
|
128
128
|
// lockfile or `pnpm-workspace.yaml` moved from the merge-base (joshuafolkken/kit#4090), so it
|
|
129
129
|
// reserves no core. Kit's own until a consumer's private-registry entries are known to verify.
|
|
130
|
-
{ label:
|
|
130
|
+
{ label: LOCKFILE_LABEL, target: 'lockfile:policy', reserved_cores: 0, is_kit_only: true },
|
|
131
131
|
]
|
|
132
132
|
|
|
133
133
|
// The checks, in the order their output is printed — the static set, then the unit suite last (the
|
|
@@ -140,7 +140,7 @@ const STATIC_CHECKS: ReadonlyArray<GateCheck> = [
|
|
|
140
140
|
// sharded suite regardless.
|
|
141
141
|
const GATE_CHECKS: ReadonlyArray<GateCheck> = [
|
|
142
142
|
...STATIC_CHECKS,
|
|
143
|
-
{ label: UNIT_LABEL, target: UNIT_TARGET, reserved_cores: 0 },
|
|
143
|
+
{ label: UNIT_LABEL, target: UNIT_TARGET, args: [KEEP_WHOLE_SUITE_FLAG], reserved_cores: 0 },
|
|
144
144
|
]
|
|
145
145
|
|
|
146
146
|
// **Selecting is not skipping, and the difference is where the unit suite runs rather than whether
|
|
@@ -166,7 +166,7 @@ function has_unit_check(checks: ReadonlyArray<GateCheck>): boolean {
|
|
|
166
166
|
return checks.some((check) => check.label === UNIT_LABEL)
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
// What the non-elastic checks hold between them: 2 + 2 +
|
|
169
|
+
// What the non-elastic checks hold between them: 2 + 2 + 1. Reduced over `STATIC_CHECKS`
|
|
170
170
|
// rather than over every check, because that is the set the sentence above names: `resolve_unit_worker_cap`
|
|
171
171
|
// spends this as the cores the unit suite must leave to its siblings, so summing the unit check into
|
|
172
172
|
// it would have the suite subtract its own reservation from its own budget the day that reservation
|
|
@@ -223,6 +223,15 @@ interface GatePlan {
|
|
|
223
223
|
// the exact opposite of what this function is for. `bounded-pool.ts` closes the same hole for the
|
|
224
224
|
// same reason. A count below one is nonsense too and is read as one run, which is the direction
|
|
225
225
|
// that leaves behavior where it was rather than throttling a gate on a bad input.
|
|
226
|
+
// The order the gate both counts and starts its checks in. `toSorted` is stable, so checks of one
|
|
227
|
+
// weight keep their declaration order.
|
|
228
|
+
function lightest_first<Item>(
|
|
229
|
+
items: ReadonlyArray<Item>,
|
|
230
|
+
reserved_cores_of: (item: Item) => number,
|
|
231
|
+
): Array<Item> {
|
|
232
|
+
return items.toSorted((left, right) => reserved_cores_of(left) - reserved_cores_of(right))
|
|
233
|
+
}
|
|
234
|
+
|
|
226
235
|
function shared_cores(available_cores: number, concurrent_runs: number): number {
|
|
227
236
|
const runs = Number.isFinite(concurrent_runs)
|
|
228
237
|
? Math.max(unit_worker_share.SOLO_RUNS, concurrent_runs)
|
|
@@ -231,9 +240,9 @@ function shared_cores(available_cores: number, concurrent_runs: number): number
|
|
|
231
240
|
return Math.max(MIN_SHARED_CORES, Math.floor(available_cores / runs))
|
|
232
241
|
}
|
|
233
242
|
|
|
234
|
-
// Admit checks
|
|
243
|
+
// Admit checks, lightest first, while the running set's reserved cores still fit **this run's
|
|
235
244
|
// share** of the machine. On a machine running one gate that share is the machine, so this bites
|
|
236
|
-
// only below
|
|
245
|
+
// only below five cores — the three reserving checks want five between them — and there it is the
|
|
237
246
|
// difference between two checks sharing a core and four fighting over it.
|
|
238
247
|
//
|
|
239
248
|
// **Under concurrency it is the only lever there is, and that is a measurement rather than a
|
|
@@ -250,16 +259,23 @@ function shared_cores(available_cores: number, concurrent_runs: number): number
|
|
|
250
259
|
// the gate still reports every failure in one pass — `bounded_pool` queues what it does not start,
|
|
251
260
|
// and no check ever rejects (see `run_gate_steps`). What changes is how many are in flight at
|
|
252
261
|
// once, which is scheduling and never coverage.
|
|
262
|
+
//
|
|
263
|
+
// **The checks are counted lightest first, and `run_gate_steps` starts them in the same order**
|
|
264
|
+
// (joshuafolkken/kit#4609). Counted in declaration order, the first check over the share ended the
|
|
265
|
+
// count, so on CI's four cores lint and the type check filled it and every zero-weight check after
|
|
266
|
+
// the spell check queued behind a check that was only waiting for cores. Lightest first, the `break`
|
|
267
|
+
// is exact: once one check does not fit, no heavier one after it can.
|
|
253
268
|
function resolve_concurrency(
|
|
254
269
|
available_cores: number,
|
|
255
270
|
concurrent_runs: number = unit_worker_share.SOLO_RUNS,
|
|
256
271
|
checks: ReadonlyArray<GateCheck> = GATE_CHECKS,
|
|
257
272
|
): number {
|
|
258
273
|
const share = shared_cores(available_cores, concurrent_runs)
|
|
274
|
+
const ordered = lightest_first(checks, (check) => check.reserved_cores)
|
|
259
275
|
let admitted = 0
|
|
260
276
|
let reserved = 0
|
|
261
277
|
|
|
262
|
-
for (const check of
|
|
278
|
+
for (const check of ordered) {
|
|
263
279
|
reserved += check.reserved_cores
|
|
264
280
|
|
|
265
281
|
if (reserved > share) break
|
|
@@ -283,8 +299,8 @@ function resolve_concurrency(
|
|
|
283
299
|
//
|
|
284
300
|
// **The shared branch drops `RESERVED_CORES`, knowingly, and it is not a strict improvement.** Each
|
|
285
301
|
// concurrent gate still runs lint, the type check and the spell check beside its unit step, and the
|
|
286
|
-
// share below does not subtract them: on 12 cores a solo gate takes
|
|
287
|
-
//
|
|
302
|
+
// share below does not subtract them: on 12 cores a solo gate takes 7 unit workers plus 3 siblings —
|
|
303
|
+
// 10 processes for 12 cores — while two concurrent gates take 6 each plus 3 siblings each, which is 18.
|
|
288
304
|
// The obvious correction, `⌊(cores − RESERVED_CORES × runs) ÷ runs⌋`, is **not** applied because
|
|
289
305
|
// nothing has measured it: it hands two gates on an 11-core machine one worker apiece, against the
|
|
290
306
|
// 11.7s-at-8-workers / 16.7s-at-4 curve the table above was built from, and trading a measured
|
|
@@ -323,8 +339,8 @@ function solo_unit_weight(available_cores: number): number {
|
|
|
323
339
|
// once**: no second set of weights is introduced, so a change to the measured reservation moves the
|
|
324
340
|
// admission with it.
|
|
325
341
|
//
|
|
326
|
-
// **A solo gate's four weights sum to exactly the core count** — `reserved(2 + 2 +
|
|
327
|
-
// unit_cap(cores -
|
|
342
|
+
// **A solo gate's four weights sum to exactly the core count** — `reserved(2 + 2 + 1) +
|
|
343
|
+
// unit_cap(cores - 5)` is `cores` — which is what lets every check of a lone gate on a machine with room
|
|
328
344
|
// (its busy cores within what the ledger holds, `core-budget.ts`) be admitted at once,
|
|
329
345
|
// its concurrency unchanged. A machine below the measured one leaves the unit suite uncapped and reads
|
|
330
346
|
// its weight from the same identity, `cores - RESERVED_CORES` clamped at zero, so the sum is the core
|
|
@@ -336,7 +352,7 @@ function check_weight(check: GateCheck, plan: GatePlan, available_cores: number)
|
|
|
336
352
|
}
|
|
337
353
|
|
|
338
354
|
function unit_memory(workers: number): number {
|
|
339
|
-
return workers *
|
|
355
|
+
return workers * core_weights.MEMORY_MB.unit_worker
|
|
340
356
|
}
|
|
341
357
|
|
|
342
358
|
// The memory a check holds: its declared figure, or for the unit suite one
|
|
@@ -347,34 +363,66 @@ function check_memory(check: GateCheck, plan: GatePlan, available_cores: number)
|
|
|
347
363
|
return unit_memory(check_weight(check, plan, available_cores))
|
|
348
364
|
}
|
|
349
365
|
|
|
366
|
+
// The workers a lone direct run opens below the gate's solo weight: vitest's own default, one per core
|
|
367
|
+
// but one, bounded by the gate's solo workers on the measured machine. **A direct run has no siblings**,
|
|
368
|
+
// so subtracting `RESERVED_CORES` for them sized a four-core CI runner to zero and its suite to one
|
|
369
|
+
// worker (joshuafolkken/kit#4607); vitest's default is what that runner ran before the claim bounded it.
|
|
370
|
+
// The bound keeps a mid-sized machine from claiming more than the measured one does.
|
|
371
|
+
function direct_solo_workers(available_cores: number): number {
|
|
372
|
+
const vitest_default = available_cores - unit_worker_share.MAIN_PROCESS_CORES
|
|
373
|
+
const floor = Math.min(vitest_default, solo_unit_weight(MEASURED_CORES))
|
|
374
|
+
|
|
375
|
+
return Math.max(solo_unit_weight(available_cores), floor)
|
|
376
|
+
}
|
|
377
|
+
|
|
350
378
|
// The cores a unit run started directly reserves: the share it will pass to
|
|
351
|
-
// vitest while other runs are live, and otherwise
|
|
352
|
-
// machine
|
|
379
|
+
// vitest while other runs are live, and otherwise `direct_solo_workers`. **Not the whole
|
|
380
|
+
// machine where there is room to leave**: FIFO admission lets a claim of every core in only
|
|
353
381
|
// once the ledger is empty, so a one-file `josh test:related` would wait out every other lane's gate
|
|
354
|
-
// and hold every later claim behind it
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
// and the claim holds the process that drives them on top (`unit_worker_share.cap_to_claim` takes it
|
|
359
|
-
// back off).
|
|
382
|
+
// and hold every later claim behind it — the solo bound stops below the core count from seven cores up.
|
|
383
|
+
// One weight for the suite however it is started. **Plus vitest's own process** (joshuafolkken/kit#4362):
|
|
384
|
+
// the workers are the share, and the claim holds the process that drives them on top
|
|
385
|
+
// (`unit_worker_share.cap_to_claim` takes it back off).
|
|
360
386
|
function direct_unit_weight(
|
|
361
387
|
available_cores: number = availableParallelism(),
|
|
362
388
|
live_runs: number = unit_worker_share.live_run_count(),
|
|
363
389
|
): number {
|
|
364
390
|
const workers =
|
|
365
|
-
unit_worker_share.current_share(available_cores, live_runs) ??
|
|
391
|
+
unit_worker_share.current_share(available_cores, live_runs) ??
|
|
392
|
+
direct_solo_workers(available_cores)
|
|
366
393
|
|
|
367
394
|
return Math.max(unit_worker_share.MIN_WORKERS, workers) + unit_worker_share.MAIN_PROCESS_CORES
|
|
368
395
|
}
|
|
369
396
|
|
|
397
|
+
// The related files one vitest worker clears in about 30 seconds: `tools/test/unit-durations.json`'s
|
|
398
|
+
// median file takes 105 ms (2077 files), and 30 000 ÷ 105 ≈ 285 (joshuafolkken/kit#5135).
|
|
399
|
+
const FILES_PER_WORKER = 285
|
|
400
|
+
|
|
401
|
+
// The cores a narrowed `josh test:related` reserves once its scope is known: one worker for each
|
|
402
|
+
// `FILES_PER_WORKER` related files, at least `MIN_WORKERS` and at most the share `direct_unit_weight`
|
|
403
|
+
// gives the whole suite, plus vitest's own process. **A small scope no longer claims the whole width**,
|
|
404
|
+
// so the other lanes' unit claims stop waiting behind a twenty-second run (joshuafolkken/kit#5135).
|
|
405
|
+
function scoped_unit_weight(
|
|
406
|
+
files: number,
|
|
407
|
+
available_cores: number = availableParallelism(),
|
|
408
|
+
live_runs: number = unit_worker_share.live_run_count(),
|
|
409
|
+
): number {
|
|
410
|
+
const { MAIN_PROCESS_CORES, MIN_WORKERS } = unit_worker_share
|
|
411
|
+
const share = direct_unit_weight(available_cores, live_runs) - MAIN_PROCESS_CORES
|
|
412
|
+
const wanted = Math.max(MIN_WORKERS, Math.ceil(files / FILES_PER_WORKER))
|
|
413
|
+
|
|
414
|
+
return Math.min(wanted, share) + MAIN_PROCESS_CORES
|
|
415
|
+
}
|
|
416
|
+
|
|
370
417
|
// What a unit run started directly holds: one worker's peak for each core `direct_unit_weight` gives
|
|
371
418
|
// it, vitest's own process counted as one more.
|
|
372
419
|
function direct_unit_memory(): number {
|
|
373
420
|
return unit_memory(direct_unit_weight())
|
|
374
421
|
}
|
|
375
422
|
|
|
376
|
-
// The claim every unit run started directly declares — `josh test:unit
|
|
377
|
-
//
|
|
423
|
+
// The claim every unit run started directly declares — `josh test:unit` and the pre-push hook —
|
|
424
|
+
// declared once so the two cannot drift apart. `josh test:related` claims in its body instead, once
|
|
425
|
+
// its scope is known (`scoped_unit_weight`).
|
|
378
426
|
const DIRECT_UNIT_CLAIM = {
|
|
379
427
|
core_weight: direct_unit_weight,
|
|
380
428
|
memory_mb: direct_unit_memory,
|
|
@@ -468,28 +516,25 @@ function format_gate_plan(
|
|
|
468
516
|
|
|
469
517
|
const gate_plan = {
|
|
470
518
|
DIRECT_UNIT_CLAIM,
|
|
471
|
-
|
|
519
|
+
FILES_PER_WORKER,
|
|
472
520
|
GATE_CHECKS,
|
|
473
|
-
LINT_LABEL,
|
|
474
521
|
MEASURED_CORES,
|
|
475
|
-
METRICS_LABEL,
|
|
476
522
|
RESERVED_CORES,
|
|
477
523
|
STATIC_CHECKS,
|
|
478
|
-
TYPE_CHECK_LABEL,
|
|
479
|
-
UNIT_LABEL,
|
|
480
|
-
UNIT_TARGET,
|
|
481
|
-
WARNING_CHECKER_LABELS,
|
|
482
524
|
check_memory,
|
|
483
525
|
check_weight,
|
|
484
526
|
direct_unit_weight,
|
|
485
527
|
format_gate_plan,
|
|
486
528
|
format_machine,
|
|
487
529
|
has_unit_check,
|
|
530
|
+
lightest_first,
|
|
488
531
|
plan_of,
|
|
489
532
|
resolve_concurrency,
|
|
490
533
|
resolve_gate_plan,
|
|
491
534
|
resolve_unit_worker_cap,
|
|
535
|
+
scoped_unit_weight,
|
|
492
536
|
select_gate_checks,
|
|
537
|
+
unit_memory,
|
|
493
538
|
}
|
|
494
539
|
|
|
495
540
|
export type { GateCheck, GatePlan }
|
|
@@ -5,8 +5,9 @@ import { status_icons } from '#scripts/lib/status-icons'
|
|
|
5
5
|
import { MS_PER_SECOND } from '#scripts/lib/timeouts'
|
|
6
6
|
import { NOT_USED_MARKER, NOTHING_TO_CHECK_MARKER } from '#scripts/test/skip-marker'
|
|
7
7
|
import { test_unit_guard } from '#scripts/test/test-unit-guard'
|
|
8
|
+
import { gate_labels } from './gate-labels'
|
|
8
9
|
import { gate_log } from './gate-log'
|
|
9
|
-
import {
|
|
10
|
+
import { verification_tail } from './verification-tail'
|
|
10
11
|
|
|
11
12
|
// The gate's console reporting, split out of `verification-gate.ts` so that file stays under its line
|
|
12
13
|
// ceiling while it grows the scoped pre-check and the failure summary. Nothing
|
|
@@ -98,7 +99,7 @@ function checker_lines(result: GateStepResult): ReadonlyArray<string> {
|
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
function has_checker_warning(result: GateStepResult): boolean {
|
|
101
|
-
if (!
|
|
102
|
+
if (!gate_labels.WARNING_CHECKER_LABELS.includes(result.label)) return false
|
|
102
103
|
|
|
103
104
|
return checker_lines(result).some((line) =>
|
|
104
105
|
WARNING_MARKERS.some((marker) => line.includes(marker)),
|
|
@@ -201,15 +202,16 @@ function print_gate_step(result: GateStepResult, is_verbose: boolean): void {
|
|
|
201
202
|
function format_failure_actions(failed: ReadonlyArray<GateStepResult>): string {
|
|
202
203
|
if (failed.length === 0) return ''
|
|
203
204
|
|
|
204
|
-
const lines = failed.map(
|
|
205
|
-
(result
|
|
205
|
+
const lines = failed.map((result) =>
|
|
206
|
+
verification_tail.format_rerun(result.label, `pnpm ${result.command}`),
|
|
206
207
|
)
|
|
207
208
|
|
|
208
209
|
return `${GATE_COMMAND} — next:\n${lines.join('\n')}\n`
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
// **A check that started past the core budget is said in the summary, not only in the log**.
|
|
212
|
-
// The wait cap admits a check that waited two minutes whatever the budget says
|
|
213
|
+
// The wait cap admits a check that waited two minutes whatever the budget says — sooner where outside
|
|
214
|
+
// load holds it and does not ease —
|
|
213
215
|
// so a gate that ran over-subscribed would otherwise look exactly like one that fitted.
|
|
214
216
|
function format_budget_notes(results: ReadonlyArray<GateStepResult>): string {
|
|
215
217
|
const lines = results.flatMap((result) =>
|
|
@@ -255,10 +257,10 @@ function print_gate_summary(
|
|
|
255
257
|
failed.length === 0
|
|
256
258
|
? format_green_verdict(results, total)
|
|
257
259
|
: josh_verdict.format_gate_failed(failed.map((result) => result.label).join(', '), total)
|
|
258
|
-
const
|
|
260
|
+
const failures = `${format_budget_notes(results)}${format_failure_actions(failed)}`
|
|
259
261
|
|
|
260
262
|
process.stdout.write(
|
|
261
|
-
`\n${
|
|
263
|
+
`\n${verification_tail.format_tail({ failures, log: { path: log_path }, verdict })}`,
|
|
262
264
|
)
|
|
263
265
|
}
|
|
264
266
|
|
|
@@ -5,6 +5,7 @@ import { unit_worker_share } from '#scripts/test/unit-worker-share'
|
|
|
5
5
|
import { check_cpu, type CheckCpu } from './check-cpu'
|
|
6
6
|
import { core_budget, type Admission } from './core-budget'
|
|
7
7
|
import { free_cores } from './free-cores'
|
|
8
|
+
import { gate_labels } from './gate-labels'
|
|
8
9
|
import { gate_plan, type GatePlan } from './gate-plan'
|
|
9
10
|
import type { CheckClaim, GateStep, GateStepResult } from './gate-report'
|
|
10
11
|
import { build_gate_step, with_granted_workers } from './gate-steps'
|
|
@@ -61,6 +62,8 @@ function default_budget(): BudgetContext {
|
|
|
61
62
|
interface ReservedStep {
|
|
62
63
|
step: GateStep
|
|
63
64
|
weight: number
|
|
65
|
+
// The check's own `reserved_cores`, the key `gate_plan.lightest_first` orders the pool's queue by.
|
|
66
|
+
reserved_cores: number
|
|
64
67
|
memory_mb: number
|
|
65
68
|
// The plan's `--maxWorkers` for the unit suite, the width the free memory bounds once it is admitted.
|
|
66
69
|
worker_cap: number | undefined
|
|
@@ -80,6 +83,7 @@ async function build_reserved_steps(
|
|
|
80
83
|
plan.checks.map(async (check) => ({
|
|
81
84
|
step: await build_gate_step(check, process.cwd(), plan),
|
|
82
85
|
weight: gate_plan.check_weight(check, plan, available_cores),
|
|
86
|
+
reserved_cores: check.reserved_cores,
|
|
83
87
|
memory_mb: gate_plan.check_memory(check, plan, available_cores),
|
|
84
88
|
worker_cap: plan.unit_worker_cap,
|
|
85
89
|
reused_at: reused.get(check.label),
|
|
@@ -119,7 +123,7 @@ async function admitted_step(
|
|
|
119
123
|
admission: Admission,
|
|
120
124
|
available_cores: number,
|
|
121
125
|
): Promise<GateStep> {
|
|
122
|
-
if (reserved.step.label !==
|
|
126
|
+
if (reserved.step.label !== gate_labels.UNIT_LABEL) return reserved.step
|
|
123
127
|
|
|
124
128
|
const { memory_workers } = await free_cores.read({ available_cores })
|
|
125
129
|
const asked = admission.granted ?? reserved.worker_cap
|
|
@@ -155,11 +159,30 @@ async function run_reserved_step(
|
|
|
155
159
|
budget: budget.available_cores,
|
|
156
160
|
memory_mb: reserved.memory_mb,
|
|
157
161
|
command: `gate ${reserved.step.label}`,
|
|
158
|
-
is_unit: reserved.step.label ===
|
|
162
|
+
is_unit: reserved.step.label === gate_labels.UNIT_LABEL,
|
|
159
163
|
},
|
|
160
164
|
)
|
|
161
165
|
}
|
|
162
166
|
|
|
167
|
+
// The pool's queue in the order `resolve_concurrency` counted it (joshuafolkken/kit#4609), so the
|
|
168
|
+
// checks its width admitted are the ones that start, and one over the share waits for a slot rather
|
|
169
|
+
// than taking one ahead of a zero-weight check. Each result goes back to its check's declaration
|
|
170
|
+
// position, so the printed sections keep their order.
|
|
171
|
+
async function run_lightest_first(
|
|
172
|
+
reserved: ReadonlyArray<ReservedStep>,
|
|
173
|
+
concurrency: number,
|
|
174
|
+
run: (entry: ReservedStep) => Promise<GateStepResult>,
|
|
175
|
+
): Promise<ReadonlyArray<GateStepResult>> {
|
|
176
|
+
const indexed = reserved.map((entry, index) => ({ entry, index }))
|
|
177
|
+
const queue = gate_plan.lightest_first(indexed, ({ entry }) => entry.reserved_cores)
|
|
178
|
+
const finished = await bounded_pool.bounded_map(queue, concurrency, async ({ entry, index }) => ({
|
|
179
|
+
index,
|
|
180
|
+
result: await run(entry),
|
|
181
|
+
}))
|
|
182
|
+
|
|
183
|
+
return finished.toSorted((left, right) => left.index - right.index).map(({ result }) => result)
|
|
184
|
+
}
|
|
185
|
+
|
|
163
186
|
// `bounded_pool` rather than a bare `Promise.all`, so the plan's `concurrency` is what decides how
|
|
164
187
|
// many run at once. **The all-failures-in-one-pass property survives the
|
|
165
188
|
// change** because no check ever rejects: `buffered_process` reports a non-zero exit as a value, so
|
|
@@ -181,7 +204,7 @@ async function run_gate_steps(
|
|
|
181
204
|
// sets the mark too, since its checks are covered by the outer gate's reservation.
|
|
182
205
|
return await core_budget.with_held_mark(
|
|
183
206
|
async () =>
|
|
184
|
-
await
|
|
207
|
+
await run_lightest_first(
|
|
185
208
|
reserved,
|
|
186
209
|
plan.concurrency,
|
|
187
210
|
async (entry) => await run_reserved_step(entry, budget, cpu),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { file_map_stamp, type FileMapStamp } from '#scripts/josh/file-map-stamp'
|
|
2
2
|
import { review_brief } from '#scripts/review/review-brief'
|
|
3
3
|
import { review_stamps } from '#scripts/review/review-stamps'
|
|
4
4
|
|
|
@@ -64,11 +64,15 @@ const FORCE_FLAG = '--force'
|
|
|
64
64
|
// rewritten by the hook's own install each cost minutes before anyone could tell them apart.
|
|
65
65
|
type GateReuse = { stamp: FileMapStamp } | { miss: string }
|
|
66
66
|
|
|
67
|
+
const NO_BASE = 'the merge base could not be read'
|
|
68
|
+
const NO_CHANGE = 'no file differs from the merge base'
|
|
69
|
+
|
|
67
70
|
// The fingerprint of every declared check's tools and environment (`verification-inputs.ts`).
|
|
68
71
|
const INPUTS_MOVED = 'a checked tool or environment variable changed since the green gate'
|
|
72
|
+
const BASE_MOVED = 'the merge base moved since the green gate'
|
|
69
73
|
|
|
70
74
|
function base_moved(recorded: string | undefined, base: string): string {
|
|
71
|
-
return
|
|
75
|
+
return `${BASE_MOVED} (${recorded ?? 'none'} → ${base})`
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
function stamp_miss(stamp: FileMapStamp, base: string): string | undefined {
|
|
@@ -77,23 +81,57 @@ function stamp_miss(stamp: FileMapStamp, base: string): string | undefined {
|
|
|
77
81
|
return review_stamps.gate_stamp.describes_inputs(stamp) ? undefined : INPUTS_MOVED
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
const NO_MATCHING_RECORD = 'no green gate record matches the changed files'
|
|
85
|
+
|
|
86
|
+
// joshuafolkken/kit#5214: a record that exists but covers other files is told apart from no record
|
|
87
|
+
// at all, with the sizes of the two maps, so a log shows how far the tree had moved past it.
|
|
88
|
+
function record_miss(recorded: FileMapStamp | undefined, tree: Record<string, string>): string {
|
|
89
|
+
if (recorded === undefined) return NO_MATCHING_RECORD
|
|
90
|
+
|
|
91
|
+
const changed = String(Object.keys(tree).length)
|
|
92
|
+
const covered = String(Object.keys(recorded.files).length)
|
|
93
|
+
const differing = String(file_map_stamp.changed_since(recorded, tree).length)
|
|
94
|
+
|
|
95
|
+
return `${NO_MATCHING_RECORD} (${changed} changed, record covers ${covered}, ${differing} differ)`
|
|
96
|
+
}
|
|
97
|
+
|
|
80
98
|
function gate_reuse(
|
|
81
99
|
tree: Record<string, string>,
|
|
82
100
|
base: string | undefined,
|
|
83
101
|
source?: string,
|
|
84
102
|
): GateReuse {
|
|
85
|
-
if (base === undefined) return { miss:
|
|
86
|
-
if (Object.keys(tree).length === 0) return { miss:
|
|
103
|
+
if (base === undefined) return { miss: NO_BASE }
|
|
104
|
+
if (Object.keys(tree).length === 0) return { miss: NO_CHANGE }
|
|
87
105
|
|
|
88
|
-
const
|
|
106
|
+
const recorded = review_stamps.gate_stamp.read(source)
|
|
107
|
+
const stamp = review_brief.matching_stamp(recorded, tree)
|
|
89
108
|
|
|
90
|
-
if (stamp === undefined) return { miss:
|
|
109
|
+
if (stamp === undefined) return { miss: record_miss(recorded, tree) }
|
|
91
110
|
|
|
92
111
|
const miss = stamp_miss(stamp, base)
|
|
93
112
|
|
|
94
113
|
return miss === undefined ? { stamp } : { miss }
|
|
95
114
|
}
|
|
96
115
|
|
|
116
|
+
// joshuafolkken/kit#5234: the kind of a miss, read off the sentence `gate_reuse` wrote, so a ledger
|
|
117
|
+
// counts the reasons without a second wording of them. A record that covers other files is checked
|
|
118
|
+
// before no record at all, since its sentence starts with the other's. A miss no prefix names is
|
|
119
|
+
// `other`; a hook's own refusals are told apart first, by `hook_gate_reuse.miss_kind`.
|
|
120
|
+
const MISS_KINDS: ReadonlyArray<readonly [string, string]> = [
|
|
121
|
+
[NO_BASE, 'no-base'],
|
|
122
|
+
[NO_CHANGE, 'no-change'],
|
|
123
|
+
[`${NO_MATCHING_RECORD} (`, 'record-differs'],
|
|
124
|
+
[NO_MATCHING_RECORD, 'no-record'],
|
|
125
|
+
[BASE_MOVED, 'base-moved'],
|
|
126
|
+
[INPUTS_MOVED, 'inputs-moved'],
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
const OTHER_MISS = 'other'
|
|
130
|
+
|
|
131
|
+
function miss_kind(miss: string): string {
|
|
132
|
+
return MISS_KINDS.find(([prefix]) => miss.startsWith(prefix))?.[1] ?? OTHER_MISS
|
|
133
|
+
}
|
|
134
|
+
|
|
97
135
|
function stamp_of(reuse: GateReuse): FileMapStamp | undefined {
|
|
98
136
|
return 'stamp' in reuse ? reuse.stamp : undefined
|
|
99
137
|
}
|
|
@@ -153,6 +191,7 @@ const gate_skip = {
|
|
|
153
191
|
format_reuse_notice,
|
|
154
192
|
format_skip,
|
|
155
193
|
gate_reuse,
|
|
194
|
+
miss_kind,
|
|
156
195
|
reusable_green_gate,
|
|
157
196
|
stamp_of,
|
|
158
197
|
}
|