@joshuafolkken/kit 1.1471.0 → 1.1784.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/investigator.md +1 -1
- package/.claude/settings.json +6 -6
- package/.claude/skills/epic-commands/SKILL.md +26 -77
- package/.claude/skills/epic-commands/epic-bundle.md +12 -6
- package/.claude/skills/epic-commands/execution-waves.md +1 -2
- package/.claude/skills/verify-ui/SKILL.md +1 -2
- package/.claude/skills/workflow-commands/SKILL.md +12 -14
- package/.claude/skills/workflow-commands/background-commands.md +8 -12
- package/.claude/skills/workflow-commands/backlogrun-child.md +13 -18
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +23 -28
- package/.claude/skills/workflow-commands/backlogrun-park.md +16 -31
- package/.claude/skills/workflow-commands/backlogrun-progress.md +12 -21
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +12 -12
- package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -20
- package/.claude/skills/workflow-commands/backlogrun.md +32 -51
- package/.claude/skills/workflow-commands/chain-rule.md +18 -11
- package/.claude/skills/workflow-commands/delegation.md +13 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +10 -12
- package/.claude/skills/workflow-commands/followup.md +10 -35
- package/.claude/skills/workflow-commands/fullrun-steps.md +38 -49
- package/.claude/skills/workflow-commands/fullrun.md +6 -8
- package/.claude/skills/workflow-commands/halfrun.md +20 -32
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +19 -15
- package/.claude/skills/workflow-commands/issue-scout.md +5 -4
- package/.claude/skills/workflow-commands/kickoff.md +24 -23
- package/.claude/skills/workflow-commands/latest-gate.md +9 -18
- package/.claude/skills/workflow-commands/needs-human-review.md +11 -19
- package/.claude/skills/workflow-commands/observation-filing.md +4 -50
- package/.claude/skills/workflow-commands/observation-ledger.md +5 -10
- package/.claude/skills/workflow-commands/pre-gate-cut.md +22 -44
- package/.claude/skills/workflow-commands/prerequisite.md +11 -18
- package/.claude/skills/workflow-commands/progress-watcher.md +3 -8
- package/.claude/skills/workflow-commands/prrun.md +6 -12
- package/.claude/skills/workflow-commands/retrospective.md +5 -5
- package/.claude/skills/workflow-commands/split-assessment.md +14 -4
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +11 -13
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +10 -1
- package/.github/actions/setup-pnpm/action.yml +1 -1
- package/.github/dependabot.yml +16 -0
- package/.github/release.yml +0 -2
- package/.github/workflows/ci.yml +121 -11
- package/.github/workflows/publish.yml +10 -3
- package/.github/workflows/sonar-qube.yml +1 -0
- package/.prettierignore +2 -0
- package/.vscode/tasks.json +1 -2
- package/CLAUDE.md +4 -8
- package/README.md +4 -2
- package/SECURITY.md +1 -1
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +4 -8
- package/dist/commands/document-read-cli.js +882 -0
- package/dist/commands/{document-section-cli.js → document-section-main.js} +137 -62
- package/dist/commands/read-set-cli.js +1867 -0
- package/dist/commands/run-prep-main.js +21653 -0
- package/dist/commands/run-step-cli.js +23880 -0
- package/dist/config-merge/index.js +5 -1
- package/dist/hooks/audit-provision.js +20 -35
- package/dist/hooks/{chunk-DGT54IH5.js → chunk-AZX4FGQ3.js} +63 -17
- package/dist/hooks/chunk-CWMBGKYW.js +6483 -0
- package/dist/hooks/chunk-O2YBIDSI.js +4306 -0
- package/dist/hooks/{chunk-AS74OU3D.js → chunk-PT5R6UJD.js} +4582 -2118
- package/dist/hooks/chunk-TUIFS5E7.js +72 -0
- package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
- package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-WR2KQAYZ.js} +1863 -382
- package/dist/hooks/{chunk-KC5AK2GF.js → chunk-XGBNSWEI.js} +248 -46
- package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
- package/dist/hooks/codex-hook-adapter.js +10 -19
- package/dist/hooks/format-edited.js +5 -5
- package/dist/hooks/inputs.json +436 -257
- package/dist/hooks/pretool-guard.js +7 -22
- package/dist/hooks/session-lang.js +380 -42
- package/dist/hooks/stop-guard.js +8711 -782
- package/dist/josh.js +5263 -997
- package/dist/self-sync-guard/index.js +74 -10
- package/dist/version/index.js +115 -406
- package/eslint/base.js +1 -1
- package/lefthook/base.yml +8 -4
- package/package.json +17 -53
- package/pnpm-workspace.yaml +4 -2
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +1 -9
- package/prompts/collaboration-workflow/gh-rest.md +1 -2
- package/prompts/collaboration-workflow/issue-citation.md +2 -4
- package/prompts/collaboration-workflow/issue-template.md +42 -17
- package/prompts/collaboration-workflow/lane-instructions.md +34 -0
- package/prompts/collaboration-workflow/measurement.md +37 -0
- package/prompts/collaboration-workflow/operating-rules.md +6 -12
- package/prompts/collaboration-workflow/output-bounds.md +4 -9
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/plan-comment.md +3 -42
- package/prompts/collaboration-workflow/principles.md +19 -8
- package/prompts/collaboration-workflow/report-format.md +37 -57
- package/prompts/collaboration-workflow/residency.md +12 -8
- package/prompts/collaboration-workflow/rule-delivery.md +3 -11
- package/prompts/collaboration-workflow/shell-body.md +8 -18
- package/prompts/collaboration-workflow/turn-batching.md +4 -6
- package/prompts/collaboration-workflow/upstream-interrupt.md +16 -6
- package/prompts/collaboration-workflow/wip-cap.md +7 -7
- package/prompts/collaboration-workflow.md +4 -7
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +45 -26
- package/prompts/testing-guide.md +10 -45
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-event.ts +15 -15
- package/scripts/agent/agent-exit-record.ts +13 -1
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/api-auth.ts +41 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +2 -0
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/auto-ok/auto-ok-cli.ts +14 -16
- package/scripts/auto-ok/auto-ok-judge-read.ts +12 -3
- package/scripts/auto-ok/auto-ok-judge-write.ts +46 -19
- package/scripts/auto-ok/auto-ok-judge.ts +13 -2
- package/scripts/auto-ok/auto-ok-main.ts +17 -0
- package/scripts/backlog/backlog-arrival.ts +14 -3
- package/scripts/backlog/backlog-budget-cli.ts +7 -33
- package/scripts/backlog/backlog-budget-main.ts +16 -0
- package/scripts/backlog/backlog-budget.ts +6 -7
- package/scripts/backlog/backlog-defect-priority.ts +4 -3
- package/scripts/backlog/backlog-drive-adopt.ts +67 -0
- package/scripts/backlog/backlog-drive-args.ts +4 -5
- package/scripts/backlog/backlog-drive-cli.ts +113 -28
- package/scripts/backlog/backlog-drive-hold.ts +162 -0
- package/scripts/backlog/backlog-drive-idle.ts +151 -0
- package/scripts/backlog/backlog-drive-judge.ts +25 -0
- package/scripts/backlog/backlog-drive-memory.ts +126 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +5 -10
- package/scripts/backlog/backlog-drive-named.ts +54 -7
- package/scripts/backlog/backlog-drive-offer-argv.ts +3 -8
- package/scripts/backlog/backlog-drive-paused.ts +169 -0
- package/scripts/backlog/backlog-drive-restore.ts +39 -8
- package/scripts/backlog/backlog-drive-seats.ts +18 -8
- package/scripts/backlog/backlog-drive-token-handling.ts +38 -0
- package/scripts/backlog/backlog-drive.ts +79 -75
- package/scripts/backlog/backlog-next-main.ts +16 -0
- package/scripts/backlog/backlog-next-shared.ts +73 -0
- package/scripts/backlog/backlog-next.ts +48 -16
- package/scripts/backlog/backlog-occupied.ts +69 -0
- package/scripts/backlog/backlog-offer-cli.ts +6 -21
- package/scripts/backlog/backlog-offer-exclude.ts +15 -0
- package/scripts/backlog/backlog-offer-main.ts +12 -0
- package/scripts/backlog/backlog-offer.ts +36 -3
- package/scripts/backlog/backlog-overlap.ts +22 -4
- package/scripts/backlog/backlog-plan-read.ts +6 -2
- package/scripts/backlog/backlog-plan.ts +18 -4
- package/scripts/backlog/backlog-pool.ts +10 -10
- package/scripts/backlog/backlog-rank.ts +10 -2
- package/scripts/backlog/backlog-ready.ts +137 -18
- package/scripts/backlog/backlog-stalled-detect.ts +109 -36
- package/scripts/backlog/backlog-stalled.ts +52 -16
- package/scripts/backlog/backlog-wait-cause.ts +86 -0
- package/scripts/backlog/backlog-waves.ts +39 -13
- package/scripts/backlog/backlogrun-args.ts +19 -7
- package/scripts/backlog/backlogrun-cli.ts +19 -5
- package/scripts/backlog/backlogrun-launch.ts +6 -0
- package/scripts/backlog/backlogrun-restart.ts +97 -0
- package/scripts/backlog/backlogrun-stop.ts +79 -7
- package/scripts/behavior/behavior-cli.ts +2 -2
- package/scripts/behavior/behavior-rules.ts +47 -24
- package/scripts/build/build-bin.ts +2 -16
- package/scripts/build/build-claude-md.ts +0 -7
- package/scripts/build/build-commands.ts +0 -13
- package/scripts/build/build-hooks.ts +49 -48
- package/scripts/build/hook-bundle-stamp.ts +29 -11
- package/scripts/build/local-bin.ts +1 -1
- package/scripts/cases/cases-cli.ts +25 -13
- package/scripts/cases/cases-interaction-scan.ts +134 -0
- package/scripts/cases/cases-interaction.ts +183 -0
- package/scripts/cases/cases-logic.ts +39 -6
- package/scripts/ci/pr-classification-main.ts +18 -0
- package/scripts/ci/pr-classification.ts +10 -17
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/cost-runtime/cost-blocks.ts +22 -37
- package/scripts/cost-runtime/cost-cli.ts +31 -14
- package/scripts/cost-runtime/cost-main.ts +12 -0
- package/scripts/cost-runtime/cost-transcript.ts +1 -0
- package/scripts/delegation/delegation-policy.ts +17 -4
- package/scripts/delegation/duplicate-read-guard.ts +2 -10
- package/scripts/delegation/investigation-guard.ts +15 -73
- package/scripts/delegation/investigation-reads.ts +3 -5
- package/scripts/dependabot/dependabot-cooldown.ts +194 -0
- package/scripts/discovery/repo-discovery.ts +24 -6
- package/scripts/doctor/doctor-consumer.ts +2 -5
- package/scripts/document/document-byte-budget.ts +9 -6
- package/scripts/document/document-scan.ts +1 -1
- package/scripts/document/document-section-cli.ts +17 -13
- package/scripts/document/document-section-main.ts +12 -0
- package/scripts/document/entry-read-budget.ts +2 -2
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-cli.ts +12 -6
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-apply.ts +137 -0
- package/scripts/epic/epic-bundle-cli.ts +32 -121
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-format.ts +116 -0
- package/scripts/epic/epic-bundle-main.ts +17 -0
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/epic/epic-busy.ts +5 -12
- package/scripts/epic/epic-classify.ts +24 -15
- package/scripts/epic/epic-cli-argv.ts +31 -0
- package/scripts/epic/epic-cli-decide.ts +42 -0
- package/scripts/epic/epic-cli.ts +6 -38
- package/scripts/epic/epic-close.ts +112 -55
- package/scripts/epic/epic-cross-repo.ts +4 -7
- package/scripts/epic/epic-decide.ts +119 -0
- package/scripts/epic/epic-decision.ts +9 -0
- package/scripts/epic/epic-fetch.ts +4 -0
- package/scripts/epic/epic-graph.ts +2 -0
- package/scripts/epic/epic-issue.ts +5 -1
- package/scripts/epic/epic-label-age.ts +1 -1
- package/scripts/epic/epic-lane-offer.ts +39 -4
- package/scripts/epic/epic-next-main.ts +24 -0
- package/scripts/epic/epic-next.ts +6 -24
- package/scripts/epic/epic-outside-blocker.ts +6 -2
- package/scripts/epic/epic-parse.ts +9 -3
- package/scripts/epic/epic-read.ts +1 -0
- package/scripts/epic/epic-reconcile.ts +39 -0
- package/scripts/epic/epic-run.ts +10 -1
- package/scripts/epic/epic-solo.ts +50 -14
- package/scripts/epic/epic.ts +41 -7
- package/scripts/exports/unused-members-cli.ts +2 -2
- package/scripts/followup/followup-checks-event.ts +8 -3
- package/scripts/followup/followup-coderabbit-wait.ts +82 -0
- package/scripts/followup/followup-review-gates.ts +81 -0
- package/scripts/followup/git-followup-stages.ts +13 -3
- package/scripts/followup/git-followup-workflow.ts +31 -60
- package/scripts/followup/git-pr-followup-wrapup.ts +9 -14
- package/scripts/followup/git-pr-followup.ts +36 -8
- package/scripts/fresh-machine/fresh-machine-cli.ts +1 -1
- package/scripts/fresh-machine/fresh-machine-run.ts +8 -8
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +1 -1
- package/scripts/gate/busy-average.ts +58 -0
- package/scripts/gate/check-cpu.ts +60 -0
- package/scripts/gate/check-inputs.ts +73 -0
- package/scripts/gate/check-reuse.ts +141 -0
- package/scripts/gate/command-memory.ts +192 -0
- package/scripts/gate/core-admission.ts +218 -28
- package/scripts/gate/core-budget-timing.ts +37 -0
- package/scripts/gate/core-budget.ts +150 -119
- package/scripts/gate/core-wait-record.ts +48 -0
- package/scripts/gate/core-wait.ts +162 -0
- package/scripts/gate/core-weights.ts +86 -0
- package/scripts/gate/free-cores.ts +72 -0
- package/scripts/gate/gate-ledger.ts +49 -7
- package/scripts/gate/gate-plan.ts +44 -15
- package/scripts/gate/gate-report.ts +29 -4
- package/scripts/gate/gate-run-steps.ts +195 -0
- package/scripts/gate/gate-skip.ts +12 -2
- package/scripts/gate/gate-steps.ts +12 -1
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/input-fingerprint.ts +42 -0
- package/scripts/gate/machine-capacity.ts +124 -31
- package/scripts/gate/moved-paths.ts +67 -0
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/project-checks.ts +5 -12
- package/scripts/gate/scoped-green.ts +12 -8
- package/scripts/gate/since-green.ts +62 -0
- package/scripts/gate/toolchain-inputs.ts +115 -0
- package/scripts/gate/verification-gate.ts +65 -129
- package/scripts/gate/verification-inputs.ts +250 -0
- package/scripts/gh/gh-author-association.ts +96 -9
- package/scripts/gh/git-ai-review-scan.ts +4 -2
- package/scripts/gh/git-gh-api-path.ts +15 -0
- package/scripts/gh/git-gh-branch-rules.ts +73 -0
- package/scripts/gh/git-gh-conditional.ts +5 -2
- package/scripts/gh/git-gh-issue-read.ts +5 -1
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +77 -17
- package/scripts/gh/git-gh-issue.ts +7 -3
- package/scripts/gh/git-gh-poll-read.ts +89 -0
- package/scripts/gh/git-gh-pr-auto-merge.ts +8 -3
- package/scripts/gh/git-gh-pr-rest.ts +1 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +33 -20
- package/scripts/gh/git-gh-pr.ts +27 -15
- package/scripts/gh/git-pr-checks-eval.ts +39 -7
- package/scripts/gh/git-pr-checks-parse.ts +39 -9
- package/scripts/gh/git-pr-merge-checked.ts +80 -0
- package/scripts/gh/git-pr.ts +13 -1
- package/scripts/git/base-tree.ts +19 -2
- package/scripts/git/changed-file-scope.ts +6 -4
- package/scripts/git/changed-paths.ts +18 -1
- package/scripts/git/git-diff-reads.ts +27 -2
- package/scripts/git/git-grep-hits.ts +85 -0
- package/scripts/git/git-location-environment.ts +1 -1
- package/scripts/git/git-merge-conflicts.ts +83 -0
- package/scripts/git/git-preflight.ts +37 -12
- package/scripts/git/git-push-transport.ts +1 -2
- package/scripts/git/git-schemas.ts +17 -7
- package/scripts/git/git-spawn.ts +1 -2
- package/scripts/git/git-status.ts +4 -4
- package/scripts/git/main-merge-main.ts +12 -0
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +39 -14
- package/scripts/git/main-sync-main.ts +12 -0
- package/scripts/git/main-sync.ts +0 -9
- package/scripts/git/stash/git-stash.ts +27 -4
- package/scripts/git/stash/{stash-pop-args.ts → stash-args.ts} +13 -10
- package/scripts/git/stash/stash-pop-cli.ts +6 -12
- package/scripts/git/stash/stash-pop-main.ts +12 -0
- package/scripts/git/stash/stash-push-cli.ts +76 -0
- package/scripts/git/stash/stash-push-main.ts +12 -0
- package/scripts/hooks/batch-guard.ts +5 -16
- package/scripts/hooks/check-commit-message-main.ts +8 -0
- package/scripts/hooks/check-commit-message.ts +4 -7
- package/scripts/hooks/format-edited-file.ts +8 -24
- package/scripts/hooks/pre-commit-lint.ts +118 -0
- package/scripts/hooks/pre-push-unit.ts +4 -2
- package/scripts/hooks/pretool-guard-cli.ts +1 -8
- package/scripts/hooks/pretool-guard.ts +57 -69
- package/scripts/hooks/reserved-run.ts +67 -8
- package/scripts/hooks/run-hook.sh +18 -11
- package/scripts/hooks/shell-rules-notice.ts +37 -0
- package/scripts/hooks/stop-actions.ts +185 -0
- package/scripts/hooks/stop-guard.ts +72 -27
- package/scripts/init/hook-command-rewrite.ts +19 -5
- package/scripts/init/hook-launch.ts +15 -12
- package/scripts/init/init-actions.ts +0 -6
- package/scripts/init/init-ai-copy.ts +10 -36
- package/scripts/init/init-bootstrap.ts +9 -8
- package/scripts/init/init-dry-run-report.ts +1 -1
- package/scripts/init/init-dry-run.ts +1 -1
- package/scripts/init/init-file-action.ts +7 -9
- package/scripts/init/init-logic-json-merge.ts +2 -2
- package/scripts/init/init-logic-migrate.ts +9 -82
- package/scripts/init/init-logic.ts +3 -2
- package/scripts/init/init-main.ts +12 -0
- package/scripts/init/init.ts +5 -12
- package/scripts/init/kit-development-versions.ts +3 -7
- package/scripts/init/kit-written-paths.ts +2 -2
- package/scripts/init/project-profile.ts +5 -4
- package/scripts/init/tsconfig-preset-migration.ts +2 -1
- package/scripts/init/vscode-tasks.ts +1 -1
- package/scripts/issue/defect-origin-cli.ts +106 -0
- package/scripts/issue/defect-origin-line.ts +60 -0
- package/scripts/issue/defect-origin-main.ts +11 -0
- package/scripts/issue/defect-origin.ts +114 -0
- package/scripts/issue/defect-rate-cli.ts +34 -78
- package/scripts/issue/defect-rate.ts +0 -16
- package/scripts/issue/defect-report-cli.ts +128 -0
- package/scripts/issue/defect-report-format.ts +56 -0
- package/scripts/issue/defect-report-main.ts +11 -0
- package/scripts/issue/defect-report.ts +160 -0
- package/scripts/issue/expected-effect-lint.ts +60 -0
- package/scripts/issue/issue-already-done-cli.ts +62 -0
- package/scripts/issue/issue-body-or-comment.ts +40 -0
- package/scripts/issue/issue-cite-cli.ts +33 -22
- package/scripts/issue/issue-cite-main.ts +12 -0
- package/scripts/issue/issue-classification.ts +13 -8
- package/scripts/issue/issue-comment-cli.ts +10 -24
- package/scripts/issue/issue-comment-main.ts +12 -0
- package/scripts/issue/issue-evidence-exit.ts +100 -0
- package/scripts/issue/issue-file-cli.ts +29 -7
- package/scripts/issue/issue-file.ts +19 -19
- package/scripts/issue/issue-fold-cli.ts +2 -11
- package/scripts/issue/issue-fold-main.ts +12 -0
- package/scripts/issue/issue-labels.ts +81 -90
- package/scripts/issue/issue-lint-cli.ts +7 -13
- package/scripts/issue/issue-lint-main.ts +12 -0
- package/scripts/issue/issue-measured-cli.ts +56 -0
- package/scripts/issue/issue-merged.ts +19 -2
- package/scripts/issue/issue-not-before-label.ts +135 -0
- package/scripts/issue/issue-not-before.ts +111 -0
- package/scripts/issue/issue-number-shape.ts +15 -1
- package/scripts/issue/issue-park.ts +28 -0
- package/scripts/issue/issue-plan-cli.ts +151 -0
- package/scripts/issue/issue-priority.ts +151 -0
- package/scripts/issue/issue-rank.ts +7 -1
- package/scripts/issue/issue-read-cli.ts +3 -10
- package/scripts/issue/issue-read-main.ts +12 -0
- package/scripts/issue/issue-read.ts +29 -5
- package/scripts/issue/issue-release-cli.ts +0 -10
- package/scripts/issue/issue-release-main.ts +13 -0
- package/scripts/issue/issue-release.ts +7 -12
- package/scripts/issue/issue-sample-gate.ts +192 -0
- package/scripts/issue/issue-sample-source.ts +76 -0
- package/scripts/issue/issue-scout-cli.ts +19 -25
- package/scripts/issue/issue-scout-main.ts +14 -0
- package/scripts/issue/issue-state-cli.ts +0 -10
- package/scripts/issue/issue-state-main.ts +12 -0
- package/scripts/issue/issue-watch-diff.ts +56 -15
- package/scripts/issue/issue-watch.ts +2 -1
- package/scripts/issue/issue-wip.ts +2 -7
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/issue/measure-rerun-cli.ts +13 -8
- package/scripts/issue/plan-consumers-cli.ts +39 -0
- package/scripts/issue/plan-consumers-main.ts +11 -0
- package/scripts/issue/plan-consumers-section.ts +55 -0
- package/scripts/issue/plan-consumers.ts +127 -0
- package/scripts/josh/agent-session-environment.ts +1 -1
- package/scripts/josh/command-usage.ts +82 -0
- package/scripts/josh/file-map-stamp.ts +49 -16
- package/scripts/josh/hook-decision.ts +32 -20
- package/scripts/josh/josh-command-map.ts +6 -1
- package/scripts/josh/josh-command-types.ts +65 -13
- package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
- package/scripts/josh/josh-commands-ai.ts +169 -157
- package/scripts/josh/josh-commands-backlog.ts +82 -16
- package/scripts/josh/josh-commands-clone.ts +1 -0
- package/scripts/josh/josh-commands-development.ts +111 -71
- package/scripts/josh/josh-commands-document.ts +43 -1
- package/scripts/josh/josh-commands-epic.ts +171 -0
- package/scripts/josh/josh-commands-hooks.ts +31 -2
- package/scripts/josh/josh-commands-issue-write.ts +181 -0
- package/scripts/josh/josh-commands-issue.ts +124 -24
- package/scripts/josh/josh-commands-lane.ts +112 -2
- package/scripts/josh/josh-commands-lint.ts +19 -8
- package/scripts/josh/josh-commands-maintenance.ts +112 -4
- package/scripts/josh/josh-commands-pause.ts +29 -0
- package/scripts/josh/josh-commands-progress.ts +87 -0
- package/scripts/josh/josh-commands-project.ts +138 -9
- package/scripts/josh/josh-commands-review.ts +124 -0
- package/scripts/josh/josh-commands-run.ts +211 -23
- package/scripts/josh/josh-commands-ship.ts +169 -0
- package/scripts/josh/josh-commands-split.ts +9 -0
- package/scripts/josh/josh-commands-versioning.ts +49 -2
- package/scripts/josh/josh-commands-workflow.ts +149 -6
- package/scripts/josh/josh-logic.ts +11 -27
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +18 -0
- package/scripts/josh/process-identity.ts +13 -4
- package/scripts/josh/session-language-cli.ts +4 -8
- package/scripts/josh/session-language-main.ts +13 -0
- package/scripts/josh/session-language.ts +6 -1
- package/scripts/josh/shared-cache.ts +90 -0
- package/scripts/josh/stamp-file.ts +9 -15
- package/scripts/lane/lane-await.ts +51 -12
- package/scripts/lane/lane-cache.ts +5 -30
- package/scripts/lane/lane-capacity.ts +19 -22
- package/scripts/lane/lane-check-stats.ts +97 -0
- package/scripts/lane/lane-child-invocation.ts +43 -4
- package/scripts/lane/lane-cli.ts +15 -5
- package/scripts/lane/lane-close.ts +86 -18
- package/scripts/lane/lane-core-wait-stats.ts +66 -0
- package/scripts/lane/lane-dispatch.ts +27 -6
- package/scripts/lane/lane-gap-stats.ts +156 -0
- package/scripts/lane/lane-guard-policy.ts +2 -2
- package/scripts/lane/lane-handoff.ts +76 -1
- package/scripts/lane/lane-held-stats.ts +129 -0
- package/scripts/lane/lane-install.ts +16 -15
- package/scripts/lane/lane-launch-cli.ts +0 -9
- package/scripts/lane/lane-launch-main.ts +12 -0
- package/scripts/lane/lane-ledger-schema.ts +266 -0
- package/scripts/lane/lane-ledger.ts +108 -97
- package/scripts/lane/lane-limit-cli.ts +19 -9
- package/scripts/lane/lane-measure-cli.ts +58 -10
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-parked.ts +3 -3
- package/scripts/lane/lane-pause-cli.ts +130 -0
- package/scripts/lane/lane-pause.ts +158 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-process-table.ts +166 -0
- package/scripts/lane/lane-reap-settle.ts +124 -0
- package/scripts/lane/lane-reap.ts +50 -15
- package/scripts/lane/lane-registry.ts +33 -10
- package/scripts/lane/lane-residents.ts +162 -0
- package/scripts/lane/lane-restart.ts +26 -27
- package/scripts/lane/lane-round-two-stats.ts +49 -0
- package/scripts/lane/lane-sampler.ts +4 -0
- package/scripts/lane/lane-session-action.ts +160 -0
- package/scripts/lane/lane-session-broker.ts +134 -134
- package/scripts/lane/lane-snapshot-trace.ts +84 -0
- package/scripts/lane/lane-spans.ts +51 -0
- package/scripts/lane/lane-spent.ts +6 -3
- package/scripts/lane/lane-stage-stats.ts +7 -2
- package/scripts/lane/lane-state.ts +302 -0
- package/scripts/lane/lane-stats.ts +58 -4
- package/scripts/lane/lane-stop-stats.ts +113 -37
- package/scripts/lane/lane-test-related-stats.ts +127 -0
- package/scripts/lane/lane-transcript-calls.ts +145 -0
- package/scripts/lane/lane-transcript-stats.ts +168 -0
- package/scripts/lane/lane-vacant.ts +13 -3
- package/scripts/lane/lane-withdraw-cli.ts +72 -0
- package/scripts/lane/lane-withdraw.ts +183 -0
- package/scripts/lane/process-directories.ts +70 -0
- package/scripts/lane/process-lane-marks.ts +94 -0
- package/scripts/lib/atomic-write.ts +62 -0
- package/scripts/lib/buffered-process.ts +12 -5
- package/scripts/lib/cli-flags.ts +53 -0
- package/scripts/lib/figure-format.ts +63 -0
- package/scripts/lib/json-value.ts +9 -1
- package/scripts/lib/package-manifest.ts +35 -0
- package/scripts/lib/read-file.ts +3 -1
- package/scripts/lib/stamped-memo.ts +63 -0
- package/scripts/lib/stdout-on-stderr.ts +24 -0
- package/scripts/lib/timeouts.ts +9 -0
- package/scripts/lib/transcript-record.ts +91 -0
- package/scripts/lines/effective-limit.ts +1 -1
- package/scripts/lint/eslint-cache-dependencies.ts +145 -0
- package/scripts/lint/eslint-daemon.ts +265 -0
- package/scripts/lint/format.ts +14 -5
- package/scripts/lint/import-graph.ts +279 -0
- package/scripts/lint/lint-gate-scope.ts +102 -0
- package/scripts/lint/lint-parallel-main.ts +19 -0
- package/scripts/lint/lint-parallel.ts +72 -33
- package/scripts/lint/lint-related-scope.ts +33 -24
- package/scripts/lint/lint-related.ts +38 -6
- package/scripts/notify/confirmation-options.ts +1 -2
- package/scripts/notify/telegram-notify.ts +20 -20
- package/scripts/notify/telegram-test-logic.ts +0 -1
- package/scripts/notify/telegram-test-main.ts +8 -0
- package/scripts/notify/telegram-test.ts +12 -11
- package/scripts/observations/observation-ledger.ts +13 -0
- package/scripts/observations/observations-flush-landing.ts +5 -3
- package/scripts/observations/observations-flush.ts +6 -1
- package/scripts/overrides/overrides-check.ts +2 -5
- package/scripts/overrides/overrides-files.ts +2 -1
- package/scripts/overrides/overrides-logic.ts +3 -6
- package/scripts/package/verify-optional-eslint-install.ts +8 -6
- package/scripts/propagate/propagate-publish.ts +2 -7
- package/scripts/propagate/propagate-targets.ts +4 -12
- package/scripts/refactor/import-graph.ts +9 -7
- package/scripts/release/github-release-runs.ts +17 -6
- package/scripts/release/release-approval-prune.ts +18 -0
- package/scripts/release/release-history.ts +1 -3
- package/scripts/release/release-progress.ts +42 -22
- package/scripts/release/release-publish-run.ts +39 -0
- package/scripts/release/release-publish.ts +6 -6
- package/scripts/release/release-scope-cli.ts +0 -10
- package/scripts/release/release-scope-main.ts +12 -0
- package/scripts/repo/repo-setting.ts +3 -6
- package/scripts/repo/required-checks-logic.ts +6 -15
- package/scripts/report/report-format-reference.ts +4 -0
- package/scripts/report/report-labels.ts +155 -0
- package/scripts/report/report-lint-cli.ts +3 -0
- package/scripts/report/report-lint.ts +85 -110
- package/scripts/report/report-template-cli.ts +59 -0
- package/scripts/report/report-template.ts +112 -0
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +206 -0
- package/scripts/review/removed-tests-check.ts +86 -0
- package/scripts/review/removed-tests.ts +149 -0
- package/scripts/review/review-brief-cli.ts +82 -16
- package/scripts/review/review-brief-main.ts +12 -0
- package/scripts/review/review-brief.ts +31 -3
- package/scripts/review/review-code-tree.ts +10 -6
- package/scripts/review/review-comment-round.ts +26 -8
- package/scripts/review/review-finding-ledger.ts +30 -15
- package/scripts/review/review-interaction.ts +94 -0
- package/scripts/review/review-readers-scan.ts +163 -0
- package/scripts/review/review-record-cli.ts +69 -30
- package/scripts/review/review-record-main.ts +12 -0
- package/scripts/review/review-round-one-blobs.ts +221 -0
- package/scripts/review/review-round2-cli.ts +49 -12
- package/scripts/review/review-round2.ts +80 -12
- package/scripts/review/review-stamps.ts +19 -1
- package/scripts/review/review-stop-log.ts +96 -0
- package/scripts/review/review-stops-cli.ts +85 -0
- package/scripts/review/review-tree.ts +6 -17
- package/scripts/review/review-untouched-readers.ts +146 -0
- package/scripts/review/test-titles.ts +118 -0
- package/scripts/rules/agent-model.ts +67 -0
- package/scripts/rules/bash-triggers.ts +46 -3
- package/scripts/rules/decision-oracle-batch.ts +9 -1
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +90 -3
- package/scripts/rules/destructive-command.ts +8 -1
- package/scripts/rules/direct-filing.ts +10 -2
- package/scripts/rules/direct-issue-comment.ts +117 -0
- package/scripts/rules/direct-pr-create.ts +69 -3
- package/scripts/rules/early-heartbeat.ts +2 -1
- package/scripts/rules/file-body.ts +7 -0
- package/scripts/rules/filing-cap.ts +8 -0
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/git-argv.ts +72 -14
- package/scripts/rules/git-force.ts +12 -2
- package/scripts/rules/guard-remedy.ts +121 -0
- package/scripts/rules/implementation-cut-verdict.ts +1 -1
- package/scripts/rules/implementation-cut.ts +11 -3
- package/scripts/rules/index-guard.ts +8 -1
- package/scripts/rules/issue-comments.ts +76 -7
- package/scripts/rules/josh-git-bare.ts +7 -0
- package/scripts/rules/lane-background.ts +67 -25
- package/scripts/rules/lane-carry-conflict.ts +6 -0
- package/scripts/rules/lane-direct-tool.ts +74 -0
- package/scripts/rules/lane-interactive-ask.ts +9 -2
- package/scripts/rules/lane-park.ts +45 -23
- package/scripts/rules/lane-split-park.ts +10 -2
- package/scripts/rules/lane-switch-main.ts +7 -0
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-consulted.ts +10 -0
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/permission-guards.ts +3 -0
- package/scripts/rules/piped-verification.ts +4 -2
- package/scripts/rules/poll-loop.ts +7 -0
- package/scripts/rules/pr-merge.ts +123 -0
- package/scripts/rules/protected-files.ts +32 -5
- package/scripts/rules/raw-field-body.ts +6 -0
- package/scripts/rules/rule-body-guard.ts +8 -0
- package/scripts/rules/rule-list.ts +12 -28
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value-cache.ts +4 -9
- package/scripts/rules/rule-value-cli.ts +51 -32
- package/scripts/rules/rule-value.ts +8 -2
- package/scripts/rules/shell-segments.ts +50 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rule-rows.ts +64 -0
- package/scripts/rules/stop-rules.ts +150 -51
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/rules/test-declared-commit.ts +11 -1
- package/scripts/rules/third-party-write.ts +7 -0
- package/scripts/rules/timed-rerun.ts +69 -0
- package/scripts/rules/worktree-guard.ts +13 -3
- package/scripts/run/board/run-board-app-name.ts +23 -0
- package/scripts/run/board/run-board-cli.ts +65 -30
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-earlier.ts +94 -0
- package/scripts/run/board/run-board-ending-reason.ts +67 -0
- package/scripts/run/board/run-board-estimate-schedule.ts +103 -0
- package/scripts/run/board/run-board-estimate.ts +98 -0
- package/scripts/run/board/run-board-fit.ts +153 -36
- package/scripts/run/board/run-board-fold.ts +123 -0
- package/scripts/run/board/run-board-fresh.ts +2 -2
- package/scripts/run/board/run-board-gather-live.ts +29 -0
- package/scripts/run/board/run-board-gather-thread.ts +189 -0
- package/scripts/run/board/run-board-gather-worker.ts +29 -0
- package/scripts/run/board/run-board-gather.ts +187 -0
- package/scripts/run/board/run-board-github.ts +119 -31
- package/scripts/run/board/run-board-header.ts +86 -21
- package/scripts/run/board/run-board-keys.ts +58 -0
- package/scripts/run/board/run-board-kind.ts +20 -6
- package/scripts/run/board/run-board-labels.ts +118 -71
- package/scripts/run/board/run-board-lane-state.ts +109 -0
- package/scripts/run/board/run-board-lane-time.ts +122 -0
- package/scripts/run/board/run-board-layout.ts +240 -61
- package/scripts/run/board/run-board-length.ts +52 -0
- package/scripts/run/board/run-board-machine.ts +8 -4
- package/scripts/run/board/run-board-main.ts +12 -0
- package/scripts/run/board/run-board-notes.ts +52 -31
- package/scripts/run/board/run-board-now.ts +1 -1
- package/scripts/run/board/run-board-operation.ts +15 -33
- package/scripts/run/board/run-board-phase.ts +1 -1
- package/scripts/run/board/run-board-plan-shared.ts +115 -0
- package/scripts/run/board/run-board-plan.ts +55 -3
- package/scripts/run/board/run-board-planning.ts +45 -0
- package/scripts/run/board/run-board-priority.ts +44 -0
- package/scripts/run/board/run-board-process-groups.ts +195 -0
- package/scripts/run/board/run-board-read.ts +153 -13
- package/scripts/run/board/run-board-reason.ts +238 -45
- package/scripts/run/board/run-board-released.ts +35 -0
- package/scripts/run/board/run-board-render-checks.ts +39 -5
- package/scripts/run/board/run-board-render-condition.ts +96 -0
- package/scripts/run/board/run-board-render-drawn.ts +67 -0
- package/scripts/run/board/run-board-render-foot.ts +59 -0
- package/scripts/run/board/run-board-render-icon.ts +35 -0
- package/scripts/run/board/run-board-render-lanes.ts +145 -0
- package/scripts/run/board/run-board-render-lead.ts +80 -0
- package/scripts/run/board/run-board-render-legend.ts +117 -47
- package/scripts/run/board/run-board-render-notes.ts +156 -29
- package/scripts/run/board/run-board-render-processes.ts +196 -0
- package/scripts/run/board/run-board-render-section.ts +119 -0
- package/scripts/run/board/run-board-render-slot.ts +3 -36
- package/scripts/run/board/run-board-render-tail.ts +115 -48
- package/scripts/run/board/run-board-render-time.ts +56 -0
- package/scripts/run/board/run-board-render-title.ts +117 -24
- package/scripts/run/board/run-board-render-waits.ts +125 -0
- package/scripts/run/board/run-board-render.ts +206 -259
- package/scripts/run/board/run-board-roots.ts +54 -0
- package/scripts/run/board/run-board-row-yield.ts +10 -4
- package/scripts/run/board/run-board-setup.ts +1 -12
- package/scripts/run/board/run-board-snapshot.ts +111 -0
- package/scripts/run/board/run-board-spin.ts +2 -2
- package/scripts/run/board/run-board-state.ts +23 -29
- package/scripts/run/board/run-board-status.ts +206 -79
- package/scripts/run/board/run-board-thanks-read.ts +2 -2
- package/scripts/run/board/run-board-tick.ts +123 -104
- package/scripts/run/board/run-board-usage-board.ts +78 -0
- package/scripts/run/board/run-board-usage-lanes.ts +113 -0
- package/scripts/run/board/run-board-usage-listing.ts +93 -0
- package/scripts/run/board/run-board-usage-read.ts +120 -150
- package/scripts/run/board/run-board-usage-rusage.ts +19 -7
- package/scripts/run/board/run-board-usage-text.ts +139 -51
- package/scripts/run/board/run-board-usage-top.ts +102 -0
- package/scripts/run/board/run-board-usage.ts +89 -72
- package/scripts/run/board/run-board-usual.ts +20 -9
- package/scripts/run/carry/run-carry-args.ts +4 -7
- package/scripts/run/carry/run-carry-conversation.ts +1 -1
- package/scripts/run/carry/run-carry.ts +9 -4
- package/scripts/run/cut/run-cut-cli.ts +3 -2
- package/scripts/run/cut/run-cut-handoff.ts +2 -2
- package/scripts/run/cut/run-cut-report.ts +16 -0
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-cli.ts +1 -5
- package/scripts/run/event/run-event-filed.ts +12 -6
- package/scripts/run/event/run-event-follow.ts +2 -3
- package/scripts/run/event/run-event-render.ts +7 -10
- package/scripts/run/event/run-event-scope.ts +20 -2
- package/scripts/run/event/run-event-stream-emit.ts +78 -11
- package/scripts/run/event/run-event-stream.ts +37 -7
- package/scripts/run/hold/run-hold-adopt.ts +65 -0
- package/scripts/run/hold/run-hold-cli.ts +93 -22
- package/scripts/run/hold/run-hold-main.ts +12 -0
- package/scripts/run/hold/run-hold-member.ts +37 -0
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +7 -1
- package/scripts/run/hold/run-stop-notify.ts +183 -0
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-auth.ts +31 -0
- package/scripts/run/merge/run-merge-cli.ts +72 -107
- package/scripts/run/merge/run-merge-close.ts +74 -0
- package/scripts/run/merge/run-merge-collect.ts +6 -13
- package/scripts/run/merge/run-merge-driver.ts +71 -0
- package/scripts/run/merge/run-merge-main.ts +12 -0
- package/scripts/run/merge/run-merge-outcome.ts +23 -0
- package/scripts/run/merge/run-merge-restart.ts +39 -0
- package/scripts/run/merge/run-merge-ship.ts +20 -4
- package/scripts/run/merge/run-merge-signals.ts +123 -0
- package/scripts/run/merge/run-merge-steps.ts +128 -83
- package/scripts/run/merge/run-merge.ts +53 -40
- package/scripts/run/park/run-park-cli.ts +91 -0
- package/scripts/run/park/run-park.ts +88 -0
- package/scripts/run/park/run-stalled.ts +68 -0
- package/scripts/run/pause/run-pause-cli.ts +73 -0
- package/scripts/run/pause/run-pause.ts +251 -0
- package/scripts/run/progress/run-progress-cli.ts +4 -12
- package/scripts/run/progress/run-progress-clock.ts +1 -1
- package/scripts/run/progress/run-progress-config.ts +6 -14
- package/scripts/run/progress/run-progress-main.ts +12 -0
- package/scripts/run/progress/run-progress.ts +1 -4
- package/scripts/run/review/run-review.ts +2 -1
- package/scripts/run/run-ending.ts +1 -0
- package/scripts/run/run-invocation.ts +5 -6
- package/scripts/run/run-liveness-cli.ts +6 -8
- package/scripts/run/run-liveness.ts +61 -30
- package/scripts/run/run-next.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +2 -2
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-preflight.ts +18 -3
- package/scripts/run/run-prep-cli.ts +1 -10
- package/scripts/run/run-prep-locate.ts +7 -50
- package/scripts/run/run-prep-main.ts +12 -0
- package/scripts/run/run-prep.ts +6 -0
- package/scripts/run/run-report-cli.ts +101 -13
- package/scripts/run/run-report-handoff.ts +114 -0
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +13 -0
- package/scripts/run/run-watcher-guard-cli.ts +1 -1
- package/scripts/run/run-watcher-guard.ts +1 -1
- package/scripts/run/ship/run-ship-args.ts +121 -0
- package/scripts/run/ship/run-ship-body-draft.ts +110 -0
- package/scripts/run/ship/run-ship-cli.ts +67 -151
- package/scripts/run/ship/run-ship-detach.ts +27 -7
- package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
- package/scripts/run/ship/run-ship-next.ts +27 -3
- package/scripts/run/ship/run-ship-overlap.ts +232 -0
- package/scripts/run/ship/run-ship-place.ts +96 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +43 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +102 -27
- package/scripts/run/ship/run-ship-preflight.ts +161 -30
- package/scripts/run/ship/run-ship-probe.ts +11 -3
- package/scripts/run/ship/run-ship-relaunch-cap.ts +70 -0
- package/scripts/run/ship/run-ship-removed-rows.ts +61 -0
- package/scripts/run/ship/run-ship-return.ts +123 -15
- package/scripts/run/ship/run-ship-review-steps.ts +105 -149
- package/scripts/run/ship/run-ship-review.ts +73 -6
- package/scripts/run/ship/run-ship-reviewer.ts +207 -0
- package/scripts/run/ship/run-ship-stage.ts +55 -6
- package/scripts/run/ship/run-ship-steps.ts +46 -15
- package/scripts/run/ship/run-ship-stop-cause.ts +135 -0
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-stop-text.ts +11 -6
- package/scripts/run/ship/run-ship-sync.ts +57 -12
- package/scripts/run/ship/run-ship.ts +30 -2
- package/scripts/run/tidy/run-tidy-cli.ts +0 -4
- package/scripts/run/tidy/run-tidy-lanes.ts +3 -0
- package/scripts/run/tidy/run-tidy-main.ts +8 -0
- package/scripts/run/wake/run-wake-cli.ts +119 -100
- package/scripts/run/wake/run-wake-code.ts +83 -0
- package/scripts/run/wake/run-wake-driver.ts +19 -8
- package/scripts/run/wake/run-wake-loop.ts +34 -3
- package/scripts/run/wake/run-wake-main.ts +13 -0
- package/scripts/run/wake/run-wake-ports.ts +90 -0
- package/scripts/run/wake/run-wake-takeover.ts +66 -0
- package/scripts/run/wake/run-wake.ts +2 -1
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -1
- package/scripts/safe-chain/project-config.ts +3 -9
- package/scripts/security/security-audit-main.ts +8 -0
- package/scripts/security/security-audit-provision-logic.ts +0 -11
- package/scripts/security/security-audit-provision-main.ts +12 -0
- package/scripts/security/security-audit-provision.ts +11 -26
- package/scripts/security/security-audit.ts +6 -7
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +6 -13
- package/scripts/split/split-assess-cli.ts +2 -2
- package/scripts/split/split-assess.ts +15 -0
- package/scripts/split/split-measure.ts +65 -0
- package/scripts/sync/claude-settings-merge.ts +8 -15
- package/scripts/sync/directory-copy-guard.ts +4 -9
- package/scripts/sync/file-content.ts +78 -8
- package/scripts/sync/sync-ai-files.ts +3 -5
- package/scripts/sync/sync-configs.ts +11 -23
- package/scripts/sync/sync-hook-safety.ts +4 -10
- package/scripts/sync/sync-main.ts +11 -0
- package/scripts/sync/sync.ts +25 -37
- package/scripts/test/test-declared-changed.ts +2 -2
- package/scripts/test/test-declared.ts +1 -1
- package/scripts/test/test-e2e-guard.ts +55 -6
- package/scripts/test/test-e2e-stamp.ts +38 -0
- package/scripts/test/test-pinned-logic.ts +145 -0
- package/scripts/test/test-pinned-main.ts +78 -0
- package/scripts/test/test-pinned.ts +100 -0
- package/scripts/test/test-read-map.ts +264 -0
- package/scripts/test/test-read-recording.ts +91 -0
- package/scripts/test/test-read-trace.ts +148 -0
- package/scripts/test/test-red-main.ts +12 -0
- package/scripts/test/test-red.ts +12 -30
- package/scripts/test/test-related-main.ts +18 -0
- package/scripts/test/test-related-record.ts +119 -0
- package/scripts/test/test-related-scope.ts +229 -43
- package/scripts/test/test-related.ts +300 -22
- package/scripts/test/test-unit-guard-main.ts +15 -0
- package/scripts/test/test-unit-guard.ts +54 -21
- package/scripts/test/unit-count-file.ts +37 -0
- package/scripts/test/unit-run-marker.ts +162 -0
- package/scripts/test/unit-setup-files.ts +51 -0
- package/scripts/test/unit-worker-share.ts +71 -137
- package/scripts/test/whole-suite-files.ts +63 -0
- package/scripts/time-runtime/time-background.ts +20 -2
- package/scripts/time-runtime/time-bundles.ts +4 -3
- package/scripts/time-runtime/time-density-hook.ts +8 -6
- package/scripts/time-runtime/time-followup-stage.ts +1 -3
- package/scripts/time-runtime/time-format.ts +5 -28
- package/scripts/time-runtime/time-markers.ts +10 -1
- package/scripts/time-runtime/time-shell.ts +126 -14
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/scripts/time-runtime/time-transcript-line.ts +49 -62
- package/scripts/uninstall/uninstall.ts +1 -1
- package/scripts/version/bump-version-main.ts +12 -0
- package/scripts/version/bump-version.ts +25 -25
- package/scripts/version/effective-upstream.ts +6 -12
- package/scripts/version/latest-corepack.ts +17 -32
- package/scripts/version/latest-if-required-cli.ts +93 -0
- package/scripts/version/latest-lane-guard-main.ts +8 -0
- package/scripts/version/latest-lane-guard.ts +0 -4
- package/scripts/version/latest-scope-cli.ts +0 -9
- package/scripts/version/latest-scope-main.ts +12 -0
- package/scripts/version/latest-update.ts +5 -5
- package/scripts/version/npm-registry.ts +44 -6
- package/scripts/version/publishable-range-check.ts +5 -16
- package/scripts/version/release-age.ts +1 -1
- package/scripts/version/release-hold.ts +1 -1
- package/scripts/version/release-window.ts +38 -0
- package/scripts/version/running-binary.ts +1 -1
- package/scripts/version/safe-chain-version-update.ts +3 -8
- package/scripts/version/version-targets.ts +6 -28
- package/templates/dependabot.yml +29 -0
- package/templates/gitignore +10 -3
- package/templates/pnpm-workspace.basic.yaml +1 -1
- package/templates/sonar-project.properties +3 -2
- package/templates/workflows/ci.yml +12 -4
- package/templates/workflows/github-release.yml +4 -0
- package/tsconfig.sonar.json +1 -1
- package/.ncurc.json +0 -3
- package/dist/hooks/batch-guard.js +0 -29
- package/dist/hooks/chunk-43ZHT22P.js +0 -3495
- package/dist/hooks/chunk-CDY4NFQG.js +0 -15
- package/dist/hooks/chunk-EUMACUK2.js +0 -2038
- package/dist/hooks/chunk-H5HVWYXK.js +0 -359
- package/dist/hooks/chunk-IIGFYXKC.js +0 -7104
- package/dist/hooks/chunk-IX6TTTI6.js +0 -95
- package/dist/hooks/chunk-J47HU5H5.js +0 -237
- package/dist/hooks/chunk-K4EOONYM.js +0 -45
- package/dist/hooks/chunk-K4LMBQC2.js +0 -68
- package/dist/hooks/chunk-SHGPANFB.js +0 -56
- package/dist/hooks/chunk-YHBZAJSV.js +0 -79
- package/dist/hooks/chunk-YYPI7SJZ.js +0 -131
- package/dist/hooks/duplicate-read-guard.js +0 -30
- package/dist/hooks/investigation-guard.js +0 -32
- package/scripts/backlog/backlog-stalled-cli.ts +0 -30
- package/scripts/cost-runtime/cost-format.ts +0 -29
- package/scripts/init/basic-path-migration.ts +0 -24
- package/scripts/issue/issue-backlinks-cli.ts +0 -93
- package/scripts/josh/josh-commands-guard.ts +0 -38
- package/scripts/lint/cross-file-recheck.ts +0 -155
- package/scripts/registry-migration/migrate-logic.ts +0 -237
- package/scripts/registry-migration/migrate.ts +0 -292
- package/scripts/registry-migration/user-npmrc.ts +0 -15
- package/scripts/rules/rule-guard.ts +0 -23
- package/scripts/rules/rule-registry-rows.ts +0 -282
- package/scripts/rules/rule-registry.ts +0 -109
- package/scripts/run/run-stranded-cli.ts +0 -27
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { gate_plan } from '#scripts/gate/gate-plan'
|
|
4
4
|
import type { GateTree } from '#scripts/gate/gate-tree'
|
|
5
|
+
import { input_fingerprint } from '#scripts/gate/input-fingerprint'
|
|
6
|
+
import { moved_paths } from '#scripts/gate/moved-paths'
|
|
5
7
|
import { scoped_green } from '#scripts/gate/scoped-green'
|
|
8
|
+
import { since_green } from '#scripts/gate/since-green'
|
|
6
9
|
import { changed_file_scope } from '#scripts/git/changed-file-scope'
|
|
10
|
+
import { changed_paths } from '#scripts/git/changed-paths'
|
|
7
11
|
import { review_stamps } from '#scripts/review/review-stamps'
|
|
8
|
-
import {
|
|
12
|
+
import { test_read_map, type ReadMap } from './test-read-map'
|
|
13
|
+
import { test_related_record, type RunInput } from './test-related-record'
|
|
14
|
+
import { related_scope, type RelatedScope, type ScopeRequest } from './test-related-scope'
|
|
9
15
|
import { test_unit_guard } from './test-unit-guard'
|
|
10
16
|
|
|
11
17
|
// `josh test:related` — the unit check an implementation loop runs between edits.
|
|
@@ -30,27 +36,303 @@ function conclusive_tree(before: GateTree | undefined): GateTree | undefined {
|
|
|
30
36
|
return test_unit_guard.is_running(process.cwd()) ? before : undefined
|
|
31
37
|
}
|
|
32
38
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
// The change a narrowing reads, and the map it reads it against. `is_unmoved` is the since-green
|
|
40
|
+
// reading's positive fact that nothing moved since this command was last green on this checkout.
|
|
41
|
+
// `synced` is the part of the change a main sync brought in, kept for the run's ledger record, and
|
|
42
|
+
// `since_map` the part the change since the map's tree joined to what this change moved.
|
|
43
|
+
type ChangeReading = Pick<ScopeRequest, 'changed' | 'map' | 'since_map'> & {
|
|
44
|
+
is_unmoved?: true
|
|
45
|
+
synced?: ReadonlyArray<string>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// A failure answers `undefined` rather than an empty list: the two are opposite inputs to
|
|
49
|
+
// `resolve_scope`, and only one of them means "could not tell".
|
|
50
|
+
async function read_or_undefined(
|
|
51
|
+
read: () => Promise<ReadonlyArray<string>>,
|
|
52
|
+
): Promise<ReadonlyArray<string> | undefined> {
|
|
53
|
+
try {
|
|
54
|
+
return await read()
|
|
55
|
+
} catch {
|
|
56
|
+
return undefined
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function branch_change(): Promise<ReadonlyArray<string> | undefined> {
|
|
61
|
+
return await read_or_undefined(async () => await changed_paths.read_changed_paths(false))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// **The change a map answers for is the change since the tree it was recorded on** — its commit and
|
|
65
|
+
// the content its dirty files held then (`test_read_map.changed_since_tree`). A commit git can no
|
|
66
|
+
// longer resolve — a pruned or foreign map — leaves the branch change with no map, which runs the
|
|
67
|
+
// whole suite on any non-code file.
|
|
68
|
+
async function change_since(
|
|
69
|
+
root: string,
|
|
70
|
+
map: ReadMap,
|
|
71
|
+
): Promise<ReadonlyArray<string> | undefined> {
|
|
72
|
+
const since = await read_or_undefined(
|
|
73
|
+
async () => await changed_paths.read_changed_since(map.commit),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
if (since === undefined) return undefined
|
|
77
|
+
|
|
78
|
+
return test_read_map.changed_since_tree(
|
|
79
|
+
map,
|
|
80
|
+
since,
|
|
81
|
+
input_fingerprint.of_files(root, Object.keys(map.dirty)),
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// **The map's tree is whichever lane last ran the whole suite green**, so the change since it holds that
|
|
86
|
+
// lane's own branch change too (joshuafolkken/kit#4527). What this branch did not change is marked
|
|
87
|
+
// `since_map`: it still reaches its readers — a source file only when it names what moved — but only
|
|
88
|
+
// this branch's change can send the run to the whole suite. A branch change git cannot read marks nothing.
|
|
89
|
+
async function map_change(root: string, map: ReadMap): Promise<ChangeReading> {
|
|
90
|
+
const changed = await change_since(root, map)
|
|
91
|
+
|
|
92
|
+
if (changed === undefined) return { changed: await branch_change(), map: undefined }
|
|
93
|
+
|
|
94
|
+
const branch = await branch_change()
|
|
95
|
+
|
|
96
|
+
if (branch === undefined) return { changed, map }
|
|
97
|
+
|
|
98
|
+
return { changed, map, since_map: changed.filter((file) => !branch.includes(file)) }
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Explicit file arguments win over the git reading, which is what makes the narrowing testable by
|
|
102
|
+
// hand and usable from a hook that already knows which file it just wrote. **The map still answers
|
|
103
|
+
// only for the change since its tree**, so that change joins the arguments: a test added since the
|
|
104
|
+
// map was recorded is in no entry, and only its own appearance in the change runs it — a source file
|
|
105
|
+
// there only when it names a file the arguments moved (`naming_moved`).
|
|
106
|
+
async function explicit_change(
|
|
107
|
+
root: string,
|
|
108
|
+
explicit: ReadonlyArray<string>,
|
|
109
|
+
map: ReadMap | undefined,
|
|
110
|
+
): Promise<ChangeReading> {
|
|
111
|
+
const since = map === undefined ? undefined : await change_since(root, map)
|
|
112
|
+
|
|
113
|
+
if (since === undefined) return { changed: explicit, map: undefined }
|
|
114
|
+
|
|
115
|
+
const named = new Set(explicit)
|
|
116
|
+
const since_map = since.filter((file) => !named.has(file))
|
|
117
|
+
|
|
118
|
+
return { changed: [...named, ...since_map], map, since_map }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// **A non-code file a main sync brought in is not this branch's change** (joshuafolkken/kit#4572), so it
|
|
122
|
+
// joins `since_map`: it still reaches the tests reading it, but never sends the run to the whole suite —
|
|
123
|
+
// main's CI verified it. A synced module stays a moved file, so `vitest related` still walks to the
|
|
124
|
+
// tests importing it, a branch-only one among them. A branch change git cannot read marks nothing.
|
|
125
|
+
async function synced_data(synced: ReadonlyArray<string>): Promise<ReadonlyArray<string>> {
|
|
126
|
+
const data = synced.filter((file) => !related_scope.is_relatable(file))
|
|
127
|
+
|
|
128
|
+
if (data.length === 0) return []
|
|
129
|
+
|
|
130
|
+
const branch = (await branch_change()) ?? data
|
|
131
|
+
|
|
132
|
+
return data.filter((file) => !branch.includes(file))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// **What moved since this command's last green run** (`since-green.ts`), read as explicit arguments
|
|
136
|
+
// are. A moved file — code or not — reaches the tests reading it as data through the map, whose
|
|
137
|
+
// entries hold no module that started reading it after the map's tree; the change since that tree
|
|
138
|
+
// joins the list — its test files, and a source file only when it names a moved file
|
|
139
|
+
// (`naming_moved`) — so such a module runs the tests importing it. Nothing moved runs nothing; no map,
|
|
140
|
+
// or one git can no longer diff against, answers `undefined`, which reads the whole branch change.
|
|
141
|
+
async function since_green_change(
|
|
142
|
+
root: string,
|
|
143
|
+
map: ReadMap | undefined,
|
|
144
|
+
): Promise<ChangeReading | undefined> {
|
|
145
|
+
const parts = await since_green.read_moved_parts(
|
|
146
|
+
review_stamps.test_related_stamp,
|
|
147
|
+
gate_plan.UNIT_LABEL,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
if (parts === undefined) return undefined
|
|
151
|
+
|
|
152
|
+
const moved = moved_paths.union_of(parts)
|
|
153
|
+
|
|
154
|
+
if (moved.length === 0) return { changed: [], map, is_unmoved: true }
|
|
155
|
+
|
|
156
|
+
const change = await explicit_change(root, moved, map)
|
|
157
|
+
|
|
158
|
+
if (change.map === undefined) return undefined
|
|
159
|
+
|
|
160
|
+
process.stdout.write(`${since_green.describe(related_scope.COMMAND_LABEL, moved)}\n`)
|
|
161
|
+
|
|
162
|
+
const since_map = [...(change.since_map ?? []), ...(await synced_data(parts.synced))]
|
|
163
|
+
|
|
164
|
+
return { ...change, since_map, synced: parts.synced }
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function whole_change(root: string, map: ReadMap | undefined): Promise<ChangeReading> {
|
|
168
|
+
const since = await since_green_change(root, map)
|
|
169
|
+
|
|
170
|
+
if (since !== undefined) return since
|
|
171
|
+
|
|
172
|
+
return map === undefined ? { changed: await branch_change(), map } : await map_change(root, map)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function read_change(
|
|
176
|
+
root: string,
|
|
177
|
+
command_arguments: ReadonlyArray<string>,
|
|
178
|
+
): Promise<ChangeReading> {
|
|
179
|
+
const map = test_read_map.read_map(root)
|
|
180
|
+
const explicit = command_arguments
|
|
181
|
+
.filter((argument) => !changed_file_scope.is_flag(argument))
|
|
182
|
+
.map((file) => path.relative(root, path.resolve(file)))
|
|
183
|
+
|
|
184
|
+
return explicit.length > 0
|
|
185
|
+
? await explicit_change(root, explicit, map)
|
|
186
|
+
: await whole_change(root, map)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// **The changed non-code files the map's tree held and that did not already differ from it** — the
|
|
190
|
+
// ones whose having no reader in the map means no test reads them. A file that was dirty when the
|
|
191
|
+
// map was recorded is left out, since the tree the tests read then was not the commit's. A git
|
|
192
|
+
// failure holds none, which runs the whole suite on any of them.
|
|
193
|
+
async function recorded_files(change: ChangeReading): Promise<ReadonlySet<string>> {
|
|
194
|
+
const { changed, map } = change
|
|
195
|
+
|
|
196
|
+
if (changed === undefined || map === undefined) return new Set()
|
|
197
|
+
|
|
198
|
+
const dirty = new Set(Object.keys(map.dirty))
|
|
199
|
+
const candidates = changed.filter((file) => !related_scope.is_relatable(file) && !dirty.has(file))
|
|
200
|
+
|
|
201
|
+
return new Set(
|
|
202
|
+
await read_or_undefined(async () => await changed_paths.read_held_at(map.commit, candidates)),
|
|
203
|
+
)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function text_of(file_path: string): string {
|
|
207
|
+
try {
|
|
208
|
+
return readFileSync(file_path, 'utf8')
|
|
209
|
+
} catch {
|
|
210
|
+
return ''
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Each file's text is read once, however many names it is checked for.
|
|
215
|
+
function names_any(text: string, names: ReadonlyArray<string>): boolean {
|
|
216
|
+
return names.some((name) => text.includes(name))
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// **The code files of the change since the map that name a file this change moved** — read off their
|
|
220
|
+
// text, the one place a file-system read added since the map's tree shows (`is_code_input` in
|
|
221
|
+
// `test-related-scope.ts`, joshuafolkken/kit#4532). A file the tree no longer holds names nothing.
|
|
222
|
+
function naming_moved(root: string, change: ChangeReading): ReadonlySet<string> {
|
|
223
|
+
const { changed = [], since_map = [] } = change
|
|
224
|
+
const names = changed
|
|
225
|
+
.filter((file) => !since_map.includes(file))
|
|
226
|
+
.map((file) => path.basename(file))
|
|
227
|
+
const code = since_map.filter((file) => related_scope.is_relatable(file))
|
|
228
|
+
|
|
229
|
+
return new Set(code.filter((file) => names_any(text_of(path.join(root, file)), names)))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function scope_of(root: string, change: ChangeReading): Promise<RelatedScope> {
|
|
233
|
+
const recorded = await recorded_files(change)
|
|
234
|
+
const naming = naming_moved(root, change)
|
|
235
|
+
|
|
236
|
+
return related_scope.resolve_scope({
|
|
37
237
|
root,
|
|
38
|
-
|
|
238
|
+
...change,
|
|
239
|
+
recorded,
|
|
240
|
+
naming_moved: naming,
|
|
241
|
+
is_present: existsSync,
|
|
39
242
|
})
|
|
243
|
+
}
|
|
40
244
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
245
|
+
// **Whether a set of changed files can reach any test**, answered by the decision this command
|
|
246
|
+
// narrows with, so the gate's reuse of a green unit step (`check-inputs.ts`) can never trust a change
|
|
247
|
+
// this command would have run tests for. Unknown reaches: no map, or one recorded on a tree git can
|
|
248
|
+
// no longer diff against. The change since the map joins the paths as it does for explicit
|
|
249
|
+
// arguments, so a test added or edited after the map was recorded still reaches.
|
|
250
|
+
async function reaches_tests(root: string, paths: ReadonlyArray<string>): Promise<boolean> {
|
|
251
|
+
if (paths.length === 0) return false
|
|
46
252
|
|
|
47
|
-
const
|
|
48
|
-
|
|
253
|
+
const change = await explicit_change(root, paths, test_read_map.read_map(root))
|
|
254
|
+
|
|
255
|
+
if (change.map === undefined) return true
|
|
256
|
+
|
|
257
|
+
const scope = await scope_of(root, change)
|
|
258
|
+
|
|
259
|
+
return scope.mode !== 'none'
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// A change known to reach no test succeeds without starting vitest, and says why.
|
|
263
|
+
async function run_scope(
|
|
264
|
+
scope: RelatedScope,
|
|
265
|
+
root: string,
|
|
266
|
+
command_arguments: ReadonlyArray<string>,
|
|
267
|
+
): Promise<number> {
|
|
268
|
+
const description = related_scope.describe_scope(scope, root)
|
|
269
|
+
|
|
270
|
+
if (scope.mode === 'none') {
|
|
271
|
+
process.stdout.write(`${description}\n`)
|
|
272
|
+
|
|
273
|
+
return 0
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return await test_unit_guard.run_guarded_vitest(
|
|
49
277
|
process.cwd(),
|
|
50
278
|
related_scope.vitest_arguments(scope, changed_file_scope.flags_of(command_arguments)),
|
|
51
279
|
related_scope.COMMAND_NAME,
|
|
52
|
-
|
|
280
|
+
description,
|
|
53
281
|
)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
async function resolve_change(root: string, change: ChangeReading): Promise<RelatedScope> {
|
|
285
|
+
const { UNMOVED_REASON } = related_scope
|
|
286
|
+
|
|
287
|
+
if (change.is_unmoved === true) return { mode: 'none', files: [], reason: UNMOVED_REASON }
|
|
288
|
+
|
|
289
|
+
return await scope_of(root, change)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function read_run_input(
|
|
293
|
+
root: string,
|
|
294
|
+
command_arguments: ReadonlyArray<string>,
|
|
295
|
+
): Promise<RunInput> {
|
|
296
|
+
const change = await read_change(root, command_arguments)
|
|
297
|
+
const scope = await resolve_change(root, change)
|
|
298
|
+
|
|
299
|
+
const { changed, synced = [], since_map = [] } = change
|
|
300
|
+
|
|
301
|
+
return { scope, root, changed, synced, since_map }
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Every run is timed and counted into the lane ledger (joshuafolkken/kit#4465).
|
|
305
|
+
async function run_and_record(
|
|
306
|
+
input: RunInput,
|
|
307
|
+
command_arguments: ReadonlyArray<string>,
|
|
308
|
+
): Promise<number> {
|
|
309
|
+
const started = performance.now()
|
|
310
|
+
const { exit_code, test_files } = await test_related_record.with_test_count(
|
|
311
|
+
async () => await run_scope(input.scope, input.root, command_arguments),
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
await test_related_record.record_run(input, {
|
|
315
|
+
elapsed_ms: performance.now() - started,
|
|
316
|
+
test_files,
|
|
317
|
+
})
|
|
318
|
+
|
|
319
|
+
return exit_code
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
async function run_related_tests(command_arguments: ReadonlyArray<string>): Promise<number> {
|
|
323
|
+
const root = await changed_file_scope.repository_root_or_cwd()
|
|
324
|
+
const input = await read_run_input(root, command_arguments)
|
|
325
|
+
|
|
326
|
+
// A non-code argument is resolved through the map rather than handed to vitest, so only the
|
|
327
|
+
// code arguments can be ones vitest was not given.
|
|
328
|
+
changed_file_scope.report_unusable_arguments(
|
|
329
|
+
command_arguments.filter((argument) => related_scope.is_relatable(argument)),
|
|
330
|
+
input.scope,
|
|
331
|
+
related_scope.COMMAND_LABEL,
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
const before = await scoped_green.read_before(command_arguments)
|
|
335
|
+
const exit_code = await run_and_record(input, command_arguments)
|
|
54
336
|
|
|
55
337
|
await scoped_green.record_if_green(review_stamps.test_related_stamp, {
|
|
56
338
|
before: conclusive_tree(before),
|
|
@@ -60,10 +342,6 @@ async function run_related_tests(command_arguments: ReadonlyArray<string>): Prom
|
|
|
60
342
|
return exit_code
|
|
61
343
|
}
|
|
62
344
|
|
|
63
|
-
|
|
64
|
-
process.exitCode = await run_related_tests(process.argv.slice(changed_file_scope.ARGV_START))
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const test_related = { run_related_tests }
|
|
345
|
+
const test_related = { reaches_tests, run_related_tests }
|
|
68
346
|
|
|
69
347
|
export { test_related }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { test_unit_guard } from './test-unit-guard'
|
|
4
|
+
|
|
5
|
+
// The `josh test:unit` entry, kept apart from `test-unit-guard.ts` because the gate and the pre-push
|
|
6
|
+
// hook import that one: a bundle is one file, so a main guard there would fire for every command that
|
|
7
|
+
// carries it (joshuafolkken/kit#4186).
|
|
8
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
9
|
+
const ARGV_OFFSET = 2
|
|
10
|
+
|
|
11
|
+
process.exitCode = await test_unit_guard.run_guarded_unit(
|
|
12
|
+
process.cwd(),
|
|
13
|
+
process.argv.slice(ARGV_OFFSET),
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
1
|
import { existsSync, globSync } from 'node:fs'
|
|
2
|
+
import { availableParallelism } from 'node:os'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { fileURLToPath } from 'node:url'
|
|
5
4
|
import { PROJECT_ENVIRONMENT_KEYS } from '#ports'
|
|
5
|
+
import { core_budget } from '#scripts/gate/core-budget'
|
|
6
|
+
import { free_cores } from '#scripts/gate/free-cores'
|
|
6
7
|
import { project_checks } from '#scripts/gate/project-checks'
|
|
8
|
+
import { changed_file_scope } from '#scripts/git/changed-file-scope'
|
|
7
9
|
import { execa } from 'execa'
|
|
8
10
|
import { project_test_script, type ProjectScriptState } from './project-test-script'
|
|
9
11
|
import { SKIP_MARKER } from './skip-marker'
|
|
12
|
+
import { test_read_recording, type RecordingEnvironment } from './test-read-recording'
|
|
10
13
|
import { unit_worker_share } from './unit-worker-share'
|
|
11
14
|
|
|
12
15
|
const PNPM = 'pnpm'
|
|
13
16
|
const FAIL_EXIT_CODE = 1
|
|
14
|
-
const ARGV_START = 2
|
|
15
17
|
const VITEST_PACKAGE = path.join('node_modules', 'vitest')
|
|
16
18
|
const UNIT_GLOB = '**/*.{test,spec}.{ts,js}'
|
|
17
19
|
const NODE_MODULES = 'node_modules'
|
|
@@ -175,20 +177,57 @@ function isolated_unit_environment(
|
|
|
175
177
|
// Reading the share first and claiming afterwards leaves a window in which two hooks firing together
|
|
176
178
|
// both count "alone" and both run uncapped. Inside the marker the number is identical — this run's own
|
|
177
179
|
// record is now on disk and `is_nested_run` therefore contributes nothing — and the window is gone.
|
|
180
|
+
//
|
|
181
|
+
// **The share is bounded by the claim the run was admitted on** (`unit_worker_share.cap_to_claim`), so
|
|
182
|
+
// a share read after admission never opens more workers than the ledger holds for it
|
|
183
|
+
// (joshuafolkken/kit#4235).
|
|
184
|
+
//
|
|
185
|
+
// **The machine is read only when no count was typed.** The reading waits out a sample window, and a
|
|
186
|
+
// caller's `--maxWorkers` wins whatever it says. The gate's cap is one: its admission narrows it to the
|
|
187
|
+
// free cores, and its unit step bounds it by the free memory once admitted (`gate-run-steps.ts`).
|
|
188
|
+
async function vitest_share(vitest_arguments: ReadonlyArray<string>): Promise<number | undefined> {
|
|
189
|
+
if (unit_worker_share.has_worker_flag(vitest_arguments)) return undefined
|
|
190
|
+
|
|
191
|
+
const available_cores = availableParallelism()
|
|
192
|
+
// The cores and the memory free right now (joshuafolkken/kit#4528), from one reading.
|
|
193
|
+
const free = await free_cores.read({ available_cores })
|
|
194
|
+
const share = unit_worker_share.current_share(
|
|
195
|
+
available_cores,
|
|
196
|
+
unit_worker_share.live_run_count(),
|
|
197
|
+
free,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
return unit_worker_share.cap_to_claim(share, core_budget.held_unit_claim())
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async function execute_vitest(
|
|
204
|
+
vitest_arguments: ReadonlyArray<string>,
|
|
205
|
+
recording: RecordingEnvironment,
|
|
206
|
+
): Promise<number> {
|
|
207
|
+
const result = await execa(PNPM, ['exec', 'vitest', ...vitest_arguments], {
|
|
208
|
+
env: { ...isolated_unit_environment(), ...recording },
|
|
209
|
+
extendEnv: false,
|
|
210
|
+
stdio: 'inherit',
|
|
211
|
+
reject: false,
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
return result.exitCode ?? FAIL_EXIT_CODE
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// A whole-suite run also records the test-read map `josh test:related` narrows by.
|
|
178
218
|
async function run_vitest(vitest_arguments: ReadonlyArray<string>): Promise<number> {
|
|
179
219
|
return await unit_worker_share.with_run_marker(async () => {
|
|
180
|
-
const sized =
|
|
181
|
-
vitest_arguments,
|
|
182
|
-
unit_worker_share.
|
|
220
|
+
const sized = [
|
|
221
|
+
...vitest_arguments,
|
|
222
|
+
...unit_worker_share.worker_arguments(vitest_arguments, await vitest_share(vitest_arguments)),
|
|
223
|
+
]
|
|
224
|
+
const root = await changed_file_scope.repository_root_or_cwd()
|
|
225
|
+
|
|
226
|
+
return await test_read_recording.with_read_recording(
|
|
227
|
+
root,
|
|
228
|
+
sized,
|
|
229
|
+
async (recording) => await execute_vitest(sized, recording),
|
|
183
230
|
)
|
|
184
|
-
const result = await execa(PNPM, ['exec', 'vitest', ...vitest_arguments, ...sized], {
|
|
185
|
-
env: isolated_unit_environment(),
|
|
186
|
-
extendEnv: false,
|
|
187
|
-
stdio: 'inherit',
|
|
188
|
-
reject: false,
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
return result.exitCode ?? FAIL_EXIT_CODE
|
|
192
231
|
})
|
|
193
232
|
}
|
|
194
233
|
|
|
@@ -247,13 +286,6 @@ async function run_guarded_unit(
|
|
|
247
286
|
return await run_guarded_vitest(project_directory, ['run', ...extra_arguments])
|
|
248
287
|
}
|
|
249
288
|
|
|
250
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
251
|
-
const extra_arguments = process.argv.slice(ARGV_START)
|
|
252
|
-
const exit_code = await run_guarded_unit(process.cwd(), extra_arguments)
|
|
253
|
-
|
|
254
|
-
process.exit(exit_code)
|
|
255
|
-
}
|
|
256
|
-
|
|
257
289
|
const test_unit_guard = {
|
|
258
290
|
SKIP_MARKER,
|
|
259
291
|
guard_action,
|
|
@@ -265,6 +297,7 @@ const test_unit_guard = {
|
|
|
265
297
|
isolated_unit_environment,
|
|
266
298
|
run_guarded_unit,
|
|
267
299
|
run_guarded_vitest,
|
|
300
|
+
vitest_share,
|
|
268
301
|
}
|
|
269
302
|
|
|
270
303
|
export type { GuardAction }
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import { writeFile } from 'node:fs/promises'
|
|
3
|
+
|
|
4
|
+
// How many test files a unit run ran, handed from the unit reporter to the caller that named a file to
|
|
5
|
+
// receive it — `josh test:related`, which records it beside the scope it handed vitest
|
|
6
|
+
// (joshuafolkken/kit#4465). Its own shipped module: the reporter is kit-only and the setup-file list
|
|
7
|
+
// names files only, so neither can own a protocol a shipped reader shares.
|
|
8
|
+
|
|
9
|
+
// Names the file the run's test-file count is written to.
|
|
10
|
+
const COUNT_FILE_ENVIRONMENT = 'JOSH_UNIT_COUNT_FILE'
|
|
11
|
+
|
|
12
|
+
// Best-effort like the ledger: a run is never failed by the file it reports into.
|
|
13
|
+
async function write_count(count: number, target: string | undefined): Promise<void> {
|
|
14
|
+
if (target === undefined || target === '') return
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
await writeFile(target, String(count))
|
|
18
|
+
} catch {
|
|
19
|
+
// The caller reads a missing count as unknown.
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// A missing, empty or non-integer file is an unknown count, never zero.
|
|
24
|
+
function read_count(file: string): number | undefined {
|
|
25
|
+
try {
|
|
26
|
+
const text = readFileSync(file, 'utf8').trim()
|
|
27
|
+
const count = Number(text)
|
|
28
|
+
|
|
29
|
+
return text !== '' && Number.isSafeInteger(count) ? count : undefined
|
|
30
|
+
} catch {
|
|
31
|
+
return undefined
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const unit_count_file = { COUNT_FILE_ENVIRONMENT, read_count, write_count }
|
|
36
|
+
|
|
37
|
+
export { unit_count_file }
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { readdirSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { PLATFORM_TEMP_ROOT } from '#scripts/josh/platform-temporary'
|
|
4
|
+
import { process_identity } from '#scripts/josh/process-identity'
|
|
5
|
+
import { process_owner_schema, type ProcessOwner } from '#scripts/josh/process-owner'
|
|
6
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
7
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
8
|
+
|
|
9
|
+
// The run markers that count the unit runs in flight, and the division of the machine by that count —
|
|
10
|
+
// the part of the worker share `vitest.config.ts` reads (`vitest-config-workers.ts`).
|
|
11
|
+
//
|
|
12
|
+
// **Kept apart from `unit-worker-share.ts` because the config imports it** (joshuafolkken/kit#4572).
|
|
13
|
+
// Every module the vitest config imports is a whole-suite file (`whole-suite-files.ts`), and the
|
|
14
|
+
// capacity and claim bounds of the share change often; held here, only this stable part is one.
|
|
15
|
+
|
|
16
|
+
// A record that means something only while it exists, in the shape `stamp-file.ts` already keeps for
|
|
17
|
+
// the in-flight gate marker. Keyed by pid rather than by checkout: `josh gate`'s unit step and a
|
|
18
|
+
// `josh test:related` can be in flight in one checkout at once, and both of them are load.
|
|
19
|
+
const RUN_PREFIX = 'josh-unit-running-'
|
|
20
|
+
// Never below one: a share of zero would run no test at all and report the suite green.
|
|
21
|
+
const MIN_WORKERS = 1
|
|
22
|
+
// One run in flight is this run alone, which is the case that changes nothing.
|
|
23
|
+
const SOLO_RUNS = 1
|
|
24
|
+
|
|
25
|
+
// A marker is the writing process's identity and nothing else; a pid-only marker has an answer of its
|
|
26
|
+
// own below (`is_running`) rather than being rejected here.
|
|
27
|
+
type RunMarker = ProcessOwner
|
|
28
|
+
|
|
29
|
+
function marker_path(pid: number = process.pid): string {
|
|
30
|
+
return stamp_file.stamp_path(RUN_PREFIX, String(pid))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// **A marker is evidence, and the process behind it is the test.** A run killed outright leaves its
|
|
34
|
+
// file behind, and a count that trusted the file alone would hold every later run down to one worker
|
|
35
|
+
// for good — the failure mode `run-hold.ts` answers with an expiry, which cannot be sized here because
|
|
36
|
+
// a unit suite under six-way load already takes minutes. The process that writes this marker is the
|
|
37
|
+
// long-lived one, so unlike a `run:hold` record its identity is a liveness test rather than a note for
|
|
38
|
+
// the reader.
|
|
39
|
+
//
|
|
40
|
+
// **The pid alone was not that identity**. The section below already named
|
|
41
|
+
// what goes wrong — a reissued pid turns a leaked marker into a permanent phantom — and answered it by
|
|
42
|
+
// sweeping, which only ever collected the markers whose pid had *not* yet been reissued. Since the
|
|
43
|
+
// record now carries the writing process's start time beside its pid, a reissued pid is recognized as
|
|
44
|
+
// a different process and swept like any other dead one. A pid that is not positive is caught by the
|
|
45
|
+
// same check, inside `process_identity`: `process.kill(0, …)` addresses the caller's own process group
|
|
46
|
+
// rather than a process, so a truncated or hand-edited marker would otherwise answer "alive" forever.
|
|
47
|
+
//
|
|
48
|
+
// **"Cannot tell" counts as live here, which is the opposite of what the in-flight gate marker's
|
|
49
|
+
// readers do with it, and deliberately so.** A marker with no recorded start time — written before the
|
|
50
|
+
// field existed, or on a platform where it cannot be read — resolves toward *more* sharing: being
|
|
51
|
+
// wrong that way costs this run a narrower share of the machine, while being wrong the other way puts
|
|
52
|
+
// six unit suites on eleven cores, an oversubscription measured at a load
|
|
53
|
+
// average of 209.
|
|
54
|
+
function is_running(marker: RunMarker): boolean {
|
|
55
|
+
return process_identity.is_same_process(marker.pid, marker.process_start) !== false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function read_marker(source: string): RunMarker | undefined {
|
|
59
|
+
const raw = stamp_file.read_stamp_text(source)
|
|
60
|
+
|
|
61
|
+
if (raw === undefined) return undefined
|
|
62
|
+
|
|
63
|
+
const parsed = process_owner_schema.safeParse(json_value.parse_or_undefined(raw))
|
|
64
|
+
|
|
65
|
+
return parsed.success ? parsed.data : undefined
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// An unreadable temp directory answers "no other run", which is the direction that leaves behavior
|
|
69
|
+
// as it was rather than throttling a run on a guess. Unlike the network guard, being wrong here costs
|
|
70
|
+
// wall time and never a false result.
|
|
71
|
+
function marker_files(directory: string = PLATFORM_TEMP_ROOT): Array<string> {
|
|
72
|
+
try {
|
|
73
|
+
return readdirSync(directory).filter((name) => name.startsWith(RUN_PREFIX))
|
|
74
|
+
} catch {
|
|
75
|
+
return []
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// **A marker whose process is gone is removed, not merely skipped.** Skipping it is correct only until
|
|
80
|
+
// the operating system reissues that pid to something else, which on a machine left running for days
|
|
81
|
+
// it will — and from then on the phantom is counted as a live run for good, with every solo run held
|
|
82
|
+
// at one worker and `josh gate` announcing lanes that do not exist. `finally` in `with_run_marker`
|
|
83
|
+
// cannot prevent the leak, because the interrupt that produces it (Ctrl-C reaching the whole foreground
|
|
84
|
+
// group) does not unwind. Sweeping on read is what bounds it: the first later run collects it.
|
|
85
|
+
function sweep_marker(source: string): void {
|
|
86
|
+
try {
|
|
87
|
+
stamp_file.remove_stamp(source)
|
|
88
|
+
} catch {
|
|
89
|
+
/* not ours to remove; counting it out is the whole requirement */
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// **Only a marker that parsed to a dead pid is swept, and the unlink still cannot throw.** A marker
|
|
94
|
+
// this account may not read — another user's file on a sticky `/tmp` — is `undefined` here, and
|
|
95
|
+
// deleting on that answer would raise `EPERM` from a path with no `catch` between it and
|
|
96
|
+
// `announce_gate_plan`: an unreadable file belonging to somebody else would abort the gate outright,
|
|
97
|
+
// which is worse than the leak this sweep exists for. Unreadable therefore counts as not-live and is
|
|
98
|
+
// left alone, exactly as it was before the sweep existed.
|
|
99
|
+
function is_marker_live(source: string): boolean {
|
|
100
|
+
const marker = read_marker(source)
|
|
101
|
+
|
|
102
|
+
if (marker === undefined) return false
|
|
103
|
+
if (is_running(marker)) return true
|
|
104
|
+
|
|
105
|
+
sweep_marker(source)
|
|
106
|
+
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Every marker in the temp directory whose process is still alive. This run's own is deliberately not
|
|
111
|
+
// among them: both callers count *before* writing theirs, so the `+ 1` at the call site adds it.
|
|
112
|
+
function live_run_count(directory: string = PLATFORM_TEMP_ROOT): number {
|
|
113
|
+
return marker_files(directory).filter((name) => is_marker_live(path.join(directory, name))).length
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// **The gate claims its place before its unit step exists, and the child must not claim a second
|
|
117
|
+
// one.** `josh gate` counts the runs in flight and then spawns `josh test:unit`, so without this the
|
|
118
|
+
// marker appears a second or so after the count that needed it — and two lanes launched together, the
|
|
119
|
+
// shape `epicrun` produces, both read "nothing else is running" and both take the whole machine. The
|
|
120
|
+
// gate therefore marks itself around the whole run and passes this down through the environment; the
|
|
121
|
+
// guard inside the child sees it and marks nothing, because the two processes are one run.
|
|
122
|
+
const NESTED_KEY = 'JOSH_UNIT_RUN_MARKED'
|
|
123
|
+
const NESTED_VALUE = '1'
|
|
124
|
+
|
|
125
|
+
function is_nested_run(): boolean {
|
|
126
|
+
return process.env[NESTED_KEY] === NESTED_VALUE
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// **`undefined` at one run means "leave the choice where it was".** The gate then applies its own
|
|
130
|
+
// core reservation and the hook passes no flag at all, which is what both did before this existed.
|
|
131
|
+
function resolve_unit_workers(available_cores: number, runs: number): number | undefined {
|
|
132
|
+
if (runs <= SOLO_RUNS) return undefined
|
|
133
|
+
|
|
134
|
+
return Math.max(MIN_WORKERS, Math.floor(available_cores / runs))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// **The write failing is not a reason to fail the run.** A marker that could not be written costs the
|
|
138
|
+
// next run a wider share than it should have — the behavior that was there before — while a thrown
|
|
139
|
+
// error here would fail a unit suite over bookkeeping.
|
|
140
|
+
function mark_run_started(target: string): void {
|
|
141
|
+
try {
|
|
142
|
+
stamp_file.write_stamp(target, process_identity.own_fields())
|
|
143
|
+
} catch {
|
|
144
|
+
/* a missing marker costs a wide share, never a wrong result */
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const unit_run_marker = {
|
|
149
|
+
MIN_WORKERS,
|
|
150
|
+
NESTED_KEY,
|
|
151
|
+
NESTED_VALUE,
|
|
152
|
+
RUN_PREFIX,
|
|
153
|
+
SOLO_RUNS,
|
|
154
|
+
is_nested_run,
|
|
155
|
+
live_run_count,
|
|
156
|
+
mark_run_started,
|
|
157
|
+
marker_path,
|
|
158
|
+
read_marker,
|
|
159
|
+
resolve_unit_workers,
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export { unit_run_marker }
|