@joshuafolkken/kit 1.1035.0 → 1.1094.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/settings.json +9 -8
- package/.claude/skills/epic-commands/SKILL.md +5 -7
- package/.claude/skills/verify-ui/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/SKILL.md +21 -13
- package/.claude/skills/workflow-commands/background-commands.md +5 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -3
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +9 -7
- package/.claude/skills/workflow-commands/backlogrun-park.md +6 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -37
- package/.claude/skills/workflow-commands/backlogrun-steps.md +25 -25
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +6 -4
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +3 -3
- package/.claude/skills/workflow-commands/followup.md +7 -3
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/fullrun.md +3 -2
- package/.claude/skills/workflow-commands/halfrun.md +16 -19
- package/.claude/skills/workflow-commands/issue-comments.md +2 -2
- package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
- package/.claude/skills/workflow-commands/issue-scout.md +1 -1
- package/.claude/skills/workflow-commands/kickoff.md +9 -4
- package/.claude/skills/workflow-commands/latest-gate.md +1 -1
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +44 -89
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -36
- package/.claude/skills/workflow-commands/prerequisite.md +1 -1
- package/.claude/skills/workflow-commands/prrun.md +36 -0
- package/.claude/skills/workflow-commands/retrospective.md +1 -1
- package/.claude/skills/workflow-commands/working-tree-hold.md +24 -4
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +21 -0
- package/.github/workflows/ci.yml +26 -128
- package/.github/workflows/pr-classification.yml +5 -41
- package/.github/workflows/publish.yml +42 -48
- package/.github/workflows/sonar-qube.yml +37 -4
- package/AGENTS.md +12 -2
- package/CLAUDE.md +15 -16
- package/GEMINI.md +14 -2
- package/README.md +59 -18
- package/SECURITY.md +36 -6
- package/cspell/index.yaml +2 -1
- package/dist/CLAUDE.md +15 -16
- package/dist/config-merge/index.js +15 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-Y27M6A7X.js → chunk-3C4YCCEF.js} +5 -13
- package/dist/hooks/{chunk-D67KVGGY.js → chunk-7ZPFAVR7.js} +17 -88
- package/dist/hooks/{chunk-HOYJU5RM.js → chunk-E54KGFEQ.js} +11 -4
- package/dist/hooks/{chunk-KG6PZD72.js → chunk-IL27YTPH.js} +2 -2
- package/dist/hooks/{chunk-GJT4BNVE.js → chunk-KHWHKJOM.js} +3 -3
- package/dist/hooks/{chunk-HU66PWWL.js → chunk-M2XDCUKD.js} +1076 -509
- package/dist/hooks/{chunk-GLBDBJOK.js → chunk-NKOG3XAV.js} +199 -304
- package/dist/hooks/{chunk-ZXNE6NY3.js → chunk-O4LL4HTI.js} +2 -7
- package/dist/hooks/{chunk-XPLP27WA.js → chunk-OIZUHPJI.js} +5 -27
- package/dist/hooks/{chunk-EIFCAJRB.js → chunk-UD24EAIL.js} +2546 -1636
- package/dist/hooks/codex-hook-adapter.js +10 -11
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +15 -34
- package/dist/hooks/inputs.json +279 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +23 -16
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +188 -509
- package/dist/josh.js +166 -225
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +412 -64
- package/eslint/rules/promise.js +5 -0
- package/package.json +13 -8
- package/prompts/collaboration-workflow/file-edits.md +6 -53
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/operating-rules.md +4 -4
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +4 -4
- package/prompts/collaboration-workflow/rule-delivery.md +5 -36
- package/prompts/collaboration-workflow/shell-body.md +7 -9
- package/prompts/collaboration-workflow/turn-batching.md +21 -37
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +36 -36
- package/prompts/collaboration-workflow.md +5 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +12 -4
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +2 -2
- package/scripts/adopt/adopt.ts +0 -2
- package/scripts/agent/agent-argv.ts +0 -2
- package/scripts/agent/agent-diagnostics.ts +1 -1
- package/scripts/agent/agent-role-profile.ts +0 -7
- package/scripts/agent/claude-agent-argv.ts +0 -2
- package/scripts/agent/codex-agent-argv.ts +1 -1
- package/scripts/agent/codex-hooks.ts +92 -0
- package/scripts/agent/interactive-ask.ts +1 -1
- package/scripts/auto-ok/auto-ok-cli.ts +15 -25
- package/scripts/backlog/backlog-budget.ts +0 -2
- package/scripts/backlog/backlog-defect-priority.ts +2 -2
- package/scripts/backlog/backlog-drive-cli.ts +10 -8
- package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
- package/scripts/backlog/backlog-drive-named.ts +2 -1
- package/scripts/backlog/backlog-drive.ts +76 -16
- package/scripts/backlog/backlog-named.ts +0 -3
- package/scripts/backlog/backlog-next.ts +32 -22
- package/scripts/backlog/backlog-offer-cli.ts +0 -5
- package/scripts/backlog/backlog-plan-cli.ts +6 -8
- package/scripts/backlog/backlog-plan.ts +1 -1
- package/scripts/backlog/backlog-pool.ts +34 -17
- package/scripts/backlog/backlog-rank.ts +106 -0
- package/scripts/backlog/backlog-ready.ts +19 -3
- package/scripts/backlog/backlog-scope.ts +1 -3
- package/scripts/backlog/backlog-stalled-detect.ts +2 -2
- package/scripts/backlog/backlog-stalled.ts +0 -1
- package/scripts/backlog/backlog-waves.ts +47 -31
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +92 -11
- package/scripts/build/hook-bundle-stamp.ts +111 -0
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +1 -1
- package/scripts/ci/composite-actions.ts +30 -0
- package/scripts/ci/pr-classification.ts +3 -3
- package/scripts/claude/workflow-destination.ts +10 -1
- package/scripts/clone/clone-fingerprint.ts +0 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/json-format.ts +0 -1
- package/scripts/config-merge/patch-yaml-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +2 -9
- package/scripts/cost-runtime/cost-attribute.ts +0 -1
- package/scripts/cost-runtime/cost-cli.ts +0 -3
- package/scripts/cost-runtime/cost-corpus.ts +0 -2
- package/scripts/cost-runtime/cost-format.ts +0 -3
- package/scripts/cost-runtime/cost-pricing.ts +0 -1
- package/scripts/cost-runtime/cost-tokens.ts +0 -1
- package/scripts/delegation/delegation-cli.ts +1 -1
- package/scripts/delegation/delegation-policy.ts +11 -1
- package/scripts/delegation/duplicate-read-guard.ts +0 -8
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +0 -2
- package/scripts/delegation/investigation-reads.ts +1 -164
- package/scripts/discovery/repo-map-logic.ts +0 -1
- package/scripts/discovery/repo-party-cli.ts +1 -1
- package/scripts/doctor/doctor-consumer.ts +4 -6
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/document-byte-budget.ts +8 -9
- package/scripts/document/document-byte-check.ts +0 -1
- package/scripts/document/document-read-cli.ts +0 -2
- package/scripts/document/document-section-cli.ts +1 -1
- package/scripts/document/document-section.ts +0 -3
- package/scripts/document/edit-files-cli.ts +0 -1
- package/scripts/document/entry-read-budget.ts +13 -4
- package/scripts/document/lane-child-read-set.ts +1 -6
- package/scripts/document/read-files-cli.ts +0 -4
- package/scripts/document/read-set-cli.ts +0 -2
- package/scripts/document/read-set-point-of-use.ts +1 -0
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +1 -1
- package/scripts/epic/epic-add.ts +1 -1
- package/scripts/epic/epic-audit-cli.ts +1 -4
- package/scripts/epic/epic-audit-orphans.ts +1 -3
- package/scripts/epic/epic-audit-rationale.ts +0 -1
- package/scripts/epic/epic-audit-report.ts +0 -2
- package/scripts/epic/epic-audit.ts +5 -4
- package/scripts/epic/epic-bundle-cli.ts +1 -1
- package/scripts/epic/epic-bundle-evidence.ts +0 -1
- package/scripts/epic/epic-bundle-referenced.ts +1 -5
- package/scripts/epic/epic-bundle.ts +0 -4
- package/scripts/epic/epic-busy.ts +4 -5
- package/scripts/epic/epic-candidate-confirm.ts +0 -5
- package/scripts/epic/epic-classify.ts +2 -2
- package/scripts/epic/epic-cli-argv.ts +0 -1
- package/scripts/epic/epic-close-comment.ts +1 -1
- package/scripts/epic/epic-close.ts +5 -2
- package/scripts/epic/epic-cross-repo.ts +2 -4
- package/scripts/epic/epic-decision.ts +0 -1
- package/scripts/epic/epic-fetch.ts +2 -2
- package/scripts/epic/epic-index.ts +2 -3
- package/scripts/epic/epic-issue.ts +1 -15
- package/scripts/epic/epic-lane-offer.ts +20 -30
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +1 -3
- package/scripts/epic/epic-next-views.ts +0 -1
- package/scripts/epic/epic-next.ts +1 -10
- package/scripts/epic/epic-parse.ts +0 -1
- package/scripts/epic/epic-promote.ts +0 -9
- package/scripts/epic/epic-rank.ts +37 -0
- package/scripts/epic/epic-read.ts +1 -2
- package/scripts/epic/epic-reconcile.ts +1 -1
- package/scripts/epic/epic-reference.ts +1 -13
- package/scripts/epic/epic-relation-recheck.ts +1 -1
- package/scripts/epic/epic-relations.ts +1 -1
- package/scripts/epic/epic-remove.ts +1 -1
- package/scripts/epic/epic-report.ts +0 -1
- package/scripts/epic/epic-run.ts +2 -3
- package/scripts/epic/epic-shape.ts +1 -1
- package/scripts/epic/epic-solo-stale.ts +107 -0
- package/scripts/epic/epic-solo.ts +32 -30
- package/scripts/epic/epic-triage.ts +1 -1
- package/scripts/epic/epic-validate.ts +1 -1
- package/scripts/epic/epic.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +53 -0
- package/scripts/{git → followup}/followup-issue-number.ts +1 -6
- package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
- package/scripts/{git → followup}/git-followup-finish.ts +1 -3
- package/scripts/{git → followup}/git-followup-flush.ts +2 -2
- package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
- package/scripts/{git → followup}/git-followup-label.ts +4 -4
- package/scripts/followup/git-followup-merged.ts +112 -0
- package/scripts/{git → followup}/git-followup-pending.ts +1 -1
- package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
- package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
- package/scripts/{git → followup}/git-pr-followup.ts +53 -16
- package/scripts/gate/core-budget.ts +3 -9
- package/scripts/gate/gate-plan.ts +7 -4
- package/scripts/gate/gate-report.ts +0 -6
- package/scripts/gate/gate-tree.ts +1 -1
- package/scripts/gate/pre-commit-type-check.ts +0 -6
- package/scripts/gate/project-checks.ts +7 -8
- package/scripts/gate/scoped-green.ts +0 -1
- package/scripts/gate/type-check-step.ts +1 -1
- package/scripts/gate/verification-gate.ts +0 -2
- package/scripts/gh/fix-gh-packages.ts +15 -12
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
- package/scripts/{git → gh}/git-gh-check.ts +2 -1
- package/scripts/{git → gh}/git-gh-exec.ts +1 -1
- package/scripts/{git → gh}/git-gh-failure.ts +1 -1
- package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
- package/scripts/{git → gh}/git-gh-issue-list.ts +2 -0
- package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
- package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
- package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
- package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
- package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
- package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
- package/scripts/{git → gh}/git-gh-pr.ts +3 -1
- package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
- package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
- package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
- package/scripts/{git → gh}/git-pr-checks.ts +2 -1
- package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
- package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
- package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
- package/scripts/{git → gh}/git-pr.ts +3 -3
- package/scripts/git/changed-file-scope.ts +0 -1
- package/scripts/git/git-branch.ts +3 -6
- package/scripts/git/git-command.ts +1 -1
- package/scripts/git/git-commit.ts +1 -1
- package/scripts/git/git-common-directory.ts +80 -24
- package/scripts/git/git-error.ts +66 -9
- package/scripts/git/git-execa-error.ts +6 -1
- package/scripts/git/git-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +24 -6
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push-transport.ts +12 -69
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn.ts +79 -3
- package/scripts/git/git-ssh-keepalive.ts +74 -0
- package/scripts/git/git-staging.ts +1 -0
- package/scripts/git/git-status.ts +1 -1
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/gone-branch.ts +4 -2
- package/scripts/git/listing-cutoff.ts +1 -1
- package/scripts/git/main-merge.ts +1 -1
- package/scripts/git/main-sync.ts +19 -1
- package/scripts/git/parse-json-array.ts +0 -3
- package/scripts/git/repository-lock.ts +16 -16
- package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
- package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +1 -1
- package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
- package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
- package/scripts/hooks/codex-hook-adapter.ts +0 -1
- package/scripts/hooks/edited-cspell.ts +1 -1
- package/scripts/hooks/format-edited-cli.ts +15 -0
- package/scripts/hooks/format-edited-file.ts +4 -9
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard-cli.ts +21 -0
- package/scripts/hooks/pretool-guard.ts +36 -19
- package/scripts/hooks/reserved-run.ts +1 -1
- package/scripts/hooks/step-zero-notice.ts +76 -0
- package/scripts/hooks/stop-guard.ts +47 -21
- package/scripts/init/claude-plugin-config.ts +4 -5
- package/scripts/init/hook-command-rewrite.ts +16 -8
- package/scripts/init/hook-launch.ts +41 -15
- package/scripts/init/init-basic.ts +2 -5
- package/scripts/init/init-logic.ts +7 -0
- package/scripts/init/init.ts +0 -3
- package/scripts/init/project-profile.ts +6 -11
- package/scripts/init/start-exec.ts +8 -2
- package/scripts/init/start-plan.ts +18 -5
- package/scripts/init/start-setup-pr.ts +52 -25
- package/scripts/init/start-steps.ts +42 -9
- package/scripts/init/start.ts +40 -10
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +3 -3
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +37 -8
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +19 -3
- package/scripts/issue/issue-classification.ts +1 -9
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +2 -2
- package/scripts/issue/issue-file-cli.ts +5 -5
- package/scripts/issue/issue-file.ts +2 -2
- package/scripts/issue/issue-fold-cli.ts +1 -1
- package/scripts/issue/issue-fold-existing-cli.ts +1 -1
- package/scripts/{git → issue}/issue-labels.ts +20 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/issue/issue-rank.ts +89 -0
- package/scripts/issue/issue-read-cli.ts +8 -47
- package/scripts/issue/issue-read.ts +0 -2
- package/scripts/issue/issue-report-failures.ts +80 -0
- package/scripts/issue/issue-scout-cli.ts +1 -7
- package/scripts/issue/issue-scout-closed.ts +2 -2
- package/scripts/issue/issue-scout.ts +0 -2
- package/scripts/issue/issue-state-cli.ts +5 -46
- package/scripts/issue/issue-state.ts +1 -5
- package/scripts/issue/markdown-section.ts +1 -1
- package/scripts/issue/measure-rerun-cli.ts +1 -1
- package/scripts/issue/reproduction-measure.ts +1 -1
- package/scripts/josh/cli-body.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +0 -3
- package/scripts/josh/josh-command-map.ts +2 -102
- package/scripts/josh/josh-commands-ai.ts +9 -102
- package/scripts/josh/josh-commands-backlog.ts +5 -1
- package/scripts/josh/josh-commands-development.ts +10 -3
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/josh/josh-commands-maintenance.ts +7 -0
- package/scripts/josh/josh-commands-project.ts +7 -1
- package/scripts/josh/josh-commands-run.ts +114 -0
- package/scripts/josh/josh-commands-versioning.ts +8 -0
- package/scripts/josh/josh-commands-workflow.ts +2 -2
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +3 -6
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-child-marker.ts +16 -2
- package/scripts/lane/lane-cli.ts +33 -18
- package/scripts/lane/lane-close.ts +1 -3
- package/scripts/lane/lane-dispatch.ts +3 -4
- package/scripts/lane/lane-environment.ts +0 -9
- package/scripts/lane/lane-handoff.ts +38 -0
- package/scripts/lane/lane-launch-cli.ts +21 -11
- package/scripts/lane/lane-open.ts +0 -3
- package/scripts/lane/lane-output.ts +0 -1
- package/scripts/lane/lane-registry.ts +9 -0
- package/scripts/lane/lane-report.ts +10 -4
- package/scripts/lane/openai-lane-ship.ts +2 -0
- package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
- package/scripts/lane/openai-lane-supervisor.ts +6 -4
- package/scripts/lane/openai-review-broker.ts +3 -0
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/json-value.ts +5 -4
- package/scripts/lib/poll.ts +3 -1
- package/scripts/lib/timed-fetch.ts +15 -0
- package/scripts/lib/timeouts.ts +13 -0
- package/scripts/{yaml → lib}/yaml-document.ts +3 -1
- package/scripts/{bytes → lines}/bytes-command.ts +0 -2
- package/scripts/lines/lines-command.ts +0 -1
- package/scripts/lint/lint-related-scope.ts +0 -1
- package/scripts/lint/lint-related.ts +1 -1
- package/scripts/{git → notify}/telegram-notify.ts +2 -2
- package/scripts/{git → notify}/telegram-test.ts +4 -4
- package/scripts/observations/observation-ledger-home.ts +0 -1
- package/scripts/observations/observation-ledger-line.ts +0 -1
- package/scripts/observations/observation-ledger-migrate.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +3 -3
- package/scripts/observations/observations-flush.ts +2 -2
- package/scripts/overrides/lockfile-overrides.ts +1 -1
- package/scripts/overrides/overrides-logic.ts +1 -1
- package/scripts/package/package-scout-cli.ts +2 -7
- package/scripts/package/package-scout.ts +0 -2
- package/scripts/propagate/propagate-git-failure.ts +0 -1
- package/scripts/propagate/propagate-git.ts +0 -2
- package/scripts/propagate/propagate-plan.ts +185 -0
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -3
- package/scripts/propagate/propagate-steps.ts +19 -6
- package/scripts/propagate/propagate-targets.ts +13 -6
- package/scripts/propagate/propagate.ts +60 -46
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +0 -1
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +1 -2
- package/scripts/registry-migration/migrate.ts +19 -9
- package/scripts/release/github-release-cli.ts +8 -6
- package/scripts/release/github-release-environment.ts +46 -0
- package/scripts/release/github-release.ts +151 -94
- package/scripts/release/release-history.ts +0 -1
- package/scripts/release/release-plan.ts +0 -1
- package/scripts/release/release-publish.ts +2 -3
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/repo/auto-merge-setting-logic.ts +1 -4
- package/scripts/repo/repo-setting.ts +1 -1
- package/scripts/repo/repository-labels.ts +3 -3
- package/scripts/repo/required-checks-logic.ts +206 -0
- package/scripts/repo/required-checks-report.ts +71 -0
- package/scripts/repo/ruleset-check-cli.ts +53 -0
- package/scripts/repo/ruleset-check.ts +147 -0
- package/scripts/report/report-lint-cli.ts +0 -4
- package/scripts/review/disposition-cli.ts +1 -1
- package/scripts/review/live-evidence.ts +1 -1
- package/scripts/review/review-attest-cli.ts +0 -6
- package/scripts/review/review-attest.ts +48 -16
- package/scripts/review/review-brief-cli.ts +72 -8
- package/scripts/review/review-brief.ts +67 -9
- package/scripts/review/review-diff-parts.ts +89 -0
- package/scripts/review/review-diff-write.ts +97 -0
- package/scripts/review/review-finding-ledger.ts +0 -1
- package/scripts/review/review-record-cli.ts +1 -1
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +6 -2
- package/scripts/review/review-tree.ts +14 -2
- package/scripts/rules/decision-oracle-stage.ts +18 -0
- package/scripts/rules/decision-oracle.ts +10 -7
- package/scripts/rules/delivered-rules.ts +9 -1
- package/scripts/rules/destructive-command.ts +119 -0
- package/scripts/rules/direct-filing.ts +1 -1
- package/scripts/rules/file-body.ts +0 -3
- package/scripts/rules/filing-cap.ts +0 -2
- package/scripts/rules/gh-api.ts +7 -2
- package/scripts/rules/git-argv.ts +18 -7
- package/scripts/rules/git-force.ts +0 -2
- package/scripts/rules/implementation-cut.ts +1 -2
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/issue-fold.ts +1 -2
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-carry-conflict.ts +1 -2
- package/scripts/rules/lane-park.ts +14 -8
- package/scripts/rules/last-prompt.ts +1 -0
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/oracle-firing.ts +1 -0
- package/scripts/rules/oracle-list-cli.ts +0 -3
- package/scripts/rules/permission-guards.ts +14 -0
- package/scripts/rules/pre-gate-cut.ts +2 -2
- package/scripts/rules/protected-files.ts +74 -0
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +0 -3
- package/scripts/rules/rule-value-cli.ts +0 -1
- package/scripts/rules/shell-body-trigger.ts +0 -1
- package/scripts/rules/shell-segments.ts +0 -1
- package/scripts/rules/stop-rules.ts +13 -5
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +0 -1
- package/scripts/rules/worktree-guard.ts +26 -9
- package/scripts/run/run-carry-cli.ts +0 -2
- package/scripts/run/run-carry-stash.ts +2 -2
- package/scripts/run/run-carry-streak.ts +1 -1
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +1 -1
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +101 -24
- package/scripts/run/run-entry.ts +0 -1
- package/scripts/run/run-event-cli.ts +0 -2
- package/scripts/run/run-event-follow.ts +1 -0
- package/scripts/run/run-event-render.ts +1 -1
- package/scripts/run/run-event-scope.ts +53 -4
- package/scripts/run/run-event-stream.ts +0 -3
- package/scripts/run/run-event-watch.ts +1 -0
- package/scripts/run/run-halfrun-resume.ts +20 -7
- package/scripts/run/run-headless.ts +24 -8
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +25 -5
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +1 -1
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +5 -13
- package/scripts/run/run-merge-steps.ts +5 -5
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-next-cli.ts +1 -1
- package/scripts/run/run-parent-cut-hook.ts +143 -0
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +2 -2
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-cli.ts +4 -7
- package/scripts/run/run-progress-clock.ts +6 -34
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +3 -3
- package/scripts/run/run-progress.ts +22 -10
- package/scripts/run/run-prrun-resume.ts +117 -0
- package/scripts/run/run-report-cli.ts +1 -2
- package/scripts/run/run-report.ts +0 -1
- package/scripts/run/run-retrospective.ts +1 -1
- package/scripts/run/run-review-cli.ts +0 -3
- package/scripts/run/run-review-steps.ts +2 -0
- package/scripts/run/run-review.ts +0 -2
- package/scripts/run/run-ship-cli.ts +27 -77
- package/scripts/run/run-ship-detach.ts +1 -0
- package/scripts/run/run-ship-next.ts +106 -0
- package/scripts/run/run-ship-preflight.ts +87 -0
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +23 -30
- package/scripts/run/run-ship-review.ts +20 -0
- package/scripts/run/run-ship-scoped.ts +45 -0
- package/scripts/run/run-ship-stage.ts +5 -1
- package/scripts/run/run-ship-steps.ts +105 -0
- package/scripts/run/run-ship.ts +2 -1
- package/scripts/run/run-stage-read.ts +62 -0
- package/scripts/run/run-stage.ts +160 -0
- package/scripts/run/run-status-cli.ts +1 -1
- package/scripts/run/run-step-cli.ts +21 -14
- package/scripts/run/run-step.ts +1 -1
- package/scripts/run/run-stop-notify.ts +1 -3
- package/scripts/run/run-stranded-cli.ts +0 -4
- package/scripts/run/run-stranded-detect.ts +2 -2
- package/scripts/run/run-tail-cli.ts +17 -11
- package/scripts/run/run-tail.ts +2 -0
- package/scripts/run/run-tidy-lanes.ts +2 -1
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -5
- package/scripts/run/run-wake-describe.ts +19 -1
- package/scripts/run/run-wake-loop.ts +2 -2
- package/scripts/run/run-wake.ts +2 -4
- package/scripts/run/run-watcher-guard-cli.ts +0 -4
- package/scripts/run/run-watcher-guard.ts +9 -7
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +0 -1
- package/scripts/security/security-audit-provision.ts +3 -2
- package/scripts/security/security-audit.ts +0 -1
- package/scripts/security/security-updates-logic.ts +0 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
- package/scripts/sonar/sonar-hotspots.ts +0 -1
- package/scripts/sonar/sonar-new-code-cli.ts +150 -0
- package/scripts/sonar/sonar-new-code.ts +79 -0
- package/scripts/sonar/sonar-project.ts +97 -0
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +2 -5
- package/scripts/sync/managed-config-scope-cli.ts +1 -1
- package/scripts/sync/skill-migration.ts +0 -1
- package/scripts/sync/sync-hook-safety.ts +2 -3
- package/scripts/sync/sync.ts +1 -8
- package/scripts/sync/template-source-logic.ts +0 -1
- package/scripts/sync/workflow-pin-logic.ts +16 -28
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +0 -2
- package/scripts/test/test-red-commit.ts +2 -2
- package/scripts/test/test-red.ts +14 -7
- package/scripts/test/test-type-logic.ts +1 -1
- package/scripts/test/unit-worker-share.ts +7 -16
- package/scripts/time-runtime/time-batch-guard.ts +1 -2
- package/scripts/time-runtime/time-bundle-call.ts +2 -3
- package/scripts/time-runtime/time-bundles.ts +0 -4
- package/scripts/time-runtime/time-density-hook.ts +0 -2
- package/scripts/time-runtime/time-followup-stage.ts +1 -1
- package/scripts/time-runtime/time-format.ts +0 -73
- package/scripts/time-runtime/time-round-trips.ts +0 -4
- package/scripts/time-runtime/time-single-check.ts +1 -1
- package/scripts/time-runtime/time-spans.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +1 -2
- package/scripts/ui/ui-routes-cli.ts +0 -5
- package/scripts/ui/ui-routes.ts +0 -5
- package/scripts/version/effective-upstream.ts +2 -2
- package/scripts/version/latest-corepack.ts +7 -9
- package/scripts/version/latest-scope-cli.ts +0 -2
- package/scripts/version/latest-update.ts +0 -2
- package/scripts/version/npm-registry.ts +97 -0
- package/scripts/version/publishable-range-check.ts +1 -1
- package/scripts/version/release-hold.ts +0 -4
- package/scripts/version/running-binary.ts +2 -2
- package/scripts/version/version-check-logic.ts +0 -2
- package/scripts/version/version-commands.ts +5 -4
- package/scripts/version/version-remote.ts +28 -14
- package/scripts/version/version-targets.ts +4 -4
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/dependabot-auto-merge.yml +5 -3
- package/templates/workflows/github-release.yml +81 -0
- package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
- package/prompts/collaboration-workflow/epic-audit.md +0 -5
- package/prompts/collaboration-workflow/epic-bundle.md +0 -5
- package/scripts/init/plugin-install-hint.ts +0 -47
- package/scripts/version/parse-json.ts +0 -13
- /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
- /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
- /package/scripts/{git → gh}/git-gh-command.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue-write.ts +0 -0
- /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +0 -0
- /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
- /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
- /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
- /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
- /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
- /package/scripts/{git → gh}/git-pr-error.ts +0 -0
- /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
- /package/scripts/{git → gh}/github-issue-url.ts +0 -0
- /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
- /package/scripts/{git → issue}/issue-reference.ts +0 -0
- /package/scripts/{git → lib}/animation-helpers.ts +0 -0
- /package/scripts/{git → lib}/git-animation.ts +0 -0
- /package/scripts/{git → notify}/git-notify.ts +0 -0
- /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
|
@@ -9,13 +9,14 @@ import { epic_next } from '#scripts/epic/epic-next'
|
|
|
9
9
|
import { epic_next_read, type EpicRead } from '#scripts/epic/epic-next-read'
|
|
10
10
|
import type { EpicView } from '#scripts/epic/epic-next-views'
|
|
11
11
|
import { epic_report, type EpicNextResult, type EpicVerdict } from '#scripts/epic/epic-report'
|
|
12
|
-
import {
|
|
12
|
+
import { epic_solo_stale } from '#scripts/epic/epic-solo-stale'
|
|
13
13
|
import { epic_triage, type TriageVerdict } from '#scripts/epic/epic-triage'
|
|
14
|
-
import { git_gh_command } from '#scripts/
|
|
14
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
15
15
|
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
16
16
|
import { issue_citation } from '#scripts/rules/issue-citation'
|
|
17
17
|
import { backlog_defect_priority } from './backlog-defect-priority'
|
|
18
18
|
import { backlog_pool } from './backlog-pool'
|
|
19
|
+
import { backlog_rank } from './backlog-rank'
|
|
19
20
|
|
|
20
21
|
// `josh backlog:next` — what the whole opted-in backlog may run next (joshuafolkken/kit#1630).
|
|
21
22
|
//
|
|
@@ -235,12 +236,15 @@ async function resolve(context: PoolContext): Promise<EpicNextResult | undefined
|
|
|
235
236
|
return undefined
|
|
236
237
|
}
|
|
237
238
|
|
|
238
|
-
// The defect priority
|
|
239
|
-
// the run takes (joshuafolkken/kit#2455).
|
|
240
|
-
|
|
239
|
+
// The defect priority and the ranking keys are applied here rather than when printing, so
|
|
240
|
+
// `backlog:plan` shows the order the run takes (joshuafolkken/kit#2455, joshuafolkken/kit#2928). The
|
|
241
|
+
// ranking goes last: its sort is stable, so the defect order survives as its final key.
|
|
242
|
+
const ordered = await backlog_defect_priority.prioritize(
|
|
241
243
|
combine(views_from(reads, context), context),
|
|
242
244
|
context.repo,
|
|
243
245
|
)
|
|
246
|
+
|
|
247
|
+
return backlog_rank.rank_result(ordered, context.repo)
|
|
244
248
|
}
|
|
245
249
|
|
|
246
250
|
// Whether the `error` verdict is really a transport failure wearing the graph's clothes.
|
|
@@ -274,13 +278,31 @@ function report_retry(context: PoolContext): number {
|
|
|
274
278
|
return SUCCESS_EXIT_CODE
|
|
275
279
|
}
|
|
276
280
|
|
|
281
|
+
// The rows the offer's cap bounds — the standalone half, which `backlog:plan --waves` reads too.
|
|
282
|
+
function standalone_keys(context: PoolContext): ReadonlySet<string> {
|
|
283
|
+
return backlog_pool.standalone_keys(context.opted_in.issues, {
|
|
284
|
+
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
285
|
+
exclude: context.exclude,
|
|
286
|
+
repo: context.repo,
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
|
|
277
290
|
// The `run:solo` gate is applied here rather than in `resolve`, because `backlog:plan` shares
|
|
278
291
|
// `resolve` and a plan made before the run lists everything (joshuafolkken/kit#2776). The holders are
|
|
279
|
-
// read only on a `run` answer — the one answer the gate can change.
|
|
280
|
-
|
|
292
|
+
// read only on a `run` answer — the one answer the gate can change. The cap follows the gate
|
|
293
|
+
// (`backlog-rank.ts`, joshuafolkken/kit#2928).
|
|
294
|
+
async function gate_solo(result: EpicNextResult, context: PoolContext): Promise<EpicNextResult> {
|
|
281
295
|
if (result.verdict !== 'run') return result
|
|
282
296
|
|
|
283
|
-
const
|
|
297
|
+
const { repo } = context
|
|
298
|
+
const { read, notice } = await epic_solo_stale.release(
|
|
299
|
+
await epic_busy.read_repository(repo),
|
|
300
|
+
repo,
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
if (notice !== undefined) console.error(notice)
|
|
304
|
+
|
|
305
|
+
const gated = backlog_rank.gate(result, read, repo, standalone_keys(context))
|
|
284
306
|
|
|
285
307
|
if (gated.notice !== undefined) console.error(gated.notice)
|
|
286
308
|
|
|
@@ -314,7 +336,7 @@ async function answer_pool(context: PoolContext): Promise<number> {
|
|
|
314
336
|
|
|
315
337
|
if (untriaged.length > 0) return report_triage(context, untriaged)
|
|
316
338
|
|
|
317
|
-
return report(await gate_solo(result, context
|
|
339
|
+
return report(await gate_solo(result, context), context)
|
|
318
340
|
}
|
|
319
341
|
|
|
320
342
|
// A backlog nobody has opted into answers `none` before either listing below is asked for.
|
|
@@ -395,22 +417,10 @@ const backlog_next = {
|
|
|
395
417
|
RETRY_MESSAGE,
|
|
396
418
|
READ_FAILURES,
|
|
397
419
|
VERDICT_TOKENS,
|
|
398
|
-
tokens_of,
|
|
399
|
-
warn_epic_gap,
|
|
400
|
-
warn_gaps,
|
|
401
|
-
report,
|
|
402
|
-
combine,
|
|
403
|
-
views_from,
|
|
404
420
|
resolve,
|
|
405
|
-
|
|
406
|
-
report_retry,
|
|
407
|
-
report_triage,
|
|
421
|
+
standalone_keys,
|
|
408
422
|
context_of,
|
|
409
|
-
answer_pool,
|
|
410
|
-
report_none,
|
|
411
|
-
answer,
|
|
412
423
|
run,
|
|
413
|
-
main,
|
|
414
424
|
}
|
|
415
425
|
|
|
416
426
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -262,16 +262,11 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
262
262
|
|
|
263
263
|
const backlog_offer_cli = {
|
|
264
264
|
JSON_KEY,
|
|
265
|
-
USAGE,
|
|
266
265
|
budget_argv,
|
|
267
266
|
counts_of,
|
|
268
|
-
emit,
|
|
269
|
-
main,
|
|
270
|
-
mark_drain,
|
|
271
267
|
next_argv,
|
|
272
268
|
read_values,
|
|
273
269
|
run,
|
|
274
|
-
to_tokens,
|
|
275
270
|
}
|
|
276
271
|
|
|
277
272
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -3,7 +3,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
3
3
|
import { auto_ok_cli } from '#scripts/auto-ok/auto-ok-cli'
|
|
4
4
|
import { epic_index } from '#scripts/epic/epic-index'
|
|
5
5
|
import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
6
|
-
import { git_gh_command } from '#scripts/
|
|
6
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
7
7
|
import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
8
8
|
import { open_issue_schema, type OpenIssueData } from '#scripts/git/schemas'
|
|
9
9
|
import { run_invocation } from '#scripts/run/run-invocation'
|
|
@@ -104,6 +104,9 @@ interface Plan {
|
|
|
104
104
|
// past the listing cap. Carrying the *whole* index here instead would move that misreport rather
|
|
105
105
|
// than remove it: the sentence would name an epic that is withholding nothing.
|
|
106
106
|
tracked: ReadonlyMap<number, number>
|
|
107
|
+
// The rows the offer's cap bounds, so `--waves` cuts each wave where `backlog:next` does
|
|
108
|
+
// (joshuafolkken/kit#2928).
|
|
109
|
+
standalone: ReadonlySet<string>
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
// The listing plus whether it was cut. Carried together because the rows alone cannot say whether
|
|
@@ -138,6 +141,7 @@ async function classify(
|
|
|
138
141
|
repo: context.repo,
|
|
139
142
|
exclude,
|
|
140
143
|
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
144
|
+
standalone: backlog_next.standalone_keys(context),
|
|
141
145
|
}
|
|
142
146
|
}
|
|
143
147
|
|
|
@@ -168,7 +172,7 @@ function print_plan(plan: Plan, listing: OpenListing, view: PlanView): void {
|
|
|
168
172
|
const context = context_of(plan, listing)
|
|
169
173
|
|
|
170
174
|
if (view.is_waves) {
|
|
171
|
-
console.info(backlog_waves.format_waves(plan.result, context))
|
|
175
|
+
console.info(backlog_waves.format_waves(plan.result, context, plan.standalone))
|
|
172
176
|
|
|
173
177
|
return
|
|
174
178
|
}
|
|
@@ -259,13 +263,7 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
259
263
|
const backlog_plan_cli = {
|
|
260
264
|
OPEN_TRUNCATED_MESSAGE,
|
|
261
265
|
OPEN_UNREADABLE_MESSAGE,
|
|
262
|
-
USAGE,
|
|
263
266
|
WAVES_WITH_NAMED_MESSAGE,
|
|
264
|
-
classify,
|
|
265
|
-
fetch_open,
|
|
266
|
-
main,
|
|
267
|
-
print_plan,
|
|
268
|
-
report,
|
|
269
267
|
run,
|
|
270
268
|
}
|
|
271
269
|
|
|
@@ -3,7 +3,7 @@ import type { IssueReference } from '#scripts/epic/epic-reference'
|
|
|
3
3
|
import { epic_report, type EpicNextResult } from '#scripts/epic/epic-report'
|
|
4
4
|
import { epic_solo } from '#scripts/epic/epic-solo'
|
|
5
5
|
import { epic_triage } from '#scripts/epic/epic-triage'
|
|
6
|
-
import { has_label_name, IN_PROGRESS_LABEL, RUN_SOLO_LABEL } from '#scripts/
|
|
6
|
+
import { has_label_name, IN_PROGRESS_LABEL, RUN_SOLO_LABEL } from '#scripts/issue/issue-labels'
|
|
7
7
|
import type { OutOfScopeRow } from './backlog-scope'
|
|
8
8
|
|
|
9
9
|
// The plan a person reads before a `backlogrun` starts (joshuafolkken/kit#1652).
|
|
@@ -5,14 +5,14 @@ import { epic_index } from '#scripts/epic/epic-index'
|
|
|
5
5
|
import { epic_issue } from '#scripts/epic/epic-issue'
|
|
6
6
|
import type { EpicView } from '#scripts/epic/epic-next-views'
|
|
7
7
|
import { epic_outside_blocker } from '#scripts/epic/epic-outside-blocker'
|
|
8
|
-
import {
|
|
8
|
+
import type { OpenIssueData } from '#scripts/git/schemas'
|
|
9
|
+
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
9
10
|
import {
|
|
10
11
|
ALREADY_DONE_LABEL,
|
|
11
12
|
EPIC_LABEL,
|
|
12
13
|
has_any_label,
|
|
13
14
|
NEEDS_DECISION_LABEL,
|
|
14
|
-
} from '#scripts/
|
|
15
|
-
import type { OpenIssueData } from '#scripts/git/schemas'
|
|
15
|
+
} from '#scripts/issue/issue-labels'
|
|
16
16
|
|
|
17
17
|
// The candidate pool `josh backlog:next` answers from (joshuafolkken/kit#1630).
|
|
18
18
|
//
|
|
@@ -37,6 +37,9 @@ const DECISION_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALRE
|
|
|
37
37
|
// `tracked` is the narrowed set `epic_index.withheld_children` builds, not every child an epic
|
|
38
38
|
// tracks (joshuafolkken/kit#1668) — the narrowing itself is defined there, once, for this half and
|
|
39
39
|
// `auto-ok:next` alike.
|
|
40
|
+
// The part of the context that decides which rows the standalone half considers at all.
|
|
41
|
+
type ConsideredContext = Pick<StandaloneContext, 'tracked' | 'exclude' | 'repo'>
|
|
42
|
+
|
|
40
43
|
interface StandaloneContext {
|
|
41
44
|
tracked: ReadonlyMap<number, number>
|
|
42
45
|
exclude: ReadonlyArray<number>
|
|
@@ -135,26 +138,28 @@ function standalone_rows(issues: ReadonlyArray<OpenIssueData>): ReadonlyArray<Op
|
|
|
135
138
|
// are actually going to offer their children and applied here for the same reason. Which rows those
|
|
136
139
|
// are is `epic_index.withheld_children`'s answer, not a second test made here. A row the caller
|
|
137
140
|
// excluded is out of the pool entirely rather than merely unoffered: it has just merged.
|
|
138
|
-
function is_considered(issue: OpenIssueData, context:
|
|
141
|
+
function is_considered(issue: OpenIssueData, context: ConsideredContext): boolean {
|
|
139
142
|
return !context.tracked.has(issue.number) && !context.exclude.includes(issue.number)
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
// The standalone half, in the buckets the verdict is read from.
|
|
143
146
|
//
|
|
144
|
-
// The order is `git_next_issues.
|
|
145
|
-
// `🗒 Next issues` display and `auto-ok:next` already answer with,
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
149
|
-
//
|
|
150
|
-
//
|
|
151
|
-
//
|
|
147
|
+
// The order is `git_next_issues.order`'s and not a second one — the same ranking the
|
|
148
|
+
// `🗒 Next issues` display and `auto-ok:next` already answer with, so the three cannot disagree about
|
|
149
|
+
// what comes next. Anything it withholds is still open work: `needs-decision` is waiting on a person,
|
|
150
|
+
// and everything else — a standing blocker, a run already in progress — resolves on its own and is
|
|
151
|
+
// waiting on time.
|
|
152
|
+
//
|
|
153
|
+
// **The display's cap is not applied here** (joshuafolkken/kit#2928). Cut at this point, a sixth
|
|
154
|
+
// runnable `run:solo` issue never reached the gate that holds back what is ranked below it, so the
|
|
155
|
+
// cap is applied after that gate instead (`backlog-rank.ts`). A row past it is still reported as
|
|
156
|
+
// waiting and offered by a later ask, so the backlog drains without it ever being lost.
|
|
152
157
|
function classify_standalone(
|
|
153
158
|
issues: ReadonlyArray<OpenIssueData>,
|
|
154
159
|
context: StandaloneContext,
|
|
155
160
|
): Classification {
|
|
156
161
|
const considered = issues.filter((issue) => is_considered(issue, context))
|
|
157
|
-
const runnable = git_next_issues.
|
|
162
|
+
const runnable = git_next_issues.order(
|
|
158
163
|
considered.filter((issue) => auto_ok_cli.is_runnable(issue, context.tracked, context.exclude)),
|
|
159
164
|
)
|
|
160
165
|
const offered = new Set(runnable.map((issue) => issue.number))
|
|
@@ -301,22 +306,34 @@ function merge_classifications(left: Classification, right: Classification): Cla
|
|
|
301
306
|
}
|
|
302
307
|
}
|
|
303
308
|
|
|
309
|
+
// The keys of the rows the standalone half considers — the rows the offer's cap bounds. An issue an
|
|
310
|
+
// opted-in epic tracks is that epic's child here, and never capped, exactly as before.
|
|
311
|
+
function standalone_keys(
|
|
312
|
+
issues: ReadonlyArray<OpenIssueData>,
|
|
313
|
+
context: ConsideredContext,
|
|
314
|
+
): ReadonlySet<string> {
|
|
315
|
+
return keys_of(
|
|
316
|
+
to_children(
|
|
317
|
+
standalone_rows(issues).filter((issue) => is_considered(issue, context)),
|
|
318
|
+
context.repo,
|
|
319
|
+
),
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
|
|
304
323
|
const backlog_pool = {
|
|
305
324
|
classify_standalone,
|
|
306
325
|
cross_epic_cycles,
|
|
307
326
|
running_set,
|
|
308
327
|
settle_standalone,
|
|
328
|
+
standalone_keys,
|
|
309
329
|
drop_excluded,
|
|
310
330
|
epic_classification,
|
|
311
|
-
is_epic_row,
|
|
312
|
-
keys_of,
|
|
313
331
|
merge_classifications,
|
|
314
332
|
opted_in_epics,
|
|
315
333
|
standalone_rows,
|
|
316
334
|
to_child,
|
|
317
335
|
to_children,
|
|
318
|
-
unique_children,
|
|
319
336
|
}
|
|
320
337
|
|
|
321
338
|
export { backlog_pool }
|
|
322
|
-
export type { StandaloneContext }
|
|
339
|
+
export type { ConsideredContext, StandaloneContext }
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { BusyRead } from '#scripts/epic/epic-busy'
|
|
2
|
+
import { epic_graph, type EpicChild } from '#scripts/epic/epic-graph'
|
|
3
|
+
import { epic_rank } from '#scripts/epic/epic-rank'
|
|
4
|
+
import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
5
|
+
import { epic_solo, type SoloGate, type SoloSelection } from '#scripts/epic/epic-solo'
|
|
6
|
+
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
7
|
+
|
|
8
|
+
// What the backlog offers, in the order it is decided (joshuafolkken/kit#2928): rank, then the
|
|
9
|
+
// `run:solo` gate, then the cap. `backlog:next` and `backlog:plan --waves` both call `select`, so the
|
|
10
|
+
// plan's first wave is what the run starts into an idle repository rather than an order the run never
|
|
11
|
+
// takes.
|
|
12
|
+
//
|
|
13
|
+
// **The cap comes last.** It used to be applied while the standalone half was classified, before the
|
|
14
|
+
// gate, so a `run:solo` issue ranked sixth or lower was cut before the gate could see it — and the
|
|
15
|
+
// issues below it were offered past it. Cut after the gate, the cap only ever removes what the gate
|
|
16
|
+
// would have offered, so it cannot hide a waiting `run:solo` issue from it. It still bounds only the
|
|
17
|
+
// standalone rows, as it always has; an epic's children were never capped.
|
|
18
|
+
|
|
19
|
+
// Every child the classification placed, in the order it placed them: the ranked candidates first,
|
|
20
|
+
// then the waiting ones, then the ones waiting on a person.
|
|
21
|
+
function everything_in(result: EpicNextResult): ReadonlyArray<EpicChild> {
|
|
22
|
+
const candidates = result.candidates.flatMap((bundle) => bundle.children)
|
|
23
|
+
|
|
24
|
+
return [...candidates, ...result.waiting, ...result.blocked_on_people]
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// The ranking is `epic_rank.rank`, shared with a named epic's lanes.
|
|
28
|
+
const { rank } = epic_rank
|
|
29
|
+
|
|
30
|
+
// This repository's candidates re-ranked inside the result, so `backlog:plan` prints the order the
|
|
31
|
+
// offer is decided in.
|
|
32
|
+
function rank_result(result: EpicNextResult, repo: string): EpicNextResult {
|
|
33
|
+
if (result.verdict !== 'run') return result
|
|
34
|
+
|
|
35
|
+
const pool = everything_in(result)
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
...result,
|
|
39
|
+
candidates: result.candidates.map((bundle) =>
|
|
40
|
+
bundle.repo === repo ? { ...bundle, children: rank(bundle.children, pool) } : bundle,
|
|
41
|
+
),
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// The standalone rows past the cap, in offer order.
|
|
46
|
+
function overflow_of(
|
|
47
|
+
offered: ReadonlyArray<EpicChild>,
|
|
48
|
+
standalone: ReadonlySet<string>,
|
|
49
|
+
): ReadonlySet<string> {
|
|
50
|
+
const keys = offered.map((child) => epic_graph.key_of(child)).filter((key) => standalone.has(key))
|
|
51
|
+
|
|
52
|
+
return new Set(keys.slice(git_next_issues.DISPLAY_LIMIT))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function is_in(child: EpicChild, keys: ReadonlySet<string>): boolean {
|
|
56
|
+
return keys.has(epic_graph.key_of(child))
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function cap(selection: SoloSelection, standalone: ReadonlySet<string>): SoloSelection {
|
|
60
|
+
const overflow = overflow_of(selection.offered, standalone)
|
|
61
|
+
|
|
62
|
+
if (overflow.size === 0) return selection
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
...selection,
|
|
66
|
+
offered: selection.offered.filter((child) => !is_in(child, overflow)),
|
|
67
|
+
withheld: [
|
|
68
|
+
...selection.offered.filter((child) => is_in(child, overflow)),
|
|
69
|
+
...selection.withheld,
|
|
70
|
+
],
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface OfferInput {
|
|
75
|
+
candidates: ReadonlyArray<EpicChild>
|
|
76
|
+
pool: ReadonlyArray<EpicChild>
|
|
77
|
+
read: BusyRead
|
|
78
|
+
repo: string
|
|
79
|
+
// The keys of the standalone rows — the ones the cap bounds.
|
|
80
|
+
standalone: ReadonlySet<string>
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function select(input: OfferInput): SoloSelection {
|
|
84
|
+
const ranked = rank(input.candidates, input.pool)
|
|
85
|
+
|
|
86
|
+
return cap(epic_solo.select(ranked, input.read, input.repo), input.standalone)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// `backlog:next`'s gate: `epic_solo.gate` with this selection in place of its bare one.
|
|
90
|
+
function gate(
|
|
91
|
+
result: EpicNextResult,
|
|
92
|
+
read: BusyRead,
|
|
93
|
+
repo: string,
|
|
94
|
+
standalone: ReadonlySet<string>,
|
|
95
|
+
): SoloGate {
|
|
96
|
+
const pool = everything_in(result)
|
|
97
|
+
|
|
98
|
+
return epic_solo.gate(result, read, repo, (candidates) =>
|
|
99
|
+
select({ candidates, pool, read, repo, standalone }),
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const backlog_rank = { everything_in, gate, rank_result, select }
|
|
104
|
+
|
|
105
|
+
export { backlog_rank }
|
|
106
|
+
export type { OfferInput }
|
|
@@ -21,6 +21,13 @@ interface ReadyPorts {
|
|
|
21
21
|
ready_issues: () => Promise<ReadonlyArray<string>>
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
async function free_under(limit: number): Promise<number> {
|
|
25
|
+
const lanes = await lane_registry.list_lanes()
|
|
26
|
+
const live = lanes.filter((lane) => !lane.is_stranded).length
|
|
27
|
+
|
|
28
|
+
return lane_capacity.free_lanes(limit, live)
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
// Free lanes right now: the limit less the live lanes. An unreadable limit reads as no free lane — the
|
|
25
32
|
// safe direction, since both the stall and the ready line need a free lane and reporting one that is
|
|
26
33
|
// not there is the false positive neither may raise.
|
|
@@ -35,10 +42,18 @@ async function free_lane_count(): Promise<number> {
|
|
|
35
42
|
|
|
36
43
|
if (limit.kind !== 'limit') return NO_FREE
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
return await free_under(limit.limit)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// **The drive's count throws on an unreadable limit** (joshuafolkken/kit#3027). The drive launches no
|
|
49
|
+
// more than this count, so the safe-direction zero above would leave it launching nothing and reporting
|
|
50
|
+
// nothing for good; a bad setting is the hard error `lane_capacity` says it is, ending the drive loudly.
|
|
51
|
+
async function drive_free_lane_count(): Promise<number> {
|
|
52
|
+
const limit = lane_capacity.lane_limit()
|
|
53
|
+
|
|
54
|
+
if (limit.kind !== 'limit') throw new Error(limit.problem)
|
|
40
55
|
|
|
41
|
-
return
|
|
56
|
+
return await free_under(limit.limit)
|
|
42
57
|
}
|
|
43
58
|
|
|
44
59
|
// **A `--only` run has no pool to drain** (joshuafolkken/kit#2472). `backlog:next` lists the opted-in
|
|
@@ -135,6 +150,7 @@ const backlog_ready = {
|
|
|
135
150
|
read_backlog_next,
|
|
136
151
|
print_offer_hint,
|
|
137
152
|
free_lane_count,
|
|
153
|
+
drive_free_lane_count,
|
|
138
154
|
drains_pool,
|
|
139
155
|
print_ready_line,
|
|
140
156
|
read_ready,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
2
|
-
import { AUTO_OK_LABEL, EPIC_LABEL, has_any_label } from '#scripts/git/issue-labels'
|
|
3
2
|
import type { OpenIssueData } from '#scripts/git/schemas'
|
|
3
|
+
import { AUTO_OK_LABEL, EPIC_LABEL, has_any_label } from '#scripts/issue/issue-labels'
|
|
4
4
|
|
|
5
5
|
// Which open issues the backlog will not run, and why (joshuafolkken/kit#1652).
|
|
6
6
|
//
|
|
@@ -135,8 +135,6 @@ const backlog_scope = {
|
|
|
135
135
|
OPTED_IN_UNPLACED_REASON,
|
|
136
136
|
open_numbers_of,
|
|
137
137
|
out_of_scope,
|
|
138
|
-
planned_numbers,
|
|
139
|
-
reason_for,
|
|
140
138
|
titles_of,
|
|
141
139
|
}
|
|
142
140
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { telegram_notify } from '#scripts/
|
|
1
|
+
import { telegram_notify } from '#scripts/notify/telegram-notify'
|
|
2
2
|
import { run_event_stream, type RunEvent } from '#scripts/run/run-event-stream'
|
|
3
3
|
import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
|
|
4
4
|
import { backlog_ready, type ReadyPorts } from './backlog-ready'
|
|
@@ -137,7 +137,7 @@ async function run_stall_check(ready: ReadyPorts = backlog_ready.DEFAULT_PORTS):
|
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
const backlog_stalled_detect = {
|
|
140
|
+
const backlog_stalled_detect = { detect_and_report, run_stall_check }
|
|
141
141
|
|
|
142
142
|
export { backlog_stalled_detect }
|
|
143
143
|
export type { DetectPorts }
|
|
@@ -4,9 +4,13 @@ import { epic_cross_repo } from '#scripts/epic/epic-cross-repo'
|
|
|
4
4
|
import { epic_graph, type EpicChild } from '#scripts/epic/epic-graph'
|
|
5
5
|
import { epic_outside_blocker } from '#scripts/epic/epic-outside-blocker'
|
|
6
6
|
import { epic_report, type EpicNextResult } from '#scripts/epic/epic-report'
|
|
7
|
-
import {
|
|
8
|
-
|
|
7
|
+
import {
|
|
8
|
+
has_label_name,
|
|
9
|
+
IN_PROGRESS_LABEL,
|
|
10
|
+
NEEDS_DECISION_LABEL,
|
|
11
|
+
} from '#scripts/issue/issue-labels'
|
|
9
12
|
import { backlog_plan, type PlanContext } from './backlog-plan'
|
|
13
|
+
import { backlog_rank } from './backlog-rank'
|
|
10
14
|
|
|
11
15
|
// The order a `backlogrun` takes, wave by wave, before it starts (joshuafolkken/kit#2778).
|
|
12
16
|
//
|
|
@@ -14,13 +18,13 @@ import { backlog_plan, type PlanContext } from './backlog-plan'
|
|
|
14
18
|
// made from, so the order past the first answer was left for a person to work out by hand. This plays
|
|
15
19
|
// the asks forward under one assumption: **every issue of a wave merges before the next wave starts**.
|
|
16
20
|
//
|
|
17
|
-
// **No rule is written twice.** The first wave is `
|
|
18
|
-
// `backlog:next` resolves, asked of an idle repository — so it is what
|
|
19
|
-
// nothing is running. Each later wave marks the earlier waves closed and re-classifies the same pool
|
|
21
|
+
// **No rule is written twice.** The first wave is `backlog_rank.select` — rank, `run:solo` gate, cap —
|
|
22
|
+
// over the very candidates `backlog:next` resolves, asked of an idle repository — so it is what
|
|
23
|
+
// `backlog:next` prints when nothing is running (joshuafolkken/kit#2928). Each later wave marks the earlier waves closed and re-classifies the same pool
|
|
20
24
|
// through `epic_classify.classify_children` with the resolver `epic:next` sorted it with the first
|
|
21
25
|
// time — `epic_cross_repo.resolve_cross_repo`, so a blocker in another repository still waits for its
|
|
22
26
|
// release rather than counting as done on close — then puts the runnable set through
|
|
23
|
-
// `
|
|
27
|
+
// `backlog_rank.select` again.
|
|
24
28
|
|
|
25
29
|
const IDLE: BusyRead = { kind: 'idle' }
|
|
26
30
|
const CLOSED = 'CLOSED'
|
|
@@ -45,14 +49,6 @@ function is_running(child: EpicChild): boolean {
|
|
|
45
49
|
return has_label_name(child.labels, IN_PROGRESS_LABEL)
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
// Every child the classification placed, in the order it placed them: the ranked candidates first,
|
|
49
|
-
// then the waiting ones, then the ones waiting on a person.
|
|
50
|
-
function everything_in(result: EpicNextResult): ReadonlyArray<EpicChild> {
|
|
51
|
-
const candidates = result.candidates.flatMap((bundle) => bundle.children)
|
|
52
|
-
|
|
53
|
-
return [...candidates, ...result.waiting, ...result.blocked_on_people]
|
|
54
|
-
}
|
|
55
|
-
|
|
56
52
|
function as_closed(child: EpicChild, done: ReadonlySet<string>): EpicChild {
|
|
57
53
|
return done.has(epic_graph.key_of(child)) ? { ...child, state: CLOSED } : child
|
|
58
54
|
}
|
|
@@ -63,24 +59,35 @@ interface WavePool {
|
|
|
63
59
|
children: ReadonlyArray<EpicChild>
|
|
64
60
|
running: ReadonlySet<string>
|
|
65
61
|
repo: string
|
|
62
|
+
standalone: ReadonlySet<string>
|
|
66
63
|
}
|
|
67
64
|
|
|
68
|
-
function pool_of(result: EpicNextResult, repo: string): WavePool {
|
|
69
|
-
const all = everything_in(result)
|
|
65
|
+
function pool_of(result: EpicNextResult, repo: string, standalone: ReadonlySet<string>): WavePool {
|
|
66
|
+
const all = backlog_rank.everything_in(result)
|
|
70
67
|
|
|
71
68
|
return {
|
|
72
69
|
children: all.filter((child) => !is_running(child)),
|
|
73
70
|
running: epic_outside_blocker.running_keys(all),
|
|
74
71
|
repo,
|
|
72
|
+
standalone,
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
|
|
78
|
-
function offer(
|
|
79
|
-
|
|
76
|
+
function offer(
|
|
77
|
+
candidates: ReadonlyArray<EpicChild>,
|
|
78
|
+
children: ReadonlyArray<EpicChild>,
|
|
79
|
+
pool: WavePool,
|
|
80
|
+
): ReadonlyArray<EpicChild> {
|
|
81
|
+
const { repo, standalone } = pool
|
|
82
|
+
|
|
83
|
+
return backlog_rank.select({ candidates, pool: children, read: IDLE, repo, standalone }).offered
|
|
80
84
|
}
|
|
81
85
|
|
|
82
|
-
|
|
83
|
-
|
|
86
|
+
// Ranked against the whole result, exactly as `backlog:next` ranks it, so the two agree.
|
|
87
|
+
function first_wave(result: EpicNextResult, pool: WavePool): ReadonlyArray<EpicChild> {
|
|
88
|
+
const candidates = epic_report.candidates_for_repo(result, pool.repo)
|
|
89
|
+
|
|
90
|
+
return offer(candidates, backlog_rank.everything_in(result), pool)
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
function next_wave(pool: WavePool, done: ReadonlySet<string>): ReadonlyArray<EpicChild> {
|
|
@@ -93,25 +100,31 @@ function next_wave(pool: WavePool, done: ReadonlySet<string>): ReadonlyArray<Epi
|
|
|
93
100
|
|
|
94
101
|
return offer(
|
|
95
102
|
runnable.filter((child) => child.repo === pool.repo),
|
|
96
|
-
|
|
103
|
+
children,
|
|
104
|
+
pool,
|
|
97
105
|
)
|
|
98
106
|
}
|
|
99
107
|
|
|
100
108
|
// Each wave is closed before the next is asked for; a wave that offers nothing ends the plan, which
|
|
101
|
-
// the pool's size bounds because every wave closes at least one child.
|
|
102
|
-
|
|
103
|
-
|
|
109
|
+
// the pool's size bounds because every wave closes at least one child. `standalone` names the rows the
|
|
110
|
+
// offer's cap bounds; left empty, no wave is capped.
|
|
111
|
+
function build(
|
|
112
|
+
result: EpicNextResult,
|
|
113
|
+
repo: string,
|
|
114
|
+
standalone: ReadonlySet<string> = new Set(),
|
|
115
|
+
): WavePlan {
|
|
116
|
+
const pool = pool_of(result, repo, standalone)
|
|
104
117
|
const done = new Set<string>()
|
|
105
118
|
const waves: Array<ReadonlyArray<EpicChild>> = []
|
|
106
119
|
|
|
107
|
-
for (let wave = first_wave(result,
|
|
120
|
+
for (let wave = first_wave(result, pool); wave.length > 0; wave = next_wave(pool, done)) {
|
|
108
121
|
waves.push(wave)
|
|
109
122
|
for (const child of wave) done.add(epic_graph.key_of(child))
|
|
110
123
|
}
|
|
111
124
|
|
|
112
|
-
const unreached =
|
|
113
|
-
|
|
114
|
-
|
|
125
|
+
const unreached = backlog_rank
|
|
126
|
+
.everything_in(result)
|
|
127
|
+
.filter((child) => child.repo === repo && !done.has(epic_graph.key_of(child)))
|
|
115
128
|
|
|
116
129
|
return { waves, unreached }
|
|
117
130
|
}
|
|
@@ -139,10 +152,14 @@ function unreached_lines(plan: WavePlan, context: PlanContext): Array<string> {
|
|
|
139
152
|
)
|
|
140
153
|
}
|
|
141
154
|
|
|
142
|
-
function format_waves(
|
|
155
|
+
function format_waves(
|
|
156
|
+
result: EpicNextResult,
|
|
157
|
+
context: PlanContext,
|
|
158
|
+
standalone: ReadonlySet<string> = new Set(),
|
|
159
|
+
): string {
|
|
143
160
|
if (result.verdict === 'error') return backlog_plan.format_unusable(result)
|
|
144
161
|
|
|
145
|
-
const plan = build(result, context.repo)
|
|
162
|
+
const plan = build(result, context.repo, standalone)
|
|
146
163
|
const waves = plan.waves.map((wave, index) => wave_line(wave, index, context.repo))
|
|
147
164
|
|
|
148
165
|
return [
|
|
@@ -158,7 +175,6 @@ function format_waves(result: EpicNextResult, context: PlanContext): string {
|
|
|
158
175
|
const backlog_waves = {
|
|
159
176
|
HEADING_ASSUMPTION,
|
|
160
177
|
NEEDS_DECISION_NOTE,
|
|
161
|
-
NOT_REACHED_NOTE,
|
|
162
178
|
PARALLEL_NOTE,
|
|
163
179
|
UNREACHED_HEADING,
|
|
164
180
|
build,
|
|
@@ -81,7 +81,7 @@ function run(cwd: string = process.cwd()): number {
|
|
|
81
81
|
return file === undefined ? report_no_transcript() : check_session(file)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
const behavior_cli = {
|
|
84
|
+
const behavior_cli = { check_session, run }
|
|
85
85
|
|
|
86
86
|
if (process.argv[1] === fileURLToPath(import.meta.url)) process.exitCode = run()
|
|
87
87
|
|