@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,91 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
4
|
+
import { issue_comment_cli, type CommentRequest } from '#scripts/issue/issue-comment-cli'
|
|
5
|
+
import { NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
6
|
+
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
7
|
+
import { issue_park } from '#scripts/issue/issue-park'
|
|
8
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
9
|
+
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
10
|
+
import { run_park } from './run-park'
|
|
11
|
+
|
|
12
|
+
// `josh run:park <N> --body-file <path>` — park a lane child for a person's decision in one call: the
|
|
13
|
+
// question as a comment, `needs-decision`, and the local record the `lane-park` guard reads.
|
|
14
|
+
// `josh run:park <N> --clear` takes the park back off once the decision is recorded.
|
|
15
|
+
//
|
|
16
|
+
// **The park was two hand-typed commands, and a child could stop after either one**
|
|
17
|
+
// (joshuafolkken/kit#4132). One call writes both, and only a park that has both is recorded, so the
|
|
18
|
+
// guard falls silent on exactly the child that left a question behind.
|
|
19
|
+
//
|
|
20
|
+
// **`in-progress` and the hold are not this command's.** A parked child keeps `in-progress`, and every
|
|
21
|
+
// parked ending still owes `pnpm josh run:release <N>` (`backlogrun-park.md` → "park and continue").
|
|
22
|
+
|
|
23
|
+
const SUCCESS_EXIT_CODE = 0
|
|
24
|
+
const FAILURE_EXIT_CODE = 1
|
|
25
|
+
const ARGV_OFFSET = 2
|
|
26
|
+
const CLEAR_FLAG = '--clear'
|
|
27
|
+
const USAGE = `Usage: josh run:park <issue-number> --body-file <path> | <issue-number> ${CLEAR_FLAG}`
|
|
28
|
+
const CLEAR_OPTIONS = { clear: { type: 'boolean' } } as const
|
|
29
|
+
|
|
30
|
+
function clear_issue(argv: ReadonlyArray<string>): string | undefined {
|
|
31
|
+
const parsed = cli_flags.arguments_of(argv, CLEAR_OPTIONS)
|
|
32
|
+
|
|
33
|
+
if (parsed === undefined) return undefined
|
|
34
|
+
|
|
35
|
+
return issue_number_shape.single_of(parsed.positionals)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function park(request: CommentRequest, directory: string): Promise<number> {
|
|
39
|
+
const { issue_number, body } = request
|
|
40
|
+
const write = await issue_park.apply(issue_number, NEEDS_DECISION_LABEL, body)
|
|
41
|
+
const is_parked = write.is_labelled && write.is_commented
|
|
42
|
+
const is_recorded = is_parked && run_park.record(issue_number, directory)
|
|
43
|
+
|
|
44
|
+
console.info(
|
|
45
|
+
`park ${session_cite.issue(issue_number)} — label: ${String(write.is_labelled)} · comment: ${String(write.is_commented)} · recorded: ${String(is_recorded)}`,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return is_parked ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// **The record goes whatever the label answers**: the decision is a person's and already made, so a
|
|
52
|
+
// guard reading a stale park would only stay silent on the child's next stop.
|
|
53
|
+
async function clear(issue_number: string, directory: string): Promise<number> {
|
|
54
|
+
run_park.clear(issue_number, directory)
|
|
55
|
+
const is_cleared = await git_gh_issue_write.issue_clear_label(issue_number, NEEDS_DECISION_LABEL)
|
|
56
|
+
|
|
57
|
+
console.info(`park ${session_cite.issue(issue_number)} — cleared: ${String(is_cleared)}`)
|
|
58
|
+
|
|
59
|
+
return is_cleared ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function run_clear(argv: ReadonlyArray<string>, directory: string): Promise<number> {
|
|
63
|
+
const issue_number = clear_issue(argv)
|
|
64
|
+
|
|
65
|
+
if (issue_number !== undefined) return await clear(issue_number, directory)
|
|
66
|
+
|
|
67
|
+
console.error(USAGE)
|
|
68
|
+
|
|
69
|
+
return FAILURE_EXIT_CODE
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function run(
|
|
73
|
+
argv: ReadonlyArray<string>,
|
|
74
|
+
directory: string = process.cwd(),
|
|
75
|
+
): Promise<number> {
|
|
76
|
+
if (argv.includes(CLEAR_FLAG)) return await run_clear(argv, directory)
|
|
77
|
+
|
|
78
|
+
const request = issue_comment_cli.resolve_request(argv, USAGE)
|
|
79
|
+
|
|
80
|
+
return request === undefined ? FAILURE_EXIT_CODE : await park(request, directory)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
84
|
+
process.exitCode = await run(argv)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const run_park_cli = { USAGE, run }
|
|
88
|
+
|
|
89
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
90
|
+
|
|
91
|
+
export { run_park_cli }
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { backlog_budget } from '#scripts/backlog/backlog-budget'
|
|
2
|
+
import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
3
|
+
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
4
|
+
import { stamp_record, type StampRecordSpec } from '#scripts/josh/stamp-record'
|
|
5
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
6
|
+
import { z } from 'zod'
|
|
7
|
+
|
|
8
|
+
// The local record of a lane child's park — the half of `run:park` a `PreToolUse` guard can read.
|
|
9
|
+
//
|
|
10
|
+
// **The park itself is a GitHub label, which a synchronous guard cannot read**, so `lane-park` used to
|
|
11
|
+
// fire on every lane-child stop, parked or not (joshuafolkken/kit#4132). `run:park` writes this record
|
|
12
|
+
// once the comment and the label are both on the issue, and the guard reads it back synchronously, the
|
|
13
|
+
// way the pre-gate cut guard reads `run-cut.ts`'s record.
|
|
14
|
+
//
|
|
15
|
+
// **Keyed to the repository and the issue, not the work tree.** The child parks from its lane, and the
|
|
16
|
+
// parent clears the park from the main checkout once a person has decided; both resolve the same
|
|
17
|
+
// common git directory, so `run:park --clear` removes the record wherever it runs.
|
|
18
|
+
//
|
|
19
|
+
// **Bounded like the cut record, and taken back by the next dispatch.** The guard asks within the run
|
|
20
|
+
// that parked, seconds after the park; a label a person removed by hand, without `--clear`, must not
|
|
21
|
+
// leave the guard silent on that issue's next dispatch, so `lane:dispatch` clears the record before it
|
|
22
|
+
// starts the child, and a record past the lane child's idle bound reads as no park.
|
|
23
|
+
|
|
24
|
+
const PARK_PREFIX = 'josh-run-park-'
|
|
25
|
+
const PARK_MAX_AGE_MS = backlog_budget.DEFAULT_IDLE_MS
|
|
26
|
+
|
|
27
|
+
const run_park_schema = z.object({
|
|
28
|
+
issue: z.string(),
|
|
29
|
+
parked_at: z.string(),
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
type RunPark = z.infer<typeof run_park_schema>
|
|
33
|
+
|
|
34
|
+
function parse_park(raw: string): RunPark | undefined {
|
|
35
|
+
return json_value.parse_with(raw, run_park_schema)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parked_at_of(park: RunPark): string {
|
|
39
|
+
return park.parked_at
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const PARK_SPEC: StampRecordSpec<RunPark> = {
|
|
43
|
+
parse: parse_park,
|
|
44
|
+
timestamp_of: parked_at_of,
|
|
45
|
+
max_age_ms: PARK_MAX_AGE_MS,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function park_path(repository: string, issue: string): string {
|
|
49
|
+
return stamp_file.stamp_path(`${PARK_PREFIX}${issue}-`, repository)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// **The directory is injectable so a test never writes the live record** — the same reason
|
|
53
|
+
// `run_cut.carried_cut_sync` takes one.
|
|
54
|
+
function record(issue: string, directory: string, now: Date = new Date()): boolean {
|
|
55
|
+
const repository = git_common_directory.repository(directory)
|
|
56
|
+
|
|
57
|
+
if (repository === undefined) return false
|
|
58
|
+
|
|
59
|
+
stamp_file.replace_stamp(park_path(repository, issue), { issue, parked_at: now.toISOString() })
|
|
60
|
+
|
|
61
|
+
return true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function clear(issue: string, directory: string): void {
|
|
65
|
+
const repository = git_common_directory.repository(directory)
|
|
66
|
+
|
|
67
|
+
if (repository !== undefined) stamp_file.remove_stamp(park_path(repository, issue))
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// **A fault reads as "not parked"**, the direction `carried_cut_sync` takes: the guard then speaks once,
|
|
71
|
+
// which a child answers by reissuing, rather than falling silent on a run that never parked.
|
|
72
|
+
function is_parked_sync(issue: string, directory: string, now: Date = new Date()): boolean {
|
|
73
|
+
const repository = git_common_directory.repository(directory)
|
|
74
|
+
|
|
75
|
+
if (repository === undefined) return false
|
|
76
|
+
|
|
77
|
+
const read = stamp_record.classify(
|
|
78
|
+
stamp_file.read_stamp_text(park_path(repository, issue)),
|
|
79
|
+
PARK_SPEC,
|
|
80
|
+
now,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return read.kind === 'carried' && read.record.issue === issue
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const run_park = { PARK_MAX_AGE_MS, clear, is_parked_sync, record }
|
|
87
|
+
|
|
88
|
+
export { run_park }
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
2
|
+
import { RUN_STALLED_LABEL } from '#scripts/issue/issue-labels'
|
|
3
|
+
|
|
4
|
+
// What a `run:stalled` park says, written and read in one place (joshuafolkken/kit#4215): the park
|
|
5
|
+
// event carries the cause's short name after the label, the park comment its whole `Why:`, and the
|
|
6
|
+
// park comments, `backlog:plan --waves` and `run:board` name the one next action.
|
|
7
|
+
|
|
8
|
+
// Why a child was parked: `short` rides on the park event and the board row, `why` on the comment.
|
|
9
|
+
interface StallCause {
|
|
10
|
+
short: string
|
|
11
|
+
why: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// What `run:merge` judged when it parks a child with no ship stop to name.
|
|
15
|
+
const SESSION_UNFINISHED: StallCause = {
|
|
16
|
+
short: 'session unfinished',
|
|
17
|
+
why: 'the child’s session ended with its issue still open and unfinished.',
|
|
18
|
+
}
|
|
19
|
+
const CUT_NOT_RELAUNCHED: StallCause = {
|
|
20
|
+
short: 'cut not relaunched',
|
|
21
|
+
why: 'its lane held a declared cut, but no successor could be relaunched from it (or it already was once).',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const RESUME_COMMAND = 'fullrun'
|
|
25
|
+
const CAUSE_LEAD = `${RUN_STALLED_LABEL}: `
|
|
26
|
+
const NEXT_ARROW = ' → '
|
|
27
|
+
|
|
28
|
+
function resume_of(child: number | string): string {
|
|
29
|
+
return `${RESUME_COMMAND} ${issue_cite.plain(child)}`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The next action as a clause, which a park comment's `Next:` and the plan's note end with.
|
|
33
|
+
function next_step(child: number | string): string {
|
|
34
|
+
return `fix the cause, then resume it with \`${resume_of(child)}\` or remove \`${RUN_STALLED_LABEL}\` to offer it again`
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function park_event(child: number | string, cause: string): string {
|
|
38
|
+
return `${issue_cite.plain(child)} parked (${CAUSE_LEAD}${cause})`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The cause a park event's reason carries: `''` for a bare `run:stalled` (written before the event
|
|
42
|
+
// carried one), `undefined` for a reason that is no `run:stalled` park.
|
|
43
|
+
function cause_of(reason: string): string | undefined {
|
|
44
|
+
if (reason === RUN_STALLED_LABEL) return ''
|
|
45
|
+
|
|
46
|
+
return reason.startsWith(CAUSE_LEAD) ? reason.slice(CAUSE_LEAD.length) : undefined
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// A stalled row's right end: its cause, then the action that resumes it — the action alone where no
|
|
50
|
+
// cause was recorded.
|
|
51
|
+
function row_text(child: number | string, cause = ''): string {
|
|
52
|
+
const resume = resume_of(child)
|
|
53
|
+
|
|
54
|
+
return cause === '' ? resume : `${cause}${NEXT_ARROW}${resume}`
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const run_stalled = {
|
|
58
|
+
CUT_NOT_RELAUNCHED,
|
|
59
|
+
SESSION_UNFINISHED,
|
|
60
|
+
cause_of,
|
|
61
|
+
next_step,
|
|
62
|
+
park_event,
|
|
63
|
+
resume_of,
|
|
64
|
+
row_text,
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { run_stalled }
|
|
68
|
+
export type { StallCause }
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
4
|
+
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
|
+
import { run_pause, type PauseRequest, type PauseResult, type StepReport } from './run-pause'
|
|
6
|
+
|
|
7
|
+
// `josh run:pause <M> --for <N>` — the argument parsing and the report around `run-pause.ts`. One
|
|
8
|
+
// line per step that landed; a failure names its step, what was already done, and the rerun that
|
|
9
|
+
// continues from there.
|
|
10
|
+
|
|
11
|
+
const SUCCESS_EXIT_CODE = 0
|
|
12
|
+
const FAILURE_EXIT_CODE = 1
|
|
13
|
+
const ARGV_OFFSET = 2
|
|
14
|
+
const USAGE = 'Usage: josh run:pause <issue> --for <prerequisite>'
|
|
15
|
+
const OPTIONS = { for: { type: 'string' } } as const
|
|
16
|
+
|
|
17
|
+
// The prerequisite has to be another issue: `#M` blocked by itself is no order at all.
|
|
18
|
+
function prerequisite_of(value: string | undefined, issue: string): string | undefined {
|
|
19
|
+
if (value === undefined || value === issue) return undefined
|
|
20
|
+
|
|
21
|
+
return issue_number_shape.is_issue_number(value) ? value : undefined
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parse_request(argv: ReadonlyArray<string>): PauseRequest | undefined {
|
|
25
|
+
const parsed = cli_flags.arguments_of(argv, OPTIONS)
|
|
26
|
+
if (parsed === undefined) return undefined
|
|
27
|
+
const issue = issue_number_shape.single_of(parsed.positionals)
|
|
28
|
+
const prerequisite = issue === undefined ? undefined : prerequisite_of(parsed.values.for, issue)
|
|
29
|
+
|
|
30
|
+
return issue === undefined || prerequisite === undefined ? undefined : { issue, prerequisite }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function report_done(done: ReadonlyArray<StepReport>): void {
|
|
34
|
+
for (const { step, detail } of done) console.info(`${step}: ${detail}`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function report_failure(request: PauseRequest, result: PauseResult & { kind: 'failed' }): void {
|
|
38
|
+
const steps = result.done.map(({ step }) => step).join(', ')
|
|
39
|
+
|
|
40
|
+
console.error(`✖ ${result.step} failed: ${result.reason}`)
|
|
41
|
+
console.error(`Done: ${steps.length === 0 ? 'nothing' : steps}.`)
|
|
42
|
+
console.error(
|
|
43
|
+
`Rerun \`pnpm josh run:pause ${request.issue} --for ${request.prerequisite}\` to continue from ${result.step}.`,
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
48
|
+
const request = parse_request(argv)
|
|
49
|
+
|
|
50
|
+
if (request === undefined) {
|
|
51
|
+
console.error(USAGE)
|
|
52
|
+
|
|
53
|
+
return FAILURE_EXIT_CODE
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const result = await run_pause.pause(request)
|
|
57
|
+
|
|
58
|
+
report_done(result.done)
|
|
59
|
+
if (result.kind === 'paused') return SUCCESS_EXIT_CODE
|
|
60
|
+
report_failure(request, result)
|
|
61
|
+
|
|
62
|
+
return FAILURE_EXIT_CODE
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
66
|
+
process.exitCode = await run(argv)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const run_pause_cli = { USAGE, run }
|
|
70
|
+
|
|
71
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
72
|
+
|
|
73
|
+
export { run_pause_cli }
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { epic_add } from '#scripts/epic/epic-add'
|
|
2
|
+
import { epic_bundle_gaps } from '#scripts/epic/epic-bundle-gaps'
|
|
3
|
+
import { epic_index } from '#scripts/epic/epic-index'
|
|
4
|
+
import { epic_reconcile } from '#scripts/epic/epic-reconcile'
|
|
5
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
6
|
+
import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
|
|
7
|
+
import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
|
|
8
|
+
import { git_stash } from '#scripts/git/stash/git-stash'
|
|
9
|
+
import { stash_push_cli } from '#scripts/git/stash/stash-push-cli'
|
|
10
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
11
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
12
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
13
|
+
import { run_hold_cli } from '#scripts/run/hold/run-hold-cli'
|
|
14
|
+
import { z } from 'zod'
|
|
15
|
+
|
|
16
|
+
// `josh run:pause <M> --for <N>` — set a run aside while its prerequisite `#N` lands first
|
|
17
|
+
// (`prerequisite.md`): the work in progress stashed under a fixed name, a comment on `#M` naming the
|
|
18
|
+
// pop, `#M` blocked by `#N` and the hold released, in that order.
|
|
19
|
+
//
|
|
20
|
+
// **Every step asks whether it is already done before it acts**, so a rerun after a failure carries on
|
|
21
|
+
// from the step that failed rather than stashing, commenting or recording twice. The state lives where
|
|
22
|
+
// each write lands — the stash stack, the Issue's comments and its `blocked_by` relations — so no
|
|
23
|
+
// record of its own is kept. Each write is the existing command's implementation, not a copy of it.
|
|
24
|
+
|
|
25
|
+
// `epic:bundle`'s own listing limit, so both commands see the same epics.
|
|
26
|
+
const EPIC_LIMIT = 200
|
|
27
|
+
const SUCCESS_EXIT_CODE = 0
|
|
28
|
+
const ALREADY = 'already'
|
|
29
|
+
const comment_schema = z.object({ body: z.string().nullish() })
|
|
30
|
+
|
|
31
|
+
interface PauseRequest {
|
|
32
|
+
issue: string
|
|
33
|
+
prerequisite: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type StepName = 'stash' | 'comment' | 'blocked-by' | 'release'
|
|
37
|
+
|
|
38
|
+
interface StepReport {
|
|
39
|
+
step: StepName
|
|
40
|
+
detail: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type PauseResult =
|
|
44
|
+
| { kind: 'paused'; done: ReadonlyArray<StepReport> }
|
|
45
|
+
| { kind: 'failed'; step: StepName; reason: string; done: ReadonlyArray<StepReport> }
|
|
46
|
+
|
|
47
|
+
function stash_message(request: PauseRequest): string {
|
|
48
|
+
return `run:pause: ${issue_cite.plain(request.issue)} waits on ${issue_cite.plain(request.prerequisite)}`
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function comment_marker(request: PauseRequest): string {
|
|
52
|
+
return `<!-- josh:run-pause ${issue_cite.plain(request.issue)} for ${issue_cite.plain(request.prerequisite)} -->`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function is_stashed(request: PauseRequest): Promise<boolean> {
|
|
56
|
+
return git_stash.select(await git_stash.list(), stash_message(request)).kind !== 'none'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function stash_step(request: PauseRequest): Promise<string> {
|
|
60
|
+
if (await is_stashed(request)) return ALREADY
|
|
61
|
+
|
|
62
|
+
return await stash_push_cli.set_aside({ message: stash_message(request), dir: undefined })
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function pause_comment(request: PauseRequest, is_work_stashed: boolean): string {
|
|
66
|
+
const work = is_work_stashed
|
|
67
|
+
? `- The work in progress was stashed. After \`pnpm josh ms\`, recover it with \`pnpm josh stash:pop "${stash_message(request)}"\` (expect conflicts).`
|
|
68
|
+
: '- The tree held no uncommitted work, so nothing was stashed.'
|
|
69
|
+
|
|
70
|
+
return [
|
|
71
|
+
`Paused: ${issue_cite.plain(request.prerequisite)} has to land first.`,
|
|
72
|
+
work,
|
|
73
|
+
comment_marker(request),
|
|
74
|
+
].join('\n')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async function has_pause_comment(request: PauseRequest): Promise<boolean> {
|
|
78
|
+
const json = await git_gh_issue_read.issue_list_comments(request.issue)
|
|
79
|
+
const rows = json === undefined ? undefined : parse_json_array_or_undefined(json, comment_schema)
|
|
80
|
+
|
|
81
|
+
if (rows === undefined) {
|
|
82
|
+
throw new Error(`the comments on ${session_cite.issue(request.issue)} could not be read`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return rows.some((row) => row.body?.includes(comment_marker(request)) === true)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function comment_step(request: PauseRequest): Promise<string> {
|
|
89
|
+
if (await has_pause_comment(request)) return ALREADY
|
|
90
|
+
|
|
91
|
+
const body = pause_comment(request, await is_stashed(request))
|
|
92
|
+
|
|
93
|
+
return await git_gh_issue_write.issue_comment(request.issue, body)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function is_blocked(request: PauseRequest): Promise<boolean> {
|
|
97
|
+
const blockers = await git_gh_issue_read.issue_blocked_by_numbers(request.issue)
|
|
98
|
+
|
|
99
|
+
return blockers.includes(Number(request.prerequisite))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface Tracking {
|
|
103
|
+
epic: number
|
|
104
|
+
// Whether the same epic already tracks the prerequisite as a row of its own.
|
|
105
|
+
is_prerequisite_child: boolean
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Every epic listing the child, not the one `build_epic_index` keeps: a child a second epic also
|
|
109
|
+
// lists is still a row of this one.
|
|
110
|
+
function is_listed_by(
|
|
111
|
+
epics: ReadonlyArray<{ number: number; body: string }>,
|
|
112
|
+
child: string,
|
|
113
|
+
epic: number,
|
|
114
|
+
): boolean {
|
|
115
|
+
return epic_index.build_tracking_index(epics).get(Number(child))?.includes(epic) === true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// A listing cut short is no answer about absence: an epic past the cut tracks `#M` invisibly, and a
|
|
119
|
+
// direct relation written then leaves that epic recording an order its body never declares.
|
|
120
|
+
async function tracking_epic(request: PauseRequest): Promise<Tracking | undefined> {
|
|
121
|
+
const fetched = await epic_index.fetch_epics(EPIC_LIMIT)
|
|
122
|
+
if (fetched === undefined) throw new Error('the open epics could not be read')
|
|
123
|
+
const index = epic_index.build_epic_index(fetched.epics)
|
|
124
|
+
const epic = index.get(Number(request.issue))
|
|
125
|
+
|
|
126
|
+
if (epic === undefined && !epic_bundle_gaps.is_membership_established(fetched.cutoff)) {
|
|
127
|
+
throw new Error('the open epics were not read in full, so an epic tracking it may be unseen')
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (epic === undefined) return undefined
|
|
131
|
+
|
|
132
|
+
return { epic, is_prerequisite_child: is_listed_by(fetched.epics, request.prerequisite, epic) }
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function add_to_epic(epic: number, request: PauseRequest): Promise<void> {
|
|
136
|
+
const code = await epic_add.add_children({
|
|
137
|
+
epic_number: epic,
|
|
138
|
+
children: [Number(request.prerequisite)],
|
|
139
|
+
position: { kind: 'before', target: Number(request.issue) },
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
if (code !== SUCCESS_EXIT_CODE) {
|
|
143
|
+
throw new Error(`\`epic --add\` into ${session_cite.issue(epic)} failed`)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async function record_relation(request: PauseRequest): Promise<void> {
|
|
148
|
+
if (await git_gh_issue_write.issue_add_blocked_by(request.issue, request.prerequisite)) return
|
|
149
|
+
|
|
150
|
+
throw new Error('the blocked-by relation was not recorded')
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async function refuse_unreconcilable(epic: number, request: PauseRequest): Promise<void> {
|
|
154
|
+
const link = { blocker: Number(request.prerequisite), blocked: Number(request.issue) }
|
|
155
|
+
const refusal = await epic_reconcile.refusal_after(epic, link)
|
|
156
|
+
if (refusal === undefined) return
|
|
157
|
+
|
|
158
|
+
throw new Error(
|
|
159
|
+
`\`pnpm josh epic --reconcile ${String(epic)}\` would refuse the relation, so none was recorded: ${refusal}`,
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async function reconcile_epic(epic: number): Promise<void> {
|
|
164
|
+
if ((await epic_reconcile.reconcile_epic(epic)) === SUCCESS_EXIT_CODE) return
|
|
165
|
+
|
|
166
|
+
throw new Error(
|
|
167
|
+
`the relation was recorded, but \`pnpm josh epic --reconcile ${String(epic)}\` failed to declare it`,
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// A prerequisite outside the epic gains its row, declaration and relation from `epic --add --before`.
|
|
172
|
+
// One the epic already tracks does not: `epic --add` reads it as a move and drops every order it
|
|
173
|
+
// already had, where a pause only adds one — so the relation is recorded directly and
|
|
174
|
+
// `epic --reconcile` copies it into the declaration beside the others, once a dry plan shows the
|
|
175
|
+
// reconcile accepts it: a refusal after the write would leave the relation undeclared. `epic --add`
|
|
176
|
+
// exits 0 on a relation it failed to post, so the relation is read back after the insertion.
|
|
177
|
+
async function record_in_epic(tracking: Tracking, request: PauseRequest): Promise<string> {
|
|
178
|
+
if (tracking.is_prerequisite_child) {
|
|
179
|
+
await refuse_unreconcilable(tracking.epic, request)
|
|
180
|
+
await record_relation(request)
|
|
181
|
+
await reconcile_epic(tracking.epic)
|
|
182
|
+
} else {
|
|
183
|
+
await add_to_epic(tracking.epic, request)
|
|
184
|
+
if (!(await is_blocked(request))) await record_relation(request)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return `recorded in epic ${session_cite.issue(tracking.epic)}`
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// A relation recorded inside an epic tracking both issues is only done once it is declared, so a
|
|
191
|
+
// rerun past a failed reconcile reconciles again — a no-op on an epic that already declares it.
|
|
192
|
+
async function settle_recorded(request: PauseRequest): Promise<string> {
|
|
193
|
+
const tracking = await tracking_epic(request)
|
|
194
|
+
if (tracking?.is_prerequisite_child === true) await reconcile_epic(tracking.epic)
|
|
195
|
+
|
|
196
|
+
return ALREADY
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function blocked_by_step(request: PauseRequest): Promise<string> {
|
|
200
|
+
if (await is_blocked(request)) return await settle_recorded(request)
|
|
201
|
+
|
|
202
|
+
const tracking = await tracking_epic(request)
|
|
203
|
+
if (tracking !== undefined) return await record_in_epic(tracking, request)
|
|
204
|
+
await record_relation(request)
|
|
205
|
+
|
|
206
|
+
return 'recorded'
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Releasing a free record is a success, so a rerun past this step answers `released` again.
|
|
210
|
+
async function release_step(request: PauseRequest): Promise<string> {
|
|
211
|
+
const code = await run_hold_cli.run(['--release', request.issue])
|
|
212
|
+
if (code !== SUCCESS_EXIT_CODE) throw new Error('`run:release` refused')
|
|
213
|
+
|
|
214
|
+
return 'released'
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const STEPS: ReadonlyArray<[StepName, (request: PauseRequest) => Promise<string>]> = [
|
|
218
|
+
['stash', stash_step],
|
|
219
|
+
['comment', comment_step],
|
|
220
|
+
['blocked-by', blocked_by_step],
|
|
221
|
+
['release', release_step],
|
|
222
|
+
]
|
|
223
|
+
|
|
224
|
+
async function attempt(
|
|
225
|
+
act: (request: PauseRequest) => Promise<string>,
|
|
226
|
+
request: PauseRequest,
|
|
227
|
+
): Promise<{ detail: string } | { reason: string }> {
|
|
228
|
+
try {
|
|
229
|
+
return { detail: await act(request) }
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return { reason: error_text.message_of(error) }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async function pause(request: PauseRequest): Promise<PauseResult> {
|
|
236
|
+
const done: Array<StepReport> = []
|
|
237
|
+
|
|
238
|
+
for (const [step, act] of STEPS) {
|
|
239
|
+
// eslint-disable-next-line no-await-in-loop -- each step runs only once the one before it landed
|
|
240
|
+
const outcome = await attempt(act, request)
|
|
241
|
+
if ('reason' in outcome) return { kind: 'failed', step, reason: outcome.reason, done }
|
|
242
|
+
done.push({ step, detail: outcome.detail })
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return { kind: 'paused', done }
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const run_pause = { pause }
|
|
249
|
+
|
|
250
|
+
export type { PauseRequest, PauseResult, StepReport }
|
|
251
|
+
export { run_pause }
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
1
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
2
|
import { backlog_arrival, type ArrivalProbe } from '#scripts/backlog/backlog-arrival'
|
|
5
3
|
import { backlog_ready } from '#scripts/backlog/backlog-ready'
|
|
6
4
|
import { gh_spawn } from '#scripts/gh/gh-spawn'
|
|
7
5
|
import { lane_child_marker } from '#scripts/lane/lane-child-marker'
|
|
8
6
|
import { error_text } from '#scripts/lib/error-message'
|
|
7
|
+
import { MS_PER_SECOND } from '#scripts/lib/timeouts'
|
|
9
8
|
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
10
9
|
import { run_progress, type ProgressState } from './run-progress'
|
|
11
10
|
import { run_progress_args, type ParsedValues } from './run-progress-args'
|
|
@@ -34,7 +33,6 @@ import { run_progress_read, type ObservationRead } from './run-progress-read'
|
|
|
34
33
|
|
|
35
34
|
const SUCCESS_EXIT_CODE = 0
|
|
36
35
|
const FAILURE_EXIT_CODE = 1
|
|
37
|
-
const ARGV_OFFSET = 2
|
|
38
36
|
// How often the loop wakes to look at the clock — not how often it reports. It is short relative to
|
|
39
37
|
// the interval so that a `--mark` written by the run is noticed promptly, and long enough that a
|
|
40
38
|
// watcher left running overnight costs nothing measurable.
|
|
@@ -78,7 +76,7 @@ const WAIT_EXPIRED_NOTICE = `The watch bound (\`--hours\`, ${String(DEFAULT_WAIT
|
|
|
78
76
|
// one: a `gh` call that hangs would otherwise block the synchronous read at startup and leave the
|
|
79
77
|
// watcher neither running nor saying so.
|
|
80
78
|
const REPO_LOOKUP_TIMEOUT_SECONDS = 10
|
|
81
|
-
const REPO_LOOKUP_TIMEOUT_MS = REPO_LOOKUP_TIMEOUT_SECONDS *
|
|
79
|
+
const REPO_LOOKUP_TIMEOUT_MS = REPO_LOOKUP_TIMEOUT_SECONDS * MS_PER_SECOND
|
|
82
80
|
// A lookup that timed out or failed is not an argument the caller got wrong, so it is told apart from
|
|
83
81
|
// the usage error — read as one, it would send a person to fix arguments that were correct.
|
|
84
82
|
const REPO_UNRESOLVED_NOTICE = `The repository could not be resolved (\`gh\` did not answer within ${String(REPO_LOOKUP_TIMEOUT_SECONDS)}s or failed), so the progress watcher did not start. Pass \`--repo <owner/repo>\` and start it again.`
|
|
@@ -215,7 +213,7 @@ async function emit(options: WatchOptions, context: EmitContext): Promise<EmitRe
|
|
|
215
213
|
function decline(loop: WatchLoop, now_ms: number, notice: string): WatchLoop {
|
|
216
214
|
if (loop.said !== notice) console.error(notice)
|
|
217
215
|
|
|
218
|
-
const cooldown_ms = DECLINE_RETRY_SECONDS *
|
|
216
|
+
const cooldown_ms = DECLINE_RETRY_SECONDS * MS_PER_SECOND
|
|
219
217
|
|
|
220
218
|
return { ...loop, retry_at_ms: now_ms + cooldown_ms, said: notice }
|
|
221
219
|
}
|
|
@@ -442,7 +440,7 @@ function to_options(values: ParsedValues): WatchOptions | undefined {
|
|
|
442
440
|
max_ms: run_progress_args.to_max_ms(values.hours, values.wait === true),
|
|
443
441
|
output_paths: values.output ?? [],
|
|
444
442
|
repo,
|
|
445
|
-
tick_ms: TICK_SECONDS *
|
|
443
|
+
tick_ms: TICK_SECONDS * MS_PER_SECOND,
|
|
446
444
|
}
|
|
447
445
|
}
|
|
448
446
|
|
|
@@ -480,10 +478,6 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
480
478
|
return await run_watch(values)
|
|
481
479
|
}
|
|
482
480
|
|
|
483
|
-
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
484
|
-
process.exitCode = await run(argv)
|
|
485
|
-
}
|
|
486
|
-
|
|
487
481
|
const run_progress_cli = {
|
|
488
482
|
DECLINE_RETRY_SECONDS,
|
|
489
483
|
DEFAULT_WAIT_MAX_HOURS,
|
|
@@ -503,7 +497,5 @@ const run_progress_cli = {
|
|
|
503
497
|
wait_once,
|
|
504
498
|
}
|
|
505
499
|
|
|
506
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
507
|
-
|
|
508
500
|
export type { WatchLoop, WatchOptions }
|
|
509
501
|
export { run_progress_cli }
|
|
@@ -2,6 +2,7 @@ import { git_common_directory } from '#scripts/git/git-common-directory'
|
|
|
2
2
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
3
3
|
import { error_text } from '#scripts/lib/error-message'
|
|
4
4
|
import { json_value } from '#scripts/lib/json-value'
|
|
5
|
+
import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
|
|
5
6
|
import { z } from 'zod'
|
|
6
7
|
|
|
7
8
|
// The report clock `josh run:progress` keeps, in the one form both of its readers can use.
|
|
@@ -48,7 +49,6 @@ const LOG_SUFFIX = '.log'
|
|
|
48
49
|
// A few hours of heartbeats at the twenty-minute interval — enough to read the run's recent shape, and
|
|
49
50
|
// bounded so an unattended run cannot grow the file without limit.
|
|
50
51
|
const LOG_KEEP = 12
|
|
51
|
-
const MS_PER_MINUTE = 60_000
|
|
52
52
|
// Longer than any heartbeat interval and shorter than any gap between two runs. Heartbeats land at most
|
|
53
53
|
// one interval apart while a run is live (twenty minutes by default, well under this), so a newest block
|
|
54
54
|
// older than this belongs to a previous run: past it the log is reset rather than extended, and a fresh
|