@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,183 @@
|
|
|
1
|
+
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
2
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
3
|
+
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
4
|
+
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
5
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
6
|
+
import { run_event_stream } from '#scripts/run/event/run-event-stream'
|
|
7
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
8
|
+
import { run_label } from '#scripts/run/run-label'
|
|
9
|
+
import { lane_close, type CloseKind } from './lane-close'
|
|
10
|
+
import { lane_preserve, type KeptWork } from './lane-preserve'
|
|
11
|
+
import { lane_reap } from './lane-reap'
|
|
12
|
+
import { lane_registry, type LaneInfo } from './lane-registry'
|
|
13
|
+
import { lane_residents } from './lane-residents'
|
|
14
|
+
import { lane_state } from './lane-state'
|
|
15
|
+
|
|
16
|
+
// `josh lane:withdraw <N> --reason <text>` — a person takes a running lane child's issue out of the
|
|
17
|
+
// current run: the child is stopped, its work stashed and the lane closed. **The Issue stays open** —
|
|
18
|
+
// a withdrawal ends this run's attempt, not the work — so a later run offers it again; this run does
|
|
19
|
+
// not (`backlog-drive-restore.ts` → `offer_exclude`, and the drive's own exclusion).
|
|
20
|
+
//
|
|
21
|
+
// **The `withdraw` event is written first, before anything is stopped.** Killing the child alone would
|
|
22
|
+
// let `lane:await` book it stopped and `run:merge` classify it from GitHub — an open issue resumed as an
|
|
23
|
+
// `outage` or parked `run:stalled`. `run:merge` reads the event stream before GitHub, so a child whose
|
|
24
|
+
// newest launch-or-withdraw event is a withdraw is booked `withdrawn` whatever the Issue's state reads.
|
|
25
|
+
//
|
|
26
|
+
// A tree that could not be stashed is left in place: closing the lane would delete the work, and the
|
|
27
|
+
// person decides what to keep.
|
|
28
|
+
|
|
29
|
+
const WITHDRAW_OCCASION = 'lane withdraw'
|
|
30
|
+
const WITHDRAW_CAUSE = 'a person withdrew it with `lane:withdraw`'
|
|
31
|
+
const CLOSED_STATE = 'CLOSED'
|
|
32
|
+
const CLOSED_KIND = 'closed'
|
|
33
|
+
const NO_LANE_KIND = 'no-lane'
|
|
34
|
+
const UNREADABLE_KIND = 'unreadable'
|
|
35
|
+
|
|
36
|
+
type Unsaved = Extract<KeptWork, { kind: 'unsaved' }>
|
|
37
|
+
|
|
38
|
+
interface Withdrawn {
|
|
39
|
+
kind: 'withdrawn'
|
|
40
|
+
// How many of the child's processes the withdrawal stopped — 0 for a child that had already ended.
|
|
41
|
+
reaped: number
|
|
42
|
+
stash: string | undefined
|
|
43
|
+
// Whether the comment saying the issue stays open reached it.
|
|
44
|
+
is_noted: boolean
|
|
45
|
+
lane: CloseKind
|
|
46
|
+
// What else the close ended from the checkout; `undefined` where it could not be read.
|
|
47
|
+
residents: ReadonlyArray<number> | undefined
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
type Refused =
|
|
51
|
+
{ kind: typeof CLOSED_KIND } | { kind: typeof NO_LANE_KIND } | { kind: typeof UNREADABLE_KIND }
|
|
52
|
+
type WithdrawOutcome = Withdrawn | Unsaved | Refused
|
|
53
|
+
|
|
54
|
+
function withdraw_comment(reason: string): string {
|
|
55
|
+
return [
|
|
56
|
+
'Withdrawn from the current run by a person with `pnpm josh lane:withdraw`.',
|
|
57
|
+
'Its lane child was stopped and the lane closed. The Issue stays open: this run does not resume it, and the next run offers it again.',
|
|
58
|
+
`- Why: ${reason}`,
|
|
59
|
+
].join('\n')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function record_withdraw(issue: string, reason: string): Promise<void> {
|
|
63
|
+
await run_event_stream_emit.emit(
|
|
64
|
+
run_event_stream.EVENT_KIND.WITHDRAW,
|
|
65
|
+
`${issue_cite.plain(issue)} withdrawn by a person: ${reason}`,
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// A closed issue has nothing to withdraw, and an unread one might be: neither writes anything.
|
|
70
|
+
async function refusal_of(issue: string): Promise<Refused | undefined> {
|
|
71
|
+
const read = await issue_state_cli.read_issue(issue)
|
|
72
|
+
|
|
73
|
+
if (read.kind !== 'state') return { kind: UNREADABLE_KIND }
|
|
74
|
+
if (read.state.state.toUpperCase() === CLOSED_STATE) return { kind: CLOSED_KIND }
|
|
75
|
+
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function note_issue(
|
|
80
|
+
issue: string,
|
|
81
|
+
reason: string,
|
|
82
|
+
stash: string | undefined,
|
|
83
|
+
): Promise<boolean> {
|
|
84
|
+
const is_noted = await git_gh_issue_write.issue_try_comment(issue, withdraw_comment(reason))
|
|
85
|
+
|
|
86
|
+
if (stash !== undefined) await lane_preserve.announce(issue, stash, WITHDRAW_CAUSE)
|
|
87
|
+
await run_label.unmark(issue)
|
|
88
|
+
|
|
89
|
+
return is_noted
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function stop_and_close(lane: LaneInfo, reason: string): Promise<WithdrawOutcome> {
|
|
93
|
+
await record_withdraw(lane.issue, reason)
|
|
94
|
+
const reaped = lane_reap.reap_child(lane).length
|
|
95
|
+
const saved = await lane_preserve.keep_work(lane.issue, lane.directory, WITHDRAW_OCCASION)
|
|
96
|
+
|
|
97
|
+
if (saved.kind === 'unsaved') return saved
|
|
98
|
+
const is_noted = await note_issue(lane.issue, reason, saved.stash)
|
|
99
|
+
const closed = await lane_close.close_lane(lane.issue)
|
|
100
|
+
|
|
101
|
+
// After the close, so the record names the withdrawal rather than the close it ran. An `incomplete`
|
|
102
|
+
// close is not `ended`: the supervisor closes the lane again until its last process is gone.
|
|
103
|
+
if (closed.kind !== 'incomplete') {
|
|
104
|
+
await lane_state.record_change({ issue: lane.issue, state: 'ended', command: 'lane:withdraw' })
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
kind: 'withdrawn',
|
|
109
|
+
reaped,
|
|
110
|
+
stash: saved.stash,
|
|
111
|
+
is_noted,
|
|
112
|
+
lane: closed.kind,
|
|
113
|
+
residents: closed.residents,
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Stop `#<N>`'s lane child, stash its work and close the lane, leaving the Issue open. */
|
|
118
|
+
async function withdraw(issue: string, reason: string): Promise<WithdrawOutcome> {
|
|
119
|
+
issue_number_shape.require_issue_number(issue)
|
|
120
|
+
const refusal = await refusal_of(issue)
|
|
121
|
+
|
|
122
|
+
if (refusal !== undefined) return refusal
|
|
123
|
+
const lane = await lane_registry.find_open_lane(issue)
|
|
124
|
+
|
|
125
|
+
if (lane === undefined) return { kind: NO_LANE_KIND }
|
|
126
|
+
|
|
127
|
+
return await stop_and_close(lane, reason)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function stash_sentence(stash: string | undefined): string {
|
|
131
|
+
if (stash === undefined) return 'The lane held no uncommitted work.'
|
|
132
|
+
|
|
133
|
+
return `Its uncommitted work was stashed — recover with \`pnpm josh stash:pop "${stash}"\`.`
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// What the lane's close left or ended, as a suffix.
|
|
137
|
+
function lane_suffix(outcome: Withdrawn, cited: string): string {
|
|
138
|
+
const removed = outcome.lane === 'incomplete' ? ' The lane could not be fully removed.' : ''
|
|
139
|
+
const residents = lane_residents.residents_sentence(outcome.residents, cited)
|
|
140
|
+
|
|
141
|
+
return residents === undefined ? removed : `${removed} ${residents}`
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function withdrawn_text(outcome: Withdrawn, issue: string): string {
|
|
145
|
+
const cited = session_cite.issue(issue)
|
|
146
|
+
const stopped = outcome.reaped === 0 ? 'Its child had already ended.' : 'Stopped its child.'
|
|
147
|
+
const head = `Withdrew ${cited}. ${stopped} ${stash_sentence(outcome.stash)}`
|
|
148
|
+
const lane = lane_suffix(outcome, cited)
|
|
149
|
+
const noted = outcome.is_noted ? '' : ' The comment saying so could not be posted.'
|
|
150
|
+
|
|
151
|
+
return `${head} The Issue stays open: this run does not offer it again, the next run does.${noted}${lane}`
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function unsaved_text(outcome: Unsaved, issue: string): string {
|
|
155
|
+
return `The child for ${session_cite.issue(issue)} was stopped, but its uncommitted work could not be stashed (${outcome.reason}), so the lane is left at ${outcome.directory}; \`run:merge\` books it withdrawn.`
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function refused_text(outcome: Refused, issue: string): string {
|
|
159
|
+
const cited = session_cite.issue(issue)
|
|
160
|
+
|
|
161
|
+
if (outcome.kind === CLOSED_KIND) {
|
|
162
|
+
return `${cited} is already closed, so there is nothing to withdraw.`
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (outcome.kind === NO_LANE_KIND) {
|
|
166
|
+
return `No lane is open for ${cited}, so there is no child to withdraw.`
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return `The state of ${cited} could not be read, so nothing was stopped or closed — try again.`
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function describe(outcome: WithdrawOutcome, issue: string): string {
|
|
173
|
+
if (outcome.kind === 'unsaved') return unsaved_text(outcome, issue)
|
|
174
|
+
|
|
175
|
+
return outcome.kind === 'withdrawn'
|
|
176
|
+
? withdrawn_text(outcome, issue)
|
|
177
|
+
: refused_text(outcome, issue)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const lane_withdraw = { describe, withdraw }
|
|
181
|
+
|
|
182
|
+
export type { WithdrawOutcome }
|
|
183
|
+
export { lane_withdraw }
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
4
|
+
import { lane_paths } from './lane-paths'
|
|
5
|
+
|
|
6
|
+
// Each process's working directory, read with `lsof` — the one place its output is parsed.
|
|
7
|
+
//
|
|
8
|
+
// **A process belongs to a lane by its working directory first, its ancestry only after.** A process
|
|
9
|
+
// detached from a lane (`josh ship --detach`, a diagnostic started under `script`) is re-parented to
|
|
10
|
+
// pid 1, so no parent chain reaches it, while its working directory still sits under `.kit-lanes/<N>`.
|
|
11
|
+
// `run:board` draws such a process as a lane's or a leftover, and `lane:close` ends it
|
|
12
|
+
// (joshuafolkken/kit#4304); the board falls back to the ancestry where the directory names no lane
|
|
13
|
+
// (`run-board-usage-lanes.ts`).
|
|
14
|
+
// **macOS alone**, as the board reads it: elsewhere nothing is listed.
|
|
15
|
+
|
|
16
|
+
const LSOF_COMMAND = 'lsof'
|
|
17
|
+
// `-a` joins the conditions: the `cwd` descriptor only, in `-F` fields. The board appends `-p <pids>`.
|
|
18
|
+
const CWD_ARGUMENTS = ['-a', '-d', 'cwd', '-Fn']
|
|
19
|
+
// `lsof -F`'s field lines: `p<pid>` opens a process, `n<path>` names its directory.
|
|
20
|
+
const LSOF_PROCESS = /^(?=p)/mu
|
|
21
|
+
const LSOF_NAME = 'n'
|
|
22
|
+
const LISTING_PLATFORMS: ReadonlySet<NodeJS.Platform> = new Set(['darwin'])
|
|
23
|
+
|
|
24
|
+
function lsof_block(block: string): [number, string] | undefined {
|
|
25
|
+
const [process_line = '', ...rest] = block.trim().split('\n')
|
|
26
|
+
const name = rest.find((line) => line.startsWith(LSOF_NAME))
|
|
27
|
+
|
|
28
|
+
return name === undefined ? undefined : [Number(process_line.slice(1)), name.slice(1)]
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Each process's working directory from `lsof -F`'s output. */
|
|
32
|
+
function parse(output: string): Map<number, string> {
|
|
33
|
+
const blocks = output.split(LSOF_PROCESS).map((block) => lsof_block(block))
|
|
34
|
+
|
|
35
|
+
return new Map(blocks.filter((block) => block !== undefined))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Every process's working directory, `undefined` where `lsof` could not be run or timed out — never
|
|
40
|
+
* read as "nothing there". `lsof` exits non-zero when one process cannot be read and still lists the
|
|
41
|
+
* rest, so its output is read whatever the exit status.
|
|
42
|
+
*/
|
|
43
|
+
function list_all(platform: NodeJS.Platform = process.platform): Map<number, string> | undefined {
|
|
44
|
+
if (!LISTING_PLATFORMS.has(platform)) return new Map()
|
|
45
|
+
|
|
46
|
+
const result = spawnSync(LSOF_COMMAND, CWD_ARGUMENTS, {
|
|
47
|
+
encoding: 'utf8',
|
|
48
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
49
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return result.error === undefined ? parse(result.stdout) : undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The lane of `root` a directory sits under — itself or a directory above it, the outermost first.
|
|
57
|
+
* The one lane-membership reading: the board draws a leftover by it, and the close ends by it
|
|
58
|
+
* (joshuafolkken/kit#4300).
|
|
59
|
+
*/
|
|
60
|
+
function lane_of(directory: string, root: string): string | undefined {
|
|
61
|
+
const parts = directory.split(path.sep)
|
|
62
|
+
const ancestors = parts.map((_, index) => parts.slice(0, index + 1).join(path.sep)).slice(1)
|
|
63
|
+
const environment = { [lane_paths.LANE_ROOT_KEY]: root }
|
|
64
|
+
|
|
65
|
+
return ancestors.map((ancestor) => lane_paths.lane_issue_of(ancestor, environment)).find(Boolean)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const process_directories = { CWD_ARGUMENTS, lane_of, list_all, parse }
|
|
69
|
+
|
|
70
|
+
export { process_directories }
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
3
|
+
import { lane_child_marker } from './lane-child-marker'
|
|
4
|
+
|
|
5
|
+
// Each process's lane mark — the `JOSH_LANE_CHILD` it inherited — read from `ps -E`
|
|
6
|
+
// (joshuafolkken/kit#4315).
|
|
7
|
+
//
|
|
8
|
+
// **A process belongs to a lane by its mark wherever it runs.** A lane child that measures something
|
|
9
|
+
// from the main checkout or `/tmp` leaves processes whose working directory is not under the lane, and
|
|
10
|
+
// one started under `script` or a new session has left the child's tree and group for pid 1. The
|
|
11
|
+
// environment survives all of that, and `lane:dispatch` puts the issue number in it
|
|
12
|
+
// (`lane-child-marker.ts`), so the mark names the lane a process was started from.
|
|
13
|
+
//
|
|
14
|
+
// **The mark is read from the environment, never from the arguments.** `ps -E` appends the environment
|
|
15
|
+
// to the command line, so the plain command line is read too and only what follows it is searched: a
|
|
16
|
+
// `grep JOSH_LANE_CHILD=42` carries the text without the mark.
|
|
17
|
+
//
|
|
18
|
+
// **An application bundle is never marked.** A lane that opened Docker Desktop passed its environment
|
|
19
|
+
// to an application the whole machine uses; it is a person's, not the lane's.
|
|
20
|
+
//
|
|
21
|
+
// **macOS alone**, as `process-directories.ts` reads it: elsewhere nothing is listed.
|
|
22
|
+
|
|
23
|
+
const PS_COMMAND = '/bin/ps'
|
|
24
|
+
const LISTING_ARGUMENTS = ['-A', '-ww', '-o', 'pid=,command=']
|
|
25
|
+
const ENVIRONMENT_FLAG = '-E'
|
|
26
|
+
// `ps -E` over every process runs to hundreds of kilobytes; the default 1 MiB would cut it short.
|
|
27
|
+
const LISTING_BUFFER_BYTES = 67_108_864
|
|
28
|
+
const PID_LINE = /^\s*(?<pid>\d+) (?<command>.*)$/u
|
|
29
|
+
const APPLICATION_BUNDLE = '.app/Contents/'
|
|
30
|
+
const LISTING_PLATFORMS: ReadonlySet<NodeJS.Platform> = new Set(['darwin'])
|
|
31
|
+
const MARK = new RegExp(String.raw`(?:^|\s)${lane_child_marker.KEY}=(?<issue>\d+)(?=\s|$)`, 'u')
|
|
32
|
+
|
|
33
|
+
function command_lines(printed: string): Map<number, string> {
|
|
34
|
+
const groups = printed.split('\n').map((line) => PID_LINE.exec(line)?.groups)
|
|
35
|
+
|
|
36
|
+
return new Map(
|
|
37
|
+
groups
|
|
38
|
+
.filter((group) => group !== undefined)
|
|
39
|
+
.map((group) => [Number(group['pid']), group['command'] ?? '']),
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// What `ps -E` printed after the plain command line; `undefined` for an application bundle and for a
|
|
44
|
+
// process the two listings disagree on (it ended or exec'd between them).
|
|
45
|
+
function environment_of(command: string | undefined, with_environment: string): string | undefined {
|
|
46
|
+
if (command === undefined || command.includes(APPLICATION_BUNDLE)) return undefined
|
|
47
|
+
|
|
48
|
+
return with_environment.startsWith(command) ? with_environment.slice(command.length) : undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function mark_of(command: string | undefined, with_environment: string): string | undefined {
|
|
52
|
+
const environment = environment_of(command, with_environment)
|
|
53
|
+
|
|
54
|
+
return environment === undefined ? undefined : MARK.exec(environment)?.groups?.['issue']
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Each marked process's issue, from `ps`'s plain and `-E` listings. */
|
|
58
|
+
function parse(plain: string, with_environment: string): Map<number, string> {
|
|
59
|
+
const commands = command_lines(plain)
|
|
60
|
+
const marks = [...command_lines(with_environment)].map(
|
|
61
|
+
([pid, line]) => [pid, mark_of(commands.get(pid), line)] as const,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return new Map(marks.filter((pair): pair is [number, string] => pair[1] !== undefined))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function listing(arguments_: ReadonlyArray<string>): string | undefined {
|
|
68
|
+
const result = spawnSync(PS_COMMAND, arguments_, {
|
|
69
|
+
encoding: 'utf8',
|
|
70
|
+
maxBuffer: LISTING_BUFFER_BYTES,
|
|
71
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
72
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
return result.error === undefined ? result.stdout : undefined
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Every marked process's issue, `undefined` where `ps` could not be run or timed out — never read as
|
|
80
|
+
* "nothing marked".
|
|
81
|
+
*/
|
|
82
|
+
function list_all(platform: NodeJS.Platform = process.platform): Map<number, string> | undefined {
|
|
83
|
+
if (!LISTING_PLATFORMS.has(platform)) return new Map()
|
|
84
|
+
const plain = listing(LISTING_ARGUMENTS)
|
|
85
|
+
const with_environment = listing([ENVIRONMENT_FLAG, ...LISTING_ARGUMENTS])
|
|
86
|
+
|
|
87
|
+
if (plain === undefined || with_environment === undefined) return undefined
|
|
88
|
+
|
|
89
|
+
return parse(plain, with_environment)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const process_lane_marks = { list_all, parse }
|
|
93
|
+
|
|
94
|
+
export { process_lane_marks }
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto'
|
|
2
|
+
import { chmodSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
|
|
5
|
+
// Replacing a file so a concurrent reader sees the old content or the new, never half of either.
|
|
6
|
+
//
|
|
7
|
+
// The content is written to a staging file and renamed over the target; `rename` swaps the path
|
|
8
|
+
// itself, so a reader that opened the old file keeps reading it. **The staging name is unique per
|
|
9
|
+
// write** — process id and a random UUID — because two writers sharing one name interleave their bytes
|
|
10
|
+
// into the same staging file and both rename the mix into place. Create-exclusively refuses a name
|
|
11
|
+
// someone else already holds rather than writing through it, and the `finally` removes the staging
|
|
12
|
+
// file on every failing path. The `.tmp` ending keeps it out of a directory scan that matches the
|
|
13
|
+
// target's own extension.
|
|
14
|
+
|
|
15
|
+
const STAGING_EXTENSION = '.tmp'
|
|
16
|
+
const CREATE_EXCLUSIVE_FLAG = 'wx'
|
|
17
|
+
|
|
18
|
+
interface AtomicWriteOptions {
|
|
19
|
+
// Given to the create, so a private file is never readable at another mode in between, and
|
|
20
|
+
// applied again with `chmod`, so the umask cannot narrow it.
|
|
21
|
+
readonly mode?: number
|
|
22
|
+
// Where the staging file is written; the target's directory by default. It must sit on the
|
|
23
|
+
// target's filesystem for the rename to stay atomic.
|
|
24
|
+
readonly staging_directory?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function staging_path(target: string, staging_directory: string): string {
|
|
28
|
+
const name = `${path.basename(target)}.${String(process.pid)}.${randomUUID()}${STAGING_EXTENSION}`
|
|
29
|
+
|
|
30
|
+
return path.join(staging_directory, name)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function write_staged(staging: string, content: string | Uint8Array, mode?: number): void {
|
|
34
|
+
writeFileSync(staging, content, {
|
|
35
|
+
flag: CREATE_EXCLUSIVE_FLAG,
|
|
36
|
+
...(mode !== undefined && { mode }),
|
|
37
|
+
})
|
|
38
|
+
if (mode !== undefined) chmodSync(staging, mode)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function replace_file(
|
|
42
|
+
target: string,
|
|
43
|
+
content: string | Uint8Array,
|
|
44
|
+
options: AtomicWriteOptions = {},
|
|
45
|
+
): void {
|
|
46
|
+
const directory = options.staging_directory ?? path.dirname(target)
|
|
47
|
+
const staging = staging_path(target, directory)
|
|
48
|
+
|
|
49
|
+
mkdirSync(directory, { recursive: true })
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
write_staged(staging, content, options.mode)
|
|
53
|
+
renameSync(staging, target)
|
|
54
|
+
} finally {
|
|
55
|
+
rmSync(staging, { force: true })
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const atomic_write = { replace_file }
|
|
60
|
+
|
|
61
|
+
export { atomic_write }
|
|
62
|
+
export type { AtomicWriteOptions }
|
|
@@ -69,6 +69,16 @@ function collect_output(all: string, reason: ReadonlyArray<string>): string {
|
|
|
69
69
|
return [all, ...reason].filter((part) => part !== '').join('\n')
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
// A buffered child writes to a pipe, so it is told to keep its colors unless the caller opted out.
|
|
73
|
+
// Exported for the eslint daemon route (`eslint-daemon.ts`), which buffers the same way.
|
|
74
|
+
function child_environment(): NodeJS.ProcessEnv {
|
|
75
|
+
const environment = { ...process.env }
|
|
76
|
+
if (environment['NO_COLOR'] === undefined) environment['FORCE_COLOR'] = FORCE_COLOR
|
|
77
|
+
else delete environment['FORCE_COLOR']
|
|
78
|
+
|
|
79
|
+
return environment
|
|
80
|
+
}
|
|
81
|
+
|
|
72
82
|
async function run_buffered_process(
|
|
73
83
|
command_args: ReadonlyArray<string>,
|
|
74
84
|
options: BufferedProcessOptions = {},
|
|
@@ -76,14 +86,11 @@ async function run_buffered_process(
|
|
|
76
86
|
// `performance.now()` rather than `Date.now()`: it is monotonic, so a system clock adjusted
|
|
77
87
|
// mid-check cannot produce a negative or wildly inflated duration.
|
|
78
88
|
const started_at = performance.now()
|
|
79
|
-
const environment = { ...process.env }
|
|
80
|
-
if (environment['NO_COLOR'] === undefined) environment['FORCE_COLOR'] = FORCE_COLOR
|
|
81
|
-
else delete environment['FORCE_COLOR']
|
|
82
89
|
// `cwd` is spread in rather than assigned: `exactOptionalPropertyTypes` refuses an explicit
|
|
83
90
|
// `undefined` for an optional `string`, and passing one anyway breaks execa's overload
|
|
84
91
|
// resolution — which silently widens `result.all` back to `string | undefined`.
|
|
85
92
|
const result = await execa(PNPM, [...command_args], {
|
|
86
|
-
env:
|
|
93
|
+
env: child_environment(),
|
|
87
94
|
extendEnv: false,
|
|
88
95
|
all: true,
|
|
89
96
|
reject: false,
|
|
@@ -104,7 +111,7 @@ function is_process_failed(result: Pick<BufferedProcessResult, 'exit_code'>): bo
|
|
|
104
111
|
return result.exit_code !== 0
|
|
105
112
|
}
|
|
106
113
|
|
|
107
|
-
const buffered_process = { is_process_failed, run_buffered_process }
|
|
114
|
+
const buffered_process = { child_environment, is_process_failed, run_buffered_process }
|
|
108
115
|
|
|
109
116
|
export type { BufferedProcessResult }
|
|
110
117
|
export { buffered_process, FAIL_EXIT_CODE }
|
package/scripts/lib/cli-flags.ts
CHANGED
|
@@ -152,7 +152,59 @@ function attach_values(
|
|
|
152
152
|
return attached
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
// Digits and nothing else. `Number('')`, `Number(' ')` and `Number('0x10')` are all safe integers, so a
|
|
156
|
+
// check that only asked `Number.isSafeInteger` would read an unset shell variable — `--max
|
|
157
|
+
// "$max_issues"` — as zero. The magnitude check is separate because the pattern bounds nothing: a
|
|
158
|
+
// number past the safe range would be read as a different number.
|
|
159
|
+
const COUNT_PATTERN = /^\d+$/u
|
|
160
|
+
// Whole and positive: `0`, a sign, a decimal point and anything not a digit are refused.
|
|
161
|
+
const POSITIVE_PATTERN = /^[1-9]\d*$/u
|
|
162
|
+
|
|
163
|
+
// The value a positive-integer setting answers, or why it could not be read. A problem rather than a
|
|
164
|
+
// throw: the caller decides whether a bad setting ends the command or is reported and worked around.
|
|
165
|
+
type PositiveSetting = { kind: 'limit'; limit: number } | { kind: 'problem'; problem: string }
|
|
166
|
+
|
|
167
|
+
function to_integer(raw: string | undefined, pattern: RegExp): number | undefined {
|
|
168
|
+
if (raw === undefined || !pattern.test(raw)) return undefined
|
|
169
|
+
|
|
170
|
+
const parsed = Number(raw)
|
|
171
|
+
|
|
172
|
+
return Number.isSafeInteger(parsed) ? parsed : undefined
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// A count flag's value — zero or more — or `undefined` when it is absent or not a count.
|
|
176
|
+
function to_count(raw: string | undefined): number | undefined {
|
|
177
|
+
return to_integer(raw, COUNT_PATTERN)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// A value that must be one or more, or `undefined` when it is absent or not.
|
|
181
|
+
function to_positive(raw: string | undefined): number | undefined {
|
|
182
|
+
return to_integer(raw, POSITIVE_PATTERN)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// A positive-integer setting read from the environment or an argument. Blank is unset, not invalid — an
|
|
186
|
+
// `.env` line left as `KEY=` is a setting nobody configured — and answers `fallback`. Anything else that
|
|
187
|
+
// is not a positive integer is a problem naming `name`, never a silent fall back to the default: a typo
|
|
188
|
+
// that quietly became the default is a number nobody chose.
|
|
189
|
+
function read_positive_setting(
|
|
190
|
+
raw: string | undefined,
|
|
191
|
+
name: string,
|
|
192
|
+
fallback: number,
|
|
193
|
+
): PositiveSetting {
|
|
194
|
+
const trimmed = raw?.trim() ?? ''
|
|
195
|
+
|
|
196
|
+
if (trimmed === '') return { kind: 'limit', limit: fallback }
|
|
197
|
+
|
|
198
|
+
const limit = to_positive(trimmed)
|
|
199
|
+
if (limit !== undefined) return { kind: 'limit', limit }
|
|
200
|
+
|
|
201
|
+
return { kind: 'problem', problem: `${name} must be a positive integer, not "${trimmed}"` }
|
|
202
|
+
}
|
|
203
|
+
|
|
155
204
|
const cli_flags = {
|
|
205
|
+
to_count,
|
|
206
|
+
to_positive,
|
|
207
|
+
read_positive_setting,
|
|
156
208
|
attach_values,
|
|
157
209
|
usage_line,
|
|
158
210
|
refuse_unknown_flags,
|
|
@@ -167,3 +219,4 @@ const cli_flags = {
|
|
|
167
219
|
}
|
|
168
220
|
|
|
169
221
|
export { cli_flags }
|
|
222
|
+
export type { PositiveSetting }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
|
|
2
|
+
|
|
3
|
+
// The figures the reports print — a dollar amount, a token count, a percentage share, a duration in
|
|
4
|
+
// minutes and a local wall clock — and the precision each uses. The cost reports, `josh time`'s
|
|
5
|
+
// reports, `run:board` and the run event pane all render these, so each is written once here.
|
|
6
|
+
|
|
7
|
+
const USD_DECIMALS = 4
|
|
8
|
+
const PERCENT_SCALE = 100
|
|
9
|
+
const PERCENT_DECIMALS = 1
|
|
10
|
+
const MINUTE_DECIMALS = 1
|
|
11
|
+
const CLOCK_WIDTH = 2
|
|
12
|
+
const CLOCK_PAD = '0'
|
|
13
|
+
|
|
14
|
+
// The caller names the decimals where its figure rounds to another place — a run total to the cent.
|
|
15
|
+
function format_usd(usd: number, decimals: number = USD_DECIMALS): string {
|
|
16
|
+
return `$${usd.toFixed(decimals)}`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function format_tokens(count: number): string {
|
|
20
|
+
return count.toLocaleString('en-US')
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function format_share(part: number, whole: number): string {
|
|
24
|
+
if (whole === 0) return 'n/a'
|
|
25
|
+
|
|
26
|
+
return `${((part / whole) * PERCENT_SCALE).toFixed(PERCENT_DECIMALS)}%`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function format_minutes(duration_ms: number): string {
|
|
30
|
+
return `${(duration_ms / MS_PER_MINUTE).toFixed(MINUTE_DECIMALS)} min`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function two_digits(value: number): string {
|
|
34
|
+
return String(value).padStart(CLOCK_WIDTH, CLOCK_PAD)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// The local wall-clock `HH:MM:SS` of a moment.
|
|
38
|
+
function clock_of(ms: number): string {
|
|
39
|
+
const date = new Date(ms)
|
|
40
|
+
|
|
41
|
+
return [date.getHours(), date.getMinutes(), date.getSeconds()]
|
|
42
|
+
.map((value) => two_digits(value))
|
|
43
|
+
.join(':')
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// The local wall-clock `HH:MM` of a moment, for one a person reads to the minute.
|
|
47
|
+
function minute_of(ms: number): string {
|
|
48
|
+
const date = new Date(ms)
|
|
49
|
+
|
|
50
|
+
return [date.getHours(), date.getMinutes()].map((value) => two_digits(value)).join(':')
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const figure_format = {
|
|
54
|
+
format_usd,
|
|
55
|
+
format_tokens,
|
|
56
|
+
format_share,
|
|
57
|
+
format_minutes,
|
|
58
|
+
two_digits,
|
|
59
|
+
clock_of,
|
|
60
|
+
minute_of,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { figure_format }
|
|
@@ -28,12 +28,20 @@ function parse_with<T>(text: string, schema: z.ZodType<T>): T | undefined {
|
|
|
28
28
|
return parsed.success ? parsed.data : undefined
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// The read a listing wants: text that is not JSON and JSON that is not an array both answer
|
|
32
|
+
// `undefined`, so a caller can keep "unreadable" apart from an empty listing.
|
|
33
|
+
function parse_array(text: string): Array<unknown> | undefined {
|
|
34
|
+
const value = parse_or_undefined(text)
|
|
35
|
+
|
|
36
|
+
return Array.isArray(value) ? value : undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
// A plain object, as opposed to an array or a primitive. `typeof null` is `'object'`, and an array
|
|
32
40
|
// answers `'object'` too, so both have to be excluded by hand before a key lookup means anything.
|
|
33
41
|
function is_record(value: unknown): value is Record<string, unknown> {
|
|
34
42
|
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
35
43
|
}
|
|
36
44
|
|
|
37
|
-
const json_value = { parse_or_undefined, parse_with, is_record }
|
|
45
|
+
const json_value = { parse_or_undefined, parse_with, parse_array, is_record }
|
|
38
46
|
|
|
39
47
|
export { json_value }
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import type { z } from 'zod'
|
|
4
|
+
import { json_value } from './json-value'
|
|
5
|
+
import { file_reader } from './read-file'
|
|
6
|
+
|
|
7
|
+
// The one place a `package.json` is named and read. Readers across `scripts/` had each spelled the
|
|
8
|
+
// file name and written their own read-then-parse; they now ask here, and choose only how a manifest
|
|
9
|
+
// that cannot be read answers.
|
|
10
|
+
const PACKAGE_JSON = 'package.json'
|
|
11
|
+
|
|
12
|
+
function manifest_path(directory: string): string {
|
|
13
|
+
return path.join(directory, PACKAGE_JSON)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// For a manifest that must exist: a missing file, text that is not JSON and a shape the schema
|
|
17
|
+
// rejects all throw, so the defect surfaces where it was met.
|
|
18
|
+
function read_manifest<T>(directory: string, schema: z.ZodType<T>): T {
|
|
19
|
+
const text = readFileSync(manifest_path(directory), 'utf8')
|
|
20
|
+
|
|
21
|
+
return schema.parse(JSON.parse(text))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// For a manifest that may be absent or broken without that being this reader's failure: every one of
|
|
25
|
+
// those answers `undefined`.
|
|
26
|
+
function read_manifest_if_valid<T>(directory: string, schema: z.ZodType<T>): T | undefined {
|
|
27
|
+
const text = file_reader.read_if_readable(manifest_path(directory))
|
|
28
|
+
if (text === undefined) return undefined
|
|
29
|
+
|
|
30
|
+
return json_value.parse_with(text, schema)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const package_manifest = { manifest_path, read_manifest, read_manifest_if_valid }
|
|
34
|
+
|
|
35
|
+
export { PACKAGE_JSON, package_manifest }
|
package/scripts/lib/read-file.ts
CHANGED
|
@@ -2,6 +2,8 @@ import { readFileSync } from 'node:fs'
|
|
|
2
2
|
|
|
3
3
|
const ABSENT_CODE = 'ENOENT'
|
|
4
4
|
|
|
5
|
+
// Whether a filesystem error says "there is nothing here" — ENOENT and nothing else. A permission
|
|
6
|
+
// error or ENOTDIR says something is there, so neither reads as absent.
|
|
5
7
|
function is_absent(error: unknown): boolean {
|
|
6
8
|
return error instanceof Error && 'code' in error && error.code === ABSENT_CODE
|
|
7
9
|
}
|
|
@@ -35,6 +37,6 @@ function read_if_readable(path: string): string | undefined {
|
|
|
35
37
|
}
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
const file_reader = { read_optional, read_file_or_empty, read_if_readable }
|
|
40
|
+
const file_reader = { is_absent, read_optional, read_file_or_empty, read_if_readable }
|
|
39
41
|
|
|
40
42
|
export { file_reader }
|