@joshuafolkken/kit 1.1240.0 → 1.1370.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 -0
- package/.claude/settings.json +4 -0
- package/.claude/skills/dependency-update/SKILL.md +5 -3
- package/.claude/skills/epic-commands/SKILL.md +82 -113
- package/.claude/skills/epic-commands/epic-bundle.md +38 -63
- package/.claude/skills/epic-commands/execution-waves.md +30 -51
- package/.claude/skills/verify-ui/SKILL.md +13 -20
- package/.claude/skills/workflow-commands/SKILL.md +10 -10
- package/.claude/skills/workflow-commands/background-commands.md +4 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
- package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
- package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
- package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
- package/.claude/skills/workflow-commands/backlogrun.md +50 -61
- package/.claude/skills/workflow-commands/chain-rule.md +36 -40
- package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
- package/.claude/skills/workflow-commands/followup.md +19 -20
- package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
- package/.claude/skills/workflow-commands/fullrun.md +10 -10
- package/.claude/skills/workflow-commands/halfrun.md +9 -8
- package/.claude/skills/workflow-commands/into-target.md +12 -18
- package/.claude/skills/workflow-commands/issue-comments.md +11 -26
- package/.claude/skills/workflow-commands/kickoff.md +26 -16
- package/.claude/skills/workflow-commands/latest-gate.md +17 -28
- package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
- package/.claude/skills/workflow-commands/observation-filing.md +37 -28
- package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
- package/.claude/skills/workflow-commands/prerequisite.md +23 -15
- package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
- package/.claude/skills/workflow-commands/prrun.md +3 -3
- package/.claude/skills/workflow-commands/retrospective.md +13 -18
- package/.claude/skills/workflow-commands/split-assessment.md +6 -4
- package/.claude/skills/workflow-commands/target-repository.md +25 -28
- package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
- package/.gitattributes +2 -1
- package/.github/workflows/ci.yml +14 -0
- package/.vscode/tasks.json +14 -0
- package/CLAUDE.md +10 -61
- package/README.md +29 -47
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +10 -61
- package/dist/commands/document-section-cli.js +42 -10
- package/dist/config-merge/index.js +11 -2
- package/dist/hooks/audit-provision.js +2 -2
- package/dist/hooks/batch-guard.js +7 -7
- package/dist/hooks/{chunk-KHGB5S3Y.js → chunk-43G45XJF.js} +18 -20
- package/dist/hooks/{chunk-4TZVB44A.js → chunk-4TW4MQUL.js} +284 -362
- package/dist/hooks/{chunk-XZYKEM6J.js → chunk-76RK6E3H.js} +13 -11
- package/dist/hooks/{chunk-F3ELQ2AF.js → chunk-DZWZ3DKY.js} +4 -4
- package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
- package/dist/hooks/{chunk-GPTFMK5E.js → chunk-GG72ANKI.js} +1 -1
- package/dist/hooks/{chunk-ZQGD4GBY.js → chunk-KPM4YIIX.js} +8 -44
- package/dist/hooks/chunk-MXVQMLDP.js +3705 -0
- package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
- package/dist/hooks/{chunk-QVSWU24O.js → chunk-NZBHG6FW.js} +7 -5
- package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
- package/dist/hooks/{chunk-KRBERBBI.js → chunk-R6CRQEAL.js} +4 -4
- package/dist/hooks/chunk-SYSRHRWU.js +1589 -0
- package/dist/hooks/{chunk-WK2XSHSI.js → chunk-TLJYAGZK.js} +549 -874
- package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
- package/dist/hooks/codex-hook-adapter.js +26 -21
- package/dist/hooks/duplicate-read-guard.js +8 -8
- package/dist/hooks/format-edited.js +4 -4
- package/dist/hooks/inputs.json +216 -202
- package/dist/hooks/investigation-guard.js +8 -8
- package/dist/hooks/pretool-guard.js +15 -15
- package/dist/hooks/session-lang.js +406 -8
- package/dist/hooks/stop-guard.js +122 -187
- package/dist/josh.js +281 -94
- package/dist/version/index.js +15 -13
- package/eslint/base.js +43 -5
- package/eslint/rules/english-only-prose.js +3 -3
- package/eslint/rules/import.js +12 -0
- package/eslint/rules/namespace-object-export.js +2 -2
- package/package.json +16 -10
- package/pnpm-workspace.yaml +2 -4
- package/prompts/coding-standards.md +14 -48
- package/prompts/collaboration-workflow/file-edits.md +1 -1
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +3 -10
- package/prompts/collaboration-workflow/operating-rules.md +7 -8
- package/prompts/collaboration-workflow/output-bounds.md +1 -1
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/plan-comment.md +2 -1
- package/prompts/collaboration-workflow/principles.md +21 -3
- package/prompts/collaboration-workflow/report-format.md +16 -29
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +7 -95
- package/prompts/collaboration-workflow/shell-body.md +3 -23
- package/prompts/collaboration-workflow/turn-batching.md +4 -13
- package/prompts/collaboration-workflow/wip-cap.md +5 -11
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +3 -22
- package/prompts/review.md +15 -38
- package/prompts/testing-guide.md +2 -4
- package/scripts/adopt/adopt-logic.ts +5 -5
- package/scripts/adopt/adopt-toolkits.ts +4 -5
- package/scripts/adopt/adopt.ts +2 -3
- package/scripts/agent/agent-argv.ts +7 -7
- package/scripts/agent/agent-diagnostics.ts +2 -2
- package/scripts/agent/agent-exit-record.ts +1 -1
- package/scripts/agent/agent-headless.ts +1 -1
- package/scripts/agent/agent-launch-environment.ts +6 -1
- package/scripts/agent/agent-role-profile.ts +49 -22
- package/scripts/agent/agent-session-role.ts +32 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/agent/claude-agent-argv.ts +4 -4
- package/scripts/agent/claude-result-event.ts +4 -4
- package/scripts/agent/codex-hooks.ts +2 -2
- package/scripts/agent/interactive-ask.ts +3 -6
- package/scripts/auto-ok/auto-ok-cli.ts +46 -60
- package/scripts/backlog/backlog-arrival-added.ts +34 -0
- package/scripts/backlog/backlog-arrival.ts +54 -17
- package/scripts/backlog/backlog-budget-cli.ts +34 -6
- package/scripts/backlog/backlog-budget.ts +17 -24
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +5 -4
- package/scripts/backlog/backlog-drive-cli.ts +14 -10
- package/scripts/backlog/backlog-drive-epic.ts +85 -0
- package/scripts/backlog/backlog-drive-launch.ts +1 -1
- package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
- package/scripts/backlog/backlog-drive-named.ts +39 -9
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
- package/scripts/backlog/backlog-drive.ts +43 -28
- package/scripts/backlog/backlog-idle.ts +88 -0
- package/scripts/backlog/backlog-named.ts +11 -15
- package/scripts/backlog/backlog-next.ts +26 -30
- package/scripts/backlog/backlog-offer-cli.ts +28 -23
- package/scripts/backlog/backlog-offer.ts +7 -7
- package/scripts/backlog/backlog-overlap.ts +178 -0
- package/scripts/backlog/backlog-plan-cli.ts +14 -90
- package/scripts/backlog/backlog-plan-read.ts +111 -0
- package/scripts/backlog/backlog-plan.ts +11 -10
- package/scripts/backlog/backlog-pool.ts +13 -14
- package/scripts/backlog/backlog-rank.ts +11 -11
- package/scripts/backlog/backlog-ready.ts +15 -10
- package/scripts/backlog/backlog-scope.ts +14 -15
- package/scripts/backlog/backlog-stalled-cli.ts +2 -2
- package/scripts/backlog/backlog-stalled-detect.ts +4 -4
- package/scripts/backlog/backlog-stalled.ts +5 -6
- package/scripts/backlog/backlog-waves.ts +4 -4
- package/scripts/backlog/backlogrun-args.ts +74 -0
- package/scripts/backlog/backlogrun-cli.ts +113 -0
- package/scripts/backlog/backlogrun-launch.ts +178 -0
- package/scripts/behavior/behavior-assertion.ts +6 -8
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/behavior/behavior-rules.ts +3 -3
- package/scripts/build/build-claude-md.ts +4 -4
- package/scripts/build/build-codex-hooks.ts +2 -2
- package/scripts/build/build-commands.ts +1 -1
- package/scripts/build/build-hooks.ts +5 -5
- package/scripts/build/build.ts +1 -1
- package/scripts/build/hook-bundle-stamp.ts +109 -7
- package/scripts/build/local-bin.ts +2 -2
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +2 -2
- package/scripts/ci/composite-actions.ts +1 -2
- package/scripts/ci/pr-classification.ts +2 -2
- package/scripts/claude/workflow-destination.ts +1 -1
- package/scripts/clone/clone-aggregate.ts +1 -1
- package/scripts/clone/clone-fingerprint.ts +1 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/index.ts +1 -1
- package/scripts/config-merge/json-format.ts +1 -3
- package/scripts/config-merge/patch-json-array.ts +90 -0
- package/scripts/config-merge/patch-json-key.ts +6 -3
- package/scripts/config-merge/patch-json-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +1 -1
- package/scripts/cost-runtime/context-cut-payback.ts +4 -5
- package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
- package/scripts/cost-runtime/cost-attribute.ts +3 -3
- package/scripts/cost-runtime/cost-blocks.ts +3 -4
- package/scripts/cost-runtime/cost-cli.ts +14 -11
- package/scripts/cost-runtime/cost-corpus.ts +11 -11
- package/scripts/cost-runtime/cost-pricing.ts +4 -4
- package/scripts/cost-runtime/cost-tokens.ts +1 -2
- package/scripts/cost-runtime/cost-transcript.ts +29 -29
- package/scripts/cost-runtime/cost-usage.ts +6 -7
- package/scripts/cost-runtime/cost-verdict.ts +10 -11
- package/scripts/cost-runtime/own-session.ts +1 -1
- package/scripts/cost-runtime/transcript-cwd.ts +2 -2
- package/scripts/delegation/delegation-cli.ts +4 -4
- package/scripts/delegation/delegation-policy.ts +13 -15
- package/scripts/delegation/duplicate-read-guard.ts +9 -10
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +1 -1
- package/scripts/delegation/investigation-guard.ts +18 -22
- package/scripts/delegation/investigation-reads.ts +48 -238
- package/scripts/discovery/repo-discovery.ts +1 -1
- package/scripts/discovery/repo-map-logic.ts +1 -2
- package/scripts/discovery/repo-origin.ts +3 -3
- package/scripts/discovery/repo-party-cli.ts +2 -2
- package/scripts/discovery/repo-party.ts +2 -2
- package/scripts/doctor/doctor-consumer.ts +1 -1
- package/scripts/doctor/doctor-io.ts +6 -7
- package/scripts/doctor/doctor-logic.ts +1 -1
- package/scripts/doctor/doctor-ports.ts +1 -1
- package/scripts/doctor/doctor.ts +8 -9
- package/scripts/document/backlogrun-parent-read-set.ts +5 -6
- package/scripts/document/bash-output-cap.ts +5 -7
- package/scripts/document/capped-print-part.ts +1 -1
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/document-byte-budget.ts +33 -64
- package/scripts/document/document-byte-check.ts +4 -4
- package/scripts/document/document-reachability.ts +7 -8
- package/scripts/document/document-read-cli.ts +2 -2
- package/scripts/document/document-scan.ts +26 -2
- package/scripts/document/document-section-cli.ts +6 -8
- package/scripts/document/document-section.ts +8 -12
- package/scripts/document/edit-files-cli.ts +3 -4
- package/scripts/document/entry-read-budget.ts +8 -70
- package/scripts/document/entry-read-set.ts +51 -34
- package/scripts/document/lane-child-read-set.ts +9 -9
- package/scripts/document/read-files-cli.ts +1 -2
- package/scripts/document/read-set-cli.ts +16 -19
- package/scripts/document/read-set-cost.ts +4 -4
- package/scripts/document/read-set-point-of-use.ts +28 -38
- package/scripts/document/read-set-pricing.ts +1 -1
- package/scripts/document/read-set-trim.ts +3 -3
- package/scripts/document/resident-budget.ts +8 -10
- package/scripts/epic/epic-add-body.ts +15 -18
- package/scripts/epic/epic-add-plan.ts +26 -28
- package/scripts/epic/epic-add.ts +32 -25
- package/scripts/epic/epic-audit-checks.ts +27 -37
- package/scripts/epic/epic-audit-cli.ts +21 -22
- package/scripts/epic/epic-audit-orphans.ts +16 -17
- package/scripts/epic/epic-audit-rationale.ts +10 -15
- package/scripts/epic/epic-audit-report.ts +2 -5
- package/scripts/epic/epic-audit.ts +18 -14
- package/scripts/epic/epic-body.ts +10 -10
- package/scripts/epic/epic-bundle-cli.ts +36 -34
- package/scripts/epic/epic-bundle-evidence.ts +5 -5
- package/scripts/epic/epic-bundle-gaps.ts +6 -9
- package/scripts/epic/epic-bundle-poll.ts +1 -1
- package/scripts/epic/epic-bundle-referenced.ts +11 -14
- package/scripts/epic/epic-bundle.ts +19 -20
- package/scripts/epic/epic-busy.ts +44 -21
- package/scripts/epic/epic-candidate-confirm.ts +15 -18
- package/scripts/epic/epic-chains.ts +18 -23
- package/scripts/epic/epic-classify.ts +11 -12
- package/scripts/epic/epic-cli-argv.ts +5 -6
- package/scripts/epic/epic-cli-remove.ts +9 -4
- package/scripts/epic/epic-cli.ts +38 -26
- package/scripts/epic/epic-close-comment.ts +14 -15
- package/scripts/epic/epic-close.ts +25 -29
- package/scripts/epic/epic-cross-repo.ts +18 -21
- package/scripts/epic/epic-decision.ts +14 -18
- package/scripts/epic/epic-fetch.ts +25 -31
- package/scripts/epic/epic-graph.ts +15 -17
- package/scripts/epic/epic-index.ts +14 -16
- package/scripts/epic/epic-issue.ts +9 -11
- package/scripts/epic/epic-label-age.ts +74 -0
- package/scripts/epic/epic-lane-offer.ts +35 -24
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +8 -8
- package/scripts/epic/epic-next-views.ts +12 -12
- package/scripts/epic/epic-next.ts +29 -33
- package/scripts/epic/epic-outside-blocker.ts +11 -10
- package/scripts/epic/epic-parse.ts +22 -24
- package/scripts/epic/epic-promote.ts +3 -2
- package/scripts/epic/epic-rank.ts +1 -1
- package/scripts/epic/epic-read.ts +10 -8
- package/scripts/epic/epic-reconcile.ts +8 -6
- package/scripts/epic/epic-reference.ts +5 -4
- package/scripts/epic/epic-relation-recheck.ts +10 -11
- package/scripts/epic/epic-relations.ts +9 -8
- package/scripts/epic/epic-remove-plan.ts +4 -5
- package/scripts/epic/epic-remove.ts +7 -5
- package/scripts/epic/epic-report.ts +18 -20
- package/scripts/epic/epic-run.ts +6 -5
- package/scripts/epic/epic-sections.ts +2 -2
- package/scripts/epic/epic-shape.ts +3 -3
- package/scripts/epic/epic-solo-stale.ts +3 -2
- package/scripts/epic/epic-solo.ts +8 -8
- package/scripts/epic/epic-triage.ts +5 -4
- package/scripts/epic/epic-validate.ts +8 -7
- package/scripts/epic/epic.ts +5 -5
- package/scripts/exports/unused-members-cli.ts +1 -1
- package/scripts/followup/followup-issue-number.ts +1 -2
- package/scripts/followup/git-followup-cleanup.ts +6 -7
- package/scripts/followup/git-followup-finish.ts +11 -13
- package/scripts/followup/git-followup-flush.ts +11 -7
- package/scripts/followup/git-followup-issue-close.ts +16 -13
- package/scripts/followup/git-followup-label.ts +9 -6
- package/scripts/followup/git-followup-merged.ts +1 -1
- package/scripts/followup/git-followup-pending.ts +7 -9
- package/scripts/followup/git-followup-stages.ts +28 -17
- package/scripts/followup/git-followup-workflow.ts +19 -21
- package/scripts/followup/git-pr-followup-checks.ts +13 -20
- package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
- package/scripts/followup/git-pr-followup.ts +18 -17
- package/scripts/gate/core-admission.ts +2 -2
- package/scripts/gate/core-budget.ts +15 -26
- package/scripts/gate/gate-ledger.ts +114 -0
- package/scripts/gate/gate-log.ts +7 -9
- package/scripts/gate/gate-plan.ts +70 -35
- package/scripts/gate/gate-report.ts +14 -15
- package/scripts/gate/gate-skip.ts +11 -13
- package/scripts/gate/gate-steps.ts +5 -1
- package/scripts/gate/gate-tree.ts +3 -4
- package/scripts/gate/hook-gate-reuse.ts +9 -9
- package/scripts/gate/machine-capacity.ts +168 -30
- package/scripts/gate/pre-commit-type-check.ts +4 -4
- package/scripts/gate/project-checks.ts +12 -4
- package/scripts/gate/scoped-green.ts +11 -18
- package/scripts/gate/type-check-command.ts +2 -2
- package/scripts/gate/type-check-step.ts +4 -4
- package/scripts/gate/verification-gate.ts +53 -51
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/gh/git-ai-review-scan.ts +3 -2
- package/scripts/gh/git-gh-api-path.ts +10 -11
- package/scripts/gh/git-gh-exec.ts +43 -48
- package/scripts/gh/git-gh-failure.ts +6 -9
- package/scripts/gh/git-gh-helpers.ts +1 -1
- package/scripts/gh/git-gh-issue-list.ts +15 -19
- package/scripts/gh/git-gh-issue-read.ts +43 -60
- package/scripts/gh/git-gh-issue-rest.ts +14 -15
- package/scripts/gh/git-gh-issue-write.ts +52 -40
- package/scripts/gh/git-gh-issue.ts +23 -24
- package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
- package/scripts/gh/git-gh-pr-read.ts +46 -50
- package/scripts/gh/git-gh-pr-rest.ts +23 -26
- package/scripts/gh/git-gh-pr-review.ts +2 -2
- package/scripts/gh/git-gh-pr-rollup.ts +4 -4
- package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
- package/scripts/gh/git-gh-pr.ts +16 -16
- package/scripts/gh/git-gh-reachability.ts +11 -12
- package/scripts/gh/git-gh-repo.ts +2 -3
- package/scripts/gh/git-gh-rest-state.ts +1 -1
- package/scripts/gh/git-pr-ai-review.ts +6 -5
- package/scripts/gh/git-pr-checks-eval.ts +28 -30
- package/scripts/gh/git-pr-checks-parse.ts +14 -16
- package/scripts/gh/git-pr-checks-watch.ts +17 -17
- package/scripts/gh/git-pr-checks.ts +20 -23
- package/scripts/gh/git-pr-coderabbit.ts +8 -6
- package/scripts/gh/git-pr-confirmation.ts +5 -5
- package/scripts/gh/git-pr-managed-config.ts +7 -9
- package/scripts/gh/git-pr-messages.ts +1 -1
- package/scripts/gh/git-pr.ts +15 -16
- package/scripts/gh/github-issue-url.ts +8 -9
- package/scripts/git/base-tree.ts +66 -0
- package/scripts/git/change-base.ts +42 -2
- package/scripts/git/changed-file-scope.ts +5 -5
- package/scripts/git/changed-paths.ts +1 -2
- package/scripts/git/constants.ts +2 -2
- package/scripts/git/git-branch.ts +1 -1
- package/scripts/git/git-closes-keyword.ts +3 -3
- package/scripts/git/git-command.ts +53 -41
- package/scripts/git/git-common-directory.ts +3 -3
- package/scripts/git/git-diff-reads.ts +14 -15
- package/scripts/git/git-error.ts +1 -1
- package/scripts/git/git-execa-error.ts +1 -2
- package/scripts/git/git-issue.ts +10 -8
- package/scripts/git/git-location-environment.ts +3 -4
- package/scripts/git/git-ls-remote.ts +6 -8
- package/scripts/git/git-pre-push-hook.ts +11 -10
- package/scripts/git/git-preflight.ts +5 -5
- package/scripts/git/git-push-transport.ts +2 -2
- package/scripts/git/git-remote-branch.ts +1 -2
- package/scripts/git/git-schemas.ts +16 -23
- package/scripts/git/git-spawn-sync.ts +1 -1
- package/scripts/git/git-spawn.ts +37 -14
- package/scripts/git/git-ssh-keepalive.ts +12 -5
- package/scripts/git/git-staging.ts +7 -8
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/git-worktree.ts +35 -27
- package/scripts/git/gone-branch.ts +2 -2
- package/scripts/git/listing-cutoff.ts +1 -2
- package/scripts/git/lockfile-sync.ts +65 -0
- package/scripts/git/main-merge-guard.ts +1 -2
- package/scripts/git/main-merge.ts +7 -7
- package/scripts/git/main-sync.ts +23 -8
- package/scripts/git/parse-json-array.ts +18 -23
- package/scripts/git/repository-lock.ts +34 -2
- package/scripts/git/stash/git-stash.ts +4 -5
- package/scripts/git/stash/stash-orphans.ts +5 -3
- package/scripts/git/stash/stash-pop-args.ts +1 -1
- package/scripts/git/stash/stash-pop-cli.ts +3 -3
- package/scripts/git/stash/stash-sweep-lock.ts +2 -2
- package/scripts/hooks/batch-guard.ts +11 -13
- package/scripts/hooks/check-commit-message.ts +12 -9
- package/scripts/hooks/codex-hook-adapter.ts +16 -10
- package/scripts/hooks/edited-cspell.ts +3 -4
- package/scripts/hooks/format-edited-cli.ts +1 -1
- package/scripts/hooks/format-edited-file.ts +11 -17
- package/scripts/hooks/format-rewrite-notice.ts +19 -17
- package/scripts/hooks/pre-push-unit.ts +10 -14
- package/scripts/hooks/pretool-guard-cli.ts +4 -4
- package/scripts/hooks/pretool-guard.ts +93 -18
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/step-zero-notice.ts +1 -1
- package/scripts/hooks/stop-guard.ts +21 -10
- package/scripts/init/basic-path-migration.ts +2 -2
- package/scripts/init/claude-kit-only-settings.ts +2 -2
- package/scripts/init/claude-plugin-config.ts +2 -2
- package/scripts/init/distributed-paths.ts +4 -4
- package/scripts/init/hook-command-rewrite.ts +3 -3
- package/scripts/init/hook-launch.ts +5 -5
- package/scripts/init/init-actions.ts +13 -0
- package/scripts/init/init-ai-copy.ts +11 -11
- package/scripts/init/init-bootstrap.ts +3 -3
- package/scripts/init/init-copy-content.ts +4 -4
- package/scripts/init/init-logic-json-merge.ts +7 -9
- package/scripts/init/init-logic-migrate.ts +1 -1
- package/scripts/init/init-logic-templates.ts +1 -1
- package/scripts/init/init-logic-workspace.ts +4 -4
- package/scripts/init/init-logic-yaml-merge.ts +2 -2
- package/scripts/init/init-logic.ts +19 -22
- package/scripts/init/init.ts +7 -7
- package/scripts/init/kit-base-preset.ts +1 -1
- package/scripts/init/kit-setup-state.ts +1 -1
- package/scripts/init/kit-written-paths.ts +1 -2
- package/scripts/init/package-manager-pin.ts +1 -1
- package/scripts/init/project-profile-cli.ts +1 -1
- package/scripts/init/project-profile.ts +3 -3
- package/scripts/init/session-language-environment.ts +1 -1
- package/scripts/init/start-exec.ts +3 -4
- package/scripts/init/start-plan.ts +2 -2
- package/scripts/init/start-setup-pr.ts +3 -2
- package/scripts/init/start-steps.ts +2 -2
- package/scripts/init/tsconfig-preset-migration.ts +1 -1
- package/scripts/init/vscode-tasks.ts +62 -0
- package/scripts/issue/baseline-measure.ts +2 -2
- package/scripts/issue/behavior-change-lint.ts +2 -2
- package/scripts/issue/defect-rate-cli.ts +6 -7
- package/scripts/issue/defect-rate.ts +37 -27
- package/scripts/issue/git-next-issues.ts +9 -8
- package/scripts/issue/issue-auto-ok.ts +24 -11
- package/scripts/issue/issue-backlinks-cli.ts +5 -5
- package/scripts/issue/issue-backlinks.ts +6 -6
- package/scripts/issue/issue-cite-cli.ts +20 -18
- package/scripts/issue/issue-cite.ts +18 -8
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +6 -4
- package/scripts/issue/issue-file-cli.ts +52 -15
- package/scripts/issue/issue-file-fold.ts +155 -0
- package/scripts/issue/issue-file.ts +9 -6
- package/scripts/issue/issue-fold-cli.ts +14 -9
- package/scripts/issue/issue-fold.ts +23 -8
- package/scripts/issue/issue-labels.ts +34 -38
- package/scripts/issue/issue-lint-cli.ts +2 -2
- package/scripts/issue/issue-lint.ts +1 -1
- package/scripts/issue/issue-merged.ts +10 -4
- package/scripts/issue/issue-number-shape.ts +27 -0
- package/scripts/issue/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +4 -5
- package/scripts/issue/issue-read.ts +4 -5
- package/scripts/issue/issue-reference.ts +5 -5
- package/scripts/issue/issue-release-cli.ts +17 -7
- package/scripts/issue/issue-release.ts +3 -3
- package/scripts/issue/issue-report-failures.ts +7 -4
- package/scripts/issue/issue-scout-cli.ts +11 -11
- package/scripts/issue/issue-scout-closed.ts +4 -4
- package/scripts/issue/issue-scout.ts +4 -5
- package/scripts/issue/issue-state-cli.ts +17 -10
- package/scripts/issue/issue-state.ts +12 -13
- package/scripts/issue/issue-wip.ts +7 -7
- package/scripts/issue/markdown-section.ts +3 -3
- package/scripts/issue/measure-rerun-cli.ts +10 -9
- package/scripts/issue/reproduction-measure.ts +3 -3
- package/scripts/issue/session-cite.ts +56 -0
- package/scripts/josh/agent-session-environment.ts +10 -8
- package/scripts/josh/cli-body.ts +2 -2
- package/scripts/josh/command-suggest.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +20 -23
- package/scripts/josh/hook-decision.ts +24 -28
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +30 -35
- package/scripts/josh/josh-commands-ai.ts +6 -6
- package/scripts/josh/josh-commands-backlog.ts +15 -3
- package/scripts/josh/josh-commands-clone.ts +1 -1
- package/scripts/josh/josh-commands-development.ts +25 -4
- package/scripts/josh/josh-commands-document.ts +3 -3
- package/scripts/josh/josh-commands-guard.ts +3 -3
- package/scripts/josh/josh-commands-issue.ts +4 -5
- package/scripts/josh/josh-commands-lane.ts +14 -4
- package/scripts/josh/josh-commands-lint.ts +1 -1
- package/scripts/josh/josh-commands-run.ts +20 -6
- package/scripts/josh/josh-commands-split.ts +1 -2
- package/scripts/josh/josh-commands-versioning.ts +5 -5
- package/scripts/josh/josh-commands-workflow.ts +30 -22
- package/scripts/josh/josh-environment-file.ts +1 -1
- package/scripts/josh/josh-in-process.ts +3 -3
- package/scripts/josh/josh-logic.ts +6 -7
- package/scripts/josh/josh-run.ts +3 -3
- package/scripts/josh/josh-verdict.ts +9 -12
- package/scripts/josh/josh.ts +3 -3
- package/scripts/josh/kit-only.ts +2 -2
- package/scripts/josh/path-decision.ts +3 -3
- package/scripts/josh/platform-temporary.ts +7 -5
- package/scripts/josh/process-identity.ts +24 -6
- package/scripts/josh/process-owner.ts +4 -4
- package/scripts/josh/session-language-cli.ts +53 -11
- package/scripts/josh/session-language.ts +1 -1
- package/scripts/josh/stamp-file.ts +48 -29
- package/scripts/josh/stamp-record.ts +57 -0
- package/scripts/lane/lane-await.ts +35 -11
- package/scripts/lane/lane-cache.ts +6 -6
- package/scripts/lane/lane-capacity.ts +32 -17
- package/scripts/lane/lane-child-invocation.ts +17 -15
- package/scripts/lane/lane-child-marker.ts +12 -12
- package/scripts/lane/lane-cli.ts +12 -13
- package/scripts/lane/lane-close.ts +6 -6
- package/scripts/lane/lane-dispatch.ts +61 -72
- package/scripts/lane/lane-environment.ts +5 -5
- package/scripts/lane/lane-guard-policy.ts +7 -21
- package/scripts/lane/lane-handoff.ts +2 -2
- package/scripts/lane/lane-install.ts +9 -10
- package/scripts/lane/lane-launch-cli.ts +13 -8
- package/scripts/lane/lane-ledger.ts +73 -11
- package/scripts/lane/lane-leftover.ts +2 -2
- package/scripts/lane/lane-limit-cli.ts +160 -0
- package/scripts/lane/lane-limit-override.ts +74 -0
- package/scripts/lane/lane-load.ts +19 -68
- package/scripts/lane/lane-measure-cli.ts +15 -25
- package/scripts/lane/lane-occupancy.ts +6 -4
- package/scripts/lane/lane-open.ts +20 -19
- package/scripts/lane/lane-output.ts +4 -3
- package/scripts/lane/lane-paths.ts +12 -11
- package/scripts/lane/lane-phase.ts +33 -0
- package/scripts/lane/lane-reap.ts +2 -2
- package/scripts/lane/lane-registry.ts +16 -15
- package/scripts/lane/lane-relaunch.ts +9 -9
- package/scripts/lane/lane-report.ts +5 -4
- package/scripts/lane/lane-resume.ts +2 -2
- package/scripts/lane/lane-sampler.ts +55 -0
- package/scripts/lane/lane-seed.ts +7 -7
- package/scripts/lane/lane-stage-stats.ts +135 -0
- package/scripts/lane/lane-start-point.ts +8 -11
- package/scripts/lane/lane-stats.ts +60 -15
- package/scripts/lane/lane-stray.ts +1 -1
- package/scripts/lane/lane-vacant.ts +1 -1
- package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
- package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +1 -1
- package/scripts/lib/bounded-pool.ts +2 -2
- package/scripts/lib/buffered-process.ts +4 -6
- package/scripts/lib/caddy-logs.sh +0 -0
- package/scripts/lib/cli-flags.ts +39 -6
- package/scripts/lib/error-message.ts +1 -1
- package/scripts/lib/json-value.ts +17 -3
- package/scripts/lib/poll.ts +1 -1
- package/scripts/lib/status-icons.ts +3 -3
- package/scripts/lib/timed-fetch.ts +1 -1
- package/scripts/lib/timeouts.ts +1 -1
- package/scripts/lines/bytes-command.ts +3 -4
- package/scripts/lines/effective-limit.ts +25 -12
- package/scripts/lines/line-budget.ts +47 -55
- package/scripts/lines/line-targets.ts +6 -2
- package/scripts/lines/lines-command.ts +3 -3
- package/scripts/lint/cspell-cached.ts +1 -1
- package/scripts/lint/cycle-recheck.ts +122 -0
- package/scripts/lint/format.ts +1 -2
- package/scripts/lint/lint-parallel.ts +34 -19
- package/scripts/lint/lint-related-scope.ts +25 -15
- package/scripts/lint/lint-related.ts +6 -7
- package/scripts/managed-marker/index.ts +1 -1
- package/scripts/managed-marker/managed-marker-logic.ts +1 -2
- package/scripts/notify/git-notify.ts +9 -7
- package/scripts/notify/telegram-notify.ts +53 -37
- package/scripts/notify/telegram-test-logic.ts +3 -3
- package/scripts/notify/telegram-test.ts +45 -30
- package/scripts/observations/observation-ledger-home.ts +14 -8
- package/scripts/observations/observation-ledger-line.ts +3 -2
- package/scripts/observations/observation-ledger-migrate.ts +3 -4
- package/scripts/observations/observation-ledger-prepare.ts +4 -4
- package/scripts/observations/observation-ledger.ts +14 -15
- package/scripts/observations/observation-record-cli.ts +83 -0
- package/scripts/observations/observation-record.ts +91 -0
- package/scripts/observations/observations-flush-cli.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +7 -6
- package/scripts/observations/observations-flush.ts +26 -27
- package/scripts/overrides/overrides-check.ts +18 -8
- package/scripts/package/package-scout-cli.ts +1 -1
- package/scripts/package/package-scout-format.ts +2 -2
- package/scripts/package/package-scout.ts +1 -1
- package/scripts/propagate/propagate-git-failure.ts +1 -1
- package/scripts/propagate/propagate-git.ts +7 -7
- package/scripts/propagate/propagate-plan.ts +2 -2
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -7
- package/scripts/propagate/propagate-select.ts +1 -1
- package/scripts/propagate/propagate-steps.ts +19 -20
- package/scripts/propagate/propagate-targets.ts +6 -10
- package/scripts/propagate/propagate.ts +5 -5
- package/scripts/refactor/import-graph.ts +1 -1
- package/scripts/refactor/refactor-lint.ts +4 -10
- package/scripts/refactor/refactor-scan-cli.ts +1 -1
- package/scripts/refactor/refactor-scan.ts +2 -2
- package/scripts/refactor/refactor-targets.ts +1 -1
- package/scripts/release/github-release-cli.ts +25 -3
- package/scripts/release/github-release-runs.ts +1 -1
- package/scripts/release/release-cli.ts +21 -4
- package/scripts/release/release-history.ts +6 -10
- package/scripts/release/release-plan.ts +3 -3
- package/scripts/release/release-progress.ts +3 -4
- package/scripts/release/release-publish.ts +8 -9
- package/scripts/release/release-scope-cli.ts +8 -10
- package/scripts/release/release-tag.ts +6 -8
- package/scripts/release/release-worktree.ts +5 -5
- package/scripts/repo/auto-merge-setting-logic.ts +7 -9
- package/scripts/repo/auto-merge-setting.ts +1 -1
- package/scripts/repo/repo-setting.ts +4 -4
- package/scripts/repo/repository-labels.ts +1 -1
- package/scripts/repo/required-checks-logic.ts +3 -3
- package/scripts/repo/required-checks-report.ts +1 -1
- package/scripts/repo/ruleset-check-cli.ts +1 -1
- package/scripts/repo/ruleset-check.ts +1 -1
- package/scripts/report/report-format-reference.ts +26 -0
- package/scripts/report/report-lint-cli.ts +2 -2
- package/scripts/report/report-lint.ts +16 -2
- package/scripts/review/disposition-cli.ts +2 -2
- package/scripts/review/disposition-logic.ts +1 -1
- package/scripts/review/live-evidence.ts +9 -6
- package/scripts/review/review-attest-cli.ts +1 -2
- package/scripts/review/review-attest.ts +3 -3
- package/scripts/review/review-brief-cli.ts +19 -20
- package/scripts/review/review-brief.ts +29 -32
- package/scripts/review/review-checkout.ts +2 -2
- package/scripts/review/review-diff-parts.ts +3 -5
- package/scripts/review/review-diff-write.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +7 -4
- package/scripts/review/review-findings-cli.ts +2 -2
- package/scripts/review/review-level.ts +4 -7
- package/scripts/review/review-record-cli.ts +73 -16
- package/scripts/review/review-record.ts +5 -4
- package/scripts/review/review-round2-cli.ts +2 -3
- package/scripts/review/review-round2.ts +13 -21
- package/scripts/review/review-stamps.ts +9 -71
- package/scripts/review/review-tree.ts +4 -5
- package/scripts/rules/bash-triggers.ts +4 -4
- package/scripts/rules/decision-oracle-batch.ts +5 -6
- package/scripts/rules/decision-oracle-stage.ts +1 -1
- package/scripts/rules/decision-oracle-tokens.ts +1 -2
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +61 -406
- package/scripts/rules/destructive-command.ts +2 -2
- package/scripts/rules/direct-filing.ts +4 -4
- package/scripts/rules/direct-pr-create.ts +2 -2
- package/scripts/rules/early-heartbeat.ts +15 -19
- package/scripts/rules/file-body.ts +5 -6
- package/scripts/rules/filing-cap.ts +6 -7
- package/scripts/rules/filing-offer.ts +1 -1
- package/scripts/rules/firing-point.ts +6 -6
- package/scripts/rules/gh-api.ts +2 -2
- package/scripts/rules/git-argv.ts +3 -3
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/hook-context-line.ts +31 -0
- package/scripts/rules/implementation-cut-verdict.ts +5 -8
- package/scripts/rules/implementation-cut.ts +35 -32
- package/scripts/rules/index-guard.ts +2 -2
- package/scripts/rules/issue-citation.ts +7 -7
- package/scripts/rules/issue-comments.ts +21 -13
- package/scripts/rules/josh-git-bare.ts +2 -2
- package/scripts/rules/lane-background.ts +14 -16
- package/scripts/rules/lane-carry-conflict.ts +41 -5
- package/scripts/rules/lane-interactive-ask.ts +6 -9
- package/scripts/rules/lane-park.ts +12 -16
- package/scripts/rules/lane-split-park.ts +1 -2
- package/scripts/rules/lane-switch-main.ts +10 -13
- package/scripts/rules/last-prompt.ts +1 -1
- package/scripts/rules/oracle-consulted.ts +5 -5
- package/scripts/rules/oracle-firing.ts +6 -9
- package/scripts/rules/oracle-list-cli.ts +2 -2
- package/scripts/rules/permission-guards.ts +2 -2
- package/scripts/rules/piped-verification.ts +79 -9
- package/scripts/rules/poll-loop.ts +9 -11
- package/scripts/rules/pre-gate-cut.ts +33 -30
- package/scripts/rules/prior-comment-read.ts +3 -3
- package/scripts/rules/protected-files.ts +25 -13
- package/scripts/rules/raw-field-body.ts +3 -4
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +10 -12
- package/scripts/rules/rule-guard.ts +1 -1
- package/scripts/rules/rule-list.ts +51 -0
- package/scripts/rules/rule-registry-rows.ts +282 -0
- package/scripts/rules/rule-registry.ts +109 -0
- package/scripts/rules/rule-value-cache.ts +2 -2
- package/scripts/rules/rule-value-cli.ts +6 -4
- package/scripts/rules/rule-value.ts +61 -22
- package/scripts/rules/run-tail-rule.ts +11 -15
- package/scripts/rules/shell-body-trigger.ts +7 -7
- package/scripts/rules/shell-segments.ts +2 -4
- package/scripts/rules/stop-rules.ts +54 -41
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +2 -2
- package/scripts/rules/third-party-write.ts +3 -3
- package/scripts/rules/worktree-guard.ts +12 -5
- package/scripts/run/add/run-add-cli.ts +165 -0
- package/scripts/run/add/run-add.ts +124 -0
- package/scripts/run/board/run-board-cli.ts +207 -0
- package/scripts/run/board/run-board-closed.ts +95 -0
- package/scripts/run/board/run-board-every.ts +60 -0
- package/scripts/run/board/run-board-fetch.ts +38 -0
- package/scripts/run/board/run-board-fit.ts +219 -0
- package/scripts/run/board/run-board-github.ts +162 -0
- package/scripts/run/board/run-board-header.ts +275 -0
- package/scripts/run/board/run-board-kind.ts +35 -0
- package/scripts/run/board/run-board-labels.ts +299 -0
- package/scripts/run/board/run-board-layout.ts +222 -0
- package/scripts/run/board/run-board-link.ts +31 -0
- package/scripts/run/board/run-board-machine.ts +198 -0
- package/scripts/run/board/run-board-notes.ts +103 -0
- package/scripts/run/board/run-board-phase.ts +136 -0
- package/scripts/run/board/run-board-plan.ts +129 -0
- package/scripts/run/board/run-board-read.ts +62 -0
- package/scripts/run/board/run-board-render-legend.ts +82 -0
- package/scripts/run/board/run-board-render-notes.ts +77 -0
- package/scripts/run/board/run-board-render-slot.ts +50 -0
- package/scripts/run/board/run-board-render.ts +407 -0
- package/scripts/run/board/run-board-scope.ts +17 -0
- package/scripts/run/board/run-board-screen.ts +43 -0
- package/scripts/run/board/run-board-span.ts +66 -0
- package/scripts/run/board/run-board-spin.ts +115 -0
- package/scripts/run/board/run-board-state.ts +113 -0
- package/scripts/run/board/run-board-status.ts +279 -0
- package/scripts/run/board/run-board-tick.ts +210 -0
- package/scripts/run/board/run-board-track.ts +22 -0
- package/scripts/run/board/run-board-usage-read.ts +255 -0
- package/scripts/run/board/run-board-usage-rusage.ts +124 -0
- package/scripts/run/board/run-board-usage-text.ts +80 -0
- package/scripts/run/board/run-board-usage.ts +165 -0
- package/scripts/run/carry/run-carry-added.ts +62 -0
- package/scripts/run/carry/run-carry-args.ts +25 -22
- package/scripts/run/carry/run-carry-change.ts +1 -1
- package/scripts/run/carry/run-carry-cli.ts +71 -48
- package/scripts/run/carry/run-carry-conversation.ts +6 -7
- package/scripts/run/carry/run-carry-ended.ts +85 -0
- package/scripts/run/carry/run-carry-reclaim.ts +1 -1
- package/scripts/run/carry/run-carry-stash.ts +3 -2
- package/scripts/run/carry/run-carry-streak.ts +8 -10
- package/scripts/run/carry/run-carry.ts +85 -89
- package/scripts/run/cut/run-cut-args.ts +7 -7
- package/scripts/run/cut/run-cut-cli.ts +54 -36
- package/scripts/run/cut/run-cut-handoff.ts +15 -15
- package/scripts/run/cut/run-cut-report.ts +37 -16
- package/scripts/run/cut/run-cut.ts +63 -77
- package/scripts/run/detached-launch.ts +35 -50
- package/scripts/run/entry/run-entry-cli.ts +48 -27
- package/scripts/run/entry/run-entry-stop.ts +7 -9
- package/scripts/run/entry/run-entry.ts +5 -6
- package/scripts/run/event/run-event-cli.ts +5 -6
- package/scripts/run/event/run-event-filed.ts +69 -0
- package/scripts/run/event/run-event-follow.ts +3 -3
- package/scripts/run/event/run-event-plan.ts +38 -0
- package/scripts/run/event/run-event-render.ts +9 -4
- package/scripts/run/event/run-event-scope.ts +47 -18
- package/scripts/run/event/run-event-stream-emit.ts +64 -11
- package/scripts/run/event/run-event-stream.ts +171 -46
- package/scripts/run/event/run-event-watch.ts +4 -6
- package/scripts/run/hold/run-hold-cli.ts +65 -62
- package/scripts/run/hold/run-hold.ts +88 -46
- package/scripts/run/merge/run-merge-cli.ts +116 -77
- package/scripts/run/merge/run-merge-collect.ts +107 -0
- package/scripts/run/merge/run-merge-steps.ts +112 -65
- package/scripts/run/merge/run-merge-token.ts +30 -0
- package/scripts/run/merge/run-merge.ts +31 -22
- package/scripts/run/progress/run-progress-args.ts +4 -4
- package/scripts/run/progress/run-progress-cli.ts +39 -50
- package/scripts/run/progress/run-progress-clock.ts +25 -32
- package/scripts/run/progress/run-progress-config.ts +6 -9
- package/scripts/run/progress/run-progress-read.ts +9 -10
- package/scripts/run/progress/run-progress.ts +48 -53
- package/scripts/run/review/run-review-cli.ts +6 -6
- package/scripts/run/review/run-review-steps.ts +6 -6
- package/scripts/run/review/run-review.ts +9 -11
- package/scripts/run/run-cli-fault.ts +29 -0
- package/scripts/run/run-ending-cli.ts +3 -3
- package/scripts/run/run-ending.ts +10 -14
- package/scripts/run/run-halfrun-resume.ts +6 -8
- package/scripts/run/run-headless.ts +25 -12
- package/scripts/run/run-invocation.ts +17 -22
- package/scripts/run/run-label.ts +7 -5
- package/scripts/run/run-liveness-cli.ts +19 -6
- package/scripts/run/run-liveness.ts +27 -38
- package/scripts/run/run-next-cli.ts +5 -9
- package/scripts/run/run-next.ts +4 -5
- package/scripts/run/run-parent-cut-hook.ts +10 -12
- package/scripts/run/run-preflight.ts +25 -29
- package/scripts/run/run-prep-cli.ts +17 -13
- package/scripts/run/run-prep-locate.ts +4 -5
- package/scripts/run/run-prep.ts +7 -10
- package/scripts/run/run-prrun-resume.ts +2 -2
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +9 -14
- package/scripts/run/run-retrospective.ts +3 -3
- package/scripts/run/run-section.ts +42 -0
- package/scripts/run/run-stage-read.ts +2 -2
- package/scripts/run/run-stage.ts +6 -4
- package/scripts/run/run-status-cli.ts +7 -5
- package/scripts/run/run-status.ts +6 -7
- package/scripts/run/run-step-cli.ts +13 -15
- package/scripts/run/run-step.ts +58 -47
- package/scripts/run/run-stop-notify.ts +7 -8
- package/scripts/run/run-stranded-cli.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +11 -13
- package/scripts/run/run-tail-cli.ts +15 -16
- package/scripts/run/run-tail.ts +14 -33
- package/scripts/run/run-watcher-guard-cli.ts +3 -4
- package/scripts/run/run-watcher-guard.ts +11 -12
- package/scripts/run/run-watcher-hook.ts +6 -12
- package/scripts/run/ship/run-ship-cli.ts +67 -33
- package/scripts/run/ship/run-ship-detach.ts +15 -13
- package/scripts/run/ship/run-ship-lock.ts +1 -1
- package/scripts/run/ship/run-ship-next.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
- package/scripts/run/ship/run-ship-preflight.ts +10 -11
- package/scripts/run/ship/run-ship-probe.ts +4 -4
- package/scripts/run/ship/run-ship-return.ts +1 -1
- package/scripts/run/ship/run-ship-review-steps.ts +43 -24
- package/scripts/run/ship/run-ship-review.ts +12 -14
- package/scripts/run/ship/run-ship-scoped.ts +15 -6
- package/scripts/run/ship/run-ship-stage.ts +80 -26
- package/scripts/run/ship/run-ship-steps.ts +26 -16
- package/scripts/run/ship/run-ship-stop-text.ts +4 -2
- package/scripts/run/ship/run-ship-sync.ts +9 -8
- package/scripts/run/ship/run-ship.ts +17 -32
- package/scripts/run/tidy/run-tidy-cli.ts +9 -5
- package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
- package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
- package/scripts/run/tidy/run-tidy.ts +4 -3
- package/scripts/run/wake/run-wake-cli.ts +27 -32
- package/scripts/run/wake/run-wake-describe.ts +24 -28
- package/scripts/run/wake/run-wake-driver.ts +14 -14
- package/scripts/run/wake/run-wake-handoff.ts +6 -6
- package/scripts/run/wake/run-wake-loop.ts +9 -9
- package/scripts/run/wake/run-wake-restart.ts +4 -5
- package/scripts/run/wake/run-wake-session.ts +23 -27
- package/scripts/run/wake/run-wake.ts +57 -279
- package/scripts/safe-chain/ci-installer-pin.ts +3 -3
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -2
- package/scripts/security/security-audit-logic.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +1 -1
- package/scripts/security/security-audit-provision.ts +2 -2
- package/scripts/security/security-audit.ts +5 -5
- package/scripts/security/security-updates-logic.ts +2 -3
- package/scripts/security/security-updates.ts +2 -4
- package/scripts/self-sync-guard/index.ts +1 -1
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
- package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
- package/scripts/sonar/sonar-hotspots.ts +1 -1
- package/scripts/sonar/sonar-new-code-cli.ts +1 -1
- package/scripts/sonar/sonar-new-code.ts +1 -1
- package/scripts/sonar/sonar-project.ts +1 -1
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +3 -3
- package/scripts/sync/directory-copy-guard.ts +2 -3
- package/scripts/sync/managed-config-scope-cli.ts +1 -2
- package/scripts/sync/managed-config-scope.ts +4 -4
- package/scripts/sync/plugin-skill-directories.ts +2 -2
- package/scripts/sync/reconcile-templates.ts +17 -8
- package/scripts/sync/removed-skill-manifest.ts +2 -3
- package/scripts/sync/sync-ai-files.ts +7 -7
- package/scripts/sync/sync-configs.ts +30 -3
- package/scripts/sync/sync-hook-safety.ts +2 -2
- package/scripts/sync/sync.ts +23 -10
- package/scripts/sync/synced-paths.ts +2 -1
- package/scripts/sync/workflow-pin-logic.ts +1 -1
- package/scripts/test/test-declared-changed.ts +4 -4
- package/scripts/test/test-declared-logic.ts +2 -3
- package/scripts/test/test-declared-match.ts +25 -4
- package/scripts/test/test-declared.ts +26 -9
- package/scripts/test/test-red-commit.ts +3 -2
- package/scripts/test/test-red-logic.ts +7 -14
- package/scripts/test/test-red.ts +12 -47
- package/scripts/test/test-related-scope.ts +2 -3
- package/scripts/test/test-related.ts +3 -3
- package/scripts/test/test-type-logic.ts +1 -2
- package/scripts/test/test-unit-guard.ts +13 -17
- package/scripts/test/unit-worker-share.ts +7 -8
- package/scripts/time-runtime/time-agent-bundles.ts +2 -4
- package/scripts/time-runtime/time-background.ts +17 -21
- package/scripts/time-runtime/time-batch-guard.ts +67 -342
- package/scripts/time-runtime/time-bundle-call.ts +26 -28
- package/scripts/time-runtime/time-bundles.ts +11 -12
- package/scripts/time-runtime/time-call-identity.ts +1 -1
- package/scripts/time-runtime/time-command-key.ts +2 -2
- package/scripts/time-runtime/time-density-hook.ts +8 -11
- package/scripts/time-runtime/time-density.ts +5 -5
- package/scripts/time-runtime/time-followup-stage.ts +7 -7
- package/scripts/time-runtime/time-format.ts +5 -5
- package/scripts/time-runtime/time-hook-transcript.ts +3 -3
- package/scripts/time-runtime/time-instant.ts +1 -1
- package/scripts/time-runtime/time-markers.ts +15 -19
- package/scripts/time-runtime/time-phase-names.ts +3 -3
- package/scripts/time-runtime/time-reported-failure.ts +15 -19
- package/scripts/time-runtime/time-round-trips.ts +20 -23
- package/scripts/time-runtime/time-shell.ts +8 -8
- package/scripts/time-runtime/time-single-check.ts +1 -2
- package/scripts/time-runtime/time-spans.ts +35 -40
- package/scripts/time-runtime/time-tool-call.ts +15 -16
- package/scripts/time-runtime/time-transcript-line.ts +53 -34
- package/scripts/time-runtime/time-writes.ts +5 -5
- package/scripts/ui/ui-routes-cli.ts +1 -2
- package/scripts/ui/ui-routes.ts +1 -2
- package/scripts/version/bump-version.ts +1 -1
- package/scripts/version/fresh-metadata-cache.ts +2 -2
- package/scripts/version/latest-corepack.ts +26 -26
- package/scripts/version/latest-lane-guard.ts +1 -1
- package/scripts/version/latest-scope-cli.ts +2 -2
- package/scripts/version/latest-stamp.ts +1 -2
- package/scripts/version/latest-update.ts +2 -2
- package/scripts/version/npm-registry.ts +2 -2
- package/scripts/version/package-manager-version.ts +18 -0
- package/scripts/version/publishable-range-check.ts +2 -1
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +11 -11
- package/scripts/version/release-hold.ts +2 -2
- package/scripts/version/safe-chain-version-update.ts +3 -3
- package/scripts/version/version-check-logic.ts +2 -3
- package/scripts/version/version-check.ts +1 -2
- package/scripts/version/version-command-config.ts +2 -2
- package/scripts/version/version-commands.ts +3 -3
- package/scripts/version/version-remote.ts +4 -4
- package/scripts/version/version-targets.ts +2 -2
- package/templates/gitignore +7 -0
- package/dist/hooks/chunk-KHX4U3BG.js +0 -6400
- package/dist/hooks/chunk-RKUAD3I6.js +0 -90
- package/dist/hooks/chunk-WPALEIRX.js +0 -18
- package/scripts/backlog/backlog-restructure.ts +0 -152
- package/scripts/rules/issue-fold-rule.ts +0 -72
- package/scripts/rules/wip-cap.ts +0 -63
- package/scripts/run/run-issue-number.ts +0 -19
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { run_progress } from '#scripts/run/progress/run-progress'
|
|
2
|
+
import type { ClosedIssue } from './run-board-closed'
|
|
3
|
+
import { run_board_github } from './run-board-github'
|
|
4
|
+
import { run_board_header, type BoardHeader } from './run-board-header'
|
|
5
|
+
import { run_board_labels } from './run-board-labels'
|
|
6
|
+
import { run_board_layout, type BoardLayout, type BoardPlan } from './run-board-layout'
|
|
7
|
+
import { run_board_link } from './run-board-link'
|
|
8
|
+
import { run_board_machine } from './run-board-machine'
|
|
9
|
+
import { run_board_notes, type Titles } from './run-board-notes'
|
|
10
|
+
import type { LocalRead } from './run-board-read'
|
|
11
|
+
import { run_board_render, type FrameBounds } from './run-board-render'
|
|
12
|
+
import { run_board_spin, type Spun } from './run-board-spin'
|
|
13
|
+
import { run_board_state, type BoardPorts, type BoardState, type Pace } from './run-board-state'
|
|
14
|
+
import { run_board_status } from './run-board-status'
|
|
15
|
+
import { run_board_usage } from './run-board-usage'
|
|
16
|
+
|
|
17
|
+
// One `run:board` redraw. **Three speeds**: the frame is redrawn once a second, on the second, so
|
|
18
|
+
// every elapsed time moves by one, its spinners turned between redraws by `run-board-spin.ts`; the
|
|
19
|
+
// run's own stream and lanes are re-read no more often than `LOCAL_READ_MS`, because each read parses
|
|
20
|
+
// the whole stream and asks git twice, and a board left open all night would otherwise grow heavier
|
|
21
|
+
// as the run grew longer; the GitHub reads they are laid over are `run-board-github.ts`'s, which a
|
|
22
|
+
// live board never waits on. Between reads the last one is kept and drawn against the current time.
|
|
23
|
+
// A run that ended stays on screen until the next one starts. With no run in this checkout it reads
|
|
24
|
+
// nothing from GitHub. The machine is sampled once a second: one `sysctl` takes a few milliseconds,
|
|
25
|
+
// and its gauges are the differences between consecutive samples.
|
|
26
|
+
|
|
27
|
+
const { REDRAW_MS, SPOT } = run_board_spin
|
|
28
|
+
const MACHINE_SAMPLE_MS = run_progress.MS_PER_SECOND
|
|
29
|
+
const LOCAL_READ_SECONDS = 5
|
|
30
|
+
const LOCAL_READ_MS = LOCAL_READ_SECONDS * run_progress.MS_PER_SECOND
|
|
31
|
+
const { FRESH_STATE, is_due } = run_board_state
|
|
32
|
+
const { PLAN_RETRY_MS, gather_github, statuses_for } = run_board_github
|
|
33
|
+
|
|
34
|
+
async function reread(state: BoardState, ports: BoardPorts, now_ms: number): Promise<BoardState> {
|
|
35
|
+
if (!is_due(state.read_ms, LOCAL_READ_MS, now_ms)) return state
|
|
36
|
+
|
|
37
|
+
return { ...state, local: await ports.read_local(), read_ms: now_ms }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Each lane's usage, read on the machine's second; a reading that failed draws no column.
|
|
41
|
+
async function read_usages(
|
|
42
|
+
state: BoardState,
|
|
43
|
+
ports: BoardPorts,
|
|
44
|
+
): Promise<Pick<BoardState, 'usage' | 'usages'>> {
|
|
45
|
+
const usage = await ports.read_usage(state.usage)
|
|
46
|
+
const usages = usage === undefined ? undefined : run_board_usage.usage_of(state.usage, usage)
|
|
47
|
+
|
|
48
|
+
return { usage, usages }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// The sample is timed when it is taken, not when the tick began: a plan read between the two would put
|
|
52
|
+
// its seconds on the wrong side of the rate's interval. It is due by the tick's clock, so a sample
|
|
53
|
+
// taken a few milliseconds into its tick does not slip to the redraw after the second.
|
|
54
|
+
async function resample(state: BoardState, ports: BoardPorts, now_ms: number): Promise<BoardState> {
|
|
55
|
+
if (!is_due(state.sampled_ms, MACHINE_SAMPLE_MS, now_ms)) return state
|
|
56
|
+
|
|
57
|
+
const at_ms = ports.now()
|
|
58
|
+
const machine = { sample: await ports.read_machine(), at_ms }
|
|
59
|
+
const gauges = run_board_machine.gauges_of(state.machine, machine)
|
|
60
|
+
|
|
61
|
+
return { ...state, ...(await read_usages(state, ports)), machine, gauges, sampled_ms: now_ms }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The state of the run on screen; a different run starts its plan state from nothing, so no row, count
|
|
65
|
+
// or baseline of the previous run is drawn over the new one.
|
|
66
|
+
function state_for(state: BoardState, local: LocalRead): BoardState {
|
|
67
|
+
if (state.run_started_ms === local.started_ms) return state
|
|
68
|
+
|
|
69
|
+
const { local: kept, read_ms } = state
|
|
70
|
+
|
|
71
|
+
return { ...FRESH_STATE, local: kept, read_ms, run_started_ms: local.started_ms }
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The plan with a closed child's title and labels under the listing's own.
|
|
75
|
+
function with_closed(plan: BoardPlan, closed: ReadonlyMap<number, ClosedIssue>): BoardPlan {
|
|
76
|
+
const closed_titles = [...closed].map(([issue, { title }]) => [issue, title] as const)
|
|
77
|
+
const closed_labels = [...closed].map(([issue, { labels }]) => [issue, labels] as const)
|
|
78
|
+
const titles = new Map([...closed_titles, ...plan.context.titles])
|
|
79
|
+
const labels = new Map([...closed_labels, ...plan.labels])
|
|
80
|
+
|
|
81
|
+
return { ...plan, context: { ...plan.context, titles }, labels }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The titles the findings name a parked issue by — the rows' own; none before the plan is read.
|
|
85
|
+
function titles_of(state: BoardState): Titles {
|
|
86
|
+
if (state.plan === undefined) return new Map()
|
|
87
|
+
|
|
88
|
+
return with_closed(state.plan, state.closed).context.titles
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// The statuses scoped to the run's plan, a running child the plan's listing no longer holds settled.
|
|
92
|
+
// Before the plan is read, the run's own children alone.
|
|
93
|
+
function layout_for(state: BoardState, local: LocalRead): BoardLayout {
|
|
94
|
+
const { plan, closed } = state
|
|
95
|
+
|
|
96
|
+
if (plan === undefined) {
|
|
97
|
+
return run_board_layout.local_layout_of(
|
|
98
|
+
run_board_status.statuses_of(local.events, local.lanes, new Set()),
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const read = {
|
|
103
|
+
open_numbers: plan.context.open_numbers,
|
|
104
|
+
read_ms: state.fetched_ms,
|
|
105
|
+
closed,
|
|
106
|
+
labels: plan.labels,
|
|
107
|
+
}
|
|
108
|
+
const statuses = run_board_status.settle_closed(statuses_for(plan, local), read)
|
|
109
|
+
|
|
110
|
+
return run_board_layout.layout_of(with_closed(plan, closed), statuses)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// What one redraw draws with.
|
|
114
|
+
interface Redraw {
|
|
115
|
+
ports: BoardPorts
|
|
116
|
+
now_ms: number
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function header_of(
|
|
120
|
+
state: BoardState,
|
|
121
|
+
local: LocalRead,
|
|
122
|
+
layout: BoardLayout,
|
|
123
|
+
redraw: Redraw,
|
|
124
|
+
): BoardHeader {
|
|
125
|
+
return {
|
|
126
|
+
now_ms: redraw.now_ms,
|
|
127
|
+
started_ms: local.started_ms,
|
|
128
|
+
ended_ms: local.ended_ms,
|
|
129
|
+
activity: run_board_status.activity_of(local.events, local.ended_ms !== undefined),
|
|
130
|
+
layout,
|
|
131
|
+
baseline_total: state.baseline_total,
|
|
132
|
+
plan_fetched_ms: state.fetched_ms,
|
|
133
|
+
plan_failed_ms: state.failed_ms,
|
|
134
|
+
is_plan_loading: state.plan_fetch !== undefined,
|
|
135
|
+
machine: state.gauges,
|
|
136
|
+
usages: state.usages,
|
|
137
|
+
form: redraw.ports.form,
|
|
138
|
+
spinner: redraw.ports.is_tty ? SPOT : undefined,
|
|
139
|
+
link: run_board_link.linker(state.plan?.context.repo, redraw.ports.link),
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// The pane a live frame is kept within and the footer it ends on, read at every redraw.
|
|
144
|
+
function bounds_of(ports: BoardPorts): FrameBounds {
|
|
145
|
+
return { size: ports.size?.(), footer: ports.footer }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// The frame with its spinners drawn at this moment's frame, and where they are on screen.
|
|
149
|
+
function frame_of(state: BoardState, local: LocalRead, layout: BoardLayout, redraw: Redraw): Spun {
|
|
150
|
+
const bounds = bounds_of(redraw.ports)
|
|
151
|
+
const lines = run_board_render.render({
|
|
152
|
+
header: header_of(state, local, layout, redraw),
|
|
153
|
+
notes: run_board_notes.notes_of(local.events, titles_of(state)),
|
|
154
|
+
resume: local.resume,
|
|
155
|
+
...bounds,
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return run_board_spin.spun(lines, run_board_labels.spinner_of(redraw.now_ms), bounds.size)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function draw(ports: BoardPorts, lines: ReadonlyArray<string>): void {
|
|
162
|
+
ports.write(`${lines.join('\n')}\n`)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// The first total the plan gives is the baseline every later arrival is counted against; the run's own
|
|
166
|
+
// children before it are no total.
|
|
167
|
+
function draw_run(state: BoardState, local: LocalRead, redraw: Redraw): BoardState {
|
|
168
|
+
const layout = layout_for(state, local)
|
|
169
|
+
const first_total =
|
|
170
|
+
state.plan === undefined ? undefined : run_board_header.counts_of(layout).total
|
|
171
|
+
const settled = { ...state, baseline_total: state.baseline_total ?? first_total }
|
|
172
|
+
const { lines, spots } = frame_of(settled, local, layout, redraw)
|
|
173
|
+
|
|
174
|
+
draw(redraw.ports, lines)
|
|
175
|
+
|
|
176
|
+
return { ...settled, spots }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// One redraw. No run reads nothing from GitHub and keeps the plan it had for when one starts. A live
|
|
180
|
+
// board redraws at the `background` pace; one plain frame waits for the GitHub reads.
|
|
181
|
+
async function tick(
|
|
182
|
+
state: BoardState,
|
|
183
|
+
ports: BoardPorts,
|
|
184
|
+
pace: Pace = 'settled',
|
|
185
|
+
): Promise<BoardState> {
|
|
186
|
+
const now_ms = ports.now()
|
|
187
|
+
const read = await reread(state, ports, now_ms)
|
|
188
|
+
const { local } = read
|
|
189
|
+
|
|
190
|
+
if (local === undefined) {
|
|
191
|
+
draw(ports, run_board_render.render_no_run(now_ms, bounds_of(ports)))
|
|
192
|
+
|
|
193
|
+
return { ...read, spots: [] }
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const gathered = await gather_github(state_for(read, local), { ports, local, now_ms, pace })
|
|
197
|
+
|
|
198
|
+
return draw_run(await resample(gathered, ports, now_ms), local, { ports, now_ms })
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const run_board_tick = {
|
|
202
|
+
FRESH_STATE,
|
|
203
|
+
LOCAL_READ_MS,
|
|
204
|
+
MACHINE_SAMPLE_MS,
|
|
205
|
+
PLAN_RETRY_MS,
|
|
206
|
+
REDRAW_MS,
|
|
207
|
+
tick,
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { run_board_tick }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { run_board_labels } from './run-board-labels'
|
|
2
|
+
import type { Phase } from './run-board-phase'
|
|
3
|
+
import type { ItemState } from './run-board-status'
|
|
4
|
+
|
|
5
|
+
// A row's phases as a track: the icon of every phase it has passed, left to right, so how far a child
|
|
6
|
+
// has got and what it is doing now are one mark. **The track is a history**: it grows as the child
|
|
7
|
+
// goes and draws nothing ahead, since a ship that stops sends the child back and no fixed frame says
|
|
8
|
+
// how many rounds are left.
|
|
9
|
+
|
|
10
|
+
const { PHASE_ICONS, STATE_ICONS } = run_board_labels
|
|
11
|
+
|
|
12
|
+
// A settled row's track ends on the row's own state icon rather than a fixed ✅, so a child that
|
|
13
|
+
// stopped or parked never reads as having succeeded.
|
|
14
|
+
function track_of(track: ReadonlyArray<Phase>, state: ItemState = 'running'): string {
|
|
15
|
+
const end = state === 'running' ? '' : STATE_ICONS[state]
|
|
16
|
+
|
|
17
|
+
return `${track.map((phase) => PHASE_ICONS[phase]).join('')}${end}`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const run_board_track = { track_of }
|
|
21
|
+
|
|
22
|
+
export { run_board_track }
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { cpus, totalmem } from 'node:os'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { lane_paths } from '#scripts/lane/lane-paths'
|
|
4
|
+
import { lane_registry } from '#scripts/lane/lane-registry'
|
|
5
|
+
import { PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
6
|
+
import { execa } from 'execa'
|
|
7
|
+
import type { ProcessReading, UsageMark } from './run-board-usage'
|
|
8
|
+
import { run_board_usage_rusage, type RusageReader } from './run-board-usage-rusage'
|
|
9
|
+
|
|
10
|
+
// How `run:board` reads which lane each process belongs to and what it uses.
|
|
11
|
+
// **One `ps` a second, and `lsof` only for a process not seen before.** `ps` lists every process's
|
|
12
|
+
// cumulative CPU time and resident memory in about 15 ms; a process is put in the lane its working
|
|
13
|
+
// directory sits under (`.kit-lanes/<N>`), looked up once and remembered, so a full `lsof` (about
|
|
14
|
+
// 220 ms) is paid on the first sample alone. The working directory rather than the parent chain: a
|
|
15
|
+
// process detached with `josh ship --detach` is re-parented and no longer traceable to its lane.
|
|
16
|
+
// **Only this repository's lanes root counts** — another repository's lane of the same number is a
|
|
17
|
+
// different lane. **macOS alone:** Linux's `ps` prints `time` in whole seconds, too coarse for a
|
|
18
|
+
// one-second difference, so there the board draws no column rather than a figure flickering to 0.
|
|
19
|
+
// **A process born and gone between two samples** — a vitest worker, a gate's eslint / tsc / cspell —
|
|
20
|
+
// is never seen by `ps`, and macOS's `ps -S` does not fold a reaped child's time into its parent's.
|
|
21
|
+
// Where `node:ffi` reaches the kernel's reaped-children times (`run-board-usage-rusage.ts`), each
|
|
22
|
+
// process's CPU time is read with them folded in and its parent is kept, so such a child lands in its
|
|
23
|
+
// parent's lane; elsewhere the figure stays `ps`'s own time, a lower bound.
|
|
24
|
+
|
|
25
|
+
const PS_ARGUMENTS = ['-A', '-o', 'pid=,ppid=,time=,rss=']
|
|
26
|
+
const LSOF_ARGUMENTS = ['-a', '-d', 'cwd', '-Fn', '-p']
|
|
27
|
+
const PID_SEPARATOR = ','
|
|
28
|
+
const PS_FIELDS = 4
|
|
29
|
+
const DAY_SEPARATOR = '-'
|
|
30
|
+
const CLOCK_SEPARATOR = ':'
|
|
31
|
+
const SECONDS_PER_DAY = 86_400
|
|
32
|
+
const SECONDS_PER_CLOCK_PART = 60
|
|
33
|
+
const MS_PER_SECOND = 1000
|
|
34
|
+
const BYTES_PER_KB = 1024
|
|
35
|
+
// `lsof -F`'s field lines: `p<pid>` opens a process, `n<path>` names its directory.
|
|
36
|
+
const LSOF_PROCESS = /^(?=p)/mu
|
|
37
|
+
const LSOF_NAME = 'n'
|
|
38
|
+
const { load_builtin, rusage_reader } = run_board_usage_rusage
|
|
39
|
+
|
|
40
|
+
// One process's line of `ps`'s listing.
|
|
41
|
+
interface ProcessListing {
|
|
42
|
+
parent: number
|
|
43
|
+
reading: ProcessReading
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface UsagePorts {
|
|
47
|
+
// `ps`'s listing.
|
|
48
|
+
list: () => Promise<string>
|
|
49
|
+
// Each process's CPU time with its reaped children's, where `node:ffi` reaches it.
|
|
50
|
+
rusage: RusageReader | undefined
|
|
51
|
+
// The working directory of each process that answered.
|
|
52
|
+
directories: (pids: ReadonlyArray<number>) => Promise<ReadonlyMap<number, string>>
|
|
53
|
+
now: () => number
|
|
54
|
+
// The board's own lanes root.
|
|
55
|
+
root: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// `ps`'s `time`, `[DD-][HH:]MM:SS[.ss]`, in milliseconds.
|
|
59
|
+
function cpu_ms_of(text: string): number {
|
|
60
|
+
const [days, clock = ''] = text.includes(DAY_SEPARATOR) ? text.split(DAY_SEPARATOR) : ['0', text]
|
|
61
|
+
const seconds = clock
|
|
62
|
+
.split(CLOCK_SEPARATOR)
|
|
63
|
+
.reduce((sum, part) => sum * SECONDS_PER_CLOCK_PART + Number(part), 0)
|
|
64
|
+
|
|
65
|
+
return (Number(days) * SECONDS_PER_DAY + seconds) * MS_PER_SECOND
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function listing_of(line: string): [number, ProcessListing] | undefined {
|
|
69
|
+
const fields = line.trim().split(/\s+/u)
|
|
70
|
+
const [pid, parent, time = '', rss] = fields
|
|
71
|
+
const reading = { cpu_ms: cpu_ms_of(time), rss_bytes: Number(rss) * BYTES_PER_KB }
|
|
72
|
+
const is_number = !Number.isNaN(reading.cpu_ms + reading.rss_bytes + Number(parent))
|
|
73
|
+
|
|
74
|
+
if (!is_number || fields.length !== PS_FIELDS) return undefined
|
|
75
|
+
|
|
76
|
+
return [Number(pid), { parent: Number(parent), reading }]
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function parse_ps(output: string): Map<number, ProcessListing> {
|
|
80
|
+
const listings = output.split('\n').map((line) => listing_of(line))
|
|
81
|
+
|
|
82
|
+
return new Map(listings.filter((listing) => listing !== undefined))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// A process whose read failed keeps the larger of `ps`'s own time and its last reading: once reaped,
|
|
86
|
+
// its whole folded count lands in its parent's, so what comes off there has to be that count — its own
|
|
87
|
+
// time alone would count its reaped children a second time.
|
|
88
|
+
function folded_reading(
|
|
89
|
+
reading: ProcessReading,
|
|
90
|
+
cpu_ms: number | undefined,
|
|
91
|
+
earlier: ProcessReading | undefined,
|
|
92
|
+
): ProcessReading {
|
|
93
|
+
if (cpu_ms !== undefined) return { ...reading, cpu_ms }
|
|
94
|
+
|
|
95
|
+
return { ...reading, cpu_ms: Math.max(reading.cpu_ms, earlier?.cpu_ms ?? 0) }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
type Readings = Pick<UsageMark, 'folded' | 'parents' | 'processes'>
|
|
99
|
+
|
|
100
|
+
function own_readings(listings: ReadonlyMap<number, ProcessListing>): Readings {
|
|
101
|
+
const processes = new Map([...listings].map(([pid, { reading }]) => [pid, reading] as const))
|
|
102
|
+
|
|
103
|
+
return { processes, parents: new Map(), folded: new Set() }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// `ps`'s own-time readings, each replaced by its reaped-children-folded time where `rusage` reads one.
|
|
107
|
+
// Every process keeps its parent once there is a reader: one whose own read failed — gone by then, or
|
|
108
|
+
// another user's — still lands in its parent's count when reaped, so what was counted for it comes off.
|
|
109
|
+
function readings_of(
|
|
110
|
+
listings: ReadonlyMap<number, ProcessListing>,
|
|
111
|
+
rusage: RusageReader | undefined,
|
|
112
|
+
earlier: ReadonlyMap<number, ProcessReading> = new Map(),
|
|
113
|
+
): Readings {
|
|
114
|
+
if (rusage === undefined) return own_readings(listings)
|
|
115
|
+
|
|
116
|
+
const processes = new Map<number, ProcessReading>()
|
|
117
|
+
const folded = new Set<number>()
|
|
118
|
+
const parents = new Map([...listings].map(([pid, { parent }]) => [pid, parent] as const))
|
|
119
|
+
|
|
120
|
+
for (const [pid, { reading }] of listings) {
|
|
121
|
+
const cpu_ms = rusage(pid)
|
|
122
|
+
|
|
123
|
+
processes.set(pid, folded_reading(reading, cpu_ms, earlier.get(pid)))
|
|
124
|
+
if (cpu_ms !== undefined) folded.add(pid)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return { processes, parents, folded }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function lsof_block(block: string): [number, string] | undefined {
|
|
131
|
+
const [process_line = '', ...rest] = block.trim().split('\n')
|
|
132
|
+
const name = rest.find((line) => line.startsWith(LSOF_NAME))
|
|
133
|
+
|
|
134
|
+
return name === undefined ? undefined : [Number(process_line.slice(1)), name.slice(1)]
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function parse_lsof(output: string): Map<number, string> {
|
|
138
|
+
const blocks = output.split(LSOF_PROCESS).map((block) => lsof_block(block))
|
|
139
|
+
|
|
140
|
+
return new Map(blocks.filter((block) => block !== undefined))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// The lane of `root` a directory sits under — itself or a directory above it, the outermost first.
|
|
144
|
+
function lane_of(directory: string, root: string): string | undefined {
|
|
145
|
+
const parts = directory.split(path.sep)
|
|
146
|
+
const ancestors = parts.map((_, index) => parts.slice(0, index + 1).join(path.sep)).slice(1)
|
|
147
|
+
const environment = { [lane_paths.LANE_ROOT_KEY]: root }
|
|
148
|
+
|
|
149
|
+
return ancestors.map((ancestor) => lane_paths.lane_issue_of(ancestor, environment)).find(Boolean)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function directory_lane(directory: string | undefined, root: string): string | undefined {
|
|
153
|
+
return directory === undefined ? undefined : lane_of(directory, root)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The lanes of the processes still listed: a gone one dropped, and one not seen before looked up.
|
|
157
|
+
async function lanes_for(
|
|
158
|
+
known: ReadonlyMap<number, string | undefined>,
|
|
159
|
+
processes: ReadonlyMap<number, ProcessReading>,
|
|
160
|
+
ports: UsagePorts,
|
|
161
|
+
): Promise<Map<number, string | undefined>> {
|
|
162
|
+
const kept = new Map([...known].filter(([pid]) => processes.has(pid)))
|
|
163
|
+
const fresh = [...processes.keys()].filter((pid) => !kept.has(pid))
|
|
164
|
+
|
|
165
|
+
if (fresh.length === 0) return kept
|
|
166
|
+
|
|
167
|
+
const directories = await ports.directories(fresh)
|
|
168
|
+
const found = fresh.map((pid) => [pid, directory_lane(directories.get(pid), ports.root)] as const)
|
|
169
|
+
|
|
170
|
+
return new Map([...kept, ...found])
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async function sample(before: UsageMark | undefined, ports: UsagePorts): Promise<UsageMark> {
|
|
174
|
+
const at_ms = ports.now()
|
|
175
|
+
const readings = readings_of(parse_ps(await ports.list()), ports.rusage, before?.processes)
|
|
176
|
+
const lanes = await lanes_for(before?.lanes ?? new Map(), readings.processes, ports)
|
|
177
|
+
|
|
178
|
+
return { at_ms, ...readings, lanes, cores: cpus().length, total_bytes: totalmem() }
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function darwin_directories(
|
|
182
|
+
pids: ReadonlyArray<number>,
|
|
183
|
+
): Promise<ReadonlyMap<number, string>> {
|
|
184
|
+
// `lsof` exits non-zero when any one process is gone, and still lists the rest. A budget kill is
|
|
185
|
+
// not that: it lists nothing, and `lanes_for` never asks again about a process it read as being in
|
|
186
|
+
// no lane, so the sample fails instead of pinning every live process to none.
|
|
187
|
+
const lsof_arguments = [...LSOF_ARGUMENTS, pids.join(PID_SEPARATOR)]
|
|
188
|
+
const result = await execa('lsof', lsof_arguments, { reject: false, timeout: PROBE_TIMEOUT_MS })
|
|
189
|
+
|
|
190
|
+
if (result.timedOut) throw new Error('lsof timed out')
|
|
191
|
+
|
|
192
|
+
return parse_lsof(result.stdout)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const PLATFORM_DIRECTORIES: Readonly<Partial<Record<NodeJS.Platform, UsagePorts['directories']>>> =
|
|
196
|
+
{ darwin: darwin_directories }
|
|
197
|
+
|
|
198
|
+
async function list_live(): Promise<string> {
|
|
199
|
+
const { stdout } = await execa('ps', PS_ARGUMENTS, { timeout: PROBE_TIMEOUT_MS })
|
|
200
|
+
|
|
201
|
+
return stdout
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function board_lane_root(): Promise<string> {
|
|
205
|
+
return lane_paths.lane_root(await lane_registry.main_repository_root())
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// What one board's reader resolves once and keeps, since neither moves while the board is open.
|
|
209
|
+
interface ReaderSetup {
|
|
210
|
+
root: Promise<string>
|
|
211
|
+
rusage: RusageReader | undefined
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// `undefined` where the processes cannot be read — no `ps`, no way to a working directory, no
|
|
215
|
+
// repository — so the board draws no column rather than failing.
|
|
216
|
+
async function read_usage(
|
|
217
|
+
before: UsageMark | undefined,
|
|
218
|
+
setup: ReaderSetup,
|
|
219
|
+
platform: NodeJS.Platform,
|
|
220
|
+
): Promise<UsageMark | undefined> {
|
|
221
|
+
const directories = PLATFORM_DIRECTORIES[platform]
|
|
222
|
+
|
|
223
|
+
if (directories === undefined) return undefined
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const { rusage } = setup
|
|
227
|
+
const ports = { list: list_live, rusage, directories, now: Date.now, root: await setup.root }
|
|
228
|
+
|
|
229
|
+
return await sample(before, ports)
|
|
230
|
+
} catch {
|
|
231
|
+
return undefined
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// One board's reader: the `node:ffi` reader is opened with it, and the lanes root resolved on the first
|
|
236
|
+
// sample.
|
|
237
|
+
function usage_reader(
|
|
238
|
+
platform: NodeJS.Platform = process.platform,
|
|
239
|
+
): (before: UsageMark | undefined) => Promise<UsageMark | undefined> {
|
|
240
|
+
const rusage = rusage_reader(platform, load_builtin)
|
|
241
|
+
const resolved: { root?: Promise<string> } = {}
|
|
242
|
+
|
|
243
|
+
async function read(before: UsageMark | undefined): Promise<UsageMark | undefined> {
|
|
244
|
+
resolved.root ??= board_lane_root()
|
|
245
|
+
|
|
246
|
+
return await read_usage(before, { root: resolved.root, rusage }, platform)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return read
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const run_board_usage_read = { lane_of, parse_lsof, parse_ps, sample, usage_reader }
|
|
253
|
+
|
|
254
|
+
export { run_board_usage_read }
|
|
255
|
+
export type { UsagePorts }
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { dlopen } from 'node:ffi'
|
|
2
|
+
|
|
3
|
+
// A process's CPU time with the children it has reaped folded in, so a vitest worker or a gate's
|
|
4
|
+
// eslint born and gone between two `run:board` samples still reaches its lane through its parent.
|
|
5
|
+
// macOS's `ps -S` does not fold them; the kernel keeps them in `proc_pid_rusage`'s
|
|
6
|
+
// `ri_child_user_time` / `ri_child_system_time`, reached here through `node:ffi`.
|
|
7
|
+
//
|
|
8
|
+
// **`node:ffi` is experimental** — added in Node 26 (kit's `engines` is `^22.19.0 || ^24.0.0 ||
|
|
9
|
+
// >=26.0.0`) and liable to change. Where it is missing, or the platform is not macOS, or a call
|
|
10
|
+
// fails, there is no reader and the board keeps `ps`'s own-time figure. Loading it emits an
|
|
11
|
+
// `ExperimentalWarning`, which would land on the board's alternate screen, so the load alone drops it.
|
|
12
|
+
|
|
13
|
+
// The one part of `node:ffi` the board calls.
|
|
14
|
+
interface Ffi {
|
|
15
|
+
dlopen: typeof dlopen
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type ModuleLoad = (id: string) => unknown
|
|
19
|
+
|
|
20
|
+
// `ri_*` times are mach absolute time units, which `mach_timebase_info`'s numer / denom turn into ns.
|
|
21
|
+
interface Timebase {
|
|
22
|
+
numer: number
|
|
23
|
+
denom: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// The CPU milliseconds of one process, `undefined` where it cannot be read (gone, or another user's).
|
|
27
|
+
type RusageReader = (pid: number) => number | undefined
|
|
28
|
+
|
|
29
|
+
const PROC_LIBRARY = '/usr/lib/libproc.dylib'
|
|
30
|
+
const SYSTEM_LIBRARY = '/usr/lib/libSystem.B.dylib'
|
|
31
|
+
const RUSAGE_INFO_V2 = 2
|
|
32
|
+
const RUSAGE_INFO_V2_BYTES = 160
|
|
33
|
+
// `rusage_info_v2`'s `ri_user_time`, `ri_system_time`, `ri_child_user_time`, `ri_child_system_time`.
|
|
34
|
+
const USER_TIME_OFFSET = 16
|
|
35
|
+
const SYSTEM_TIME_OFFSET = 24
|
|
36
|
+
const CHILD_USER_TIME_OFFSET = 96
|
|
37
|
+
const CHILD_SYSTEM_TIME_OFFSET = 104
|
|
38
|
+
const TIME_OFFSETS = [
|
|
39
|
+
USER_TIME_OFFSET,
|
|
40
|
+
SYSTEM_TIME_OFFSET,
|
|
41
|
+
CHILD_USER_TIME_OFFSET,
|
|
42
|
+
CHILD_SYSTEM_TIME_OFFSET,
|
|
43
|
+
]
|
|
44
|
+
const TIMEBASE_BYTES = 8
|
|
45
|
+
const DENOM_OFFSET = 4
|
|
46
|
+
const NS_PER_MS = 1_000_000
|
|
47
|
+
const EXPERIMENTAL_WARNING = 'ExperimentalWarning'
|
|
48
|
+
const DARWIN: NodeJS.Platform = 'darwin'
|
|
49
|
+
|
|
50
|
+
const PROC_PID_RUSAGE = {
|
|
51
|
+
proc_pid_rusage: { arguments: ['int32', 'int32', 'buffer'], return: 'int32' },
|
|
52
|
+
} as const
|
|
53
|
+
const MACH_TIMEBASE_INFO = {
|
|
54
|
+
mach_timebase_info: { arguments: ['buffer'], return: 'int32' },
|
|
55
|
+
} as const
|
|
56
|
+
|
|
57
|
+
// The four times of an `rusage_info_v2`, in milliseconds.
|
|
58
|
+
function cpu_ms_of(buffer: Buffer, timebase: Timebase): number {
|
|
59
|
+
const ticks = TIME_OFFSETS.reduce(
|
|
60
|
+
(sum, offset) => sum + Number(buffer.readBigUInt64LE(offset)),
|
|
61
|
+
0,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return (ticks * timebase.numer) / timebase.denom / NS_PER_MS
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// `node:ffi`, its load's `ExperimentalWarning` dropped — the load is synchronous, so no other warning
|
|
68
|
+
// can fall inside the window.
|
|
69
|
+
function quiet_ffi(load: ModuleLoad): Ffi | undefined {
|
|
70
|
+
const emit_warning = process.emitWarning
|
|
71
|
+
|
|
72
|
+
process.emitWarning = function quiet(warning: string | Error, ...rest: Array<unknown>): void {
|
|
73
|
+
if (rest[0] !== EXPERIMENTAL_WARNING) Reflect.apply(emit_warning, process, [warning, ...rest])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
return load('node:ffi') as Ffi | undefined
|
|
78
|
+
} finally {
|
|
79
|
+
process.emitWarning = emit_warning
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function timebase_of(ffi: Ffi): Timebase {
|
|
84
|
+
const buffer = Buffer.alloc(TIMEBASE_BYTES)
|
|
85
|
+
|
|
86
|
+
ffi.dlopen(SYSTEM_LIBRARY, MACH_TIMEBASE_INFO).functions.mach_timebase_info(buffer)
|
|
87
|
+
|
|
88
|
+
return { numer: buffer.readUInt32LE(0), denom: buffer.readUInt32LE(DENOM_OFFSET) }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function reader_of(ffi: Ffi): RusageReader {
|
|
92
|
+
const timebase = timebase_of(ffi)
|
|
93
|
+
const { proc_pid_rusage } = ffi.dlopen(PROC_LIBRARY, PROC_PID_RUSAGE).functions
|
|
94
|
+
const buffer = Buffer.alloc(RUSAGE_INFO_V2_BYTES)
|
|
95
|
+
|
|
96
|
+
return function read(pid: number): number | undefined {
|
|
97
|
+
const status = proc_pid_rusage(pid, RUSAGE_INFO_V2, buffer)
|
|
98
|
+
|
|
99
|
+
return status === 0 ? cpu_ms_of(buffer, timebase) : undefined
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function load_builtin(id: string): unknown {
|
|
104
|
+
return process.getBuiltinModule(id)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// `load` answers `undefined` for a module this Node lacks, as `process.getBuiltinModule` does; there,
|
|
108
|
+
// and off macOS, there is no reader and every process keeps `ps`'s figure.
|
|
109
|
+
function rusage_reader(platform: NodeJS.Platform, load: ModuleLoad): RusageReader | undefined {
|
|
110
|
+
if (platform !== DARWIN) return undefined
|
|
111
|
+
|
|
112
|
+
try {
|
|
113
|
+
const ffi = quiet_ffi(load)
|
|
114
|
+
|
|
115
|
+
return ffi === undefined ? undefined : reader_of(ffi)
|
|
116
|
+
} catch {
|
|
117
|
+
return undefined
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const run_board_usage_rusage = { cpu_ms_of, load_builtin, quiet_ffi, rusage_reader }
|
|
122
|
+
|
|
123
|
+
export { run_board_usage_rusage }
|
|
124
|
+
export type { RusageReader, Timebase }
|