@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
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
epic_child_schema,
|
|
4
|
+
epic_issue_schema,
|
|
5
|
+
type EpicChildData,
|
|
6
|
+
type EpicIssueData,
|
|
7
|
+
} from '#scripts/git/git-schemas'
|
|
3
8
|
import { cutoff_cause, cutoff_of, type ScanCutoff } from '#scripts/git/listing-cutoff'
|
|
4
9
|
import {
|
|
5
10
|
parse_json_array_or_undefined,
|
|
@@ -37,6 +42,7 @@ interface EpicIssue {
|
|
|
37
42
|
children: Array<number>
|
|
38
43
|
external_children: Array<ExternalChild>
|
|
39
44
|
has_declared_order: boolean
|
|
45
|
+
is_reopened: boolean
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
interface SiblingState {
|
|
@@ -44,8 +50,12 @@ interface SiblingState {
|
|
|
44
50
|
has_blocked_by: boolean
|
|
45
51
|
}
|
|
46
52
|
|
|
47
|
-
|
|
53
|
+
// GitHub's `state_reason` for an open issue that was closed once and reopened.
|
|
54
|
+
const REOPENED = 'reopened'
|
|
55
|
+
|
|
56
|
+
function to_epic_issue(raw: EpicIssueData): EpicIssue {
|
|
48
57
|
return {
|
|
58
|
+
is_reopened: raw.stateReason === REOPENED,
|
|
49
59
|
number: raw.number,
|
|
50
60
|
children: epic_parse.parse_task_list_issue_numbers(raw.body),
|
|
51
61
|
external_children: epic_parse.parse_external_task_list_children(raw.body),
|
|
@@ -98,30 +108,32 @@ function to_sibling_state(raw_json: string | undefined): SiblingState {
|
|
|
98
108
|
}
|
|
99
109
|
}
|
|
100
110
|
|
|
101
|
-
|
|
102
|
-
return to_sibling_state(await git_gh_command.issue_get_state_and_relations(String(sibling), repo))
|
|
103
|
-
}
|
|
111
|
+
type ChildRead = SiblingState & { is_readable: boolean }
|
|
104
112
|
|
|
105
|
-
// A
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
// A same-repository child carries no `repo`; a cross-repository one names it.
|
|
114
|
+
type ChildReference = Omit<ExternalChild, 'repo'> & { repo?: string | undefined }
|
|
115
|
+
|
|
116
|
+
// A child read by number, naming its repository in the REST path when it lives in another one.
|
|
117
|
+
// `is_readable` is what decides whether the epic may close at all: closing while a child's state is
|
|
118
|
+
// unknown is exactly what the refusal prevents. A failed read is told apart from an open child
|
|
119
|
+
// rather than read as one, which left a finished epic open with nothing in the output (#4560). A
|
|
120
|
+
// read whose answer carries no state is a failed read too.
|
|
121
|
+
async function inspect_child(child: ChildReference): Promise<ChildRead> {
|
|
111
122
|
const raw = await git_gh_command.issue_get_state_and_relations(String(child.number), child.repo)
|
|
112
123
|
|
|
113
|
-
return { ...to_sibling_state(raw), is_readable: raw !== undefined }
|
|
124
|
+
return { ...to_sibling_state(raw), is_readable: parse_child(raw)?.state !== undefined }
|
|
114
125
|
}
|
|
115
126
|
|
|
116
127
|
// The merged Issue is excluded rather than queried: GitHub applies `closes #N` asynchronously, so
|
|
117
128
|
// reading its state immediately after the merge races with that propagation.
|
|
118
|
-
async function
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
)
|
|
122
|
-
const siblings = epic.children.filter((child) => child !== merged_number)
|
|
129
|
+
async function inspect_children(epic: EpicIssue, merged_number: number): Promise<Array<ChildRead>> {
|
|
130
|
+
const siblings: Array<ChildReference> = epic.children
|
|
131
|
+
.filter((child) => child !== merged_number)
|
|
132
|
+
.map((number) => ({ number }))
|
|
123
133
|
|
|
124
|
-
return await Promise.all(
|
|
134
|
+
return await Promise.all(
|
|
135
|
+
[...siblings, ...epic.external_children].map(async (child) => await inspect_child(child)),
|
|
136
|
+
)
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
// `pnpm josh epic --ordered` and `--add` record the declared chain themselves, through the REST
|
|
@@ -165,9 +177,8 @@ const CASCADE_DEPTH_NOTE = `⚠️ Epic auto-close cascade reached its ${String
|
|
|
165
177
|
|
|
166
178
|
// **An unreadable comment listing does not stop the close.** It is announced and closed exactly as
|
|
167
179
|
// it was before the duplicate check existed, because refusing here would strand the epic: nothing
|
|
168
|
-
// re-triggers the auto-close
|
|
169
|
-
//
|
|
170
|
-
// would leave a finished epic open until somebody noticed.
|
|
180
|
+
// re-triggers the auto-close until some later child close sweeps the open epics, and that close may
|
|
181
|
+
// never come. One rate-limited read would leave a finished epic open until somebody noticed.
|
|
171
182
|
//
|
|
172
183
|
// The direction is chosen on what each mistake costs, and they are not symmetric. Announcing twice
|
|
173
184
|
// costs one redundant comment and nothing else, because the epic *closes* — which is what ends a loop
|
|
@@ -209,38 +220,26 @@ async function close_epic(epic: EpicIssue): Promise<boolean> {
|
|
|
209
220
|
return await close_epic_with(epic_number, comment)
|
|
210
221
|
}
|
|
211
222
|
|
|
212
|
-
// The
|
|
213
|
-
//
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
): Promise<{ states: Array<SiblingState>; is_complete: boolean }> {
|
|
217
|
-
if (epic.external_children.length === 0) return { states: [], is_complete: true }
|
|
218
|
-
const results = await Promise.all(
|
|
219
|
-
epic.external_children.map(async (child) => await inspect_external(child)),
|
|
220
|
-
)
|
|
223
|
+
// The manual-close request is made only when every child that was read is closed: while one is still
|
|
224
|
+
// open the batch is unfinished anyway, and asking for a manual close would invite closing it early.
|
|
225
|
+
function warn_when_unread_blocks_close(epic: EpicIssue, states: ReadonlyArray<ChildRead>): void {
|
|
226
|
+
if (states.some((state) => state.is_readable && !state.is_closed)) return
|
|
221
227
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
has_blocked_by: result.has_blocked_by,
|
|
226
|
-
})),
|
|
227
|
-
is_complete: results.every((result) => result.is_readable),
|
|
228
|
-
}
|
|
228
|
+
console.info(
|
|
229
|
+
`⚠️ Epic ${session_cite.issue(epic.number)} has a child whose state could not be read; ${CLOSE_MANUALLY}`,
|
|
230
|
+
)
|
|
229
231
|
}
|
|
230
232
|
|
|
233
|
+
// An epic with a child whose state is unknown is left open for manual closing, and says so.
|
|
231
234
|
async function close_epic_when_complete(epic: EpicIssue, merged_number: number): Promise<boolean> {
|
|
232
|
-
const
|
|
235
|
+
const states = await inspect_children(epic, merged_number)
|
|
233
236
|
|
|
234
|
-
if (!
|
|
235
|
-
|
|
236
|
-
`ℹ️ Epic ${session_cite.issue(epic.number)} has a child in another repository whose state could not be read; ${CLOSE_MANUALLY}`,
|
|
237
|
-
)
|
|
237
|
+
if (states.some((state) => !state.is_readable)) {
|
|
238
|
+
warn_when_unread_blocks_close(epic, states)
|
|
238
239
|
|
|
239
240
|
return false
|
|
240
241
|
}
|
|
241
242
|
|
|
242
|
-
const states = [...(await inspect_siblings(epic, merged_number)), ...external.states]
|
|
243
|
-
|
|
244
243
|
warn_when_order_unrecorded(epic, states)
|
|
245
244
|
|
|
246
245
|
if (states.some((state) => !state.is_closed)) return false
|
|
@@ -315,22 +314,74 @@ async function close_next_level(
|
|
|
315
314
|
return next
|
|
316
315
|
}
|
|
317
316
|
|
|
318
|
-
// Breadth-first up the nesting:
|
|
319
|
-
//
|
|
320
|
-
async function
|
|
317
|
+
// Breadth-first up the nesting: each closed epic becomes the next level's completed child, so a
|
|
318
|
+
// fully-finished parent closes in the same pass. `false` when the depth cap stopped the walk.
|
|
319
|
+
async function cascade_from(
|
|
321
320
|
open_epics: ReadonlyArray<EpicIssue>,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
let frontier
|
|
321
|
+
start: ReadonlyArray<number>,
|
|
322
|
+
evaluated: Set<number>,
|
|
323
|
+
): Promise<boolean> {
|
|
324
|
+
let frontier = start
|
|
326
325
|
|
|
327
326
|
for (let depth = 0; depth < MAX_CASCADE_DEPTH; depth++) {
|
|
328
|
-
if (frontier.length === 0) return
|
|
327
|
+
if (frontier.length === 0) return true
|
|
329
328
|
// eslint-disable-next-line no-await-in-loop -- the cascade closes one level before reading the next
|
|
330
329
|
frontier = await close_next_level(open_epics, frontier, evaluated)
|
|
331
330
|
}
|
|
332
331
|
|
|
333
332
|
if (frontier.length > 0) console.info(CASCADE_DEPTH_NOTE)
|
|
333
|
+
|
|
334
|
+
return frontier.length === 0
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// An epic listing no child has nothing to be complete: with no state to read, the completion check
|
|
338
|
+
// would close it — a prose epic, or one whose task list is not written yet.
|
|
339
|
+
function tracks_children(epic: EpicIssue): boolean {
|
|
340
|
+
return epic.children.length + epic.external_children.length > 0
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Every open epic the cascade did not reach, closed when each child is: an epic whose last child
|
|
344
|
+
// closed outside every josh path — an `already-done` child `run:merge` parked and a person closed by
|
|
345
|
+
// hand (#4564) — is found by the next close of any child. An epic is marked evaluated only once it
|
|
346
|
+
// closes, so a parent read before its child epic closed here is evaluated again by that cascade.
|
|
347
|
+
//
|
|
348
|
+
// A reopened epic is left out: a person reopening a finished epic has said it is not done, and only
|
|
349
|
+
// a close of one of its own children — the cascade above — may close it again.
|
|
350
|
+
function is_sweep_target(epic: EpicIssue, evaluated: ReadonlySet<number>): boolean {
|
|
351
|
+
return !evaluated.has(epic.number) && !epic.is_reopened && tracks_children(epic)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async function sweep_unreached(
|
|
355
|
+
open_epics: ReadonlyArray<EpicIssue>,
|
|
356
|
+
merged_number: number,
|
|
357
|
+
evaluated: Set<number>,
|
|
358
|
+
): Promise<Array<number>> {
|
|
359
|
+
const closed: Array<number> = []
|
|
360
|
+
const unreached = open_epics.filter((epic) => is_sweep_target(epic, evaluated))
|
|
361
|
+
|
|
362
|
+
for (const epic of unreached) {
|
|
363
|
+
// eslint-disable-next-line no-await-in-loop -- a closed epic joins the evaluated set the cascade reads
|
|
364
|
+
if (await close_epic_isolated(epic, merged_number)) closed.push(epic.number)
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
for (const number of closed) evaluated.add(number)
|
|
368
|
+
|
|
369
|
+
return closed
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Level 0 closes the epics holding the merged issue; the sweep then closes any other finished epic.
|
|
373
|
+
// A cascade stopped at the depth cap asks for a manual close, so the sweep does not run past it.
|
|
374
|
+
async function cascade_close(
|
|
375
|
+
open_epics: ReadonlyArray<EpicIssue>,
|
|
376
|
+
merged_number: number,
|
|
377
|
+
): Promise<void> {
|
|
378
|
+
const evaluated = new Set<number>()
|
|
379
|
+
|
|
380
|
+
if (!(await cascade_from(open_epics, [merged_number], evaluated))) return
|
|
381
|
+
|
|
382
|
+
const swept = await sweep_unreached(open_epics, merged_number, evaluated)
|
|
383
|
+
|
|
384
|
+
await cascade_from(open_epics, swept, evaluated)
|
|
334
385
|
}
|
|
335
386
|
|
|
336
387
|
const UNREADABLE_EPIC_LIST_MESSAGE =
|
|
@@ -363,9 +414,15 @@ async function resolve_and_close_safely(merged_number: number): Promise<void> {
|
|
|
363
414
|
/**
|
|
364
415
|
* Close every open epic whose task list is fully complete once `issue_number` closed.
|
|
365
416
|
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
417
|
+
* **The one entry every child close goes through** (#4560): `followup` after its merge,
|
|
418
|
+
* `josh issue:measured` after its own close, and `run:merge` for every child it counts as merged —
|
|
419
|
+
* which also catches a merge GitHub left OPEN. Running it
|
|
420
|
+
* twice for one child is harmless: a closed epic is no longer in the open listing. Every other open
|
|
421
|
+
* epic is swept too, so one whose last child closed outside these paths closes here (#4564).
|
|
422
|
+
*
|
|
423
|
+
* Requires `is_merged` — the child is known closed: the linked Issue is treated as closed without
|
|
424
|
+
* being queried. On a `--no-merge` run that Issue is still open, so skipping this guard would close
|
|
425
|
+
* an epic whose batch is not finished.
|
|
369
426
|
*/
|
|
370
427
|
async function close_completed_epics(input: {
|
|
371
428
|
issue_number: string | undefined
|
|
@@ -2,6 +2,7 @@ import { repo_map_logic } from '#scripts/discovery/repo-map-logic'
|
|
|
2
2
|
import { repo_origin } from '#scripts/discovery/repo-origin'
|
|
3
3
|
import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
|
|
4
4
|
import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
5
|
+
import { json_value } from '#scripts/lib/json-value'
|
|
5
6
|
import { GH_API_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
6
7
|
import { propagate_publish } from '#scripts/propagate/propagate-publish'
|
|
7
8
|
import { derive_versions_endpoint } from '#scripts/version/version-command-config'
|
|
@@ -209,14 +210,10 @@ function to_answer(repo: string, fields: ManifestFields): ManifestAnswer {
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
function to_manifest(repo: string, stdout: string): ManifestAnswer {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (typeof parsed !== 'object' || parsed === null) return { kind: 'unreadable' }
|
|
213
|
+
const parsed = json_value.parse_or_undefined(stdout.trim())
|
|
214
|
+
if (typeof parsed !== 'object' || parsed === null) return { kind: 'unreadable' }
|
|
215
215
|
|
|
216
|
-
|
|
217
|
-
} catch {
|
|
218
|
-
return { kind: 'unreadable' }
|
|
219
|
-
}
|
|
216
|
+
return to_answer(repo, parsed)
|
|
220
217
|
}
|
|
221
218
|
|
|
222
219
|
// Why the read failed, asked only when it did. The status line is the protocol rather than prose, so
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
+
import { NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
3
|
+
import { issue_read } from '#scripts/issue/issue-read'
|
|
4
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
5
|
+
import { epic_decision } from './epic-decision'
|
|
6
|
+
import { epic_parse } from './epic-parse'
|
|
7
|
+
import { epic_read } from './epic-read'
|
|
8
|
+
import type { EpicSubject } from './epic-validate'
|
|
9
|
+
|
|
10
|
+
// `josh epic --decide <E> <N...> --decision-file <path|->` — record a decision about children the epic
|
|
11
|
+
// already tracks: the epic's `## Decisions` entry, a comment on each child, and each child's
|
|
12
|
+
// `needs-decision` label removed. The text is the caller's; placing it is this command's.
|
|
13
|
+
//
|
|
14
|
+
// **A rerun writes nothing twice.** The entry and each comment are looked for before they are
|
|
15
|
+
// written, so a run that stopped half way is finished by running it again.
|
|
16
|
+
|
|
17
|
+
const SUCCESS_EXIT_CODE = 0
|
|
18
|
+
const FAILURE_EXIT_CODE = 1
|
|
19
|
+
|
|
20
|
+
interface DecideInput {
|
|
21
|
+
epic_number: number
|
|
22
|
+
children: ReadonlyArray<number>
|
|
23
|
+
decision: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function format_list(numbers: ReadonlyArray<number>): string {
|
|
27
|
+
return numbers.map((issue_number) => session_cite.issue(issue_number)).join(', ')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// A child the epic does not track is refused before anything is written: placing it is `--add`'s,
|
|
31
|
+
// which records the same decision in the same call.
|
|
32
|
+
function untracked_error(epic_number: number, untracked: ReadonlyArray<number>): string {
|
|
33
|
+
return `${format_list(untracked)} not tracked by ${session_cite.issue(epic_number)}; place it with \`pnpm josh epic --add ${String(epic_number)} <N> --decision-file <path>\`. Nothing was written.`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// The epic the decision goes to, or why nothing is written: a record `append_decision` would refuse
|
|
37
|
+
// (checked before any read), an unreadable epic, or a child it does not track.
|
|
38
|
+
async function read_decision_target(input: DecideInput): Promise<EpicSubject | { error: string }> {
|
|
39
|
+
const record_error = epic_decision.find_decision_error(input.decision)
|
|
40
|
+
if (record_error !== undefined) return { error: record_error }
|
|
41
|
+
const subject = await epic_read.read_subject(input.epic_number)
|
|
42
|
+
|
|
43
|
+
if (subject === undefined) {
|
|
44
|
+
return { error: `Could not read issue ${session_cite.issue(input.epic_number)}.` }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const tracked = epic_parse.parse_task_list_issue_numbers(subject.body)
|
|
48
|
+
const untracked = input.children.filter((child) => !tracked.includes(child))
|
|
49
|
+
|
|
50
|
+
return untracked.length === 0 ? subject : { error: untracked_error(input.epic_number, untracked) }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function record_on_epic(subject: EpicSubject, decision: string): Promise<string> {
|
|
54
|
+
const epic = session_cite.issue(subject.number)
|
|
55
|
+
|
|
56
|
+
if (epic_decision.has_decision(subject.body, decision)) {
|
|
57
|
+
return `📝 ${epic} already records this decision.`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const body = epic_decision.append_decision(subject.body ?? '', decision)
|
|
61
|
+
|
|
62
|
+
await git_gh_command.issue_edit_body(String(subject.number), body)
|
|
63
|
+
|
|
64
|
+
return `📝 Decision recorded in ${epic}'s \`## Decisions\`.`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// `undefined` when the comments could not be read: posting then risks the duplicate this exists to
|
|
68
|
+
// prevent, so the child is reported as not recorded and a rerun finishes it.
|
|
69
|
+
async function has_comment(child: number, decision: string): Promise<boolean | undefined> {
|
|
70
|
+
const comments = await issue_read.parse_comments(
|
|
71
|
+
await git_gh_command.issue_list_comments(String(child)),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
return comments?.some((comment) => comment.body.trim() === decision.trim())
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// The label goes only once the child carries the record, so a failed comment leaves it parked.
|
|
78
|
+
async function record_on_child(child: number, decision: string): Promise<boolean> {
|
|
79
|
+
const has_record = await has_comment(child, decision)
|
|
80
|
+
if (has_record === undefined) return false
|
|
81
|
+
const is_commented =
|
|
82
|
+
has_record || (await git_gh_command.issue_try_comment(String(child), decision))
|
|
83
|
+
if (!is_commented) return false
|
|
84
|
+
|
|
85
|
+
return await git_gh_command.issue_clear_label(String(child), NEEDS_DECISION_LABEL)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function format_child_report(total: number, failures: number): string {
|
|
89
|
+
if (failures === 0) return epic_decision.format_decision_report({ total, failures })
|
|
90
|
+
|
|
91
|
+
return `⚠️ ${String(failures)} of ${String(total)} child issue(s) could not be given the comment or lose \`${NEEDS_DECISION_LABEL}\`; rerun the same command — nothing is written twice.`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function decide(input: DecideInput): Promise<number> {
|
|
95
|
+
const epic = await read_decision_target(input)
|
|
96
|
+
|
|
97
|
+
if ('error' in epic) {
|
|
98
|
+
console.error(`✖ ${epic.error}`)
|
|
99
|
+
|
|
100
|
+
return FAILURE_EXIT_CODE
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.info(await record_on_epic(epic, input.decision))
|
|
104
|
+
const recorded = await Promise.all(
|
|
105
|
+
input.children.map(async (child) => await record_on_child(child, input.decision)),
|
|
106
|
+
)
|
|
107
|
+
const failures = recorded.filter((is_recorded) => !is_recorded).length
|
|
108
|
+
|
|
109
|
+
console.info(format_child_report(input.children.length, failures))
|
|
110
|
+
|
|
111
|
+
return failures === 0 ? SUCCESS_EXIT_CODE : FAILURE_EXIT_CODE
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const epic_decide = {
|
|
115
|
+
decide,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export { epic_decide }
|
|
119
|
+
export type { DecideInput }
|
|
@@ -153,8 +153,17 @@ function read_recorded_reasons(body: string | undefined): string {
|
|
|
153
153
|
].join('\n')
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
+
// Whether `## Decisions` already carries this record, compared as `append_decision` writes it — so a
|
|
157
|
+
// rerun of `epic --decide` after a partial failure appends nothing a second time.
|
|
158
|
+
function has_decision(body: string | undefined, record: string): boolean {
|
|
159
|
+
if (body === undefined) return false
|
|
160
|
+
|
|
161
|
+
return read_section(body, DECISIONS_HEADING_PATTERN).includes(record.trimEnd())
|
|
162
|
+
}
|
|
163
|
+
|
|
156
164
|
const epic_decision = {
|
|
157
165
|
append_decision,
|
|
166
|
+
has_decision,
|
|
158
167
|
append_replacements,
|
|
159
168
|
read_recorded_reasons,
|
|
160
169
|
find_decision_error,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
2
|
import type { IssueReadFailure } from '#scripts/gh/git-gh-issue-read'
|
|
3
|
+
import { issue_sample_gate } from '#scripts/issue/issue-sample-gate'
|
|
3
4
|
import { epic_cross_repo } from './epic-cross-repo'
|
|
4
5
|
import type { EpicChild, IssueReference } from './epic-graph'
|
|
5
6
|
import { epic_issue, type EpicIssue } from './epic-issue'
|
|
@@ -21,6 +22,7 @@ function to_child(parsed: EpicIssue, repo: string): EpicChild {
|
|
|
21
22
|
state: epic_issue.normalize_state(parsed.state),
|
|
22
23
|
labels: epic_issue.label_names(parsed),
|
|
23
24
|
blocked_by: epic_issue.blocker_references_of(parsed, repo),
|
|
25
|
+
body: parsed.body,
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -132,6 +134,8 @@ async function fetch_child_read(
|
|
|
132
134
|
|
|
133
135
|
const parsed = epic_issue.parse_epic_issue(read.json)
|
|
134
136
|
|
|
137
|
+
await issue_sample_gate.prime([parsed?.body])
|
|
138
|
+
|
|
135
139
|
return { child: parsed === undefined ? undefined : to_child(parsed, repo), is_unreachable: false }
|
|
136
140
|
}
|
|
137
141
|
|
|
@@ -29,6 +29,8 @@ interface EpicChild {
|
|
|
29
29
|
state: 'OPEN' | 'CLOSED'
|
|
30
30
|
labels: ReadonlyArray<string>
|
|
31
31
|
blocked_by: ReadonlyArray<IssueReference>
|
|
32
|
+
// Read only to hold a child until its declared start time; absent on rows built without a read.
|
|
33
|
+
body?: string | undefined
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
// What is wrong with the graph. Both stop the run — neither is something to pick a winner for.
|
|
@@ -2,6 +2,7 @@ import { git_gh_issue_rest } from '#scripts/gh/git-gh-issue-rest'
|
|
|
2
2
|
import { blocked_by_schema } from '#scripts/git/git-schemas'
|
|
3
3
|
import { parse_json_object_or_undefined } from '#scripts/git/parse-json-array'
|
|
4
4
|
import { z } from 'zod'
|
|
5
|
+
import { REPOSITORY_SEGMENT_SOURCE } from './epic-parse'
|
|
5
6
|
import type { IssueReference } from './epic-reference'
|
|
6
7
|
|
|
7
8
|
// The shapes one issue is read as, and the argument every epic command takes.
|
|
@@ -116,7 +117,10 @@ interface EpicReference {
|
|
|
116
117
|
number: number
|
|
117
118
|
}
|
|
118
119
|
|
|
119
|
-
const QUALIFIED_REFERENCE =
|
|
120
|
+
const QUALIFIED_REFERENCE = new RegExp(
|
|
121
|
+
String.raw`^(${REPOSITORY_SEGMENT_SOURCE}\/${REPOSITORY_SEGMENT_SOURCE})#(\d+)$`,
|
|
122
|
+
'u',
|
|
123
|
+
)
|
|
120
124
|
const QUALIFIED_REPO_GROUP = 1
|
|
121
125
|
const QUALIFIED_NUMBER_GROUP = 2
|
|
122
126
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
|
|
2
2
|
import { git_gh_exec } from '#scripts/gh/git-gh-exec'
|
|
3
3
|
import { IN_PROGRESS_LABEL } from '#scripts/issue/issue-labels'
|
|
4
|
+
import { MS_PER_MINUTE } from '#scripts/lib/timeouts'
|
|
4
5
|
|
|
5
6
|
// How long each lane holder has carried `in-progress`. The stale-label rule
|
|
6
7
|
// in `backlogrun-progress.md` is applied by age, and until this read the age was a hand-written
|
|
@@ -12,7 +13,6 @@ import { IN_PROGRESS_LABEL } from '#scripts/issue/issue-labels'
|
|
|
12
13
|
|
|
13
14
|
// Matches the `Stale \`in-progress\`` row of the table in `backlogrun-progress.md`.
|
|
14
15
|
const STALE_MINUTES = 90
|
|
15
|
-
const MS_PER_MINUTE = 60_000
|
|
16
16
|
const TIMELINE_PAGE = 100
|
|
17
17
|
|
|
18
18
|
const LABELED_FILTER = `.[] | select(.event == "labeled" and (.label.name | ascii_downcase) == "${IN_PROGRESS_LABEL}") | .created_at`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { lane_capacity } from '#scripts/lane/lane-capacity'
|
|
2
|
+
import { lane_snapshot_trace } from '#scripts/lane/lane-snapshot-trace'
|
|
2
3
|
import { epic_busy, type BusyRead } from './epic-busy'
|
|
3
4
|
import {
|
|
4
5
|
epic_candidate_confirm,
|
|
@@ -39,11 +40,13 @@ interface RepoPool {
|
|
|
39
40
|
|
|
40
41
|
// What is being asked of one repository. `is_all_lanes` is the caller's appetite rather than the
|
|
41
42
|
// repository's capacity: `epic:next --repo` prints a single token unless `--lanes` was passed, so a
|
|
42
|
-
// caller written against the one-child contract keeps getting exactly one child.
|
|
43
|
+
// caller written against the one-child contract keeps getting exactly one child. `is_this_checkout`
|
|
44
|
+
// says whether `repo` is the repository this command runs in, whose ship records are the ones read.
|
|
43
45
|
interface LaneRequest {
|
|
44
46
|
repo: string
|
|
45
47
|
limit: number
|
|
46
48
|
is_all_lanes: boolean
|
|
49
|
+
is_this_checkout: boolean
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
// The answer for one repository: the children to start, the verdict standing in their place when
|
|
@@ -62,8 +65,27 @@ function is_held(read: BusyRead): boolean {
|
|
|
62
65
|
return read.kind === 'unreadable' || read.kind === 'truncated'
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
function free_lanes(read: BusyRead, limit: number): number {
|
|
66
|
-
|
|
68
|
+
function free_lanes(read: BusyRead, limit: number, merge_waiting: number): number {
|
|
69
|
+
if (is_held(read)) return NO_LANES
|
|
70
|
+
|
|
71
|
+
const holders = epic_busy.occupied_lanes(read)
|
|
72
|
+
|
|
73
|
+
// A merge-waiting holder frees its place under the limit but keeps its port seat
|
|
74
|
+
// (`lane_capacity.free_lanes`).
|
|
75
|
+
return lane_capacity.free_lanes(limit, holders - merge_waiting, holders)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// **A holder whose detached ship waits on its merge holds no lane** — the count `backlog:drive` makes
|
|
79
|
+
// for the pool (`backlog-occupied.ts`), so a named epic's lanes are offered the place too
|
|
80
|
+
// (joshuafolkken/kit#4466). It keeps `in-progress` until the merge. The ship records read are this
|
|
81
|
+
// checkout's, so a `--repo` naming another repository is discounted nothing: its holder numbers
|
|
82
|
+
// would be matched against this repository's unrelated ships.
|
|
83
|
+
async function merge_waiting_holders(read: BusyRead, request: LaneRequest): Promise<number> {
|
|
84
|
+
if (read.kind !== 'busy' || !request.is_this_checkout) return NO_LANES
|
|
85
|
+
|
|
86
|
+
return await lane_snapshot_trace.count_merge_waiting(
|
|
87
|
+
read.issues.map((issue) => String(issue.number)),
|
|
88
|
+
)
|
|
67
89
|
}
|
|
68
90
|
|
|
69
91
|
function wanted_of(request: LaneRequest, free: number): number {
|
|
@@ -247,7 +269,7 @@ async function offer_for_repo(
|
|
|
247
269
|
|
|
248
270
|
if (notice !== undefined) console.error(notice)
|
|
249
271
|
|
|
250
|
-
const free = free_lanes(read, request.limit)
|
|
272
|
+
const free = free_lanes(read, request.limit, await merge_waiting_holders(read, request))
|
|
251
273
|
const ages = await holder_ages(read, request.repo)
|
|
252
274
|
|
|
253
275
|
if (free === NO_LANES) {
|
|
@@ -263,9 +285,22 @@ async function offer_for_repo(
|
|
|
263
285
|
return solo_offer(await collect(for_repo, wanted_of(request, free)), read, request, ages)
|
|
264
286
|
}
|
|
265
287
|
|
|
288
|
+
// A `--repo` compared against the repository this command runs in, case-insensitively as GitHub
|
|
289
|
+
// names it.
|
|
290
|
+
function lane_request(
|
|
291
|
+
asked: Pick<LaneRequest, 'repo' | 'is_all_lanes'>,
|
|
292
|
+
limit: number,
|
|
293
|
+
current_repo: string,
|
|
294
|
+
): LaneRequest {
|
|
295
|
+
const is_this_checkout = asked.repo.toLowerCase() === current_repo.toLowerCase()
|
|
296
|
+
|
|
297
|
+
return { ...asked, limit, is_this_checkout }
|
|
298
|
+
}
|
|
299
|
+
|
|
266
300
|
const epic_lane_offer = {
|
|
267
301
|
combine_verdicts,
|
|
268
302
|
dedupe_pools,
|
|
303
|
+
lane_request,
|
|
269
304
|
offer_for_repo,
|
|
270
305
|
}
|
|
271
306
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { josh_environment_file } from '#scripts/josh/josh-environment-file'
|
|
4
|
+
import { epic_next } from './epic-next'
|
|
5
|
+
|
|
6
|
+
// The `josh epic:next` entry, kept apart from `epic-next.ts` because other modules import that one: a
|
|
7
|
+
// bundle is one file, so a main guard there would fire for every command that carries it
|
|
8
|
+
// (joshuafolkken/kit#4186).
|
|
9
|
+
//
|
|
10
|
+
// `.env` is read here rather than through the dispatcher's `tsx_arguments`: declaring any would
|
|
11
|
+
// disqualify this command from in-process dispatch, and an unattended `epicrun` asks it every sixty
|
|
12
|
+
// seconds for the whole life of a run (`josh-environment-file.ts` records the measurement). Inside the
|
|
13
|
+
// guard, so a developer's own `.env` cannot decide what the unit tests see.
|
|
14
|
+
//
|
|
15
|
+
// `process.exitCode` rather than `process.exit()`, for the reason `scripts/cost-runtime/cost-main.ts`
|
|
16
|
+
// records: the answer goes to standard output and a write to a pipe is asynchronous on macOS, so
|
|
17
|
+
// exiting can tear the process down before it drains. This command's contract is
|
|
18
|
+
// `answer=$(pnpm josh epic:next <E>)`, which is exactly that pipe.
|
|
19
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
20
|
+
const ARGV_OFFSET = 2
|
|
21
|
+
|
|
22
|
+
josh_environment_file.load_environment_file()
|
|
23
|
+
process.exitCode = await epic_next.run(process.argv.slice(ARGV_OFFSET))
|
|
24
|
+
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
import { fileURLToPath } from 'node:url'
|
|
3
1
|
import { repo_discovery } from '#scripts/discovery/repo-discovery'
|
|
4
2
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
5
3
|
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
6
|
-
import { josh_environment_file } from '#scripts/josh/josh-environment-file'
|
|
7
4
|
import { lane_capacity } from '#scripts/lane/lane-capacity'
|
|
8
5
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
9
6
|
import { issue_citation } from '#scripts/rules/issue-citation'
|
|
@@ -31,7 +28,6 @@ import { epic_report, type EpicNextResult } from './epic-report'
|
|
|
31
28
|
|
|
32
29
|
const SUCCESS_EXIT_CODE = 0
|
|
33
30
|
const FAILURE_EXIT_CODE = 1
|
|
34
|
-
const ARGV_OFFSET = 2
|
|
35
31
|
// Asking for every free lane (`--lanes`) is opt-in, so the answer stays one token for a caller that
|
|
36
32
|
// has not been changed. `--repo` alone prints exactly one number.
|
|
37
33
|
const OPTIONS = { repo: { type: 'string' }, lanes: { type: 'boolean' } } as const
|
|
@@ -351,11 +347,13 @@ async function report_epics(
|
|
|
351
347
|
const choice = await lane_capacity.lane_limit()
|
|
352
348
|
if (choice.kind === 'problem') return refuse(choice.problem)
|
|
353
349
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
350
|
+
const request = epic_lane_offer.lane_request(
|
|
351
|
+
{ repo: options.repo, is_all_lanes: options.is_all_lanes ?? false },
|
|
352
|
+
choice.limit,
|
|
357
353
|
current_repo,
|
|
358
354
|
)
|
|
355
|
+
|
|
356
|
+
return await report(views, request, current_repo)
|
|
359
357
|
}
|
|
360
358
|
|
|
361
359
|
// One view per named epic, classified against one shared registry read. `running` is every named
|
|
@@ -416,14 +414,6 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
416
414
|
return await run_epics(options)
|
|
417
415
|
}
|
|
418
416
|
|
|
419
|
-
// `process.exitCode` rather than `process.exit()`, for the reason `scripts/cost-runtime/cost-cli.ts` records:
|
|
420
|
-
// the answer goes to standard output and a write to a pipe is asynchronous on macOS, so exiting can
|
|
421
|
-
// tear the process down before it drains. This command's contract is `answer=$(pnpm josh epic:next
|
|
422
|
-
// <E>)`, which is exactly that pipe.
|
|
423
|
-
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
424
|
-
process.exitCode = await run(argv)
|
|
425
|
-
}
|
|
426
|
-
|
|
427
417
|
const epic_next = {
|
|
428
418
|
EXTERNAL_NOTICE,
|
|
429
419
|
FOREIGN_EPIC,
|
|
@@ -433,19 +423,11 @@ const epic_next = {
|
|
|
433
423
|
parse_options,
|
|
434
424
|
refuse_reads,
|
|
435
425
|
views_of,
|
|
426
|
+
run,
|
|
436
427
|
run_epics,
|
|
437
428
|
decide,
|
|
438
429
|
report,
|
|
439
430
|
}
|
|
440
431
|
|
|
441
|
-
// `.env` is read here rather than through the dispatcher's `tsx_arguments`: declaring any would
|
|
442
|
-
// disqualify this command from in-process dispatch, and an unattended `epicrun` asks it every sixty
|
|
443
|
-
// seconds for the whole life of a run (`josh-environment-file.ts` records the measurement). Inside the guard
|
|
444
|
-
// rather than in `main`, so a developer's own `.env` cannot decide what the unit tests see.
|
|
445
|
-
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
446
|
-
josh_environment_file.load_environment_file()
|
|
447
|
-
await main(process.argv.slice(ARGV_OFFSET))
|
|
448
|
-
}
|
|
449
|
-
|
|
450
432
|
export type { NextOptions }
|
|
451
433
|
export { epic_next }
|