@joshuafolkken/kit 1.1784.0 → 1.2116.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +60 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +386 -360
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +16 -9
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
2
|
+
import { SPLIT_ROUTE_LABEL } from '#scripts/issue/issue-labels'
|
|
3
|
+
import { issue_read } from '#scripts/issue/issue-read'
|
|
4
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
5
|
+
import {
|
|
6
|
+
lane_ledger,
|
|
7
|
+
type LedgerEntry,
|
|
8
|
+
type SplitFiledEntry,
|
|
9
|
+
type SplitNoticeEntry,
|
|
10
|
+
} from '#scripts/lane/lane-ledger'
|
|
11
|
+
import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
|
|
12
|
+
import { split_assess } from './split-assess'
|
|
13
|
+
|
|
14
|
+
// **What answers a split notice** (joshuafolkken/kit#4695). Of the lanes the notice reached, none split
|
|
15
|
+
// and none recorded why it stayed one Issue (joshuafolkken/kit#4676): the notice asked, and nothing
|
|
16
|
+
// checked. The pre-gate `josh run:cut` now does. A noticed Issue passes once it has either answer:
|
|
17
|
+
//
|
|
18
|
+
// - **a split child** — a `josh issue:file --route split` filed from its lane, recorded in the lane
|
|
19
|
+
// ledger as the filing lands;
|
|
20
|
+
// - **a reason** — a trusted Issue comment carrying the filing's own reason line
|
|
21
|
+
// (`split_assess.REASON_PREFIX`), so one declaration reads the same at filing and before the gate.
|
|
22
|
+
|
|
23
|
+
const { REASON_PREFIX } = split_assess
|
|
24
|
+
const NOTICE_SECTION = `split-assessment.md → "${split_assess.NOTICE_SECTION}"`
|
|
25
|
+
const UNREAD_NOTE = 'Its comments could not be read, so no recorded reason was found. '
|
|
26
|
+
|
|
27
|
+
function is_notice(entry: LedgerEntry): entry is SplitNoticeEntry {
|
|
28
|
+
return entry.kind === lane_ledger.KIND.SPLIT_NOTICE
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function is_split_child(entry: LedgerEntry): entry is SplitFiledEntry {
|
|
32
|
+
return entry.kind === lane_ledger.KIND.SPLIT_FILED
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// The ledger's split notices, oldest first — `josh lane:stats` counts the lanes they reached.
|
|
36
|
+
function notices(entries: ReadonlyArray<LedgerEntry>): ReadonlyArray<SplitNoticeEntry> {
|
|
37
|
+
return entries.filter((entry) => is_notice(entry))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// The Issues whose lane filed a split child.
|
|
41
|
+
function split_issues(entries: ReadonlyArray<LedgerEntry>): ReadonlySet<number> {
|
|
42
|
+
return new Set(entries.filter((entry) => is_split_child(entry)).map((entry) => entry.issue))
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function is_reason_line(line: string): boolean {
|
|
46
|
+
const text = line.trim()
|
|
47
|
+
|
|
48
|
+
return text.startsWith(REASON_PREFIX) && text !== REASON_PREFIX
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function has_reason(bodies: ReadonlyArray<string>): boolean {
|
|
52
|
+
return bodies.some((body) => body.split('\n').some((line) => is_reason_line(line)))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The trusted comments' bodies, or `undefined` when the listing could not be read.
|
|
56
|
+
async function trusted_comments(issue: number): Promise<ReadonlyArray<string> | undefined> {
|
|
57
|
+
const json = await git_gh_issue_read.issue_list_comments(String(issue))
|
|
58
|
+
const comments = await issue_read.parse_comments(json)
|
|
59
|
+
|
|
60
|
+
return comments === undefined ? undefined : issue_read.trusted_bodies(comments)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function refusal_text(notice: SplitNoticeEntry, bodies: ReadonlyArray<string> | undefined): string {
|
|
64
|
+
const counted = `${String(notice.files)} file(s), ${String(notice.lines)} line(s), tests excluded`
|
|
65
|
+
const unread = bodies === undefined ? UNREAD_NOTE : ''
|
|
66
|
+
const answers = `post an Issue comment with the line \`${REASON_PREFIX} <理由>\`, or file the rest with \`pnpm josh issue:file --route split\``
|
|
67
|
+
|
|
68
|
+
return `${session_cite.issue(notice.issue)} got the split notice (${counted}) and has neither a recorded reason nor a split child. ${unread}Either ${answers}, then run \`pnpm josh run:cut ${String(notice.issue)}\` again — ${NOTICE_SECTION}`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// The refusal for a noticed Issue that has no answer yet, else `undefined`. The ledger is read first,
|
|
72
|
+
// so an Issue the notice never reached costs no GitHub read.
|
|
73
|
+
async function refusal(
|
|
74
|
+
issue: number,
|
|
75
|
+
entries: ReadonlyArray<LedgerEntry>,
|
|
76
|
+
): Promise<string | undefined> {
|
|
77
|
+
const notice = notices(entries).findLast((entry) => entry.issue === issue)
|
|
78
|
+
|
|
79
|
+
if (notice === undefined || split_issues(entries).has(issue)) return undefined
|
|
80
|
+
const bodies = await trusted_comments(issue)
|
|
81
|
+
|
|
82
|
+
return bodies !== undefined && has_reason(bodies) ? undefined : refusal_text(notice, bodies)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The refusal against this repository's lane ledger; outside a repository there is none to read.
|
|
86
|
+
async function ledger_refusal(issue: number): Promise<string | undefined> {
|
|
87
|
+
const ledger = await lane_ledger.target()
|
|
88
|
+
|
|
89
|
+
return ledger === undefined ? undefined : await refusal(issue, lane_ledger.read_entries(ledger))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface Filing {
|
|
93
|
+
route: string | undefined
|
|
94
|
+
found_during: string | undefined
|
|
95
|
+
child: string
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// What `josh issue:file` just filed: a split child is recorded against the lane it was found in. Any
|
|
99
|
+
// other route, and a filing found in no lane, record nothing.
|
|
100
|
+
async function record_child({ route, found_during, child }: Filing): Promise<void> {
|
|
101
|
+
if (route !== SPLIT_ROUTE_LABEL || found_during === undefined) return
|
|
102
|
+
await lane_ledger_write.record_split_filed({ issue: Number(found_during), child })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const split_resolution = { ledger_refusal, notices, record_child, refusal, split_issues }
|
|
106
|
+
|
|
107
|
+
export { split_resolution }
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { git_spawn } from '#scripts/git/git-spawn'
|
|
4
|
+
import { test_declared_logic } from './test-declared-logic'
|
|
5
|
+
import { whole_suite_files } from './whole-suite-files'
|
|
6
|
+
|
|
7
|
+
// **The test files that import a module directly, read off their text** (joshuafolkken/kit#5122). A
|
|
8
|
+
// file every test imports (`whole_suite_files.EVERY_TEST_IMPORTS`) sends `vitest related` to the whole
|
|
9
|
+
// suite, so `josh test:related` and the `josh test:pinned` probe hand vitest the test files importing it
|
|
10
|
+
// directly instead. The whole suite still runs once, in the gate's `test:unit` and in every CI shard.
|
|
11
|
+
//
|
|
12
|
+
// The same reading decides which heavy test files a scoped run keeps (`related-heavy-tests.ts`).
|
|
13
|
+
|
|
14
|
+
const PACKAGE_FILE = 'package.json'
|
|
15
|
+
const WILDCARD = '*'
|
|
16
|
+
const CURRENT_DIRECTORY_PREFIX = './'
|
|
17
|
+
const NUL = '\0'
|
|
18
|
+
|
|
19
|
+
// The module specifiers a source names in a static or dynamic import, an export-from or a `vi.mock`.
|
|
20
|
+
const SPECIFIER_PATTERN = /(?:\bfrom\s+|\bimport\s*\(\s*|\bimport\s+|\bmock\(\s*)["']([^"']+)["']/gu
|
|
21
|
+
|
|
22
|
+
type ImportMap = Readonly<Record<string, string>>
|
|
23
|
+
|
|
24
|
+
interface SourceReader {
|
|
25
|
+
imports: ImportMap
|
|
26
|
+
read_source: (file: string) => string | undefined
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Repository-relative, `/`-separated and without its extension — the one key a specifier and a changed
|
|
30
|
+
// file are compared by, since an import names `./thing`, `./thing.ts` or `./thing.js` alike.
|
|
31
|
+
function module_key(file: string): string {
|
|
32
|
+
const posix = file.split(path.sep).join(path.posix.sep)
|
|
33
|
+
|
|
34
|
+
return posix.slice(0, posix.length - path.posix.extname(posix).length)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function specifiers_of(source: string): Array<string> {
|
|
38
|
+
return [...source.matchAll(SPECIFIER_PATTERN)].flatMap((match) => match.slice(1))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function alias_target(specifier: string, imports: ImportMap): string | undefined {
|
|
42
|
+
const exact = imports[specifier]
|
|
43
|
+
|
|
44
|
+
if (exact !== undefined) return exact
|
|
45
|
+
|
|
46
|
+
const key = Object.keys(imports).find(
|
|
47
|
+
(pattern) => pattern.endsWith(WILDCARD) && specifier.startsWith(pattern.slice(0, -1)),
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
if (key === undefined) return undefined
|
|
51
|
+
|
|
52
|
+
return imports[key]?.split(WILDCARD).join(specifier.slice(key.length - 1))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function relative_target(specifier: string, from: string): string {
|
|
56
|
+
return path.posix.join(path.posix.dirname(from), specifier)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// The repository-relative module key a specifier names, or `undefined` for a package import.
|
|
60
|
+
function resolve_specifier(
|
|
61
|
+
specifier: string,
|
|
62
|
+
from: string,
|
|
63
|
+
imports: ImportMap,
|
|
64
|
+
): string | undefined {
|
|
65
|
+
if (specifier.startsWith('.')) return module_key(relative_target(specifier, from))
|
|
66
|
+
|
|
67
|
+
const target = alias_target(specifier, imports)
|
|
68
|
+
|
|
69
|
+
if (target === undefined) return undefined
|
|
70
|
+
|
|
71
|
+
return module_key(path.posix.normalize(target.replace(CURRENT_DIRECTORY_PREFIX, '')))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Whether `source`, the text of `from`, imports one of the `scoped` module keys directly.
|
|
75
|
+
function names_any(
|
|
76
|
+
source: string,
|
|
77
|
+
from: string,
|
|
78
|
+
scoped: ReadonlySet<string>,
|
|
79
|
+
imports: ImportMap,
|
|
80
|
+
): boolean {
|
|
81
|
+
return specifiers_of(source).some((specifier) => {
|
|
82
|
+
const resolved = resolve_specifier(specifier, from, imports)
|
|
83
|
+
|
|
84
|
+
return resolved !== undefined && scoped.has(resolved)
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function read_imports(root: string): ImportMap {
|
|
89
|
+
try {
|
|
90
|
+
const parsed: unknown = JSON.parse(readFileSync(path.join(root, PACKAGE_FILE), 'utf8'))
|
|
91
|
+
const imports: unknown = Reflect.get(new Object(parsed), 'imports')
|
|
92
|
+
|
|
93
|
+
if (typeof imports !== 'object' || imports === null) return {}
|
|
94
|
+
|
|
95
|
+
// A conditional entry (`{ "node": … }`) names no single file, so it resolves nothing.
|
|
96
|
+
return Object.fromEntries(
|
|
97
|
+
Object.entries(imports).filter(
|
|
98
|
+
(entry): entry is [string, string] => typeof entry[1] === 'string',
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
} catch {
|
|
102
|
+
return {}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function read_source_at(root: string, file: string): string | undefined {
|
|
107
|
+
try {
|
|
108
|
+
return readFileSync(path.join(root, file), 'utf8')
|
|
109
|
+
} catch {
|
|
110
|
+
return undefined
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function source_reader(root: string): SourceReader {
|
|
115
|
+
return { imports: read_imports(root), read_source: (file) => read_source_at(root, file) }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The test files the work tree at `root` holds, tracked or not but not ignored, repository-relative.
|
|
119
|
+
async function test_files(root: string): Promise<Array<string>> {
|
|
120
|
+
const listed = await git_spawn.read(['-C', root, 'ls-files', '-coz', '--exclude-standard'])
|
|
121
|
+
|
|
122
|
+
return listed.split(NUL).filter((file) => test_declared_logic.is_test_file(file))
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// The test files of `tests` importing `file` directly; an unreadable one imports nothing.
|
|
126
|
+
function importers_among(
|
|
127
|
+
file: string,
|
|
128
|
+
tests: ReadonlyArray<string>,
|
|
129
|
+
reader: SourceReader,
|
|
130
|
+
): Array<string> {
|
|
131
|
+
const scoped = new Set([module_key(file)])
|
|
132
|
+
|
|
133
|
+
return tests.filter((test) => {
|
|
134
|
+
const source = reader.read_source(test)
|
|
135
|
+
|
|
136
|
+
return source !== undefined && names_any(source, test, scoped, reader.imports)
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function every_test_imports_of(files: ReadonlyArray<string>): Array<string> {
|
|
141
|
+
return files.filter((file) => whole_suite_files.EVERY_TEST_IMPORTS.has(path.normalize(file)))
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Whether a command argument, relative to the working directory or absolute, is a file every test imports.
|
|
145
|
+
function is_every_test_import(root: string, argument: string): boolean {
|
|
146
|
+
return whole_suite_files.EVERY_TEST_IMPORTS.has(path.relative(root, path.resolve(argument)))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// For each of `files`, the test files in the work tree at `root` importing it directly; a file no test
|
|
150
|
+
// imports directly maps to none.
|
|
151
|
+
async function importers_of(
|
|
152
|
+
root: string,
|
|
153
|
+
files: ReadonlyArray<string>,
|
|
154
|
+
): Promise<Map<string, Array<string>>> {
|
|
155
|
+
if (files.length === 0) return new Map()
|
|
156
|
+
|
|
157
|
+
const tests = await test_files(root)
|
|
158
|
+
const reader = source_reader(root)
|
|
159
|
+
|
|
160
|
+
return new Map(files.map((file) => [file, importers_among(file, tests, reader)]))
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// `importers_of` for the `files` every test imports; any other file is left out, for vitest to walk
|
|
164
|
+
// its graph.
|
|
165
|
+
async function every_test_importers(
|
|
166
|
+
root: string,
|
|
167
|
+
files: ReadonlyArray<string>,
|
|
168
|
+
): Promise<Map<string, Array<string>>> {
|
|
169
|
+
return await importers_of(root, every_test_imports_of(files))
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const direct_importers = {
|
|
173
|
+
every_test_importers,
|
|
174
|
+
every_test_imports_of,
|
|
175
|
+
importers_of,
|
|
176
|
+
is_every_test_import,
|
|
177
|
+
module_key,
|
|
178
|
+
names_any,
|
|
179
|
+
resolve_specifier,
|
|
180
|
+
source_reader,
|
|
181
|
+
specifiers_of,
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type { ImportMap, SourceReader }
|
|
185
|
+
export { direct_importers }
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { git_command } from '#scripts/git/git-command'
|
|
3
|
+
import { file_reader } from '#scripts/lib/read-file'
|
|
4
|
+
|
|
5
|
+
// **`tools/test/pure-files.ts` is a whole-suite file only for what is not its entries**
|
|
6
|
+
// (joshuafolkken/kit#5001). The vitest config imports it, so `vitest related` widens to every test on
|
|
7
|
+
// it, but an entry added, removed or rewritten moves only that test file between the pure and the
|
|
8
|
+
// isolated project. A change made of entry lines alone therefore reaches the moved entries and the two
|
|
9
|
+
// tests that hold the list to the classifier; any other line — an import, the export — still runs the
|
|
10
|
+
// whole suite.
|
|
11
|
+
|
|
12
|
+
const PURE_FILES_PATH = path.join('tools', 'test', 'pure-files.ts')
|
|
13
|
+
const LIST_TESTS: ReadonlyArray<string> = [
|
|
14
|
+
path.join('tools', 'test', 'pure-files.test.ts'),
|
|
15
|
+
path.join('tools', 'test', 'classify-isolation.test.ts'),
|
|
16
|
+
]
|
|
17
|
+
const ENTRY_LINE = /^\t'(?<entry>[^']+)',$/u
|
|
18
|
+
|
|
19
|
+
function entry_of(line: string): string | undefined {
|
|
20
|
+
return ENTRY_LINE.exec(line)?.groups?.['entry']
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function lines_of(text: string): Array<string> {
|
|
24
|
+
return text.trimEnd().split('\n')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function frame_of(text: string): string {
|
|
28
|
+
return lines_of(text)
|
|
29
|
+
.filter((line) => entry_of(line) === undefined)
|
|
30
|
+
.join('\n')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function entries_of(text: string): Set<string> {
|
|
34
|
+
return new Set(lines_of(text).flatMap((line) => entry_of(line) ?? []))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function missing_from(entries: ReadonlySet<string>, other: ReadonlySet<string>): Array<string> {
|
|
38
|
+
return [...entries].filter((entry) => !other.has(entry))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The entries one text holds and the other does not, or `undefined` when anything but entry lines
|
|
42
|
+
// differs — the answer that keeps the whole suite.
|
|
43
|
+
function moved_entries(before: string, after: string): ReadonlyArray<string> | undefined {
|
|
44
|
+
if (frame_of(before) !== frame_of(after)) return undefined
|
|
45
|
+
|
|
46
|
+
const was = entries_of(before)
|
|
47
|
+
const is = entries_of(after)
|
|
48
|
+
|
|
49
|
+
return [...missing_from(is, was), ...missing_from(was, is)]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The test files an entries-only change reaches, the list's own tests first.
|
|
53
|
+
function tests_of(entries: ReadonlyArray<string>): ReadonlyArray<string> {
|
|
54
|
+
return [...LIST_TESTS, ...entries]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function base_text(): Promise<string | undefined> {
|
|
58
|
+
try {
|
|
59
|
+
return await git_command.show_file(`${await git_command.change_base()}:${PURE_FILES_PATH}`)
|
|
60
|
+
} catch {
|
|
61
|
+
return undefined
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// The entries this branch moved in the list against its change base, or `undefined` when the list did
|
|
66
|
+
// not change, changed beyond its entries, or either side cannot be read.
|
|
67
|
+
async function read_moved(
|
|
68
|
+
root: string,
|
|
69
|
+
changed: ReadonlyArray<string> | undefined,
|
|
70
|
+
): Promise<ReadonlyArray<string> | undefined> {
|
|
71
|
+
if (changed?.includes(PURE_FILES_PATH) !== true) return undefined
|
|
72
|
+
|
|
73
|
+
const before = await base_text()
|
|
74
|
+
const after = file_reader.read_if_readable(path.join(root, PURE_FILES_PATH))
|
|
75
|
+
|
|
76
|
+
if (before === undefined || after === undefined) return undefined
|
|
77
|
+
|
|
78
|
+
return moved_entries(before, after)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const pure_files_entries = { PURE_FILES_PATH, moved_entries, read_moved, tests_of }
|
|
82
|
+
|
|
83
|
+
export { pure_files_entries }
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
import { direct_importers, type SourceReader } from './direct-importers'
|
|
3
|
+
import type { RelatedScope } from './test-related-scope'
|
|
4
|
+
import { unit_durations, type Durations } from './unit-durations'
|
|
5
|
+
import { vitest_cli_excludes } from './vitest-cli-excludes'
|
|
6
|
+
|
|
7
|
+
// **A scoped run leaves out the heavy test files a change reaches only indirectly**
|
|
8
|
+
// (joshuafolkken/kit#5105). A hub module's change reaches the integration tests importing it through
|
|
9
|
+
// the shared harnesses, and a scoped run's wall clock is bounded below by its longest file — over
|
|
10
|
+
// `HEAVY_TEST_MS` each — whatever else it narrows. A heavy file still runs when this change moved it,
|
|
11
|
+
// the module it is named for, or a file it imports directly, so the test written for a module is never
|
|
12
|
+
// left out with it, even when it reaches that module through a harness.
|
|
13
|
+
//
|
|
14
|
+
// "Heavy" is read off the CI shards' duration record (`unit-durations.json`), never a named list, so
|
|
15
|
+
// a file that slows down or speeds up moves in or out on the record's next refresh. The whole-suite
|
|
16
|
+
// fallback and every CI shard carry no exclusion, so a heavy file left out here still runs before the
|
|
17
|
+
// merge.
|
|
18
|
+
|
|
19
|
+
const HEAVY_TEST_MS = 10_000
|
|
20
|
+
const { EXCLUDE_FLAG } = vitest_cli_excludes
|
|
21
|
+
// The suffix a test file's module key carries past the module it is named for.
|
|
22
|
+
const TEST_SUFFIX_PATTERN = /(?:\.integration)?\.test$/u
|
|
23
|
+
const { module_key } = direct_importers
|
|
24
|
+
|
|
25
|
+
interface HeavyReader extends SourceReader {
|
|
26
|
+
durations: Durations
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function heavy_tests(durations: Durations): Array<string> {
|
|
30
|
+
return Object.keys(durations).filter((file) => (durations[file] ?? 0) > HEAVY_TEST_MS)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function imports_directly(file: string, scoped: ReadonlySet<string>, reader: HeavyReader): boolean {
|
|
34
|
+
const source = reader.read_source(file)
|
|
35
|
+
|
|
36
|
+
if (source === undefined) return true
|
|
37
|
+
|
|
38
|
+
return direct_importers.names_any(source, file, scoped, reader.imports)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function is_kept(file: string, scoped: ReadonlySet<string>, reader: HeavyReader): boolean {
|
|
42
|
+
const key = module_key(file)
|
|
43
|
+
|
|
44
|
+
if (scoped.has(key) || scoped.has(key.replace(TEST_SUFFIX_PATTERN, ''))) return true
|
|
45
|
+
|
|
46
|
+
return imports_directly(file, scoped, reader)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The heavy files to leave out of a scoped run: every one this scope neither holds, names nor imports from.
|
|
50
|
+
function excluded_tests(scoped_files: ReadonlyArray<string>, reader: HeavyReader): Array<string> {
|
|
51
|
+
const scoped = new Set(scoped_files.map((file) => module_key(file)))
|
|
52
|
+
|
|
53
|
+
return heavy_tests(reader.durations).filter((file) => !is_kept(file, scoped, reader))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function file_reader(root: string): HeavyReader {
|
|
57
|
+
return { ...direct_importers.source_reader(root), durations: unit_durations.read(root) }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// The `--exclude` flags a scope's vitest run carries: none unless it narrowed to related files.
|
|
61
|
+
function exclude_flags(
|
|
62
|
+
scope: RelatedScope,
|
|
63
|
+
root: string,
|
|
64
|
+
reader: HeavyReader = file_reader(root),
|
|
65
|
+
): Array<string> {
|
|
66
|
+
if (scope.mode !== 'related') return []
|
|
67
|
+
|
|
68
|
+
const scoped = scope.files.map((file) => path.relative(root, file))
|
|
69
|
+
|
|
70
|
+
return excluded_tests(scoped, reader).flatMap((file) => [EXCLUDE_FLAG, file])
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const related_heavy_tests = {
|
|
74
|
+
EXCLUDE_FLAG,
|
|
75
|
+
HEAVY_TEST_MS,
|
|
76
|
+
exclude_flags,
|
|
77
|
+
heavy_tests,
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type { HeavyReader }
|
|
81
|
+
export { related_heavy_tests }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { project_checks } from '#scripts/gate/project-checks'
|
|
4
|
+
import { no_base_checkout } from '#scripts/git/no-base-checkout'
|
|
5
|
+
import { test_related_claim } from './test-related-claim'
|
|
6
|
+
import { related_scope } from './test-related-scope'
|
|
7
|
+
import { test_unit_guard } from './test-unit-guard'
|
|
8
|
+
|
|
9
|
+
// **The second pass of `josh test:related` for a change that touches how the base branch is
|
|
10
|
+
// resolved** (joshuafolkken/kit#4710). A lane has a local `main`; CI's checkout has none, so a diff
|
|
11
|
+
// against a bare `main` passes every local check and fails only in CI. The related tests of each such
|
|
12
|
+
// file run again in `no-base-checkout.ts`'s checkout, which has none either.
|
|
13
|
+
//
|
|
14
|
+
// **A change that touches none of it runs nothing more** — no checkout, no vitest — so the gate takes
|
|
15
|
+
// no longer for it. **Nor does a consumer project**: the checkout holds only what git tracks, and a
|
|
16
|
+
// consumer's vitest config can read a generated, ignored file (`.svelte-kit/tsconfig.json`) it lacks.
|
|
17
|
+
|
|
18
|
+
// The names a file that resolves the base, or reads a diff against it, carries — the modules'
|
|
19
|
+
// own, and the bare default-branch name a caller could hand git.
|
|
20
|
+
const BASE_NAMES: ReadonlyArray<string> = [
|
|
21
|
+
'change_base',
|
|
22
|
+
'default_branch',
|
|
23
|
+
'diff_main',
|
|
24
|
+
"'main'",
|
|
25
|
+
'"main"',
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
// Shared with `test-related.ts`'s own reading of which files name another: a file it cannot read
|
|
29
|
+
// names nothing.
|
|
30
|
+
function text_of(file_path: string): string {
|
|
31
|
+
try {
|
|
32
|
+
return readFileSync(file_path, 'utf8')
|
|
33
|
+
} catch {
|
|
34
|
+
return ''
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function names_any(text: string, names: ReadonlyArray<string>): boolean {
|
|
39
|
+
return names.some((name) => text.includes(name))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function touches_base(root: string, file: string): boolean {
|
|
43
|
+
if (!related_scope.is_relatable(file)) return false
|
|
44
|
+
|
|
45
|
+
return names_any(text_of(path.join(root, file)), BASE_NAMES)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function touching(root: string, changed: ReadonlyArray<string>): Array<string> {
|
|
49
|
+
return changed.filter((file) => touches_base(root, file))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function run_in_checkout(
|
|
53
|
+
root: string,
|
|
54
|
+
files: ReadonlyArray<string>,
|
|
55
|
+
flags: ReadonlyArray<string>,
|
|
56
|
+
): Promise<number> {
|
|
57
|
+
const directory = await no_base_checkout.create(root)
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
return await test_unit_guard.run_vitest_in(directory, ['related', ...files, '--run', ...flags])
|
|
61
|
+
} finally {
|
|
62
|
+
no_base_checkout.remove(directory)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async function run_if_touched(
|
|
67
|
+
root: string,
|
|
68
|
+
changed: ReadonlyArray<string>,
|
|
69
|
+
flags: ReadonlyArray<string>,
|
|
70
|
+
): Promise<number> {
|
|
71
|
+
const files = project_checks.is_kit_repository(root) ? touching(root, changed) : []
|
|
72
|
+
|
|
73
|
+
if (files.length === 0) return 0
|
|
74
|
+
|
|
75
|
+
process.stdout.write(
|
|
76
|
+
`josh test:related: ${String(files.length)} changed file(s) touch the base branch's resolution — their related tests run again in a checkout with no local main, as CI's has none\n`,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// Its own claim, since the first pass released its own before this one starts.
|
|
80
|
+
return await test_related_claim.with_unit_claim(
|
|
81
|
+
files,
|
|
82
|
+
async () => await run_in_checkout(root, files, flags),
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const test_no_base = { names_any, run_if_touched, text_of, touching }
|
|
87
|
+
|
|
88
|
+
export { test_no_base }
|