@joshuafolkken/kit 1.1784.0 → 1.2114.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 +59 -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 +415 -389
- 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 +15 -8
- 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,265 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
4
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
5
|
+
import { lint_related_scope } from '#scripts/lint/lint-related-scope'
|
|
6
|
+
import { review_record_pinned } from '#scripts/review/review-record-pinned'
|
|
7
|
+
import { execa } from 'execa'
|
|
8
|
+
import run_parallel from 'run-parallel'
|
|
9
|
+
import { check_related_pinned } from './check-related-pinned'
|
|
10
|
+
import { check_related_reuse } from './check-related-reuse'
|
|
11
|
+
import { check_related_section, type CheckResult } from './check-related-section'
|
|
12
|
+
import { check_related_unplanned } from './check-related-unplanned'
|
|
13
|
+
import { gate_labels } from './gate-labels'
|
|
14
|
+
import { gate_log } from './gate-log'
|
|
15
|
+
import { metrics_totals } from './metrics-totals'
|
|
16
|
+
import { verification_tail } from './verification-tail'
|
|
17
|
+
|
|
18
|
+
const COMMAND = 'check:related'
|
|
19
|
+
// One file per checkout beside the gate's own log, overwritten by each run.
|
|
20
|
+
const LOG_PATH = stamp_file.stamp_path(
|
|
21
|
+
'josh-check-related-log-',
|
|
22
|
+
PROJECT_ROOT,
|
|
23
|
+
gate_log.GATE_LOG_SUFFIX,
|
|
24
|
+
)
|
|
25
|
+
const LINT_RELATED = 'lint:related'
|
|
26
|
+
// The verdict `lint:related` itself prints last, under its own label.
|
|
27
|
+
const LINT_PASSED = verification_tail.format_verdict(lint_related_scope.COMMAND_LABEL, [])
|
|
28
|
+
const CHECKS: ReadonlyArray<string> = [
|
|
29
|
+
LINT_RELATED,
|
|
30
|
+
'test:related',
|
|
31
|
+
gate_labels.TYPE_CHECK_TARGET,
|
|
32
|
+
'cspell:dot',
|
|
33
|
+
]
|
|
34
|
+
const REUSED = 'reused'
|
|
35
|
+
const METRICS_STOP =
|
|
36
|
+
'`josh ship`\'s pre-detach stops on the metrics notice above unless the branch approval already names the total; settle it first (`pnpm josh metrics --accept --reason "<why>"`); the accept needs no `check:related` re-run, as the notice changed no exit code'
|
|
37
|
+
|
|
38
|
+
type CheckExecutor = (command: string) => Promise<CheckResult>
|
|
39
|
+
type ProcessRunner = (
|
|
40
|
+
file: string,
|
|
41
|
+
args: Array<string>,
|
|
42
|
+
options: { all: true; reject: false },
|
|
43
|
+
) => Promise<{ all: string | null; exitCode?: number }>
|
|
44
|
+
|
|
45
|
+
async function run_execa(
|
|
46
|
+
file: string,
|
|
47
|
+
args: Array<string>,
|
|
48
|
+
options: { all: true; reject: false },
|
|
49
|
+
): Promise<{ all: string | null; exitCode?: number }> {
|
|
50
|
+
return await execa(file, args, options)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function failed_result(command: string, error: unknown): CheckResult {
|
|
54
|
+
return {
|
|
55
|
+
command,
|
|
56
|
+
exit_code: 1,
|
|
57
|
+
output: error instanceof Error ? error.message : String(error),
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function execute_check(
|
|
62
|
+
command: string,
|
|
63
|
+
run: ProcessRunner = run_execa,
|
|
64
|
+
): Promise<CheckResult> {
|
|
65
|
+
try {
|
|
66
|
+
const result = await run('pnpm', ['josh', command], { all: true, reject: false })
|
|
67
|
+
|
|
68
|
+
return { command, exit_code: result.exitCode ?? 1, output: result.all ?? '' }
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return failed_result(command, error)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function start_check(
|
|
75
|
+
command: string,
|
|
76
|
+
execute: CheckExecutor,
|
|
77
|
+
complete: run_parallel.TaskCallback<CheckResult>,
|
|
78
|
+
): Promise<void> {
|
|
79
|
+
try {
|
|
80
|
+
const result = await execute(command)
|
|
81
|
+
|
|
82
|
+
// eslint-disable-next-line unicorn/no-null -- run-parallel requires null for successful tasks.
|
|
83
|
+
complete(null, result)
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// eslint-disable-next-line unicorn/no-null -- run-parallel requires null for successful tasks.
|
|
86
|
+
complete(null, failed_result(command, error))
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function run_checks(
|
|
91
|
+
execute: CheckExecutor = execute_check,
|
|
92
|
+
commands: ReadonlyArray<string> = CHECKS,
|
|
93
|
+
): Promise<Array<CheckResult>> {
|
|
94
|
+
const tasks = commands.map((command): run_parallel.Task<CheckResult> => {
|
|
95
|
+
return (complete): void => {
|
|
96
|
+
void start_check(command, execute, complete)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
return await new Promise<Array<CheckResult>>((resolve): void => {
|
|
101
|
+
run_parallel(tasks, (_error, results): void => {
|
|
102
|
+
resolve(results)
|
|
103
|
+
})
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function failed_commands(results: ReadonlyArray<CheckResult>): ReadonlyArray<string> {
|
|
108
|
+
return results.filter((result) => result.exit_code !== 0).map((result) => result.command)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// The verdict is the last line, as every josh check prints it, so a reader of the tail sees every
|
|
112
|
+
// check that failed rather than only the section that finished last (joshuafolkken/kit#4940).
|
|
113
|
+
function checks_line(results: ReadonlyArray<CheckResult>): string {
|
|
114
|
+
return verification_tail.format_verdict(COMMAND, failed_commands(results))
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Each failed check and the command that reproduces it alone, above the log notice (joshuafolkken/kit#5162).
|
|
118
|
+
function failure_lines(results: ReadonlyArray<CheckResult>): string {
|
|
119
|
+
const failed = failed_commands(results)
|
|
120
|
+
if (failed.length === 0) return ''
|
|
121
|
+
|
|
122
|
+
const lines = failed.map((command) =>
|
|
123
|
+
verification_tail.format_rerun(command, `pnpm josh ${command}`),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return `${COMMAND} — next:\n${lines.join('\n')}\n`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Every check's whole output, kept where the console's size limit cannot reach, as `josh gate` keeps its own.
|
|
130
|
+
function write_log(results: ReadonlyArray<CheckResult>, target: string): string | undefined {
|
|
131
|
+
const entries = results.map((result) => ({
|
|
132
|
+
header: `${result.command}: ${check_related_section.result_status(result)}`,
|
|
133
|
+
output: result.output,
|
|
134
|
+
}))
|
|
135
|
+
|
|
136
|
+
return gate_log.write_gate_log(entries, target)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function reused_suffix(reused: ReadonlySet<string>): string {
|
|
140
|
+
return reused.size === 0 ? '' : ` (reused: ${[...reused].join(', ')})`
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// A notice is never a failure, so a passing verdict line alone hid it from a reader of the last lines,
|
|
144
|
+
// and the ship's pre-detach stopped on it (joshuafolkken/kit#4987).
|
|
145
|
+
function verdict_line(
|
|
146
|
+
results: ReadonlyArray<CheckResult>,
|
|
147
|
+
has_metrics_notice: boolean,
|
|
148
|
+
reused: ReadonlySet<string>,
|
|
149
|
+
): string {
|
|
150
|
+
const line = `${checks_line(results)}${reused_suffix(reused)}`
|
|
151
|
+
|
|
152
|
+
return has_metrics_notice ? `${line} — ${METRICS_STOP}` : line
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// `josh lint:related` ends its section with the metrics growth notice, which the sections after it
|
|
156
|
+
// bury; it is repeated above the verdict so the tail still carries what stops `josh ship`
|
|
157
|
+
// (joshuafolkken/kit#4939).
|
|
158
|
+
function metrics_notice(results: ReadonlyArray<CheckResult>): string | undefined {
|
|
159
|
+
const output = results.find((result) => result.command === LINT_RELATED)?.output ?? ''
|
|
160
|
+
const start = output.indexOf(metrics_totals.NOTICE_HEADING)
|
|
161
|
+
|
|
162
|
+
if (start === -1) return undefined
|
|
163
|
+
|
|
164
|
+
// The lint's own verdict closes its section; it is not part of the notice.
|
|
165
|
+
return output.slice(start).replace(LINT_PASSED, '').trimEnd()
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function report_reused(reused: ReadonlySet<string>): void {
|
|
169
|
+
for (const command of reused) {
|
|
170
|
+
process.stdout.write(`\n=== ${command}: ${REUSED} ===\n`)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface ReportOptions {
|
|
175
|
+
pinned_notice?: string | undefined
|
|
176
|
+
unplanned_notice?: string | undefined
|
|
177
|
+
reused?: ReadonlySet<string>
|
|
178
|
+
log_target?: string
|
|
179
|
+
is_full?: boolean
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function report_notices(notices: ReadonlyArray<string | undefined>): void {
|
|
183
|
+
for (const notice of notices) {
|
|
184
|
+
if (notice !== undefined) process.stdout.write(`\n${notice}\n`)
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function report_results(results: ReadonlyArray<CheckResult>, options: ReportOptions = {}): void {
|
|
189
|
+
const { is_full, log_target = LOG_PATH, pinned_notice, reused = new Set<string>() } = options
|
|
190
|
+
|
|
191
|
+
report_reused(reused)
|
|
192
|
+
|
|
193
|
+
for (const result of results) {
|
|
194
|
+
process.stdout.write(check_related_section.format_section(result, is_full))
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const metrics = metrics_notice(results)
|
|
198
|
+
|
|
199
|
+
report_notices([metrics, pinned_notice, options.unplanned_notice])
|
|
200
|
+
|
|
201
|
+
const log = { path: write_log(results, log_target) }
|
|
202
|
+
const verdict = verdict_line(results, metrics !== undefined, reused)
|
|
203
|
+
|
|
204
|
+
process.stdout.write(
|
|
205
|
+
`\n${verification_tail.format_tail({ failures: failure_lines(results), log, verdict })}`,
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function exit_code(results: ReadonlyArray<CheckResult>): number {
|
|
210
|
+
return results.every((result: CheckResult): boolean => result.exit_code === 0) ? 0 : 1
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// **The first check of a round-1 fix starts `josh test:pinned` again on the fixed tree**
|
|
214
|
+
// (joshuafolkken/kit#4948): left to `josh review:record`, the restart came minutes before the ship, and
|
|
215
|
+
// its pre-detach waited out a whole run. Started here, the check runs beside these four; a tree that did
|
|
216
|
+
// not move, or a run outside a lane child, starts nothing. A verdict that check already reached on this
|
|
217
|
+
// tree is printed above the verdict line, waited for when this run started it (`check-related-pinned.ts`).
|
|
218
|
+
// A check whose green record still holds is not run (`check-related-reuse.ts`).
|
|
219
|
+
async function run_all(
|
|
220
|
+
root?: string,
|
|
221
|
+
execute: CheckExecutor = execute_check,
|
|
222
|
+
is_full = false,
|
|
223
|
+
): Promise<number> {
|
|
224
|
+
const is_started = await review_record_pinned.restart_in_lane(root)
|
|
225
|
+
const tree = await check_related_reuse.read_tree()
|
|
226
|
+
const reused = await check_related_reuse.reusable(CHECKS, tree)
|
|
227
|
+
const results = await run_checks(
|
|
228
|
+
execute,
|
|
229
|
+
CHECKS.filter((command) => !reused.has(command)),
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
await check_related_reuse.record(results, tree)
|
|
233
|
+
report_results(results, {
|
|
234
|
+
is_full,
|
|
235
|
+
pinned_notice: await check_related_pinned.notice(root, is_started),
|
|
236
|
+
unplanned_notice: await check_related_unplanned.notice(),
|
|
237
|
+
reused,
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
return exit_code(results)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const check_related = {
|
|
244
|
+
CHECKS,
|
|
245
|
+
METRICS_STOP,
|
|
246
|
+
REUSED,
|
|
247
|
+
execute_check,
|
|
248
|
+
exit_code,
|
|
249
|
+
report_results,
|
|
250
|
+
run_all,
|
|
251
|
+
run_checks,
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
255
|
+
process.exitCode = await check_related.run_all(
|
|
256
|
+
undefined,
|
|
257
|
+
execute_check,
|
|
258
|
+
check_related_section.is_full_requested(process.argv),
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export type { CheckExecutor }
|
|
263
|
+
export { check_related }
|
|
264
|
+
|
|
265
|
+
export { type CheckResult } from './check-related-section'
|
|
@@ -186,7 +186,7 @@ function runs_multi_worker_eslint(
|
|
|
186
186
|
)
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
-
const command_memory = { estimated_memory_mb, runs_multi_worker_eslint, tool_calls_of }
|
|
189
|
+
const command_memory = { estimated_memory_mb, runs_multi_worker_eslint, tool_calls_of, workers_of }
|
|
190
190
|
|
|
191
191
|
export { command_memory }
|
|
192
192
|
export type { ToolCall }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MS_PER_SECOND } from '#scripts/lib/timeouts'
|
|
2
|
+
import { core_budget_timing } from './core-budget-timing'
|
|
2
3
|
import type { LedgerLoad, MachineBudget } from './machine-capacity'
|
|
3
4
|
|
|
4
5
|
// The ledger's admission arithmetic, kept apart from the markers `core-budget.ts` reads and writes so
|
|
@@ -16,6 +17,11 @@ const RAMP_UP_MS = 30_000
|
|
|
16
17
|
// enough for the related checks an edit triggers together, short enough that a heavy claim waits only
|
|
17
18
|
// for the claims already in flight.
|
|
18
19
|
const BYPASS_WINDOW_MS = 30_000
|
|
20
|
+
// How long after a heavier waiting claim a lighter one may still pass it: half the wait cap
|
|
21
|
+
// (`core-budget-timing.ts`), so the heavier claim still has the cap's second half to find its room before
|
|
22
|
+
// it starts narrowed or past the budget.
|
|
23
|
+
const WAIT_CAP_SHARE = 0.5
|
|
24
|
+
const HEAVIER_BYPASS_WINDOW_MS = core_budget_timing.WAIT_CAP_MS * WAIT_CAP_SHARE
|
|
19
25
|
// A narrowed unit claim still runs one worker: zero would run no test and report the suite green.
|
|
20
26
|
const MIN_GRANT = 1
|
|
21
27
|
// A unit claim narrowed to less than its asked weight over this waits rather than starts (`is_too_narrow`).
|
|
@@ -128,15 +134,26 @@ function first_waiter_limit(budget: MachineBudget): LedgerLoad {
|
|
|
128
134
|
return { cores: budget.cores + (budget.busy_excess ?? 0), memory_mb: budget.memory_mb }
|
|
129
135
|
}
|
|
130
136
|
|
|
137
|
+
// Whether `own` may pass one waiter ahead: any waiter claimed within the window before it, and a heavier
|
|
138
|
+
// one within the longer window (joshuafolkken/kit#4595) — a two-core `lint:related` queued for most of the
|
|
139
|
+
// cap behind a unit claim of five cores that the running claims had no room for.
|
|
140
|
+
function may_pass_waiter(own: LedgerReservation, waiter: LedgerReservation): boolean {
|
|
141
|
+
const since_ms = own.claimed_at - waiter.claimed_at
|
|
142
|
+
|
|
143
|
+
if (since_ms < BYPASS_WINDOW_MS) return true
|
|
144
|
+
|
|
145
|
+
return waiter.weight > own.weight && since_ms < HEAVIER_BYPASS_WINDOW_MS
|
|
146
|
+
}
|
|
147
|
+
|
|
131
148
|
// **A light claim passes a waiting one only within a window of that one's claim** (#4313). A claim that
|
|
132
149
|
// fits the room the running claims leave runs instead of queueing behind a heavier claim that does not
|
|
133
|
-
// fit it; a claim made more than the window after a waiter
|
|
134
|
-
// bounded set of claims and is never
|
|
150
|
+
// fit it; a claim made more than the window after a waiter — the heavier window after a heavier one
|
|
151
|
+
// (`may_pass_waiter`) — queues behind it, so a waiter is passed by a bounded set of claims and is never
|
|
152
|
+
// starved.
|
|
135
153
|
function may_pass({ own, ahead, running }: Placement, budget: MachineBudget): boolean {
|
|
136
|
-
const
|
|
137
|
-
const is_recent = ahead.every((entry) => entry.reservation.claimed_at > latest)
|
|
154
|
+
const is_passable = ahead.every((entry) => may_pass_waiter(own.reservation, entry.reservation))
|
|
138
155
|
|
|
139
|
-
return
|
|
156
|
+
return is_passable && fits([...running, own], budget)
|
|
140
157
|
}
|
|
141
158
|
|
|
142
159
|
function fits_in_order({ own, ahead, running }: Placement, budget: MachineBudget): boolean {
|
|
@@ -252,7 +269,7 @@ function total_weight(reservations: ReadonlyArray<LedgerEntry>): number {
|
|
|
252
269
|
return sum_load(reservations).cores
|
|
253
270
|
}
|
|
254
271
|
|
|
255
|
-
// **The weight a unit claim admitted past
|
|
272
|
+
// **The weight a unit claim admitted past its wait (the cap, or outside load that does not ease) may take: the cores the admitted claims leave
|
|
256
273
|
// free, never below one worker and never above what it asked for.** Admitting it at full width put the
|
|
257
274
|
// ledger past the machine (joshuafolkken/kit#4235); a unit suite is the one tool whose width follows a
|
|
258
275
|
// number, so it narrows instead. `undefined` for any other claim, and for one that fits as asked.
|
|
@@ -335,6 +352,7 @@ function describe_overflow(admission: Admission): string | undefined {
|
|
|
335
352
|
|
|
336
353
|
const core_admission = {
|
|
337
354
|
BYPASS_WINDOW_MS,
|
|
355
|
+
HEAVIER_BYPASS_WINDOW_MS,
|
|
338
356
|
RAMP_UP_MS,
|
|
339
357
|
admitted_keys,
|
|
340
358
|
admitted_load,
|
|
@@ -6,14 +6,21 @@ const POLL_INTERVAL_MS = 50
|
|
|
6
6
|
// for good. Two minutes is well past a unit suite's worst measured time under six-way load. A claim a
|
|
7
7
|
// swap stall holds is the exception (`core_admission.is_swap_held`).
|
|
8
8
|
const WAIT_CAP_MS = 120_000
|
|
9
|
+
// How long the load may go without easing before a held reservation is admitted at minimum width ahead
|
|
10
|
+
// of the cap (`busy_average.is_unrelieved`): ten of the busy average's windows.
|
|
11
|
+
const EASE_WINDOW_MS = 30_000
|
|
12
|
+
|
|
13
|
+
interface Cadence {
|
|
14
|
+
poll_interval_ms: number
|
|
15
|
+
wait_cap_ms: number
|
|
16
|
+
ease_window_ms: number
|
|
17
|
+
}
|
|
9
18
|
|
|
10
19
|
// The clock and cadence a wait runs on, resolved apart from the ledger fields so `reserve` stays under
|
|
11
20
|
// the complexity limit — each default is a branch.
|
|
12
|
-
interface TimingConfig {
|
|
21
|
+
interface TimingConfig extends Cadence {
|
|
13
22
|
now: () => number
|
|
14
23
|
sleep: (ms: number) => Promise<void>
|
|
15
|
-
poll_interval_ms: number
|
|
16
|
-
wait_cap_ms: number
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
async function default_sleep(ms: number): Promise<void> {
|
|
@@ -22,16 +29,23 @@ async function default_sleep(ms: number): Promise<void> {
|
|
|
22
29
|
})
|
|
23
30
|
}
|
|
24
31
|
|
|
32
|
+
function resolve_cadence(options: Partial<Cadence>): Cadence {
|
|
33
|
+
return {
|
|
34
|
+
poll_interval_ms: options.poll_interval_ms ?? POLL_INTERVAL_MS,
|
|
35
|
+
wait_cap_ms: options.wait_cap_ms ?? WAIT_CAP_MS,
|
|
36
|
+
ease_window_ms: options.ease_window_ms ?? EASE_WINDOW_MS,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
function resolve_timing(options: Partial<TimingConfig>): TimingConfig {
|
|
26
41
|
return {
|
|
27
42
|
now: options.now ?? Date.now,
|
|
28
43
|
sleep: options.sleep ?? default_sleep,
|
|
29
|
-
|
|
30
|
-
wait_cap_ms: options.wait_cap_ms ?? WAIT_CAP_MS,
|
|
44
|
+
...resolve_cadence(options),
|
|
31
45
|
}
|
|
32
46
|
}
|
|
33
47
|
|
|
34
|
-
const core_budget_timing = { resolve_timing }
|
|
48
|
+
const core_budget_timing = { WAIT_CAP_MS, resolve_timing }
|
|
35
49
|
|
|
36
50
|
export type { TimingConfig }
|
|
37
51
|
export { core_budget_timing }
|
|
@@ -9,7 +9,7 @@ import { stamp_file } from '#scripts/josh/stamp-file'
|
|
|
9
9
|
import { json_value } from '#scripts/lib/json-value'
|
|
10
10
|
import { unit_worker_share } from '#scripts/test/unit-worker-share'
|
|
11
11
|
import { z } from 'zod'
|
|
12
|
-
import { busy_average, type BusySample } from './busy-average'
|
|
12
|
+
import { busy_average, type BusySample, type LoadEase } from './busy-average'
|
|
13
13
|
import { core_admission, type Admission, type LedgerEntry, type Overflow } from './core-admission'
|
|
14
14
|
import { core_budget_timing, type TimingConfig } from './core-budget-timing'
|
|
15
15
|
import { core_wait, type BudgetWait, type WaitReason } from './core-wait'
|
|
@@ -29,7 +29,7 @@ import { machine_capacity, type MachineBudget, type MachineReading } from './mac
|
|
|
29
29
|
//
|
|
30
30
|
// **A solo run is bit-for-bit unchanged, and that is arithmetic rather than a branch.** The gate's
|
|
31
31
|
// weights are its `reserved_cores` (the static checks) and its `unit_worker_cap` (the unit suite), and
|
|
32
|
-
// `reserved(2 + 2 +
|
|
32
|
+
// `reserved(2 + 2 + 1) + unit_cap(cores - 5)` is exactly `cores` — so a single gate's four claims sum
|
|
33
33
|
// to the whole budget and, while the busy cores stay within what the ledger holds, every one is
|
|
34
34
|
// admitted the instant it is made, with no poll and no wait. Under
|
|
35
35
|
// concurrency the same weights sum past the budget and the ledger is what holds the machine down.
|
|
@@ -53,7 +53,7 @@ const MIN_BUDGET = 1
|
|
|
53
53
|
// declared memory, and it counts as load from outside the ledger until it is gone.
|
|
54
54
|
// `command`, `checkout`, `lane`, `lanes_root` and `wait_reason` name a waiting claim on `run:board`
|
|
55
55
|
// (`core-wait.ts`). `is_unit` marks a unit suite's claim, which may be admitted narrowed to `granted`
|
|
56
|
-
// past the wait cap (`core_admission.narrowed_weight`).
|
|
56
|
+
// past the wait cap, or once outside load holding it does not ease (`core_admission.narrowed_weight`).
|
|
57
57
|
const reservation_schema = process_owner_schema.extend({
|
|
58
58
|
weight: z.number(),
|
|
59
59
|
claimed_at: z.number(),
|
|
@@ -86,6 +86,7 @@ interface ReserveOptions {
|
|
|
86
86
|
report?: (line: string) => void
|
|
87
87
|
read_machine?: () => Promise<MachineReading>
|
|
88
88
|
wait_cap_ms?: number
|
|
89
|
+
ease_window_ms?: number
|
|
89
90
|
poll_interval_ms?: number
|
|
90
91
|
directory?: string
|
|
91
92
|
now?: () => number
|
|
@@ -188,6 +189,8 @@ interface WaitContext extends TimingConfig {
|
|
|
188
189
|
deadline: number
|
|
189
190
|
fields: ReservationFields
|
|
190
191
|
busy_samples: Array<BusySample>
|
|
192
|
+
// Unset until the first reading of the machine (`busy_average.with_ease`).
|
|
193
|
+
ease?: LoadEase | undefined
|
|
191
194
|
}
|
|
192
195
|
|
|
193
196
|
// **A claim alone in the ledger reads the machine too** (joshuafolkken/kit#4238): load outside the
|
|
@@ -211,6 +214,8 @@ async function current_budget(
|
|
|
211
214
|
|
|
212
215
|
const mean = busy_average.averaged(reading, context.busy_samples, ledger.cores)
|
|
213
216
|
|
|
217
|
+
context.ease = busy_average.with_ease(context.ease, mean.busy_cores, context.now())
|
|
218
|
+
|
|
214
219
|
return machine_capacity.machine_budget(context.budget, mean, ledger)
|
|
215
220
|
}
|
|
216
221
|
|
|
@@ -250,21 +255,37 @@ function mark_waiting(context: WaitContext, reason: WaitReason): void {
|
|
|
250
255
|
if (previous === undefined) context.report(core_wait.wait_line(context.fields.command, reason))
|
|
251
256
|
}
|
|
252
257
|
|
|
258
|
+
// Past the cap a held claim runs regardless, and so does one only load outside the ledger holds once
|
|
259
|
+
// that load has not eased for a window of the wait — waiting on gains it nothing. A claim a swap stall
|
|
260
|
+
// holds is the exception to both.
|
|
261
|
+
function is_wait_spent(
|
|
262
|
+
context: WaitContext,
|
|
263
|
+
reservations: ReadonlyArray<LiveReservation>,
|
|
264
|
+
budget: MachineBudget,
|
|
265
|
+
): boolean {
|
|
266
|
+
if (core_admission.is_swap_held(context.key, reservations, budget)) return false
|
|
267
|
+
|
|
268
|
+
const now = context.now()
|
|
269
|
+
|
|
270
|
+
if (now >= context.deadline) return true
|
|
271
|
+
|
|
272
|
+
return (
|
|
273
|
+
busy_average.is_unrelieved(context.ease, now, context.ease_window_ms) &&
|
|
274
|
+
core_wait.is_outside_held(context.key, reservations, budget)
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
|
|
253
278
|
async function poll_admission(context: WaitContext): Promise<Admission | undefined> {
|
|
254
279
|
const reservations = live_reservations(context.directory)
|
|
255
280
|
const budget = await current_budget(context, reservations)
|
|
256
281
|
// A unit claim is admitted at the room the budget leaves rather than at full width — the first
|
|
257
|
-
// waiter, which load outside the ledger does not hold, as well as one
|
|
282
|
+
// waiter, which load outside the ledger does not hold, as well as one whose wait is spent.
|
|
258
283
|
const granted = core_admission.narrowed_weight(context.key, reservations, budget.cores)
|
|
259
284
|
const reason = core_wait.hold_reason(context.key, reservations, budget, granted)
|
|
260
285
|
|
|
261
286
|
if (reason === undefined) return admit(context, undefined, granted)
|
|
262
287
|
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
context.now() >= context.deadline &&
|
|
266
|
-
!core_admission.is_swap_held(context.key, reservations, budget)
|
|
267
|
-
) {
|
|
288
|
+
if (is_wait_spent(context, reservations, budget)) {
|
|
268
289
|
const held = core_admission.with_grant(context.key, reservations, granted)
|
|
269
290
|
|
|
270
291
|
return admit(context, overflow_of(context, held, budget), granted)
|
|
@@ -275,7 +296,8 @@ async function poll_admission(context: WaitContext): Promise<Admission | undefin
|
|
|
275
296
|
return undefined
|
|
276
297
|
}
|
|
277
298
|
|
|
278
|
-
// Poll the ledger until this reservation is admitted, or until the wait cap
|
|
299
|
+
// Poll the ledger until this reservation is admitted, or until the wait cap — or, for a claim only load
|
|
300
|
+
// outside the ledger holds, that load not easing — admits it at minimum width.
|
|
279
301
|
// A solo run is admitted on the first read — its own claim is the ledger's head — so the loop body never
|
|
280
302
|
// runs and the wait costs nothing.
|
|
281
303
|
async function await_admission(context: WaitContext): Promise<Admission> {
|
|
@@ -370,6 +392,12 @@ async function with_core_reservation<T>(
|
|
|
370
392
|
}
|
|
371
393
|
}
|
|
372
394
|
|
|
395
|
+
// Whether a parent's claim already covers this process — a held parent command, or a unit suite this
|
|
396
|
+
// runs inside — so a command claims nothing, and one that sizes its claim need not size it.
|
|
397
|
+
function is_covered(): boolean {
|
|
398
|
+
return held_mark.is_held() || unit_worker_share.is_nested_run()
|
|
399
|
+
}
|
|
400
|
+
|
|
373
401
|
// **A command's reservation: the gate's claim, unless a parent already holds the cores**
|
|
374
402
|
// `josh-logic.ts` calls this around every command that declares a weight.
|
|
375
403
|
// Each command then only declares its weight, and no command carries a copy of the claim, run and
|
|
@@ -381,7 +409,7 @@ async function with_command_reservation<T>(
|
|
|
381
409
|
run: () => Promise<T>,
|
|
382
410
|
options: ReserveOptions = {},
|
|
383
411
|
): Promise<T> {
|
|
384
|
-
if (
|
|
412
|
+
if (is_covered()) return await run()
|
|
385
413
|
|
|
386
414
|
return await with_core_reservation(
|
|
387
415
|
weight,
|
|
@@ -413,6 +441,7 @@ const core_budget = {
|
|
|
413
441
|
budget_waits,
|
|
414
442
|
describe_overflow: core_admission.describe_overflow,
|
|
415
443
|
held_unit_claim,
|
|
444
|
+
is_covered,
|
|
416
445
|
is_held: held_mark.is_held,
|
|
417
446
|
live_reservations,
|
|
418
447
|
release,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { CoreWaitRecord } from '#scripts/lane/lane-ledger-schema'
|
|
2
|
+
import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
|
|
2
3
|
|
|
3
4
|
// How long a claim waited for the core budget, written to the lane ledger once it is admitted, so
|
|
4
5
|
// `josh lane:stats` can split a lane's time into work and waiting (joshuafolkken/kit#4382). The
|
|
@@ -21,7 +22,7 @@ interface AdmittedClaim {
|
|
|
21
22
|
type WaitSink = (wait: CoreWaitRecord) => Promise<void>
|
|
22
23
|
|
|
23
24
|
async function to_ledger(wait: CoreWaitRecord): Promise<void> {
|
|
24
|
-
await
|
|
25
|
+
await lane_ledger_write.record_core_wait(wait)
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
function wait_of(claim: AdmittedClaim, now: number): CoreWaitRecord | undefined {
|
|
@@ -95,6 +95,25 @@ function hold_reason(
|
|
|
95
95
|
return core_admission.is_too_narrow(key, reservations, granted) ? 'cpu' : undefined
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
// **Whether only load from outside the ledger holds the claim** (joshuafolkken/kit#4982): with that load
|
|
99
|
+
// gone — its busy cores handed back and no run-queue overload — the claim would be admitted at a width
|
|
100
|
+
// that is not too narrow. A claim the ledger or memory holds is not, and waits for its room to come back.
|
|
101
|
+
function is_outside_held(
|
|
102
|
+
key: string,
|
|
103
|
+
reservations: ReadonlyArray<LedgerEntry>,
|
|
104
|
+
budget: MachineBudget,
|
|
105
|
+
): boolean {
|
|
106
|
+
const unloaded = {
|
|
107
|
+
...budget,
|
|
108
|
+
cores: budget.cores + (budget.busy_excess ?? 0),
|
|
109
|
+
busy_excess: 0,
|
|
110
|
+
is_overloaded: false,
|
|
111
|
+
}
|
|
112
|
+
const granted = core_admission.narrowed_weight(key, reservations, unloaded.cores)
|
|
113
|
+
|
|
114
|
+
return hold_reason(key, reservations, unloaded, granted) === undefined
|
|
115
|
+
}
|
|
116
|
+
|
|
98
117
|
// The line a waiting command prints once, when its wait starts.
|
|
99
118
|
function wait_line(command: string | undefined, reason: WaitReason): string {
|
|
100
119
|
return `⏳ ${command ?? 'a step'} waits for the core budget — ${REASON_TEXT[reason]}`
|
|
@@ -102,10 +121,13 @@ function wait_line(command: string | undefined, reason: WaitReason): string {
|
|
|
102
121
|
|
|
103
122
|
// The lanes root a checkout belongs to: a lane's parent, or the root beside a main checkout. Two
|
|
104
123
|
// checkouts of one repository share it; the ledger is machine-wide, so another repository's do not.
|
|
124
|
+
// A Claude Code worktree under a checkout reads as that checkout (`lane_paths.checkout_of`).
|
|
105
125
|
function lanes_root_of(checkout: string): string {
|
|
106
|
-
|
|
126
|
+
const resolved = lane_paths.checkout_of(path.resolve(checkout))
|
|
127
|
+
|
|
128
|
+
if (lane_paths.lane_issue_of(resolved) === undefined) return lane_paths.lane_root(resolved)
|
|
107
129
|
|
|
108
|
-
return path.dirname(
|
|
130
|
+
return path.dirname(resolved)
|
|
109
131
|
}
|
|
110
132
|
|
|
111
133
|
// Where a claim runs, read by the claimer under its own environment: `JOSH_LANE_ROOT` is a
|
|
@@ -152,6 +174,7 @@ function waits_of(
|
|
|
152
174
|
const core_wait = {
|
|
153
175
|
WAIT_REASONS,
|
|
154
176
|
hold_reason,
|
|
177
|
+
is_outside_held,
|
|
155
178
|
wait_line,
|
|
156
179
|
wait_reason,
|
|
157
180
|
waits_of,
|
|
@@ -10,15 +10,19 @@ interface Measurement {
|
|
|
10
10
|
// **What each heavy tool was measured at, on the 11-core machine.** The whole-tree eslint scan behind
|
|
11
11
|
// `josh lines` and `josh refactor:scan`, cold on 2026-10-06. eslint over 40 staged files
|
|
12
12
|
// (`pre-commit-lint.ts`), which the gate's lint also runs beside its sibling linters, so it is the
|
|
13
|
-
// lint's floor; whole runs were observed at 124–147% CPU. The type check
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
13
|
+
// lint's floor; whole runs were observed at 124–147% CPU. The type check with `/usr/bin/time -l` on
|
|
14
|
+
// 2026-10-21 under a load average of 14. `prettier --check` over 40 staged files, `josh retrospective`
|
|
15
|
+
// and a fresh lane's `pnpm install --frozen-lockfile` with `/usr/bin/time -l` on 2026-10-17 under a
|
|
16
|
+
// load average of 16. The gate ledger records each check's CPU beside its duration (`check-cpu.ts`),
|
|
17
|
+
// so these can be re-measured from it. The spell check was re-measured from it
|
|
18
|
+
// (joshuafolkken/kit#5140): its median CPU and median wall over the lane ledger's 413 gate `cspell`
|
|
19
|
+
// runs that were not reused, from 2026-10-24 to 2026-10-27, whose per-run cores had a median of 0.91
|
|
20
|
+
// and a p90 of 1.31 — one core rounded up, where the single 2026-10-21 run of 6.0s over 5.6s had
|
|
21
|
+
// rounded up to two.
|
|
18
22
|
const MEASURED = {
|
|
19
23
|
lint: { cpu_s: 16.9, wall_s: 14 },
|
|
20
24
|
type_check: { cpu_s: 31.2, wall_s: 27.3 },
|
|
21
|
-
spell_check: { cpu_s:
|
|
25
|
+
spell_check: { cpu_s: 5.7, wall_s: 6.2 },
|
|
22
26
|
eslint_scan: { cpu_s: 113, wall_s: 98 },
|
|
23
27
|
format: { cpu_s: 2.1, wall_s: 1.7 },
|
|
24
28
|
retrospective: { cpu_s: 16.5, wall_s: 19.8 },
|
|
@@ -57,9 +61,13 @@ const CORE_WEIGHTS = {
|
|
|
57
61
|
// On 2026-10-17: prettier 260 MB, the retrospective 862 MB and a lane install 65 MB. On 2026-10-22
|
|
58
62
|
// (joshuafolkken/kit#4528) the whole suite, 1,830 files at `--maxWorkers=3` beside four lanes, sampled
|
|
59
63
|
// each worker's resident size once a second: the largest peaked at 381 MB, so the 54-file
|
|
60
|
-
// measurement had read a worker short of the files it lives through.
|
|
64
|
+
// measurement had read a worker short of the files it lives through. On 2026-10-23
|
|
65
|
+
// (joshuafolkken/kit#4595) `josh metrics`, its process tree sampled four times a second, peaked at
|
|
66
|
+
// 1,176 MB on a merge-base cache hit and 1,851 MB on a miss, where its own untyped `max-lines`-only
|
|
67
|
+
// eslint pass still holds its heap beside the `--json` child measuring the merge-base. It takes the miss.
|
|
61
68
|
const MEMORY_MB = {
|
|
62
69
|
lint: 2400,
|
|
70
|
+
metrics: 1900,
|
|
63
71
|
type_check: 1300,
|
|
64
72
|
spell_check: 350,
|
|
65
73
|
eslint_scan: 2400,
|