@joshuafolkken/kit 1.1784.0 → 1.2114.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/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +59 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +415 -389
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +15 -8
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
2
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
3
|
+
import { issue_measured_close } from '#scripts/issue/issue-measured-close'
|
|
4
|
+
import {
|
|
5
|
+
measure_declaration,
|
|
6
|
+
type MeasureDeclaration,
|
|
7
|
+
type MeasureVerdict,
|
|
8
|
+
} from '#scripts/issue/measure-declaration'
|
|
9
|
+
import { trusted_measure, type CommandRun } from '#scripts/issue/trusted-measure'
|
|
10
|
+
import { error_text } from '#scripts/lib/error-message'
|
|
11
|
+
import { run_event_stream } from '#scripts/run/event/run-event-stream'
|
|
12
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
13
|
+
|
|
14
|
+
// joshuafolkken/kit#4621: the drive runs a due issue's measurement declaration (`measure-declaration.ts`)
|
|
15
|
+
// before it opens a lane. A value within the bound closes the issue the way `issue:measured` does — the
|
|
16
|
+
// result comment, the `measured` label, the close and the epic's progress — and puts a `measured` event
|
|
17
|
+
// on the stream, so no lane is spent. Anything else — no declaration, an untrusted body, a value out of
|
|
18
|
+
// bound, a failed command, output that is not one number — launches the lane as before; where a
|
|
19
|
+
// command ran, its result is commented first, so the child starts from the measurement, not a re-run.
|
|
20
|
+
|
|
21
|
+
const FENCE = '```'
|
|
22
|
+
const VERDICT_WORDS: Readonly<Record<MeasureVerdict['kind'], string>> = {
|
|
23
|
+
pass: 'within the bound, so the issue is closed without a lane.',
|
|
24
|
+
fail: 'out of the bound, so the issue goes to a lane.',
|
|
25
|
+
unreadable: 'no value could be read from the output, so the issue goes to a lane.',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Measurement {
|
|
29
|
+
declaration: MeasureDeclaration
|
|
30
|
+
run: CommandRun
|
|
31
|
+
verdict: MeasureVerdict
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function declared(issue: string): Promise<MeasureDeclaration | undefined> {
|
|
35
|
+
const read = await trusted_measure.read_trusted_body(issue)
|
|
36
|
+
|
|
37
|
+
return read.kind === 'trusted' ? measure_declaration.parse(read.body) : undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function measured(declaration: MeasureDeclaration): Measurement {
|
|
41
|
+
const run = trusted_measure.run_command(declaration.command)
|
|
42
|
+
const verdict: MeasureVerdict =
|
|
43
|
+
run.kind === 'ok' ? measure_declaration.judge(declaration, run.output) : { kind: 'unreadable' }
|
|
44
|
+
|
|
45
|
+
return { declaration, run, verdict }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function value_words(verdict: MeasureVerdict): string {
|
|
49
|
+
return verdict.kind === 'unreadable' ? 'unreadable' : String(verdict.value)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// The result comment: the declaration, the value read, what follows and the command's own output.
|
|
53
|
+
// Script-emitted, so English (`run-merge.ts` → `park_comment`).
|
|
54
|
+
function report(measurement: Measurement): string {
|
|
55
|
+
const { declaration, run, verdict } = measurement
|
|
56
|
+
|
|
57
|
+
return [
|
|
58
|
+
'`backlog:drive` ran the measurement declaration.',
|
|
59
|
+
'',
|
|
60
|
+
`- Declaration: ${measure_declaration.format(declaration)}`,
|
|
61
|
+
`- Value: ${value_words(verdict)}`,
|
|
62
|
+
`- Verdict: ${VERDICT_WORDS[verdict.kind]}`,
|
|
63
|
+
'',
|
|
64
|
+
FENCE,
|
|
65
|
+
trusted_measure.text_of(run),
|
|
66
|
+
FENCE,
|
|
67
|
+
].join('\n')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function close_passed(issue: string, measurement: Measurement): Promise<boolean> {
|
|
71
|
+
const is_closed = await issue_measured_close.close(issue, report(measurement))
|
|
72
|
+
const value = value_words(measurement.verdict)
|
|
73
|
+
const bound = `${measurement.declaration.operator} ${String(measurement.declaration.threshold)}`
|
|
74
|
+
|
|
75
|
+
if (is_closed) {
|
|
76
|
+
await run_event_stream_emit.emit(
|
|
77
|
+
run_event_stream.EVENT_KIND.MEASURED,
|
|
78
|
+
`${issue_cite.plain(issue)} measured by backlog:drive: ${value} ${bound}`,
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return is_closed
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// The result handed to the lane on the issue itself, which the child reads with its comments. A comment
|
|
86
|
+
// that cannot be posted still launches the lane: the child re-runs the declaration.
|
|
87
|
+
async function hand_over(issue: string, measurement: Measurement): Promise<false> {
|
|
88
|
+
try {
|
|
89
|
+
await git_gh_command.issue_comment(issue, report(measurement))
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(`Measurement result not posted: ${error_text.message_of(error)}`)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Whether the drive closed the issue by its declaration; `false` launches its lane.
|
|
98
|
+
async function closed(issue: string): Promise<boolean> {
|
|
99
|
+
const declaration = await declared(issue)
|
|
100
|
+
|
|
101
|
+
if (declaration === undefined) return false
|
|
102
|
+
|
|
103
|
+
const measurement = measured(declaration)
|
|
104
|
+
|
|
105
|
+
return measurement.verdict.kind === 'pass'
|
|
106
|
+
? await close_passed(issue, measurement)
|
|
107
|
+
: await hand_over(issue, measurement)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const backlog_measure_close = { closed }
|
|
111
|
+
|
|
112
|
+
export { backlog_measure_close }
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { auto_ok_author } from '#scripts/auto-ok/auto-ok-author'
|
|
2
|
+
import { auto_ok_cli, type OptedInRead } from '#scripts/auto-ok/auto-ok-cli'
|
|
2
3
|
import { repo_discovery } from '#scripts/discovery/repo-discovery'
|
|
3
4
|
import { epic_bundle_gaps } from '#scripts/epic/epic-bundle-gaps'
|
|
4
5
|
import { epic_busy } from '#scripts/epic/epic-busy'
|
|
6
|
+
import type { Classification } from '#scripts/epic/epic-classify'
|
|
5
7
|
import type { EpicChild } from '#scripts/epic/epic-graph'
|
|
6
8
|
import { epic_index } from '#scripts/epic/epic-index'
|
|
7
9
|
import { epic_next } from '#scripts/epic/epic-next'
|
|
@@ -15,12 +17,11 @@ import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
|
15
17
|
import { issue_not_before } from '#scripts/issue/issue-not-before'
|
|
16
18
|
import { issue_not_before_label } from '#scripts/issue/issue-not-before-label'
|
|
17
19
|
import { session_cite } from '#scripts/issue/session-cite'
|
|
18
|
-
import { lane_state } from '#scripts/lane/lane-state'
|
|
19
20
|
import { issue_citation } from '#scripts/rules/issue-citation'
|
|
20
21
|
import { backlog_defect_priority } from './backlog-defect-priority'
|
|
21
|
-
import {
|
|
22
|
+
import { backlog_gate_scope, type OptedIn, type PoolContext } from './backlog-gate-scope'
|
|
22
23
|
import { backlog_pool } from './backlog-pool'
|
|
23
|
-
import { backlog_rank
|
|
24
|
+
import { backlog_rank } from './backlog-rank'
|
|
24
25
|
import { backlog_wait_cause } from './backlog-wait-cause'
|
|
25
26
|
|
|
26
27
|
// `josh backlog:next` — what the whole opted-in backlog may run next.
|
|
@@ -84,17 +85,6 @@ const VERDICT_TOKENS: Readonly<Record<BacklogVerdict, string>> = {
|
|
|
84
85
|
wait: 'wait',
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
type OptedIn = Extract<OptedInRead, { kind: 'read' }>
|
|
88
|
-
type Tracking = Extract<TrackingRead, { kind: 'read' }>
|
|
89
|
-
|
|
90
|
-
// Everything the answer is assembled from, read once and passed down rather than re-fetched.
|
|
91
|
-
interface PoolContext {
|
|
92
|
-
opted_in: OptedIn
|
|
93
|
-
tracking: Tracking
|
|
94
|
-
repo: string
|
|
95
|
-
exclude: ReadonlyArray<number>
|
|
96
|
-
}
|
|
97
|
-
|
|
98
88
|
// One token per line on standard output: the runnable issue numbers of **this** repository, in the
|
|
99
89
|
// order they may be started, or the single verdict word when there is nothing to offer here. Every
|
|
100
90
|
// explanation is on standard error, so `answers=$(pnpm josh backlog:next)` captures something a loop
|
|
@@ -193,14 +183,27 @@ function running_of(
|
|
|
193
183
|
// The two halves as one result. The epic half is already classified by `epic:next`; the standalone
|
|
194
184
|
// half is classified here; the verdict is decided from the merge, so a backlog with a runnable epic
|
|
195
185
|
// child and nothing else says `run` exactly as one with a runnable standalone issue does.
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
186
|
+
// `untrusted` is the epic children an author without write access filed (joshuafolkken/kit#4633).
|
|
187
|
+
function epic_half(
|
|
188
|
+
views: ReadonlyArray<EpicView>,
|
|
189
|
+
context: PoolContext,
|
|
190
|
+
untrusted: ReadonlySet<string>,
|
|
191
|
+
): Classification {
|
|
192
|
+
return backlog_pool.drop_excluded(
|
|
193
|
+
backlog_pool.epic_classification(views, untrusted),
|
|
201
194
|
context.exclude,
|
|
202
195
|
context.repo,
|
|
203
196
|
)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function combine(
|
|
200
|
+
views: ReadonlyArray<EpicView>,
|
|
201
|
+
context: PoolContext,
|
|
202
|
+
untrusted: ReadonlySet<string>,
|
|
203
|
+
): EpicNextResult {
|
|
204
|
+
const graphs = views.map((view) => view.snapshot.children)
|
|
205
|
+
const standalone = backlog_pool.standalone_rows(context.opted_in.issues)
|
|
206
|
+
const from_epics = epic_half(views, context, untrusted)
|
|
204
207
|
const from_standalone = backlog_pool.classify_standalone(standalone, {
|
|
205
208
|
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
206
209
|
exclude: context.exclude,
|
|
@@ -245,10 +248,17 @@ function settled_views(
|
|
|
245
248
|
//
|
|
246
249
|
// The running set covers the standalone rows as well as every read graph, so an epic child waiting on
|
|
247
250
|
// an opted-in standalone issue waits rather than stops.
|
|
248
|
-
function views_from(
|
|
251
|
+
function views_from(
|
|
252
|
+
reads: ReadonlyArray<EpicRead>,
|
|
253
|
+
context: PoolContext,
|
|
254
|
+
untrusted: ReadonlySet<string>,
|
|
255
|
+
): ReadonlyArray<EpicView> {
|
|
249
256
|
if (reads.length === 0) return []
|
|
250
257
|
|
|
251
|
-
const graphs =
|
|
258
|
+
const graphs = backlog_pool.trusted_graphs(
|
|
259
|
+
reads.map((read) => read.snapshot.children),
|
|
260
|
+
untrusted,
|
|
261
|
+
)
|
|
252
262
|
|
|
253
263
|
return settled_views(
|
|
254
264
|
reads,
|
|
@@ -277,11 +287,15 @@ async function resolve(context: PoolContext): Promise<EpicNextResult | undefined
|
|
|
277
287
|
return undefined
|
|
278
288
|
}
|
|
279
289
|
|
|
290
|
+
const untrusted = await auto_ok_author.untrusted_child_keys(
|
|
291
|
+
reads.flatMap((read) => read.snapshot.children),
|
|
292
|
+
context.repo,
|
|
293
|
+
)
|
|
280
294
|
// The defect priority and the ranking keys are applied here rather than when printing, so
|
|
281
295
|
// `backlog:plan` shows the order the run takes. The
|
|
282
296
|
// ranking goes last: its sort is stable, so the defect order survives as its final key.
|
|
283
297
|
const ordered = await backlog_defect_priority.prioritize(
|
|
284
|
-
combine(views_from(reads, context), context),
|
|
298
|
+
combine(views_from(reads, context, untrusted), context, untrusted),
|
|
285
299
|
context.repo,
|
|
286
300
|
)
|
|
287
301
|
|
|
@@ -318,29 +332,6 @@ function report_retry(context: PoolContext): number {
|
|
|
318
332
|
return SUCCESS_EXIT_CODE
|
|
319
333
|
}
|
|
320
334
|
|
|
321
|
-
// The rows the offer's cap bounds — the standalone half.
|
|
322
|
-
function standalone_keys(context: PoolContext): ReadonlySet<string> {
|
|
323
|
-
return backlog_pool.standalone_keys(context.opted_in.issues, {
|
|
324
|
-
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
325
|
-
exclude: context.exclude,
|
|
326
|
-
repo: context.repo,
|
|
327
|
-
})
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// The running lanes still carry the pickup label, so the opted-in listing holds their bodies too —
|
|
331
|
-
// which is what lets a candidate be held back from a path a running lane already declares.
|
|
332
|
-
// `backlog:plan --waves` reads the same scope, so its first wave is this offer. Their lane state
|
|
333
|
-
// records name a paused holder in the wait it causes (joshuafolkken/kit#4270); they are local files.
|
|
334
|
-
async function gate_scope(context: PoolContext): Promise<GateScope> {
|
|
335
|
-
const { issues } = context.opted_in
|
|
336
|
-
|
|
337
|
-
return {
|
|
338
|
-
standalone: standalone_keys(context),
|
|
339
|
-
declared: backlog_overlap.declared_of(issues),
|
|
340
|
-
lanes: await lane_state.read_states(issues.map((issue) => String(issue.number))),
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
335
|
// The `run:solo` gate is applied here rather than in `resolve`, because `backlog:plan` shares
|
|
345
336
|
// `resolve` and a plan made before the run lists everything. The holders are
|
|
346
337
|
// read only on a `run` answer — the one answer the gate can change. The cap follows the gate
|
|
@@ -356,7 +347,7 @@ async function gate_solo(result: EpicNextResult, context: PoolContext): Promise<
|
|
|
356
347
|
|
|
357
348
|
if (notice !== undefined) console.error(notice)
|
|
358
349
|
|
|
359
|
-
const gated = backlog_rank.gate(result, read, repo, await gate_scope(context))
|
|
350
|
+
const gated = backlog_rank.gate(result, read, repo, await backlog_gate_scope.gate_scope(context))
|
|
360
351
|
|
|
361
352
|
if (gated.notice !== undefined) console.error(gated.notice)
|
|
362
353
|
|
|
@@ -470,10 +461,9 @@ const backlog_next = {
|
|
|
470
461
|
READ_FAILURES,
|
|
471
462
|
VERDICT_TOKENS,
|
|
472
463
|
resolve,
|
|
473
|
-
gate_scope,
|
|
474
464
|
context_of,
|
|
475
465
|
run,
|
|
476
466
|
}
|
|
477
467
|
|
|
478
468
|
export { backlog_next }
|
|
479
|
-
export type { BacklogVerdict
|
|
469
|
+
export type { BacklogVerdict }
|
|
@@ -27,8 +27,8 @@ import type { LaneRecords } from '#scripts/lane/lane-state'
|
|
|
27
27
|
// child ended at the hand-off, and while `josh followup` runs the supervisor only polls CI, CodeRabbit
|
|
28
28
|
// and the merge, so the slot is free for the next launch while every merge check still runs. The wait is
|
|
29
29
|
// unmarked while the followup stage merges and gates again (`run-ship-sync.ts`); a stop there counts
|
|
30
|
-
// the lane again, and past the limit the supervisor waits for a place before it
|
|
31
|
-
// (`run-ship-
|
|
30
|
+
// the lane again, and more than one lane past the limit the supervisor waits for a place before it
|
|
31
|
+
// relaunches the child (`run-ship-place.ts`). A named epic's offer discounts the same lanes (`epic-lane-offer.ts`).
|
|
32
32
|
|
|
33
33
|
// The issues whose lane has no child working in it (`lane_spent.idle_lanes`).
|
|
34
34
|
type IdleRead = (lanes: ReadonlyArray<LaneInfo>) => ReadonlyArray<string>
|
|
@@ -17,11 +17,16 @@ import { lane_state, type LaneRecords } from '#scripts/lane/lane-state'
|
|
|
17
17
|
const CODE_SPAN = /`([^`\s]+)`/gu
|
|
18
18
|
const LINE_SUFFIX = /:\d+(?:[-:]\d+)?$/u
|
|
19
19
|
const FILE_EXTENSION = /\.[a-z]\w*$/iu
|
|
20
|
-
|
|
20
|
+
// `properties`: `sonar-project.properties`, which joshuafolkken/kit#5083 and its holder both named
|
|
21
|
+
// and neither declared (joshuafolkken/kit#5107).
|
|
22
|
+
const ROOT_FILE_EXTENSION =
|
|
23
|
+
/\.(?:[cm]?[jt]sx?|svelte|jsonc?|md|ya?ml|css|html|sh|toml|txt|properties)$/u
|
|
21
24
|
const GLOB = '*'
|
|
22
25
|
const ISSUE_MARK = '#'
|
|
23
26
|
const SEPARATOR = '/'
|
|
24
27
|
const MIN_DIRECTORY_DEPTH = 2
|
|
28
|
+
const DOCS_DIRECTORY = 'docs/'
|
|
29
|
+
const MARKDOWN = '.md'
|
|
25
30
|
|
|
26
31
|
// The paths each issue declares, by issue number. A directory ends in `/`; anything else is a file.
|
|
27
32
|
type Declared = ReadonlyMap<number, ReadonlySet<string>>
|
|
@@ -52,9 +57,8 @@ function claim_of(path: string): string | undefined {
|
|
|
52
57
|
return is_file(path) ? path : undefined
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
// The
|
|
56
|
-
function
|
|
57
|
-
const tokens = [...body.matchAll(CODE_SPAN)].map((match) => match[1] ?? '')
|
|
60
|
+
// The files and directories `tokens` claim — a body's code spans, or the paths a lane plans to edit.
|
|
61
|
+
function path_claims(tokens: ReadonlyArray<string>): ReadonlySet<string> {
|
|
58
62
|
const paths = tokens
|
|
59
63
|
.filter((token) => !token.includes(ISSUE_MARK))
|
|
60
64
|
.map((token) => claim_of(without_glob(token.replace(LINE_SUFFIX, ''))))
|
|
@@ -62,6 +66,11 @@ function declared_paths(body: string): ReadonlySet<string> {
|
|
|
62
66
|
return new Set(paths.filter((path) => path !== undefined))
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
// The backticked files and directories `body` declares.
|
|
70
|
+
function declared_paths(body: string): ReadonlySet<string> {
|
|
71
|
+
return path_claims([...body.matchAll(CODE_SPAN)].map((match) => match[1] ?? ''))
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
function declared_of(issues: ReadonlyArray<DeclaringIssue>): Declared {
|
|
66
75
|
return new Map(issues.map((issue) => [issue.number, declared_paths(issue.body ?? '')]))
|
|
67
76
|
}
|
|
@@ -70,7 +79,17 @@ function contains(outer: string, inner: string): boolean {
|
|
|
70
79
|
return outer.endsWith(SEPARATOR) ? inner.startsWith(outer) : outer === inner
|
|
71
80
|
}
|
|
72
81
|
|
|
82
|
+
// A document under `docs/` — a Markdown file or a directory of them. Nearly every issue edits one
|
|
83
|
+
// (`docs/josh-commands-run.md`), and the lane's sync with main resolves the overlap, so holding a lane
|
|
84
|
+
// back for it cost a whole lane each (joshuafolkken/kit#4926). `prompts/` and `.claude/` are the rules
|
|
85
|
+
// themselves and still count.
|
|
86
|
+
function is_shared_document(path: string): boolean {
|
|
87
|
+
return path.startsWith(DOCS_DIRECTORY) && (path.endsWith(SEPARATOR) || path.endsWith(MARKDOWN))
|
|
88
|
+
}
|
|
89
|
+
|
|
73
90
|
function overlaps(left: string, right: string): boolean {
|
|
91
|
+
if (is_shared_document(left) || is_shared_document(right)) return false
|
|
92
|
+
|
|
74
93
|
return contains(left, right) || contains(right, left)
|
|
75
94
|
}
|
|
76
95
|
|
|
@@ -125,12 +144,19 @@ interface Holding {
|
|
|
125
144
|
repo: string
|
|
126
145
|
}
|
|
127
146
|
|
|
147
|
+
// The path of `paths` that one of `holders` already declares — what `lane:plan` yields on.
|
|
148
|
+
function path_clash(
|
|
149
|
+
paths: ReadonlySet<string>,
|
|
150
|
+
declared: Declared,
|
|
151
|
+
holders: ReadonlyArray<number>,
|
|
152
|
+
): Clash | undefined {
|
|
153
|
+
return clash_of(claims_of(declared, holders), paths)
|
|
154
|
+
}
|
|
155
|
+
|
|
128
156
|
// The path `child` declares that one of the running `holders` already declares — the clash `separate`
|
|
129
157
|
// withholds a candidate on, for a reader that names the running issues itself (`run:board`).
|
|
130
158
|
function running_clash(child: EpicChild, declared: Declared, holding: Holding): Clash | undefined {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
return clash_of(claims, paths_of(child, declared, holding.repo))
|
|
159
|
+
return path_clash(paths_of(child, declared, holding.repo), declared, holding.holders)
|
|
134
160
|
}
|
|
135
161
|
|
|
136
162
|
// Whether `waiting` declares a path `holder` declares — the overlap `separate` withholds it on.
|
|
@@ -207,7 +233,15 @@ function separate(
|
|
|
207
233
|
return { offered: walk.offered, withheld, ...(notice !== undefined && { notice }) }
|
|
208
234
|
}
|
|
209
235
|
|
|
210
|
-
const backlog_overlap = {
|
|
236
|
+
const backlog_overlap = {
|
|
237
|
+
declared_of,
|
|
238
|
+
declared_paths,
|
|
239
|
+
holds,
|
|
240
|
+
path_claims,
|
|
241
|
+
path_clash,
|
|
242
|
+
running_clash,
|
|
243
|
+
separate,
|
|
244
|
+
}
|
|
211
245
|
|
|
212
246
|
export { backlog_overlap }
|
|
213
247
|
export type { Clash, Declared }
|
|
@@ -6,6 +6,7 @@ import { backlog_named } from './backlog-named'
|
|
|
6
6
|
import { backlog_next } from './backlog-next'
|
|
7
7
|
import { backlog_plan, type NamedPlan } from './backlog-plan'
|
|
8
8
|
import { backlog_plan_read, type OpenListing, type Plan } from './backlog-plan-read'
|
|
9
|
+
import { backlog_rank } from './backlog-rank'
|
|
9
10
|
import { backlog_scope } from './backlog-scope'
|
|
10
11
|
import { backlog_waves } from './backlog-waves'
|
|
11
12
|
|
|
@@ -105,7 +106,9 @@ function print_plan(plan: Plan, listing: OpenListing, view: PlanView): void {
|
|
|
105
106
|
const scope = { repo: plan.repo, exclude: plan.exclude, tracked: plan.tracked }
|
|
106
107
|
const rows = backlog_scope.out_of_scope(listing.rows, plan.result, scope)
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
const ordered = backlog_rank.offer_order(plan.result, plan.repo, plan.scope.yielded)
|
|
110
|
+
|
|
111
|
+
console.info(backlog_plan.format_plan(ordered, rows, context, view.named))
|
|
109
112
|
}
|
|
110
113
|
|
|
111
114
|
async function report(plan: Plan, view: PlanView): Promise<number> {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
2
|
+
import { has_any_label, PLANNED_LABEL } from '#scripts/issue/issue-labels'
|
|
3
|
+
import { issue_read, type IssueComment } from '#scripts/issue/issue-read'
|
|
4
|
+
import { markdown_section } from '#scripts/issue/markdown-section'
|
|
5
|
+
import { plan_consumers_section } from '#scripts/issue/plan-consumers-section'
|
|
6
|
+
import { lane_plan } from '#scripts/lane/lane-plan'
|
|
7
|
+
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
8
|
+
import { backlog_overlap, type Declared } from './backlog-overlap'
|
|
9
|
+
|
|
10
|
+
// The paths a pool issue declares — the plan a running lane recorded with `lane:plan`, else the plan
|
|
11
|
+
// `issue:plan` posted as a comment, else its body.
|
|
12
|
+
//
|
|
13
|
+
// **A plan replaces the body**: a body cites paths as evidence (joshuafolkken/kit#4937). A plan naming
|
|
14
|
+
// no path leaves the body.
|
|
15
|
+
//
|
|
16
|
+
// **A plan posted as a comment declares paths too.** joshuafolkken/kit#4910's body named none of the
|
|
17
|
+
// files its plan comment did, so dispatch saw no overlap with joshuafolkken/kit#4911 and
|
|
18
|
+
// joshuafolkken/kit#4907, and the lane sat in `lane:plan`'s `wait` for 23 minutes
|
|
19
|
+
// (joshuafolkken/kit#4923). Only a `run:planned` issue is read, so an unplanned pool costs no request,
|
|
20
|
+
// and only a trusted author's comment counts — the same trust `issue:read` applies. A plan is the
|
|
21
|
+
// comment carrying the consumers section `issue:plan` refuses a plan without; the latest one wins.
|
|
22
|
+
// A listing that cannot be read leaves the body alone — the scope dispatch gated on before — and
|
|
23
|
+
// `lane:plan` still holds the lane at its first edit.
|
|
24
|
+
|
|
25
|
+
const PLANNED: ReadonlySet<string> = new Set([PLANNED_LABEL])
|
|
26
|
+
const READ_CONCURRENCY = 8
|
|
27
|
+
|
|
28
|
+
interface PoolIssue {
|
|
29
|
+
number: number
|
|
30
|
+
body?: string | undefined
|
|
31
|
+
labels?: ReadonlyArray<{ name: string }> | undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function is_plan(comment: IssueComment): boolean {
|
|
35
|
+
return (
|
|
36
|
+
comment.is_trusted === true &&
|
|
37
|
+
markdown_section.has_line(comment.body, plan_consumers_section.HEADING)
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The latest trusted plan among `comments`, less its consumers section — whose entries are readers,
|
|
42
|
+
// not edited files — or `undefined` when none is one.
|
|
43
|
+
function plan_of(comments: ReadonlyArray<IssueComment>): string | undefined {
|
|
44
|
+
const plan = comments.findLast((comment) => is_plan(comment))?.body
|
|
45
|
+
|
|
46
|
+
return plan === undefined ? undefined : plan_consumers_section.without(plan)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// The plan comment `issue` carries, or `undefined` when none does or the listing could not be read.
|
|
50
|
+
async function read_plan(issue: number): Promise<string | undefined> {
|
|
51
|
+
const json = await git_gh_issue_read.issue_list_comments(String(issue))
|
|
52
|
+
const comments = await issue_read.parse_comments(json)
|
|
53
|
+
|
|
54
|
+
return comments === undefined ? undefined : plan_of(comments)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// The paths `issue`'s plan comment declares — what `lane:plan` is handed before the first edit.
|
|
58
|
+
async function plan_paths(issue: number): Promise<ReadonlyArray<string>> {
|
|
59
|
+
return [...backlog_overlap.declared_paths((await read_plan(issue)) ?? '')]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function with_plan(issue: PoolIssue): Promise<PoolIssue> {
|
|
63
|
+
if (!has_any_label(issue.labels, PLANNED)) return issue
|
|
64
|
+
|
|
65
|
+
const plan = await read_plan(issue.number)
|
|
66
|
+
|
|
67
|
+
if (plan === undefined || backlog_overlap.declared_paths(plan).size === 0) return issue
|
|
68
|
+
|
|
69
|
+
return { ...issue, body: plan }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// What each of `issues` declares, read from `directory`'s lane plans — the scope dispatch gates on.
|
|
73
|
+
async function declared_of(issues: ReadonlyArray<PoolIssue>, directory: string): Promise<Declared> {
|
|
74
|
+
const planned = await bounded_pool.bounded_map(issues, READ_CONCURRENCY, with_plan)
|
|
75
|
+
|
|
76
|
+
return lane_plan.with_plans(backlog_overlap.declared_of(planned), directory)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const backlog_plan_comment = { declared_of, plan_of, plan_paths }
|
|
80
|
+
|
|
81
|
+
export { backlog_plan_comment }
|
|
@@ -4,8 +4,10 @@ import type { EpicNextResult } from '#scripts/epic/epic-report'
|
|
|
4
4
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
5
5
|
import { open_issue_schema, type OpenIssueData } from '#scripts/git/git-schemas'
|
|
6
6
|
import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { issue_sample_prime } from '#scripts/issue/issue-sample-prime'
|
|
8
|
+
import { lane_capacity } from '#scripts/lane/lane-capacity'
|
|
9
|
+
import { backlog_gate_scope, type OptedIn } from './backlog-gate-scope'
|
|
10
|
+
import { backlog_next } from './backlog-next'
|
|
9
11
|
import type { PlanContext } from './backlog-plan'
|
|
10
12
|
import type { GateScope } from './backlog-rank'
|
|
11
13
|
import { backlog_scope } from './backlog-scope'
|
|
@@ -24,8 +26,8 @@ interface Plan {
|
|
|
24
26
|
// past the listing cap. Carrying the *whole* index here instead would move that misreport rather
|
|
25
27
|
// than remove it: the sentence would name an epic that is withholding nothing.
|
|
26
28
|
tracked: ReadonlyMap<number, number>
|
|
27
|
-
// The rows the offer's cap bounds and the paths each issue declares, so `--waves`
|
|
28
|
-
// wave
|
|
29
|
+
// The rows the offer's cap bounds and the paths each issue declares, so `--waves` separates each
|
|
30
|
+
// wave as `backlog:next` does — and the lane limit it cuts each wave at.
|
|
29
31
|
scope: GateScope
|
|
30
32
|
}
|
|
31
33
|
|
|
@@ -42,6 +44,14 @@ interface PlanRead {
|
|
|
42
44
|
listing: OpenListing
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
// The lane limit a wave is cut at, capped at the port seats as a launch is; `undefined` when the
|
|
48
|
+
// limit cannot be read, so the plan stays drawable and says it is uncapped.
|
|
49
|
+
async function read_wave_limit(): Promise<number | undefined> {
|
|
50
|
+
const choice = await lane_capacity.lane_limit()
|
|
51
|
+
|
|
52
|
+
return choice.kind === 'limit' ? lane_capacity.seated_limit(choice.limit) : undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
// The same reads and the same classification `backlog:next` makes, through the same two functions.
|
|
46
56
|
// `undefined` is a failure it has already reported.
|
|
47
57
|
async function classify(
|
|
@@ -61,7 +71,10 @@ async function classify(
|
|
|
61
71
|
repo: context.repo,
|
|
62
72
|
exclude,
|
|
63
73
|
tracked: epic_index.withheld_children(context.tracking.index, context.opted_in.issues),
|
|
64
|
-
scope:
|
|
74
|
+
scope: {
|
|
75
|
+
...(await backlog_gate_scope.gate_scope(context)),
|
|
76
|
+
wave_limit: await read_wave_limit(),
|
|
77
|
+
},
|
|
65
78
|
}
|
|
66
79
|
}
|
|
67
80
|
|
|
@@ -76,7 +89,7 @@ async function fetch_open(): Promise<OpenListing | undefined> {
|
|
|
76
89
|
const read = read_json_listing(json, open_issue_schema)
|
|
77
90
|
|
|
78
91
|
if (read.kind !== 'read') return undefined
|
|
79
|
-
await
|
|
92
|
+
await issue_sample_prime.prime(read.rows.map((row) => row.body))
|
|
80
93
|
|
|
81
94
|
return { rows: read.rows, is_capped }
|
|
82
95
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { auto_ok_author } from '#scripts/auto-ok/auto-ok-author'
|
|
1
2
|
import { auto_ok_cli } from '#scripts/auto-ok/auto-ok-cli'
|
|
2
3
|
import type { Classification } from '#scripts/epic/epic-classify'
|
|
3
4
|
import { epic_graph, type EpicChild, type GraphAnomaly } from '#scripts/epic/epic-graph'
|
|
@@ -61,13 +62,19 @@ function waits_outside(issue: OpenIssueData, running: ReadonlySet<string>, repo:
|
|
|
61
62
|
.some((blocker) => blocker.state === 'OPEN' && !running.has(epic_graph.blocker_key(blocker)))
|
|
62
63
|
}
|
|
63
64
|
|
|
64
|
-
|
|
65
|
+
// An issue whose author lacks write access waits on a person too: only they can vouch for its body.
|
|
66
|
+
function is_stuck(issue: OpenIssueData, running: ReadonlySet<string>, repo: string): boolean {
|
|
65
67
|
return (
|
|
68
|
+
!auto_ok_author.is_author_trusted(issue) ||
|
|
66
69
|
has_any_label(issue.labels, DECISION_LABELS) ||
|
|
67
|
-
waits_outside(issue,
|
|
70
|
+
waits_outside(issue, running, repo)
|
|
68
71
|
)
|
|
69
72
|
}
|
|
70
73
|
|
|
74
|
+
function needs_person(issue: OpenIssueData, context: StandaloneContext): boolean {
|
|
75
|
+
return is_stuck(issue, context.running, context.repo)
|
|
76
|
+
}
|
|
77
|
+
|
|
71
78
|
// Each open epic's key, read off the tracking index — child number to the epics listing it.
|
|
72
79
|
function epic_keys_of(tracking: TrackingIndex, repo: string): ReadonlySet<string> {
|
|
73
80
|
return new Set([...tracking.values()].flat().map((number) => epic_graph.key_of({ repo, number })))
|
|
@@ -102,10 +109,6 @@ function rooted(
|
|
|
102
109
|
return with_tracking_epics(members, tracking, repo)
|
|
103
110
|
}
|
|
104
111
|
|
|
105
|
-
function is_stuck(issue: OpenIssueData, running: ReadonlySet<string>, repo: string): boolean {
|
|
106
|
-
return has_any_label(issue.labels, DECISION_LABELS) || waits_outside(issue, running, repo)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
112
|
// The running set with every standalone row a person has to resolve taken out, repeated until a pass
|
|
110
113
|
// removes nothing — a row waiting on such a row waits on that person too, however long the chain.
|
|
111
114
|
function settle_standalone(
|
|
@@ -293,6 +296,29 @@ function keys_of(children: ReadonlyArray<EpicChild>): Set<string> {
|
|
|
293
296
|
return new Set(children.map((child) => epic_graph.key_of(child)))
|
|
294
297
|
}
|
|
295
298
|
|
|
299
|
+
// The graphs with every untrusted child taken out before the running set is built from them, so a row
|
|
300
|
+
// blocked by one — standalone or in another epic — waits on a person rather than on time.
|
|
301
|
+
function trusted_graphs(
|
|
302
|
+
graphs: ReadonlyArray<ReadonlyArray<EpicChild>>,
|
|
303
|
+
untrusted: ReadonlySet<string>,
|
|
304
|
+
): Array<Array<EpicChild>> {
|
|
305
|
+
return graphs.map((children) => without(children, untrusted))
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function waits_on(child: EpicChild, held: ReadonlySet<string>): boolean {
|
|
309
|
+
return child.blocked_by.some((blocker) => held.has(epic_graph.blocker_key(blocker)))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// The held keys and, however long the chain, every child waiting on one of them.
|
|
313
|
+
function with_dependants(
|
|
314
|
+
children: ReadonlyArray<EpicChild>,
|
|
315
|
+
held: ReadonlySet<string>,
|
|
316
|
+
): ReadonlySet<string> {
|
|
317
|
+
const grown = new Set([...held, ...keys_of(children.filter((child) => waits_on(child, held)))])
|
|
318
|
+
|
|
319
|
+
return grown.size === held.size ? held : with_dependants(children, grown)
|
|
320
|
+
}
|
|
321
|
+
|
|
296
322
|
// The epic half, already classified. `epic:next` decided each of these — the `blocked-by` graph, the
|
|
297
323
|
// wave, the anomalies — so this only flattens the per-repository bundles back into one list, in the
|
|
298
324
|
// order the epics' own task lists gave them.
|
|
@@ -302,15 +328,26 @@ function keys_of(children: ReadonlyArray<EpicChild>): Set<string> {
|
|
|
302
328
|
// `runnable` — and a child offered on standard output while standard error lists it as waiting is
|
|
303
329
|
// work a loop would start against a dependency that is still standing. So `human` is settled first,
|
|
304
330
|
// `time` next, and `runnable` keeps only what neither claimed.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
331
|
+
//
|
|
332
|
+
// `untrusted` names the children whose author lacks write access (`auto_ok_author.untrusted_child_keys`).
|
|
333
|
+
// Each waits on a person wherever `epic:next` put it, exactly as a standalone row's does in
|
|
334
|
+
// `needs_person`: only a person can vouch for its body (joshuafolkken/kit#4633). A sibling waiting on
|
|
335
|
+
// one waits on that person too — `epic:next` weighs a blocker in the same graph by its own category,
|
|
336
|
+
// never by the running set, so the untrusted child's absence from that set does not reach it.
|
|
337
|
+
function epic_classification(
|
|
338
|
+
views: ReadonlyArray<EpicView>,
|
|
339
|
+
untrusted: ReadonlySet<string>,
|
|
340
|
+
): Classification {
|
|
341
|
+
const waiting = views.flatMap((view) => view.result.waiting)
|
|
311
342
|
const offered = views.flatMap((view) =>
|
|
312
343
|
view.result.candidates.flatMap((bundle) => bundle.children),
|
|
313
344
|
)
|
|
345
|
+
const held = with_dependants(waiting, untrusted)
|
|
346
|
+
const human = unique_children([
|
|
347
|
+
...views.flatMap((view) => view.result.blocked_on_people),
|
|
348
|
+
...[...waiting, ...offered].filter((child) => held.has(epic_graph.key_of(child))),
|
|
349
|
+
])
|
|
350
|
+
const time = without(unique_children(waiting), keys_of(human))
|
|
314
351
|
|
|
315
352
|
return {
|
|
316
353
|
runnable: without(unique_children(offered), keys_of([...human, ...time])),
|
|
@@ -378,6 +415,7 @@ const backlog_pool = {
|
|
|
378
415
|
standalone_rows,
|
|
379
416
|
to_child,
|
|
380
417
|
to_children,
|
|
418
|
+
trusted_graphs,
|
|
381
419
|
}
|
|
382
420
|
|
|
383
421
|
export { backlog_pool }
|