@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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, rmSync, statSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
4
|
+
import { atomic_write } from '#scripts/lib/atomic-write'
|
|
5
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
6
|
+
import { test_read_trace, type ReadRecords } from './test-read-trace'
|
|
7
|
+
|
|
8
|
+
// The test-read map: for every repository path a full unit run read, the modules that read it.
|
|
9
|
+
// `josh test:related` resolves a changed non-code file through it to the code files `vitest related`
|
|
10
|
+
// can walk, so a changed document runs the tests that read it rather than the whole suite.
|
|
11
|
+
//
|
|
12
|
+
// **The map is valid against the tree it was recorded on, and only that tree.** It records the
|
|
13
|
+
// commit and the files that differed from it, so the change a narrowing reads is the change since
|
|
14
|
+
// then. A tree whose own code changed what it reads has changed that code, and `vitest related`
|
|
15
|
+
// runs the tests importing it. **It lives in the git common directory**, which every lane worktree of
|
|
16
|
+
// one clone shares along with the commits it names, so one lane's full run narrows the next lane's.
|
|
17
|
+
// **One file per version** (joshuafolkken/kit#4423): a lane on an older kit writing its map leaves a
|
|
18
|
+
// newer lane's map in place, so a version bump no longer sends either to the whole suite.
|
|
19
|
+
|
|
20
|
+
interface ReadMap {
|
|
21
|
+
version: number
|
|
22
|
+
commit: string
|
|
23
|
+
// The files that differed from `commit` when the map was recorded, each with the digest of its
|
|
24
|
+
// content then (`input_fingerprint.of_files`), so one whose content has not moved since does not count as changed
|
|
25
|
+
// (joshuafolkken/kit#4425).
|
|
26
|
+
dirty: Record<string, string>
|
|
27
|
+
// The directories `commit` holds, so a directory new since then is told apart from one no test
|
|
28
|
+
// read — the map's own keys cannot say which, since an unread directory has none.
|
|
29
|
+
directories: Array<string>
|
|
30
|
+
readers: ReadRecords
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Bumped whenever the shape, what a reader means or how `dirty` is digested changes, so a map an older
|
|
34
|
+
// kit wrote reads as no map at all and the next full run writes it afresh. 6: `dirty` is
|
|
35
|
+
// `input-fingerprint.ts`'s digest of every changed file (joshuafolkken/kit#4497).
|
|
36
|
+
const MAP_VERSION = 6
|
|
37
|
+
|
|
38
|
+
const MAP_DIRECTORY = 'josh'
|
|
39
|
+
const MAP_FILE_STEM = 'test-read-map'
|
|
40
|
+
const RECORD_EXTENSION = '.json'
|
|
41
|
+
|
|
42
|
+
// A map file of another version no lane has written for this long belongs to no kit still running,
|
|
43
|
+
// and is removed by the next write: one week.
|
|
44
|
+
const STALE_AFTER_MS = 604_800_000
|
|
45
|
+
|
|
46
|
+
type ReadPair = [string, string]
|
|
47
|
+
|
|
48
|
+
function record_pairs(record: ReadRecords): Array<ReadPair> {
|
|
49
|
+
return Object.entries(record).flatMap(([read_path, readers]) =>
|
|
50
|
+
readers.map((reader): ReadPair => [read_path, reader]),
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function merge_records(records: ReadonlyArray<ReadRecords>): ReadRecords {
|
|
55
|
+
const merged = new Map<string, Set<string>>()
|
|
56
|
+
const pairs = records.flatMap((record) => record_pairs(record))
|
|
57
|
+
|
|
58
|
+
for (const [read_path, reader] of pairs) {
|
|
59
|
+
test_read_trace.add_reader(merged, read_path, reader)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return test_read_trace.to_records(merged)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function is_object(value: unknown): value is object {
|
|
66
|
+
return typeof value === 'object' && value !== null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function is_string_array(value: unknown): value is Array<string> {
|
|
70
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === 'string')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function is_read_records(value: unknown): value is ReadRecords {
|
|
74
|
+
return is_object(value) && Object.values(value).every(is_string_array)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function is_digest_record(value: unknown): value is Record<string, string> {
|
|
78
|
+
if (!is_object(value) || Array.isArray(value)) return false
|
|
79
|
+
|
|
80
|
+
return Object.values(value).every((digest) => typeof digest === 'string')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const FIELD_CHECKS: ReadonlyArray<[keyof ReadMap, (field: unknown) => boolean]> = [
|
|
84
|
+
['version', (field) => field === MAP_VERSION],
|
|
85
|
+
['commit', (field) => typeof field === 'string'],
|
|
86
|
+
['dirty', is_digest_record],
|
|
87
|
+
['directories', is_string_array],
|
|
88
|
+
['readers', is_read_records],
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
function is_read_map(value: unknown): value is ReadMap {
|
|
92
|
+
if (!is_object(value)) return false
|
|
93
|
+
|
|
94
|
+
return FIELD_CHECKS.every(([field, is_valid]) => is_valid(Reflect.get(value, field)))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// **The files whose content differs from the tree the map was recorded on** (joshuafolkken/kit#4425).
|
|
98
|
+
// `since` is every path that differs from `map.commit` now, and `current` the digest of every path
|
|
99
|
+
// that was dirty then. A path dirty then is changed only when its digest moved: counted by name, a
|
|
100
|
+
// lane's own change the map was recorded over read as changed on every later run, so a gate reused
|
|
101
|
+
// no green unit step whenever the lane held any code.
|
|
102
|
+
function changed_since_tree(
|
|
103
|
+
map: ReadMap,
|
|
104
|
+
since: ReadonlyArray<string>,
|
|
105
|
+
current: Readonly<Record<string, string>>,
|
|
106
|
+
): Array<string> {
|
|
107
|
+
const fresh = since.filter((file) => !Object.hasOwn(map.dirty, file))
|
|
108
|
+
const moved = Object.entries(map.dirty)
|
|
109
|
+
.filter(([file, digest]) => current[file] !== digest)
|
|
110
|
+
.map(([file]) => file)
|
|
111
|
+
|
|
112
|
+
return [...new Set([...fresh, ...moved])]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function parse_map(text: string): ReadMap | undefined {
|
|
116
|
+
const value = json_value.parse_or_undefined(text)
|
|
117
|
+
|
|
118
|
+
return is_read_map(value) ? value : undefined
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function parse_records(text: string): ReadRecords {
|
|
122
|
+
const value = json_value.parse_or_undefined(text)
|
|
123
|
+
|
|
124
|
+
return is_read_records(value) ? value : {}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Innermost first, ending at the root `.`.
|
|
128
|
+
function directories_above(relative: string): Array<string> {
|
|
129
|
+
const parent = path.dirname(relative)
|
|
130
|
+
|
|
131
|
+
if (parent === relative) return []
|
|
132
|
+
|
|
133
|
+
return [parent, ...directories_above(parent)]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// The directories on the file's path the recorded commit did not hold, innermost first. The root
|
|
137
|
+
// always existed.
|
|
138
|
+
function created_directories(
|
|
139
|
+
directories: ReadonlyArray<string>,
|
|
140
|
+
recorded: ReadonlySet<string>,
|
|
141
|
+
): Array<string> {
|
|
142
|
+
return directories.filter(
|
|
143
|
+
(directory) => directory !== test_read_trace.ROOT_ENTRY && !recorded.has(directory),
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// A changed file is read by whoever read it, listed its own directory or walked any directory above
|
|
148
|
+
// it. A directory new since the recording is also a new entry in the listing above it and a probe of
|
|
149
|
+
// it that now answers differently; a directory that already existed reads the same to both, whatever
|
|
150
|
+
// changed deeper down.
|
|
151
|
+
function lookup_keys(relative: string, recorded: ReadonlySet<string>): Array<string> {
|
|
152
|
+
const directories = directories_above(relative)
|
|
153
|
+
const created = created_directories(directories, recorded)
|
|
154
|
+
const listed = [
|
|
155
|
+
directories[0] ?? test_read_trace.ROOT_ENTRY,
|
|
156
|
+
...created.map((directory) => path.dirname(directory)),
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
return [
|
|
160
|
+
relative,
|
|
161
|
+
...created,
|
|
162
|
+
...listed.map((directory) => test_read_trace.read_key(directory, 'listing')),
|
|
163
|
+
...directories.map((directory) => test_read_trace.read_key(directory, 'walk')),
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function readers_of(map: ReadMap, relative: string): Array<string> {
|
|
168
|
+
const keys = lookup_keys(relative, new Set(map.directories))
|
|
169
|
+
|
|
170
|
+
return [...new Set(keys.flatMap((key) => map.readers[key] ?? []))]
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// **A directory the recorded tree held, inside which no recorded test listed, walked or read any
|
|
174
|
+
// entry** (joshuafolkken/kit#4303). A file added to it since is one no test reads, as surely as one
|
|
175
|
+
// the tree already held there: a test that builds a path into it reads some file there, and one that
|
|
176
|
+
// enumerates it lists it, both of which leave a key whose directory is this one.
|
|
177
|
+
function in_unread_directory(map: ReadMap, relative: string): boolean {
|
|
178
|
+
const directory = path.dirname(relative)
|
|
179
|
+
|
|
180
|
+
if (!map.directories.includes(directory)) return false
|
|
181
|
+
|
|
182
|
+
return Object.keys(map.readers).every((key) => path.dirname(key) !== directory)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function map_path(root: string, version: number = MAP_VERSION): string | undefined {
|
|
186
|
+
const common = git_common_directory.repository(root)
|
|
187
|
+
const name = `${MAP_FILE_STEM}.v${String(version)}${RECORD_EXTENSION}`
|
|
188
|
+
|
|
189
|
+
return common === undefined ? undefined : path.join(common, MAP_DIRECTORY, name)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Every version's map, the unversioned one kits before joshuafolkken/kit#4423 wrote included; a
|
|
193
|
+
// staging file ends in `.tmp`, not the extension.
|
|
194
|
+
function is_map_file(name: string): boolean {
|
|
195
|
+
return name.startsWith(MAP_FILE_STEM) && name.endsWith(RECORD_EXTENSION)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// A file another lane's write pruned meanwhile has no stat, and is not this write's to remove.
|
|
199
|
+
function is_stale(file_path: string, now: number): boolean {
|
|
200
|
+
const modified = statSync(file_path, { throwIfNoEntry: false })?.mtimeMs ?? now
|
|
201
|
+
|
|
202
|
+
return now - modified > STALE_AFTER_MS
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// The map just written is never stale, so it survives its own prune.
|
|
206
|
+
function prune_stale_maps(directory: string): void {
|
|
207
|
+
const now = Date.now()
|
|
208
|
+
const maps = readdirSync(directory)
|
|
209
|
+
.filter((name) => is_map_file(name))
|
|
210
|
+
.map((name) => path.join(directory, name))
|
|
211
|
+
|
|
212
|
+
for (const file_path of maps) {
|
|
213
|
+
if (is_stale(file_path, now)) rmSync(file_path, { force: true })
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function read_text(file_path: string): string | undefined {
|
|
218
|
+
try {
|
|
219
|
+
return readFileSync(file_path, 'utf8')
|
|
220
|
+
} catch {
|
|
221
|
+
return undefined
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function read_map(root: string): ReadMap | undefined {
|
|
226
|
+
const file_path = map_path(root)
|
|
227
|
+
const text = file_path === undefined ? undefined : read_text(file_path)
|
|
228
|
+
|
|
229
|
+
return text === undefined ? undefined : parse_map(text)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Written beside the target and renamed over it, so a lane reading the map while another lane
|
|
233
|
+
// replaces it reads one whole map or the other. It lands in its own version's file.
|
|
234
|
+
function write_map(root: string, map: ReadMap): void {
|
|
235
|
+
const file_path = map_path(root, map.version)
|
|
236
|
+
|
|
237
|
+
if (file_path === undefined) return
|
|
238
|
+
|
|
239
|
+
atomic_write.replace_file(file_path, JSON.stringify(map))
|
|
240
|
+
prune_stale_maps(path.dirname(file_path))
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Every worker writes its own files into the run's directory; this reads them all back.
|
|
244
|
+
function collect_records(directory: string): Array<ReadRecords> {
|
|
245
|
+
return readdirSync(directory)
|
|
246
|
+
.filter((name) => name.endsWith(RECORD_EXTENSION))
|
|
247
|
+
.map((name) => parse_records(read_text(path.join(directory, name)) ?? ''))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const test_read_map = {
|
|
251
|
+
MAP_VERSION,
|
|
252
|
+
changed_since_tree,
|
|
253
|
+
collect_records,
|
|
254
|
+
in_unread_directory,
|
|
255
|
+
map_path,
|
|
256
|
+
merge_records,
|
|
257
|
+
parse_map,
|
|
258
|
+
read_map,
|
|
259
|
+
readers_of,
|
|
260
|
+
write_map,
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export type { ReadMap }
|
|
264
|
+
export { test_read_map }
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from 'node:fs'
|
|
2
|
+
import { tmpdir } from 'node:os'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { input_fingerprint } from '#scripts/gate/input-fingerprint'
|
|
5
|
+
import { changed_paths } from '#scripts/git/changed-paths'
|
|
6
|
+
import { git_command } from '#scripts/git/git-command'
|
|
7
|
+
import { git_spawn } from '#scripts/git/git-spawn'
|
|
8
|
+
import { test_read_map, type ReadMap } from './test-read-map'
|
|
9
|
+
import { test_read_trace } from './test-read-trace'
|
|
10
|
+
|
|
11
|
+
// When a unit run records the test-read map, and how the records become one. **Only a run of the
|
|
12
|
+
// whole suite records**: a map is read as "nothing else reads this file", which a narrowed, sharded
|
|
13
|
+
// or filtered run cannot vouch for. **Only a green run replaces the map**: a failed test may have
|
|
14
|
+
// stopped before the read it would have made.
|
|
15
|
+
|
|
16
|
+
type RecordingEnvironment = Record<string, string>
|
|
17
|
+
|
|
18
|
+
const RUN_SUBCOMMAND = 'run'
|
|
19
|
+
|
|
20
|
+
// The one flag a whole-suite run still carries — the gate's worker cap, which sizes the run without
|
|
21
|
+
// narrowing it.
|
|
22
|
+
const WORKER_FLAG_PREFIX = '--maxWorkers'
|
|
23
|
+
|
|
24
|
+
const RECORD_DIRECTORY_PREFIX = 'josh-test-reads-'
|
|
25
|
+
|
|
26
|
+
function is_recordable(vitest_arguments: ReadonlyArray<string>): boolean {
|
|
27
|
+
const [subcommand, ...flags] = vitest_arguments
|
|
28
|
+
|
|
29
|
+
return subcommand === RUN_SUBCOMMAND && flags.every((flag) => flag.startsWith(WORKER_FLAG_PREFIX))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Every directory the commit holds, NUL-separated so a name git would quote reads as itself.
|
|
33
|
+
async function commit_directories(commit: string): Promise<Array<string>> {
|
|
34
|
+
const output = await git_spawn.read(['ls-tree', '-r', '-d', '--name-only', '-z', commit])
|
|
35
|
+
|
|
36
|
+
return output.split('\0').filter((listed) => listed.length > 0)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type TreeSnapshot = Pick<ReadMap, 'commit' | 'dirty' | 'directories'>
|
|
40
|
+
|
|
41
|
+
// The tree the run read: the commit, every file that differed from it with its content's digest, and
|
|
42
|
+
// the directories it holds. **Read before the run starts**: a digest taken after it would vouch for
|
|
43
|
+
// an edit made while the tests ran as content they read.
|
|
44
|
+
async function tree_snapshot(root: string): Promise<TreeSnapshot> {
|
|
45
|
+
const commit = await git_command.head_commit()
|
|
46
|
+
const dirty = input_fingerprint.of_files(root, await changed_paths.read_changed_since(commit))
|
|
47
|
+
|
|
48
|
+
return { commit, dirty, directories: await commit_directories(commit) }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// A map that cannot be written — no git, a read-only common directory — leaves the previous map in
|
|
52
|
+
// place, and a narrowing over a stale map is refused by the commit it names.
|
|
53
|
+
function save_map(root: string, directory: string, snapshot: TreeSnapshot): void {
|
|
54
|
+
try {
|
|
55
|
+
const readers = test_read_map.merge_records(test_read_map.collect_records(directory))
|
|
56
|
+
|
|
57
|
+
test_read_map.write_map(root, { version: test_read_map.MAP_VERSION, ...snapshot, readers })
|
|
58
|
+
} catch {
|
|
59
|
+
// The previous map stays; the run's own result is unaffected.
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function with_read_recording(
|
|
64
|
+
root: string,
|
|
65
|
+
vitest_arguments: ReadonlyArray<string>,
|
|
66
|
+
run: (environment: RecordingEnvironment) => Promise<number>,
|
|
67
|
+
): Promise<number> {
|
|
68
|
+
if (!is_recordable(vitest_arguments)) return await run({})
|
|
69
|
+
|
|
70
|
+
const directory = mkdtempSync(path.join(tmpdir(), RECORD_DIRECTORY_PREFIX))
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
// Settled rather than awaited, so a tree git cannot read records no map and fails no run.
|
|
74
|
+
const [tree] = await Promise.allSettled([tree_snapshot(root)])
|
|
75
|
+
const exit_code = await run({
|
|
76
|
+
[test_read_trace.RECORD_DIRECTORY_KEY]: directory,
|
|
77
|
+
[test_read_trace.ROOT_KEY]: root,
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
if (exit_code === 0 && tree.status === 'fulfilled') save_map(root, directory, tree.value)
|
|
81
|
+
|
|
82
|
+
return exit_code
|
|
83
|
+
} finally {
|
|
84
|
+
rmSync(directory, { recursive: true, force: true })
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const test_read_recording = { is_recordable, with_read_recording }
|
|
89
|
+
|
|
90
|
+
export type { RecordingEnvironment }
|
|
91
|
+
export { test_read_recording }
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
|
|
4
|
+
// What one recorded read says, decided without touching `fs`: which repository path was read, and
|
|
5
|
+
// which module read it. `test-read-capture.ts`, armed by the `test-read-recorder.ts` setup file,
|
|
6
|
+
// feeds this from inside every unit worker; everything here is pure so the decisions are testable without patching `fs`.
|
|
7
|
+
//
|
|
8
|
+
// **The reader is the outermost repository frame on the stack, not the test file alone.** Under
|
|
9
|
+
// `isolate: false` a module that reads a document at load time is evaluated once per worker, so its
|
|
10
|
+
// read lands on whichever test imported it first. Recording the module whose evaluation made the read
|
|
11
|
+
// lets `vitest related` widen the read to every test that imports it, on any worker. A read a test
|
|
12
|
+
// makes has the test outermost, so a shared helper it reads through — every test importing it — is
|
|
13
|
+
// never the reader (joshuafolkken/kit#4417). The test file is recorded beside it, because an async
|
|
14
|
+
// callback (a directory walk inside a dependency) leaves no repository frame at all.
|
|
15
|
+
|
|
16
|
+
type ReadRecords = Record<string, Array<string>>
|
|
17
|
+
|
|
18
|
+
// The worker setup file and the run that starts it agree on these two names and nothing else. They
|
|
19
|
+
// live here rather than beside the map because the setup file is loaded before any test's
|
|
20
|
+
// `vi.mock`: whatever it imports, no test can mock.
|
|
21
|
+
const RECORD_DIRECTORY_KEY = 'JOSH_TEST_READS_DIRECTORY'
|
|
22
|
+
const ROOT_KEY = 'JOSH_TEST_READS_ROOT'
|
|
23
|
+
|
|
24
|
+
const FILE_URL_PREFIX = 'file://'
|
|
25
|
+
const NODE_MODULES = 'node_modules'
|
|
26
|
+
const GIT_DIRECTORY = '.git'
|
|
27
|
+
const ROOT_ENTRY = '.'
|
|
28
|
+
|
|
29
|
+
// **What a read depends on is decided by the call, not by the path alone.** Reading or probing a
|
|
30
|
+
// path depends on that path; listing a directory depends on its direct entries; a recursive listing
|
|
31
|
+
// depends on everything beneath it. The two directory kinds are keyed with a glob-shaped suffix so
|
|
32
|
+
// the map keeps one shape: `scripts/*` is a listing of `scripts`, `scripts/**` a walk over it, and a
|
|
33
|
+
// listing of the root is `*`.
|
|
34
|
+
type ReadKind = 'path' | 'listing' | 'walk'
|
|
35
|
+
|
|
36
|
+
const LISTING_READS: ReadonlySet<string> = new Set([
|
|
37
|
+
'readdir',
|
|
38
|
+
'readdirSync',
|
|
39
|
+
'opendir',
|
|
40
|
+
'opendirSync',
|
|
41
|
+
])
|
|
42
|
+
|
|
43
|
+
const KIND_SUFFIX: Record<Exclude<ReadKind, 'path'>, string> = { listing: '*', walk: '**' }
|
|
44
|
+
|
|
45
|
+
function is_recursive(options: unknown): boolean {
|
|
46
|
+
return (
|
|
47
|
+
typeof options === 'object' && options !== null && Reflect.get(options, 'recursive') === true
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The kind of read an `fs` call by this name makes, given its second argument.
|
|
52
|
+
function read_kind(name: string, options: unknown): ReadKind {
|
|
53
|
+
if (!LISTING_READS.has(name)) return 'path'
|
|
54
|
+
|
|
55
|
+
return is_recursive(options) ? 'walk' : 'listing'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function read_key(relative: string, kind: ReadKind): string {
|
|
59
|
+
return kind === 'path' ? relative : path.join(relative, KIND_SUFFIX[kind])
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// The file a call site's script name points at — an absolute path or a `file://` URL — or
|
|
63
|
+
// `undefined` for a `node:` internal or an evaluated string.
|
|
64
|
+
function script_path(script_name: string): string | undefined {
|
|
65
|
+
if (script_name.startsWith(FILE_URL_PREFIX)) return fileURLToPath(script_name)
|
|
66
|
+
|
|
67
|
+
return path.isAbsolute(script_name) ? script_name : undefined
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function is_outside(relative: string): boolean {
|
|
71
|
+
return relative.startsWith('..') || path.isAbsolute(relative)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function is_ignored(relative: string): boolean {
|
|
75
|
+
const segments = relative.split(path.sep)
|
|
76
|
+
|
|
77
|
+
return segments.includes(NODE_MODULES) || segments[0] === GIT_DIRECTORY
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// A path relative to the root, or `undefined` when it lies outside it or inside a directory no test
|
|
81
|
+
// result depends on. The root itself is `.`.
|
|
82
|
+
function repository_path(root: string, file_path: string): string | undefined {
|
|
83
|
+
const relative = path.relative(root, file_path)
|
|
84
|
+
|
|
85
|
+
if (relative === '') return ROOT_ENTRY
|
|
86
|
+
|
|
87
|
+
return is_outside(relative) || is_ignored(relative) ? undefined : relative
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// The path an `fs` call names. A descriptor or a buffer names no path this map can key on.
|
|
91
|
+
function read_target(argument: unknown, cwd: string): string | undefined {
|
|
92
|
+
if (typeof argument === 'string') return path.resolve(cwd, argument)
|
|
93
|
+
if (argument instanceof URL) return fileURLToPath(argument)
|
|
94
|
+
|
|
95
|
+
return undefined
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface ReaderQuery {
|
|
99
|
+
root: string
|
|
100
|
+
// The script name of every call site, innermost first.
|
|
101
|
+
scripts: ReadonlyArray<string>
|
|
102
|
+
// The recorder's own file, which is always the top frame and never the reader.
|
|
103
|
+
recorder: string
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function frame_reader(query: ReaderQuery, script_name: string): string | undefined {
|
|
107
|
+
const file_path = script_path(script_name)
|
|
108
|
+
|
|
109
|
+
if (file_path === undefined || file_path === query.recorder) return undefined
|
|
110
|
+
|
|
111
|
+
const relative = repository_path(query.root, file_path)
|
|
112
|
+
|
|
113
|
+
return relative === ROOT_ENTRY ? undefined : relative
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function stack_reader(query: ReaderQuery): string | undefined {
|
|
117
|
+
return query.scripts
|
|
118
|
+
.map((script_name) => frame_reader(query, script_name))
|
|
119
|
+
.findLast((reader) => reader !== undefined)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function add_reader(records: Map<string, Set<string>>, read_path: string, reader: string): void {
|
|
123
|
+
const readers = records.get(read_path) ?? new Set<string>()
|
|
124
|
+
|
|
125
|
+
readers.add(reader)
|
|
126
|
+
records.set(read_path, readers)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function to_records(records: ReadonlyMap<string, ReadonlySet<string>>): ReadRecords {
|
|
130
|
+
return Object.fromEntries([...records].map(([read_path, readers]) => [read_path, [...readers]]))
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const test_read_trace = {
|
|
134
|
+
RECORD_DIRECTORY_KEY,
|
|
135
|
+
ROOT_ENTRY,
|
|
136
|
+
ROOT_KEY,
|
|
137
|
+
add_reader,
|
|
138
|
+
read_key,
|
|
139
|
+
read_kind,
|
|
140
|
+
read_target,
|
|
141
|
+
repository_path,
|
|
142
|
+
script_path,
|
|
143
|
+
stack_reader,
|
|
144
|
+
to_records,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export type { ReadKind, ReaderQuery, ReadRecords }
|
|
148
|
+
export { test_read_trace }
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { test_red } from './test-red'
|
|
4
|
+
|
|
5
|
+
// The `josh test:red` entry, kept apart from `test-red.ts` because `test-red-commit.ts` imports that
|
|
6
|
+
// one: a bundle is one file, so a main guard there would fire for every command that carries it
|
|
7
|
+
// (joshuafolkken/kit#4186).
|
|
8
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
9
|
+
const ARGV_OFFSET = 2
|
|
10
|
+
|
|
11
|
+
process.exitCode = await test_red.main(process.argv.slice(ARGV_OFFSET))
|
|
12
|
+
}
|
package/scripts/test/test-red.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { existsSync } from 'node:fs'
|
|
2
|
-
import {
|
|
2
|
+
import { readFile, rm } from 'node:fs/promises'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { fileURLToPath } from 'node:url'
|
|
5
4
|
import { base_tree, type BaseTree } from '#scripts/git/base-tree'
|
|
6
5
|
import { change_base } from '#scripts/git/change-base'
|
|
7
6
|
import { changed_paths } from '#scripts/git/changed-paths'
|
|
@@ -16,7 +15,6 @@ import { test_red_logic, type RedVerdict } from './test-red-logic'
|
|
|
16
15
|
// (`base-tree.ts`). The tests are copied in from the working tree, so what runs is the new test
|
|
17
16
|
// against the old code.
|
|
18
17
|
|
|
19
|
-
const ARGV_OFFSET = 2
|
|
20
18
|
const TREE_PREFIX = 'josh-test-red-'
|
|
21
19
|
const REPORT_NAME = 'report.json'
|
|
22
20
|
const VITEST_BIN = path.join(base_tree.NODE_MODULES, '.bin', 'vitest')
|
|
@@ -33,22 +31,6 @@ function changed_tests(paths: ReadonlyArray<string>): Array<string> {
|
|
|
33
31
|
return test_red_logic.unit_test_files(paths).filter((file) => existsSync(file))
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
async function copy_one(tree: string, file: string): Promise<void> {
|
|
37
|
-
const target = path.join(tree, file)
|
|
38
|
-
|
|
39
|
-
await mkdir(path.dirname(target), { recursive: true })
|
|
40
|
-
await copyFile(file, target)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Each file has its own target, and a recursive `mkdir` tolerates a sibling creating the same parent.
|
|
44
|
-
async function copy_in(tree: string, files: ReadonlyArray<string>): Promise<void> {
|
|
45
|
-
await Promise.all(
|
|
46
|
-
files.map(async (file) => {
|
|
47
|
-
await copy_one(tree, file)
|
|
48
|
-
}),
|
|
49
|
-
)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
34
|
function reporter_arguments(report: string): Array<string> {
|
|
53
35
|
// The plain `--outputFile`, not `--outputFile.json`: a config that sets `test.outputFile` as a string
|
|
54
36
|
// wins over the keyed form, which would send the report into the tree and read every run `no-test`.
|
|
@@ -59,16 +41,20 @@ async function read_report(report: string): Promise<string> {
|
|
|
59
41
|
return existsSync(report) ? await readFile(report, 'utf8') : ''
|
|
60
42
|
}
|
|
61
43
|
|
|
62
|
-
// The verdict of one run
|
|
44
|
+
// The verdict of one run over `selection` — `run <files>`, or `related <file> --run` for
|
|
45
|
+
// `josh test:pinned`. `--passWithNoTests` keeps "the filter matched nothing" from reading as a
|
|
63
46
|
// failure, and the JSON report — written beside the tree, never into it — says whether anything ran at
|
|
64
47
|
// all, so a file the old config excludes is `no-test` rather than a `green` that refuses a correct fix.
|
|
65
|
-
// A test that ran and broke, or a file that could not load against the old code, makes it `red`.
|
|
48
|
+
// A test that ran and broke, or a file that could not load against the old code, makes it `red`. The
|
|
49
|
+
// report is removed first, so a run that writes none never reads the one before it.
|
|
66
50
|
async function verdict_in(
|
|
67
51
|
{ parent, tree }: BaseTree,
|
|
68
|
-
|
|
52
|
+
selection: ReadonlyArray<string>,
|
|
69
53
|
): Promise<RedVerdict> {
|
|
70
54
|
const report = path.join(parent, REPORT_NAME)
|
|
71
|
-
const vitest_args = [
|
|
55
|
+
const vitest_args = [...selection, '--passWithNoTests', ...reporter_arguments(report)]
|
|
56
|
+
|
|
57
|
+
await rm(report, { force: true })
|
|
72
58
|
const result = await execa(path.join(tree, VITEST_BIN), vitest_args, {
|
|
73
59
|
cwd: tree,
|
|
74
60
|
env: git_location_environment.location_free_environment(),
|
|
@@ -82,9 +68,9 @@ async function verdict_in(
|
|
|
82
68
|
|
|
83
69
|
async function verdict_on(base: string, files: ReadonlyArray<string>): Promise<RedVerdict> {
|
|
84
70
|
return await base_tree.with_tree(TREE_PREFIX, base, async (pre_fix) => {
|
|
85
|
-
await copy_in(pre_fix.tree, files)
|
|
71
|
+
await base_tree.copy_in(pre_fix.tree, files)
|
|
86
72
|
|
|
87
|
-
return await verdict_in(pre_fix, files)
|
|
73
|
+
return await verdict_in(pre_fix, ['run', ...files])
|
|
88
74
|
})
|
|
89
75
|
}
|
|
90
76
|
|
|
@@ -117,11 +103,7 @@ async function main(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
117
103
|
return 0
|
|
118
104
|
}
|
|
119
105
|
|
|
120
|
-
|
|
121
|
-
process.exitCode = await main(process.argv.slice(ARGV_OFFSET))
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const test_red = { run }
|
|
106
|
+
const test_red = { main, run, verdict_in }
|
|
125
107
|
|
|
126
108
|
export type { RedRun }
|
|
127
109
|
export { test_red }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { changed_file_scope } from '#scripts/git/changed-file-scope'
|
|
4
|
+
import { run_ship_removed_rows } from '#scripts/run/ship/run-ship-removed-rows'
|
|
5
|
+
import { test_related } from './test-related'
|
|
6
|
+
|
|
7
|
+
// The `josh test:related` entry, kept apart from `test-related.ts` because `check-inputs.ts` imports
|
|
8
|
+
// that one: a bundle is one file, so a main guard there would fire for every command that carries it
|
|
9
|
+
// (joshuafolkken/kit#4186). A green run then shows the tests the change removed, the one place a run
|
|
10
|
+
// meets them before `josh ship` (joshuafolkken/kit#4563).
|
|
11
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
12
|
+
const exit_code = await test_related.run_related_tests(
|
|
13
|
+
process.argv.slice(changed_file_scope.ARGV_START),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if (exit_code === 0) await run_ship_removed_rows.surface()
|
|
17
|
+
process.exitCode = exit_code
|
|
18
|
+
}
|