@joshuafolkken/kit 1.1050.0 → 1.1128.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/workflow-commands/SKILL.md +20 -12
- package/.claude/skills/workflow-commands/background-commands.md +36 -84
- package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
- package/.claude/skills/workflow-commands/backlogrun-progress.md +30 -33
- package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -12
- package/.claude/skills/workflow-commands/backlogrun.md +2 -2
- package/.claude/skills/workflow-commands/chain-rule.md +4 -2
- package/.claude/skills/workflow-commands/delegation.md +3 -3
- package/.claude/skills/workflow-commands/followup-reference.md +1 -1
- 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 +8 -6
- package/.claude/skills/workflow-commands/halfrun.md +19 -21
- package/.claude/skills/workflow-commands/issue-comments.md +1 -1
- 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 +8 -16
- package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
- package/.claude/skills/workflow-commands/observation-filing.md +3 -3
- package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
- 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/split-assessment.md +4 -18
- package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
- package/.codex/hooks.json +16 -20
- package/.github/actions/setup-node/action.yml +33 -0
- package/.github/actions/setup-pnpm/action.yml +93 -0
- package/.github/dependabot.yml +5 -1
- package/.github/workflows/auto-tag.yml +2 -3
- package/.github/workflows/ci.yml +31 -134
- package/.github/workflows/dependabot-auto-merge.yml +1 -0
- package/.github/workflows/pr-classification.yml +6 -44
- package/.github/workflows/production.yml +1 -0
- package/.github/workflows/publish.yml +43 -47
- package/.github/workflows/sonar-qube.yml +41 -4
- package/.pnpmfile.mjs +29 -0
- package/AGENTS.md +5 -2
- package/CLAUDE.md +33 -27
- package/GEMINI.md +5 -2
- package/README.md +66 -20
- package/SECURITY.md +37 -6
- package/cspell/index.yaml +6 -1
- package/dist/CLAUDE.basic.md +6 -6
- package/dist/CLAUDE.md +33 -27
- package/dist/CLAUDE.static.md +6 -6
- package/dist/config-merge/index.js +48 -12
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-7VPDUBRN.js → chunk-4JZDP5X5.js} +152 -155
- package/dist/hooks/{chunk-HJIISEAC.js → chunk-5SD2YM7Z.js} +5 -13
- package/dist/hooks/{chunk-NAS4C7GP.js → chunk-77J7IEQM.js} +2 -2
- package/dist/hooks/{chunk-DMQN45FN.js → chunk-7HVB7SZG.js} +3 -3
- package/dist/hooks/{chunk-RLDX5SOC.js → chunk-AIOIOMPX.js} +4413 -1970
- package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M7QKEKWO.js} +873 -2049
- package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-MKVGBQPA.js} +2 -2
- package/dist/hooks/{chunk-EJDX2TOB.js → chunk-NXYMNPUQ.js} +7 -88
- package/dist/hooks/{chunk-NJQOBE6L.js → chunk-QVLT52OV.js} +2 -7
- package/dist/hooks/{chunk-GQ7KP45M.js → chunk-XYUIQOW3.js} +2 -2
- package/dist/hooks/codex-hook-adapter.js +12 -48
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +280 -0
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/session-lang.js +0 -1
- package/dist/hooks/stop-guard.js +192 -333
- package/dist/josh.js +240 -148
- package/dist/managed-marker/index.js +2 -1
- package/dist/version/index.js +70 -78
- package/eslint/rules/promise.js +5 -0
- package/eslint/rules/unicorn.js +3 -2
- package/package.json +26 -5
- package/pnpm-workspace.yaml +5 -7
- package/prompts/collaboration-workflow/glossary.md +17 -0
- package/prompts/collaboration-workflow/issue-citation.md +5 -5
- package/prompts/collaboration-workflow/issue-template.md +1 -1
- package/prompts/collaboration-workflow/operating-rules.md +5 -5
- package/prompts/collaboration-workflow/overview.md +13 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/report-format.md +1 -1
- package/prompts/collaboration-workflow/residency.md +3 -3
- package/prompts/collaboration-workflow/rule-delivery.md +1 -1
- package/prompts/collaboration-workflow/turn-batching.md +3 -3
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +25 -22
- package/prompts/collaboration-workflow.md +6 -8
- package/prompts/review-rubric.md +1 -1
- package/prompts/review.md +3 -3
- package/prompts/sonar-hotspot-handling.md +11 -3
- package/prompts/testing-guide.md +3 -3
- package/scripts/adopt/adopt-toolkits.ts +0 -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 +6 -16
- package/scripts/backlog/backlog-arrival.ts +30 -10
- package/scripts/backlog/backlog-budget-cli.ts +15 -16
- 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 +9 -15
- package/scripts/backlog/backlog-offer-cli.ts +6 -19
- package/scripts/backlog/backlog-plan-cli.ts +1 -7
- package/scripts/backlog/backlog-plan.ts +30 -19
- package/scripts/backlog/backlog-pool.ts +3 -6
- package/scripts/backlog/backlog-rank.ts +2 -2
- package/scripts/backlog/backlog-ready.ts +39 -10
- 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 +5 -2
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/build/build-codex-hooks.ts +26 -0
- package/scripts/build/build-hooks.ts +85 -9
- 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/parse-jsonc.ts +33 -3
- package/scripts/config-merge/patch-json-key.ts +13 -6
- 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 +3 -10
- 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 +0 -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 +6 -10
- package/scripts/doctor/doctor-io.ts +9 -13
- package/scripts/doctor/doctor-logic.ts +0 -4
- package/scripts/doctor/doctor.ts +14 -9
- package/scripts/document/backlogrun-parent-read-set.ts +12 -1
- package/scripts/document/document-byte-budget.ts +5 -5
- 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 +21 -7
- package/scripts/document/entry-read-set.ts +32 -8
- package/scripts/document/lane-child-read-set.ts +8 -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 +9 -3
- package/scripts/document/read-set-pricing.ts +0 -1
- package/scripts/document/read-set-trim.ts +4 -2
- 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 +8 -22
- 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 +9 -8
- 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 +2 -2
- 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 +3 -2
- 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 +13 -10
- 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-issue-write.ts +4 -1
- package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +4 -1
- 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 +6 -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-issue.ts +1 -1
- package/scripts/git/git-preflight.ts +2 -2
- package/scripts/git/git-prompt.ts +6 -31
- package/scripts/git/git-push.ts +1 -1
- package/scripts/git/git-spawn-sync.ts +65 -0
- package/scripts/git/git-spawn.ts +5 -4
- 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 +1 -0
- 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} +2 -7
- 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-file.ts +2 -0
- package/scripts/hooks/pre-push-unit.ts +0 -4
- package/scripts/hooks/pretool-guard.ts +22 -4
- 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-file-action.ts +54 -0
- package/scripts/init/init-logic-migrate.ts +35 -17
- package/scripts/init/init-logic-secretlint.ts +1 -1
- package/scripts/init/init-logic.ts +10 -19
- package/scripts/init/init.ts +11 -71
- package/scripts/init/kit-written-paths.ts +2 -0
- package/scripts/init/project-profile.ts +9 -17
- package/scripts/init/start-exec.ts +1 -1
- package/scripts/init/start-setup-pr.ts +6 -6
- package/scripts/init/start-steps.ts +3 -1
- package/scripts/issue/behavior-change-lint.ts +0 -1
- package/scripts/issue/defect-rate-cli.ts +64 -23
- package/scripts/issue/defect-rate.ts +1 -2
- package/scripts/{git → issue}/git-next-issues.ts +3 -3
- package/scripts/issue/issue-backlinks-cli.ts +1 -5
- package/scripts/issue/issue-backlinks.ts +7 -14
- package/scripts/issue/issue-cite-cli.ts +2 -6
- package/scripts/issue/issue-cite.ts +12 -8
- 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 +7 -14
- 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 +8 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-merged.ts +2 -2
- package/scripts/{git → issue}/issue-rank.ts +1 -1
- 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 +21 -6
- package/scripts/issue/measure-rerun-cli.ts +74 -15
- 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 -0
- 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 +8 -1
- 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 +3 -3
- package/scripts/josh/path-decision.ts +0 -3
- package/scripts/josh/process-owner.ts +16 -0
- package/scripts/josh/run-github-prerequisite.ts +3 -6
- package/scripts/josh/session-language-cli.ts +0 -1
- package/scripts/lane/lane-await.ts +46 -19
- package/scripts/lane/lane-capacity.ts +6 -3
- package/scripts/lane/lane-child-invocation.ts +20 -7
- package/scripts/lane/lane-cli.ts +1 -4
- package/scripts/lane/lane-close.ts +5 -4
- 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 +31 -27
- 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/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 +7 -1
- package/scripts/lib/bounded-pool.ts +1 -0
- package/scripts/lib/cli-flags.ts +31 -2
- package/scripts/lib/error-message.ts +12 -1
- 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/line-targets.ts +0 -11
- package/scripts/lines/lines-command.ts +5 -4
- 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 +3 -10
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +0 -2
- package/scripts/propagate/propagate-steps.ts +3 -5
- package/scripts/propagate/propagate-targets.ts +0 -4
- package/scripts/propagate/propagate.ts +0 -4
- package/scripts/refactor/import-graph.ts +0 -1
- package/scripts/refactor/refactor-lint.ts +0 -2
- package/scripts/refactor/refactor-scan.ts +2 -2
- package/scripts/refactor/refactor-targets.ts +0 -1
- package/scripts/registry-migration/migrate-logic.ts +28 -21
- package/scripts/registry-migration/migrate.ts +25 -14
- package/scripts/release/github-release-cli.ts +19 -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 +38 -5
- package/scripts/release/release-scope-cli.ts +1 -2
- package/scripts/release/release-tag.ts +2 -4
- package/scripts/release/release-worktree.ts +97 -2
- 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 +4 -16
- package/scripts/review/review-brief-cli.ts +23 -6
- package/scripts/review/review-brief.ts +21 -8
- package/scripts/review/review-checkout.ts +3 -2
- 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 +10 -17
- package/scripts/review/review-record.ts +0 -1
- package/scripts/review/review-round2-cli.ts +1 -1
- package/scripts/review/review-stamps.ts +0 -3
- 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/early-heartbeat.ts +4 -3
- 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 +0 -1
- package/scripts/rules/index-guard.ts +71 -0
- package/scripts/rules/issue-citation.ts +50 -25
- package/scripts/rules/lane-background.ts +15 -7
- package/scripts/rules/lane-park.ts +22 -6
- 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/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 +20 -9
- 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-args.ts +8 -12
- 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-args.ts +1 -6
- package/scripts/run/run-cut-cli.ts +0 -7
- package/scripts/run/run-cut.ts +8 -54
- package/scripts/run/run-ending-cli.ts +2 -6
- package/scripts/run/run-ending.ts +1 -4
- package/scripts/run/run-entry-cli.ts +133 -25
- package/scripts/run/run-entry-stop.ts +104 -0
- 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-emit.ts +7 -2
- 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 +2 -2
- package/scripts/run/run-hold-cli.ts +33 -10
- package/scripts/run/run-hold.ts +29 -6
- package/scripts/run/run-issue-number.ts +1 -1
- package/scripts/run/run-liveness-cli.ts +2 -6
- package/scripts/run/run-liveness.ts +2 -3
- package/scripts/run/run-merge-cli.ts +7 -23
- 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 +4 -2
- package/scripts/run/run-preflight.ts +2 -9
- package/scripts/run/run-prep-cli.ts +6 -3
- package/scripts/run/run-prep-locate.ts +1 -1
- package/scripts/run/run-progress-args.ts +20 -4
- package/scripts/run/run-progress-cli.ts +35 -36
- package/scripts/run/run-progress-clock.ts +10 -35
- package/scripts/run/run-progress-config.ts +0 -4
- package/scripts/run/run-progress-read.ts +1 -2
- package/scripts/run/run-progress.ts +1 -2
- 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 +29 -19
- 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 +1 -1
- package/scripts/run/run-ship-probe.ts +4 -1
- package/scripts/run/run-ship-return.ts +8 -3
- package/scripts/run/run-ship-review-steps.ts +18 -4
- package/scripts/run/run-ship-review.ts +11 -0
- package/scripts/run/run-ship-scoped.ts +1 -0
- package/scripts/run/run-ship-steps.ts +1 -1
- package/scripts/run/run-ship.ts +0 -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 +3 -16
- 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 +6 -2
- package/scripts/run/run-tidy-stashes.ts +12 -12
- package/scripts/run/run-wake-cli.ts +4 -13
- 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 +18 -12
- package/scripts/run/run-watcher-hook.ts +1 -1
- package/scripts/safe-chain/ci-installer-pin.ts +11 -5
- package/scripts/safe-chain/pack-hook.ts +92 -0
- 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-ai-files.ts +4 -0
- 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-changed.ts +13 -16
- package/scripts/test/test-declared-logic.ts +0 -1
- package/scripts/test/test-declared.ts +3 -9
- 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 +0 -1
- 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 +2 -2
- 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 +11 -1
- package/scripts/version/version-remote.ts +3 -3
- package/scripts/version/version-targets.ts +4 -4
- package/templates/CLAUDE.basic.md +6 -6
- package/templates/sonar-project.properties +28 -1
- package/templates/workflows/ci.yml +16 -82
- package/templates/workflows/dependabot-auto-merge.yml +6 -3
- package/templates/workflows/github-release.yml +79 -0
- package/tsconfig.sonar.json +4 -22
- 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.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
|
@@ -3,19 +3,19 @@ import { fileURLToPath } from 'node:url'
|
|
|
3
3
|
import { epic_bundle_gaps } from '#scripts/epic/epic-bundle-gaps'
|
|
4
4
|
import { epic_index, type FetchedEpics } from '#scripts/epic/epic-index'
|
|
5
5
|
import { epic_issue } from '#scripts/epic/epic-issue'
|
|
6
|
-
import { git_gh_command } from '#scripts/
|
|
7
|
-
import { SUMMARY_FIELDS } from '#scripts/
|
|
8
|
-
import { git_next_issues } from '#scripts/git/git-next-issues'
|
|
9
|
-
import { AUTO_OK_LABEL } from '#scripts/git/issue-labels'
|
|
6
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
7
|
+
import { SUMMARY_FIELDS } from '#scripts/gh/git-gh-issue'
|
|
10
8
|
import { cutoff_cause, cutoff_of, type ScanCutoff } from '#scripts/git/listing-cutoff'
|
|
11
9
|
import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
12
10
|
import { open_issue_schema, type OpenIssueData } from '#scripts/git/schemas'
|
|
11
|
+
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
12
|
+
import { AUTO_OK_LABEL } from '#scripts/issue/issue-labels'
|
|
13
13
|
|
|
14
14
|
// `josh auto-ok:next` — which issue outside the epic an unattended run picks up next
|
|
15
15
|
// (joshuafolkken/kit#906).
|
|
16
16
|
//
|
|
17
17
|
// A command rather than a documented `gh` invocation, for the reason the label constant exists: the
|
|
18
|
-
// name `auto-ok` is single-sourced in `scripts/
|
|
18
|
+
// name `auto-ok` is single-sourced in `scripts/issue/issue-labels.ts`, and a procedure that told an
|
|
19
19
|
// agent to type `gh issue list --label auto-ok` would put a second copy of it in prose, where
|
|
20
20
|
// nothing checks it. The contract is `epic:next`'s: one token on standard output, every explanation
|
|
21
21
|
// on standard error, so `answer=$(pnpm josh auto-ok:next)` reads it.
|
|
@@ -48,7 +48,7 @@ const LISTING_LIMIT = 200
|
|
|
48
48
|
// CLI's version cannot be what changed the row shape — the same misdirection the message below
|
|
49
49
|
// already refuses to repeat for the blocker relations, left standing one constant above it.
|
|
50
50
|
const UNREADABLE_MESSAGE = `Could not read the \`${AUTO_OK_LABEL}\` listing. That is not "nothing is opted in" — check \`gh auth status\` and ask again.`
|
|
51
|
-
const UNEXPECTED_SHAPE_MESSAGE = `Read the \`${AUTO_OK_LABEL}\` listing but could not parse it. That is not "nothing is opted in" — the rows came back in a shape this command does not recognize, so check the fields it asks for and the REST field mapping in \`scripts/
|
|
51
|
+
const UNEXPECTED_SHAPE_MESSAGE = `Read the \`${AUTO_OK_LABEL}\` listing but could not parse it. That is not "nothing is opted in" — the rows came back in a shape this command does not recognize, so check the fields it asks for and the REST field mapping in \`scripts/gh/git-gh-issue-rest.ts\` rather than your authentication.`
|
|
52
52
|
// The blocker relations failing takes the whole listing with them, and `issue_list` swallows
|
|
53
53
|
// the error — so the read looks exactly like an access failure and sends the reader to
|
|
54
54
|
// `gh auth status`, which is green. That is the misdirection joshuafolkken/kit#996 added the message
|
|
@@ -491,23 +491,13 @@ const auto_ok_cli = {
|
|
|
491
491
|
TRUNCATED_WITHOUT_ANSWER,
|
|
492
492
|
NONE_OPTED_IN_MESSAGE,
|
|
493
493
|
truncated_cause,
|
|
494
|
-
parse_issue_number,
|
|
495
|
-
parse_exclude,
|
|
496
|
-
parse_pair,
|
|
497
494
|
parse_options,
|
|
498
495
|
fetch_opted_in,
|
|
499
|
-
parse_listing,
|
|
500
|
-
is_page_complete,
|
|
501
|
-
is_closed,
|
|
502
|
-
is_unblocked,
|
|
503
496
|
fetch_tracking,
|
|
504
497
|
is_runnable,
|
|
505
498
|
pick_next,
|
|
506
499
|
truncation_note,
|
|
507
|
-
none_reason,
|
|
508
|
-
report,
|
|
509
500
|
run,
|
|
510
|
-
main,
|
|
511
501
|
}
|
|
512
502
|
|
|
513
503
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
@@ -18,10 +18,11 @@ import { backlog_stalled } from './backlog-stalled'
|
|
|
18
18
|
//
|
|
19
19
|
// **"New" is measured against the watcher's own start**, so one issue wakes the parent once: the next
|
|
20
20
|
// `--wait` the parent starts takes the pool as it stands then — the woken issue included, dispatched or
|
|
21
|
-
// not — as its baseline. A reading that fails is not an arrival; the probe says nothing and
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
//
|
|
21
|
+
// not — as its baseline. A reading that fails is not an arrival; the probe says nothing and reads again
|
|
22
|
+
// a minute later. A baseline that cannot be read is never read as empty — an empty one would wake the
|
|
23
|
+
// parent for the whole pool — but it is not given up on either: the scheduled report no longer ends the
|
|
24
|
+
// wait (joshuafolkken/kit#3102), so an inert probe would leave the parent without a wake until `--hours`. The
|
|
25
|
+
// probe reads the baseline again each minute until one answers.
|
|
25
26
|
//
|
|
26
27
|
// **Every read is bounded.** The probe is awaited inside the watcher's tick loop, so a `gh` call that
|
|
27
28
|
// hangs would otherwise freeze the loop — its `--hours` bound, its liveness ping and the exit that is
|
|
@@ -116,19 +117,40 @@ async function never_arrives(): Promise<boolean> {
|
|
|
116
117
|
|
|
117
118
|
const INERT: ArrivalProbe = { has_arrived: never_arrives }
|
|
118
119
|
|
|
119
|
-
//
|
|
120
|
+
// A probe spent on the baseline reports no arrival, whether or not the baseline answered.
|
|
121
|
+
async function retry_baseline(
|
|
122
|
+
answered: Array<ReadonlySet<string>>,
|
|
123
|
+
ports: ReadyPorts,
|
|
124
|
+
): Promise<boolean> {
|
|
125
|
+
const late = await read_baseline(ports)
|
|
126
|
+
|
|
127
|
+
if (late !== undefined) answered.push(late)
|
|
128
|
+
|
|
129
|
+
return false
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The next-probe instant is set before any read is awaited. A baseline that did not answer is read again
|
|
133
|
+
// at the next probe instead of the reading, and the first one that answers is the baseline from then on
|
|
134
|
+
// — never an arrival itself, since it is the pool as it stands.
|
|
120
135
|
function probe_of(
|
|
121
|
-
|
|
136
|
+
initial: ReadonlySet<string> | undefined,
|
|
122
137
|
first_ms: number,
|
|
123
138
|
ports: ReadyPorts,
|
|
124
139
|
): ArrivalProbe {
|
|
125
140
|
let next_ms = first_ms
|
|
141
|
+
// At most one entry, held in a list so the baseline that answers after an await is added rather than
|
|
142
|
+
// reassigned over the value read before it.
|
|
143
|
+
const answered: Array<ReadonlySet<string>> = initial === undefined ? [] : [initial]
|
|
126
144
|
|
|
127
145
|
async function has_arrived(now_ms: number): Promise<boolean> {
|
|
128
146
|
if (now_ms < next_ms) return false
|
|
129
147
|
|
|
130
148
|
next_ms = now_ms + PROBE_INTERVAL_MS
|
|
131
149
|
|
|
150
|
+
const [baseline] = answered
|
|
151
|
+
|
|
152
|
+
if (baseline === undefined) return await retry_baseline(answered, ports)
|
|
153
|
+
|
|
132
154
|
const reading = await read_reading(ports)
|
|
133
155
|
|
|
134
156
|
return reading !== undefined && arrivals(baseline, reading).length > NONE
|
|
@@ -146,12 +168,10 @@ async function start(
|
|
|
146
168
|
): Promise<ArrivalProbe> {
|
|
147
169
|
if (!(await is_parent_safely(is_parent))) return INERT
|
|
148
170
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
return baseline === undefined ? INERT : probe_of(baseline, now_ms + PROBE_INTERVAL_MS, ports)
|
|
171
|
+
return probe_of(await read_baseline(ports), now_ms + PROBE_INTERVAL_MS, ports)
|
|
152
172
|
}
|
|
153
173
|
|
|
154
|
-
const backlog_arrival = {
|
|
174
|
+
const backlog_arrival = { PROBE_INTERVAL_MS, answered_issues, arrivals, start }
|
|
155
175
|
|
|
156
176
|
export type { ArrivalProbe }
|
|
157
177
|
export { backlog_arrival }
|
|
@@ -32,11 +32,7 @@ type ParsedValues = Partial<Record<OptionName, string | boolean>>
|
|
|
32
32
|
// A misspelled flag is refused rather than defaulted, the contract `path_decision.has_unknown_flag`
|
|
33
33
|
// states for the path-decided commands: an invocation nobody can read is never answered.
|
|
34
34
|
function read_arguments(argv: ReadonlyArray<string>): ParsedValues | undefined {
|
|
35
|
-
return cli_flags.
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function text_of(value: string | boolean | undefined): string | undefined {
|
|
39
|
-
return typeof value === 'string' ? value : undefined
|
|
35
|
+
return cli_flags.values_of(argv, OPTIONS)
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
// `find` rather than a cast: an unrecognized word has to be refused, and a type assertion would
|
|
@@ -79,15 +75,15 @@ type Counts = Record<(typeof COUNT_NAMES)[number], number | undefined>
|
|
|
79
75
|
|
|
80
76
|
function counts_of(values: ParsedValues): Counts {
|
|
81
77
|
return {
|
|
82
|
-
idle: to_count(
|
|
83
|
-
max: to_count(
|
|
84
|
-
merged: to_count(
|
|
85
|
-
running: to_count(
|
|
78
|
+
idle: to_count(cli_flags.string_of(values.idle)),
|
|
79
|
+
max: to_count(cli_flags.string_of(values.max)),
|
|
80
|
+
merged: to_count(cli_flags.string_of(values.merged)),
|
|
81
|
+
running: to_count(cli_flags.string_of(values.running)),
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
|
|
89
85
|
function are_counts_readable(values: ParsedValues, counts: Counts): boolean {
|
|
90
|
-
return COUNT_NAMES.every((name) => is_readable(
|
|
86
|
+
return COUNT_NAMES.every((name) => is_readable(cli_flags.string_of(values[name]), counts[name]))
|
|
91
87
|
}
|
|
92
88
|
|
|
93
89
|
// **`--idle 0` is how the watch is turned off, and omitting the flag takes the default**
|
|
@@ -116,14 +112,17 @@ function to_idle_ms(idle_minutes: number | undefined): number | undefined {
|
|
|
116
112
|
// lands on the very first ask, before the run has started anything, and the fix is one flag the loop
|
|
117
113
|
// already holds: it always knows when it last had work.
|
|
118
114
|
function is_watch_readable(values: ParsedValues): boolean {
|
|
119
|
-
if (to_idle_ms(to_count(
|
|
115
|
+
if (to_idle_ms(to_count(cli_flags.string_of(values.idle))) === undefined) return true
|
|
120
116
|
|
|
121
|
-
return
|
|
117
|
+
return cli_flags.string_of(values.active) !== undefined
|
|
122
118
|
}
|
|
123
119
|
|
|
124
120
|
function are_values_readable(values: ParsedValues): boolean {
|
|
125
121
|
return (
|
|
126
|
-
is_readable(
|
|
122
|
+
is_readable(
|
|
123
|
+
cli_flags.string_of(values.active),
|
|
124
|
+
to_time_ms(cli_flags.string_of(values.active)),
|
|
125
|
+
) &&
|
|
127
126
|
is_watch_readable(values) &&
|
|
128
127
|
are_counts_readable(values, counts_of(values))
|
|
129
128
|
)
|
|
@@ -138,7 +137,7 @@ function input_of(values: ParsedValues, base: InputBase): BudgetInput {
|
|
|
138
137
|
|
|
139
138
|
return {
|
|
140
139
|
...base,
|
|
141
|
-
active_at_ms: to_time_ms(
|
|
140
|
+
active_at_ms: to_time_ms(cli_flags.string_of(values.active)) ?? base.started_at_ms,
|
|
142
141
|
merged: counts.merged ?? 0,
|
|
143
142
|
running: counts.running ?? 0,
|
|
144
143
|
max_issues: counts.max,
|
|
@@ -147,11 +146,11 @@ function input_of(values: ParsedValues, base: InputBase): BudgetInput {
|
|
|
147
146
|
}
|
|
148
147
|
|
|
149
148
|
function build_input(values: ParsedValues, now_ms: number): BudgetInput | undefined {
|
|
150
|
-
const answer = to_answer(
|
|
149
|
+
const answer = to_answer(cli_flags.string_of(values.answer))
|
|
151
150
|
|
|
152
151
|
if (answer === undefined) return undefined
|
|
153
152
|
|
|
154
|
-
const started_at_ms = to_time_ms(
|
|
153
|
+
const started_at_ms = to_time_ms(cli_flags.string_of(values.started))
|
|
155
154
|
|
|
156
155
|
if (started_at_ms === undefined) return undefined
|
|
157
156
|
if (!are_values_readable(values)) return undefined
|
|
@@ -268,7 +268,6 @@ function decide(input: BudgetInput): BudgetDecision {
|
|
|
268
268
|
|
|
269
269
|
const backlog_budget = {
|
|
270
270
|
ANSWERS,
|
|
271
|
-
ANSWER_STOP_REASONS,
|
|
272
271
|
BLOCKED_REASON,
|
|
273
272
|
DEFAULT_IDLE_MINUTES,
|
|
274
273
|
DEFAULT_IDLE_MS,
|
|
@@ -283,7 +282,6 @@ const backlog_budget = {
|
|
|
283
282
|
UNREADABLE_REASON,
|
|
284
283
|
WATCH_VERDICT,
|
|
285
284
|
WHOLE_RUN_BUDGET_HOURS,
|
|
286
|
-
WHOLE_RUN_BUDGET_MINUTES,
|
|
287
285
|
WHOLE_RUN_BUDGET_MS,
|
|
288
286
|
WHOLE_RUN_REASON,
|
|
289
287
|
decide,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EpicChild } from '#scripts/epic/epic-graph'
|
|
2
2
|
import type { EpicNextResult, RepoCandidates } from '#scripts/epic/epic-report'
|
|
3
|
-
import { git_gh_command } from '#scripts/
|
|
3
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
4
4
|
import { defect_rate, type DefectRate, type IssueKind } from '#scripts/issue/defect-rate'
|
|
5
5
|
import { defect_rate_cli } from '#scripts/issue/defect-rate-cli'
|
|
6
6
|
|
|
@@ -72,6 +72,6 @@ async function prioritize(
|
|
|
72
72
|
return await reorder(result, repo)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const backlog_defect_priority = { UNMEASURED_MESSAGE,
|
|
75
|
+
const backlog_defect_priority = { UNMEASURED_MESSAGE, prioritize }
|
|
76
76
|
|
|
77
77
|
export { backlog_defect_priority }
|
|
@@ -5,13 +5,13 @@ import { CONTEXT_CUT_THRESHOLD } from '#scripts/cost-runtime/context-cut-thresho
|
|
|
5
5
|
import { hook_decision } from '#scripts/josh/hook-decision'
|
|
6
6
|
import { josh_command } from '#scripts/josh/josh-run'
|
|
7
7
|
import { lane_await, type AwaitState } from '#scripts/lane/lane-await'
|
|
8
|
-
import { lane_launch_cli } from '#scripts/lane/lane-launch-cli'
|
|
8
|
+
import { lane_launch_cli, type LaunchOutcome } from '#scripts/lane/lane-launch-cli'
|
|
9
9
|
import { lane_registry } from '#scripts/lane/lane-registry'
|
|
10
10
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
11
11
|
import { error_text } from '#scripts/lib/error-message'
|
|
12
12
|
import { run_carry, type RunCarry } from '#scripts/run/run-carry'
|
|
13
13
|
import { run_event_stream_emit } from '#scripts/run/run-event-stream-emit'
|
|
14
|
-
import { run_merge_cli } from '#scripts/run/run-merge-cli'
|
|
14
|
+
import { run_merge_cli, type MergeResult } from '#scripts/run/run-merge-cli'
|
|
15
15
|
import { z } from 'zod'
|
|
16
16
|
import {
|
|
17
17
|
backlog_drive,
|
|
@@ -28,6 +28,7 @@ import { backlog_drive_owner } from './backlog-drive-owner'
|
|
|
28
28
|
import { backlog_drive_restore } from './backlog-drive-restore'
|
|
29
29
|
import { backlog_drive_retrospective } from './backlog-drive-retrospective'
|
|
30
30
|
import { backlog_offer_cli } from './backlog-offer-cli'
|
|
31
|
+
import { backlog_ready } from './backlog-ready'
|
|
31
32
|
|
|
32
33
|
// `josh backlog:drive` — the backlogrun parent's loop as one resident wait (joshuafolkken/kit#2499).
|
|
33
34
|
// The parent issues it once, in the background, and is woken only when it exits — with a token the model
|
|
@@ -217,7 +218,7 @@ function merge_token(out: string, code: number): string {
|
|
|
217
218
|
|
|
218
219
|
// The child's transcript, where its lane recorded one, so `run:merge` can tell an API outage from a
|
|
219
220
|
// failure exactly as it does for the parent that passes `--output` by hand.
|
|
220
|
-
async function merge(issue: string, owner: string): Promise<
|
|
221
|
+
async function merge(issue: string, owner: string): Promise<MergeResult> {
|
|
221
222
|
await backlog_drive_owner.assert_current(owner)
|
|
222
223
|
const lane = await lane_registry.find_open_lane(issue)
|
|
223
224
|
const result = await run_merge_cli.merge_child({
|
|
@@ -231,13 +232,15 @@ async function merge(issue: string, owner: string): Promise<string> {
|
|
|
231
232
|
|
|
232
233
|
await backlog_drive_named.mark_done(issue, result, owner)
|
|
233
234
|
|
|
234
|
-
return result
|
|
235
|
+
return result
|
|
235
236
|
}
|
|
236
237
|
|
|
237
|
-
async function launch(issue: string, owner: string): Promise<
|
|
238
|
+
async function launch(issue: string, owner: string): Promise<LaunchOutcome['kind']> {
|
|
238
239
|
await backlog_drive_owner.assert_current(owner)
|
|
239
240
|
|
|
240
|
-
|
|
241
|
+
const outcome = await lane_launch_cli.launch_lane({ issue, stash: undefined })
|
|
242
|
+
|
|
243
|
+
return outcome.kind
|
|
241
244
|
}
|
|
242
245
|
|
|
243
246
|
// `lane:await`'s re-confirmed check, one state per child. A child already gone when the loop starts —
|
|
@@ -304,6 +307,7 @@ function ports_of(
|
|
|
304
307
|
merge: async (issue) => await merge(issue, context.owner),
|
|
305
308
|
offer: async (state) => await read_offer(state, context),
|
|
306
309
|
launch: async (issue) => await launch(issue, context.owner),
|
|
310
|
+
free_lanes: backlog_ready.drive_free_lane_count,
|
|
307
311
|
now: () => new Date(),
|
|
308
312
|
sleep: async (milliseconds) => {
|
|
309
313
|
await sleep(milliseconds)
|
|
@@ -375,14 +379,12 @@ async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
|
375
379
|
}
|
|
376
380
|
|
|
377
381
|
const backlog_drive_cli = {
|
|
378
|
-
USAGE,
|
|
379
382
|
end_line,
|
|
380
383
|
finish: backlog_drive_finish.finish,
|
|
381
384
|
merge_token,
|
|
382
385
|
offer_argv: backlog_drive_offer_argv.offer_argv,
|
|
383
386
|
parse,
|
|
384
387
|
resume_line,
|
|
385
|
-
run,
|
|
386
388
|
to_offer,
|
|
387
389
|
}
|
|
388
390
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { EPIC_LABEL, has_label_name } from '#scripts/
|
|
1
|
+
import { EPIC_LABEL, has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
2
|
+
import type { IssueState } from '#scripts/issue/issue-state'
|
|
2
3
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
3
4
|
import type { RunCarry } from '#scripts/run/run-carry'
|
|
5
|
+
import type { MergeResult } from '#scripts/run/run-merge-cli'
|
|
4
6
|
import { backlog_budget } from './backlog-budget'
|
|
5
7
|
import type { DriveState, OfferRead } from './backlog-drive'
|
|
6
8
|
import { backlog_drive_named } from './backlog-drive-named'
|
|
@@ -44,6 +46,15 @@ function budget_offer(
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
// The outcome a named issue has already reached without this run dispatching it: closed is merged, and
|
|
50
|
+
// a `needs-decision` park waits on a person, so re-dispatching it only repeats the stop it parked on
|
|
51
|
+
// (joshuafolkken/kit#2965). Either is booked done rather than offered.
|
|
52
|
+
function settled_outcome(state: IssueState): MergeResult['outcome'] | undefined {
|
|
53
|
+
if (state.state.toUpperCase() === 'CLOSED') return 'merged'
|
|
54
|
+
|
|
55
|
+
return has_label_name(state.labels, NEEDS_DECISION_LABEL) ? 'parked' : undefined
|
|
56
|
+
}
|
|
57
|
+
|
|
47
58
|
async function classify(issue: string, named: OfferRead, owner: string): Promise<OfferRead> {
|
|
48
59
|
const result = await issue_state_cli.read_issue(issue)
|
|
49
60
|
|
|
@@ -51,8 +62,10 @@ async function classify(issue: string, named: OfferRead, owner: string): Promise
|
|
|
51
62
|
return { verdict: 'issue-state', issues: [], retries: NO_RETRIES }
|
|
52
63
|
}
|
|
53
64
|
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
const outcome = settled_outcome(result.state)
|
|
66
|
+
|
|
67
|
+
if (outcome !== undefined) {
|
|
68
|
+
await backlog_drive_named.mark_done(issue, { outcome, code: 0, token: 'none' }, owner)
|
|
56
69
|
|
|
57
70
|
return { verdict: 'wait', issues: [], retries: NO_RETRIES }
|
|
58
71
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { has_label_name, NEEDS_DECISION_LABEL } from '#scripts/
|
|
1
|
+
import { has_label_name, NEEDS_DECISION_LABEL } from '#scripts/issue/issue-labels'
|
|
2
2
|
import { issue_state_cli } from '#scripts/issue/issue-state-cli'
|
|
3
3
|
import { run_carry, type RunCarry } from '#scripts/run/run-carry'
|
|
4
4
|
import type { RunEvent } from '#scripts/run/run-event-stream'
|
|
@@ -94,6 +94,7 @@ async function reconcile(
|
|
|
94
94
|
for (const issue of completed) {
|
|
95
95
|
const outcome = parked.has(issue) ? 'parked' : 'merged'
|
|
96
96
|
|
|
97
|
+
// eslint-disable-next-line no-await-in-loop -- each mark rewrites the same carry file
|
|
97
98
|
await mark_done(String(issue), { outcome, code: 0, token: 'none' }, owner)
|
|
98
99
|
}
|
|
99
100
|
}
|
|
@@ -16,6 +16,9 @@
|
|
|
16
16
|
// **Everything it touches is a port**, the pattern `run-wake-loop.ts` set, so the sequencing is pinned
|
|
17
17
|
// without a process, a network or a clock.
|
|
18
18
|
|
|
19
|
+
import type { LaunchOutcome } from '#scripts/lane/lane-launch-cli'
|
|
20
|
+
import type { MergeResult } from '#scripts/run/run-merge-cli'
|
|
21
|
+
|
|
19
22
|
const RUN_VERDICT = 'run'
|
|
20
23
|
const STOP_VERDICT = 'stop'
|
|
21
24
|
// The `run:merge` tokens that end the loop at once: a hand-off, a person's stop, the environment down,
|
|
@@ -32,6 +35,7 @@ const IMMEDIATE_TOKENS: ReadonlySet<string> = new Set([
|
|
|
32
35
|
// and the children still in flight are collected before the loop ends (joshuafolkken/kit#2881).
|
|
33
36
|
const HANDOFF_TOKENS: ReadonlySet<string> = new Set([...IMMEDIATE_TOKENS, STOP_VERDICT])
|
|
34
37
|
const RESUMED_TOKEN = 'resumed'
|
|
38
|
+
const MERGED_OUTCOME = 'merged'
|
|
35
39
|
const WATCH_VERDICT = 'watch'
|
|
36
40
|
// The verdicts the loop acts on without the parent. Any other is handed back as it was printed.
|
|
37
41
|
const KNOWN_VERDICTS: ReadonlySet<string> = new Set([
|
|
@@ -41,6 +45,9 @@ const KNOWN_VERDICTS: ReadonlySet<string> = new Set([
|
|
|
41
45
|
'wait',
|
|
42
46
|
])
|
|
43
47
|
const NO_RETRIES = 0
|
|
48
|
+
const NO_FREE_LANES = 0
|
|
49
|
+
const LAUNCHED = 'launched'
|
|
50
|
+
const UNOPENED = 'unopened'
|
|
44
51
|
|
|
45
52
|
interface OfferRead {
|
|
46
53
|
verdict: string
|
|
@@ -57,7 +64,9 @@ interface OfferRead {
|
|
|
57
64
|
interface DriveState {
|
|
58
65
|
// The children this run has in flight — seeded from the open lanes, so a restarted loop resumes them.
|
|
59
66
|
in_flight: Array<string>
|
|
60
|
-
// Every child
|
|
67
|
+
// Every child merged, fed back to `backlog:offer` because GitHub closes a merged issue late. A parked
|
|
68
|
+
// child is left out: its labels classify it, so one a person released is offered again
|
|
69
|
+
// (joshuafolkken/kit#3041).
|
|
61
70
|
exclude: Array<string>
|
|
62
71
|
// When the run last did something, handed to `backlog:budget` as `--active`.
|
|
63
72
|
active: string
|
|
@@ -80,14 +89,20 @@ interface DriveEnd {
|
|
|
80
89
|
is_finish?: boolean | undefined
|
|
81
90
|
}
|
|
82
91
|
|
|
92
|
+
type Collected = Pick<MergeResult, 'token' | 'outcome'>
|
|
93
|
+
|
|
83
94
|
interface DrivePorts {
|
|
84
95
|
// Whether a child's process has confirmed-ended — `lane:await`'s re-confirmed check in production.
|
|
85
96
|
is_finished: (issue: string) => boolean
|
|
86
|
-
// `run:merge <N>`'s first stdout token.
|
|
87
|
-
merge: (issue: string) => Promise<
|
|
97
|
+
// `run:merge <N>`'s first stdout token and the outcome it handled the child as.
|
|
98
|
+
merge: (issue: string) => Promise<Collected>
|
|
88
99
|
// `backlog:offer`'s answer for the state, or `undefined` when it exited non-zero.
|
|
89
100
|
offer: (state: DriveState) => Promise<OfferRead | undefined>
|
|
90
|
-
launch
|
|
101
|
+
// Where `lane:launch`'s chain ended — `launched`, `unopened` (no lane taken) or `failed` (one taken).
|
|
102
|
+
launch: (issue: string) => Promise<LaunchOutcome['kind']>
|
|
103
|
+
// The lanes free right now — `backlog_ready.drive_free_lane_count` in production, the limit less the
|
|
104
|
+
// open lanes.
|
|
105
|
+
free_lanes: () => Promise<number>
|
|
91
106
|
now: () => Date
|
|
92
107
|
}
|
|
93
108
|
|
|
@@ -150,29 +165,40 @@ function merge_stopped(issue: string, state: DriveState): DriveState {
|
|
|
150
165
|
}
|
|
151
166
|
}
|
|
152
167
|
|
|
153
|
-
//
|
|
168
|
+
// Only a merged child is excluded: `backlog:next` may still read it OPEN. Any other is classified by
|
|
169
|
+
// its labels, so excluding it would hide a child a person released for the rest of the process.
|
|
170
|
+
function excluded(issue: string, outcome: Collected['outcome'], state: DriveState): Array<string> {
|
|
171
|
+
if (outcome !== MERGED_OUTCOME || state.exclude.includes(issue)) return state.exclude
|
|
172
|
+
|
|
173
|
+
return [...state.exclude, issue]
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// The child collected, and — unless its cut was resumed in place — out of flight.
|
|
154
177
|
function collected_state(
|
|
155
178
|
issue: string,
|
|
156
|
-
|
|
179
|
+
collected: Collected,
|
|
157
180
|
state: DriveState,
|
|
158
181
|
active: string,
|
|
159
182
|
): DriveState {
|
|
160
183
|
const in_flight =
|
|
161
|
-
token === RESUMED_TOKEN
|
|
162
|
-
|
|
184
|
+
collected.token === RESUMED_TOKEN
|
|
185
|
+
? state.in_flight
|
|
186
|
+
: state.in_flight.filter((item) => item !== issue)
|
|
187
|
+
const exclude = excluded(issue, collected.outcome, state)
|
|
163
188
|
|
|
164
189
|
return { ...state, in_flight, exclude, active }
|
|
165
190
|
}
|
|
166
191
|
|
|
167
192
|
// One finished child: handed back on an immediate token, otherwise collected.
|
|
168
193
|
async function collect(issue: string, state: DriveState, ports: DrivePorts): Promise<PassResult> {
|
|
169
|
-
const
|
|
194
|
+
const collected = await ports.merge(issue)
|
|
195
|
+
const { token } = collected
|
|
170
196
|
|
|
171
197
|
// An empty first line is a `run:merge` that failed before printing one: never read as a collection.
|
|
172
198
|
if (token === '') return ended('merge', state, undefined, issue)
|
|
173
199
|
if (IMMEDIATE_TOKENS.has(token)) return ended('merge', state, token, issue)
|
|
174
200
|
|
|
175
|
-
const next = collected_state(issue,
|
|
201
|
+
const next = collected_state(issue, collected, state, ports.now().toISOString())
|
|
176
202
|
|
|
177
203
|
return { kind: 'continue', state: token === STOP_VERDICT ? merge_stopped(issue, next) : next }
|
|
178
204
|
}
|
|
@@ -182,6 +208,7 @@ async function collect_finished(state: DriveState, ports: DrivePorts): Promise<P
|
|
|
182
208
|
let current = state
|
|
183
209
|
|
|
184
210
|
for (const issue of finished) {
|
|
211
|
+
// eslint-disable-next-line no-await-in-loop -- each collect starts from the state the previous one returned
|
|
185
212
|
const result = await collect(issue, current, ports)
|
|
186
213
|
|
|
187
214
|
if (result.kind === 'end') return { ...result, state: current }
|
|
@@ -192,22 +219,55 @@ async function collect_finished(state: DriveState, ports: DrivePorts): Promise<P
|
|
|
192
219
|
return { kind: 'continue', state: current }
|
|
193
220
|
}
|
|
194
221
|
|
|
222
|
+
// A `lane:open` refused with every lane taken is a wait, not a judgement (joshuafolkken/kit#3027): the
|
|
223
|
+
// next offer after a lane frees retries it. A step failing after the lane opened is always handed back —
|
|
224
|
+
// that lane holds the last seat itself, so the free count would read the failure as a full pool.
|
|
225
|
+
async function refused(
|
|
226
|
+
issue: string,
|
|
227
|
+
outcome: LaunchOutcome['kind'],
|
|
228
|
+
state: DriveState,
|
|
229
|
+
ports: DrivePorts,
|
|
230
|
+
): Promise<PassResult> {
|
|
231
|
+
if (outcome !== UNOPENED) return ended('launch', state, undefined, issue)
|
|
232
|
+
if ((await ports.free_lanes()) <= NO_FREE_LANES) return { kind: 'continue', state }
|
|
233
|
+
|
|
234
|
+
return ended('launch', state, undefined, issue)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// **No more launches than free lanes** (joshuafolkken/kit#3027). `backlog:offer` lists every ready issue
|
|
238
|
+
// without reading the lanes, so launching all of them overran `JOSH_LANE_LIMIT` until `lane:open` ran
|
|
239
|
+
// out of seats. The free count is read once, before the first launch, because every launch here opens
|
|
240
|
+
// a lane the count would otherwise have to be told about.
|
|
241
|
+
//
|
|
242
|
+
// **Only a launch is activity** (joshuafolkken/kit#3027): a pass that started nothing — every lane taken
|
|
243
|
+
// — keeps `active` where it was, or the once-a-minute offer would restart the idle budget for good.
|
|
244
|
+
function launched(state: DriveState, in_flight: Array<string>, ports: DrivePorts): DriveState {
|
|
245
|
+
if (in_flight.length === state.in_flight.length) return { ...state, in_flight }
|
|
246
|
+
|
|
247
|
+
return { ...state, in_flight, active: ports.now().toISOString() }
|
|
248
|
+
}
|
|
249
|
+
|
|
195
250
|
async function launch_all(
|
|
196
251
|
issues: ReadonlyArray<string>,
|
|
197
252
|
state: DriveState,
|
|
198
253
|
ports: DrivePorts,
|
|
199
254
|
): Promise<PassResult> {
|
|
200
255
|
const in_flight = [...state.in_flight]
|
|
256
|
+
const free = await ports.free_lanes()
|
|
201
257
|
|
|
202
|
-
for (const issue of issues) {
|
|
203
|
-
|
|
258
|
+
for (const issue of issues.slice(0, free)) {
|
|
259
|
+
// eslint-disable-next-line no-await-in-loop -- lanes launch in order and the first refusal ends the pass
|
|
260
|
+
const outcome = await ports.launch(issue)
|
|
204
261
|
|
|
205
|
-
if (
|
|
262
|
+
if (outcome !== LAUNCHED) {
|
|
263
|
+
// eslint-disable-next-line no-await-in-loop -- lanes launch in order and the first refusal ends the pass
|
|
264
|
+
return await refused(issue, outcome, launched(state, in_flight, ports), ports)
|
|
265
|
+
}
|
|
206
266
|
|
|
207
267
|
in_flight.push(issue)
|
|
208
268
|
}
|
|
209
269
|
|
|
210
|
-
return { kind: 'continue', state:
|
|
270
|
+
return { kind: 'continue', state: launched(state, in_flight, ports) }
|
|
211
271
|
}
|
|
212
272
|
|
|
213
273
|
// A watch with nothing in flight is the drain: `run:step` owes the retrospective there, so it is the
|
|
@@ -337,7 +397,9 @@ async function run_loop(
|
|
|
337
397
|
let step = await loop_step(first, config, ports)
|
|
338
398
|
|
|
339
399
|
while (step.kind === 'next') {
|
|
400
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
340
401
|
await ports.sleep(config.poll_ms)
|
|
402
|
+
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
341
403
|
step = await loop_step(step.run, config, ports)
|
|
342
404
|
}
|
|
343
405
|
|
|
@@ -348,10 +410,8 @@ async function run_loop(
|
|
|
348
410
|
|
|
349
411
|
const backlog_drive = {
|
|
350
412
|
HANDOFF_TOKENS,
|
|
351
|
-
collect,
|
|
352
413
|
initial_state,
|
|
353
414
|
merge_stopped,
|
|
354
|
-
on_verdict,
|
|
355
415
|
run_loop,
|
|
356
416
|
run_pass,
|
|
357
417
|
}
|
|
@@ -9,8 +9,9 @@ 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 { epic_solo_stale } from '#scripts/epic/epic-solo-stale'
|
|
12
13
|
import { epic_triage, type TriageVerdict } from '#scripts/epic/epic-triage'
|
|
13
|
-
import { git_gh_command } from '#scripts/
|
|
14
|
+
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
14
15
|
import { PROJECT_ROOT } from '#scripts/init/init-paths'
|
|
15
16
|
import { issue_citation } from '#scripts/rules/issue-citation'
|
|
16
17
|
import { backlog_defect_priority } from './backlog-defect-priority'
|
|
@@ -294,7 +295,13 @@ async function gate_solo(result: EpicNextResult, context: PoolContext): Promise<
|
|
|
294
295
|
if (result.verdict !== 'run') return result
|
|
295
296
|
|
|
296
297
|
const { repo } = context
|
|
297
|
-
const read = await
|
|
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
|
+
|
|
298
305
|
const gated = backlog_rank.gate(result, read, repo, standalone_keys(context))
|
|
299
306
|
|
|
300
307
|
if (gated.notice !== undefined) console.error(gated.notice)
|
|
@@ -410,23 +417,10 @@ const backlog_next = {
|
|
|
410
417
|
RETRY_MESSAGE,
|
|
411
418
|
READ_FAILURES,
|
|
412
419
|
VERDICT_TOKENS,
|
|
413
|
-
tokens_of,
|
|
414
|
-
warn_epic_gap,
|
|
415
|
-
warn_gaps,
|
|
416
|
-
report,
|
|
417
|
-
combine,
|
|
418
|
-
views_from,
|
|
419
420
|
resolve,
|
|
420
421
|
standalone_keys,
|
|
421
|
-
is_transport_failure,
|
|
422
|
-
report_retry,
|
|
423
|
-
report_triage,
|
|
424
422
|
context_of,
|
|
425
|
-
answer_pool,
|
|
426
|
-
report_none,
|
|
427
|
-
answer,
|
|
428
423
|
run,
|
|
429
|
-
main,
|
|
430
424
|
}
|
|
431
425
|
|
|
432
426
|
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|