@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
|
@@ -3,6 +3,8 @@ import { fileURLToPath } from 'node:url'
|
|
|
3
3
|
import { git_gh_command } from '#scripts/gh/git-gh-command'
|
|
4
4
|
import { cutoff_of, type ScanCutoff } from '#scripts/git/listing-cutoff'
|
|
5
5
|
import { parse_json_array_or_undefined } from '#scripts/git/parse-json-array'
|
|
6
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
7
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
6
8
|
import { bounded_pool } from '#scripts/lib/bounded-pool'
|
|
7
9
|
import type { PollOptions } from '#scripts/lib/poll'
|
|
8
10
|
import { issue_citation } from '#scripts/rules/issue-citation'
|
|
@@ -19,10 +21,10 @@ import { epic_bundle_poll } from './epic-bundle-poll'
|
|
|
19
21
|
import { epic_bundle_referenced, type ReferencedContext } from './epic-bundle-referenced'
|
|
20
22
|
import { epic_index, epic_schema, type FetchedEpics } from './epic-index'
|
|
21
23
|
import { epic_issue } from './epic-issue'
|
|
22
|
-
import type
|
|
24
|
+
import { format_dependency_links, type IssueReference } from './epic-reference'
|
|
23
25
|
|
|
24
26
|
// `josh epic:bundle <N>` — after an issue is filed, look at the open backlog and say whether it
|
|
25
|
-
// belongs with something already there
|
|
27
|
+
// belongs with something already there.
|
|
26
28
|
//
|
|
27
29
|
// The machine finds the candidates; the decision to bundle is the caller's. This command prints what
|
|
28
30
|
// it found and what it recommends, and writes nothing.
|
|
@@ -37,12 +39,12 @@ const USAGE = 'Usage: josh epic:bundle <issue-number>'
|
|
|
37
39
|
const UNKNOWN_REPO_MESSAGE =
|
|
38
40
|
'Could not read this repository from `git remote`, so the backlog cannot be keyed by repository — check `gh auth status` and that this is a checkout with an `origin` remote.'
|
|
39
41
|
|
|
40
|
-
// The backlog listing asks for the title too
|
|
42
|
+
// The backlog listing asks for the title too. Kept apart from the epic
|
|
41
43
|
// listing's schema rather than made optional on one: the epic listing does not ask for the field, and
|
|
42
44
|
// a schema that tolerates its absence everywhere would let a missing title pass unnoticed here.
|
|
43
45
|
//
|
|
44
|
-
// `blocked_by_count` is the blocker count GitHub already puts in the listing response
|
|
45
|
-
//
|
|
46
|
+
// `blocked_by_count` is the blocker count GitHub already puts in the listing response.
|
|
47
|
+
// It is **nullish rather than defaulted**, and that is the whole safety of
|
|
46
48
|
// the read below: a row the listing carries no summary for must not be read as a row with no
|
|
47
49
|
// blockers, because that reading is what would silently drop a relation instead of costing a
|
|
48
50
|
// request. Nothing in today's pipeline is expected to arrive without one — the response carries the
|
|
@@ -56,8 +58,7 @@ const backlog_schema = epic_schema.extend({
|
|
|
56
58
|
|
|
57
59
|
type BacklogRow = z.infer<typeof backlog_schema>
|
|
58
60
|
|
|
59
|
-
// The epic index is `epic-index.ts`'s, shared with the `auto-ok` pickup
|
|
60
|
-
// joshuafolkken/kit#1633: both commands ask which epic tracks an issue, and a second copy of the
|
|
61
|
+
// The epic index is `epic-index.ts`'s, shared with the `auto-ok` pickup: both commands ask which epic tracks an issue, and a second copy of the
|
|
61
62
|
// task-list read would answer differently the first time that shape moved.
|
|
62
63
|
const { build_epic_index } = epic_index
|
|
63
64
|
|
|
@@ -80,21 +81,19 @@ async function epic_issue_relations(
|
|
|
80
81
|
|
|
81
82
|
// One read per backlog issue *that has blockers*, a few at a time.
|
|
82
83
|
//
|
|
83
|
-
//
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// (joshuafolkken/kit#1736). The listing that produced these rows already carries that same summary,
|
|
89
|
-
// so the zero is known *before* the read rather than inside it, and the read is skipped outright.
|
|
84
|
+
// A read is `gh api`: one REST request for the issue, and a second to its `dependencies/blocked_by`
|
|
85
|
+
// endpoint unless the issue's own dependency summary reports exactly zero blockers. The listing that
|
|
86
|
+
// produced these rows already carries that same summary, so the zero is known *before* the read
|
|
87
|
+
// rather than inside it, and the read is skipped outright — otherwise the command would pay one
|
|
88
|
+
// request for every open issue in the repository, a cost that grows with the backlog.
|
|
90
89
|
//
|
|
91
90
|
// One read would do if `gh` exposed the reverse of `blockedBy`, but it does not (`blocks` is not a
|
|
92
91
|
// JSON field), so a dependency declared on the *other* issue is only visible by asking that issue.
|
|
93
92
|
// Spawning all of them at once is what turns a rate limit into a wrong answer: a refused read becomes
|
|
94
93
|
// an empty relation list, and a bundle that should have been proposed is reported as "no strong
|
|
95
94
|
// signal" instead. Batching bounds the burst; the `unreadable` list below is what keeps a refused
|
|
96
|
-
// read from passing as an answer
|
|
97
|
-
// shared with the reference reads below it and with the eval suite
|
|
95
|
+
// read from passing as an answer. The pool itself is `bounded-pool.ts`,
|
|
96
|
+
// shared with the reference reads below it and with the eval suite.
|
|
98
97
|
const RELATION_CONCURRENCY = 8
|
|
99
98
|
const NO_BLOCKERS = 0
|
|
100
99
|
|
|
@@ -124,8 +123,8 @@ interface FetchedBacklog {
|
|
|
124
123
|
issues: Array<BacklogIssue>
|
|
125
124
|
unreadable: Array<number>
|
|
126
125
|
is_readable: boolean
|
|
127
|
-
// Why the backlog listing stopped short, or that it did not. A `ScanCutoff` rather than a flag
|
|
128
|
-
//
|
|
126
|
+
// Why the backlog listing stopped short, or that it did not. A `ScanCutoff` rather than a flag:
|
|
127
|
+
// the page ceiling bounds this listing too, and the two cutoffs
|
|
129
128
|
// cite different numbers.
|
|
130
129
|
cutoff?: ScanCutoff
|
|
131
130
|
has_epic_list?: boolean
|
|
@@ -158,7 +157,7 @@ function to_backlog_issue(
|
|
|
158
157
|
// What a caller does not need read for it. `issue:scout` asks about an issue that does not exist yet:
|
|
159
158
|
// it has no number, so no recorded dependency can name it and it declares none of its own — the
|
|
160
159
|
// relation reads cannot change its answer, and skipping them takes one request per open issue off the
|
|
161
|
-
// command a run makes before every filing
|
|
160
|
+
// command a run makes before every filing. `epic:bundle` leaves it unset and
|
|
162
161
|
// reads them exactly as before.
|
|
163
162
|
interface BacklogOptions {
|
|
164
163
|
include_relations?: boolean
|
|
@@ -212,7 +211,7 @@ const ACTION_LINES: Readonly<Record<string, string>> = {
|
|
|
212
211
|
|
|
213
212
|
// `Nothing to bundle.` is right when nothing was found, and wrong when an epic already tracks the
|
|
214
213
|
// issue — there the answer is actionable: a caller looking for somewhere to put a prerequisite adds
|
|
215
|
-
// it to *that* epic rather than creating a second one
|
|
214
|
+
// it to *that* epic rather than creating a second one.
|
|
216
215
|
const ALREADY_TRACKED_LINE = 'Already in an epic — add to that one, do not create a second.'
|
|
217
216
|
|
|
218
217
|
function headline(decision: BundleDecision): string {
|
|
@@ -223,22 +222,21 @@ function headline(decision: BundleDecision): string {
|
|
|
223
222
|
|
|
224
223
|
// The epics currently open, at this command's own listing limit. A failed read stays `undefined` and
|
|
225
224
|
// is reported: without the list, an issue an epic already tracks is told to create a second one —
|
|
226
|
-
// confidently, and with exit 0
|
|
225
|
+
// confidently, and with exit 0.
|
|
227
226
|
async function fetch_epics(): Promise<FetchedEpics | undefined> {
|
|
228
227
|
return await epic_index.fetch_epics(BACKLOG_LIMIT)
|
|
229
228
|
}
|
|
230
229
|
|
|
231
230
|
function format_numbers(numbers: ReadonlyArray<number>): string {
|
|
232
|
-
return numbers.map((issue_number) =>
|
|
231
|
+
return numbers.map((issue_number) => issue_cite.plain(issue_number)).join(', ')
|
|
233
232
|
}
|
|
234
233
|
|
|
235
234
|
// The order to record alongside the bundle. Bundling without it records the batch and loses the
|
|
236
235
|
// reason it is a batch, so the recommendation carries it rather than leaving it to be remembered.
|
|
237
236
|
function format_links(links: ReadonlyArray<{ blocker: number; blocked: number }>): string {
|
|
238
237
|
if (links.length === 0) return ' Order: none declared — do not invent one'
|
|
239
|
-
const arrows = links.map((link) => `#${String(link.blocker)} -> #${String(link.blocked)}`)
|
|
240
238
|
|
|
241
|
-
return ` Order: ${
|
|
239
|
+
return ` Order: ${format_dependency_links(links)}`
|
|
242
240
|
}
|
|
243
241
|
|
|
244
242
|
function format_order(
|
|
@@ -251,7 +249,7 @@ function format_order(
|
|
|
251
249
|
const children = epic_bundle.bundle_children(subject, members)
|
|
252
250
|
|
|
253
251
|
// The evidence goes under the order rather than beside the verdict: what it explains is the
|
|
254
|
-
// order, and a reader checking one reads straight on into the other
|
|
252
|
+
// order, and a reader checking one reads straight on into the other.
|
|
255
253
|
return [
|
|
256
254
|
` Children: ${format_numbers(children)}`,
|
|
257
255
|
format_links(epic_bundle.bundle_dependency_links(subject, members)),
|
|
@@ -261,7 +259,7 @@ function format_order(
|
|
|
261
259
|
|
|
262
260
|
// The verdicts that put the subject into an epic. Each one asserts that no epic already tracks it —
|
|
263
261
|
// `create_epic` asserts as much about the candidates too — and that negative is exactly what a cut
|
|
264
|
-
// epic listing cannot establish
|
|
262
|
+
// epic listing cannot establish. `none` is absent on purpose: it either
|
|
265
263
|
// names the epic it *found* tracking the subject, which a cut cannot unseat, or reports no candidate
|
|
266
264
|
// at all, which says nothing about epics.
|
|
267
265
|
const PLACING_ACTIONS: ReadonlySet<BundleAction> = new Set<BundleAction>([
|
|
@@ -306,7 +304,7 @@ async function read_backlog(repo: string, options?: BacklogOptions): Promise<Fet
|
|
|
306
304
|
const epics = build_epic_index(open_epics.epics)
|
|
307
305
|
// From the epic list itself, not from the index's values: an epic tracking no child yet has no
|
|
308
306
|
// entry in the index, and would enter the backlog as an ordinary issue that its own children then
|
|
309
|
-
// propose bundling with
|
|
307
|
+
// propose bundling with.
|
|
310
308
|
const epic_numbers = new Set(open_epics.epics.map((epic) => epic.number))
|
|
311
309
|
|
|
312
310
|
return {
|
|
@@ -319,7 +317,7 @@ async function read_backlog(repo: string, options?: BacklogOptions): Promise<Fet
|
|
|
319
317
|
|
|
320
318
|
// The backlog the decision is made from: the open listing, plus the referenced issues it could not
|
|
321
319
|
// show. Without the second half the command answers about a window that closes minutes after the
|
|
322
|
-
// follow-up issue is filed
|
|
320
|
+
// follow-up issue is filed.
|
|
323
321
|
async function widen_with_referenced(
|
|
324
322
|
subject: BacklogIssue,
|
|
325
323
|
backlog: FetchedBacklog,
|
|
@@ -360,7 +358,9 @@ function warn_cutoff(message: string | undefined): void {
|
|
|
360
358
|
// wording of each gap is `epic-bundle-gaps.ts`'s; what stays here is which gaps this command has.
|
|
361
359
|
function warn_about_gaps(backlog: FetchedBacklog): void {
|
|
362
360
|
if (backlog.unreadable.length > 0) {
|
|
363
|
-
|
|
361
|
+
const unreadable = backlog.unreadable.map((issue_number) => session_cite.issue(issue_number))
|
|
362
|
+
|
|
363
|
+
console.error(`⚠ Could not read ${unreadable.join(', ')}.`)
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
warn_cutoff(epic_bundle_gaps.backlog_gap(backlog.cutoff ?? NO_CUTOFF, BACKLOG_LIMIT))
|
|
@@ -373,7 +373,7 @@ function report_decision(subject: BacklogIssue, backlog: FetchedBacklog, repo: s
|
|
|
373
373
|
const decision = epic_bundle.decide_bundle(subject, others)
|
|
374
374
|
|
|
375
375
|
// The `Related:` / `Children:` listings name issues as `#N`; linkified here so the recommendation a
|
|
376
|
-
// run copies into its reply carries clickable references rather than bare ones
|
|
376
|
+
// run copies into its reply carries clickable references rather than bare ones.
|
|
377
377
|
const report = format_decision(decision, subject, others, is_established)
|
|
378
378
|
|
|
379
379
|
console.info(issue_citation.linkify(report, repo))
|
|
@@ -417,7 +417,9 @@ async function report_for(
|
|
|
417
417
|
const subject = backlog.issues.find((issue) => issue.number === issue_number)
|
|
418
418
|
|
|
419
419
|
if (subject === undefined) {
|
|
420
|
-
console.error(
|
|
420
|
+
console.error(
|
|
421
|
+
`${session_cite.issue(issue_number, undefined, repo)} is not an open issue in ${repo}.`,
|
|
422
|
+
)
|
|
421
423
|
|
|
422
424
|
return FAILURE_EXIT_CODE
|
|
423
425
|
}
|
|
@@ -436,8 +438,8 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
436
438
|
|
|
437
439
|
const repo = await git_gh_command.repo_get_name_with_owner()
|
|
438
440
|
|
|
439
|
-
// A repository that could not be read is refused rather than stood in for.
|
|
440
|
-
//
|
|
441
|
+
// A repository that could not be read is refused rather than stood in for. The members are keyed
|
|
442
|
+
// by repository and the blockers carry their own, so a
|
|
441
443
|
// placeholder matches nothing: every recorded dependency would vanish and the command would answer
|
|
442
444
|
// `Nothing to bundle.` with exit 0 — a confident verdict built on a read that failed, on the
|
|
443
445
|
// command a run consults before deciding an issue belongs nowhere.
|
|
@@ -453,7 +455,7 @@ async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
|
453
455
|
// `process.exitCode` rather than `process.exit()`: the answer goes to standard output and a write to
|
|
454
456
|
// a pipe is asynchronous on macOS, so exiting can tear the process down before it drains. This
|
|
455
457
|
// command's answer is what a workflow reads and acts on, which is exactly that pipe. The same shape
|
|
456
|
-
// is in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first
|
|
458
|
+
// is in `scripts/cost-runtime/cost-cli.ts`, which met the truncation first.
|
|
457
459
|
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
458
460
|
process.exitCode = await run(argv)
|
|
459
461
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
1
2
|
import { epic_bundle, type BacklogIssue } from './epic-bundle'
|
|
2
3
|
|
|
3
|
-
// The facts the bundle decision was already made from, printed beside the order it prints
|
|
4
|
-
// (joshuafolkken/kit#1737).
|
|
4
|
+
// The facts the bundle decision was already made from, printed beside the order it prints.
|
|
5
5
|
//
|
|
6
6
|
// `is_strong_signal` reads exactly two things — whether a body names the other issue's number, and
|
|
7
7
|
// whether a `blocked-by` is already recorded in either direction — and neither ever reached the
|
|
@@ -75,7 +75,7 @@ function member_pairs(
|
|
|
75
75
|
//
|
|
76
76
|
// The repository filter is the one `bundle_dependency_links` applies: a bare number declared in a
|
|
77
77
|
// member elsewhere would be resolved against this repository by the epic body, naming a different
|
|
78
|
-
// issue entirely
|
|
78
|
+
// issue entirely.
|
|
79
79
|
function ordering_evidence(
|
|
80
80
|
subject: BacklogIssue,
|
|
81
81
|
candidates: ReadonlyArray<BacklogIssue>,
|
|
@@ -118,8 +118,8 @@ const EVIDENCE_INDENT = ' '.repeat(EVIDENCE_INDENT_WIDTH)
|
|
|
118
118
|
|
|
119
119
|
function format_one(item: OrderingEvidence): string {
|
|
120
120
|
const { verb, where, order_prefix, order_suffix } = EVIDENCE_WORDING[item.kind]
|
|
121
|
-
const first =
|
|
122
|
-
const second =
|
|
121
|
+
const first = issue_cite.plain(item.first)
|
|
122
|
+
const second = issue_cite.plain(item.second)
|
|
123
123
|
const order = `${order_prefix}${first}${order_suffix}`
|
|
124
124
|
|
|
125
125
|
return `${EVIDENCE_INDENT}${second} ${verb} ${first}${where} — ${order}`
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { cutoff_cause, type ScanCutoff } from '#scripts/git/listing-cutoff'
|
|
2
2
|
|
|
3
|
-
// What `epic:bundle` could not see, said in the `⚠ … cap` shape
|
|
4
|
-
//
|
|
5
|
-
// than the command it warns from (joshuafolkken/kit#1067).
|
|
3
|
+
// What `epic:bundle` could not see, said in the `⚠ … cap` shape `epic:audit` uses. Split out of
|
|
4
|
+
// `epic-bundle-cli.ts` because the wording carries more explanation than the command it warns from.
|
|
6
5
|
//
|
|
7
6
|
// **Two listings, and two cuts each.** The listing decides *what* is hidden — a backlog issue, or
|
|
8
7
|
// the epic that tracks one — and the cut decides *which number to cite*, because a reader who wants
|
|
@@ -21,7 +20,7 @@ function backlog_gap(cutoff: ScanCutoff, limit: number): string | undefined {
|
|
|
21
20
|
|
|
22
21
|
// Named separately from the backlog's. What this one hides is *which epic tracks a candidate*, so
|
|
23
22
|
// `Nothing to bundle.` under it may mean "the epic was past the cut" rather than "no epic tracks
|
|
24
|
-
// it" — and acting on the second reading creates the duplicate epic
|
|
23
|
+
// it" — and acting on the second reading creates the duplicate epic.
|
|
25
24
|
function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
|
|
26
25
|
const cause = cutoff_cause(cutoff, `hit its ${String(limit)}-epic cap`)
|
|
27
26
|
if (cause === undefined) return undefined
|
|
@@ -36,8 +35,7 @@ function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
|
|
|
36
35
|
// the assertion is only as good as the epic listing it was read from: an epic past the cut tracks its
|
|
37
36
|
// children invisibly, so each of them reads as tracked by nothing. Acted on as Tier A, that absence
|
|
38
37
|
// puts a **second** epic over an issue one already tracks — the state `fullrun.md` forbids, because
|
|
39
|
-
// the auto-close then has two task lists to disagree about and `epic:next` answers from two graphs
|
|
40
|
-
// (joshuafolkken/kit#943).
|
|
38
|
+
// the auto-close then has two task lists to disagree about and `epic:next` answers from two graphs.
|
|
41
39
|
//
|
|
42
40
|
// A membership that *was* found is untouched, and that is the whole of what survives a cut: `none`
|
|
43
41
|
// reporting `#E already tracks this issue` read the epic it names, and more epics past the cut cannot
|
|
@@ -46,12 +44,11 @@ function epic_gap(cutoff: ScanCutoff, limit: number): string | undefined {
|
|
|
46
44
|
// The cut is the whole condition, and deliberately so. An epic the listing answered without a body
|
|
47
45
|
// would hide its children the same way, but it cannot arrive: the listing mapping coerces a REST
|
|
48
46
|
// `null` body to `''` before this module's caller ever parses one (`git-gh-issue-rest.ts`,
|
|
49
|
-
// `to_gh_field_value`), so a gate arm for it would be code no input can reach
|
|
50
|
-
// (joshuafolkken/kit#1697).
|
|
47
|
+
// `to_gh_field_value`), so a gate arm for it would be code no input can reach.
|
|
51
48
|
//
|
|
52
49
|
// The cutoff is optional because the fetched backlog carries it that way: a listing nothing capped
|
|
53
50
|
// records no cut at all, which is the same answer as `none`. Defaulted here rather than at each call
|
|
54
|
-
// site, so a caller holding the optional field cannot forget the coercion
|
|
51
|
+
// site, so a caller holding the optional field cannot forget the coercion.
|
|
55
52
|
function is_membership_established(cutoff: ScanCutoff = 'none'): boolean {
|
|
56
53
|
return cutoff === 'none'
|
|
57
54
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { poll, type PollOptions } from '#scripts/lib/poll'
|
|
2
2
|
|
|
3
|
-
// **The open listing trails the create call
|
|
3
|
+
// **The open listing trails the create call**: `issue:file` asks
|
|
4
4
|
// `epic:bundle` about the issue it has just filed, and the list endpoint had not shown it yet on every
|
|
5
5
|
// filing of one run, so the placement was skipped each time. A caller that knows the issue is fresh
|
|
6
6
|
// passes a poll and the listing is read again until it shows the issue. An unreadable listing is
|
|
@@ -6,22 +6,20 @@ import { epic_issue, type EpicIssue } from './epic-issue'
|
|
|
6
6
|
|
|
7
7
|
// Candidates the open backlog cannot show, read from the subject's own prose.
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// Past it the command reported `Nothing to bundle.` with exit 0, asserting there was no relation
|
|
13
|
-
// rather than that it had not looked (joshuafolkken/kit#947).
|
|
9
|
+
// The open backlog alone cannot answer: a follow-up issue names its parent, and the parent's pull
|
|
10
|
+
// request often merges minutes later. Searching open issues only would then report
|
|
11
|
+
// `Nothing to bundle.` with exit 0, asserting there was no relation rather than that it had not looked.
|
|
14
12
|
//
|
|
15
|
-
// The numbers a body names are information the command already holds; the open listing
|
|
16
|
-
// what
|
|
13
|
+
// The numbers a body names are information the command already holds; the open listing is not
|
|
14
|
+
// what supplies them. Only the *reading* of those issues needs a request, and this module decides
|
|
17
15
|
// which ones are worth one and which of the answers count.
|
|
18
16
|
|
|
19
17
|
// One read each, so the count is what bounds the cost. Chosen an order of magnitude above the
|
|
20
|
-
// references a real issue body carries
|
|
18
|
+
// handful of references a real issue body carries, so the cap is a runaway guard
|
|
21
19
|
// rather than something an ordinary issue reaches. A body naming more than this is prose about the
|
|
22
20
|
// backlog, not an issue with twenty prerequisites.
|
|
23
21
|
//
|
|
24
|
-
//
|
|
22
|
+
// A read is `gh api`, and one reference costs one REST request in the
|
|
25
23
|
// common case. Three cases cost two. The `dependencies/blocked_by` endpoint is asked unless the
|
|
26
24
|
// issue's own dependency summary reports exactly zero blockers, so an issue that declares one pays
|
|
27
25
|
// for it. So does a pull request, which the issue endpoint serves as readily as an issue and which
|
|
@@ -88,7 +86,7 @@ function to_backlog_issue(issue: EpicIssue, context: ReferencedContext): Backlog
|
|
|
88
86
|
function is_usable_candidate(issue: BacklogIssue, read: EpicIssue): boolean {
|
|
89
87
|
// The issue endpoint answers for a pull request too, and a body citing "the fix landed in #952"
|
|
90
88
|
// is ordinary prose. Without this, a merged PR reads as an open issue in no epic and the command
|
|
91
|
-
// proposes creating an epic with a pull request among its children
|
|
89
|
+
// proposes creating an epic with a pull request among its children.
|
|
92
90
|
if (issue.is_epic === true || epic_issue.is_pull_request(read)) return false
|
|
93
91
|
|
|
94
92
|
return epic_issue.is_open(read.state) || issue.epic !== undefined
|
|
@@ -96,8 +94,7 @@ function is_usable_candidate(issue: BacklogIssue, read: EpicIssue): boolean {
|
|
|
96
94
|
|
|
97
95
|
// How one referenced number came back. `missing` is GitHub resolving it to nothing — a typo, or a
|
|
98
96
|
// number belonging to another repository quoted in prose — which is an answer, not a gap: there is
|
|
99
|
-
// no candidate and nothing was lost. `unreadable` is the gap, and it is the only one reported
|
|
100
|
-
// (joshuafolkken/kit#957).
|
|
97
|
+
// no candidate and nothing was lost. `unreadable` is the gap, and it is the only one reported.
|
|
101
98
|
interface ReferencedRead {
|
|
102
99
|
number: number
|
|
103
100
|
result: EpicIssue | 'missing' | 'unreadable'
|
|
@@ -113,7 +110,7 @@ interface ReferencedResult {
|
|
|
113
110
|
// The ones whose read failed, and the ones the cap never reached. Both are gaps rather than
|
|
114
111
|
// answers: folded into "no relation found" they become the confident wrong verdict this whole
|
|
115
112
|
// module exists to remove. A number that resolves to nothing is **not** here — reporting it as a
|
|
116
|
-
// gap stops an unattended run over a reference that never existed
|
|
113
|
+
// gap stops an unattended run over a reference that never existed.
|
|
117
114
|
unreadable: Array<number>
|
|
118
115
|
}
|
|
119
116
|
|
|
@@ -156,7 +153,7 @@ async function read_one(number: number): Promise<ReferencedRead> {
|
|
|
156
153
|
|
|
157
154
|
// The pool is shared with the eval suite rather than spelled out again here: this was written as
|
|
158
155
|
// waves — slice, `Promise.all`, next slice — which holds every finished read's slot until the whole
|
|
159
|
-
// slice returns
|
|
156
|
+
// slice returns.
|
|
160
157
|
async function fetch_referenced(numbers: ReadonlyArray<number>): Promise<Array<ReferencedRead>> {
|
|
161
158
|
return await bounded_pool.bounded_map(
|
|
162
159
|
numbers,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { issue_cite } from '#scripts/issue/issue-cite'
|
|
1
2
|
import { epic_audit_logic } from './epic-audit'
|
|
2
3
|
import { epic_graph } from './epic-graph'
|
|
3
4
|
import type { DependencyLink } from './epic-parse'
|
|
@@ -7,11 +8,10 @@ import type { IssueReference } from './epic-reference'
|
|
|
7
8
|
//
|
|
8
9
|
// "Two or more always means an epic" already holds when one request is split on the spot. It does
|
|
9
10
|
// not reach the other way in: two issues filed days apart that turn out to be the front and back of
|
|
10
|
-
// one job are executed separately, in whatever order, with the reasoning recorded nowhere
|
|
11
|
-
// (joshuafolkken/kit#873).
|
|
11
|
+
// one job are executed separately, in whatever order, with the reasoning recorded nowhere.
|
|
12
12
|
//
|
|
13
|
-
// The candidate search reads issue references out of prose — the same reading
|
|
14
|
-
//
|
|
13
|
+
// The candidate search reads issue references out of prose — the same reading `epic:audit` does
|
|
14
|
+
// inside one epic. That analysis is imported rather than written a second time; the only
|
|
15
15
|
// difference is what it is pointed at.
|
|
16
16
|
|
|
17
17
|
// An open issue as the search sees it.
|
|
@@ -21,17 +21,17 @@ interface BacklogIssue {
|
|
|
21
21
|
body: string
|
|
22
22
|
// Optional because nothing in this module reads it: the strong signals below are references and
|
|
23
23
|
// recorded dependencies, and a title resemblance is deliberately not one of them. It rides on the
|
|
24
|
-
// same listing for `issue:scout`, whose duplicate search is the one thing that does compare titles
|
|
25
|
-
//
|
|
24
|
+
// same listing for `issue:scout`, whose duplicate search is the one thing that does compare titles,
|
|
25
|
+
// and is absent on an issue read one at a time by reference.
|
|
26
26
|
title?: string
|
|
27
27
|
// The epic tracking it, when one does. An issue belongs to at most one epic, because that is what
|
|
28
28
|
// a task list can express.
|
|
29
29
|
epic?: number
|
|
30
30
|
// Whether this issue *is* an epic. An epic is a container, not a sibling: every child names it as
|
|
31
31
|
// its parent, so without this every child would find its own epic as a candidate and be told to
|
|
32
|
-
// bundle with it
|
|
32
|
+
// bundle with it.
|
|
33
33
|
is_epic?: boolean
|
|
34
|
-
// Repository-qualified, not bare numbers
|
|
34
|
+
// Repository-qualified, not bare numbers. Issue numbers are unique per
|
|
35
35
|
// repository, so a blocker read as `40` alone matched any candidate numbered 40 — including one in
|
|
36
36
|
// a different repository entirely. That produced a bundle nobody's data supported, and, through
|
|
37
37
|
// `bundle_dependency_links`, a `blocked-by` relation recorded onto the wrong issue: a write, not
|
|
@@ -55,8 +55,7 @@ interface BundleDecision {
|
|
|
55
55
|
|
|
56
56
|
// Whether `from`'s body names `to`. One direction of the citation test, because which direction it
|
|
57
57
|
// was is what `epic-bundle-evidence.ts` reports — and the read is single-sourced here rather than
|
|
58
|
-
// written a second time there, so the candidate search and the evidence beside it cannot drift apart
|
|
59
|
-
// (joshuafolkken/kit#1737).
|
|
58
|
+
// written a second time there, so the candidate search and the evidence beside it cannot drift apart.
|
|
60
59
|
function names_in_body(from: BacklogIssue, to: BacklogIssue): boolean {
|
|
61
60
|
return epic_audit_logic.parse_references(from.body, from.repo).includes(to.number)
|
|
62
61
|
}
|
|
@@ -117,10 +116,10 @@ const NO_SIGNAL_REASON = 'no existing issue shares a reference or a dependency w
|
|
|
117
116
|
|
|
118
117
|
// Names the epic, rather than only reporting that one exists. The number is what the caller does
|
|
119
118
|
// something with: the prerequisite procedure inserts into that epic instead of creating a second one,
|
|
120
|
-
// and an issue tracked by two epics gives the auto-close two task lists to disagree about
|
|
121
|
-
//
|
|
119
|
+
// and an issue tracked by two epics gives the auto-close two task lists to disagree about.
|
|
120
|
+
// The decision already carried the number; only this sentence dropped it.
|
|
122
121
|
function already_tracked_reason(epic: number): string {
|
|
123
|
-
return
|
|
122
|
+
return `${issue_cite.plain(epic)} already tracks this issue`
|
|
124
123
|
}
|
|
125
124
|
|
|
126
125
|
const SPREAD_REASON =
|
|
@@ -132,13 +131,13 @@ function to_numbers(candidates: ReadonlyArray<BacklogIssue>): Array<number> {
|
|
|
132
131
|
|
|
133
132
|
function create_decision(subject: BacklogIssue, numbers: ReadonlyArray<number>): BundleDecision {
|
|
134
133
|
const count = String(numbers.length)
|
|
135
|
-
const reason =
|
|
134
|
+
const reason = `${issue_cite.plain(subject.number)} and ${count} related issue(s) belong to no epic`
|
|
136
135
|
|
|
137
136
|
return { action: 'create_epic', epics: [], candidates: numbers, reason }
|
|
138
137
|
}
|
|
139
138
|
|
|
140
139
|
// Which epic each issue is itself tracked by. An epic is a row of the backlog like any other, so a
|
|
141
|
-
// nested one carries its own parent here and no second read is needed
|
|
140
|
+
// nested one carries its own parent here and no second read is needed.
|
|
142
141
|
// The repository filter is defensive: every caller stamps one repository onto the whole listing
|
|
143
142
|
// today, and the filter is what keeps a bare epic number naming the subject's repository if one ever
|
|
144
143
|
// assembles two.
|
|
@@ -181,8 +180,8 @@ function is_cyclic(
|
|
|
181
180
|
}
|
|
182
181
|
|
|
183
182
|
// Nested epics are not two peers to choose between: the parent already contains the child, so an
|
|
184
|
-
// issue related to both belongs in the child and no merge is on the table. Asking anyway is
|
|
185
|
-
//
|
|
183
|
+
// issue related to both belongs in the child and no merge is on the table. Asking anyway is a false
|
|
184
|
+
// positive that can stop a whole batch.
|
|
186
185
|
function narrow_to_innermost(
|
|
187
186
|
epics: ReadonlyArray<number>,
|
|
188
187
|
parents: ReadonlyMap<number, number>,
|
|
@@ -200,7 +199,7 @@ function narrow_to_innermost(
|
|
|
200
199
|
// reported without narrowing above, so a lone survivor of two or more means the graph was acyclic,
|
|
201
200
|
// and there every dropped epic is a transitive parent of the one left.
|
|
202
201
|
function tracks_reason(epic: number, involved: ReadonlyArray<number>): string {
|
|
203
|
-
const tracks =
|
|
202
|
+
const tracks = `${issue_cite.plain(epic)} already tracks a related issue`
|
|
204
203
|
if (involved.length === 1) return tracks
|
|
205
204
|
|
|
206
205
|
return `${tracks}; the other epics the candidates sit in are its own parents`
|
|
@@ -256,7 +255,7 @@ function decide_bundle(
|
|
|
256
255
|
|
|
257
256
|
// The dependency links a bundle should record, from what the candidates already declare. Bundling
|
|
258
257
|
// without the order records the batch and loses the reason it is a batch — an issue that must follow
|
|
259
|
-
// another is exactly the case this exists to catch
|
|
258
|
+
// another is exactly the case this exists to catch.
|
|
260
259
|
//
|
|
261
260
|
// Only relations already declared are carried over; an order nobody stated is not invented here.
|
|
262
261
|
function bundle_dependency_links(
|
|
@@ -269,7 +268,7 @@ function bundle_dependency_links(
|
|
|
269
268
|
// rather than from each member: comparing a blocker against its *own* member's repository would
|
|
270
269
|
// let two members elsewhere emit a link between them, and the epic body would then resolve those
|
|
271
270
|
// bare numbers against this repository — a different pair of issues. `epic_graph.child_links`
|
|
272
|
-
// guards the identical case the identical way
|
|
271
|
+
// guards the identical case the identical way.
|
|
273
272
|
const declared_repo = subject.repo
|
|
274
273
|
|
|
275
274
|
return members
|
|
@@ -7,21 +7,19 @@ import {
|
|
|
7
7
|
IN_PROGRESS_LABEL,
|
|
8
8
|
NEEDS_DECISION_LABEL,
|
|
9
9
|
} from '#scripts/issue/issue-labels'
|
|
10
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
10
11
|
|
|
11
12
|
// How much of a repository's parallelism is already spoken for — asked of the *repository*, never of
|
|
12
|
-
// the epic
|
|
13
|
-
// joshuafolkken/kit#1491.
|
|
13
|
+
// the epic, and counted rather than treated as a yes/no.
|
|
14
14
|
//
|
|
15
15
|
// `epic-classify.ts` sorts only the children the epic tracks, so an `in-progress` issue belonging to
|
|
16
16
|
// a *different* epic is invisible to it: start two `epicrun`s and both answer "nothing of mine is in
|
|
17
17
|
// progress". This read is what closes that gap, and it is deliberately outside the classification —
|
|
18
18
|
// the question is not about the graph.
|
|
19
19
|
//
|
|
20
|
-
// **What an `in-progress` issue holds is one lane, not the repository.**
|
|
21
|
-
//
|
|
22
|
-
//
|
|
23
|
-
// the question stopped being "is anything running" and became "how many are running" — and the
|
|
24
|
-
// answer is a count the caller compares against `lane_capacity`'s limit.
|
|
20
|
+
// **What an `in-progress` issue holds is one lane, not the repository.** A lane is its own checkout
|
|
21
|
+
// with its own branch and its own ports, so the question is not "is anything running" but "how many
|
|
22
|
+
// are running" — and the answer is a count the caller compares against `lane_capacity`'s limit.
|
|
25
23
|
//
|
|
26
24
|
// **The count is read from GitHub, never kept in the session.** Two `epicrun`s counting to six in
|
|
27
25
|
// their own memory give twelve lanes; the label on an open issue is the one record both of them
|
|
@@ -37,14 +35,14 @@ const LISTING_LIMIT = 100
|
|
|
37
35
|
// `issue-labels.ts` records: GitHub keeps the spelling a label was created with.
|
|
38
36
|
//
|
|
39
37
|
// `already-done` joins `needs-decision` here for the same reason it joins it in
|
|
40
|
-
// `epic_classify.local_category
|
|
38
|
+
// `epic_classify.local_category`: the run that applied it committed
|
|
41
39
|
// nothing, so the checkout it ran in is clean and there is no uncommitted work for the next child to
|
|
42
40
|
// start on top of. That is exactly what separates both from `needs-human-review`, which is
|
|
43
41
|
// deliberately not parked because its work is still sitting in the tree.
|
|
44
42
|
const PARKED_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL])
|
|
45
43
|
|
|
46
|
-
// What one repository answered. `unreadable` is kept apart from `idle`
|
|
47
|
-
//
|
|
44
|
+
// What one repository answered. `unreadable` is kept apart from `idle` because reading a failed
|
|
45
|
+
// read as an empty listing is a confident absence
|
|
48
46
|
// built on a response nobody parsed — and here that absence *starts* work, which is the one
|
|
49
47
|
// direction a guard must never fail in.
|
|
50
48
|
//
|
|
@@ -55,12 +53,14 @@ const PARKED_LABELS: ReadonlySet<string> = new Set([NEEDS_DECISION_LABEL, ALREAD
|
|
|
55
53
|
// children are read first, and one that could not be read is already an anomaly that exits 1. What
|
|
56
54
|
// is left at this line is transient, and `wait` self-heals where an exit needs a person.
|
|
57
55
|
//
|
|
58
|
-
// **`truncated` is kept apart from `idle` for the same reason, one step further in
|
|
59
|
-
//
|
|
56
|
+
// **`truncated` is kept apart from `idle` for the same reason, one step further in**.
|
|
57
|
+
// Since the page ceiling applies to every listing, a listing can now come
|
|
60
58
|
// back well-formed, short, and missing the very issue that holds this repository — and "no holder in
|
|
61
59
|
// the rows I was given" is not "no holder". It is grouped with `unreadable` rather than with `idle`
|
|
62
60
|
// because what it authorizes is identical: nothing. It gets its own kind only so the message names
|
|
63
61
|
// the real cause — `unreadable_message` sends a reader to `gh auth status`, which is green here.
|
|
62
|
+
const NO_AGES: ReadonlyMap<number, string> = new Map()
|
|
63
|
+
|
|
64
64
|
type BusyRead =
|
|
65
65
|
| { kind: 'idle' }
|
|
66
66
|
| { kind: 'busy'; issues: ReadonlyArray<OpenIssueData> }
|
|
@@ -69,9 +69,25 @@ type BusyRead =
|
|
|
69
69
|
|
|
70
70
|
// Named so the reader can go and look at them: the stale-label rule is what keeps an abandoned
|
|
71
71
|
// `in-progress` from holding a repository forever, and it cannot be applied to an issue nobody was
|
|
72
|
-
// told about.
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
// told about. Each holder's label age is printed beside it when the caller read one,
|
|
73
|
+
// since the age is what that rule is applied against.
|
|
74
|
+
function format_holder(
|
|
75
|
+
issue: OpenIssueData,
|
|
76
|
+
repo: string,
|
|
77
|
+
ages: ReadonlyMap<number, string>,
|
|
78
|
+
): string {
|
|
79
|
+
const cite = session_cite.issue(issue.number, issue.title, repo)
|
|
80
|
+
const age = ages.get(issue.number)
|
|
81
|
+
|
|
82
|
+
return age === undefined ? cite : `${cite} (${age})`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function format_holders(
|
|
86
|
+
issues: ReadonlyArray<OpenIssueData>,
|
|
87
|
+
repo: string,
|
|
88
|
+
ages: ReadonlyMap<number, string>,
|
|
89
|
+
): string {
|
|
90
|
+
return issues.map((issue) => format_holder(issue, repo, ages)).join(', ')
|
|
75
91
|
}
|
|
76
92
|
|
|
77
93
|
// How many lanes this read shows occupied. Every kind but `busy` is zero, and the two that could not
|
|
@@ -87,8 +103,9 @@ function occupancy_message(
|
|
|
87
103
|
issues: ReadonlyArray<OpenIssueData>,
|
|
88
104
|
repo: string,
|
|
89
105
|
limit: number,
|
|
106
|
+
ages: ReadonlyMap<number, string> = NO_AGES,
|
|
90
107
|
): string {
|
|
91
|
-
return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues)}.`
|
|
108
|
+
return `${String(issues.length)} of ${String(limit)} lanes in use in ${repo}: ${format_holders(issues, repo, ages)}.`
|
|
92
109
|
}
|
|
93
110
|
|
|
94
111
|
// The occupancy said once, with the consequence appended — rather than a second sentence that
|
|
@@ -97,15 +114,16 @@ function lanes_full_message(
|
|
|
97
114
|
issues: ReadonlyArray<OpenIssueData>,
|
|
98
115
|
repo: string,
|
|
99
116
|
limit: number,
|
|
117
|
+
ages: ReadonlyMap<number, string> = NO_AGES,
|
|
100
118
|
): string {
|
|
101
|
-
return `${occupancy_message(issues, repo, limit)} No lane is free, so nothing is offered here. A lane is released when its child merges or is parked; if a label is stale, remove it and ask again, and \`JOSH_LANE_LIMIT\` is what raises the ceiling.`
|
|
119
|
+
return `${occupancy_message(issues, repo, limit, ages)} No lane is free, so nothing is offered here. A lane is released when its child merges or is parked; if a label is stale, remove it and ask again, and \`JOSH_LANE_LIMIT\` is what raises the ceiling.`
|
|
102
120
|
}
|
|
103
121
|
|
|
104
122
|
function unreadable_message(repo: string): string {
|
|
105
123
|
return `Could not read the \`${IN_PROGRESS_LABEL}\` listing for ${repo}. That is not "nothing is running" — check \`gh auth status\` and ask again.`
|
|
106
124
|
}
|
|
107
125
|
|
|
108
|
-
// Said in the `⚠ … cap` shape
|
|
126
|
+
// Said in the shared `⚠ … cap` shape, because it is the same kind of
|
|
109
127
|
// statement: the read happened and covered less than the whole listing. What it means here is
|
|
110
128
|
// stronger than elsewhere, so the message says the consequence out loud rather than leaving a reader
|
|
111
129
|
// to infer it from a warning marker.
|
|
@@ -129,8 +147,13 @@ const BUSY_REASONS: Readonly<
|
|
|
129
147
|
truncated: truncated_message,
|
|
130
148
|
}
|
|
131
149
|
|
|
132
|
-
function busy_reason(
|
|
133
|
-
|
|
150
|
+
function busy_reason(
|
|
151
|
+
read: BusyRead,
|
|
152
|
+
repo: string,
|
|
153
|
+
limit: number,
|
|
154
|
+
ages: ReadonlyMap<number, string> = NO_AGES,
|
|
155
|
+
): string {
|
|
156
|
+
if (read.kind === 'busy') return lanes_full_message(read.issues, repo, limit, ages)
|
|
134
157
|
if (read.kind === 'idle') return ''
|
|
135
158
|
|
|
136
159
|
return BUSY_REASONS[read.kind](repo)
|
|
@@ -141,7 +164,7 @@ function busy_reason(read: BusyRead, repo: string, limit: number): string {
|
|
|
141
164
|
// `in-progress` and so calls a parked child `human` rather than `time`. Two readings of one issue
|
|
142
165
|
// have to agree, and without this they do not — nothing removes `in-progress` when a child is
|
|
143
166
|
// parked, so `park and continue` would spend a lane on the very child it just set aside, and with
|
|
144
|
-
// one lane the run would poll instead of continuing
|
|
167
|
+
// one lane the run would poll instead of continuing. A child stopped by
|
|
145
168
|
// `needs-human-review` is deliberately not parked and goes on holding its lane: its uncommitted work
|
|
146
169
|
// is still sitting in that checkout.
|
|
147
170
|
function is_parked(issue: OpenIssueData): boolean {
|