@joshuafolkken/kit 1.1240.0 → 1.1373.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/investigator.md +1 -0
- package/.claude/settings.json +4 -0
- package/.claude/skills/dependency-update/SKILL.md +5 -3
- package/.claude/skills/epic-commands/SKILL.md +82 -113
- package/.claude/skills/epic-commands/epic-bundle.md +38 -63
- package/.claude/skills/epic-commands/execution-waves.md +30 -51
- package/.claude/skills/verify-ui/SKILL.md +13 -20
- package/.claude/skills/workflow-commands/SKILL.md +10 -10
- package/.claude/skills/workflow-commands/background-commands.md +4 -4
- package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
- package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
- package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
- package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
- package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
- package/.claude/skills/workflow-commands/backlogrun.md +52 -61
- package/.claude/skills/workflow-commands/chain-rule.md +36 -40
- package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
- package/.claude/skills/workflow-commands/followup.md +19 -20
- package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
- package/.claude/skills/workflow-commands/fullrun.md +10 -10
- package/.claude/skills/workflow-commands/halfrun.md +9 -8
- package/.claude/skills/workflow-commands/into-target.md +12 -18
- package/.claude/skills/workflow-commands/issue-comments.md +11 -26
- package/.claude/skills/workflow-commands/kickoff.md +26 -16
- package/.claude/skills/workflow-commands/latest-gate.md +17 -28
- package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
- package/.claude/skills/workflow-commands/observation-filing.md +37 -28
- package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
- package/.claude/skills/workflow-commands/prerequisite.md +23 -15
- package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
- package/.claude/skills/workflow-commands/prrun.md +3 -3
- package/.claude/skills/workflow-commands/retrospective.md +13 -18
- package/.claude/skills/workflow-commands/split-assessment.md +6 -4
- package/.claude/skills/workflow-commands/target-repository.md +25 -28
- package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
- package/.gitattributes +2 -1
- package/.github/workflows/ci.yml +14 -0
- package/.vscode/tasks.json +14 -0
- package/CLAUDE.md +10 -61
- package/README.md +23 -66
- package/SECURITY.md +1 -1
- package/dist/CLAUDE.md +10 -61
- package/dist/commands/document-section-cli.js +43 -11
- package/dist/config-merge/index.js +11 -2
- package/dist/hooks/audit-provision.js +2 -2
- package/dist/hooks/batch-guard.js +7 -7
- package/dist/hooks/{chunk-KHGB5S3Y.js → chunk-7UBFU3CL.js} +18 -20
- package/dist/hooks/{chunk-ZQGD4GBY.js → chunk-7WKYHEGU.js} +8 -44
- package/dist/hooks/{chunk-4TZVB44A.js → chunk-AKGCP4LX.js} +285 -363
- package/dist/hooks/{chunk-QVSWU24O.js → chunk-BZMPVFDY.js} +7 -5
- package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
- package/dist/hooks/{chunk-GPTFMK5E.js → chunk-GG72ANKI.js} +1 -1
- package/dist/hooks/{chunk-XZYKEM6J.js → chunk-JCRDBQXB.js} +13 -11
- package/dist/hooks/{chunk-F3ELQ2AF.js → chunk-JGW24KKM.js} +4 -4
- package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
- package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
- package/dist/hooks/{chunk-WK2XSHSI.js → chunk-SLSFIWTX.js} +550 -875
- package/dist/hooks/chunk-UTHMB4O2.js +1590 -0
- package/dist/hooks/{chunk-KRBERBBI.js → chunk-V4TKZHER.js} +4 -4
- package/dist/hooks/chunk-YLBBSSTF.js +3705 -0
- package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
- package/dist/hooks/codex-hook-adapter.js +26 -21
- package/dist/hooks/duplicate-read-guard.js +8 -8
- package/dist/hooks/format-edited.js +4 -4
- package/dist/hooks/inputs.json +195 -181
- package/dist/hooks/investigation-guard.js +8 -8
- package/dist/hooks/pretool-guard.js +15 -15
- package/dist/hooks/session-lang.js +406 -8
- package/dist/hooks/stop-guard.js +122 -187
- package/dist/josh.js +282 -95
- package/dist/version/index.js +15 -13
- package/eslint/base.js +43 -5
- package/eslint/rules/english-only-prose.js +3 -3
- package/eslint/rules/import.js +12 -0
- package/eslint/rules/namespace-object-export.js +2 -2
- package/package.json +17 -11
- package/pnpm-workspace.yaml +2 -4
- package/prompts/coding-standards.md +14 -48
- package/prompts/collaboration-workflow/file-edits.md +1 -1
- package/prompts/collaboration-workflow/issue-citation.md +1 -1
- package/prompts/collaboration-workflow/issue-template.md +3 -10
- package/prompts/collaboration-workflow/operating-rules.md +7 -8
- package/prompts/collaboration-workflow/output-bounds.md +1 -1
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/plan-comment.md +2 -1
- package/prompts/collaboration-workflow/principles.md +21 -3
- package/prompts/collaboration-workflow/report-format.md +16 -29
- package/prompts/collaboration-workflow/residency.md +1 -1
- package/prompts/collaboration-workflow/rule-delivery.md +7 -95
- package/prompts/collaboration-workflow/shell-body.md +3 -23
- package/prompts/collaboration-workflow/turn-batching.md +4 -13
- package/prompts/collaboration-workflow/wip-cap.md +5 -11
- package/prompts/refactoring.md +1 -1
- package/prompts/review-rubric.md +3 -22
- package/prompts/review.md +15 -38
- package/prompts/testing-guide.md +2 -4
- package/scripts/adopt/adopt-logic.ts +5 -5
- package/scripts/adopt/adopt-toolkits.ts +4 -5
- package/scripts/adopt/adopt.ts +2 -3
- package/scripts/agent/agent-argv.ts +7 -7
- package/scripts/agent/agent-diagnostics.ts +2 -2
- package/scripts/agent/agent-exit-record.ts +1 -1
- package/scripts/agent/agent-headless.ts +1 -1
- package/scripts/agent/agent-launch-environment.ts +6 -1
- package/scripts/agent/agent-role-profile.ts +49 -22
- package/scripts/agent/agent-session-role.ts +32 -0
- package/scripts/agent/api-outage.ts +1 -1
- package/scripts/agent/claude-agent-argv.ts +4 -4
- package/scripts/agent/claude-result-event.ts +4 -4
- package/scripts/agent/codex-hooks.ts +2 -2
- package/scripts/agent/interactive-ask.ts +3 -6
- package/scripts/auto-ok/auto-ok-cli.ts +46 -60
- package/scripts/backlog/backlog-arrival-added.ts +34 -0
- package/scripts/backlog/backlog-arrival.ts +54 -17
- package/scripts/backlog/backlog-budget-cli.ts +34 -6
- package/scripts/backlog/backlog-budget.ts +17 -24
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-args.ts +5 -4
- package/scripts/backlog/backlog-drive-cli.ts +14 -10
- package/scripts/backlog/backlog-drive-epic.ts +85 -0
- package/scripts/backlog/backlog-drive-launch.ts +1 -1
- package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
- package/scripts/backlog/backlog-drive-named.ts +39 -9
- package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +1 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
- package/scripts/backlog/backlog-drive.ts +43 -28
- package/scripts/backlog/backlog-idle.ts +88 -0
- package/scripts/backlog/backlog-named.ts +11 -15
- package/scripts/backlog/backlog-next.ts +26 -30
- package/scripts/backlog/backlog-offer-cli.ts +28 -23
- package/scripts/backlog/backlog-offer.ts +7 -7
- package/scripts/backlog/backlog-overlap.ts +178 -0
- package/scripts/backlog/backlog-plan-cli.ts +14 -90
- package/scripts/backlog/backlog-plan-read.ts +111 -0
- package/scripts/backlog/backlog-plan.ts +11 -10
- package/scripts/backlog/backlog-pool.ts +13 -14
- package/scripts/backlog/backlog-rank.ts +11 -11
- package/scripts/backlog/backlog-ready.ts +15 -10
- package/scripts/backlog/backlog-scope.ts +14 -15
- package/scripts/backlog/backlog-stalled-cli.ts +2 -2
- package/scripts/backlog/backlog-stalled-detect.ts +4 -4
- package/scripts/backlog/backlog-stalled.ts +5 -6
- package/scripts/backlog/backlog-waves.ts +4 -4
- package/scripts/backlog/backlogrun-args.ts +74 -0
- package/scripts/backlog/backlogrun-cli.ts +113 -0
- package/scripts/backlog/backlogrun-launch.ts +178 -0
- package/scripts/behavior/behavior-assertion.ts +6 -8
- package/scripts/behavior/behavior-cli.ts +1 -1
- package/scripts/behavior/behavior-rules.ts +3 -3
- package/scripts/build/build-claude-md.ts +4 -4
- package/scripts/build/build-codex-hooks.ts +2 -2
- package/scripts/build/build-commands.ts +1 -1
- package/scripts/build/build-hooks.ts +5 -5
- package/scripts/build/build.ts +1 -1
- package/scripts/build/hook-bundle-stamp.ts +109 -7
- package/scripts/build/local-bin.ts +2 -2
- package/scripts/cases/cases-cli.ts +1 -1
- package/scripts/cases/cases-logic.ts +2 -2
- package/scripts/ci/composite-actions.ts +1 -2
- package/scripts/ci/pr-classification.ts +2 -2
- package/scripts/claude/workflow-destination.ts +1 -1
- package/scripts/clone/clone-aggregate.ts +1 -1
- package/scripts/clone/clone-fingerprint.ts +1 -1
- package/scripts/clone/clone-scan-cli.ts +1 -1
- package/scripts/clone/clone-scan.ts +1 -1
- package/scripts/config-merge/index.ts +1 -1
- package/scripts/config-merge/json-format.ts +1 -3
- package/scripts/config-merge/patch-json-array.ts +90 -0
- package/scripts/config-merge/patch-json-key.ts +6 -3
- package/scripts/config-merge/patch-json-list.ts +1 -1
- package/scripts/cost-runtime/codex-usage.ts +1 -1
- package/scripts/cost-runtime/context-cut-payback.ts +4 -5
- package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
- package/scripts/cost-runtime/cost-attribute.ts +3 -3
- package/scripts/cost-runtime/cost-blocks.ts +3 -4
- package/scripts/cost-runtime/cost-cli.ts +14 -11
- package/scripts/cost-runtime/cost-corpus.ts +11 -11
- package/scripts/cost-runtime/cost-pricing.ts +4 -4
- package/scripts/cost-runtime/cost-tokens.ts +1 -2
- package/scripts/cost-runtime/cost-transcript.ts +29 -29
- package/scripts/cost-runtime/cost-usage.ts +6 -7
- package/scripts/cost-runtime/cost-verdict.ts +10 -11
- package/scripts/cost-runtime/own-session.ts +1 -1
- package/scripts/cost-runtime/transcript-cwd.ts +2 -2
- package/scripts/delegation/delegation-cli.ts +4 -4
- package/scripts/delegation/delegation-policy.ts +13 -15
- package/scripts/delegation/duplicate-read-guard.ts +9 -10
- package/scripts/delegation/fanout-cli.ts +1 -1
- package/scripts/delegation/fanout.ts +1 -1
- package/scripts/delegation/investigation-guard.ts +18 -22
- package/scripts/delegation/investigation-reads.ts +48 -238
- package/scripts/discovery/repo-discovery.ts +1 -1
- package/scripts/discovery/repo-map-logic.ts +1 -2
- package/scripts/discovery/repo-origin.ts +3 -3
- package/scripts/discovery/repo-party-cli.ts +2 -2
- package/scripts/discovery/repo-party.ts +2 -2
- package/scripts/doctor/doctor-consumer.ts +1 -1
- package/scripts/doctor/doctor-io.ts +6 -7
- package/scripts/doctor/doctor-logic.ts +1 -1
- package/scripts/doctor/doctor-ports.ts +1 -1
- package/scripts/doctor/doctor.ts +8 -9
- package/scripts/document/backlogrun-parent-read-set.ts +5 -6
- package/scripts/document/bash-output-cap.ts +5 -7
- package/scripts/document/capped-print-part.ts +1 -1
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/document-byte-budget.ts +33 -64
- package/scripts/document/document-byte-check.ts +4 -4
- package/scripts/document/document-reachability.ts +7 -8
- package/scripts/document/document-read-cli.ts +2 -2
- package/scripts/document/document-scan.ts +30 -5
- package/scripts/document/document-section-cli.ts +6 -8
- package/scripts/document/document-section.ts +8 -12
- package/scripts/document/edit-files-cli.ts +3 -4
- package/scripts/document/entry-read-budget.ts +8 -70
- package/scripts/document/entry-read-set.ts +51 -34
- package/scripts/document/lane-child-read-set.ts +9 -9
- package/scripts/document/read-files-cli.ts +1 -2
- package/scripts/document/read-set-cli.ts +16 -19
- package/scripts/document/read-set-cost.ts +4 -4
- package/scripts/document/read-set-point-of-use.ts +28 -38
- package/scripts/document/read-set-pricing.ts +1 -1
- package/scripts/document/read-set-trim.ts +3 -3
- package/scripts/document/resident-budget.ts +8 -10
- package/scripts/epic/epic-add-body.ts +15 -18
- package/scripts/epic/epic-add-plan.ts +26 -28
- package/scripts/epic/epic-add.ts +32 -25
- package/scripts/epic/epic-audit-checks.ts +27 -37
- package/scripts/epic/epic-audit-cli.ts +21 -22
- package/scripts/epic/epic-audit-orphans.ts +16 -17
- package/scripts/epic/epic-audit-rationale.ts +10 -15
- package/scripts/epic/epic-audit-report.ts +2 -5
- package/scripts/epic/epic-audit.ts +18 -14
- package/scripts/epic/epic-body.ts +10 -10
- package/scripts/epic/epic-bundle-cli.ts +36 -34
- package/scripts/epic/epic-bundle-evidence.ts +5 -5
- package/scripts/epic/epic-bundle-gaps.ts +6 -9
- package/scripts/epic/epic-bundle-poll.ts +1 -1
- package/scripts/epic/epic-bundle-referenced.ts +11 -14
- package/scripts/epic/epic-bundle.ts +19 -20
- package/scripts/epic/epic-busy.ts +44 -21
- package/scripts/epic/epic-candidate-confirm.ts +15 -18
- package/scripts/epic/epic-chains.ts +18 -23
- package/scripts/epic/epic-classify.ts +11 -12
- package/scripts/epic/epic-cli-argv.ts +5 -6
- package/scripts/epic/epic-cli-remove.ts +9 -4
- package/scripts/epic/epic-cli.ts +38 -26
- package/scripts/epic/epic-close-comment.ts +14 -15
- package/scripts/epic/epic-close.ts +25 -29
- package/scripts/epic/epic-cross-repo.ts +18 -21
- package/scripts/epic/epic-decision.ts +14 -18
- package/scripts/epic/epic-fetch.ts +25 -31
- package/scripts/epic/epic-graph.ts +15 -17
- package/scripts/epic/epic-index.ts +14 -16
- package/scripts/epic/epic-issue.ts +9 -11
- package/scripts/epic/epic-label-age.ts +74 -0
- package/scripts/epic/epic-lane-offer.ts +35 -24
- package/scripts/epic/epic-nested.ts +1 -1
- package/scripts/epic/epic-next-read.ts +8 -8
- package/scripts/epic/epic-next-views.ts +12 -12
- package/scripts/epic/epic-next.ts +29 -33
- package/scripts/epic/epic-outside-blocker.ts +11 -10
- package/scripts/epic/epic-parse.ts +22 -24
- package/scripts/epic/epic-promote.ts +3 -2
- package/scripts/epic/epic-rank.ts +1 -1
- package/scripts/epic/epic-read.ts +10 -8
- package/scripts/epic/epic-reconcile.ts +8 -6
- package/scripts/epic/epic-reference.ts +5 -4
- package/scripts/epic/epic-relation-recheck.ts +10 -11
- package/scripts/epic/epic-relations.ts +9 -8
- package/scripts/epic/epic-remove-plan.ts +4 -5
- package/scripts/epic/epic-remove.ts +7 -5
- package/scripts/epic/epic-report.ts +18 -20
- package/scripts/epic/epic-run.ts +6 -5
- package/scripts/epic/epic-sections.ts +2 -2
- package/scripts/epic/epic-shape.ts +3 -3
- package/scripts/epic/epic-solo-stale.ts +3 -2
- package/scripts/epic/epic-solo.ts +8 -8
- package/scripts/epic/epic-triage.ts +5 -4
- package/scripts/epic/epic-validate.ts +8 -7
- package/scripts/epic/epic.ts +5 -5
- package/scripts/exports/unused-members-cli.ts +1 -1
- package/scripts/followup/followup-issue-number.ts +1 -2
- package/scripts/followup/git-followup-cleanup.ts +6 -7
- package/scripts/followup/git-followup-finish.ts +11 -13
- package/scripts/followup/git-followup-flush.ts +11 -7
- package/scripts/followup/git-followup-issue-close.ts +16 -13
- package/scripts/followup/git-followup-label.ts +9 -6
- package/scripts/followup/git-followup-merged.ts +1 -1
- package/scripts/followup/git-followup-pending.ts +7 -9
- package/scripts/followup/git-followup-stages.ts +28 -17
- package/scripts/followup/git-followup-workflow.ts +19 -21
- package/scripts/followup/git-pr-followup-checks.ts +13 -20
- package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
- package/scripts/followup/git-pr-followup.ts +18 -17
- package/scripts/gate/core-admission.ts +2 -2
- package/scripts/gate/core-budget.ts +15 -26
- package/scripts/gate/gate-ledger.ts +114 -0
- package/scripts/gate/gate-log.ts +7 -9
- package/scripts/gate/gate-plan.ts +70 -35
- package/scripts/gate/gate-report.ts +14 -15
- package/scripts/gate/gate-skip.ts +11 -13
- package/scripts/gate/gate-steps.ts +5 -1
- package/scripts/gate/gate-tree.ts +3 -4
- package/scripts/gate/hook-gate-reuse.ts +9 -9
- package/scripts/gate/machine-capacity.ts +168 -30
- package/scripts/gate/pre-commit-type-check.ts +4 -4
- package/scripts/gate/project-checks.ts +12 -4
- package/scripts/gate/scoped-green.ts +11 -18
- package/scripts/gate/type-check-command.ts +2 -2
- package/scripts/gate/type-check-step.ts +4 -4
- package/scripts/gate/verification-gate.ts +53 -51
- package/scripts/gh/gh-spawn.ts +2 -2
- package/scripts/gh/git-ai-review-scan.ts +3 -2
- package/scripts/gh/git-gh-api-path.ts +10 -11
- package/scripts/gh/git-gh-exec.ts +43 -48
- package/scripts/gh/git-gh-failure.ts +6 -9
- package/scripts/gh/git-gh-helpers.ts +1 -1
- package/scripts/gh/git-gh-issue-list.ts +15 -19
- package/scripts/gh/git-gh-issue-read.ts +43 -60
- package/scripts/gh/git-gh-issue-rest.ts +14 -15
- package/scripts/gh/git-gh-issue-write.ts +52 -40
- package/scripts/gh/git-gh-issue.ts +23 -24
- package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
- package/scripts/gh/git-gh-pr-read.ts +46 -50
- package/scripts/gh/git-gh-pr-rest.ts +23 -26
- package/scripts/gh/git-gh-pr-review.ts +2 -2
- package/scripts/gh/git-gh-pr-rollup.ts +4 -4
- package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
- package/scripts/gh/git-gh-pr.ts +16 -16
- package/scripts/gh/git-gh-reachability.ts +11 -12
- package/scripts/gh/git-gh-repo.ts +2 -3
- package/scripts/gh/git-gh-rest-state.ts +1 -1
- package/scripts/gh/git-pr-ai-review.ts +6 -5
- package/scripts/gh/git-pr-checks-eval.ts +28 -30
- package/scripts/gh/git-pr-checks-parse.ts +14 -16
- package/scripts/gh/git-pr-checks-watch.ts +17 -17
- package/scripts/gh/git-pr-checks.ts +20 -23
- package/scripts/gh/git-pr-coderabbit.ts +8 -6
- package/scripts/gh/git-pr-confirmation.ts +5 -5
- package/scripts/gh/git-pr-managed-config.ts +7 -9
- package/scripts/gh/git-pr-messages.ts +1 -1
- package/scripts/gh/git-pr.ts +15 -16
- package/scripts/gh/github-issue-url.ts +8 -9
- package/scripts/git/base-tree.ts +66 -0
- package/scripts/git/change-base.ts +42 -2
- package/scripts/git/changed-file-scope.ts +5 -5
- package/scripts/git/changed-paths.ts +1 -2
- package/scripts/git/constants.ts +2 -2
- package/scripts/git/git-branch.ts +1 -1
- package/scripts/git/git-closes-keyword.ts +3 -3
- package/scripts/git/git-command.ts +53 -41
- package/scripts/git/git-common-directory.ts +3 -3
- package/scripts/git/git-diff-reads.ts +14 -15
- package/scripts/git/git-error.ts +1 -1
- package/scripts/git/git-execa-error.ts +1 -2
- package/scripts/git/git-issue.ts +10 -8
- package/scripts/git/git-location-environment.ts +3 -4
- package/scripts/git/git-ls-remote.ts +6 -8
- package/scripts/git/git-pre-push-hook.ts +11 -10
- package/scripts/git/git-preflight.ts +5 -5
- package/scripts/git/git-push-transport.ts +2 -2
- package/scripts/git/git-remote-branch.ts +1 -2
- package/scripts/git/git-schemas.ts +16 -23
- package/scripts/git/git-spawn-sync.ts +1 -1
- package/scripts/git/git-spawn.ts +37 -14
- package/scripts/git/git-ssh-keepalive.ts +12 -5
- package/scripts/git/git-staging.ts +7 -8
- package/scripts/git/git-workflow.ts +1 -1
- package/scripts/git/git-worktree.ts +35 -27
- package/scripts/git/gone-branch.ts +2 -2
- package/scripts/git/listing-cutoff.ts +1 -2
- package/scripts/git/lockfile-sync.ts +65 -0
- package/scripts/git/main-merge-guard.ts +1 -2
- package/scripts/git/main-merge.ts +7 -7
- package/scripts/git/main-sync.ts +23 -8
- package/scripts/git/parse-json-array.ts +18 -23
- package/scripts/git/repository-lock.ts +34 -2
- package/scripts/git/stash/git-stash.ts +4 -5
- package/scripts/git/stash/stash-orphans.ts +5 -3
- package/scripts/git/stash/stash-pop-args.ts +1 -1
- package/scripts/git/stash/stash-pop-cli.ts +3 -3
- package/scripts/git/stash/stash-sweep-lock.ts +2 -2
- package/scripts/hooks/batch-guard.ts +11 -13
- package/scripts/hooks/check-commit-message.ts +12 -9
- package/scripts/hooks/codex-hook-adapter.ts +16 -10
- package/scripts/hooks/edited-cspell.ts +3 -4
- package/scripts/hooks/format-edited-cli.ts +1 -1
- package/scripts/hooks/format-edited-file.ts +11 -17
- package/scripts/hooks/format-rewrite-notice.ts +19 -17
- package/scripts/hooks/pre-push-unit.ts +10 -14
- package/scripts/hooks/pretool-guard-cli.ts +4 -4
- package/scripts/hooks/pretool-guard.ts +93 -18
- package/scripts/hooks/reserved-run.ts +2 -2
- package/scripts/hooks/step-zero-notice.ts +1 -1
- package/scripts/hooks/stop-guard.ts +21 -10
- package/scripts/init/basic-path-migration.ts +2 -2
- package/scripts/init/claude-kit-only-settings.ts +2 -2
- package/scripts/init/claude-plugin-config.ts +2 -2
- package/scripts/init/distributed-paths.ts +4 -4
- package/scripts/init/hook-command-rewrite.ts +3 -3
- package/scripts/init/hook-launch.ts +5 -5
- package/scripts/init/init-actions.ts +13 -0
- package/scripts/init/init-ai-copy.ts +11 -11
- package/scripts/init/init-bootstrap.ts +3 -3
- package/scripts/init/init-copy-content.ts +4 -4
- package/scripts/init/init-logic-json-merge.ts +7 -9
- package/scripts/init/init-logic-migrate.ts +1 -1
- package/scripts/init/init-logic-templates.ts +1 -1
- package/scripts/init/init-logic-workspace.ts +4 -4
- package/scripts/init/init-logic-yaml-merge.ts +2 -2
- package/scripts/init/init-logic.ts +19 -22
- package/scripts/init/init.ts +7 -7
- package/scripts/init/kit-base-preset.ts +1 -1
- package/scripts/init/kit-setup-state.ts +1 -1
- package/scripts/init/kit-written-paths.ts +1 -2
- package/scripts/init/package-manager-pin.ts +1 -1
- package/scripts/init/project-profile-cli.ts +1 -1
- package/scripts/init/project-profile.ts +3 -3
- package/scripts/init/session-language-environment.ts +1 -1
- package/scripts/init/start-exec.ts +3 -4
- package/scripts/init/start-plan.ts +2 -2
- package/scripts/init/start-setup-pr.ts +3 -2
- package/scripts/init/start-steps.ts +2 -2
- package/scripts/init/tsconfig-preset-migration.ts +1 -1
- package/scripts/init/vscode-tasks.ts +62 -0
- package/scripts/issue/baseline-measure.ts +2 -2
- package/scripts/issue/behavior-change-lint.ts +2 -2
- package/scripts/issue/defect-rate-cli.ts +6 -7
- package/scripts/issue/defect-rate.ts +37 -27
- package/scripts/issue/git-next-issues.ts +9 -8
- package/scripts/issue/issue-auto-ok.ts +24 -11
- package/scripts/issue/issue-backlinks-cli.ts +5 -5
- package/scripts/issue/issue-backlinks.ts +6 -6
- package/scripts/issue/issue-cite-cli.ts +20 -18
- package/scripts/issue/issue-cite.ts +18 -8
- package/scripts/issue/issue-closing-pr.ts +4 -4
- package/scripts/issue/issue-comment-cli.ts +6 -4
- package/scripts/issue/issue-file-cli.ts +52 -15
- package/scripts/issue/issue-file-fold.ts +155 -0
- package/scripts/issue/issue-file.ts +9 -6
- package/scripts/issue/issue-fold-cli.ts +14 -9
- package/scripts/issue/issue-fold.ts +23 -8
- package/scripts/issue/issue-labels.ts +34 -38
- package/scripts/issue/issue-lint-cli.ts +2 -2
- package/scripts/issue/issue-lint.ts +1 -1
- package/scripts/issue/issue-merged.ts +10 -4
- package/scripts/issue/issue-number-shape.ts +27 -0
- package/scripts/issue/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +4 -5
- package/scripts/issue/issue-read.ts +4 -5
- package/scripts/issue/issue-reference.ts +5 -5
- package/scripts/issue/issue-release-cli.ts +17 -7
- package/scripts/issue/issue-release.ts +3 -3
- package/scripts/issue/issue-report-failures.ts +7 -4
- package/scripts/issue/issue-scout-cli.ts +11 -11
- package/scripts/issue/issue-scout-closed.ts +4 -4
- package/scripts/issue/issue-scout.ts +4 -5
- package/scripts/issue/issue-state-cli.ts +17 -10
- package/scripts/issue/issue-state.ts +12 -13
- package/scripts/issue/issue-wip.ts +7 -7
- package/scripts/issue/markdown-section.ts +3 -3
- package/scripts/issue/measure-rerun-cli.ts +10 -9
- package/scripts/issue/reproduction-measure.ts +3 -3
- package/scripts/issue/session-cite.ts +56 -0
- package/scripts/josh/agent-session-environment.ts +10 -8
- package/scripts/josh/cli-body.ts +2 -2
- package/scripts/josh/command-suggest.ts +1 -1
- package/scripts/josh/file-map-stamp.ts +20 -23
- package/scripts/josh/hook-decision.ts +24 -28
- package/scripts/josh/josh-command-map.ts +4 -1
- package/scripts/josh/josh-command-types.ts +30 -35
- package/scripts/josh/josh-commands-ai.ts +6 -6
- package/scripts/josh/josh-commands-backlog.ts +15 -3
- package/scripts/josh/josh-commands-clone.ts +1 -1
- package/scripts/josh/josh-commands-development.ts +25 -4
- package/scripts/josh/josh-commands-document.ts +3 -3
- package/scripts/josh/josh-commands-guard.ts +3 -3
- package/scripts/josh/josh-commands-issue.ts +4 -5
- package/scripts/josh/josh-commands-lane.ts +14 -4
- package/scripts/josh/josh-commands-lint.ts +1 -1
- package/scripts/josh/josh-commands-run.ts +21 -7
- package/scripts/josh/josh-commands-split.ts +1 -2
- package/scripts/josh/josh-commands-versioning.ts +5 -5
- package/scripts/josh/josh-commands-workflow.ts +30 -22
- package/scripts/josh/josh-environment-file.ts +1 -1
- package/scripts/josh/josh-in-process.ts +3 -3
- package/scripts/josh/josh-logic.ts +6 -7
- package/scripts/josh/josh-run.ts +3 -3
- package/scripts/josh/josh-verdict.ts +9 -12
- package/scripts/josh/josh.ts +3 -3
- package/scripts/josh/kit-only.ts +2 -2
- package/scripts/josh/path-decision.ts +3 -3
- package/scripts/josh/platform-temporary.ts +7 -5
- package/scripts/josh/process-identity.ts +24 -6
- package/scripts/josh/process-owner.ts +4 -4
- package/scripts/josh/session-language-cli.ts +53 -11
- package/scripts/josh/session-language.ts +1 -1
- package/scripts/josh/stamp-file.ts +48 -29
- package/scripts/josh/stamp-record.ts +57 -0
- package/scripts/lane/lane-await.ts +35 -11
- package/scripts/lane/lane-cache.ts +6 -6
- package/scripts/lane/lane-capacity.ts +32 -17
- package/scripts/lane/lane-child-invocation.ts +17 -15
- package/scripts/lane/lane-child-marker.ts +12 -12
- package/scripts/lane/lane-cli.ts +12 -13
- package/scripts/lane/lane-close.ts +6 -6
- package/scripts/lane/lane-dispatch.ts +61 -72
- package/scripts/lane/lane-environment.ts +5 -5
- package/scripts/lane/lane-guard-policy.ts +7 -21
- package/scripts/lane/lane-handoff.ts +2 -2
- package/scripts/lane/lane-install.ts +9 -10
- package/scripts/lane/lane-launch-cli.ts +13 -8
- package/scripts/lane/lane-ledger.ts +73 -11
- package/scripts/lane/lane-leftover.ts +2 -2
- package/scripts/lane/lane-limit-cli.ts +160 -0
- package/scripts/lane/lane-limit-override.ts +74 -0
- package/scripts/lane/lane-load.ts +19 -68
- package/scripts/lane/lane-measure-cli.ts +15 -25
- package/scripts/lane/lane-occupancy.ts +6 -4
- package/scripts/lane/lane-open.ts +20 -19
- package/scripts/lane/lane-output.ts +4 -3
- package/scripts/lane/lane-paths.ts +12 -11
- package/scripts/lane/lane-phase.ts +33 -0
- package/scripts/lane/lane-reap.ts +2 -2
- package/scripts/lane/lane-registry.ts +16 -15
- package/scripts/lane/lane-relaunch.ts +9 -9
- package/scripts/lane/lane-report.ts +5 -4
- package/scripts/lane/lane-resume.ts +2 -2
- package/scripts/lane/lane-sampler.ts +55 -0
- package/scripts/lane/lane-seed.ts +7 -7
- package/scripts/lane/lane-stage-stats.ts +135 -0
- package/scripts/lane/lane-start-point.ts +8 -11
- package/scripts/lane/lane-stats.ts +60 -15
- package/scripts/lane/lane-stray.ts +1 -1
- package/scripts/lane/lane-vacant.ts +1 -1
- package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
- package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
- package/scripts/lane/openai-review-broker.ts +2 -4
- package/scripts/lib/ancestor-directories.ts +1 -1
- package/scripts/lib/bounded-pool.ts +2 -2
- package/scripts/lib/buffered-process.ts +4 -6
- package/scripts/lib/caddy-logs.sh +0 -0
- package/scripts/lib/cli-flags.ts +39 -6
- package/scripts/lib/error-message.ts +1 -1
- package/scripts/lib/json-value.ts +17 -3
- package/scripts/lib/poll.ts +1 -1
- package/scripts/lib/status-icons.ts +3 -3
- package/scripts/lib/timed-fetch.ts +1 -1
- package/scripts/lib/timeouts.ts +1 -1
- package/scripts/lines/bytes-command.ts +3 -4
- package/scripts/lines/effective-limit.ts +25 -12
- package/scripts/lines/line-budget.ts +47 -55
- package/scripts/lines/line-targets.ts +6 -2
- package/scripts/lines/lines-command.ts +3 -3
- package/scripts/lint/cross-file-recheck.ts +155 -0
- package/scripts/lint/cspell-cached.ts +1 -1
- package/scripts/lint/format.ts +1 -2
- package/scripts/lint/lint-parallel.ts +35 -19
- package/scripts/lint/lint-related-scope.ts +25 -15
- package/scripts/lint/lint-related.ts +6 -7
- package/scripts/managed-marker/index.ts +1 -1
- package/scripts/managed-marker/managed-marker-logic.ts +1 -2
- package/scripts/notify/git-notify.ts +9 -7
- package/scripts/notify/telegram-notify.ts +53 -37
- package/scripts/notify/telegram-test-logic.ts +3 -3
- package/scripts/notify/telegram-test.ts +45 -30
- package/scripts/observations/observation-ledger-home.ts +14 -8
- package/scripts/observations/observation-ledger-line.ts +3 -2
- package/scripts/observations/observation-ledger-migrate.ts +3 -4
- package/scripts/observations/observation-ledger-prepare.ts +4 -4
- package/scripts/observations/observation-ledger.ts +14 -15
- package/scripts/observations/observation-record-cli.ts +83 -0
- package/scripts/observations/observation-record.ts +91 -0
- package/scripts/observations/observations-flush-cli.ts +1 -1
- package/scripts/observations/observations-flush-landing.ts +7 -6
- package/scripts/observations/observations-flush.ts +26 -27
- package/scripts/overrides/overrides-check.ts +18 -8
- package/scripts/package/package-scout-cli.ts +1 -1
- package/scripts/package/package-scout-format.ts +2 -2
- package/scripts/package/package-scout.ts +1 -1
- package/scripts/propagate/propagate-git-failure.ts +1 -1
- package/scripts/propagate/propagate-git.ts +7 -7
- package/scripts/propagate/propagate-plan.ts +2 -2
- package/scripts/propagate/propagate-publish.ts +2 -3
- package/scripts/propagate/propagate-run.ts +5 -7
- package/scripts/propagate/propagate-select.ts +1 -1
- package/scripts/propagate/propagate-steps.ts +19 -20
- package/scripts/propagate/propagate-targets.ts +6 -10
- package/scripts/propagate/propagate.ts +5 -5
- package/scripts/refactor/import-graph.ts +1 -1
- package/scripts/refactor/refactor-lint.ts +4 -10
- package/scripts/refactor/refactor-scan-cli.ts +1 -1
- package/scripts/refactor/refactor-scan.ts +2 -2
- package/scripts/refactor/refactor-targets.ts +1 -1
- package/scripts/release/github-release-cli.ts +25 -3
- package/scripts/release/github-release-runs.ts +1 -1
- package/scripts/release/release-cli.ts +21 -4
- package/scripts/release/release-history.ts +6 -10
- package/scripts/release/release-plan.ts +3 -3
- package/scripts/release/release-progress.ts +3 -4
- package/scripts/release/release-publish.ts +8 -9
- package/scripts/release/release-scope-cli.ts +8 -10
- package/scripts/release/release-tag.ts +6 -8
- package/scripts/release/release-worktree.ts +5 -5
- package/scripts/repo/auto-merge-setting-logic.ts +7 -9
- package/scripts/repo/auto-merge-setting.ts +1 -1
- package/scripts/repo/repo-setting.ts +4 -4
- package/scripts/repo/repository-labels.ts +1 -1
- package/scripts/repo/required-checks-logic.ts +3 -3
- package/scripts/repo/required-checks-report.ts +1 -1
- package/scripts/repo/ruleset-check-cli.ts +1 -1
- package/scripts/repo/ruleset-check.ts +1 -1
- package/scripts/report/report-format-reference.ts +26 -0
- package/scripts/report/report-lint-cli.ts +2 -2
- package/scripts/report/report-lint.ts +16 -2
- package/scripts/review/disposition-cli.ts +2 -2
- package/scripts/review/disposition-logic.ts +1 -1
- package/scripts/review/live-evidence.ts +9 -6
- package/scripts/review/review-attest-cli.ts +1 -2
- package/scripts/review/review-attest.ts +3 -3
- package/scripts/review/review-brief-cli.ts +19 -20
- package/scripts/review/review-brief.ts +29 -32
- package/scripts/review/review-checkout.ts +2 -2
- package/scripts/review/review-diff-parts.ts +3 -5
- package/scripts/review/review-diff-write.ts +1 -1
- package/scripts/review/review-finding-ledger.ts +7 -4
- package/scripts/review/review-findings-cli.ts +2 -2
- package/scripts/review/review-level.ts +4 -7
- package/scripts/review/review-record-cli.ts +73 -16
- package/scripts/review/review-record.ts +5 -4
- package/scripts/review/review-round2-cli.ts +2 -3
- package/scripts/review/review-round2.ts +13 -21
- package/scripts/review/review-stamps.ts +9 -71
- package/scripts/review/review-tree.ts +4 -5
- package/scripts/rules/bash-triggers.ts +4 -4
- package/scripts/rules/decision-oracle-batch.ts +6 -7
- package/scripts/rules/decision-oracle-stage.ts +1 -1
- package/scripts/rules/decision-oracle-tokens.ts +1 -2
- package/scripts/rules/decision-oracle.ts +2 -2
- package/scripts/rules/delivered-rules.ts +61 -406
- package/scripts/rules/destructive-command.ts +2 -2
- package/scripts/rules/direct-filing.ts +4 -4
- package/scripts/rules/direct-pr-create.ts +2 -2
- package/scripts/rules/early-heartbeat.ts +15 -19
- package/scripts/rules/file-body.ts +5 -6
- package/scripts/rules/filing-cap.ts +6 -7
- package/scripts/rules/filing-offer.ts +1 -1
- package/scripts/rules/firing-point.ts +6 -6
- package/scripts/rules/gh-api.ts +2 -2
- package/scripts/rules/git-argv.ts +3 -3
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/hook-context-line.ts +31 -0
- package/scripts/rules/implementation-cut-verdict.ts +5 -8
- package/scripts/rules/implementation-cut.ts +35 -32
- package/scripts/rules/index-guard.ts +2 -2
- package/scripts/rules/issue-citation.ts +7 -7
- package/scripts/rules/issue-comments.ts +21 -13
- package/scripts/rules/josh-git-bare.ts +2 -2
- package/scripts/rules/lane-background.ts +14 -16
- package/scripts/rules/lane-carry-conflict.ts +41 -5
- package/scripts/rules/lane-interactive-ask.ts +6 -9
- package/scripts/rules/lane-park.ts +12 -16
- package/scripts/rules/lane-split-park.ts +1 -2
- package/scripts/rules/lane-switch-main.ts +10 -13
- package/scripts/rules/last-prompt.ts +1 -1
- package/scripts/rules/oracle-consulted.ts +5 -5
- package/scripts/rules/oracle-firing.ts +6 -9
- package/scripts/rules/oracle-list-cli.ts +2 -2
- package/scripts/rules/permission-guards.ts +2 -2
- package/scripts/rules/piped-verification.ts +79 -9
- package/scripts/rules/poll-loop.ts +9 -11
- package/scripts/rules/pre-gate-cut.ts +33 -30
- package/scripts/rules/prior-comment-read.ts +3 -3
- package/scripts/rules/protected-files.ts +25 -13
- package/scripts/rules/raw-field-body.ts +3 -4
- package/scripts/rules/reply-language.ts +1 -1
- package/scripts/rules/rule-body-guard.ts +10 -12
- package/scripts/rules/rule-guard.ts +1 -1
- package/scripts/rules/rule-list.ts +51 -0
- package/scripts/rules/rule-registry-rows.ts +282 -0
- package/scripts/rules/rule-registry.ts +109 -0
- package/scripts/rules/rule-value-cache.ts +2 -2
- package/scripts/rules/rule-value-cli.ts +6 -4
- package/scripts/rules/rule-value.ts +61 -22
- package/scripts/rules/run-tail-rule.ts +11 -15
- package/scripts/rules/shell-body-trigger.ts +7 -7
- package/scripts/rules/shell-segments.ts +2 -4
- package/scripts/rules/stop-rules.ts +54 -41
- package/scripts/rules/tail-commands.ts +1 -1
- package/scripts/rules/test-declared-commit.ts +2 -2
- package/scripts/rules/third-party-write.ts +3 -3
- package/scripts/rules/worktree-guard.ts +12 -5
- package/scripts/run/add/run-add-cli.ts +165 -0
- package/scripts/run/add/run-add.ts +124 -0
- package/scripts/run/board/run-board-cli.ts +207 -0
- package/scripts/run/board/run-board-closed.ts +95 -0
- package/scripts/run/board/run-board-every.ts +60 -0
- package/scripts/run/board/run-board-fetch.ts +38 -0
- package/scripts/run/board/run-board-fit.ts +219 -0
- package/scripts/run/board/run-board-github.ts +162 -0
- package/scripts/run/board/run-board-header.ts +275 -0
- package/scripts/run/board/run-board-kind.ts +35 -0
- package/scripts/run/board/run-board-labels.ts +299 -0
- package/scripts/run/board/run-board-layout.ts +222 -0
- package/scripts/run/board/run-board-link.ts +31 -0
- package/scripts/run/board/run-board-machine.ts +198 -0
- package/scripts/run/board/run-board-notes.ts +103 -0
- package/scripts/run/board/run-board-phase.ts +136 -0
- package/scripts/run/board/run-board-plan.ts +129 -0
- package/scripts/run/board/run-board-read.ts +62 -0
- package/scripts/run/board/run-board-render-legend.ts +82 -0
- package/scripts/run/board/run-board-render-notes.ts +77 -0
- package/scripts/run/board/run-board-render-slot.ts +50 -0
- package/scripts/run/board/run-board-render.ts +407 -0
- package/scripts/run/board/run-board-scope.ts +17 -0
- package/scripts/run/board/run-board-screen.ts +43 -0
- package/scripts/run/board/run-board-span.ts +66 -0
- package/scripts/run/board/run-board-spin.ts +115 -0
- package/scripts/run/board/run-board-state.ts +113 -0
- package/scripts/run/board/run-board-status.ts +279 -0
- package/scripts/run/board/run-board-tick.ts +210 -0
- package/scripts/run/board/run-board-track.ts +22 -0
- package/scripts/run/board/run-board-usage-read.ts +255 -0
- package/scripts/run/board/run-board-usage-rusage.ts +124 -0
- package/scripts/run/board/run-board-usage-text.ts +80 -0
- package/scripts/run/board/run-board-usage.ts +165 -0
- package/scripts/run/carry/run-carry-added.ts +62 -0
- package/scripts/run/carry/run-carry-args.ts +25 -22
- package/scripts/run/carry/run-carry-change.ts +1 -1
- package/scripts/run/carry/run-carry-cli.ts +71 -48
- package/scripts/run/carry/run-carry-conversation.ts +6 -7
- package/scripts/run/carry/run-carry-ended.ts +85 -0
- package/scripts/run/carry/run-carry-reclaim.ts +1 -1
- package/scripts/run/carry/run-carry-stash.ts +3 -2
- package/scripts/run/carry/run-carry-streak.ts +8 -10
- package/scripts/run/carry/run-carry.ts +85 -89
- package/scripts/run/cut/run-cut-args.ts +7 -7
- package/scripts/run/cut/run-cut-cli.ts +54 -36
- package/scripts/run/cut/run-cut-handoff.ts +15 -15
- package/scripts/run/cut/run-cut-report.ts +37 -16
- package/scripts/run/cut/run-cut.ts +63 -77
- package/scripts/run/detached-launch.ts +35 -50
- package/scripts/run/entry/run-entry-cli.ts +48 -27
- package/scripts/run/entry/run-entry-stop.ts +7 -9
- package/scripts/run/entry/run-entry.ts +5 -6
- package/scripts/run/event/run-event-cli.ts +5 -6
- package/scripts/run/event/run-event-filed.ts +69 -0
- package/scripts/run/event/run-event-follow.ts +3 -3
- package/scripts/run/event/run-event-plan.ts +38 -0
- package/scripts/run/event/run-event-render.ts +9 -4
- package/scripts/run/event/run-event-scope.ts +47 -18
- package/scripts/run/event/run-event-stream-emit.ts +64 -11
- package/scripts/run/event/run-event-stream.ts +171 -46
- package/scripts/run/event/run-event-watch.ts +4 -6
- package/scripts/run/hold/run-hold-cli.ts +65 -62
- package/scripts/run/hold/run-hold.ts +88 -46
- package/scripts/run/merge/run-merge-cli.ts +116 -77
- package/scripts/run/merge/run-merge-collect.ts +107 -0
- package/scripts/run/merge/run-merge-steps.ts +112 -65
- package/scripts/run/merge/run-merge-token.ts +30 -0
- package/scripts/run/merge/run-merge.ts +31 -22
- package/scripts/run/progress/run-progress-args.ts +4 -4
- package/scripts/run/progress/run-progress-cli.ts +39 -50
- package/scripts/run/progress/run-progress-clock.ts +25 -32
- package/scripts/run/progress/run-progress-config.ts +6 -9
- package/scripts/run/progress/run-progress-read.ts +9 -10
- package/scripts/run/progress/run-progress.ts +48 -53
- package/scripts/run/review/run-review-cli.ts +6 -6
- package/scripts/run/review/run-review-steps.ts +6 -6
- package/scripts/run/review/run-review.ts +9 -11
- package/scripts/run/run-cli-fault.ts +29 -0
- package/scripts/run/run-ending-cli.ts +3 -3
- package/scripts/run/run-ending.ts +10 -14
- package/scripts/run/run-halfrun-resume.ts +6 -8
- package/scripts/run/run-headless.ts +26 -12
- package/scripts/run/run-invocation.ts +17 -22
- package/scripts/run/run-label.ts +7 -5
- package/scripts/run/run-liveness-cli.ts +19 -6
- package/scripts/run/run-liveness.ts +27 -38
- package/scripts/run/run-next-cli.ts +5 -9
- package/scripts/run/run-next.ts +4 -5
- package/scripts/run/run-parent-cut-hook.ts +10 -12
- package/scripts/run/run-preflight.ts +25 -29
- package/scripts/run/run-prep-cli.ts +17 -13
- package/scripts/run/run-prep-locate.ts +4 -5
- package/scripts/run/run-prep.ts +7 -10
- package/scripts/run/run-prrun-resume.ts +2 -2
- package/scripts/run/run-report-cli.ts +4 -4
- package/scripts/run/run-report.ts +9 -14
- package/scripts/run/run-retrospective.ts +3 -3
- package/scripts/run/run-section.ts +42 -0
- package/scripts/run/run-stage-read.ts +2 -2
- package/scripts/run/run-stage.ts +6 -4
- package/scripts/run/run-status-cli.ts +7 -5
- package/scripts/run/run-status.ts +6 -7
- package/scripts/run/run-step-cli.ts +64 -18
- package/scripts/run/run-step.ts +107 -51
- package/scripts/run/run-stop-notify.ts +7 -8
- package/scripts/run/run-stranded-cli.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +4 -4
- package/scripts/run/run-stranded.ts +11 -13
- package/scripts/run/run-tail-cli.ts +15 -16
- package/scripts/run/run-tail.ts +14 -33
- package/scripts/run/run-watcher-guard-cli.ts +3 -4
- package/scripts/run/run-watcher-guard.ts +11 -12
- package/scripts/run/run-watcher-hook.ts +6 -12
- package/scripts/run/ship/run-ship-cli.ts +67 -33
- package/scripts/run/ship/run-ship-detach.ts +15 -13
- package/scripts/run/ship/run-ship-lock.ts +1 -1
- package/scripts/run/ship/run-ship-next.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
- package/scripts/run/ship/run-ship-preflight.ts +10 -11
- package/scripts/run/ship/run-ship-probe.ts +4 -4
- package/scripts/run/ship/run-ship-return.ts +1 -1
- package/scripts/run/ship/run-ship-review-steps.ts +43 -24
- package/scripts/run/ship/run-ship-review.ts +12 -14
- package/scripts/run/ship/run-ship-scoped.ts +15 -6
- package/scripts/run/ship/run-ship-stage.ts +80 -26
- package/scripts/run/ship/run-ship-steps.ts +26 -16
- package/scripts/run/ship/run-ship-stop-text.ts +4 -2
- package/scripts/run/ship/run-ship-sync.ts +9 -8
- package/scripts/run/ship/run-ship.ts +17 -32
- package/scripts/run/tidy/run-tidy-cli.ts +9 -5
- package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
- package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
- package/scripts/run/tidy/run-tidy.ts +4 -3
- package/scripts/run/wake/run-wake-cli.ts +27 -32
- package/scripts/run/wake/run-wake-describe.ts +24 -28
- package/scripts/run/wake/run-wake-driver.ts +14 -14
- package/scripts/run/wake/run-wake-handoff.ts +6 -6
- package/scripts/run/wake/run-wake-loop.ts +9 -9
- package/scripts/run/wake/run-wake-restart.ts +4 -5
- package/scripts/run/wake/run-wake-session.ts +23 -27
- package/scripts/run/wake/run-wake.ts +57 -279
- package/scripts/safe-chain/ci-installer-pin.ts +3 -3
- package/scripts/safe-chain/pack-hook.ts +2 -2
- package/scripts/safe-chain/preinstall-command.ts +2 -2
- package/scripts/security/security-audit-logic.ts +1 -1
- package/scripts/security/security-audit-provision-logic.ts +1 -1
- package/scripts/security/security-audit-provision.ts +2 -2
- package/scripts/security/security-audit.ts +5 -5
- package/scripts/security/security-updates-logic.ts +2 -3
- package/scripts/security/security-updates.ts +2 -4
- package/scripts/self-sync-guard/index.ts +1 -1
- package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
- package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
- package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
- package/scripts/sonar/sonar-hotspots.ts +1 -1
- package/scripts/sonar/sonar-new-code-cli.ts +1 -1
- package/scripts/sonar/sonar-new-code.ts +1 -1
- package/scripts/sonar/sonar-project.ts +1 -1
- package/scripts/split/split-assess-cli.ts +1 -1
- package/scripts/split/split-assess.ts +3 -3
- package/scripts/sync/directory-copy-guard.ts +2 -3
- package/scripts/sync/managed-config-scope-cli.ts +1 -2
- package/scripts/sync/managed-config-scope.ts +4 -4
- package/scripts/sync/plugin-skill-directories.ts +2 -2
- package/scripts/sync/reconcile-templates.ts +17 -8
- package/scripts/sync/removed-skill-manifest.ts +2 -3
- package/scripts/sync/sync-ai-files.ts +7 -7
- package/scripts/sync/sync-configs.ts +30 -3
- package/scripts/sync/sync-hook-safety.ts +2 -2
- package/scripts/sync/sync.ts +23 -10
- package/scripts/sync/synced-paths.ts +2 -1
- package/scripts/sync/workflow-pin-logic.ts +1 -1
- package/scripts/test/test-declared-changed.ts +4 -4
- package/scripts/test/test-declared-logic.ts +2 -3
- package/scripts/test/test-declared-match.ts +25 -4
- package/scripts/test/test-declared.ts +26 -9
- package/scripts/test/test-red-commit.ts +3 -2
- package/scripts/test/test-red-logic.ts +7 -14
- package/scripts/test/test-red.ts +12 -47
- package/scripts/test/test-related-scope.ts +2 -3
- package/scripts/test/test-related.ts +3 -3
- package/scripts/test/test-type-logic.ts +1 -2
- package/scripts/test/test-unit-guard.ts +13 -17
- package/scripts/test/unit-worker-share.ts +7 -8
- package/scripts/time-runtime/time-agent-bundles.ts +2 -4
- package/scripts/time-runtime/time-background.ts +17 -21
- package/scripts/time-runtime/time-batch-guard.ts +67 -342
- package/scripts/time-runtime/time-bundle-call.ts +26 -28
- package/scripts/time-runtime/time-bundles.ts +11 -12
- package/scripts/time-runtime/time-call-identity.ts +1 -1
- package/scripts/time-runtime/time-command-key.ts +2 -2
- package/scripts/time-runtime/time-density-hook.ts +8 -11
- package/scripts/time-runtime/time-density.ts +5 -5
- package/scripts/time-runtime/time-followup-stage.ts +7 -7
- package/scripts/time-runtime/time-format.ts +5 -5
- package/scripts/time-runtime/time-hook-transcript.ts +3 -3
- package/scripts/time-runtime/time-instant.ts +1 -1
- package/scripts/time-runtime/time-markers.ts +15 -19
- package/scripts/time-runtime/time-phase-names.ts +3 -3
- package/scripts/time-runtime/time-reported-failure.ts +15 -19
- package/scripts/time-runtime/time-round-trips.ts +20 -23
- package/scripts/time-runtime/time-shell.ts +8 -8
- package/scripts/time-runtime/time-single-check.ts +1 -2
- package/scripts/time-runtime/time-spans.ts +35 -40
- package/scripts/time-runtime/time-tool-call.ts +15 -16
- package/scripts/time-runtime/time-transcript-line.ts +53 -34
- package/scripts/time-runtime/time-writes.ts +5 -5
- package/scripts/ui/ui-routes-cli.ts +1 -2
- package/scripts/ui/ui-routes.ts +1 -2
- package/scripts/version/bump-version.ts +1 -1
- package/scripts/version/fresh-metadata-cache.ts +2 -2
- package/scripts/version/latest-corepack.ts +26 -26
- package/scripts/version/latest-lane-guard.ts +1 -1
- package/scripts/version/latest-scope-cli.ts +2 -2
- package/scripts/version/latest-stamp.ts +1 -2
- package/scripts/version/latest-update.ts +2 -2
- package/scripts/version/npm-registry.ts +2 -2
- package/scripts/version/package-manager-version.ts +18 -0
- package/scripts/version/publishable-range-check.ts +2 -1
- package/scripts/version/publishable-range.ts +1 -1
- package/scripts/version/release-age.ts +11 -11
- package/scripts/version/release-hold.ts +2 -2
- package/scripts/version/safe-chain-version-update.ts +3 -3
- package/scripts/version/version-check-logic.ts +2 -3
- package/scripts/version/version-check.ts +1 -2
- package/scripts/version/version-command-config.ts +2 -2
- package/scripts/version/version-commands.ts +3 -3
- package/scripts/version/version-remote.ts +4 -4
- package/scripts/version/version-targets.ts +2 -2
- package/templates/gitignore +7 -0
- package/dist/hooks/chunk-KHX4U3BG.js +0 -6400
- package/dist/hooks/chunk-RKUAD3I6.js +0 -90
- package/dist/hooks/chunk-WPALEIRX.js +0 -18
- package/scripts/backlog/backlog-restructure.ts +0 -152
- package/scripts/rules/issue-fold-rule.ts +0 -72
- package/scripts/rules/wip-cap.ts +0 -63
- package/scripts/run/run-issue-number.ts +0 -19
|
@@ -10,9 +10,9 @@ import { cutoff_cause, cutoff_of, type ScanCutoff } from '#scripts/git/listing-c
|
|
|
10
10
|
import { read_json_listing } from '#scripts/git/parse-json-array'
|
|
11
11
|
import { git_next_issues } from '#scripts/issue/git-next-issues'
|
|
12
12
|
import { AUTO_OK_LABEL } from '#scripts/issue/issue-labels'
|
|
13
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
13
14
|
|
|
14
|
-
// `josh auto-ok:next` — which issue outside the epic an unattended run picks up next
|
|
15
|
-
// (joshuafolkken/kit#906).
|
|
15
|
+
// `josh auto-ok:next` — which issue outside the epic an unattended run picks up next.
|
|
16
16
|
//
|
|
17
17
|
// A command rather than a documented `gh` invocation, for the reason the label constant exists: the
|
|
18
18
|
// name `auto-ok` is single-sourced in `scripts/issue/issue-labels.ts`, and a procedure that told an
|
|
@@ -33,29 +33,23 @@ const USAGE = `Usage: josh auto-ok:next [${EXCLUDE_FLAG} <issue-number>[,<issue-
|
|
|
33
33
|
const NONE_TOKEN = 'none'
|
|
34
34
|
// Wide enough that the cap is never what decides the order. The listing is newest first because
|
|
35
35
|
// `git-gh-issue-list.ts` spells `sort=created&direction=desc` into every request rather than leaning
|
|
36
|
-
// on REST's default
|
|
36
|
+
// on REST's default, so a truncated listing drops the *oldest* opted-in
|
|
37
37
|
// issues — which is reported rather than silently ranked.
|
|
38
38
|
const LISTING_LIMIT = 200
|
|
39
39
|
|
|
40
40
|
// Two different gaps, told apart because they send a person to two different places. A listing that
|
|
41
41
|
// never arrived is an access or connectivity problem; a listing that arrived in a shape the schema
|
|
42
42
|
// rejects is the rows' fields having changed under the REST mapping in `git-gh-issue-rest.ts`, where
|
|
43
|
-
// `gh auth status` is green and checking it wastes the one hint the message had to give
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
// The second message named `gh --version` until joshuafolkken/kit#1069. The listing has been REST
|
|
47
|
-
// since joshuafolkken/kit#1025 and `git-gh-issue-list.ts` builds the JSON this parser reads, so the
|
|
48
|
-
// CLI's version cannot be what changed the row shape — the same misdirection the message below
|
|
49
|
-
// already refuses to repeat for the blocker relations, left standing one constant above it.
|
|
43
|
+
// `gh auth status` is green and checking it wastes the one hint the message had to give. Neither
|
|
44
|
+
// names `gh --version`: the listing is REST and `git-gh-issue-list.ts` builds the JSON this parser
|
|
45
|
+
// reads, so the CLI's version cannot be what changed the row shape.
|
|
50
46
|
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
47
|
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
48
|
// The blocker relations failing takes the whole listing with them, and `issue_list` swallows
|
|
53
49
|
// the error — so the read looks exactly like an access failure and sends the reader to
|
|
54
|
-
// `gh auth status`, which is green
|
|
55
|
-
// above to remove, walked straight back in by the field the same change started asking for
|
|
56
|
-
// (joshuafolkken/kit#1005).
|
|
50
|
+
// `gh auth status`, which is green — the misdirection the message above exists to remove.
|
|
57
51
|
//
|
|
58
|
-
// The
|
|
52
|
+
// The cause is not `gh`'s version either: the relations come from each
|
|
59
53
|
// issue's own `dependencies/blocked_by` endpoint, and it is those requests — not the CLI — that the
|
|
60
54
|
// probe has just shown to be the difference. Naming `gh --version` here would send a reader on a
|
|
61
55
|
// current `gh` to the one place the answer is not.
|
|
@@ -63,12 +57,12 @@ const UNEXPECTED_SHAPE_MESSAGE = `Read the \`${AUTO_OK_LABEL}\` listing but coul
|
|
|
63
57
|
// It names both causes rather than asserting one. The probe separates "the relations" from "the
|
|
64
58
|
// listing", and it cannot separate a host that does not serve dependencies from a rate limit reached
|
|
65
59
|
// by the one-request-per-blocked-issue pass — so claiming the first would be the same misdirection
|
|
66
|
-
// in a new place
|
|
60
|
+
// in a new place.
|
|
67
61
|
const BLOCKERS_UNREADABLE_MESSAGE = `Could not read the \`${AUTO_OK_LABEL}\` listing, though the same listing reads once the blocker relations are dropped from it — so it is reading the relations that failed, not your authentication. That is one \`dependencies/blocked_by\` request per opted-in issue declaring a blocker: either this GitHub host does not serve issue dependencies, or those requests are being rate limited. Ask again, and check the host if it persists.`
|
|
68
62
|
// Said once the answer is known, so it never claims there is an answer below when there is not.
|
|
69
63
|
// Either cutoff only ever drops the *oldest* opted-in issues, the listing being newest first, so the
|
|
70
64
|
// consequence is one sentence — but the two cite different numbers and a reader who wants the
|
|
71
|
-
// listing widened reaches for a different knob for each
|
|
65
|
+
// listing widened reaches for a different knob for each.
|
|
72
66
|
const TRUNCATED_BY_LIMIT = `hit the ${String(LISTING_LIMIT)}-issue cap`
|
|
73
67
|
const TRUNCATED_WITH_ANSWER =
|
|
74
68
|
'; the answer below is opted in, but it may not be the highest-priority one.'
|
|
@@ -81,8 +75,8 @@ function truncated_cause(cutoff: ScanCutoff): string | undefined {
|
|
|
81
75
|
|
|
82
76
|
const NONE_OPTED_IN_MESSAGE = `No open issue carries \`${AUTO_OK_LABEL}\`.`
|
|
83
77
|
// The epic listing failing is not "no epic tracks anything". Read that way, every child of every
|
|
84
|
-
// epic reads as a standalone candidate and the pickup hands one back out of its epic's order
|
|
85
|
-
//
|
|
78
|
+
// epic reads as a standalone candidate and the pickup hands one back out of its epic's order,
|
|
79
|
+
// arriving with exit 0 and nothing said.
|
|
86
80
|
const EPICS_UNREADABLE_MESSAGE = `Could not read the epic listing, so which issues an epic already tracks is unknown. That is not "no epic tracks anything" — an opted-in child would be handed back outside its epic's order, so no answer is given. Check \`gh auth status\` and ask again.`
|
|
87
81
|
const CLOSED_STATE = 'CLOSED'
|
|
88
82
|
const NO_CUTOFF: ScanCutoff = 'none'
|
|
@@ -91,12 +85,12 @@ const NO_CUTOFF: ScanCutoff = 'none'
|
|
|
91
85
|
// effect asynchronously, so for a few seconds after a merge the issue is still listed as open —
|
|
92
86
|
// which is why `prioritize` takes this number at all, and why a pickup loop that never passes it
|
|
93
87
|
// leaves an already-merged issue to be excluded only by the `in-progress` label it happens to still
|
|
94
|
-
// carry
|
|
88
|
+
// carry.
|
|
95
89
|
interface NextOptions {
|
|
96
90
|
// Every number the caller asked to skip. A pickup loop passes the ones it has already run this
|
|
97
91
|
// session, not just the last: `closes #N` can fail to fire — a reference dropped from a PR body —
|
|
98
92
|
// and the `in-progress` label the procedure itself calls an unreliable guard is then the only
|
|
99
|
-
// thing standing between the loop and running an issue twice
|
|
93
|
+
// thing standing between the loop and running an issue twice.
|
|
100
94
|
exclude?: ReadonlyArray<number>
|
|
101
95
|
usage?: string
|
|
102
96
|
}
|
|
@@ -134,7 +128,7 @@ function parse_pair(argv: ReadonlyArray<string>, index: number): ReadonlyArray<n
|
|
|
134
128
|
// argument.
|
|
135
129
|
//
|
|
136
130
|
// `usage` is a parameter so a second command with the same `--exclude` grammar reuses this rather
|
|
137
|
-
// than copying the loop — `josh backlog:next` does
|
|
131
|
+
// than copying the loop — `josh backlog:next` does. Only the line printed on
|
|
138
132
|
// a bad argument differs between them, and a caller that passes nothing gets this command's own.
|
|
139
133
|
function parse_options(argv: ReadonlyArray<string>, usage: string = USAGE): NextOptions {
|
|
140
134
|
const exclude: Array<number> = []
|
|
@@ -150,23 +144,22 @@ function parse_options(argv: ReadonlyArray<string>, usage: string = USAGE): Next
|
|
|
150
144
|
|
|
151
145
|
// Every open issue carrying the label, or which of two gaps stopped the read. Neither gap is an
|
|
152
146
|
// empty listing: reading a failed read as "none" ends the run reporting a confident absence built on
|
|
153
|
-
// a response nobody parsed
|
|
147
|
+
// a response nobody parsed. They stay apart from each other because the zod
|
|
154
148
|
// rejection `parse_json_array_or_undefined` deliberately rethrows means the listing's *fields*
|
|
155
|
-
// changed, not that the caller's authentication lapsed
|
|
149
|
+
// changed, not that the caller's authentication lapsed.
|
|
156
150
|
type OptedInRead =
|
|
157
151
|
| { kind: 'read'; issues: Array<OpenIssueData>; cutoff: ScanCutoff }
|
|
158
152
|
| { kind: 'unreadable' }
|
|
159
153
|
| { kind: 'unexpected_shape' }
|
|
160
154
|
| { kind: 'blockers_unreadable' }
|
|
161
155
|
|
|
162
|
-
// The two gaps `read_json_listing` names, carried through unchanged.
|
|
163
|
-
// `raw` is the JSON `git-gh-issue-list.ts` assembles from the REST rows rather than a CLI's stdout,
|
|
156
|
+
// The two gaps `read_json_listing` names, carried through unchanged. `raw` is the JSON `git-gh-issue-list.ts` assembles from the REST rows rather than a CLI's stdout,
|
|
164
157
|
// so a transport failure — a rate limit, a dropped connection — never reaches this parser at all:
|
|
165
158
|
// `issue_list` catches it into `json === undefined` and `classify_failed_read` decides what it
|
|
166
159
|
// was. What does reach here is the rethrown zod rejection, meaning the listing arrived and its
|
|
167
160
|
// *fields* were not what was asked for. `unreadable` is passed on rather than folded away because
|
|
168
|
-
// reading a gap as an empty listing is
|
|
169
|
-
// not the place to make that assumption.
|
|
161
|
+
// reading a gap as an empty listing is a confident absence built on a response nobody parsed, and
|
|
162
|
+
// this is not the place to make that assumption.
|
|
170
163
|
function parse_listing(raw: string, is_capped: boolean): OptedInRead {
|
|
171
164
|
const read = read_json_listing(raw, open_issue_schema)
|
|
172
165
|
if (read.kind !== 'read') return { kind: read.kind }
|
|
@@ -180,8 +173,7 @@ function parse_listing(raw: string, is_capped: boolean): OptedInRead {
|
|
|
180
173
|
|
|
181
174
|
// Whether the *identical* listing reads once `blockedBy` is dropped from it. Named for what it
|
|
182
175
|
// answers rather than for what it implies, because the two are opposite: a `true` here means the
|
|
183
|
-
// field was the problem
|
|
184
|
-
// its one call site inverted it back (joshuafolkken/kit#1005).
|
|
176
|
+
// field was the problem.
|
|
185
177
|
//
|
|
186
178
|
// **Only the field list changes.** Varying the limit as well would let a rate limit or a timeout that
|
|
187
179
|
// a smaller request happens to survive read as the blocker relations failing, on a host that serves
|
|
@@ -200,8 +192,7 @@ async function reads_without_blocked_by(): Promise<boolean> {
|
|
|
200
192
|
// success of that form is not enough on its own: a network blip or a passing rate limit on the first
|
|
201
193
|
// read clears by the time the probe runs, and the run would then send someone whose host serves
|
|
202
194
|
// dependencies perfectly well to look at it. `issue_list` swallows the underlying error, so
|
|
203
|
-
// repeating the original read is what separates a transient failure from a standing one
|
|
204
|
-
// (joshuafolkken/kit#1005).
|
|
195
|
+
// repeating the original read is what separates a transient failure from a standing one.
|
|
205
196
|
async function classify_failed_read(): Promise<OptedInRead> {
|
|
206
197
|
if (!(await reads_without_blocked_by())) return { kind: 'unreadable' }
|
|
207
198
|
|
|
@@ -226,14 +217,12 @@ async function fetch_opted_in(): Promise<OptedInRead> {
|
|
|
226
217
|
// relation `epic:next` builds its graph from, and each blocker's state comes back alongside its
|
|
227
218
|
// number, so no blocker needs a read of its own.
|
|
228
219
|
//
|
|
229
|
-
// The relations are not in the listing response at all
|
|
230
|
-
// them from each issue's own dependencies endpoint — so this pickup pays one extra request per row
|
|
220
|
+
// The relations are not in the listing response at all — REST serves them from each issue's own dependencies endpoint — so this pickup pays one extra request per row
|
|
231
221
|
// whose own dependency summary does not report exactly zero blockers, and nothing for the rest.
|
|
232
222
|
//
|
|
233
223
|
// An unattended run must not start an issue whose prerequisite is still open: `auto-ok` is applied
|
|
234
|
-
// by a person to an issue they judged needs no decision, which says nothing about ordering
|
|
235
|
-
//
|
|
236
|
-
// (joshuafolkken/kit#996). A blocker with no state reads as standing — the safe direction, since the
|
|
224
|
+
// by a person to an issue they judged needs no decision, which says nothing about ordering.
|
|
225
|
+
// A blocker with no state reads as standing — the safe direction, since the
|
|
237
226
|
// cost is deferring an issue rather than implementing one out of order.
|
|
238
227
|
// `nodes` is a page — fifty under GraphQL, one hundred under REST. When `totalCount` says there are
|
|
239
228
|
// more, the ones outside the page are unknown, and unknown reads as standing — the same direction
|
|
@@ -248,7 +237,7 @@ function is_page_complete(blocked_by: OpenIssueData['blockedBy']): boolean {
|
|
|
248
237
|
|
|
249
238
|
// `epic_issue.normalize_state` rather than a second spelling of it: the epic commands already read
|
|
250
239
|
// GitHub's state casing through one function, and "is this blocker closed" is the question it
|
|
251
|
-
// answers
|
|
240
|
+
// answers. A blocker reported without a state reads as standing.
|
|
252
241
|
function is_closed(blocker: { state?: string | undefined }): boolean {
|
|
253
242
|
return epic_issue.normalize_state(blocker.state ?? '') === CLOSED_STATE
|
|
254
243
|
}
|
|
@@ -261,21 +250,20 @@ function is_unblocked(issue: OpenIssueData): boolean {
|
|
|
261
250
|
|
|
262
251
|
// Which issues an epic already tracks, or that the epic listing could not be read.
|
|
263
252
|
//
|
|
264
|
-
// **The question is membership, not a label
|
|
253
|
+
// **The question is membership, not a label**. An epic's child carries none
|
|
265
254
|
// of `epic` / `in-progress` / `needs-decision`, so the label comparison inside `prioritize` never
|
|
266
|
-
//
|
|
255
|
+
// sees one — and `auto-ok` on a child would put that child in the standalone candidate set, where the
|
|
267
256
|
// epic's `blockedBy` ordering is never consulted. The epics themselves are still found by the `epic`
|
|
268
257
|
// label, exactly as `epic:bundle` finds them, so this does not survive an epic that never received
|
|
269
|
-
// it — what it removes is the *child's* labels deciding
|
|
258
|
+
// it — what it removes is the *child's* labels deciding.
|
|
270
259
|
//
|
|
271
|
-
// **The whole index is carried rather than its key set
|
|
260
|
+
// **The whole index is carried rather than its key set**. Which epic tracks
|
|
272
261
|
// a child decides both whether the standalone half withholds it — `epic_index.withheld_children` —
|
|
273
|
-
// and, when it is withheld, the number `backlog:plan` names as the reason.
|
|
274
|
-
// here threw that number away, so the plan reported a listing cap it had never reached.
|
|
262
|
+
// and, when it is withheld, the number `backlog:plan` names as the reason.
|
|
275
263
|
//
|
|
276
|
-
// **And every tracking epic, not one winner
|
|
264
|
+
// **And every tracking epic, not one winner**. Two epics can name the same
|
|
277
265
|
// child, and a map of one epic per child keeps whichever came last — so an opted-in epic that came
|
|
278
|
-
// earlier
|
|
266
|
+
// earlier would vanish, and the child be offered standalone *and* through that epic.
|
|
279
267
|
type TrackingRead =
|
|
280
268
|
| { kind: 'read'; index: ReadonlyMap<number, ReadonlyArray<number>>; cutoff: ScanCutoff }
|
|
281
269
|
| { kind: 'epics_unreadable' }
|
|
@@ -313,8 +301,7 @@ async function fetch_tracking(count: number): Promise<TrackingRead> {
|
|
|
313
301
|
// The pickup *order* is `git_next_issues.order` itself, not a copy of it: the ranking `prioritize`
|
|
314
302
|
// shows, with the `epic` / `in-progress` / `needs-decision` exclusions, before its display cap.
|
|
315
303
|
//
|
|
316
|
-
// The two are
|
|
317
|
-
// also drops a candidate whose prerequisite is still open, while `🗒 Next issues` shows every open
|
|
304
|
+
// The two are not the same *set*, and deliberately so: the pickup also drops a candidate whose prerequisite is still open, while `🗒 Next issues` shows every open
|
|
318
305
|
// issue and leaves the judgement to the person reading it. So the display can name an issue this
|
|
319
306
|
// command refuses — a person can see a blocked issue is next and decide to start it anyway, and an
|
|
320
307
|
// unattended run must not.
|
|
@@ -326,20 +313,19 @@ async function fetch_tracking(count: number): Promise<TrackingRead> {
|
|
|
326
313
|
// `prioritize`'s capped one, which would answer `none` whenever its first rows happen to be blocked
|
|
327
314
|
// while a runnable issue sits below them. They are applied **after** the ranking, not before it: the
|
|
328
315
|
// dependents key counts the issues waiting on a row, and a waiting issue is by definition blocked —
|
|
329
|
-
// filtered first, every row would count zero and the key would never decide anything
|
|
330
|
-
// (joshuafolkken/kit#2928).
|
|
316
|
+
// filtered first, every row would count zero and the key would never decide anything.
|
|
331
317
|
//
|
|
332
318
|
// The `🗒 Next issues` display is deliberately *not* filtered this way; `git-next-issues.ts` records
|
|
333
319
|
// why, and the short version is that a person can see a blocked issue and choose to start it anyway
|
|
334
|
-
// while an unattended run cannot
|
|
320
|
+
// while an unattended run cannot.
|
|
335
321
|
//
|
|
336
322
|
// A child of an epic that is itself opted in is dropped here for the same reason and by the same
|
|
337
323
|
// rule: that epic's declared order sequences its children, and it is going to offer them, so a
|
|
338
|
-
// standalone offer would skip the order and hand the same issue over twice
|
|
339
|
-
// **A child of an epic that is *not* opted in is
|
|
340
|
-
//
|
|
341
|
-
// by the native `blockedBy` relations `is_unblocked` already refuses to run past
|
|
342
|
-
//
|
|
324
|
+
// standalone offer would skip the order and hand the same issue over twice.
|
|
325
|
+
// **A child of an epic that is *not* opted in is kept** — no path would otherwise offer it, which
|
|
326
|
+
// would make a person's `auto-ok` on the child silently inert, and the order it does have is carried
|
|
327
|
+
// by the native `blockedBy` relations `is_unblocked` already refuses to run past.
|
|
328
|
+
// `tracked` is the narrowed set `epic_index.withheld_children` builds, not
|
|
343
329
|
// every tracked child; this function only applies it.
|
|
344
330
|
function is_runnable(
|
|
345
331
|
issue: OpenIssueData,
|
|
@@ -370,7 +356,7 @@ function none_reason(count: number): string {
|
|
|
370
356
|
|
|
371
357
|
// Said only when the cap actually bit, and worded from the answer rather than before it: the one run
|
|
372
358
|
// where truncation matters is the one where everything listed was excluded, and announcing "the
|
|
373
|
-
// answer below is opted in" there contradicted the `none` that followed
|
|
359
|
+
// answer below is opted in" there contradicted the `none` that followed.
|
|
374
360
|
function truncation_note(cutoff: ScanCutoff, has_answer: boolean): string | undefined {
|
|
375
361
|
const cause = truncated_cause(cutoff)
|
|
376
362
|
if (cause === undefined) return undefined
|
|
@@ -414,14 +400,14 @@ function report(context: PickupContext): number {
|
|
|
414
400
|
return SUCCESS_EXIT_CODE
|
|
415
401
|
}
|
|
416
402
|
|
|
417
|
-
console.error(
|
|
403
|
+
console.error(session_cite.issue(next.number, next.title))
|
|
418
404
|
console.info(String(next.number))
|
|
419
405
|
|
|
420
406
|
return SUCCESS_EXIT_CODE
|
|
421
407
|
}
|
|
422
408
|
|
|
423
409
|
// The second listing runs only once the first one has an answer to filter, and its failure is
|
|
424
|
-
// reported rather than folded into "no epic tracks anything"
|
|
410
|
+
// reported rather than folded into "no epic tracks anything".
|
|
425
411
|
async function answer(
|
|
426
412
|
read: { issues: Array<OpenIssueData>; cutoff: ScanCutoff },
|
|
427
413
|
exclude?: ReadonlyArray<number>,
|
|
@@ -444,7 +430,7 @@ async function answer(
|
|
|
444
430
|
}
|
|
445
431
|
|
|
446
432
|
// The gap that stopped the read decides the message, so a changed field list does not send anyone to
|
|
447
|
-
// `gh auth status
|
|
433
|
+
// `gh auth status`.
|
|
448
434
|
const READ_FAILURE_MESSAGES = {
|
|
449
435
|
unreadable: UNREADABLE_MESSAGE,
|
|
450
436
|
unexpected_shape: UNEXPECTED_SHAPE_MESSAGE,
|
|
@@ -474,7 +460,7 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
474
460
|
// `process.exitCode` rather than `process.exit()`: the answer is written with `console.info`, and on
|
|
475
461
|
// macOS a write to a pipe is asynchronous — `process.exit()` can tear the process down before it has
|
|
476
462
|
// drained, and this command's whole contract is `answer=$(pnpm josh auto-ok:next)`. The same shape
|
|
477
|
-
// is already in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first
|
|
463
|
+
// is already in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first.
|
|
478
464
|
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
479
465
|
process.exitCode = await run(argv)
|
|
480
466
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
2
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
3
|
+
|
|
4
|
+
// Whether `pnpm josh run:add` handed the run an issue since the watcher started.
|
|
5
|
+
// The arrival probe reads the backlog once a minute, and a `--only` run's pool is empty by definition, so
|
|
6
|
+
// an added issue would otherwise wait for the minute — or never wake a `--only` parent at all. The event
|
|
7
|
+
// stream is a local file, so this is read on every tick rather than on the probe's interval.
|
|
8
|
+
|
|
9
|
+
type EventReader = () => Promise<ReadonlyArray<RunEvent>>
|
|
10
|
+
|
|
11
|
+
async function read_stream(): Promise<ReadonlyArray<RunEvent>> {
|
|
12
|
+
const target = await run_event_stream_emit.stream_target()
|
|
13
|
+
|
|
14
|
+
return target === undefined ? [] : run_event_stream.read_events(target)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function has_added_since(events: ReadonlyArray<RunEvent>, since_ms: number): boolean {
|
|
18
|
+
return events.some(
|
|
19
|
+
(event) => event.kind === run_event_stream.EVENT_KIND.ADD && Date.parse(event.at) >= since_ms,
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// A stream that cannot be read is no addition: the probe's own backlog read is still the fallback.
|
|
24
|
+
async function is_added_since(since_ms: number, read: EventReader = read_stream): Promise<boolean> {
|
|
25
|
+
try {
|
|
26
|
+
return has_added_since(await read(), since_ms)
|
|
27
|
+
} catch {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const backlog_arrival_added = { has_added_since, is_added_since }
|
|
33
|
+
|
|
34
|
+
export { backlog_arrival_added }
|
|
@@ -1,28 +1,30 @@
|
|
|
1
1
|
import { epic_triage } from '#scripts/epic/epic-triage'
|
|
2
2
|
import type { JoshResult } from '#scripts/josh/josh-run'
|
|
3
|
+
import { lane_limit_override } from '#scripts/lane/lane-limit-override'
|
|
3
4
|
import { COMMAND_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
4
5
|
import { run_headless } from '#scripts/run/run-headless'
|
|
6
|
+
import { backlog_arrival_added } from './backlog-arrival-added'
|
|
5
7
|
import { backlog_next } from './backlog-next'
|
|
6
8
|
import { backlog_ready, type ReadyPorts, type ReadyReading } from './backlog-ready'
|
|
7
9
|
import { backlog_stalled } from './backlog-stalled'
|
|
8
10
|
|
|
9
|
-
// The arrival probe a `backlogrun` parent's `--wait` watcher runs while children are in flight
|
|
10
|
-
//
|
|
11
|
-
// next
|
|
12
|
-
//
|
|
11
|
+
// The arrival probe a `backlogrun` parent's `--wait` watcher runs while children are in flight.
|
|
12
|
+
// Without it, an issue opted in with `auto-ok` mid-run is picked up only when the parent
|
|
13
|
+
// next wakes — a child's merge, or the progress interval — so in practice the ten-minute stall detector
|
|
14
|
+
// becomes the pick-up, and the person gets a ⏳ notification for the wait.
|
|
13
15
|
//
|
|
14
16
|
// **The watcher's exit is the only thing that wakes a live parent**, so the probe rides it: once a
|
|
15
17
|
// minute it reads the backlog the pick-up line reads (`backlog_ready.read_ready`, cheap first — a full
|
|
16
18
|
// pool answers without the network read), and an issue runnable now that was not runnable when the
|
|
17
19
|
// watcher started ends the wait. The exit prints the `ready #N` line as every exit does, and that line
|
|
18
|
-
// is what sends the parent to `backlog:offer`. The stall detector
|
|
20
|
+
// is what sends the parent to `backlog:offer`. The stall detector stays the safety net.
|
|
19
21
|
//
|
|
20
22
|
// **"New" is measured against the watcher's own start**, so one issue wakes the parent once: the next
|
|
21
23
|
// `--wait` the parent starts takes the pool as it stands then — the woken issue included, dispatched or
|
|
22
24
|
// not — as its baseline. A reading that fails is not an arrival; the probe says nothing and reads again
|
|
23
25
|
// a minute later. A baseline that cannot be read is never read as empty — an empty one would wake the
|
|
24
26
|
// parent for the whole pool — but it is not given up on either: the scheduled report no longer ends the
|
|
25
|
-
// wait
|
|
27
|
+
// wait, so an inert probe would leave the parent without a wake until `--hours`. The
|
|
26
28
|
// probe reads the baseline again each minute until one answers.
|
|
27
29
|
//
|
|
28
30
|
// **Every read is bounded.** The probe is awaited inside the watcher's tick loop, so a `gh` call that
|
|
@@ -54,7 +56,7 @@ function answered_issues(result: JoshResult | undefined): ReadonlyArray<string>
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
// `triage` names no number, yet the parent has work — so it is read as one token, which a reading
|
|
57
|
-
// sees as an arrival
|
|
59
|
+
// sees as an arrival.
|
|
58
60
|
if (backlog_stalled.needs_triage(result.out)) return [epic_triage.TRIAGE_VERDICT]
|
|
59
61
|
|
|
60
62
|
return backlog_stalled.ready_tokens(result.out)
|
|
@@ -64,20 +66,32 @@ async function bounded_ready_issues(): Promise<ReadonlyArray<string>> {
|
|
|
64
66
|
return answered_issues(await backlog_ready.read_backlog_next(COMMAND_TIMEOUT_MS))
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
69
|
+
// The backlog reads, plus whether `run:add` handed the run an issue since a given instant.
|
|
70
|
+
interface ArrivalPorts extends ReadyPorts {
|
|
71
|
+
is_added_since: (since_ms: number) => Promise<boolean>
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const ARRIVAL_PORTS: ArrivalPorts = {
|
|
68
75
|
free_lane_count: backlog_ready.free_lane_count,
|
|
69
76
|
ready_issues: bounded_ready_issues,
|
|
77
|
+
is_added_since: backlog_arrival_added.is_added_since,
|
|
70
78
|
}
|
|
71
79
|
|
|
72
80
|
interface ArrivalProbe {
|
|
73
81
|
has_arrived: (now_ms: number) => Promise<boolean>
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
// Runnable now, not runnable at the start, and a lane free to take it.
|
|
77
|
-
|
|
84
|
+
// Runnable now, not runnable at the start, and a lane free to take it. **A raised lane limit makes the
|
|
85
|
+
// whole pool new**: the issues the baseline holds were waiting for a lane, and
|
|
86
|
+
// the raise — unlike a merge — wakes nothing else, so the room it made would sit idle until a merge.
|
|
87
|
+
function arrivals(
|
|
88
|
+
baseline: ReadonlySet<string>,
|
|
89
|
+
reading: ReadyReading,
|
|
90
|
+
is_raised: boolean,
|
|
91
|
+
): ReadonlyArray<string> {
|
|
78
92
|
if (reading.free_lanes <= NO_FREE) return []
|
|
79
93
|
|
|
80
|
-
return reading.issues.filter((issue) => !baseline.has(issue))
|
|
94
|
+
return is_raised ? reading.issues : reading.issues.filter((issue) => !baseline.has(issue))
|
|
81
95
|
}
|
|
82
96
|
|
|
83
97
|
// The baseline is the whole runnable pool, free lane or not: an issue that was waiting for a lane is not
|
|
@@ -132,10 +146,11 @@ async function retry_baseline(
|
|
|
132
146
|
// The next-probe instant is set before any read is awaited. A baseline that did not answer is read again
|
|
133
147
|
// at the next probe instead of the reading, and the first one that answers is the baseline from then on
|
|
134
148
|
// — never an arrival itself, since it is the pool as it stands.
|
|
135
|
-
function
|
|
149
|
+
function pool_probe_of(
|
|
136
150
|
initial: ReadonlySet<string> | undefined,
|
|
137
151
|
first_ms: number,
|
|
138
152
|
ports: ReadyPorts,
|
|
153
|
+
is_raised: () => boolean,
|
|
139
154
|
): ArrivalProbe {
|
|
140
155
|
let next_ms = first_ms
|
|
141
156
|
// At most one entry, held in a list so the baseline that answers after an await is added rather than
|
|
@@ -153,25 +168,47 @@ function probe_of(
|
|
|
153
168
|
|
|
154
169
|
const reading = await read_reading(ports)
|
|
155
170
|
|
|
156
|
-
return reading !== undefined && arrivals(baseline, reading).length > NONE
|
|
171
|
+
return reading !== undefined && arrivals(baseline, reading, is_raised()).length > NONE
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return { has_arrived }
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// An issue `run:add` handed the run since the watcher started wakes the parent at the next tick, ahead
|
|
178
|
+
// of the pool probe's minute.
|
|
179
|
+
function probe_of(
|
|
180
|
+
initial: ReadonlySet<string> | undefined,
|
|
181
|
+
started_ms: number,
|
|
182
|
+
ports: ArrivalPorts,
|
|
183
|
+
is_raised: () => boolean,
|
|
184
|
+
): ArrivalProbe {
|
|
185
|
+
const pool = pool_probe_of(initial, started_ms + PROBE_INTERVAL_MS, ports, is_raised)
|
|
186
|
+
|
|
187
|
+
async function has_arrived(now_ms: number): Promise<boolean> {
|
|
188
|
+
if (await ports.is_added_since(started_ms)) return true
|
|
189
|
+
|
|
190
|
+
return await pool.has_arrived(now_ms)
|
|
157
191
|
}
|
|
158
192
|
|
|
159
193
|
return { has_arrived }
|
|
160
194
|
}
|
|
161
195
|
|
|
162
196
|
// Inert outside a driving `backlogrun` parent — a `fullrun` watcher has no pool to pick from — and there
|
|
163
|
-
// it reads nothing at all.
|
|
197
|
+
// it reads nothing at all. The raise watch starts with the probe, so only a raise after it wakes.
|
|
164
198
|
async function start(
|
|
165
199
|
now_ms: number,
|
|
166
|
-
ports:
|
|
200
|
+
ports: ArrivalPorts = ARRIVAL_PORTS,
|
|
167
201
|
is_parent: () => Promise<boolean> = run_headless.is_backlog_parent,
|
|
202
|
+
watch_raise: () => Promise<() => boolean> = lane_limit_override.watch_raise,
|
|
168
203
|
): Promise<ArrivalProbe> {
|
|
169
204
|
if (!(await is_parent_safely(is_parent))) return INERT
|
|
170
205
|
|
|
171
|
-
|
|
206
|
+
const is_raised = await watch_raise()
|
|
207
|
+
|
|
208
|
+
return probe_of(await read_baseline(ports), now_ms, ports, is_raised)
|
|
172
209
|
}
|
|
173
210
|
|
|
174
211
|
const backlog_arrival = { PROBE_INTERVAL_MS, answered_issues, arrivals, start }
|
|
175
212
|
|
|
176
|
-
export type { ArrivalProbe }
|
|
213
|
+
export type { ArrivalPorts, ArrivalProbe }
|
|
177
214
|
export { backlog_arrival }
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
import { fileURLToPath } from 'node:url'
|
|
3
3
|
import { path_decision } from '#scripts/josh/path-decision'
|
|
4
4
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
backlog_budget,
|
|
7
|
+
type BacklogAnswer,
|
|
8
|
+
type BudgetDecision,
|
|
9
|
+
type BudgetInput,
|
|
10
|
+
} from './backlog-budget'
|
|
11
|
+
import { backlog_idle } from './backlog-idle'
|
|
6
12
|
|
|
7
13
|
// The thin half of `josh backlog:budget` (joshuafolkken/kit#1632): read the loop's state off the
|
|
8
14
|
// command line, hand it to the pure decision, print the verdict on stdout and the reason on stderr
|
|
@@ -12,6 +18,7 @@ const ARGV_OFFSET = 2
|
|
|
12
18
|
const SUCCESS_EXIT_CODE = 0
|
|
13
19
|
const FAILURE_EXIT_CODE = 1
|
|
14
20
|
const JSON_KEY = 'budget'
|
|
21
|
+
const EXHAUSTED_ANSWER: BacklogAnswer = 'exhausted'
|
|
15
22
|
|
|
16
23
|
const USAGE = `Usage: josh backlog:budget --answer <${backlog_budget.ANSWERS.join('|')}> --started <ISO-8601> [--active <ISO-8601>, required unless the watch is off] [--merged <count>] [--running <count>] [--max <count>] [--idle <minutes>, 0 to turn the watch off] [--json]`
|
|
17
24
|
|
|
@@ -158,6 +165,29 @@ function build_input(values: ParsedValues, now_ms: number): BudgetInput | undefi
|
|
|
158
165
|
return input_of(values, { answer, now_ms, started_at_ms })
|
|
159
166
|
}
|
|
160
167
|
|
|
168
|
+
// The idle window, carried only on the watch an empty backlog opens — the one `idle_decision` reaches,
|
|
169
|
+
// not the draining watch a reached bound returns while children still run — so `backlog:offer` can
|
|
170
|
+
// record when that wait ends (joshuafolkken/kit#3430).
|
|
171
|
+
function idle_of(input: BudgetInput, verdict: string): string | undefined {
|
|
172
|
+
const is_idle_watch =
|
|
173
|
+
verdict === backlog_budget.WATCH_VERDICT &&
|
|
174
|
+
input.answer === EXHAUSTED_ANSWER &&
|
|
175
|
+
backlog_budget.is_finish(input)
|
|
176
|
+
const window = is_idle_watch ? backlog_idle.window_of(input) : undefined
|
|
177
|
+
|
|
178
|
+
return window === undefined ? undefined : backlog_idle.text_of(window)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function print_json(input: BudgetInput, decision: BudgetDecision): void {
|
|
182
|
+
const { verdict, reason } = decision
|
|
183
|
+
const idle = idle_of(input, verdict)
|
|
184
|
+
const is_finish = backlog_budget.is_finish(input)
|
|
185
|
+
|
|
186
|
+
console.info(
|
|
187
|
+
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish, ...(idle !== undefined && { idle }) }),
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
|
|
161
191
|
function refuse(): number {
|
|
162
192
|
console.error(USAGE)
|
|
163
193
|
|
|
@@ -173,17 +203,15 @@ function run(argv: ReadonlyArray<string>, now_ms: number = Date.now()): number {
|
|
|
173
203
|
|
|
174
204
|
if (input === undefined) return refuse()
|
|
175
205
|
|
|
176
|
-
const
|
|
206
|
+
const decision = backlog_budget.decide(input)
|
|
177
207
|
|
|
178
208
|
if (values.json === true) {
|
|
179
|
-
|
|
180
|
-
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish: backlog_budget.is_finish(input) }),
|
|
181
|
-
)
|
|
209
|
+
print_json(input, decision)
|
|
182
210
|
|
|
183
211
|
return SUCCESS_EXIT_CODE
|
|
184
212
|
}
|
|
185
213
|
|
|
186
|
-
path_decision.print_decision(JSON_KEY, verdict, reason, false)
|
|
214
|
+
path_decision.print_decision(JSON_KEY, decision.verdict, decision.reason, false)
|
|
187
215
|
|
|
188
216
|
return SUCCESS_EXIT_CODE
|
|
189
217
|
}
|
|
@@ -1,38 +1,32 @@
|
|
|
1
|
-
// `josh backlog:budget` — whether a `backlogrun` may start more work, keep watching, or finish
|
|
2
|
-
// (joshuafolkken/kit#1632).
|
|
1
|
+
// `josh backlog:budget` — whether a `backlogrun` may start more work, keep watching, or finish.
|
|
3
2
|
//
|
|
4
|
-
// `backlog:next` says what may start; it says nothing about when the run itself should end.
|
|
5
|
-
// this
|
|
6
|
-
//
|
|
7
|
-
// needed a whole new session, or it ran to the 8-hour whole-run bound, which is a limit on waiting
|
|
8
|
-
// rather than a statement of scale.
|
|
3
|
+
// `backlog:next` says what may start; it says nothing about when the run itself should end. Without
|
|
4
|
+
// this a run would finish the moment the backlog read empty, so an issue a person opted in minutes
|
|
5
|
+
// later would need a whole new session.
|
|
9
6
|
//
|
|
10
|
-
// **The idle watch is on by default and the maximum is not
|
|
11
|
-
//
|
|
12
|
-
//
|
|
7
|
+
// **The idle watch is on by default and the maximum is not.** A `backlogrun` with neither flag given
|
|
8
|
+
// watches an empty backlog for `DEFAULT_IDLE_MINUTES` before it finishes, and takes as many issues as
|
|
9
|
+
// the backlog holds. `--idle 0` is how the watch is turned off.
|
|
13
10
|
//
|
|
14
11
|
// The decision is a command's rather than the loop's own arithmetic, for the reason `josh delegate`
|
|
15
12
|
// and `josh review:level` are commands: a count and an elapsed time kept in an agent's head are a
|
|
16
|
-
// one-shot judgement
|
|
17
|
-
// once and then never again while the run walked past it eight times.
|
|
13
|
+
// one-shot judgement — a threshold asked once and then never again while the run walks past it.
|
|
18
14
|
|
|
19
15
|
const MS_PER_MINUTE = 60_000
|
|
20
16
|
const MINUTES_PER_HOUR = 60
|
|
21
|
-
//
|
|
22
|
-
//
|
|
17
|
+
// The whole-run bound, decided here like the idle watch and the maximum rather than by an agent reading
|
|
18
|
+
// a clock.
|
|
23
19
|
const WHOLE_RUN_BUDGET_HOURS = 8
|
|
24
20
|
const WHOLE_RUN_BUDGET_MINUTES = WHOLE_RUN_BUDGET_HOURS * MINUTES_PER_HOUR
|
|
25
21
|
const WHOLE_RUN_BUDGET_MS = WHOLE_RUN_BUDGET_MINUTES * MS_PER_MINUTE
|
|
26
22
|
|
|
27
|
-
// **The default idle watch, and why it is this number
|
|
28
|
-
// 30 as an example, and an example is not a reason; these three are.
|
|
23
|
+
// **The default idle watch, and why it is this number.**
|
|
29
24
|
//
|
|
30
25
|
// - **Below it the watch is a coin flip.** What it waits for is a person noticing the run has gone
|
|
31
26
|
// quiet, filing an issue and applying `auto-ok`. Ten minutes does not reliably outlast that.
|
|
32
27
|
// - **Above it the run pays for nothing.** At `IDLE_POLL_MINUTES` a 30-minute watch is six asks —
|
|
33
28
|
// about one child's worth of turns, spent while the run holds no working tree and no lane.
|
|
34
|
-
// - **It is about the length of one child** — 12 to 28 minutes measured
|
|
35
|
-
// so a run that has emptied its backlog waits roughly as long as one more issue would have taken.
|
|
29
|
+
// - **It is about the length of one child** — 12 to 28 minutes measured — so a run that has emptied its backlog waits roughly as long as one more issue would have taken.
|
|
36
30
|
const DEFAULT_IDLE_MINUTES = 30
|
|
37
31
|
const DEFAULT_IDLE_MS = DEFAULT_IDLE_MINUTES * MS_PER_MINUTE
|
|
38
32
|
|
|
@@ -51,10 +45,10 @@ const TRIAGE_VERDICT = 'triage'
|
|
|
51
45
|
|
|
52
46
|
// `run` — start what `backlog:next` offered. `watch` — sleep the polling interval and ask again,
|
|
53
47
|
// except while something of the run's own is in flight, where the wake is the progress watcher's exit
|
|
54
|
-
// and the interval is only a floor (`backlogrun.md` → "
|
|
55
|
-
// flight").
|
|
48
|
+
// and the interval is only a floor (`docs/maintainers/backlogrun-driver.md` → "Waiting while
|
|
49
|
+
// something is in flight").
|
|
56
50
|
// `stop` — report and finish. `triage` — judge the untriaged issues `backlog:next` named, then ask
|
|
57
|
-
// again
|
|
51
|
+
// again; it is the parent's to act on, so `backlog:drive` hands it back.
|
|
58
52
|
type BudgetVerdict =
|
|
59
53
|
typeof RUN_VERDICT | typeof WATCH_VERDICT | typeof STOP_VERDICT | typeof TRIAGE_VERDICT
|
|
60
54
|
|
|
@@ -141,8 +135,7 @@ function idle_watch_reason(left_ms: number): string {
|
|
|
141
135
|
return `The backlog is empty and the idle watch has about ${to_minutes(left_ms)} minutes left. Release the working tree, ask again in ${next_ask_minutes(left_ms)} minutes, and restart the watch the moment a candidate appears.`
|
|
142
136
|
}
|
|
143
137
|
|
|
144
|
-
// **A watch that opens while children are still in lanes is not the idle watch's ordinary shape
|
|
145
|
-
// it became reachable the moment the watch was turned on by default (joshuafolkken/kit#1676): the
|
|
138
|
+
// **A watch that opens while children are still in lanes is not the idle watch's ordinary shape**: the
|
|
146
139
|
// backlog can answer `exhausted` while this run's own children are still merging. Two things the
|
|
147
140
|
// sentence above would get wrong there — the working tree is still held, because the hold is released
|
|
148
141
|
// at the *last* child's merge, and a five-minute poll would leave a merge unnoticed for five minutes.
|
|
@@ -237,7 +230,7 @@ function idle_decision(input: BudgetInput): BudgetDecision {
|
|
|
237
230
|
// Whether a `stop` for this input is the run finishing — the idle watch ending on an empty backlog —
|
|
238
231
|
// rather than stopping on something a person must act on: a parked backlog, an unreadable listing, the
|
|
239
232
|
// maximum or the whole-run bound. The two end the carry record differently (`--end` against
|
|
240
|
-
// `--end --stopped`), and `backlog:drive` reads which one from here
|
|
233
|
+
// `--end --stopped`), and `backlog:drive` reads which one from here.
|
|
241
234
|
function is_finish(input: BudgetInput): boolean {
|
|
242
235
|
return stop_reason(input) === undefined && max_decision(input) === undefined
|
|
243
236
|
}
|