@joshuafolkken/kit 1.1784.0 → 1.2116.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +60 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +386 -360
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +16 -9
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -10,7 +10,8 @@ import { backlog_overlap, type Declared } from './backlog-overlap'
|
|
|
10
10
|
// What the backlog offers, in the order it is decided: rank, then the
|
|
11
11
|
// `run:solo` gate, then the cap. `backlog:next` and `backlog:plan --waves` both call `select`, so the
|
|
12
12
|
// plan's first wave is what the run starts into an idle repository rather than an order the run never
|
|
13
|
-
// takes.
|
|
13
|
+
// takes. Only the cap's width differs: `backlog:next` prints `DISPLAY_LIMIT` rows, a wave holds the
|
|
14
|
+
// lane limit (`limit`).
|
|
14
15
|
//
|
|
15
16
|
// **The cap comes last.** Applied while the standalone half is classified, before the gate, it would
|
|
16
17
|
// cut a `run:solo` issue ranked sixth or lower before the gate could see it — and offer the issues
|
|
@@ -29,37 +30,51 @@ function everything_in(result: EpicNextResult): ReadonlyArray<EpicChild> {
|
|
|
29
30
|
// The ranking is `epic_rank.rank`, shared with a named epic's lanes.
|
|
30
31
|
const { rank } = epic_rank
|
|
31
32
|
|
|
32
|
-
// This repository's candidates
|
|
33
|
-
//
|
|
34
|
-
function
|
|
33
|
+
// This repository's candidates put in `order` inside the result; another repository's are left as
|
|
34
|
+
// they came.
|
|
35
|
+
function reorder_repo(
|
|
36
|
+
result: EpicNextResult,
|
|
37
|
+
repo: string,
|
|
38
|
+
order: (children: ReadonlyArray<EpicChild>) => ReadonlyArray<EpicChild>,
|
|
39
|
+
): EpicNextResult {
|
|
35
40
|
if (result.verdict !== 'run') return result
|
|
36
41
|
|
|
37
|
-
const pool = everything_in(result)
|
|
38
|
-
|
|
39
42
|
return {
|
|
40
43
|
...result,
|
|
41
44
|
candidates: result.candidates.map((bundle) =>
|
|
42
|
-
bundle.repo === repo ? { ...bundle, children:
|
|
45
|
+
bundle.repo === repo ? { ...bundle, children: order(bundle.children) } : bundle,
|
|
43
46
|
),
|
|
44
47
|
}
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
// The rank `select` starts from; `offer_order` adds the yielded-first step for `backlog:plan`.
|
|
51
|
+
function rank_result(result: EpicNextResult, repo: string): EpicNextResult {
|
|
52
|
+
const pool = everything_in(result)
|
|
53
|
+
|
|
54
|
+
return reorder_repo(result, repo, (children) => rank(children, pool))
|
|
55
|
+
}
|
|
56
|
+
|
|
47
57
|
// The standalone rows past the cap, in offer order.
|
|
48
58
|
function overflow_of(
|
|
49
59
|
offered: ReadonlyArray<EpicChild>,
|
|
50
60
|
standalone: ReadonlySet<string>,
|
|
61
|
+
limit: number,
|
|
51
62
|
): ReadonlySet<string> {
|
|
52
63
|
const keys = offered.map((child) => epic_graph.key_of(child)).filter((key) => standalone.has(key))
|
|
53
64
|
|
|
54
|
-
return new Set(keys.slice(
|
|
65
|
+
return new Set(keys.slice(limit))
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
function is_in(child: EpicChild, keys: ReadonlySet<string>): boolean {
|
|
58
69
|
return keys.has(epic_graph.key_of(child))
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
function cap(
|
|
62
|
-
|
|
72
|
+
function cap(
|
|
73
|
+
selection: SoloSelection,
|
|
74
|
+
standalone: ReadonlySet<string>,
|
|
75
|
+
limit: number,
|
|
76
|
+
): SoloSelection {
|
|
77
|
+
const overflow = overflow_of(selection.offered, standalone, limit)
|
|
63
78
|
|
|
64
79
|
if (overflow.size === 0) return selection
|
|
65
80
|
|
|
@@ -85,12 +100,40 @@ interface OfferInput {
|
|
|
85
100
|
declared?: Declared
|
|
86
101
|
// The issues' lane state records; a clash with a paused holder says so. Absent, none is named.
|
|
87
102
|
lanes?: LaneRecords
|
|
103
|
+
// The keys of the issues that gave their lane back (`lane-yield.ts`). Absent, none did.
|
|
104
|
+
yielded?: ReadonlySet<string>
|
|
105
|
+
// How many standalone rows the cap keeps. Absent, `DISPLAY_LIMIT` — what `backlog:next` prints.
|
|
106
|
+
limit?: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// A yielded issue ahead of the rank: its lane was taken from it, so it takes the first free one
|
|
110
|
+
// once its holder ends rather than queueing behind the pool (joshuafolkken/kit#5107). While the
|
|
111
|
+
// holder runs, its kept plan still withholds it in the separation. It goes ahead of a `run:solo`
|
|
112
|
+
// issue too: the solo gate sees it first.
|
|
113
|
+
function yielded_first(
|
|
114
|
+
ranked: ReadonlyArray<EpicChild>,
|
|
115
|
+
yielded: ReadonlySet<string>,
|
|
116
|
+
): Array<EpicChild> {
|
|
117
|
+
return [
|
|
118
|
+
...ranked.filter((child) => is_in(child, yielded)),
|
|
119
|
+
...ranked.filter((child) => !is_in(child, yielded)),
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// A ranked result in the order `select` walks it — a yielded issue ahead of the rank — so
|
|
124
|
+
// `backlog:plan`'s "Ready now" reads in the order each wave is offered in (joshuafolkken/kit#5299).
|
|
125
|
+
function offer_order(
|
|
126
|
+
result: EpicNextResult,
|
|
127
|
+
repo: string,
|
|
128
|
+
yielded: ReadonlySet<string> = new Set(),
|
|
129
|
+
): EpicNextResult {
|
|
130
|
+
return reorder_repo(result, repo, (children) => yielded_first(children, yielded))
|
|
88
131
|
}
|
|
89
132
|
|
|
90
133
|
// The overlap separation runs before the cap, for the reason the gate does: the cap only ever
|
|
91
134
|
// removes what would otherwise be offered.
|
|
92
135
|
function select(input: OfferInput): SoloSelection {
|
|
93
|
-
const ranked = rank(input.candidates, input.pool)
|
|
136
|
+
const ranked = yielded_first(rank(input.candidates, input.pool), input.yielded ?? new Set())
|
|
94
137
|
const { read, repo, lanes } = input
|
|
95
138
|
const gated = epic_solo.select(ranked, read, repo)
|
|
96
139
|
const separated = backlog_overlap.separate(gated, input.declared ?? new Map(), {
|
|
@@ -99,13 +142,17 @@ function select(input: OfferInput): SoloSelection {
|
|
|
99
142
|
lanes,
|
|
100
143
|
})
|
|
101
144
|
|
|
102
|
-
return cap(separated, input.standalone)
|
|
145
|
+
return cap(separated, input.standalone, input.limit ?? git_next_issues.DISPLAY_LIMIT)
|
|
103
146
|
}
|
|
104
147
|
|
|
105
148
|
interface GateScope {
|
|
106
149
|
standalone: ReadonlySet<string>
|
|
107
150
|
declared: Declared
|
|
108
151
|
lanes?: LaneRecords
|
|
152
|
+
yielded?: ReadonlySet<string>
|
|
153
|
+
// How many standalone rows a planned wave holds — the lane limit; `backlog:next`'s offer ignores
|
|
154
|
+
// it. Absent, a wave is not capped (joshuafolkken/kit#5300).
|
|
155
|
+
wave_limit?: number | undefined
|
|
109
156
|
}
|
|
110
157
|
|
|
111
158
|
// `backlog:next`'s gate: `epic_solo.gate` with this selection in place of its bare one.
|
|
@@ -117,7 +164,7 @@ function gate(result: EpicNextResult, read: BusyRead, repo: string, scope: GateS
|
|
|
117
164
|
)
|
|
118
165
|
}
|
|
119
166
|
|
|
120
|
-
const backlog_rank = { everything_in, gate, rank_result, select }
|
|
167
|
+
const backlog_rank = { everything_in, gate, offer_order, rank_result, select }
|
|
121
168
|
|
|
122
169
|
export { backlog_rank }
|
|
123
170
|
export type { GateScope, OfferInput }
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { lane_ledger, type LedgerEntry } from '#scripts/lane/lane-ledger'
|
|
2
|
+
import { lane_ledger_write } from '#scripts/lane/lane-ledger-write'
|
|
2
3
|
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
3
4
|
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
4
5
|
import { backlog_ready, type ReadyPorts } from './backlog-ready'
|
|
@@ -78,7 +79,7 @@ async function read_real_ledger(): Promise<ReadonlyArray<LedgerEntry>> {
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
async function real_mark_offerable(is_offerable: boolean): Promise<void> {
|
|
81
|
-
await
|
|
82
|
+
await lane_ledger_write.record_offerable(is_offerable)
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
function ports_over(ready: ReadyPorts): DetectPorts {
|
|
@@ -24,7 +24,7 @@ import { backlog_rank, type GateScope } from './backlog-rank'
|
|
|
24
24
|
// **No rule is written twice.** The first wave is `backlog_rank.select` — rank, `run:solo` gate,
|
|
25
25
|
// overlap separation, cap —
|
|
26
26
|
// over the very candidates `backlog:next` resolves, asked of an idle repository — so it is what
|
|
27
|
-
// `backlog:next` prints when nothing is running. Each later wave marks the earlier waves closed and re-classifies the same pool
|
|
27
|
+
// `backlog:next` prints when nothing is running, cut at the lane limit rather than the printed count. Each later wave marks the earlier waves closed and re-classifies the same pool
|
|
28
28
|
// through `epic_classify.classify_children` with the resolver `epic:next` sorted it with the first
|
|
29
29
|
// time — `epic_cross_repo.resolve_cross_repo`, so a blocker in another repository still waits for its
|
|
30
30
|
// release rather than counting as done on close — then puts the runnable set through
|
|
@@ -33,9 +33,13 @@ import { backlog_rank, type GateScope } from './backlog-rank'
|
|
|
33
33
|
const IDLE: BusyRead = { kind: 'idle' }
|
|
34
34
|
const CLOSED = 'CLOSED'
|
|
35
35
|
const EMPTY_SCOPE: GateScope = { standalone: new Set(), declared: new Map() }
|
|
36
|
+
// A wave is as wide as the lanes that run it, not `backlog:next`'s `DISPLAY_LIMIT` — that printed
|
|
37
|
+
// count pushed an issue whose blocker closed in wave k past wave k+1 (joshuafolkken/kit#5300).
|
|
38
|
+
const UNCAPPED = Infinity
|
|
36
39
|
|
|
37
40
|
const HEADING_ASSUMPTION =
|
|
38
41
|
'Assumes every issue in a wave merges before the next wave starts. Issues a run already has are left out and count as merged first, and only issues of this repository are planned.'
|
|
42
|
+
const UNCAPPED_WIDTH = 'A wave is not capped: the lane limit could not be read.'
|
|
39
43
|
const UNREACHED_HEADING = 'Not reached — each names what it is waiting on:'
|
|
40
44
|
const PARALLEL_NOTE = '(parallel)'
|
|
41
45
|
const NEEDS_DECISION_NOTE = `waiting on a person (\`${NEEDS_DECISION_LABEL}\`)`
|
|
@@ -84,8 +88,10 @@ function offer(
|
|
|
84
88
|
pool: WavePool,
|
|
85
89
|
): ReadonlyArray<EpicChild> {
|
|
86
90
|
const { repo, scope } = pool
|
|
91
|
+
const limit = scope.wave_limit ?? UNCAPPED
|
|
87
92
|
|
|
88
|
-
return backlog_rank.select({ candidates, pool: children, read: IDLE, repo, ...scope })
|
|
93
|
+
return backlog_rank.select({ candidates, pool: children, read: IDLE, repo, ...scope, limit })
|
|
94
|
+
.offered
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
// Ranked against the whole result, exactly as `backlog:next` ranks it, so the two agree.
|
|
@@ -175,6 +181,12 @@ function unreached_lines(plan: WavePlan, context: PlanContext): Array<string> {
|
|
|
175
181
|
)
|
|
176
182
|
}
|
|
177
183
|
|
|
184
|
+
function width_line(wave_limit: number | undefined): string {
|
|
185
|
+
if (wave_limit === undefined) return UNCAPPED_WIDTH
|
|
186
|
+
|
|
187
|
+
return `A wave holds at most ${String(wave_limit)} standalone issues, the lane limit; an epic's children are not counted.`
|
|
188
|
+
}
|
|
189
|
+
|
|
178
190
|
function format_waves(
|
|
179
191
|
result: EpicNextResult,
|
|
180
192
|
context: PlanContext,
|
|
@@ -188,6 +200,7 @@ function format_waves(
|
|
|
188
200
|
return [
|
|
189
201
|
`Backlog waves — ${context.repo}`,
|
|
190
202
|
HEADING_ASSUMPTION,
|
|
203
|
+
width_line(scope.wave_limit),
|
|
191
204
|
'',
|
|
192
205
|
...(waves.length === 0 ? [backlog_plan.NOTHING] : waves),
|
|
193
206
|
'',
|
|
@@ -200,9 +213,11 @@ const backlog_waves = {
|
|
|
200
213
|
NEEDS_DECISION_NOTE,
|
|
201
214
|
PARALLEL_NOTE,
|
|
202
215
|
run_stalled_note,
|
|
216
|
+
UNCAPPED_WIDTH,
|
|
203
217
|
UNREACHED_HEADING,
|
|
204
218
|
build,
|
|
205
219
|
format_waves,
|
|
220
|
+
width_line,
|
|
206
221
|
}
|
|
207
222
|
|
|
208
223
|
export { backlog_waves }
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type AgentProvider,
|
|
7
7
|
} from '#scripts/agent/agent-role-profile'
|
|
8
8
|
import { agent_session_environment } from '#scripts/josh/agent-session-environment'
|
|
9
|
+
import { durable_state } from '#scripts/josh/durable-state'
|
|
9
10
|
import { process_identity } from '#scripts/josh/process-identity'
|
|
10
11
|
import { stamp_file } from '#scripts/josh/stamp-file'
|
|
11
12
|
import { json_value } from '#scripts/lib/json-value'
|
|
@@ -27,8 +28,8 @@ import { z } from 'zod'
|
|
|
27
28
|
// session can still start a Codex parent. The same choice is handed to the parent as
|
|
28
29
|
// `JOSH_AGENT_PROVIDER`, the key a detached child with no session of its own resolves from.
|
|
29
30
|
|
|
30
|
-
const LAUNCH_PREFIX =
|
|
31
|
-
const LOG_PREFIX =
|
|
31
|
+
const LAUNCH_PREFIX = durable_state.PREFIX.BACKLOGRUN_LAUNCH
|
|
32
|
+
const LOG_PREFIX = durable_state.PREFIX.BACKLOGRUN_LOG
|
|
32
33
|
const LOG_SUFFIX = '.log'
|
|
33
34
|
|
|
34
35
|
const launch_schema = z.object({
|
|
@@ -64,11 +65,11 @@ interface Launched {
|
|
|
64
65
|
type StartResult = { kind: 'launched'; launched: Launched } | { kind: 'failed'; note: string }
|
|
65
66
|
|
|
66
67
|
function launch_path(git_directory: string): string {
|
|
67
|
-
return
|
|
68
|
+
return durable_state.path(LAUNCH_PREFIX, git_directory)
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
function log_path(git_directory: string): string {
|
|
71
|
-
return
|
|
72
|
+
return durable_state.path(LOG_PREFIX, git_directory, LOG_SUFFIX)
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
function read_launch(target: string): LaunchRecord | undefined {
|
|
@@ -248,6 +249,8 @@ const backlogrun_launch = {
|
|
|
248
249
|
argv_of,
|
|
249
250
|
chosen_environment,
|
|
250
251
|
is_running,
|
|
252
|
+
launch_path,
|
|
253
|
+
log_path,
|
|
251
254
|
pending_launch,
|
|
252
255
|
running_parent,
|
|
253
256
|
start,
|
|
@@ -19,55 +19,57 @@ import { cost_pricing } from './cost-pricing'
|
|
|
19
19
|
const POST_CUT_CONTEXT = 60_000
|
|
20
20
|
|
|
21
21
|
// The requests a resumed session is expected to still run — the horizon the break-even is measured
|
|
22
|
-
// against. A cut only pays if enough requests remain to recoup the preamble rewrite
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
const EXPECTED_REMAINING_REQUESTS =
|
|
22
|
+
// against. A cut only pays if enough requests remain to recoup the preamble rewrite. Measured, not
|
|
23
|
+
// chosen: the lane children resumed after a cut over the 14 days to 2026-10-28 ran a median of 23
|
|
24
|
+
// requests per resumed session (748 sessions; p25 11, p90 68 — #5341). The median, not the mean, so a
|
|
25
|
+
// few long resumes do not pull every cut earlier.
|
|
26
|
+
const EXPECTED_REMAINING_REQUESTS = 23
|
|
27
27
|
|
|
28
28
|
// The price of a dropped token relative to a rewritten one, from `cost-pricing.ts`. A cache read bills
|
|
29
|
-
//
|
|
30
|
-
// so a preamble rewrite costs this many per-request cache reads. The base
|
|
31
|
-
// and cancels, which is why only the ratio appears.
|
|
32
|
-
//
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// needs a lane measurement of its own rather than arriving as a side effect of a corrected price list.
|
|
37
|
-
function write_over_read(): number {
|
|
38
|
-
return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.DEFAULT_CACHE_READ_MULTIPLIER
|
|
29
|
+
// the running model's cache-read multiplier of base input and a 5-minute cache write
|
|
30
|
+
// `CACHE_WRITE_5M_MULTIPLIER`, so a preamble rewrite costs this many per-request cache reads. The base
|
|
31
|
+
// input rate is common to both and cancels, which is why only the ratio appears. A model that reads
|
|
32
|
+
// cache cheaper (Opus 5.5 at 0.05x, Fable 5.1 at 0.025x) saves less per dropped token, so its cut
|
|
33
|
+
// breaks even later; an unpriced model reads at the standard rate.
|
|
34
|
+
function write_over_read(model: string | undefined): number {
|
|
35
|
+
return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.cache_read_multiplier_of(model)
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
// The current per-request context at which a cut breaks even over exactly `remaining`
|
|
42
|
-
//
|
|
38
|
+
// The current per-request context at which a cut breaks even for `model` over exactly `remaining`
|
|
39
|
+
// requests. The cut threshold `pnpm josh cost --cut` applies is this evaluated at
|
|
40
|
+
// `EXPECTED_REMAINING_REQUESTS` for the session's newest request's model; rounded to an integer so the
|
|
43
41
|
// `>` comparison against a per-request billed-input count has no floating-point seam.
|
|
44
|
-
function break_even_context(
|
|
42
|
+
function break_even_context(
|
|
43
|
+
model: string | undefined,
|
|
44
|
+
remaining: number = EXPECTED_REMAINING_REQUESTS,
|
|
45
|
+
): number {
|
|
45
46
|
if (remaining <= 0) return Infinity
|
|
46
47
|
|
|
47
|
-
return Math.round(POST_CUT_CONTEXT * (1 + write_over_read() / remaining))
|
|
48
|
+
return Math.round(POST_CUT_CONTEXT * (1 + write_over_read(model) / remaining))
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
// The requests a cut must save over before it recoups its own preamble rewrite, at a given current
|
|
51
52
|
// per-request context. Decreasing in context: the more a request currently pays, the fewer resumed
|
|
52
53
|
// requests are needed to earn the cut back. Exposed as the diagnostic the break-even is read in —
|
|
53
|
-
// `break_even_requests(current) < remaining` is the same decision as `pays_back`.
|
|
54
|
-
function break_even_requests(current_context: number): number {
|
|
54
|
+
// `break_even_requests(current, model) < remaining` is the same decision as `pays_back`.
|
|
55
|
+
function break_even_requests(current_context: number, model: string | undefined): number {
|
|
55
56
|
const saved_per_request = current_context - POST_CUT_CONTEXT
|
|
56
57
|
|
|
57
58
|
if (saved_per_request <= 0) return Infinity
|
|
58
59
|
|
|
59
|
-
return (POST_CUT_CONTEXT * write_over_read()) / saved_per_request
|
|
60
|
+
return (POST_CUT_CONTEXT * write_over_read(model)) / saved_per_request
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// Whether cutting now pays back: the current per-request context has grown past the break-even point
|
|
63
64
|
// for the expected remaining requests. Compared against the rounded `break_even_context` with `>`, so
|
|
64
|
-
// it agrees to the token with `cost_verdict.classify` reading the
|
|
65
|
-
//
|
|
65
|
+
// it agrees to the token with `cost_verdict.classify` reading the same threshold — the same one
|
|
66
|
+
// decision, whether a caller holds the threshold or asks this function.
|
|
66
67
|
function pays_back(
|
|
67
68
|
current_context: number,
|
|
69
|
+
model: string | undefined,
|
|
68
70
|
remaining: number = EXPECTED_REMAINING_REQUESTS,
|
|
69
71
|
): boolean {
|
|
70
|
-
return current_context > break_even_context(remaining)
|
|
72
|
+
return current_context > break_even_context(model, remaining)
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
const context_cut_payback = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { agent_role_profile, type AgentProvider } from '#scripts/agent/agent-role-profile'
|
|
2
2
|
import { cli_flags } from '#scripts/lib/cli-flags'
|
|
3
3
|
import { codex_usage } from './codex-usage'
|
|
4
|
-
import {
|
|
4
|
+
import { context_cut_payback } from './context-cut-payback'
|
|
5
5
|
import { cost_corpus } from './cost-corpus'
|
|
6
6
|
import { cost_transcript, type SessionUsage } from './cost-transcript'
|
|
7
7
|
import { cost_usage } from './cost-usage'
|
|
@@ -16,7 +16,7 @@ import { transcript_cwd } from './transcript-cwd'
|
|
|
16
16
|
// (`--session` / `--issue` / `--all` / `--run` / `--json`) and the `--cap` counterfactual were
|
|
17
17
|
// retired because no rule or decision read them — leaving only the entry judgment `fullrun` /
|
|
18
18
|
// `backlogrun` / `halfrun` / `pre-gate-cut` ask, and the `josh time` run-timing report keeps the
|
|
19
|
-
// hand-off aggregates used to compare the
|
|
19
|
+
// hand-off aggregates used to compare the `--cut` break-even.
|
|
20
20
|
|
|
21
21
|
const FAILURE_EXIT_CODE = 1
|
|
22
22
|
const USAGE = 'Usage: josh cost (--cut | --over <tokens-per-request>) [--path <dir>]'
|
|
@@ -32,8 +32,14 @@ interface SessionFigures {
|
|
|
32
32
|
threshold: number
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
// `--cut` is not a number at parse time: its threshold is the break-even of the model the session's
|
|
36
|
+
// newest request ran on, known only once the transcript is read.
|
|
37
|
+
const CUT_LIMIT = 'cut'
|
|
38
|
+
|
|
39
|
+
type Limit = number | typeof CUT_LIMIT
|
|
40
|
+
|
|
35
41
|
interface Options {
|
|
36
|
-
over?:
|
|
42
|
+
over?: Limit
|
|
37
43
|
// The target project whose transcripts to read, or absent for this process's own working
|
|
38
44
|
// directory. From the kit checkout, `--path <dir>` reads another
|
|
39
45
|
// project's cost.
|
|
@@ -49,7 +55,7 @@ interface RawValues {
|
|
|
49
55
|
type Environment = Readonly<Record<string, string | undefined>>
|
|
50
56
|
|
|
51
57
|
interface RunContext {
|
|
52
|
-
over:
|
|
58
|
+
over: Limit
|
|
53
59
|
path: string | undefined
|
|
54
60
|
provider: AgentProvider
|
|
55
61
|
}
|
|
@@ -72,10 +78,14 @@ function is_unparsed(raw: string | undefined, parsed: number | undefined): boole
|
|
|
72
78
|
return parsed === undefined && raw !== undefined
|
|
73
79
|
}
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
|
|
81
|
+
// The cut threshold of a measured session: the break-even for its newest request's model. With no
|
|
82
|
+
// measurement it is the standard-rate break-even, the figure a report quotes beside no cost.
|
|
83
|
+
function cut_threshold(measurement: OverMeasurement | undefined): number {
|
|
84
|
+
return context_cut_payback.break_even_context(measurement?.model)
|
|
85
|
+
}
|
|
77
86
|
|
|
78
|
-
|
|
87
|
+
function limit_of(limit: Limit, measurement: OverMeasurement): number {
|
|
88
|
+
return limit === CUT_LIMIT ? cut_threshold(measurement) : limit
|
|
79
89
|
}
|
|
80
90
|
|
|
81
91
|
function threshold_option(over: number | undefined): Pick<Options, 'over'> {
|
|
@@ -86,12 +96,17 @@ function path_option(path: string | undefined): Pick<Options, 'path'> {
|
|
|
86
96
|
return path === undefined ? {} : { path }
|
|
87
97
|
}
|
|
88
98
|
|
|
99
|
+
// `--cut` and `--over` name the same limit, so giving both is a refusal.
|
|
100
|
+
function cut_options(values: RawValues): Options | undefined {
|
|
101
|
+
return values.over === undefined ? { over: CUT_LIMIT, ...path_option(values.path) } : undefined
|
|
102
|
+
}
|
|
103
|
+
|
|
89
104
|
// `exactOptionalPropertyTypes` rejects `{ over: undefined }`, so an absent flag contributes no key
|
|
90
105
|
// at all rather than an undefined one.
|
|
91
106
|
function to_options(values: RawValues): Options | undefined {
|
|
92
|
-
if (values.cut === true
|
|
107
|
+
if (values.cut === true) return cut_options(values)
|
|
93
108
|
|
|
94
|
-
const over =
|
|
109
|
+
const over = to_threshold(values.over)
|
|
95
110
|
|
|
96
111
|
if (is_unparsed(values.over, over)) return undefined
|
|
97
112
|
|
|
@@ -147,6 +162,7 @@ function measurement_of(session: SessionUsage): OverMeasurement {
|
|
|
147
162
|
billed_input_per_request: session.records.map((record) =>
|
|
148
163
|
cost_usage.billed_input(record.totals),
|
|
149
164
|
),
|
|
165
|
+
model: session.records.at(-1)?.model,
|
|
150
166
|
}
|
|
151
167
|
}
|
|
152
168
|
|
|
@@ -206,15 +222,20 @@ function measure(
|
|
|
206
222
|
// missing message; `empty` → the whole-corpus missing message. A measured session that billed
|
|
207
223
|
// nothing falls to `report_over`'s "no requests", which keeps a 0-request transcript distinct from a
|
|
208
224
|
// transcript that is not there at all.
|
|
209
|
-
function run_over_anthropic(own: OwnMeasurement, target: string, limit:
|
|
210
|
-
if (own.kind === 'measured')
|
|
225
|
+
function run_over_anthropic(own: OwnMeasurement, target: string, limit: Limit): number {
|
|
226
|
+
if (own.kind === 'measured') {
|
|
227
|
+
return cost_verdict.report_over(own.measurement, limit_of(limit, own.measurement))
|
|
228
|
+
}
|
|
211
229
|
|
|
212
230
|
return report_empty(target, own.kind === 'absent' ? own.session_id : undefined)
|
|
213
231
|
}
|
|
214
232
|
|
|
215
|
-
function run_over_codex(target: string, limit:
|
|
233
|
+
function run_over_codex(target: string, limit: Limit, environment: Environment): number {
|
|
216
234
|
const measurement = measure(target, 'openai', environment)
|
|
217
|
-
|
|
235
|
+
|
|
236
|
+
if (measurement !== undefined) {
|
|
237
|
+
return cost_verdict.report_over(measurement, limit_of(limit, measurement))
|
|
238
|
+
}
|
|
218
239
|
|
|
219
240
|
console.error(`No Codex usage found for the current OpenAI thread under ${target}.`)
|
|
220
241
|
|
|
@@ -225,7 +246,7 @@ function run_over_codex(target: string, limit: number, environment: Environment)
|
|
|
225
246
|
// alone — identified by id, not by mtime.
|
|
226
247
|
function run_over(
|
|
227
248
|
target: string,
|
|
228
|
-
limit:
|
|
249
|
+
limit: Limit,
|
|
229
250
|
provider: AgentProvider,
|
|
230
251
|
environment: Environment,
|
|
231
252
|
): number {
|
|
@@ -243,7 +264,7 @@ function verdict_of(measurement: OverMeasurement | undefined): CostVerdict {
|
|
|
243
264
|
return UNMEASURABLE_VERDICT
|
|
244
265
|
}
|
|
245
266
|
|
|
246
|
-
return cost_verdict.classify(measurement,
|
|
267
|
+
return cost_verdict.classify(measurement, cut_threshold(measurement))
|
|
247
268
|
}
|
|
248
269
|
|
|
249
270
|
// The verdict with the figures it was decided on — the newest request's billed input and the shared
|
|
@@ -254,7 +275,7 @@ function figures_of(measurement: OverMeasurement | undefined): SessionFigures {
|
|
|
254
275
|
const is_priced = measurement !== undefined && verdict !== UNMEASURABLE_VERDICT
|
|
255
276
|
const cost = is_priced ? cost_verdict.per_request_cost(measurement) : undefined
|
|
256
277
|
|
|
257
|
-
return { verdict, cost, threshold:
|
|
278
|
+
return { verdict, cost, threshold: cut_threshold(measurement) }
|
|
258
279
|
}
|
|
259
280
|
|
|
260
281
|
// The `--cut` verdict and its figures as a value, printing nothing. `run:report --handoff` quotes the
|
|
@@ -111,6 +111,14 @@ function cache_read_multiplier(price: ModelPrice): number {
|
|
|
111
111
|
return price.cache_read_multiplier ?? DEFAULT_CACHE_READ_MULTIPLIER
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
// The cache-read multiplier a model bills, by id. A model with no price row — an unpriced id, or no
|
|
115
|
+
// model at all — reads at the standard rate.
|
|
116
|
+
function cache_read_multiplier_of(model: string | undefined): number {
|
|
117
|
+
const price = model === undefined ? undefined : resolve_price(model)
|
|
118
|
+
|
|
119
|
+
return price === undefined ? DEFAULT_CACHE_READ_MULTIPLIER : cache_read_multiplier(price)
|
|
120
|
+
}
|
|
121
|
+
|
|
114
122
|
function estimate_cost(totals: UsageTotals, price: ModelPrice): number {
|
|
115
123
|
const weighted_input =
|
|
116
124
|
totals.input_tokens +
|
|
@@ -225,6 +233,7 @@ const cost_pricing = {
|
|
|
225
233
|
DEFAULT_CACHE_READ_MULTIPLIER,
|
|
226
234
|
LONG_PROMPT_THRESHOLD,
|
|
227
235
|
resolve_price,
|
|
236
|
+
cache_read_multiplier_of,
|
|
228
237
|
estimate_cost,
|
|
229
238
|
estimate_composition,
|
|
230
239
|
cost_by_model,
|
|
@@ -9,9 +9,12 @@ const UNDER_VERDICT = 'under'
|
|
|
9
9
|
|
|
10
10
|
// What `--over` reads of a session: the billed input each request paid, oldest first. The sequence
|
|
11
11
|
// is carried rather than a single sum because the hand-off prices the newest request alone
|
|
12
|
-
// — a sum could not answer what the session's current context costs.
|
|
12
|
+
// — a sum could not answer what the session's current context costs. `model` is the newest request's
|
|
13
|
+
// model, which prices the cut threshold (`context-cut-payback.ts`); a provider that records none
|
|
14
|
+
// leaves it absent and is read at the standard cache rate.
|
|
13
15
|
interface OverMeasurement {
|
|
14
16
|
billed_input_per_request: ReadonlyArray<number>
|
|
17
|
+
model?: string | undefined
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
// What a turn costs is decided by the accumulated preamble, not by what the turn does, so the
|
|
@@ -46,7 +46,7 @@ const INVESTIGATOR_AGENT = 'investigator'
|
|
|
46
46
|
// them, so a run told the step up front is told the same step the refusal would name.
|
|
47
47
|
const INVESTIGATION_LIMIT = `${String(INVESTIGATION_FILE_THRESHOLD)} files read and not edited, or ${String(INVESTIGATION_SEARCH_TURN_THRESHOLD)} search turns, since the last delegated unit`
|
|
48
48
|
// Only the dispatch resets the count, so the step names no `josh delegate` call before it (#4345).
|
|
49
|
-
const INVESTIGATION_STEP = `Dispatch the \`${INVESTIGATOR_AGENT}\` agent (\`kit:${INVESTIGATOR_AGENT}\` in a consumer)
|
|
49
|
+
const INVESTIGATION_STEP = `Dispatch the \`${INVESTIGATOR_AGENT}\` agent (\`kit:${INVESTIGATOR_AGENT}\` in a consumer) with \`run_in_background: false\`; it returns \`file:line\` citations, never the file text.`
|
|
50
50
|
|
|
51
51
|
// The enumeration. Short on purpose: every entry had to name a verifier, and most candidates could
|
|
52
52
|
// not (below).
|
|
@@ -75,7 +75,7 @@ const DELEGATABLE_STEPS: ReadonlyArray<DelegatableStep> = [
|
|
|
75
75
|
// chain at a small context, and the review round cap already composed the finding text, so what
|
|
76
76
|
// the unit is handed is mechanical: run the commands and act on their deterministic answers. This
|
|
77
77
|
// is not the batching guard's business — delegation only moves the chain to a cheaper context.
|
|
78
|
-
does: 'run the late-run follow-up filing chain in an isolated unit — issue:file (
|
|
78
|
+
does: 'run the late-run follow-up filing chain in an isolated unit — issue:file (lint, labels, scout, epic:bundle), then epic --add — given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer',
|
|
79
79
|
verifier:
|
|
80
80
|
"the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:file`'s steps are deterministic, so the unit's work is the mechanical execution `issue:state` confirms",
|
|
81
81
|
},
|
|
@@ -24,8 +24,9 @@ const STAMP_PREFIX = 'josh-investigation-guard-'
|
|
|
24
24
|
// **How the guard behaves for the session in hand, decided from the one-place enumeration**. It is
|
|
25
25
|
// `refuse` in a dispatched lane child too (joshuafolkken/kit#3927): a hook denial returns to the model
|
|
26
26
|
// as guidance, and the notice it replaced was measured not to move the reading. It wraps
|
|
27
|
-
// `investigation_reads.should_block` here rather than inside it so the
|
|
28
|
-
//
|
|
27
|
+
// `investigation_reads.should_block` here rather than inside it so the counting rule stays free of the
|
|
28
|
+
// session's switch state and its own suite keeps testing it directly — its only process read is the
|
|
29
|
+
// branch diff it asks before a refusal. A reviewer session stands down: reading
|
|
29
30
|
// the diff's files is its whole task, and it carries the lane's marker, so it would otherwise be refused
|
|
30
31
|
// like the child it reviews — the stand-down `implementation-cut.ts` takes for the same session.
|
|
31
32
|
function should_block(
|
|
@@ -56,6 +57,16 @@ const investigation_refusal = GUARD.refusal
|
|
|
56
57
|
const investigation_outcome = GUARD.outcome
|
|
57
58
|
const { is_enabled, refusal_path } = GUARD
|
|
58
59
|
const { deny_envelope, load_environment_file, DISABLED_VALUES } = hook_decision
|
|
60
|
+
const STAMP = hook_decision.create_refusal_stamp(STAMP_PREFIX)
|
|
61
|
+
|
|
62
|
+
// Whether this guard refuses the call in hand, asked with its real record — so the batching guard's
|
|
63
|
+
// lane-child search refusal can stand aside for it: only one reason surfaces per call, and delegating
|
|
64
|
+
// the reading supersedes batching it.
|
|
65
|
+
function will_refuse(tail: string, call: GuardedCall, run: GuardRun): boolean {
|
|
66
|
+
if (!is_enabled() || !investigation_reads.is_refusable_call(call)) return false
|
|
67
|
+
|
|
68
|
+
return should_block(tail, call, STAMP.last_ms(STAMP.path(run.transcript)), run)
|
|
69
|
+
}
|
|
59
70
|
|
|
60
71
|
export {
|
|
61
72
|
deny_envelope,
|
|
@@ -64,6 +75,7 @@ export {
|
|
|
64
75
|
is_enabled,
|
|
65
76
|
load_environment_file,
|
|
66
77
|
refusal_path,
|
|
78
|
+
will_refuse,
|
|
67
79
|
DISABLED_VALUES,
|
|
68
80
|
SWITCH_ENV_KEY,
|
|
69
81
|
}
|