@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,63 @@
|
|
|
1
|
+
import { lstatSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
// An answer remembered per key, recomputed only when the key's stamp changes (joshuafolkken/kit#4263).
|
|
4
|
+
//
|
|
5
|
+
// **`run:board` redraws every second, and most of what it reads has not changed since the last
|
|
6
|
+
// redraw.** A process's app name, a ledger's parsed lines and a work tree's git config were computed
|
|
7
|
+
// again on every pass, and on a saturated machine those passes stopped the spinner for 45–200ms. The
|
|
8
|
+
// stamp is what says "this has changed": a file's `file_stamp`, or a constant where the key alone
|
|
9
|
+
// decides the answer.
|
|
10
|
+
|
|
11
|
+
const NO_STAMP = ''
|
|
12
|
+
const STAMP_SEPARATOR = ':'
|
|
13
|
+
|
|
14
|
+
interface Remembered<Value> {
|
|
15
|
+
stamp: string
|
|
16
|
+
value: Value
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface StampedMemo<Value> {
|
|
20
|
+
// `compute`'s answer for `key`, run only when `key` was never seen or its stamp moved since.
|
|
21
|
+
of: (key: string, stamp: string, compute: () => Value) => Value
|
|
22
|
+
// Forget every key outside `keys` — a process gone from the table, so the memo cannot grow unbounded.
|
|
23
|
+
keep: (keys: ReadonlySet<string>) => void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function create<Value>(): StampedMemo<Value> {
|
|
27
|
+
const answers = new Map<string, Remembered<Value>>()
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
of(key, stamp, compute) {
|
|
31
|
+
const known = answers.get(key)
|
|
32
|
+
|
|
33
|
+
if (known?.stamp === stamp) return known.value
|
|
34
|
+
|
|
35
|
+
const value = compute()
|
|
36
|
+
|
|
37
|
+
answers.set(key, { stamp, value })
|
|
38
|
+
|
|
39
|
+
return value
|
|
40
|
+
},
|
|
41
|
+
keep(keys) {
|
|
42
|
+
for (const key of answers.keys()) if (!keys.has(key)) answers.delete(key)
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// What changes when a file is rewritten, appended to, replaced or re-owned: its inode, its modification
|
|
48
|
+
// and change times and its size. An absent or unreadable file is `NO_STAMP`, so it reads again once
|
|
49
|
+
// it appears.
|
|
50
|
+
function file_stamp(file: string): string {
|
|
51
|
+
try {
|
|
52
|
+
const status = lstatSync(file)
|
|
53
|
+
|
|
54
|
+
return [status.ino, status.mtimeMs, status.ctimeMs, status.size].join(STAMP_SEPARATOR)
|
|
55
|
+
} catch {
|
|
56
|
+
return NO_STAMP
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const stamped_memo = { NO_STAMP, create, file_stamp }
|
|
61
|
+
|
|
62
|
+
export { stamped_memo }
|
|
63
|
+
export type { StampedMemo }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Runs work whose own reports go to stdout with stdout pointed at stderr, for a caller whose stdout is
|
|
2
|
+
// a contract: the `Stop` hook's decision envelope, and `josh run:hold`'s single verdict token.
|
|
3
|
+
|
|
4
|
+
type StreamWrite = typeof process.stdout.write
|
|
5
|
+
|
|
6
|
+
function set_stdout_write(stream_write: StreamWrite): void {
|
|
7
|
+
process.stdout.write = stream_write
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function run<T>(work: () => Promise<T>): Promise<T> {
|
|
11
|
+
const saved = { write: process.stdout.write.bind(process.stdout) }
|
|
12
|
+
|
|
13
|
+
set_stdout_write(process.stderr.write.bind(process.stderr))
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
return await work()
|
|
17
|
+
} finally {
|
|
18
|
+
set_stdout_write(saved.write)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const stdout_on_stderr = { run }
|
|
23
|
+
|
|
24
|
+
export { stdout_on_stderr }
|
package/scripts/lib/timeouts.ts
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
// limit stays stuck where it stopped and never comes back, so every such
|
|
4
4
|
// call takes one of these, and a value used in more than one place is named once here.
|
|
5
5
|
|
|
6
|
+
// The unit conversions every duration is read and printed through. They sit beside the limits because a
|
|
7
|
+
// limit is the most common thing they convert; a second copy in a caller is a clone of these two lines.
|
|
8
|
+
const MS_PER_SECOND = 1000
|
|
9
|
+
const SECONDS_PER_MINUTE = 60
|
|
10
|
+
const MS_PER_MINUTE = MS_PER_SECOND * SECONDS_PER_MINUTE
|
|
11
|
+
|
|
6
12
|
// A probe that only asks the local machine (`ps`, `lsof`, `git config`) on a path something else is
|
|
7
13
|
// waiting on. Failing answers "cannot tell", which every caller handles, so anything slower is a fault.
|
|
8
14
|
const PROBE_TIMEOUT_MS = 2000
|
|
@@ -41,6 +47,9 @@ export {
|
|
|
41
47
|
HOOK_PROCESS_TIMEOUT_MS,
|
|
42
48
|
INSTALL_TIMEOUT_MS,
|
|
43
49
|
LINT_TIMEOUT_MS,
|
|
50
|
+
MS_PER_MINUTE,
|
|
51
|
+
MS_PER_SECOND,
|
|
44
52
|
PROBE_TIMEOUT_MS,
|
|
53
|
+
SECONDS_PER_MINUTE,
|
|
45
54
|
SUITE_TIMEOUT_MS,
|
|
46
55
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { json_value } from './json-value'
|
|
3
|
+
|
|
4
|
+
// One line of a Claude Code JSONL log — a session transcript, or the `stream-json` output of
|
|
5
|
+
// `claude -p`, which writes the same `{ type, message: { id, content } }` shape. Every reader of those
|
|
6
|
+
// lines parses through these schemas and takes what it needs from the record; a fix to the shape
|
|
7
|
+
// reaches all of them at once.
|
|
8
|
+
//
|
|
9
|
+
// **Every field is optional, including `type`.** A required field would make one unexpected block
|
|
10
|
+
// fail the whole array it sits in, and with it every other block on that line — an entire assistant
|
|
11
|
+
// turn dropped because one tool wrote a shape no reader had seen. A block that parses to nothing
|
|
12
|
+
// contributes nothing.
|
|
13
|
+
|
|
14
|
+
const TEXT_TYPE = 'text'
|
|
15
|
+
const TOOL_USE_TYPE = 'tool_use'
|
|
16
|
+
const TOOL_RESULT_TYPE = 'tool_result'
|
|
17
|
+
|
|
18
|
+
const BLOCK_SCHEMA = z.object({
|
|
19
|
+
type: z.string().nullish(),
|
|
20
|
+
text: z.string().nullish(),
|
|
21
|
+
name: z.string().nullish(),
|
|
22
|
+
id: z.string().nullish(),
|
|
23
|
+
tool_use_id: z.string().nullish(),
|
|
24
|
+
input: z.unknown().nullish(),
|
|
25
|
+
// Whether the harness wrote a `tool_result` back as a failure — absent on every other block, and
|
|
26
|
+
// on the results of tools that never report one.
|
|
27
|
+
is_error: z.boolean().nullish(),
|
|
28
|
+
// A result's body: a string or a list of blocks. Read as `unknown` because each reader flattens it
|
|
29
|
+
// its own way, and a narrower type here would drop the whole line over one odd item.
|
|
30
|
+
content: z.unknown().nullish(),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const CONTENT_SCHEMA = z.union([z.string(), z.array(BLOCK_SCHEMA)])
|
|
34
|
+
// `id` is the assistant *message* the line belongs to; Claude Code writes one line per content block,
|
|
35
|
+
// so a turn that issued two calls is several lines carrying one id.
|
|
36
|
+
const MESSAGE_SCHEMA = z.object({ id: z.string().nullish(), content: CONTENT_SCHEMA.nullish() })
|
|
37
|
+
|
|
38
|
+
const LINE_SCHEMA = z.object({
|
|
39
|
+
type: z.string().nullish(),
|
|
40
|
+
timestamp: z.string().nullish(),
|
|
41
|
+
gitBranch: z.string().nullish(),
|
|
42
|
+
// The two fields outside `message` the harness writes an end-of-task notice on. `unknown`, since a
|
|
43
|
+
// string here would reject every line whose `content` is a list of blocks.
|
|
44
|
+
content: z.unknown().nullish(),
|
|
45
|
+
attachment: z.unknown().nullish(),
|
|
46
|
+
message: MESSAGE_SCHEMA.nullish(),
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
type TranscriptBlock = z.infer<typeof BLOCK_SCHEMA>
|
|
50
|
+
type TranscriptContent = z.infer<typeof CONTENT_SCHEMA>
|
|
51
|
+
type TranscriptMessage = z.infer<typeof MESSAGE_SCHEMA>
|
|
52
|
+
type TranscriptRecord = z.infer<typeof LINE_SCHEMA>
|
|
53
|
+
type ToolCallBlock = TranscriptBlock & { name: string }
|
|
54
|
+
|
|
55
|
+
function read(value: unknown): TranscriptRecord | undefined {
|
|
56
|
+
return LINE_SCHEMA.safeParse(value).data
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// A blank line, a line that is not JSON and a line of another shape are one answer: `undefined`.
|
|
60
|
+
function parse(line: string): TranscriptRecord | undefined {
|
|
61
|
+
return read(json_value.parse_or_undefined(line))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The line's blocks. A message written as a bare string — a prompt — carries none.
|
|
65
|
+
function blocks_of(record: TranscriptRecord): ReadonlyArray<TranscriptBlock> {
|
|
66
|
+
const content = record.message?.content
|
|
67
|
+
|
|
68
|
+
return Array.isArray(content) ? content : []
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function is_tool_call(block: TranscriptBlock): block is ToolCallBlock {
|
|
72
|
+
return block.type === TOOL_USE_TYPE && typeof block.name === 'string'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The calls a line made, in order. A `tool_use` block without a name is not a call anything can name.
|
|
76
|
+
function tool_calls_of(record: TranscriptRecord): Array<ToolCallBlock> {
|
|
77
|
+
return blocks_of(record).filter((block) => is_tool_call(block))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const transcript_record = {
|
|
81
|
+
TEXT_TYPE,
|
|
82
|
+
TOOL_USE_TYPE,
|
|
83
|
+
TOOL_RESULT_TYPE,
|
|
84
|
+
read,
|
|
85
|
+
parse,
|
|
86
|
+
blocks_of,
|
|
87
|
+
tool_calls_of,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type { TranscriptBlock, TranscriptContent, TranscriptMessage, TranscriptRecord }
|
|
91
|
+
export { transcript_record }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createRequire } from 'node:module'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { pathToFileURL } from 'node:url'
|
|
4
|
+
import { PACKAGE_JSON } from '#scripts/lib/package-manifest'
|
|
4
5
|
import { z } from 'zod'
|
|
5
6
|
|
|
6
7
|
// Resolves the `max-lines` entry the project's own eslint applies, so `pnpm josh lines` explains its
|
|
@@ -28,7 +29,6 @@ import { z } from 'zod'
|
|
|
28
29
|
// consumer's config, never by whichever copy happens to sit beside this file.
|
|
29
30
|
|
|
30
31
|
const ESLINT_MODULE = 'eslint'
|
|
31
|
-
const PACKAGE_JSON = 'package.json'
|
|
32
32
|
const MAX_LINES_RULE = 'max-lines'
|
|
33
33
|
// A rule turned off enforces nothing, so there is no limit to report and no headroom to subtract from.
|
|
34
34
|
// Both spellings occur: `calculateConfigForFile` normalizes severity to a number, but a config read by
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { rmSync, writeFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { file_reader } from '#scripts/lib/read-file'
|
|
4
|
+
import { parse, stringify } from 'flatted'
|
|
5
|
+
import { import_graph, type ImportGraph } from './import-graph'
|
|
6
|
+
|
|
7
|
+
// eslint's content cache keys a verdict on the linted file's own content, so a file whose imports
|
|
8
|
+
// changed underneath it keeps answering from the cache: the error a type-aware rule would now report
|
|
9
|
+
// — an import that became `any`, read by `no-unsafe-assignment` — never reaches the report, and the
|
|
10
|
+
// type check does not report the `no-unsafe-*` rules either (joshuafolkken/kit#4415). CI restores
|
|
11
|
+
// the gate's cache file, so it answers the same stale green.
|
|
12
|
+
//
|
|
13
|
+
// So each cached entry also records what its verdict read: the hash of every file its imports reach
|
|
14
|
+
// (`import-graph.ts`). Before a cached run, an entry whose imports no longer hash the same is dropped,
|
|
15
|
+
// and eslint lints that file afresh; after it, the entries eslint wrote are given the hash taken
|
|
16
|
+
// before the run, which is the state of the files that run read. An entry with no hash — one an
|
|
17
|
+
// unguarded run wrote, or one from before this — is dropped as well, because nothing says what it
|
|
18
|
+
// read.
|
|
19
|
+
//
|
|
20
|
+
// The drop clears a stale red as well as a stale green: an import rule's report — `import/no-cycle`,
|
|
21
|
+
// `import-x/named` — is about another file too, and once that file changes the entry is linted
|
|
22
|
+
// afresh. Only imports are followed, so a rule that reads the files importing this one — a
|
|
23
|
+
// reverse-dependency rule such as `import/no-unused-modules`, a no-op under ESLint 10 — would go
|
|
24
|
+
// stale here. This is the one place cache staleness is decided; it replaced the cross-file re-read that
|
|
25
|
+
// once ran after a red cached run (joshuafolkken/kit#3641, #3667, #4407, #4420).
|
|
26
|
+
//
|
|
27
|
+
// The record rides inside eslint's own cache file, in the entry's `data` beside the results eslint
|
|
28
|
+
// keeps there, rather than a file of its own: it then travels wherever the cache file does — a lane's
|
|
29
|
+
// seed, CI's cache — and eslint replaces `data` whole whenever it lints the file again, so a hash can
|
|
30
|
+
// never outlive the verdict it was taken for. The file is `flat-cache`'s, serialized with `flatted`.
|
|
31
|
+
|
|
32
|
+
type CacheMeta = Record<string, unknown>
|
|
33
|
+
|
|
34
|
+
interface CacheEntry {
|
|
35
|
+
key: string
|
|
36
|
+
value: CacheMeta
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type Hashes = ReadonlyMap<string, string>
|
|
40
|
+
|
|
41
|
+
function is_record(value: unknown): value is Record<string, unknown> {
|
|
42
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function is_entry(item: unknown): item is CacheEntry {
|
|
46
|
+
if (!is_record(item)) return false
|
|
47
|
+
const { key, value } = item
|
|
48
|
+
|
|
49
|
+
return typeof key === 'string' && is_record(value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function is_entries(value: unknown): value is Array<CacheEntry> {
|
|
53
|
+
return Array.isArray(value) && value.every((item: unknown) => is_entry(item))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function parsed_or_undefined(content: string): unknown {
|
|
57
|
+
try {
|
|
58
|
+
return parse(content)
|
|
59
|
+
} catch {
|
|
60
|
+
return undefined
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Undefined for a missing file and for one this cannot read as eslint writes it.
|
|
65
|
+
function read_entries(cache_file: string): Array<CacheEntry> | undefined {
|
|
66
|
+
const content = file_reader.read_optional(cache_file)
|
|
67
|
+
if (content === undefined) return undefined
|
|
68
|
+
const parsed = parsed_or_undefined(content)
|
|
69
|
+
|
|
70
|
+
return is_entries(parsed) ? parsed : undefined
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// A cache file this cannot read — a corrupt one, or one another layout wrote into a cache lanes share —
|
|
74
|
+
// is removed before the run rather than left to eslint, so the run rebuilds it whole and every entry it
|
|
75
|
+
// writes carries a hash (joshuafolkken/kit#4497).
|
|
76
|
+
function read_or_discard(cache_file: string): Array<CacheEntry> {
|
|
77
|
+
const entries = read_entries(cache_file)
|
|
78
|
+
|
|
79
|
+
if (entries === undefined) rmSync(cache_file, { force: true })
|
|
80
|
+
|
|
81
|
+
return entries ?? []
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function write_entries(cache_file: string, entries: ReadonlyArray<CacheEntry>): void {
|
|
85
|
+
writeFileSync(cache_file, stringify(entries))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function recorded_hash(entry: CacheEntry): string | undefined {
|
|
89
|
+
const { data } = entry.value
|
|
90
|
+
if (!is_record(data)) return undefined
|
|
91
|
+
const { dependencies } = data
|
|
92
|
+
|
|
93
|
+
return typeof dependencies === 'string' ? dependencies : undefined
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Drops every entry whose imports no longer hash as recorded, and answers the hashes it took.
|
|
97
|
+
function drop_stale(cache_file: string, graph: ImportGraph): Hashes {
|
|
98
|
+
const entries = read_or_discard(cache_file)
|
|
99
|
+
const hashes = new Map(entries.map((entry) => [entry.key, graph.closure_hash(entry.key)]))
|
|
100
|
+
const kept = entries.filter((entry) => recorded_hash(entry) === hashes.get(entry.key))
|
|
101
|
+
|
|
102
|
+
if (kept.length !== entries.length) write_entries(cache_file, kept)
|
|
103
|
+
|
|
104
|
+
return hashes
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// eslint writes `data` only for a file it linted, so an entry with `data` and no hash is one this run
|
|
108
|
+
// linted. A file the run linted for the first time had no hash taken before it, so it is taken now.
|
|
109
|
+
function record_entry(entry: CacheEntry, hashes: Hashes, graph: ImportGraph): boolean {
|
|
110
|
+
const { data } = entry.value
|
|
111
|
+
if (!is_record(data) || 'dependencies' in data) return false
|
|
112
|
+
|
|
113
|
+
Object.assign(data, { dependencies: hashes.get(entry.key) ?? graph.closure_hash(entry.key) })
|
|
114
|
+
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function record(cache_file: string, hashes: Hashes, graph: ImportGraph): void {
|
|
119
|
+
const entries = read_entries(cache_file)
|
|
120
|
+
if (entries === undefined) return
|
|
121
|
+
const recorded = entries.filter((entry) => record_entry(entry, hashes, graph))
|
|
122
|
+
|
|
123
|
+
if (recorded.length > 0) write_entries(cache_file, entries)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Runs one cached eslint run between the drop and the record. A project without `typescript` or a `tsconfig.json` runs it as it was.
|
|
127
|
+
async function guard<T>(
|
|
128
|
+
cache_file: string,
|
|
129
|
+
run: () => Promise<T>,
|
|
130
|
+
root: string = process.cwd(),
|
|
131
|
+
): Promise<T> {
|
|
132
|
+
const graph = await import_graph.create(root)
|
|
133
|
+
if (graph === undefined) return await run()
|
|
134
|
+
const location = path.resolve(root, cache_file)
|
|
135
|
+
const hashes = drop_stale(location, graph)
|
|
136
|
+
const result = await run()
|
|
137
|
+
|
|
138
|
+
record(location, hashes, graph)
|
|
139
|
+
|
|
140
|
+
return result
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const eslint_cache_dependencies = { guard }
|
|
144
|
+
|
|
145
|
+
export { eslint_cache_dependencies }
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { lstatSync, readFileSync } from 'node:fs'
|
|
2
|
+
import { createRequire } from 'node:module'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { fileURLToPath } from 'node:url'
|
|
5
|
+
import { resolve_package_bin } from '#scripts/build/local-bin'
|
|
6
|
+
import { toolchain_inputs } from '#scripts/gate/toolchain-inputs'
|
|
7
|
+
import { git_spawn_sync } from '#scripts/git/git-spawn-sync'
|
|
8
|
+
import { atomic_write } from '#scripts/lib/atomic-write'
|
|
9
|
+
import { buffered_process, type BufferedProcessResult } from '#scripts/lib/buffered-process'
|
|
10
|
+
import { execa } from 'execa'
|
|
11
|
+
|
|
12
|
+
// One warm eslint per checkout, reached by every eslint run that is not the gate's whole tree: the
|
|
13
|
+
// `PostToolUse` edit hook, `josh lint:related` and the pre-commit hook (joshuafolkken/kit#4358).
|
|
14
|
+
// `eslint_d` forwards the argument list to the project's own `eslint/lib/cli.js` → `execute`, run in
|
|
15
|
+
// the forwarding process's cwd, so the report, the exit code and the cache file are eslint's own:
|
|
16
|
+
// measured on this repository, a CLI run and a daemon run over the same files wrote byte-identical
|
|
17
|
+
// cache files, `--quiet` included, and printed identical reports.
|
|
18
|
+
|
|
19
|
+
const ESLINT_DAEMON = 'eslint_d'
|
|
20
|
+
const DAEMON_STOP = 'stop'
|
|
21
|
+
// The pnpm argument list every eslint caller here already builds. The daemon takes what follows it.
|
|
22
|
+
const PNPM_EXEC = 'exec'
|
|
23
|
+
const ESLINT_BIN = 'eslint'
|
|
24
|
+
const PNPM_ESLINT_PREFIX_LENGTH = 2
|
|
25
|
+
const NODE_MODULES = 'node_modules'
|
|
26
|
+
// `eslint_d` writes `<token> <port> <pid> <hash>` here once, when the daemon has started, and removes
|
|
27
|
+
// it when the daemon stops — so its text names one daemon.
|
|
28
|
+
const DAEMON_RECORD = '.eslint_d'
|
|
29
|
+
// What that daemon loaded: its record's text and the fingerprint it started under, written beside it.
|
|
30
|
+
const FINGERPRINT_RECORD = '.eslint_d-toolchain'
|
|
31
|
+
const RECORD_SEPARATOR = '\n'
|
|
32
|
+
const NO_HEAD = 'no-head'
|
|
33
|
+
|
|
34
|
+
// Where this file sits inside the kit package. `eslint_d` is kit's dependency rather than the
|
|
35
|
+
// consumer's, and pnpm writes a `node_modules/.bin` shim only for a project's *direct* dependencies,
|
|
36
|
+
// so a consumer's project root cannot see it and this directory can.
|
|
37
|
+
const MODULE_DIRECTORY = path.dirname(fileURLToPath(import.meta.url))
|
|
38
|
+
|
|
39
|
+
interface DaemonOutcome {
|
|
40
|
+
exit_code: number
|
|
41
|
+
// stdout alone, which is what separates a report from a daemon that never answered.
|
|
42
|
+
stdout: string
|
|
43
|
+
// stdout and stderr interleaved, which is what a caller prints.
|
|
44
|
+
output: string
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface DaemonRecord {
|
|
48
|
+
// The running daemon's own record, or nothing when none runs.
|
|
49
|
+
daemon: string | undefined
|
|
50
|
+
// What `remember` wrote for the daemon it last saw start.
|
|
51
|
+
recorded: string | undefined
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface DaemonRunOptions {
|
|
55
|
+
project_root: string
|
|
56
|
+
timeout_ms?: number
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// `eslint_d` keys its one daemon on the record beside the eslint it resolves, so a project that
|
|
60
|
+
// borrows another checkout's `node_modules` through a symlink — a test fixture's temporary
|
|
61
|
+
// repository — would start, restart and overwrite that checkout's daemon (joshuafolkken/kit#4386).
|
|
62
|
+
function is_borrowed_install(project_root: string): boolean {
|
|
63
|
+
return (
|
|
64
|
+
lstatSync(path.join(project_root, NODE_MODULES), {
|
|
65
|
+
throwIfNoEntry: false,
|
|
66
|
+
})?.isSymbolicLink() === true
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolve_daemon_cli(project_root: string): string | undefined {
|
|
71
|
+
if (is_borrowed_install(project_root)) return undefined
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
resolve_package_bin(MODULE_DIRECTORY, ESLINT_DAEMON, ESLINT_DAEMON) ??
|
|
75
|
+
resolve_package_bin(project_root, ESLINT_DAEMON, ESLINT_DAEMON)
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// The flat config, the type program's options and the installed packages a consumer's config imports
|
|
80
|
+
// its rules from — typescript-eslint's project service watches none of them (joshuafolkken/kit#4494).
|
|
81
|
+
function is_config_input(relative_path: string): boolean {
|
|
82
|
+
return toolchain_inputs.is_input(relative_path)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The eslint arguments of a `pnpm exec eslint …` list, or nothing when the list runs another tool.
|
|
86
|
+
function eslint_arguments_of(
|
|
87
|
+
pnpm_arguments: ReadonlyArray<string>,
|
|
88
|
+
): ReadonlyArray<string> | undefined {
|
|
89
|
+
if (pnpm_arguments[0] !== PNPM_EXEC || pnpm_arguments[1] !== ESLINT_BIN) return undefined
|
|
90
|
+
|
|
91
|
+
return pnpm_arguments.slice(PNPM_ESLINT_PREFIX_LENGTH)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// **What a daemon is current for: the toolchain's content and the commit checked out.** The daemon's
|
|
95
|
+
// type program keeps every source it read but did not lint, so a merge that changes those types leaves
|
|
96
|
+
// typed rules failing on the old ones (joshuafolkken/kit#4443); every merge, checkout, reset, pull and
|
|
97
|
+
// commit moves HEAD, the commands that move sources under the daemon without an edit the hook sees.
|
|
98
|
+
// A content digest rather than a time: a copy or a checkout rewrites every mtime and leaves the
|
|
99
|
+
// content alone, and an edit can keep its old mtime. Outside a repository there is no HEAD.
|
|
100
|
+
function fingerprint(project_root: string): string {
|
|
101
|
+
const head = git_spawn_sync.read(['rev-parse', 'HEAD'], { cwd: project_root }) ?? NO_HEAD
|
|
102
|
+
|
|
103
|
+
return `${toolchain_inputs.digest(project_root)}:${head}`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Where the eslint the daemon resolves keeps its record, or nothing without an installed eslint.
|
|
107
|
+
function eslint_directory(project_root: string): string | undefined {
|
|
108
|
+
try {
|
|
109
|
+
return path.dirname(
|
|
110
|
+
createRequire(path.join(project_root, 'package.json')).resolve('eslint/package.json'),
|
|
111
|
+
)
|
|
112
|
+
} catch {
|
|
113
|
+
return undefined
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function read_text(file: string): string | undefined {
|
|
118
|
+
try {
|
|
119
|
+
return readFileSync(file, 'utf8')
|
|
120
|
+
} catch {
|
|
121
|
+
return undefined
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function read_record(project_root: string): DaemonRecord {
|
|
126
|
+
const directory = eslint_directory(project_root)
|
|
127
|
+
if (directory === undefined) return { daemon: undefined, recorded: undefined }
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
daemon: read_text(path.join(directory, DAEMON_RECORD)),
|
|
131
|
+
recorded: read_text(path.join(directory, FINGERPRINT_RECORD)),
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function record_text(daemon: string, current: string): string {
|
|
136
|
+
return `${daemon}${RECORD_SEPARATOR}${current}`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// A daemon keeps the rule modules it imported first — eslint cache-busts only the config entry file —
|
|
140
|
+
// so a toolchain input that moved since it started leaves it linting against the old rules, and a
|
|
141
|
+
// HEAD move leaves it typing against the old sources. A daemon this module did not record — another
|
|
142
|
+
// tool started it, or the record is from an older one — is stale too: nothing says what it loaded.
|
|
143
|
+
// The edit hook records the daemons it starts and restarts (`remember_started`); this catches the rest.
|
|
144
|
+
function is_stale(record: DaemonRecord, current: string): boolean {
|
|
145
|
+
if (record.daemon === undefined) return false
|
|
146
|
+
|
|
147
|
+
return record.recorded !== record_text(record.daemon, current)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Best-effort, like the daemon's own record: one that could not be written restarts the daemon once
|
|
151
|
+
// more on the next run.
|
|
152
|
+
function remember(project_root: string, current: string): void {
|
|
153
|
+
const directory = eslint_directory(project_root)
|
|
154
|
+
if (directory === undefined) return
|
|
155
|
+
const daemon = read_text(path.join(directory, DAEMON_RECORD))
|
|
156
|
+
if (daemon === undefined) return
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
atomic_write.replace_file(
|
|
160
|
+
path.join(directory, FINGERPRINT_RECORD),
|
|
161
|
+
record_text(daemon, current),
|
|
162
|
+
)
|
|
163
|
+
} catch {
|
|
164
|
+
// A lost record costs one restart.
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// The edit hook starts the daemon on its first eslint fix and restarts it after a config edit, each
|
|
169
|
+
// under the inputs as they are now, and a daemon's record changes with every start — so a record that
|
|
170
|
+
// changed across the hook's commands names a daemon they started. Recording it keeps the next lint run
|
|
171
|
+
// from stopping and cold-starting a daemon that is already current.
|
|
172
|
+
function remember_started(project_root: string, before: DaemonRecord): void {
|
|
173
|
+
if (read_record(project_root).daemon === before.daemon) return
|
|
174
|
+
|
|
175
|
+
remember(project_root, fingerprint(project_root))
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// `cwd` decides which eslint installation and which flat config answer, and `ESLINT_D_MISS=fail`
|
|
179
|
+
// refuses the bundled eslint the daemon would otherwise fall back to.
|
|
180
|
+
async function spawn_daemon(
|
|
181
|
+
cli: string,
|
|
182
|
+
cli_arguments: ReadonlyArray<string>,
|
|
183
|
+
options: DaemonRunOptions,
|
|
184
|
+
): Promise<DaemonOutcome> {
|
|
185
|
+
const result = await execa(process.execPath, [cli, ...cli_arguments], {
|
|
186
|
+
reject: false,
|
|
187
|
+
all: true,
|
|
188
|
+
cwd: options.project_root,
|
|
189
|
+
env: { ...buffered_process.child_environment(), ESLINT_D_MISS: 'fail' },
|
|
190
|
+
extendEnv: false,
|
|
191
|
+
...(options.timeout_ms !== undefined && { timeout: options.timeout_ms }),
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
return { exit_code: result.exitCode ?? 1, stdout: result.stdout, output: result.all }
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// The daemon prints every eslint line — stderr included — to its forwarder's stdout, and its own
|
|
198
|
+
// start failures to stderr with nothing on stdout.
|
|
199
|
+
function is_start_failure(outcome: DaemonOutcome): boolean {
|
|
200
|
+
return outcome.exit_code !== 0 && outcome.stdout.length === 0
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// The fingerprint is taken before the run, so an input that moves while the daemon starts is caught by
|
|
204
|
+
// the next one.
|
|
205
|
+
async function run_current(
|
|
206
|
+
cli: string,
|
|
207
|
+
eslint_arguments: ReadonlyArray<string>,
|
|
208
|
+
options: DaemonRunOptions,
|
|
209
|
+
): Promise<DaemonOutcome | undefined> {
|
|
210
|
+
const { project_root } = options
|
|
211
|
+
const current = fingerprint(project_root)
|
|
212
|
+
if (is_stale(read_record(project_root), current)) await spawn_daemon(cli, [DAEMON_STOP], options)
|
|
213
|
+
|
|
214
|
+
const outcome = await spawn_daemon(cli, eslint_arguments, options)
|
|
215
|
+
if (is_start_failure(outcome)) return undefined
|
|
216
|
+
remember(project_root, current)
|
|
217
|
+
|
|
218
|
+
return outcome
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// The run through the warm daemon, or nothing when there is no daemon to reach or it failed to
|
|
222
|
+
// start — the caller then runs its own cold route, so a project without the daemon lints as before.
|
|
223
|
+
async function run(
|
|
224
|
+
pnpm_arguments: ReadonlyArray<string>,
|
|
225
|
+
options: DaemonRunOptions,
|
|
226
|
+
): Promise<DaemonOutcome | undefined> {
|
|
227
|
+
const eslint_arguments = eslint_arguments_of(pnpm_arguments)
|
|
228
|
+
if (eslint_arguments === undefined) return undefined
|
|
229
|
+
const cli = resolve_daemon_cli(options.project_root)
|
|
230
|
+
if (cli === undefined) return undefined
|
|
231
|
+
|
|
232
|
+
return await run_current(cli, eslint_arguments, options)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// The warm run from the current directory, read as a buffered child's result, or the cold
|
|
236
|
+
// `pnpm exec eslint` when the daemon cannot answer — the one fallback `josh lint:related` and the
|
|
237
|
+
// pre-commit hook both take.
|
|
238
|
+
async function run_or_cold(pnpm_arguments: ReadonlyArray<string>): Promise<BufferedProcessResult> {
|
|
239
|
+
const started_at = performance.now()
|
|
240
|
+
const outcome = await run(pnpm_arguments, { project_root: process.cwd() })
|
|
241
|
+
if (outcome === undefined) return await buffered_process.run_buffered_process(pnpm_arguments)
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
output: outcome.output,
|
|
245
|
+
exit_code: outcome.exit_code,
|
|
246
|
+
elapsed_ms: performance.now() - started_at,
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const eslint_daemon = {
|
|
251
|
+
eslint_arguments_of,
|
|
252
|
+
fingerprint,
|
|
253
|
+
is_config_input,
|
|
254
|
+
is_stale,
|
|
255
|
+
read_record,
|
|
256
|
+
record_text,
|
|
257
|
+
remember_started,
|
|
258
|
+
resolve_daemon_cli,
|
|
259
|
+
run,
|
|
260
|
+
run_or_cold,
|
|
261
|
+
ESLINT_DAEMON,
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export type { DaemonOutcome, DaemonRecord }
|
|
265
|
+
export { eslint_daemon }
|
package/scripts/lint/format.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { project_checks } from '#scripts/gate/project-checks'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ESLINT_CACHE_FILE,
|
|
6
|
+
ESLINT_CACHE_FLAGS,
|
|
7
|
+
PRETTIER_CACHE_FLAGS,
|
|
8
|
+
} from '#scripts/josh/josh-command-types'
|
|
5
9
|
import { composite_arguments, USAGE_ERROR_EXIT_CODE } from '#scripts/josh/josh-composite-arguments'
|
|
6
10
|
import { execa } from 'execa'
|
|
11
|
+
import { eslint_cache_dependencies } from './eslint-cache-dependencies'
|
|
7
12
|
|
|
8
13
|
const COMMAND_NAME = 'format'
|
|
9
14
|
const ARGV_OFFSET = 2
|
|
10
15
|
const FAIL_EXIT_CODE = 1
|
|
11
|
-
const
|
|
16
|
+
const PRETTIER_WRITE_ARGS = ['exec', 'prettier', '--write', '.', ...PRETTIER_CACHE_FLAGS] as const
|
|
12
17
|
const ESLINT_FIX_ARGS = ['exec', 'eslint', '.', '--fix', ...ESLINT_CACHE_FLAGS] as const
|
|
13
18
|
|
|
14
19
|
async function run_step(args: ReadonlyArray<string>, directory: string): Promise<number> {
|
|
@@ -37,13 +42,17 @@ async function run_format(directory: string): Promise<number> {
|
|
|
37
42
|
const prettier_exit_code = await run_unless_skipped(
|
|
38
43
|
'prettier',
|
|
39
44
|
prettier_reason,
|
|
40
|
-
|
|
45
|
+
PRETTIER_WRITE_ARGS,
|
|
41
46
|
directory,
|
|
42
47
|
)
|
|
43
48
|
if (prettier_exit_code !== 0) return prettier_exit_code
|
|
44
49
|
const eslint_reason = project_checks.eslint_skip_reason(directory)
|
|
45
50
|
|
|
46
|
-
return await
|
|
51
|
+
return await eslint_cache_dependencies.guard(
|
|
52
|
+
ESLINT_CACHE_FILE,
|
|
53
|
+
async () => await run_unless_skipped('eslint', eslint_reason, ESLINT_FIX_ARGS, directory),
|
|
54
|
+
directory,
|
|
55
|
+
)
|
|
47
56
|
}
|
|
48
57
|
|
|
49
58
|
// The argument refusal survives leaving the `sh -c` composite shape: both tools run over the whole
|
|
@@ -64,4 +73,4 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
64
73
|
|
|
65
74
|
const format = { run, run_format }
|
|
66
75
|
|
|
67
|
-
export { ESLINT_FIX_ARGS, format }
|
|
76
|
+
export { ESLINT_FIX_ARGS, format, PRETTIER_WRITE_ARGS }
|