@joshuafolkken/kit 1.1514.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 +5 -5
- package/.claude/skills/epic-commands/SKILL.md +26 -65
- package/.claude/skills/epic-commands/epic-bundle.md +3 -1
- package/.claude/skills/workflow-commands/SKILL.md +5 -5
- package/.claude/skills/workflow-commands/background-commands.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +10 -8
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +7 -25
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +17 -13
- package/.claude/skills/workflow-commands/backlogrun-park.md +14 -23
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +5 -5
- package/.claude/skills/workflow-commands/backlogrun-steps.md +10 -10
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +13 -7
- package/.claude/skills/workflow-commands/delegation.md +6 -5
- package/.claude/skills/workflow-commands/entry-sequence.md +9 -9
- package/.claude/skills/workflow-commands/followup.md +9 -31
- package/.claude/skills/workflow-commands/fullrun-steps.md +36 -45
- package/.claude/skills/workflow-commands/fullrun.md +2 -2
- package/.claude/skills/workflow-commands/halfrun.md +17 -25
- package/.claude/skills/workflow-commands/issue-comments.md +16 -12
- package/.claude/skills/workflow-commands/issue-scout.md +2 -2
- package/.claude/skills/workflow-commands/kickoff.md +24 -23
- package/.claude/skills/workflow-commands/latest-gate.md +7 -12
- package/.claude/skills/workflow-commands/needs-human-review.md +9 -14
- package/.claude/skills/workflow-commands/observation-filing.md +4 -36
- package/.claude/skills/workflow-commands/observation-ledger.md +1 -1
- package/.claude/skills/workflow-commands/pre-gate-cut.md +13 -30
- package/.claude/skills/workflow-commands/prerequisite.md +10 -16
- package/.claude/skills/workflow-commands/progress-watcher.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +3 -7
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/split-assessment.md +13 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +9 -9
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-node/action.yml +9 -0
- 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 +120 -10
- package/.github/workflows/publish.yml +8 -1
- package/.github/workflows/sonar-qube.yml +1 -0
- package/.prettierignore +2 -0
- package/.vscode/tasks.json +1 -2
- package/CLAUDE.md +3 -7
- package/README.md +4 -2
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +3 -7
- package/dist/commands/document-read-cli.js +882 -0
- package/dist/commands/{document-section-cli.js → document-section-main.js} +79 -37
- 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-TNUMY6NL.js → chunk-PT5R6UJD.js} +4193 -1900
- package/dist/hooks/chunk-TUIFS5E7.js +72 -0
- package/dist/hooks/{chunk-723HKZO5.js → chunk-VWWCFGWK.js} +1 -1
- package/dist/hooks/{chunk-APUO6U4J.js → chunk-WR2KQAYZ.js} +1843 -440
- package/dist/hooks/{chunk-O6GDRNJB.js → chunk-XGBNSWEI.js} +248 -46
- package/dist/hooks/chunk-YCDOIR3I.js +3456 -0
- package/dist/hooks/codex-hook-adapter.js +10 -22
- package/dist/hooks/format-edited.js +5 -6
- package/dist/hooks/inputs.json +443 -317
- package/dist/hooks/pretool-guard.js +7 -25
- package/dist/hooks/session-lang.js +44 -51
- package/dist/hooks/stop-guard.js +7716 -2187
- package/dist/josh.js +6002 -3583
- 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 +3 -1
- package/package.json +10 -48
- package/pnpm-workspace.yaml +4 -2
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +1 -7
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +33 -16
- package/prompts/collaboration-workflow/lane-instructions.md +1 -2
- package/prompts/collaboration-workflow/measurement.md +37 -0
- package/prompts/collaboration-workflow/operating-rules.md +4 -6
- package/prompts/collaboration-workflow/output-bounds.md +2 -7
- package/prompts/collaboration-workflow/plan-comment.md +3 -42
- package/prompts/collaboration-workflow/principles.md +5 -0
- package/prompts/collaboration-workflow/report-format.md +31 -60
- package/prompts/collaboration-workflow/residency.md +2 -2
- package/prompts/collaboration-workflow/shell-body.md +6 -16
- package/prompts/collaboration-workflow/turn-batching.md +0 -2
- package/prompts/collaboration-workflow/upstream-interrupt.md +14 -4
- package/prompts/collaboration-workflow/wip-cap.md +1 -1
- package/prompts/collaboration-workflow.md +3 -7
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +1 -2
- package/prompts/review.md +41 -21
- package/prompts/testing-guide.md +8 -43
- package/scripts/agent/agent-event.ts +15 -15
- package/scripts/agent/agent-exit-record.ts +13 -1
- package/scripts/agent/api-auth.ts +41 -0
- package/scripts/agent/api-outage.ts +1 -1
- 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 +2 -3
- 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 +53 -6
- 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 +30 -7
- 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 +52 -39
- 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 +112 -30
- 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 +0 -8
- package/scripts/delegation/investigation-guard.ts +0 -8
- package/scripts/delegation/investigation-reads.ts +3 -4
- 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 +8 -6
- package/scripts/document/document-scan.ts +1 -1
- package/scripts/document/document-section-cli.ts +0 -8
- package/scripts/document/document-section-main.ts +12 -0
- package/scripts/epic/epic-audit-cli.ts +12 -6
- package/scripts/epic/epic-bundle-apply.ts +137 -0
- package/scripts/epic/epic-bundle-cli.ts +32 -121
- package/scripts/epic/epic-bundle-format.ts +116 -0
- package/scripts/epic/epic-bundle-main.ts +17 -0
- 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 +19 -66
- 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 +39 -95
- package/scripts/gate/check-reuse.ts +33 -54
- 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 +80 -98
- package/scripts/gate/core-wait-record.ts +48 -0
- package/scripts/gate/core-wait.ts +37 -5
- package/scripts/gate/core-weights.ts +86 -0
- package/scripts/gate/free-cores.ts +27 -4
- package/scripts/gate/gate-ledger.ts +32 -4
- package/scripts/gate/gate-plan.ts +41 -34
- package/scripts/gate/gate-report.ts +14 -2
- package/scripts/gate/gate-run-steps.ts +53 -8
- package/scripts/gate/gate-skip.ts +12 -2
- package/scripts/gate/gate-steps.ts +12 -1
- package/scripts/gate/input-fingerprint.ts +42 -0
- package/scripts/gate/machine-capacity.ts +65 -31
- package/scripts/gate/moved-paths.ts +67 -0
- 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 +27 -24
- 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-write.ts +67 -29
- 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/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 +2 -2
- package/scripts/git/main-merge.ts +25 -9
- 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 +0 -8
- 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 +30 -3
- package/scripts/hooks/pre-push-unit.ts +4 -2
- package/scripts/hooks/pretool-guard-cli.ts +1 -8
- package/scripts/hooks/pretool-guard.ts +32 -19
- package/scripts/hooks/reserved-run.ts +67 -9
- package/scripts/hooks/run-hook.sh +13 -4
- package/scripts/hooks/shell-rules-notice.ts +37 -0
- package/scripts/hooks/stop-actions.ts +2 -21
- package/scripts/hooks/stop-guard.ts +13 -9
- package/scripts/init/hook-command-rewrite.ts +19 -5
- package/scripts/init/hook-launch.ts +15 -17
- 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 +1 -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 +0 -9
- package/scripts/issue/issue-cite-main.ts +12 -0
- package/scripts/issue/issue-classification.ts +12 -7
- 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 +2 -10
- 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 +0 -11
- 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/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 +15 -43
- package/scripts/josh/file-map-stamp.ts +49 -16
- package/scripts/josh/hook-decision.ts +32 -20
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +12 -6
- package/scripts/josh/josh-commands-agent-hooks.ts +83 -0
- package/scripts/josh/josh-commands-ai.ts +157 -158
- 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 +25 -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 +103 -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 +144 -6
- package/scripts/josh/josh-logic.ts +6 -13
- package/scripts/josh/package-directory.ts +2 -4
- 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 +14 -23
- package/scripts/lane/lane-check-stats.ts +62 -21
- package/scripts/lane/lane-child-invocation.ts +8 -0
- 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 +24 -3
- package/scripts/lane/lane-gap-stats.ts +156 -0
- package/scripts/lane/lane-handoff.ts +69 -1
- package/scripts/lane/lane-held-stats.ts +129 -0
- package/scripts/lane/lane-install.ts +4 -11
- 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 +92 -123
- package/scripts/lane/lane-limit-cli.ts +12 -1
- package/scripts/lane/lane-measure-cli.ts +57 -11
- 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-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 +24 -3
- package/scripts/lane/lane-residents.ts +162 -0
- package/scripts/lane/lane-restart.ts +22 -2
- 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 +19 -5
- package/scripts/lane/lane-session-broker.ts +102 -21
- 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 +5 -4
- package/scripts/lane/lane-withdraw.ts +50 -49
- 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 +11 -2
- 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 +62 -30
- package/scripts/lint/lint-related-scope.ts +30 -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 +2 -6
- 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 +2 -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.ts +1 -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 +81 -15
- 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 +8 -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 +80 -2
- 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 +7 -0
- package/scripts/rules/git-argv.ts +72 -14
- package/scripts/rules/git-force.ts +12 -2
- package/scripts/rules/guard-remedy.ts +4 -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 +9 -1
- 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/oracle-consulted.ts +10 -0
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/permission-guards.ts +3 -0
- package/scripts/rules/piped-verification.ts +1 -1
- 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 +9 -28
- package/scripts/rules/rule-value-cache.ts +4 -9
- package/scripts/rules/rule-value-cli.ts +51 -32
- package/scripts/rules/rule-value.ts +1 -1
- package/scripts/rules/shell-segments.ts +35 -0
- package/scripts/rules/stop-rule-rows.ts +64 -0
- package/scripts/rules/stop-rules.ts +3 -4
- 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 -32
- 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 +118 -38
- package/scripts/run/board/run-board-header.ts +82 -20
- 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 +116 -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 +239 -60
- 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 +151 -27
- package/scripts/run/board/run-board-reason.ts +235 -51
- 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 -48
- 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 +104 -20
- package/scripts/run/board/run-board-render.ts +207 -265
- package/scripts/run/board/run-board-roots.ts +54 -0
- package/scripts/run/board/run-board-row-yield.ts +9 -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 +22 -33
- package/scripts/run/board/run-board-status.ts +147 -71
- package/scripts/run/board/run-board-thanks-read.ts +2 -2
- package/scripts/run/board/run-board-tick.ts +122 -107
- 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-handoff.ts +2 -2
- 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 +6 -10
- package/scripts/run/event/run-event-scope.ts +2 -2
- package/scripts/run/event/run-event-stream-emit.ts +82 -22
- package/scripts/run/event/run-event-stream.ts +34 -8
- 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-stop-notify.ts +183 -0
- package/scripts/run/merge/run-merge-auth.ts +31 -0
- package/scripts/run/merge/run-merge-cli.ts +62 -48
- 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 +33 -9
- package/scripts/run/merge/run-merge-steps.ts +120 -85
- package/scripts/run/merge/run-merge.ts +38 -37
- 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 +60 -29
- package/scripts/run/run-next.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +2 -2
- 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.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 +63 -140
- package/scripts/run/ship/run-ship-detach.ts +19 -8
- package/scripts/run/ship/run-ship-infra-retry.ts +59 -0
- package/scripts/run/ship/run-ship-next.ts +18 -2
- package/scripts/run/ship/run-ship-overlap.ts +42 -5
- 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 +81 -24
- package/scripts/run/ship/run-ship-preflight.ts +137 -32
- 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 +107 -23
- package/scripts/run/ship/run-ship-review-steps.ts +105 -151
- 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-text.ts +11 -6
- package/scripts/run/ship/run-ship-sync.ts +43 -6
- 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 +25 -1
- 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 +42 -24
- 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 +61 -149
- 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 +97 -10
- 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 +4 -1
- 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-4KKD2UTK.js +0 -66
- package/dist/hooks/chunk-6TS2JD6D.js +0 -237
- package/dist/hooks/chunk-7DSBJVFH.js +0 -50
- package/dist/hooks/chunk-A65Y4YOR.js +0 -79
- package/dist/hooks/chunk-CDY4NFQG.js +0 -15
- package/dist/hooks/chunk-EFXE6C37.js +0 -81
- package/dist/hooks/chunk-GP4IEC4O.js +0 -20
- package/dist/hooks/chunk-JP45SOCJ.js +0 -56
- package/dist/hooks/chunk-LAOV7NLM.js +0 -45
- package/dist/hooks/chunk-M4HGZV7U.js +0 -83
- package/dist/hooks/chunk-PF2NZL2A.js +0 -131
- package/dist/hooks/chunk-PTICX4OL.js +0 -358
- package/dist/hooks/chunk-RT27QRJW.js +0 -6247
- package/dist/hooks/chunk-SYOTDYCI.js +0 -3533
- package/dist/hooks/chunk-UPUZF3AN.js +0 -279
- package/dist/hooks/chunk-WK6SMBIC.js +0 -3180
- package/dist/hooks/duplicate-read-guard.js +0 -30
- package/dist/hooks/investigation-guard.js +0 -29
- 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/josh/josh-usage-automation.ts +0 -121
- package/scripts/josh/josh-usage-backlog.ts +0 -180
- package/scripts/josh/josh-usage-developer.ts +0 -230
- package/scripts/josh/josh-usage-hooks.ts +0 -38
- package/scripts/josh/josh-usage-issue.ts +0 -205
- package/scripts/josh/josh-usage-review.ts +0 -101
- package/scripts/josh/josh-usage-run.ts +0 -252
- package/scripts/josh/josh-usage-session.ts +0 -238
- package/scripts/josh/josh-usage-workflow.ts +0 -212
- 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 -292
- package/scripts/rules/rule-registry.ts +0 -112
- package/scripts/run/run-stranded-cli.ts +0 -27
|
@@ -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 }
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { lstatSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
// An answer remembered per key, recomputed only when the key's stamp changes (joshuafolkken/kit#4263).
|
|
4
|
+
//
|
|
5
|
+
// **`run:board` redraws every second, and most of what it reads has not changed since the last
|
|
6
|
+
// redraw.** A process's app name, a ledger's parsed lines and a work tree's git config were computed
|
|
7
|
+
// again on every pass, and on a saturated machine those passes stopped the spinner for 45–200ms. The
|
|
8
|
+
// stamp is what says "this has changed": a file's `file_stamp`, or a constant where the key alone
|
|
9
|
+
// decides the answer.
|
|
10
|
+
|
|
11
|
+
const NO_STAMP = ''
|
|
12
|
+
const STAMP_SEPARATOR = ':'
|
|
13
|
+
|
|
14
|
+
interface Remembered<Value> {
|
|
15
|
+
stamp: string
|
|
16
|
+
value: Value
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface StampedMemo<Value> {
|
|
20
|
+
// `compute`'s answer for `key`, run only when `key` was never seen or its stamp moved since.
|
|
21
|
+
of: (key: string, stamp: string, compute: () => Value) => Value
|
|
22
|
+
// Forget every key outside `keys` — a process gone from the table, so the memo cannot grow unbounded.
|
|
23
|
+
keep: (keys: ReadonlySet<string>) => void
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function create<Value>(): StampedMemo<Value> {
|
|
27
|
+
const answers = new Map<string, Remembered<Value>>()
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
of(key, stamp, compute) {
|
|
31
|
+
const known = answers.get(key)
|
|
32
|
+
|
|
33
|
+
if (known?.stamp === stamp) return known.value
|
|
34
|
+
|
|
35
|
+
const value = compute()
|
|
36
|
+
|
|
37
|
+
answers.set(key, { stamp, value })
|
|
38
|
+
|
|
39
|
+
return value
|
|
40
|
+
},
|
|
41
|
+
keep(keys) {
|
|
42
|
+
for (const key of answers.keys()) if (!keys.has(key)) answers.delete(key)
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// What changes when a file is rewritten, appended to, replaced or re-owned: its inode, its modification
|
|
48
|
+
// and change times and its size. An absent or unreadable file is `NO_STAMP`, so it reads again once
|
|
49
|
+
// it appears.
|
|
50
|
+
function file_stamp(file: string): string {
|
|
51
|
+
try {
|
|
52
|
+
const status = lstatSync(file)
|
|
53
|
+
|
|
54
|
+
return [status.ino, status.mtimeMs, status.ctimeMs, status.size].join(STAMP_SEPARATOR)
|
|
55
|
+
} catch {
|
|
56
|
+
return NO_STAMP
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const stamped_memo = { NO_STAMP, create, file_stamp }
|
|
61
|
+
|
|
62
|
+
export { stamped_memo }
|
|
63
|
+
export type { StampedMemo }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Runs work whose own reports go to stdout with stdout pointed at stderr, for a caller whose stdout is
|
|
2
|
+
// a contract: the `Stop` hook's decision envelope, and `josh run:hold`'s single verdict token.
|
|
3
|
+
|
|
4
|
+
type StreamWrite = typeof process.stdout.write
|
|
5
|
+
|
|
6
|
+
function set_stdout_write(stream_write: StreamWrite): void {
|
|
7
|
+
process.stdout.write = stream_write
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async function run<T>(work: () => Promise<T>): Promise<T> {
|
|
11
|
+
const saved = { write: process.stdout.write.bind(process.stdout) }
|
|
12
|
+
|
|
13
|
+
set_stdout_write(process.stderr.write.bind(process.stderr))
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
return await work()
|
|
17
|
+
} finally {
|
|
18
|
+
set_stdout_write(saved.write)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const stdout_on_stderr = { run }
|
|
23
|
+
|
|
24
|
+
export { stdout_on_stderr }
|
package/scripts/lib/timeouts.ts
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
// limit stays stuck where it stopped and never comes back, so every such
|
|
4
4
|
// call takes one of these, and a value used in more than one place is named once here.
|
|
5
5
|
|
|
6
|
+
// The unit conversions every duration is read and printed through. They sit beside the limits because a
|
|
7
|
+
// limit is the most common thing they convert; a second copy in a caller is a clone of these two lines.
|
|
8
|
+
const MS_PER_SECOND = 1000
|
|
9
|
+
const SECONDS_PER_MINUTE = 60
|
|
10
|
+
const MS_PER_MINUTE = MS_PER_SECOND * SECONDS_PER_MINUTE
|
|
11
|
+
|
|
6
12
|
// A probe that only asks the local machine (`ps`, `lsof`, `git config`) on a path something else is
|
|
7
13
|
// waiting on. Failing answers "cannot tell", which every caller handles, so anything slower is a fault.
|
|
8
14
|
const PROBE_TIMEOUT_MS = 2000
|
|
@@ -41,6 +47,9 @@ export {
|
|
|
41
47
|
HOOK_PROCESS_TIMEOUT_MS,
|
|
42
48
|
INSTALL_TIMEOUT_MS,
|
|
43
49
|
LINT_TIMEOUT_MS,
|
|
50
|
+
MS_PER_MINUTE,
|
|
51
|
+
MS_PER_SECOND,
|
|
44
52
|
PROBE_TIMEOUT_MS,
|
|
53
|
+
SECONDS_PER_MINUTE,
|
|
45
54
|
SUITE_TIMEOUT_MS,
|
|
46
55
|
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { json_value } from './json-value'
|
|
3
|
+
|
|
4
|
+
// One line of a Claude Code JSONL log — a session transcript, or the `stream-json` output of
|
|
5
|
+
// `claude -p`, which writes the same `{ type, message: { id, content } }` shape. Every reader of those
|
|
6
|
+
// lines parses through these schemas and takes what it needs from the record; a fix to the shape
|
|
7
|
+
// reaches all of them at once.
|
|
8
|
+
//
|
|
9
|
+
// **Every field is optional, including `type`.** A required field would make one unexpected block
|
|
10
|
+
// fail the whole array it sits in, and with it every other block on that line — an entire assistant
|
|
11
|
+
// turn dropped because one tool wrote a shape no reader had seen. A block that parses to nothing
|
|
12
|
+
// contributes nothing.
|
|
13
|
+
|
|
14
|
+
const TEXT_TYPE = 'text'
|
|
15
|
+
const TOOL_USE_TYPE = 'tool_use'
|
|
16
|
+
const TOOL_RESULT_TYPE = 'tool_result'
|
|
17
|
+
|
|
18
|
+
const BLOCK_SCHEMA = z.object({
|
|
19
|
+
type: z.string().nullish(),
|
|
20
|
+
text: z.string().nullish(),
|
|
21
|
+
name: z.string().nullish(),
|
|
22
|
+
id: z.string().nullish(),
|
|
23
|
+
tool_use_id: z.string().nullish(),
|
|
24
|
+
input: z.unknown().nullish(),
|
|
25
|
+
// Whether the harness wrote a `tool_result` back as a failure — absent on every other block, and
|
|
26
|
+
// on the results of tools that never report one.
|
|
27
|
+
is_error: z.boolean().nullish(),
|
|
28
|
+
// A result's body: a string or a list of blocks. Read as `unknown` because each reader flattens it
|
|
29
|
+
// its own way, and a narrower type here would drop the whole line over one odd item.
|
|
30
|
+
content: z.unknown().nullish(),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const CONTENT_SCHEMA = z.union([z.string(), z.array(BLOCK_SCHEMA)])
|
|
34
|
+
// `id` is the assistant *message* the line belongs to; Claude Code writes one line per content block,
|
|
35
|
+
// so a turn that issued two calls is several lines carrying one id.
|
|
36
|
+
const MESSAGE_SCHEMA = z.object({ id: z.string().nullish(), content: CONTENT_SCHEMA.nullish() })
|
|
37
|
+
|
|
38
|
+
const LINE_SCHEMA = z.object({
|
|
39
|
+
type: z.string().nullish(),
|
|
40
|
+
timestamp: z.string().nullish(),
|
|
41
|
+
gitBranch: z.string().nullish(),
|
|
42
|
+
// The two fields outside `message` the harness writes an end-of-task notice on. `unknown`, since a
|
|
43
|
+
// string here would reject every line whose `content` is a list of blocks.
|
|
44
|
+
content: z.unknown().nullish(),
|
|
45
|
+
attachment: z.unknown().nullish(),
|
|
46
|
+
message: MESSAGE_SCHEMA.nullish(),
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
type TranscriptBlock = z.infer<typeof BLOCK_SCHEMA>
|
|
50
|
+
type TranscriptContent = z.infer<typeof CONTENT_SCHEMA>
|
|
51
|
+
type TranscriptMessage = z.infer<typeof MESSAGE_SCHEMA>
|
|
52
|
+
type TranscriptRecord = z.infer<typeof LINE_SCHEMA>
|
|
53
|
+
type ToolCallBlock = TranscriptBlock & { name: string }
|
|
54
|
+
|
|
55
|
+
function read(value: unknown): TranscriptRecord | undefined {
|
|
56
|
+
return LINE_SCHEMA.safeParse(value).data
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// A blank line, a line that is not JSON and a line of another shape are one answer: `undefined`.
|
|
60
|
+
function parse(line: string): TranscriptRecord | undefined {
|
|
61
|
+
return read(json_value.parse_or_undefined(line))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The line's blocks. A message written as a bare string — a prompt — carries none.
|
|
65
|
+
function blocks_of(record: TranscriptRecord): ReadonlyArray<TranscriptBlock> {
|
|
66
|
+
const content = record.message?.content
|
|
67
|
+
|
|
68
|
+
return Array.isArray(content) ? content : []
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function is_tool_call(block: TranscriptBlock): block is ToolCallBlock {
|
|
72
|
+
return block.type === TOOL_USE_TYPE && typeof block.name === 'string'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The calls a line made, in order. A `tool_use` block without a name is not a call anything can name.
|
|
76
|
+
function tool_calls_of(record: TranscriptRecord): Array<ToolCallBlock> {
|
|
77
|
+
return blocks_of(record).filter((block) => is_tool_call(block))
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const transcript_record = {
|
|
81
|
+
TEXT_TYPE,
|
|
82
|
+
TOOL_USE_TYPE,
|
|
83
|
+
TOOL_RESULT_TYPE,
|
|
84
|
+
read,
|
|
85
|
+
parse,
|
|
86
|
+
blocks_of,
|
|
87
|
+
tool_calls_of,
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type { TranscriptBlock, TranscriptContent, TranscriptMessage, TranscriptRecord }
|
|
91
|
+
export { transcript_record }
|