@joshuafolkken/kit 1.1455.0 → 1.1514.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/settings.json +6 -6
- package/.claude/skills/dependency-update/SKILL.md +26 -55
- package/.claude/skills/epic-commands/SKILL.md +83 -156
- package/.claude/skills/epic-commands/epic-bundle.md +51 -79
- package/.claude/skills/epic-commands/execution-waves.md +43 -81
- package/.claude/skills/verify-ui/SKILL.md +24 -50
- package/.claude/skills/workflow-commands/SKILL.md +7 -9
- package/.claude/skills/workflow-commands/background-commands.md +31 -46
- package/.claude/skills/workflow-commands/backlogrun-child.md +65 -85
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +86 -125
- package/.claude/skills/workflow-commands/backlogrun-park.md +68 -118
- package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -28
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +17 -26
- package/.claude/skills/workflow-commands/backlogrun-steps.md +35 -52
- package/.claude/skills/workflow-commands/backlogrun.md +31 -50
- package/.claude/skills/workflow-commands/chain-rule.md +31 -40
- package/.claude/skills/workflow-commands/delegation.md +12 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
- package/.claude/skills/workflow-commands/followup.md +55 -77
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
- package/.claude/skills/workflow-commands/fullrun.md +4 -6
- package/.claude/skills/workflow-commands/halfrun.md +3 -7
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +43 -60
- package/.claude/skills/workflow-commands/issue-scout.md +3 -2
- package/.claude/skills/workflow-commands/kickoff.md +65 -74
- package/.claude/skills/workflow-commands/latest-gate.md +2 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
- package/.claude/skills/workflow-commands/observation-filing.md +59 -118
- package/.claude/skills/workflow-commands/observation-ledger.md +52 -112
- package/.claude/skills/workflow-commands/pre-gate-cut.md +88 -142
- package/.claude/skills/workflow-commands/prerequisite.md +11 -17
- package/.claude/skills/workflow-commands/progress-watcher.md +23 -33
- package/.claude/skills/workflow-commands/prrun.md +3 -5
- package/.claude/skills/workflow-commands/retrospective.md +35 -54
- package/.claude/skills/workflow-commands/split-assessment.md +32 -58
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +54 -73
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/CLAUDE.md +7 -6
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +7 -6
- package/dist/commands/document-section-cli.js +67 -34
- package/dist/hooks/batch-guard.js +6 -6
- package/dist/hooks/chunk-4KKD2UTK.js +66 -0
- package/dist/hooks/{chunk-GPLGZ6IC.js → chunk-6TS2JD6D.js} +14 -3
- package/dist/hooks/chunk-7DSBJVFH.js +50 -0
- package/dist/hooks/{chunk-5H4SSDSD.js → chunk-A65Y4YOR.js} +3 -3
- package/dist/hooks/{chunk-3C4XRYG6.js → chunk-APUO6U4J.js} +102 -19
- package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
- package/dist/hooks/chunk-GP4IEC4O.js +20 -0
- package/dist/hooks/chunk-JP45SOCJ.js +56 -0
- package/dist/hooks/{chunk-OLMO72ON.js → chunk-LAOV7NLM.js} +1 -1
- package/dist/hooks/chunk-M4HGZV7U.js +83 -0
- package/dist/hooks/{chunk-TBJFTSUY.js → chunk-O6GDRNJB.js} +9 -7
- package/dist/hooks/{chunk-HFGWYGUV.js → chunk-PF2NZL2A.js} +5 -5
- package/dist/hooks/{chunk-WNLVGT7E.js → chunk-PTICX4OL.js} +4 -5
- package/dist/hooks/{chunk-HHI6FO3R.js → chunk-RT27QRJW.js} +763 -1515
- package/dist/hooks/{chunk-7WQBPLUN.js → chunk-SYOTDYCI.js} +1149 -1095
- package/dist/hooks/{chunk-LIAFCXL7.js → chunk-TNUMY6NL.js} +1519 -1332
- package/dist/hooks/chunk-UPUZF3AN.js +279 -0
- package/dist/hooks/{chunk-Z4XI7CZS.js → chunk-WK6SMBIC.js} +1932 -784
- package/dist/hooks/codex-hook-adapter.js +17 -14
- package/dist/hooks/duplicate-read-guard.js +7 -7
- package/dist/hooks/format-edited.js +5 -4
- package/dist/hooks/inputs.json +302 -247
- package/dist/hooks/investigation-guard.js +8 -11
- package/dist/hooks/pretool-guard.js +16 -13
- package/dist/hooks/session-lang.js +372 -26
- package/dist/hooks/stop-guard.js +2593 -189
- package/dist/josh.js +2128 -282
- package/dist/managed-marker/index.js +1 -2
- package/dist/version/index.js +15 -12
- package/eslint/base.js +2 -1
- package/eslint/rules/unicorn.js +16 -0
- package/lefthook/base.yml +5 -3
- package/package.json +14 -12
- package/prompts/coding-standards.md +12 -22
- package/prompts/collaboration-workflow/file-edits.md +25 -45
- package/prompts/collaboration-workflow/gh-rest.md +19 -36
- package/prompts/collaboration-workflow/glossary.md +5 -7
- package/prompts/collaboration-workflow/issue-citation.md +6 -14
- package/prompts/collaboration-workflow/issue-template.md +40 -32
- package/prompts/collaboration-workflow/lane-instructions.md +35 -0
- package/prompts/collaboration-workflow/operating-rules.md +33 -46
- package/prompts/collaboration-workflow/output-bounds.md +15 -15
- package/prompts/collaboration-workflow/overview.md +14 -19
- package/prompts/collaboration-workflow/plan-comment.md +13 -13
- package/prompts/collaboration-workflow/principles.md +57 -54
- package/prompts/collaboration-workflow/proposal-request.md +1 -9
- package/prompts/collaboration-workflow/report-format.md +41 -49
- package/prompts/collaboration-workflow/residency.md +15 -11
- package/prompts/collaboration-workflow/rule-delivery.md +7 -15
- package/prompts/collaboration-workflow/shell-body.md +10 -20
- package/prompts/collaboration-workflow/turn-batching.md +8 -14
- package/prompts/collaboration-workflow/upstream-interrupt.md +26 -34
- package/prompts/collaboration-workflow/wip-cap.md +26 -32
- package/prompts/collaboration-workflow.md +25 -25
- package/prompts/refactoring.md +33 -43
- package/prompts/review-rubric.md +84 -129
- package/prompts/review.md +110 -141
- package/prompts/sonar-hotspot-handling.md +22 -50
- package/prompts/testing-guide.md +48 -99
- package/scripts/adopt/adopt-toolkits.ts +2 -4
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-exit-record.ts +23 -1
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +9 -2
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/backlog/backlog-budget-cli.ts +1 -2
- package/scripts/backlog/backlog-budget.ts +4 -4
- package/scripts/backlog/backlog-drive-carried.ts +26 -0
- package/scripts/backlog/backlog-drive-cli.ts +10 -5
- package/scripts/backlog/backlog-drive-named.ts +3 -5
- package/scripts/backlog/backlog-drive-restore.ts +28 -2
- package/scripts/backlog/backlog-drive-seats.ts +27 -0
- package/scripts/backlog/backlog-drive.ts +11 -6
- package/scripts/backlog/backlog-occupied.ts +56 -0
- package/scripts/backlog/backlog-ready.ts +59 -15
- package/scripts/behavior/behavior-rules.ts +3 -2
- package/scripts/cost-runtime/codex-usage.ts +4 -2
- package/scripts/cost-runtime/cost-cli.ts +1 -2
- package/scripts/delegation/duplicate-read-guard.ts +2 -2
- package/scripts/delegation/investigation-guard.ts +15 -65
- package/scripts/delegation/investigation-reads.ts +1 -2
- package/scripts/discovery/repo-discovery.ts +4 -2
- package/scripts/discovery/repo-origin.ts +2 -4
- package/scripts/doctor/doctor-logic.ts +6 -3
- package/scripts/document/document-byte-budget.ts +28 -27
- package/scripts/document/document-byte-check.ts +1 -2
- package/scripts/document/document-section-cli.ts +17 -5
- package/scripts/document/entry-read-budget.ts +3 -3
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit-rationale.ts +8 -2
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-cli.ts +1 -2
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/epic/epic-chains.ts +6 -2
- package/scripts/epic/epic-close-comment.ts +1 -2
- package/scripts/followup/git-followup-workflow.ts +19 -1
- package/scripts/gate/check-inputs.ts +129 -0
- package/scripts/gate/check-reuse.ts +162 -0
- package/scripts/gate/core-budget.ts +93 -44
- package/scripts/gate/core-wait.ts +130 -0
- package/scripts/gate/free-cores.ts +49 -0
- package/scripts/gate/gate-ledger.ts +17 -3
- package/scripts/gate/gate-plan.ts +23 -1
- package/scripts/gate/gate-report.ts +15 -2
- package/scripts/gate/gate-run-steps.ts +150 -0
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/machine-capacity.ts +70 -11
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/verification-gate.ts +65 -127
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +24 -2
- package/scripts/gh/git-pr.ts +19 -3
- package/scripts/git/git-common-directory.ts +3 -3
- package/scripts/git/git-diff-reads.ts +16 -9
- package/scripts/git/git-execa-error.ts +1 -2
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +14 -5
- package/scripts/hooks/batch-guard.ts +5 -8
- package/scripts/hooks/format-edited-file.ts +10 -4
- package/scripts/hooks/pre-commit-lint.ts +91 -0
- package/scripts/hooks/pre-push-unit.ts +15 -4
- package/scripts/hooks/pretool-guard.ts +48 -79
- package/scripts/hooks/reserved-run.ts +1 -0
- package/scripts/hooks/run-hook.sh +10 -12
- package/scripts/hooks/step-zero-notice.ts +3 -2
- package/scripts/hooks/stop-actions.ts +204 -0
- package/scripts/hooks/stop-guard.ts +62 -21
- package/scripts/init/hook-command-rewrite.ts +6 -2
- package/scripts/init/hook-launch.ts +12 -7
- package/scripts/init/init-logic-deploy-vps.ts +4 -2
- package/scripts/issue/behavior-change-lint.ts +12 -6
- package/scripts/issue/expected-effect-lint.ts +59 -0
- package/scripts/issue/issue-cite-cli.ts +35 -15
- package/scripts/issue/issue-classification.ts +1 -1
- package/scripts/issue/issue-lint-cli.ts +5 -3
- package/scripts/issue/issue-scout-cli.ts +22 -16
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/josh/command-usage.ts +110 -0
- package/scripts/josh/file-map-stamp.ts +1 -3
- package/scripts/josh/hook-decision.ts +17 -2
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +55 -9
- package/scripts/josh/josh-commands-ai.ts +13 -0
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-hooks.ts +6 -0
- package/scripts/josh/josh-commands-lane.ts +10 -1
- package/scripts/josh/josh-commands-workflow.ts +5 -0
- package/scripts/josh/josh-logic.ts +6 -15
- package/scripts/josh/josh-usage-automation.ts +121 -0
- package/scripts/josh/josh-usage-backlog.ts +180 -0
- package/scripts/josh/josh-usage-developer.ts +230 -0
- package/scripts/josh/josh-usage-hooks.ts +38 -0
- package/scripts/josh/josh-usage-issue.ts +205 -0
- package/scripts/josh/josh-usage-review.ts +101 -0
- package/scripts/josh/josh-usage-run.ts +252 -0
- package/scripts/josh/josh-usage-session.ts +238 -0
- package/scripts/josh/josh-usage-workflow.ts +212 -0
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +20 -0
- package/scripts/lane/lane-await.ts +3 -2
- package/scripts/lane/lane-capacity.ts +8 -2
- package/scripts/lane/lane-check-stats.ts +56 -0
- package/scripts/lane/lane-child-invocation.ts +49 -5
- package/scripts/lane/lane-dispatch.ts +3 -3
- package/scripts/lane/lane-guard-policy.ts +5 -5
- package/scripts/lane/lane-handoff.ts +8 -1
- package/scripts/lane/lane-install.ts +12 -4
- package/scripts/lane/lane-ledger.ts +52 -1
- package/scripts/lane/lane-limit-cli.ts +8 -9
- package/scripts/lane/lane-load.ts +9 -2
- package/scripts/lane/lane-measure-cli.ts +4 -0
- package/scripts/lane/lane-parked.ts +18 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-process-load.ts +125 -0
- package/scripts/lane/lane-process-stats.ts +93 -0
- package/scripts/lane/lane-registry.ts +17 -10
- package/scripts/lane/lane-restart.ts +5 -26
- package/scripts/lane/lane-session-action.ts +146 -0
- package/scripts/lane/lane-session-broker.ts +68 -125
- package/scripts/lane/lane-spent.ts +14 -3
- package/scripts/lane/lane-stats.ts +1 -0
- package/scripts/lane/lane-withdraw-cli.ts +71 -0
- package/scripts/lane/lane-withdraw.ts +182 -0
- package/scripts/lint/format.ts +4 -4
- package/scripts/lint/lint-parallel.ts +10 -3
- package/scripts/lint/lint-related-scope.ts +4 -1
- package/scripts/managed-marker/managed-marker-logic.ts +1 -2
- package/scripts/notify/telegram-test.ts +10 -5
- package/scripts/overrides/lockfile-overrides.ts +1 -3
- package/scripts/propagate/propagate.ts +1 -2
- package/scripts/release/release-progress.ts +3 -2
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/report/report-lint.ts +7 -4
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +205 -0
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/review/review-record-cli.ts +6 -2
- package/scripts/rules/agent-model.ts +59 -0
- package/scripts/rules/delivered-rules.ts +11 -2
- package/scripts/rules/destructive-command.ts +6 -9
- package/scripts/rules/direct-filing.ts +3 -7
- package/scripts/rules/early-heartbeat.ts +7 -18
- package/scripts/rules/file-body.ts +6 -13
- package/scripts/rules/filing-cap.ts +4 -6
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/git-force.ts +5 -9
- package/scripts/rules/guard-remedy.ts +117 -0
- package/scripts/rules/implementation-cut.ts +37 -35
- package/scripts/rules/index-guard.ts +4 -7
- package/scripts/rules/issue-comments.ts +67 -16
- package/scripts/rules/josh-git-bare.ts +3 -6
- package/scripts/rules/lane-background.ts +10 -21
- package/scripts/rules/lane-carry-conflict.ts +7 -17
- package/scripts/rules/lane-interactive-ask.ts +6 -11
- package/scripts/rules/lane-park.ts +5 -13
- package/scripts/rules/lane-split-park.ts +2 -7
- package/scripts/rules/lane-switch-main.ts +9 -12
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-consulted.ts +4 -5
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/piped-verification.ts +84 -32
- package/scripts/rules/poll-loop.ts +7 -17
- package/scripts/rules/pre-gate-cut.ts +7 -21
- package/scripts/rules/prior-comment-read.ts +7 -5
- package/scripts/rules/protected-files.ts +5 -9
- package/scripts/rules/raw-field-body.ts +3 -7
- package/scripts/rules/rule-body-guard.ts +4 -11
- package/scripts/rules/rule-list.ts +4 -1
- package/scripts/rules/rule-registry-rows.ts +10 -0
- package/scripts/rules/rule-registry.ts +7 -4
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value.ts +7 -1
- package/scripts/rules/run-tail-rule.ts +6 -22
- package/scripts/rules/shell-body-trigger.ts +4 -6
- package/scripts/rules/shell-segments.ts +22 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rules.ts +164 -77
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/rules/test-declared-commit.ts +4 -10
- package/scripts/rules/third-party-write.ts +5 -10
- package/scripts/rules/worktree-guard.ts +5 -12
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-github.ts +19 -3
- package/scripts/run/board/run-board-header.ts +4 -1
- package/scripts/run/board/run-board-idle.ts +31 -0
- package/scripts/run/board/run-board-labels.ts +2 -0
- package/scripts/run/board/run-board-layout.ts +1 -1
- package/scripts/run/board/run-board-read.ts +25 -12
- package/scripts/run/board/run-board-reason.ts +17 -4
- package/scripts/run/board/run-board-render-legend.ts +1 -0
- package/scripts/run/board/run-board-render-slot.ts +1 -1
- package/scripts/run/board/run-board-render-waits.ts +41 -0
- package/scripts/run/board/run-board-render.ts +6 -1
- package/scripts/run/board/run-board-row-yield.ts +1 -0
- package/scripts/run/board/run-board-state.ts +9 -0
- package/scripts/run/board/run-board-status.ts +89 -23
- package/scripts/run/board/run-board-thanks.ts +7 -2
- package/scripts/run/board/run-board-tick.ts +37 -8
- package/scripts/run/carry/run-carry-args.ts +1 -3
- package/scripts/run/carry/run-carry-conversation.ts +7 -2
- package/scripts/run/cut/run-cut-cli.ts +18 -22
- package/scripts/run/cut/run-cut-decline.ts +72 -0
- package/scripts/run/cut/run-cut-ready.ts +74 -0
- package/scripts/run/cut/run-cut-report.ts +29 -0
- package/scripts/run/cut/run-cut.ts +10 -1
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-render.ts +1 -0
- package/scripts/run/event/run-event-scope.ts +19 -1
- package/scripts/run/event/run-event-stream-emit.ts +13 -6
- package/scripts/run/event/run-event-stream.ts +4 -0
- package/scripts/run/hold/run-hold-cli.ts +14 -3
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +13 -4
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-cli.ts +16 -42
- package/scripts/run/merge/run-merge-ship.ts +59 -1
- package/scripts/run/merge/run-merge-signals.ts +99 -0
- package/scripts/run/merge/run-merge-steps.ts +11 -1
- package/scripts/run/merge/run-merge.ts +22 -9
- package/scripts/run/run-ending.ts +31 -3
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +5 -10
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-preflight.ts +1 -2
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/run-stop-notify.ts +1 -2
- package/scripts/run/run-watcher-guard.ts +6 -3
- package/scripts/run/ship/run-ship-cli.ts +5 -12
- package/scripts/run/ship/run-ship-detach.ts +9 -0
- package/scripts/run/ship/run-ship-next.ts +10 -2
- package/scripts/run/ship/run-ship-overlap.ts +195 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
- package/scripts/run/ship/run-ship-preflight.ts +28 -2
- package/scripts/run/ship/run-ship-return.ts +31 -7
- package/scripts/run/ship/run-ship-review-steps.ts +25 -14
- package/scripts/run/ship/run-ship-review.ts +15 -2
- package/scripts/run/ship/run-ship-steps.ts +1 -1
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-sync.ts +14 -6
- package/scripts/run/tidy/run-tidy-cli.ts +3 -3
- package/scripts/run/tidy/run-tidy-lanes.ts +3 -2
- package/scripts/safe-chain/project-config.ts +7 -2
- package/scripts/sync/sync-hook-safety.ts +8 -2
- package/scripts/test/test-e2e-guard.ts +30 -5
- package/scripts/test/test-unit-guard.ts +16 -1
- package/scripts/test/unit-worker-share.ts +26 -3
- package/scripts/time-runtime/time-batch-guard.ts +3 -3
- package/scripts/time-runtime/time-hook-transcript.ts +3 -2
- package/scripts/time-runtime/time-shell.ts +39 -4
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/scripts/version/effective-upstream.ts +3 -4
- package/scripts/version/kit-version-config.ts +8 -2
- package/scripts/version/latest-corepack.ts +1 -2
- package/scripts/version/release-hold.ts +11 -4
- package/scripts/version/version-commands.ts +12 -4
- package/templates/gitignore +6 -2
- package/dist/hooks/chunk-D5QBTOCZ.js +0 -68
- package/dist/hooks/chunk-UT7YC3N2.js +0 -56
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { availableParallelism } from 'node:os'
|
|
2
|
+
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
3
|
+
import { buffered_process } from '#scripts/lib/buffered-process'
|
|
4
|
+
import { unit_worker_share } from '#scripts/test/unit-worker-share'
|
|
5
|
+
import { core_budget } from './core-budget'
|
|
6
|
+
import { gate_plan, type GatePlan } from './gate-plan'
|
|
7
|
+
import type { GateStep, GateStepResult } from './gate-report'
|
|
8
|
+
import { build_gate_step } from './gate-steps'
|
|
9
|
+
import { project_checks } from './project-checks'
|
|
10
|
+
|
|
11
|
+
// Running the gate's checks: each one under its place in the machine-wide budget, a reused one
|
|
12
|
+
// (`check-reuse.ts`) without starting it. `verification-gate.ts` decides what runs and records the
|
|
13
|
+
// outcome; this module only runs it.
|
|
14
|
+
|
|
15
|
+
async function run_gate_step(step: GateStep): Promise<GateStepResult> {
|
|
16
|
+
if (step.skip_reason !== undefined) {
|
|
17
|
+
return {
|
|
18
|
+
label: step.label,
|
|
19
|
+
command: step.command_args.join(' '),
|
|
20
|
+
output: project_checks.skip_notice('check', step.skip_reason),
|
|
21
|
+
exit_code: 0,
|
|
22
|
+
elapsed_ms: 0,
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const result = await buffered_process.run_buffered_process(
|
|
27
|
+
step.command_args,
|
|
28
|
+
step.cwd === undefined ? {} : { cwd: step.cwd },
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return { label: step.label, command: step.command_args.join(' '), ...result }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// This gate's share of the machine, resolved once at the gate's entry and carried down as one value.
|
|
35
|
+
// `available_cores` is the budget every check reserves against; `is_reserved`
|
|
36
|
+
// is false for a gate nested inside another gate's unit suite — this repository's own gate tests — so
|
|
37
|
+
// the outer gate reserves and every gate beneath it does not. Captured before this gate sets
|
|
38
|
+
// `JOSH_UNIT_RUN_MARKED`, which is why it is read at entry rather than re-derived here.
|
|
39
|
+
interface BudgetContext {
|
|
40
|
+
available_cores: number
|
|
41
|
+
is_reserved: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function default_budget(): BudgetContext {
|
|
45
|
+
return {
|
|
46
|
+
available_cores: availableParallelism(),
|
|
47
|
+
is_reserved: !unit_worker_share.is_nested_run() && !core_budget.is_held(),
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// A gate step paired with the cores it reserves from the machine-wide budget while it runs.
|
|
52
|
+
// The weight travels with the step so `run_gate_steps` never has to re-pair a
|
|
53
|
+
// step with its check by index.
|
|
54
|
+
interface ReservedStep {
|
|
55
|
+
step: GateStep
|
|
56
|
+
weight: number
|
|
57
|
+
memory_mb: number
|
|
58
|
+
// When the check's own green record was taken, for a check `check-reuse.ts` found reusable.
|
|
59
|
+
reused_at: string | undefined
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The checks this gate reuses, each mapped to when it was last green.
|
|
63
|
+
type ReusedChecks = ReadonlyMap<string, string>
|
|
64
|
+
|
|
65
|
+
async function build_reserved_steps(
|
|
66
|
+
plan: GatePlan,
|
|
67
|
+
available_cores: number,
|
|
68
|
+
reused: ReusedChecks,
|
|
69
|
+
): Promise<ReadonlyArray<ReservedStep>> {
|
|
70
|
+
return await Promise.all(
|
|
71
|
+
plan.checks.map(async (check) => ({
|
|
72
|
+
step: await build_gate_step(check, process.cwd(), plan),
|
|
73
|
+
weight: gate_plan.check_weight(check, plan, available_cores),
|
|
74
|
+
memory_mb: gate_plan.check_memory(check, plan, available_cores),
|
|
75
|
+
reused_at: reused.get(check.label),
|
|
76
|
+
})),
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// A reused check starts no process and claims no core: its result is the record's, and the empty
|
|
81
|
+
// output is what that record was written from (`gate_report.has_nothing_to_say`).
|
|
82
|
+
function reused_result(step: GateStep, reused_at: string): GateStepResult {
|
|
83
|
+
return {
|
|
84
|
+
label: step.label,
|
|
85
|
+
command: step.command_args.join(' '),
|
|
86
|
+
output: '',
|
|
87
|
+
exit_code: 0,
|
|
88
|
+
elapsed_ms: 0,
|
|
89
|
+
reused_at,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// **A nested gate takes no reservation, and the budget is what makes that necessary rather than
|
|
94
|
+
// merely tidy**. The unit step spawns the suite, which runs this repository's
|
|
95
|
+
// own gate tests; each of those is a gate inside the outer gate's unit reservation, and a place it
|
|
96
|
+
// claimed would wait for cores the outer gate cannot free until the suite — this test included —
|
|
97
|
+
// finishes.
|
|
98
|
+
async function run_reserved_step(
|
|
99
|
+
reserved: ReservedStep,
|
|
100
|
+
budget: BudgetContext,
|
|
101
|
+
): Promise<GateStepResult> {
|
|
102
|
+
if (reserved.reused_at !== undefined) return reused_result(reserved.step, reserved.reused_at)
|
|
103
|
+
if (!budget.is_reserved) return await run_gate_step(reserved.step)
|
|
104
|
+
|
|
105
|
+
return await core_budget.with_core_reservation(
|
|
106
|
+
reserved.weight,
|
|
107
|
+
async (admission) => ({
|
|
108
|
+
...(await run_gate_step(reserved.step)),
|
|
109
|
+
budget_note: core_budget.describe_overflow(admission),
|
|
110
|
+
}),
|
|
111
|
+
{
|
|
112
|
+
budget: budget.available_cores,
|
|
113
|
+
memory_mb: reserved.memory_mb,
|
|
114
|
+
command: `gate ${reserved.step.label}`,
|
|
115
|
+
},
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// `bounded_pool` rather than a bare `Promise.all`, so the plan's `concurrency` is what decides how
|
|
120
|
+
// many run at once. **The all-failures-in-one-pass property survives the
|
|
121
|
+
// change** because no check ever rejects: `buffered_process` reports a non-zero exit as a value, so
|
|
122
|
+
// the pool's first-failure abort — written for callers that spawn real Claude sessions — never
|
|
123
|
+
// fires here and every queued check still runs. Results come back in input order however they
|
|
124
|
+
// finished, which is what keeps the printed sections in declaration order. Each step first claims its
|
|
125
|
+
// place in the machine-wide budget and waits while the budget is full.
|
|
126
|
+
async function run_gate_steps(
|
|
127
|
+
plan: GatePlan,
|
|
128
|
+
budget: BudgetContext = default_budget(),
|
|
129
|
+
reused: ReusedChecks = new Map(),
|
|
130
|
+
): Promise<ReadonlyArray<GateStepResult>> {
|
|
131
|
+
const reserved = await build_reserved_steps(plan, budget.available_cores, reused)
|
|
132
|
+
|
|
133
|
+
// **The checks run under the held mark, so a check's own dispatch claims nothing**.
|
|
134
|
+
// Each check is a `pnpm josh <target>` child, and a target that declares
|
|
135
|
+
// a weight would otherwise claim a second place for the cores reserved for it here. A nested gate
|
|
136
|
+
// sets the mark too, since its checks are covered by the outer gate's reservation.
|
|
137
|
+
return await core_budget.with_held_mark(
|
|
138
|
+
async () =>
|
|
139
|
+
await bounded_pool.bounded_map(
|
|
140
|
+
reserved,
|
|
141
|
+
plan.concurrency,
|
|
142
|
+
async (entry) => await run_reserved_step(entry, budget),
|
|
143
|
+
),
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const gate_run_steps = { default_budget, run_gate_step, run_gate_steps }
|
|
148
|
+
|
|
149
|
+
export type { BudgetContext, ReusedChecks }
|
|
150
|
+
export { gate_run_steps }
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// **The environment mark that says a parent already holds this process's cores**
|
|
2
|
+
// `josh gate` reserves per check and then spawns `pnpm josh lint`. Without
|
|
3
|
+
// the mark, that child's own dispatch would claim a second place for the cores its parent already
|
|
4
|
+
// holds. Every holder sets it, and every child inherits it through the environment and claims nothing.
|
|
5
|
+
const HELD_KEY = 'JOSH_CORE_RESERVED'
|
|
6
|
+
const HELD_VALUE = '1'
|
|
7
|
+
// The ledger key of the claim a command holds for its children (`core_budget.with_command_reservation`),
|
|
8
|
+
// so a child reading the machine can tell that claim's admitted, not-yet-busy weight from running load.
|
|
9
|
+
const HELD_RESERVATION_KEY = 'JOSH_CORE_RESERVATION'
|
|
10
|
+
|
|
11
|
+
function is_held(): boolean {
|
|
12
|
+
return process.env[HELD_KEY] === HELD_VALUE
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// The ledger key of the one claim a parent command holds for this process, `undefined` where none does.
|
|
16
|
+
function held_reservation(): string | undefined {
|
|
17
|
+
const key = process.env[HELD_RESERVATION_KEY] ?? ''
|
|
18
|
+
|
|
19
|
+
return key === '' ? undefined : key
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// A function of its own so the restoring write does not sit after an `await`, where
|
|
23
|
+
// `require-atomic-updates` reads any write to `process` as a possible race — the reason `josh.ts`
|
|
24
|
+
// gives `record_exit_code`.
|
|
25
|
+
function set_held_mark(value: string, reservation: string): void {
|
|
26
|
+
process.env[HELD_KEY] = value
|
|
27
|
+
process.env[HELD_RESERVATION_KEY] = reservation
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Marks this process, and every child it spawns, as running inside a held reservation — `reservation`
|
|
31
|
+
// names its ledger key where one claim covers them all. The previous values come back afterwards, so a
|
|
32
|
+
// nested holder never clears the mark its outer holder set.
|
|
33
|
+
async function with_held_mark<T>(run: () => Promise<T>, reservation = ''): Promise<T> {
|
|
34
|
+
const previous = process.env[HELD_KEY] ?? ''
|
|
35
|
+
const previous_reservation = process.env[HELD_RESERVATION_KEY] ?? ''
|
|
36
|
+
|
|
37
|
+
set_held_mark(HELD_VALUE, reservation)
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
return await run()
|
|
41
|
+
} finally {
|
|
42
|
+
set_held_mark(previous, previous_reservation)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const held_mark = {
|
|
47
|
+
HELD_KEY,
|
|
48
|
+
HELD_RESERVATION_KEY,
|
|
49
|
+
HELD_VALUE,
|
|
50
|
+
held_reservation,
|
|
51
|
+
is_held,
|
|
52
|
+
with_held_mark,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { held_mark }
|
|
@@ -24,7 +24,8 @@ import { execa } from 'execa'
|
|
|
24
24
|
// admits without looking at memory, exactly as before.
|
|
25
25
|
//
|
|
26
26
|
// **`run:board` draws its machine gauges from the same reading**, so what the
|
|
27
|
-
// board shows a person is what the gate admits against
|
|
27
|
+
// board shows a person is what the gate admits against — the gate reading the free memory as none
|
|
28
|
+
// while the board's pressure and swap gauges show why. The board takes a sample with no window and
|
|
28
29
|
// draws the difference from its previous one. `lane:sample` records the memory half of it, so the
|
|
29
30
|
// lane-limit measurement sets the same figures beside the lane count.
|
|
30
31
|
|
|
@@ -50,29 +51,50 @@ const PAGE_SIZE_ARGUMENTS = ['PAGESIZE']
|
|
|
50
51
|
// every second. `kern.memorystatus_level` is the kernel's own memory-pressure figure: the percentage of
|
|
51
52
|
// memory still available, compressible and purgeable pages included — what `os.freemem()` leaves out on
|
|
52
53
|
// macOS, where it reads near zero on a machine with gigabytes to spare. The swapper counters are the
|
|
53
|
-
// pages swapped in and out since boot, `vm_stat`'s `Swapins` / `Swapouts
|
|
54
|
+
// pages swapped in and out since boot, `vm_stat`'s `Swapins` / `Swapouts`; `vm.compressor_input_bytes` is
|
|
55
|
+
// the bytes the compressor has taken in since boot, `vm_stat`'s `Compressions`. The names stay in the output
|
|
54
56
|
// (no `-n`), so a name an older macOS lacks drops only its own line.
|
|
55
57
|
const LEVEL_NAME = 'kern.memorystatus_level'
|
|
56
58
|
const SWAP_IN_NAME = 'vm.compressor.swapper.swapins_total'
|
|
57
59
|
const SWAP_OUT_NAME = 'vm.compressor.swapper.swapouts_total'
|
|
60
|
+
const COMPRESSED_NAME = 'vm.compressor_input_bytes'
|
|
58
61
|
const PAGE_SIZE_NAME = 'hw.pagesize'
|
|
59
62
|
// The kernel's memory-pressure verdict — 1 normal, 2 warning, 4 critical — the one Activity Monitor
|
|
60
63
|
// colors its "memory pressure" graph by.
|
|
61
64
|
const PRESSURE_NAME = 'kern.memorystatus_vm_pressure_level'
|
|
62
|
-
const
|
|
65
|
+
const PRESSURE_WARNING = 2
|
|
66
|
+
// The swap traffic across one window that reads as pressure — 64 MB a second paged to disk. A machine
|
|
67
|
+
// that swapped once still pages a few megabytes back in as old pages are touched.
|
|
68
|
+
const SWAP_PRESSURE_MB = 16
|
|
69
|
+
// The compressor traffic across one window that reads as pressure. An idle machine compresses nothing
|
|
70
|
+
// across a window; the 2026-10-16 thrash compressed about 240,000 16 KB pages every three seconds, about
|
|
71
|
+
// 310 MB a window, with no swap figure to show for it.
|
|
72
|
+
const COMPRESSION_PRESSURE_MB = 64
|
|
73
|
+
const SYSCTL_ARGUMENTS = [
|
|
74
|
+
LEVEL_NAME,
|
|
75
|
+
SWAP_IN_NAME,
|
|
76
|
+
SWAP_OUT_NAME,
|
|
77
|
+
COMPRESSED_NAME,
|
|
78
|
+
PAGE_SIZE_NAME,
|
|
79
|
+
PRESSURE_NAME,
|
|
80
|
+
]
|
|
63
81
|
const SYSCTL_LINE = /^(?<name>[\w.]+): (?<value>\d+)$/gmu
|
|
64
82
|
|
|
83
|
+
// `memory_pressured` says why `available_mb` read none, so a claim that waits can name the pressure.
|
|
65
84
|
interface MachineReading {
|
|
66
85
|
busy_cores: number | undefined
|
|
67
86
|
available_mb: number | undefined
|
|
87
|
+
memory_pressured?: boolean | undefined
|
|
68
88
|
}
|
|
69
89
|
|
|
70
90
|
// The memory half of a reading. `swapped_mb` is a counter — every page swapped in or out since boot —
|
|
71
|
-
// so a rate is the difference between two readings
|
|
91
|
+
// so a rate is the difference between two readings, and so is `compressed_mb`, every byte compressed
|
|
92
|
+
// since boot. `pressure_level` and `compressed_mb` are read on macOS only.
|
|
72
93
|
interface MemoryReading {
|
|
73
94
|
available_mb: number | undefined
|
|
74
95
|
swapped_mb: number | undefined
|
|
75
96
|
pressure_level: number | undefined
|
|
97
|
+
compressed_mb?: number | undefined
|
|
76
98
|
}
|
|
77
99
|
|
|
78
100
|
// What the ledger's admitted reservations declare — the part of the machine's load already accounted for.
|
|
@@ -84,6 +106,7 @@ interface LedgerLoad {
|
|
|
84
106
|
interface MachineBudget {
|
|
85
107
|
cores: number
|
|
86
108
|
memory_mb: number
|
|
109
|
+
memory_pressured?: boolean | undefined
|
|
87
110
|
}
|
|
88
111
|
|
|
89
112
|
interface CpuTimes {
|
|
@@ -141,10 +164,10 @@ function swapped_pages(
|
|
|
141
164
|
return pages_in === undefined || pages_out === undefined ? undefined : pages_in + pages_out
|
|
142
165
|
}
|
|
143
166
|
|
|
144
|
-
function
|
|
145
|
-
if (
|
|
167
|
+
function mb_of(units: number | undefined, unit_bytes: number | undefined): number | undefined {
|
|
168
|
+
if (units === undefined || unit_bytes === undefined) return undefined
|
|
146
169
|
|
|
147
|
-
return (
|
|
170
|
+
return (units * unit_bytes) / BYTES_PER_MB
|
|
148
171
|
}
|
|
149
172
|
|
|
150
173
|
// What was swapped between two readings of the counter. A counter that went back — a reboot between
|
|
@@ -163,11 +186,12 @@ function parse_darwin_memory(output: string, total_bytes: number): MemoryReading
|
|
|
163
186
|
return {
|
|
164
187
|
available_mb:
|
|
165
188
|
level === undefined ? undefined : (level / PERCENT) * (total_bytes / BYTES_PER_MB),
|
|
166
|
-
swapped_mb:
|
|
189
|
+
swapped_mb: mb_of(
|
|
167
190
|
swapped_pages(values.get(SWAP_IN_NAME), values.get(SWAP_OUT_NAME)),
|
|
168
191
|
values.get(PAGE_SIZE_NAME),
|
|
169
192
|
),
|
|
170
193
|
pressure_level: values.get(PRESSURE_NAME),
|
|
194
|
+
compressed_mb: mb_of(values.get(COMPRESSED_NAME), 1),
|
|
171
195
|
}
|
|
172
196
|
}
|
|
173
197
|
|
|
@@ -187,7 +211,7 @@ function pages_of(pattern: RegExp, vmstat: string): number | undefined {
|
|
|
187
211
|
function parse_linux_swapped(vmstat: string, page_bytes: number): number | undefined {
|
|
188
212
|
const pages = swapped_pages(pages_of(LINUX_SWAP_IN, vmstat), pages_of(LINUX_SWAP_OUT, vmstat))
|
|
189
213
|
|
|
190
|
-
return
|
|
214
|
+
return mb_of(pages, page_bytes)
|
|
191
215
|
}
|
|
192
216
|
|
|
193
217
|
async function settled<T>(read: () => Promise<T>): Promise<T | undefined> {
|
|
@@ -256,16 +280,47 @@ async function default_sleep(ms: number): Promise<void> {
|
|
|
256
280
|
})
|
|
257
281
|
}
|
|
258
282
|
|
|
283
|
+
// Whether a counter gained more than `limit` MB across the window; an unread counter gained nothing.
|
|
284
|
+
function moved_over(from: number | undefined, to: number | undefined, limit: number): boolean {
|
|
285
|
+
return (swapped_between(from, to) ?? 0) > limit
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function is_pressured(before: MemoryReading, after: MemoryReading): boolean {
|
|
289
|
+
return (
|
|
290
|
+
(after.pressure_level ?? 0) >= PRESSURE_WARNING ||
|
|
291
|
+
moved_over(before.swapped_mb, after.swapped_mb, SWAP_PRESSURE_MB) ||
|
|
292
|
+
moved_over(before.compressed_mb, after.compressed_mb, COMPRESSION_PRESSURE_MB)
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// **Memory under compression and swap pressure has nothing free to admit against.** The level counts
|
|
297
|
+
// compressible pages as available, so on 2026-10-16 it read 5.4 GB free while the compressor held
|
|
298
|
+
// 5.9 GB and compressed and decompressed about 3.3 GB every three seconds, and 5.2 GB of reservations
|
|
299
|
+
// were admitted on top. A reading the kernel calls pressured, or one with swap or compressor traffic
|
|
300
|
+
// across the window, answers no free memory: what the ledger holds keeps running and a heavy claim waits
|
|
301
|
+
// for the pressure to pass.
|
|
302
|
+
function pressured_available(before: MemoryReading, after: MemoryReading): number | undefined {
|
|
303
|
+
if (after.available_mb === undefined) return undefined
|
|
304
|
+
|
|
305
|
+
return is_pressured(before, after) ? 0 : after.available_mb
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Memory is read at both ends of the window, so the swap counter's difference is the activity during it.
|
|
259
309
|
async function read_machine(
|
|
260
310
|
sleep: (ms: number) => Promise<void> = default_sleep,
|
|
261
311
|
): Promise<MachineReading> {
|
|
262
312
|
const before = cpu_times()
|
|
263
|
-
const [
|
|
313
|
+
const [memory_before] = await Promise.all([read_memory(), sleep(SAMPLE_WINDOW_MS)])
|
|
314
|
+
const memory_after = await read_memory()
|
|
264
315
|
const busy_cores = is_unquoted()
|
|
265
316
|
? busy_cores_between(before, cpu_times(), cpus().length)
|
|
266
317
|
: undefined
|
|
267
318
|
|
|
268
|
-
return {
|
|
319
|
+
return {
|
|
320
|
+
busy_cores,
|
|
321
|
+
available_mb: pressured_available(memory_before, memory_after),
|
|
322
|
+
memory_pressured: is_pressured(memory_before, memory_after),
|
|
323
|
+
}
|
|
269
324
|
}
|
|
270
325
|
|
|
271
326
|
async function read_sample(): Promise<MachineSample> {
|
|
@@ -291,6 +346,7 @@ function machine_budget(cores: number, reading: MachineReading, ledger: LedgerLo
|
|
|
291
346
|
cores: cores - external_cores(reading.busy_cores, ledger.cores),
|
|
292
347
|
memory_mb:
|
|
293
348
|
reading.available_mb === undefined ? Infinity : reading.available_mb + ledger.memory_mb,
|
|
349
|
+
memory_pressured: reading.memory_pressured,
|
|
294
350
|
}
|
|
295
351
|
}
|
|
296
352
|
|
|
@@ -298,14 +354,17 @@ const machine_capacity = {
|
|
|
298
354
|
BASELINE_CORES,
|
|
299
355
|
busy_cores_between,
|
|
300
356
|
busy_share_between,
|
|
357
|
+
COMPRESSION_PRESSURE_MB,
|
|
301
358
|
external_cores,
|
|
302
359
|
machine_budget,
|
|
303
360
|
parse_darwin_memory,
|
|
304
361
|
parse_linux_available,
|
|
305
362
|
parse_linux_swapped,
|
|
363
|
+
pressured_available,
|
|
306
364
|
read_machine,
|
|
307
365
|
read_memory,
|
|
308
366
|
read_sample,
|
|
367
|
+
SWAP_PRESSURE_MB,
|
|
309
368
|
swapped_between,
|
|
310
369
|
}
|
|
311
370
|
|
|
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
3
3
|
import type { FileMapStamp } from '#scripts/josh/file-map-stamp'
|
|
4
4
|
import { resolve_spawn_exit } from '#scripts/lib/spawn-exit'
|
|
5
5
|
import { execa } from 'execa'
|
|
6
|
+
import { core_budget } from './core-budget'
|
|
6
7
|
import { gate_skip } from './gate-skip'
|
|
7
8
|
import { gate_tree, type GateTree } from './gate-tree'
|
|
8
9
|
import { hook_gate_reuse } from './hook-gate-reuse'
|
|
@@ -143,6 +144,18 @@ async function run_type_check(): Promise<number> {
|
|
|
143
144
|
return resolve_spawn_exit(PNPM, result)
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
// **The type check claims the place `josh check` claims** (joshuafolkken/kit#3944), so lefthook's
|
|
148
|
+
// parallel commit hooks stop reaching other lanes' admission as foreign load. Only a miss reserves:
|
|
149
|
+
// a reused record runs nothing, and a claim there could make a commit wait out a full ledger for a
|
|
150
|
+
// check it then skips.
|
|
151
|
+
async function run_reserved_type_check(): Promise<number> {
|
|
152
|
+
return await core_budget.with_command_reservation(
|
|
153
|
+
core_budget.CORE_WEIGHTS.type_check,
|
|
154
|
+
run_type_check,
|
|
155
|
+
{ memory_mb: core_budget.MEMORY_MB.type_check, command: 'pre-commit type check' },
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
146
159
|
function unexpected_arguments(extra_arguments: ReadonlyArray<string>): ReadonlyArray<string> {
|
|
147
160
|
return extra_arguments.filter((argument) => argument !== gate_skip.FORCE_FLAG)
|
|
148
161
|
}
|
|
@@ -161,7 +174,7 @@ async function run_pre_commit_type_check(
|
|
|
161
174
|
|
|
162
175
|
const reusable = await reusable_green_commit(await read_commit_tree(), extra_arguments, source)
|
|
163
176
|
|
|
164
|
-
if (reusable === undefined) return await
|
|
177
|
+
if (reusable === undefined) return await run_reserved_type_check()
|
|
165
178
|
|
|
166
179
|
process.stdout.write(`${format_skip(reusable.taken_at)}\n`)
|
|
167
180
|
|