@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,158 @@
|
|
|
1
|
+
import { lane_reap, type LaneProcesses, type ReapProbes } from './lane-reap'
|
|
2
|
+
import { lane_registry } from './lane-registry'
|
|
3
|
+
import { lane_residents } from './lane-residents'
|
|
4
|
+
|
|
5
|
+
// Suspending a lane child in place, and letting it carry on from the same point.
|
|
6
|
+
//
|
|
7
|
+
// **Nothing but the processes is touched here.** The work tree, the branch and the issue stay as they
|
|
8
|
+
// are, so a paused lane is resumed rather than rebuilt — the one way to halt a lane that `lane:close`
|
|
9
|
+
// (which deletes it) and `lane:withdraw` (which takes its issue out of the run) are not. The command
|
|
10
|
+
// (`lane-pause-cli.ts`) records the change in the lane's state and on the run's event stream.
|
|
11
|
+
//
|
|
12
|
+
// **The tree is `lane_reap`'s** — the same match, the same descendants, the caller's own ancestry
|
|
13
|
+
// spared — so a pause and a reap never disagree on which processes are the lane's.
|
|
14
|
+
//
|
|
15
|
+
// **A pause reads the tree again until no new process turns up.** A parent signalled after it had
|
|
16
|
+
// already forked leaves a child that was not in the first read running; each round stops what the
|
|
17
|
+
// last one did not see, up to `PAUSE_ROUNDS`.
|
|
18
|
+
//
|
|
19
|
+
// **A process detached from the tree is stopped and continued with it** (joshuafolkken/kit#4300): the
|
|
20
|
+
// edit hook's `eslint_d`, a detached `ship`, found by its working directory or mark as `lane:close`
|
|
21
|
+
// finds it (`lane-residents.ts`), so a resume reaches every process the pause stopped. A pause with no
|
|
22
|
+
// child in the tree stops none of them: it pauses no lane and records nothing, so nothing would resume
|
|
23
|
+
// them. A read of them that failed is `is_unread`, never "none", so a caller can say they were missed.
|
|
24
|
+
|
|
25
|
+
const STOP_SIGNAL = 'SIGSTOP'
|
|
26
|
+
const CONTINUE_SIGNAL = 'SIGCONT'
|
|
27
|
+
const PAUSE_ROUNDS = 5
|
|
28
|
+
|
|
29
|
+
type LaneSignal = typeof STOP_SIGNAL | typeof CONTINUE_SIGNAL
|
|
30
|
+
|
|
31
|
+
interface PauseProbes extends ReapProbes {
|
|
32
|
+
signal: (pid: number, name: LaneSignal) => boolean
|
|
33
|
+
// What runs from the lane outside the tree (`lane-residents.ts`); `undefined` when unreadable.
|
|
34
|
+
residents: (lane: LaneProcesses) => ReadonlyArray<number> | undefined
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// What a pause or a resume reached: the lane's processes signalled, and those of them in the child's
|
|
38
|
+
// tree. Only `child` says the lane is running — a resident outlives the child it served (`eslint_d`
|
|
39
|
+
// idles on), so signalling it alone pauses no lane. `is_unread`: the residents could not be read, so
|
|
40
|
+
// any of them may have been missed.
|
|
41
|
+
interface LaneSignalled {
|
|
42
|
+
signalled: Array<number>
|
|
43
|
+
child: Array<number>
|
|
44
|
+
is_unread: boolean
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// One read of the lane: the child's tree, and the tree with what runs from the lane outside it.
|
|
48
|
+
interface LaneRead {
|
|
49
|
+
tree: Array<number>
|
|
50
|
+
all: Array<number>
|
|
51
|
+
is_unread: boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function signal(pid: number, name: LaneSignal): boolean {
|
|
55
|
+
try {
|
|
56
|
+
process.kill(pid, name)
|
|
57
|
+
|
|
58
|
+
return true
|
|
59
|
+
} catch {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const SYSTEM_PROBES: PauseProbes = {
|
|
65
|
+
...lane_reap.SYSTEM_PROBES,
|
|
66
|
+
signal,
|
|
67
|
+
residents: (lane) => lane_residents.residents(lane),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// The lane child's tree and what runs from the lane outside it, each once. The residents are read only
|
|
71
|
+
// beside a child, unless `is_resident_read_forced`.
|
|
72
|
+
function lane_processes(
|
|
73
|
+
lane: LaneProcesses,
|
|
74
|
+
probes: PauseProbes,
|
|
75
|
+
is_resident_read_forced: boolean,
|
|
76
|
+
): LaneRead {
|
|
77
|
+
const tree = lane_reap.lane_tree(lane.issue, probes)
|
|
78
|
+
if (!is_resident_read_forced && tree.length === 0) return { tree, all: tree, is_unread: false }
|
|
79
|
+
const residents = probes.residents(lane)
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
tree,
|
|
83
|
+
all: [...new Set([...tree, ...(residents ?? [])])],
|
|
84
|
+
is_unread: residents === undefined,
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function signalled_of(
|
|
89
|
+
signalled: Array<number>,
|
|
90
|
+
tree: ReadonlySet<number>,
|
|
91
|
+
is_unread: boolean,
|
|
92
|
+
): LaneSignalled {
|
|
93
|
+
return { signalled, child: signalled.filter((pid) => tree.has(pid)), is_unread }
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Every pid read is `seen`, so a process the signal could not reach is not retried each round; only the
|
|
97
|
+
// ones the signal reached are `stopped`. Every tree pid read is `tree`.
|
|
98
|
+
interface PauseProgress {
|
|
99
|
+
seen: Set<number>
|
|
100
|
+
tree: Set<number>
|
|
101
|
+
stopped: Array<number>
|
|
102
|
+
is_unread: boolean
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function stop_unseen(lane: LaneProcesses, progress: PauseProgress, probes: PauseProbes): number {
|
|
106
|
+
const read = lane_processes(lane, probes, progress.tree.size > 0)
|
|
107
|
+
const unseen = read.all.filter((pid) => !progress.seen.has(pid))
|
|
108
|
+
|
|
109
|
+
for (const pid of read.tree) progress.tree.add(pid)
|
|
110
|
+
progress.is_unread ||= read.is_unread
|
|
111
|
+
|
|
112
|
+
for (const pid of unseen) {
|
|
113
|
+
progress.seen.add(pid)
|
|
114
|
+
if (probes.signal(pid, STOP_SIGNAL)) progress.stopped.push(pid)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return unseen.length
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** SIGSTOP every process of the lane; returns the pids stopped. */
|
|
121
|
+
function pause_lane(lane: LaneProcesses, probes: PauseProbes = SYSTEM_PROBES): LaneSignalled {
|
|
122
|
+
const progress: PauseProgress = {
|
|
123
|
+
seen: new Set(),
|
|
124
|
+
tree: new Set(),
|
|
125
|
+
stopped: [],
|
|
126
|
+
is_unread: false,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
for (let round = 0; round < PAUSE_ROUNDS; round += 1) {
|
|
130
|
+
if (stop_unseen(lane, progress, probes) === 0) break
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return signalled_of(progress.stopped, progress.tree, progress.is_unread)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** SIGCONT every process of the lane; returns the pids continued. */
|
|
137
|
+
function resume_lane(lane: LaneProcesses, probes: PauseProbes = SYSTEM_PROBES): LaneSignalled {
|
|
138
|
+
const read = lane_processes(lane, probes, true)
|
|
139
|
+
const continued = read.all.filter((pid) => probes.signal(pid, CONTINUE_SIGNAL))
|
|
140
|
+
|
|
141
|
+
return signalled_of(continued, new Set(read.tree), read.is_unread)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Only what a pause reads: a lane is matched by its issue and its directory, nothing else.
|
|
145
|
+
function processes_of(lane: LaneProcesses): LaneProcesses {
|
|
146
|
+
return { issue: lane.issue, directory: lane.directory }
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function open_lanes(): Promise<Array<LaneProcesses>> {
|
|
150
|
+
const lanes = await lane_registry.list_lanes()
|
|
151
|
+
|
|
152
|
+
return lanes.map((lane) => processes_of(lane))
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const lane_pause = { PAUSE_ROUNDS, open_lanes, pause_lane, resume_lane }
|
|
156
|
+
|
|
157
|
+
export { lane_pause }
|
|
158
|
+
export type { LaneSignal, LaneSignalled, PauseProbes }
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
2
2
|
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
3
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
3
4
|
|
|
4
5
|
// Keeping a lane's uncommitted work before something discards or restarts it — `run:merge` closing a
|
|
5
6
|
// lane, `lane:restart` handing it to a fresh session. The stash stack outlives the tree, so the push is
|
|
@@ -30,6 +31,32 @@ async function announce(issue: string, message: string, cause: string): Promise<
|
|
|
30
31
|
await git_gh_issue_write.issue_try_comment(issue, preserved_comment(message, cause))
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
// The tree's work kept before a stopped child's lane is reused or closed: `saved` with the stash, or
|
|
35
|
+
// none for a clean tree, and `unsaved` with the reason when the tree could not be read or pushed — the
|
|
36
|
+
// caller then leaves the tree as it is rather than handing it on or deleting it.
|
|
37
|
+
type KeptWork =
|
|
38
|
+
| { kind: 'saved'; stash: string | undefined }
|
|
39
|
+
| { kind: 'unsaved'; directory: string; reason: string }
|
|
40
|
+
|
|
41
|
+
async function stash_of(
|
|
42
|
+
issue: string,
|
|
43
|
+
directory: string,
|
|
44
|
+
occasion: string,
|
|
45
|
+
): Promise<string | undefined> {
|
|
46
|
+
if (!(await git_stash.has_changes(directory))) return undefined
|
|
47
|
+
|
|
48
|
+
return await push_work(issue, directory, occasion)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Stash the tree's uncommitted work, if any, answering `unsaved` rather than throwing. */
|
|
52
|
+
async function keep_work(issue: string, directory: string, occasion: string): Promise<KeptWork> {
|
|
53
|
+
try {
|
|
54
|
+
return { kind: 'saved', stash: await stash_of(issue, directory, occasion) }
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return { kind: 'unsaved', directory, reason: error_text.message_of(error) }
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
33
60
|
/** `push_work`, then `announce` — for a caller with no reason to separate the two. */
|
|
34
61
|
async function stash_work(
|
|
35
62
|
issue: string,
|
|
@@ -44,6 +71,7 @@ async function stash_work(
|
|
|
44
71
|
return message
|
|
45
72
|
}
|
|
46
73
|
|
|
47
|
-
const lane_preserve = { announce,
|
|
74
|
+
const lane_preserve = { announce, keep_work, stash_work }
|
|
48
75
|
|
|
76
|
+
export type { KeptWork }
|
|
49
77
|
export { lane_preserve }
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { process_identity } from '#scripts/josh/process-identity'
|
|
2
|
+
import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
3
|
+
import { execa } from 'execa'
|
|
4
|
+
import { lane_reap, type TreeProbes } from './lane-reap'
|
|
5
|
+
import { process_tools } from './process-tools'
|
|
6
|
+
|
|
7
|
+
// Every process on the machine at one instant, read by one asynchronous `ps`, answering the probes a
|
|
8
|
+
// lane's tree is read through (joshuafolkken/kit#4241), and the listing `run:board`'s
|
|
9
|
+
// usage columns are read from (joshuafolkken/kit#4246).
|
|
10
|
+
//
|
|
11
|
+
// **Why one snapshot.** `lane_reap`'s probes start one synchronous `ps` / `pgrep` per ancestor and per
|
|
12
|
+
// descendant, so a reader that asks about every lane each few seconds — `run:board`, the backlogrun
|
|
13
|
+
// drive — blocked its event loop for over a second with seven lanes under load. The snapshot costs one
|
|
14
|
+
// spawn whatever the lane and process counts, and never blocks. `run:board` takes one per refresh and
|
|
15
|
+
// hands it to both the lane count and the usage columns (`shared`), so the two read the same instant.
|
|
16
|
+
//
|
|
17
|
+
// **The walk is not re-implemented.** `lane_reap` still walks the tree; the
|
|
18
|
+
// snapshot only answers the questions it asks. `matching` reads the full command line the way
|
|
19
|
+
// `pgrep -f` does, and `-ww` keeps `ps` from cutting it at a terminal width. The command is the full
|
|
20
|
+
// line rather than `comm`: `ps` cuts any column but the last, so the two cannot share one listing.
|
|
21
|
+
//
|
|
22
|
+
// **The start time is `process_identity`'s own reading.** A detached ship's record names its process by
|
|
23
|
+
// start time (`run-ship-detach.ts`), and the `lstart` column under `process_identity`'s environment
|
|
24
|
+
// prints it exactly as that module's own `ps` does, so a ship is told alive from these rows without
|
|
25
|
+
// starting another `ps` (joshuafolkken/kit#4245).
|
|
26
|
+
|
|
27
|
+
const COLUMNS = ['pid=', 'ppid=', 'time=', 'rss=', 'stat=', process_identity.START_TIME_FORMAT]
|
|
28
|
+
const PS_ARGUMENTS = ['-A', '-ww', '-o', [...COLUMNS, 'command='].join(',')]
|
|
29
|
+
// `ps` labels nothing locale-dependent here, and the C locale keeps its columns stable; the time zone
|
|
30
|
+
// fixes how the start time prints.
|
|
31
|
+
const PS_ENVIRONMENT = process_identity.PROBE_ENVIRONMENT
|
|
32
|
+
const FIELD_SEPARATOR = /\s+/u
|
|
33
|
+
// `lstart` prints `Tue Sep 8 08:39:04 2026`: five fields, the day of the month padded to two places.
|
|
34
|
+
const START_FIELDS = 5
|
|
35
|
+
const DAY_FIELD = 2
|
|
36
|
+
const DAY_WIDTH = 2
|
|
37
|
+
|
|
38
|
+
interface ProcessRow {
|
|
39
|
+
pid: number
|
|
40
|
+
parent: number
|
|
41
|
+
// `ps`'s cumulative CPU time as printed, `[DD-][HH:]MM:SS[.ss]`.
|
|
42
|
+
time: string
|
|
43
|
+
rss_kb: number
|
|
44
|
+
stat: string
|
|
45
|
+
// The start time as `process_identity`'s `ps` prints it.
|
|
46
|
+
start: string
|
|
47
|
+
command: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// One snapshot's rows.
|
|
51
|
+
type ProcessTable = ReadonlyArray<ProcessRow>
|
|
52
|
+
// A snapshot read on demand, `undefined` where `ps` did not answer.
|
|
53
|
+
type TableRead = () => Promise<ProcessTable | undefined>
|
|
54
|
+
|
|
55
|
+
function is_row(row: ProcessRow): boolean {
|
|
56
|
+
const { pid, parent, rss_kb, command } = row
|
|
57
|
+
|
|
58
|
+
return Number.isSafeInteger(pid + parent) && Number.isFinite(rss_kb) && command !== ''
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// The split fields put back with the day's padding the split dropped.
|
|
62
|
+
function start_of(fields: ReadonlyArray<string>): string {
|
|
63
|
+
return fields
|
|
64
|
+
.map((field, index) => (index === DAY_FIELD ? field.padStart(DAY_WIDTH) : field))
|
|
65
|
+
.join(' ')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// The command's own runs of white space read as one space, which no lane pattern tells apart.
|
|
69
|
+
function row_of(line: string): ProcessRow | undefined {
|
|
70
|
+
const [pid, parent, time = '', rss, stat = '', ...rest] = line.trim().split(FIELD_SEPARATOR)
|
|
71
|
+
const numbers = { pid: Number(pid), parent: Number(parent), rss_kb: Number(rss) }
|
|
72
|
+
const start = start_of(rest.slice(0, START_FIELDS))
|
|
73
|
+
const row = { ...numbers, time, stat, start, command: rest.slice(START_FIELDS).join(' ') }
|
|
74
|
+
|
|
75
|
+
return is_row(row) ? row : undefined
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Each `ps` line as a row; a line that does not read as one is left out. */
|
|
79
|
+
function parse(printed: string): Array<ProcessRow> {
|
|
80
|
+
return printed
|
|
81
|
+
.split('\n')
|
|
82
|
+
.map((line) => row_of(line))
|
|
83
|
+
.filter((row) => row !== undefined)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function matching_in(rows: ProcessTable, pattern: string): Array<number> {
|
|
87
|
+
const expression = new RegExp(pattern, 'u')
|
|
88
|
+
|
|
89
|
+
return rows.filter((row) => expression.test(row.command)).map((row) => row.pid)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Each parent's children, indexed once so a walk does not rescan every row per process.
|
|
93
|
+
function children_index(rows: ProcessTable): Map<number, Array<number>> {
|
|
94
|
+
const children = new Map<number, Array<number>>()
|
|
95
|
+
|
|
96
|
+
for (const { pid, parent } of rows) {
|
|
97
|
+
const siblings = children.get(parent) ?? []
|
|
98
|
+
|
|
99
|
+
siblings.push(pid)
|
|
100
|
+
children.set(parent, siblings)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return children
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** The probes a lane's tree is read through, answered from `rows` alone. */
|
|
107
|
+
function probes_of(rows: ProcessTable): TreeProbes {
|
|
108
|
+
const by_pid = new Map(rows.map((row) => [row.pid, row]))
|
|
109
|
+
const children = children_index(rows)
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
matching: (pattern) => matching_in(rows, pattern),
|
|
113
|
+
children_of: (pid) => children.get(pid) ?? [],
|
|
114
|
+
parent_of: (pid) => by_pid.get(pid)?.parent,
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** `process_identity.read_start` with its `ps` answered from `rows`: `/proc` first, as there. */
|
|
119
|
+
function start_reader(rows: ProcessTable): (pid: number) => string | undefined {
|
|
120
|
+
const starts = new Map(rows.map((row) => [row.pid, row.start]))
|
|
121
|
+
const probes = {
|
|
122
|
+
...process_identity.START_PROBES,
|
|
123
|
+
read_ps_start: (pid: number) => starts.get(pid),
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return (pid) => process_identity.read_start(pid, probes)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** The snapshot, `undefined` where `ps` did not answer; a missing `ps` is refused by name. */
|
|
130
|
+
async function read_table(): Promise<ProcessTable | undefined> {
|
|
131
|
+
try {
|
|
132
|
+
const { stdout } = await execa(lane_reap.PS_COMMAND, PS_ARGUMENTS, {
|
|
133
|
+
env: PS_ENVIRONMENT,
|
|
134
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
return parse(stdout)
|
|
138
|
+
} catch (error) {
|
|
139
|
+
process_tools.throw_if_missing(lane_reap.PS_COMMAND, error)
|
|
140
|
+
|
|
141
|
+
return undefined
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** `read`, run on the first call alone; every later call answers that same snapshot. */
|
|
146
|
+
function shared(read: TableRead): TableRead {
|
|
147
|
+
const taken: { table?: ReturnType<TableRead> } = {}
|
|
148
|
+
|
|
149
|
+
return async function table() {
|
|
150
|
+
taken.table ??= read()
|
|
151
|
+
|
|
152
|
+
return await taken.table
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const lane_process_table = {
|
|
157
|
+
PS_ARGUMENTS,
|
|
158
|
+
parse,
|
|
159
|
+
probes_of,
|
|
160
|
+
read_table,
|
|
161
|
+
shared,
|
|
162
|
+
start_reader,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export { lane_process_table }
|
|
166
|
+
export type { ProcessRow, ProcessTable, TableRead }
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { userInfo } from 'node:os'
|
|
2
|
+
import { lane_reap } from './lane-reap'
|
|
3
|
+
import { lane_residents, type ResidentLane } from './lane-residents'
|
|
4
|
+
|
|
5
|
+
// What a close does about the lane's processes once the SIGTERM went out (joshuafolkken/kit#4300).
|
|
6
|
+
//
|
|
7
|
+
// **A SIGTERM is a request, so the close looks again.** After a grace window the lane's directory is
|
|
8
|
+
// read again; whatever is still there gets a SIGKILL, and after a short wait the directory is read a
|
|
9
|
+
// last time. What survives that is reported, each with why it could — another account owns it, or it
|
|
10
|
+
// is stuck in the kernel — so `lane:close` answers `incomplete` and `run:board` can say what is wrong
|
|
11
|
+
// rather than only that something is left.
|
|
12
|
+
|
|
13
|
+
// Long enough for a node process to run its exit handlers.
|
|
14
|
+
const GRACE_MS = 3000
|
|
15
|
+
// A SIGKILL is not handled, so what still answers after this is not going to go.
|
|
16
|
+
const KILL_WAIT_MS = 1000
|
|
17
|
+
const KILL_SIGNAL = 'SIGKILL'
|
|
18
|
+
const STATE_FORMAT = ['-o', 'user=,stat=', '-p']
|
|
19
|
+
const FIELD_SEPARATOR = /\s+/u
|
|
20
|
+
const UNREADABLE_TEXT = "the lane's processes (lsof or ps failed)"
|
|
21
|
+
|
|
22
|
+
interface SettleProbes {
|
|
23
|
+
// `undefined` where the lane's processes could not be read (`lane_residents.residents`).
|
|
24
|
+
residents: (lane: ResidentLane) => Array<number> | undefined
|
|
25
|
+
kill: (pid: number) => boolean
|
|
26
|
+
wait: (milliseconds: number) => Promise<void>
|
|
27
|
+
// Why a process outlived the SIGKILL.
|
|
28
|
+
reason_of: (pid: number) => string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface Survivor {
|
|
32
|
+
pid: number
|
|
33
|
+
reason: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function kill(pid: number): boolean {
|
|
37
|
+
try {
|
|
38
|
+
process.kill(pid, KILL_SIGNAL)
|
|
39
|
+
|
|
40
|
+
return true
|
|
41
|
+
} catch {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function wait(milliseconds: number): Promise<void> {
|
|
47
|
+
await new Promise((resolve) => setTimeout(resolve, milliseconds))
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Another account's process is the usual survivor — a SIGKILL from this one is refused; otherwise
|
|
51
|
+
// `ps`'s state says it, `U` for an uninterruptible wait.
|
|
52
|
+
function reason_from(user: string, state: string): string {
|
|
53
|
+
if (user !== userInfo().username) return `owned by ${user}`
|
|
54
|
+
|
|
55
|
+
return `state ${state}`
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function reason_of(pid: number): string {
|
|
59
|
+
const printed = lane_reap.run_probe(lane_reap.PS_COMMAND, [...STATE_FORMAT, String(pid)])
|
|
60
|
+
const [user = '', state = ''] = printed.trim().split(FIELD_SEPARATOR)
|
|
61
|
+
|
|
62
|
+
return user.length === 0 ? 'unreadable' : reason_from(user, state)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const SYSTEM_PROBES: SettleProbes = {
|
|
66
|
+
residents: (lane) => lane_residents.residents(lane),
|
|
67
|
+
kill,
|
|
68
|
+
wait,
|
|
69
|
+
reason_of,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// A reading that failed is not an empty one.
|
|
73
|
+
function is_empty(reading: ReadonlyArray<number> | undefined): boolean {
|
|
74
|
+
return reading?.length === 0
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function kill_all(
|
|
78
|
+
lingering: ReadonlyArray<number> | undefined,
|
|
79
|
+
probes: SettleProbes,
|
|
80
|
+
): Promise<void> {
|
|
81
|
+
const targets = lingering ?? []
|
|
82
|
+
|
|
83
|
+
for (const pid of targets) probes.kill(pid)
|
|
84
|
+
|
|
85
|
+
await probes.wait(KILL_WAIT_MS)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function survivors(lane: ResidentLane, probes: SettleProbes): Array<Survivor> | undefined {
|
|
89
|
+
return probes.residents(lane)?.map((pid) => ({ pid, reason: probes.reason_of(pid) }))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Wait out the SIGTERM a reap sent, SIGKILL what is still in the lane's directory, and answer what
|
|
94
|
+
* outlived even that — the empty list is a lane with no process left, `undefined` a last reading that
|
|
95
|
+
* failed. A failed reading is never read as none: it is read again, and nothing is killed on it.
|
|
96
|
+
*/
|
|
97
|
+
async function settle(
|
|
98
|
+
lane: ResidentLane,
|
|
99
|
+
probes: SettleProbes = SYSTEM_PROBES,
|
|
100
|
+
): Promise<Array<Survivor> | undefined> {
|
|
101
|
+
if (is_empty(probes.residents(lane))) return []
|
|
102
|
+
|
|
103
|
+
await probes.wait(GRACE_MS)
|
|
104
|
+
|
|
105
|
+
const lingering = probes.residents(lane)
|
|
106
|
+
|
|
107
|
+
if (is_empty(lingering)) return []
|
|
108
|
+
|
|
109
|
+
await kill_all(lingering, probes)
|
|
110
|
+
|
|
111
|
+
return survivors(lane, probes)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** How a close's `left_behind` names what `settle` answered; a failed reading is named as such. */
|
|
115
|
+
function survivor_texts(settled: ReadonlyArray<Survivor> | undefined): Array<string> {
|
|
116
|
+
if (settled === undefined) return [UNREADABLE_TEXT]
|
|
117
|
+
|
|
118
|
+
return settled.map((survivor) => `process ${String(survivor.pid)} (${survivor.reason})`)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const lane_reap_settle = { GRACE_MS, KILL_WAIT_MS, reason_from, settle, survivor_texts }
|
|
122
|
+
|
|
123
|
+
export type { SettleProbes, Survivor }
|
|
124
|
+
export { lane_reap_settle }
|
|
@@ -18,6 +18,9 @@ import { process_tools } from './process-tools'
|
|
|
18
18
|
//
|
|
19
19
|
// **The caller's own ancestry is never touched.** A `lane:close` issued from inside the lane it
|
|
20
20
|
// closes would otherwise end the very session running it, before it could report.
|
|
21
|
+
//
|
|
22
|
+
// **What runs from the lane outside the tree is `lane-residents.ts`'s** (joshuafolkken/kit#4300): the
|
|
23
|
+
// edit hook's `eslint_d`, a `script` wrapper re-parented to pid 1, found by working directory or mark.
|
|
21
24
|
|
|
22
25
|
const PGREP_COMMAND = 'pgrep'
|
|
23
26
|
const MATCH_FULL_COMMAND_LINE = '-f'
|
|
@@ -26,13 +29,24 @@ const CHILDREN_OF_FLAG = '-P'
|
|
|
26
29
|
const PS_COMMAND = '/bin/ps'
|
|
27
30
|
const PARENT_FORMAT = ['-o', 'ppid=', '-p']
|
|
28
31
|
const TERMINATE_SIGNAL = 'SIGTERM'
|
|
32
|
+
const CONTINUE_SIGNAL = 'SIGCONT'
|
|
29
33
|
// `0` addresses the caller's own process group and `1` is init — neither is ever a lane child.
|
|
30
34
|
const LOWEST_CHILD_PID = 2
|
|
31
35
|
|
|
32
|
-
|
|
36
|
+
// The lane a reap or a pause acts on: the child by its issue, the rest by its directory.
|
|
37
|
+
interface LaneProcesses {
|
|
38
|
+
issue: string
|
|
39
|
+
directory: string
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// What collecting a lane's process tree reads — shared with `lane:pause` (`lane-pause.ts`).
|
|
43
|
+
interface TreeProbes {
|
|
33
44
|
matching: (pattern: string) => Array<number>
|
|
34
45
|
children_of: (pid: number) => Array<number>
|
|
35
46
|
parent_of: (pid: number) => number | undefined
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface ReapProbes extends TreeProbes {
|
|
36
50
|
terminate: (pid: number) => boolean
|
|
37
51
|
}
|
|
38
52
|
|
|
@@ -64,9 +78,9 @@ function parent_of(pid: number): number | undefined {
|
|
|
64
78
|
return parse_pids(run_probe(PS_COMMAND, [...PARENT_FORMAT, String(pid)]))[0]
|
|
65
79
|
}
|
|
66
80
|
|
|
67
|
-
function
|
|
81
|
+
function send(pid: number, name: NodeJS.Signals): boolean {
|
|
68
82
|
try {
|
|
69
|
-
process.kill(pid,
|
|
83
|
+
process.kill(pid, name)
|
|
70
84
|
|
|
71
85
|
return true
|
|
72
86
|
} catch {
|
|
@@ -74,6 +88,16 @@ function terminate(pid: number): boolean {
|
|
|
74
88
|
}
|
|
75
89
|
}
|
|
76
90
|
|
|
91
|
+
// A stopped process (`lane:pause`) holds a SIGTERM it handles pending until it is continued, so the
|
|
92
|
+
// terminate is followed by a SIGCONT; a running process ignores it.
|
|
93
|
+
function terminate(pid: number): boolean {
|
|
94
|
+
if (!send(pid, TERMINATE_SIGNAL)) return false
|
|
95
|
+
|
|
96
|
+
send(pid, CONTINUE_SIGNAL)
|
|
97
|
+
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
100
|
+
|
|
77
101
|
const SYSTEM_PROBES: ReapProbes = {
|
|
78
102
|
matching: (pattern) => parse_pids(run_probe(PGREP_COMMAND, [MATCH_FULL_COMMAND_LINE, pattern])),
|
|
79
103
|
children_of: (pid) => parse_pids(run_probe(PGREP_COMMAND, [CHILDREN_OF_FLAG, String(pid)])),
|
|
@@ -81,7 +105,7 @@ const SYSTEM_PROBES: ReapProbes = {
|
|
|
81
105
|
terminate,
|
|
82
106
|
}
|
|
83
107
|
|
|
84
|
-
function ancestry_of(pid: number, probes:
|
|
108
|
+
function ancestry_of(pid: number, probes: TreeProbes): Set<number> {
|
|
85
109
|
const ancestry = new Set<number>([pid])
|
|
86
110
|
let current = probes.parent_of(pid)
|
|
87
111
|
|
|
@@ -95,11 +119,11 @@ function ancestry_of(pid: number, probes: ReapProbes): Set<number> {
|
|
|
95
119
|
|
|
96
120
|
// This process and every process above it. The Stop hook reads it to tell whether the session that
|
|
97
121
|
// declared a carry record's `--owner "$PPID"` is the one it runs under.
|
|
98
|
-
function own_ancestry(probes:
|
|
122
|
+
function own_ancestry(probes: TreeProbes = SYSTEM_PROBES): Set<number> {
|
|
99
123
|
return ancestry_of(process.pid, probes)
|
|
100
124
|
}
|
|
101
125
|
|
|
102
|
-
function tree_of(roots: ReadonlyArray<number>, probes:
|
|
126
|
+
function tree_of(roots: ReadonlyArray<number>, probes: TreeProbes): Array<number> {
|
|
103
127
|
const tree: Array<number> = []
|
|
104
128
|
const pending = [...roots]
|
|
105
129
|
let next = pending.shift()
|
|
@@ -116,35 +140,46 @@ function tree_of(roots: ReadonlyArray<number>, probes: ReapProbes): Array<number
|
|
|
116
140
|
return tree
|
|
117
141
|
}
|
|
118
142
|
|
|
119
|
-
function roots_of(issue: string, own: Set<number>, probes:
|
|
143
|
+
function roots_of(issue: string, own: Set<number>, probes: TreeProbes): Array<number> {
|
|
120
144
|
const pattern = lane_child_invocation.process_pattern(issue)
|
|
121
145
|
|
|
122
146
|
return probes.matching(pattern).filter((pid) => !own.has(pid))
|
|
123
147
|
}
|
|
124
148
|
|
|
125
149
|
/**
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
* that had already ended by itself.
|
|
150
|
+
* Every process of the lane child for `issue` and everything under it, collected before anything is
|
|
151
|
+
* signalled, the caller's own ancestry left out.
|
|
129
152
|
*/
|
|
130
|
-
function
|
|
153
|
+
function lane_tree(issue: string, probes: TreeProbes = SYSTEM_PROBES): Array<number> {
|
|
131
154
|
const own = own_ancestry(probes)
|
|
132
|
-
const doomed = tree_of(roots_of(issue, own, probes), probes).filter((pid) => !own.has(pid))
|
|
133
155
|
|
|
134
|
-
return
|
|
156
|
+
return tree_of(roots_of(issue, own, probes), probes).filter((pid) => !own.has(pid))
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Terminate every process of the lane child for `lane.issue` and everything under it, sparing the
|
|
161
|
+
* caller's own ancestry. Returns the pids that were signalled — the empty list is the healthy case, a
|
|
162
|
+
* child that had already ended by itself.
|
|
163
|
+
*/
|
|
164
|
+
function reap_child(lane: LaneProcesses, probes: ReapProbes = SYSTEM_PROBES): Array<number> {
|
|
165
|
+
return lane_tree(lane.issue, probes).filter((pid) => probes.terminate(pid))
|
|
135
166
|
}
|
|
136
167
|
|
|
137
168
|
/** Whether a lane child for `issue` is running, by the same match `reap_child` would end. */
|
|
138
|
-
function is_child_running(issue: string, probes:
|
|
169
|
+
function is_child_running(issue: string, probes: TreeProbes = SYSTEM_PROBES): boolean {
|
|
139
170
|
return roots_of(issue, own_ancestry(probes), probes).length > 0
|
|
140
171
|
}
|
|
141
172
|
|
|
142
173
|
const lane_reap = {
|
|
143
174
|
is_child_running,
|
|
175
|
+
lane_tree,
|
|
144
176
|
own_ancestry,
|
|
145
177
|
parse_pids,
|
|
178
|
+
PS_COMMAND,
|
|
146
179
|
reap_child,
|
|
180
|
+
run_probe,
|
|
181
|
+
SYSTEM_PROBES,
|
|
147
182
|
}
|
|
148
183
|
|
|
149
|
-
export type { ReapProbes }
|
|
184
|
+
export type { LaneProcesses, ReapProbes, TreeProbes }
|
|
150
185
|
export { lane_reap }
|