@joshuafolkken/kit 1.1784.0 → 1.2114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/reviewer-verification.md +19 -0
- package/.claude/agents/reviewer.md +19 -0
- package/.claude/settings.json +5 -6
- package/.claude/skills/dependency-update/SKILL.md +9 -10
- package/.claude/skills/workflow-commands/SKILL.md +6 -6
- package/.claude/skills/workflow-commands/background-commands.md +8 -5
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -1
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-park.md +5 -2
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.md +3 -2
- package/.claude/skills/workflow-commands/backlogrun.md +1 -1
- package/.claude/skills/workflow-commands/chain-rule.md +41 -32
- package/.claude/skills/workflow-commands/delegation.md +6 -6
- package/.claude/skills/workflow-commands/entry-sequence.md +2 -2
- package/.claude/skills/workflow-commands/followup.md +7 -5
- package/.claude/skills/workflow-commands/fullrun-steps.md +6 -6
- package/.claude/skills/workflow-commands/fullrun.md +1 -1
- package/.claude/skills/workflow-commands/issue-comments.md +9 -4
- package/.claude/skills/workflow-commands/issue-fold-existing.md +2 -1
- package/.claude/skills/workflow-commands/kickoff.md +2 -2
- package/.claude/skills/workflow-commands/observation-filing.md +1 -1
- package/.claude/skills/workflow-commands/observation-ledger.md +6 -4
- package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -7
- package/.claude/skills/workflow-commands/prerequisite.md +3 -2
- package/.claude/skills/workflow-commands/retrospective.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +7 -5
- package/.codex/hooks.json +5 -5
- package/.github/actions/setup-pnpm/action.yml +9 -16
- package/.github/dependabot.yml +16 -0
- package/.github/workflows/auto-tag.yml +45 -0
- package/.github/workflows/ci.yml +155 -15
- package/.github/workflows/dependabot-auto-merge.yml +63 -4
- package/.github/workflows/production.yml +8 -0
- package/.github/workflows/publish.yml +59 -45
- package/.vscode/settings.json +19 -0
- package/CLAUDE.md +5 -12
- package/SECURITY.md +2 -2
- package/dist/CLAUDE.md +5 -12
- package/dist/commands/document-read-cli.js +2 -1
- package/dist/commands/document-section-main.js +2 -1
- package/dist/commands/read-set-cli.js +194 -134
- package/dist/commands/run-prep-main.js +9694 -10173
- package/dist/commands/run-step-cli.js +22138 -18285
- package/dist/hooks/audit-provision.js +23 -5
- package/dist/hooks/chunk-3GKE653K.js +6204 -0
- package/dist/hooks/chunk-45CJJOO7.js +1243 -0
- package/dist/hooks/{chunk-CWMBGKYW.js → chunk-5PM2JRGV.js} +2153 -856
- package/dist/hooks/{chunk-WR2KQAYZ.js → chunk-7SIUNQXK.js} +1207 -1470
- package/dist/hooks/{chunk-O2YBIDSI.js → chunk-CQD4LJE6.js} +1682 -1130
- package/dist/hooks/{chunk-VWWCFGWK.js → chunk-OPSRGWFU.js} +1 -1
- package/dist/hooks/{chunk-XGBNSWEI.js → chunk-UJ3FPMMM.js} +132 -49
- package/dist/hooks/chunk-VVNYJWEI.js +30 -0
- package/dist/hooks/chunk-Z6DQJKH3.js +2806 -0
- package/dist/hooks/codex-hook-adapter.js +8 -8
- package/dist/hooks/format-edited.js +4 -5
- package/dist/hooks/inputs.json +415 -389
- package/dist/hooks/pretool-guard.js +7 -6
- package/dist/hooks/session-lang.js +101 -258
- package/dist/hooks/stop-guard.js +1744 -2576
- package/dist/josh.js +7133 -6368
- package/dist/version/index.js +161 -1
- package/eslint/rules/comment-why-only.js +108 -0
- package/package.json +15 -8
- package/prompts/coding-standards.md +1 -1
- package/prompts/collaboration-workflow/file-edits.md +14 -11
- package/prompts/collaboration-workflow/issue-citation.md +0 -4
- package/prompts/collaboration-workflow/issue-template.md +40 -21
- package/prompts/collaboration-workflow/lane-instructions.md +3 -1
- package/prompts/collaboration-workflow/measurement.md +8 -1
- package/prompts/collaboration-workflow/operating-rules.md +11 -2
- package/prompts/collaboration-workflow/output-bounds.md +6 -2
- package/prompts/collaboration-workflow/plan-comment.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow/residency.md +3 -2
- package/prompts/collaboration-workflow/rule-delivery.md +13 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +3 -1
- package/prompts/review-rubric.md +8 -0
- package/prompts/review.md +31 -22
- package/prompts/testing-guide.md +1 -0
- package/scripts/agent/agent-argv.ts +14 -16
- package/scripts/agent/agent-provider.ts +138 -0
- package/scripts/agent/agent-role-profile.ts +108 -156
- package/scripts/agent/agent-safe-text.ts +20 -5
- package/scripts/agent/api-usage-limit.ts +65 -0
- package/scripts/agent/claude-agent-argv.ts +19 -9
- package/scripts/agent/codex-agent-argv.ts +118 -22
- package/scripts/agent/usage-limit-reset.ts +179 -0
- package/scripts/auth/claude-token-output.ts +2 -2
- package/scripts/auto-ok/auto-ok-author.ts +53 -0
- package/scripts/auto-ok/auto-ok-cli.ts +20 -9
- package/scripts/backlog/backlog-defect-priority.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +6 -1
- package/scripts/backlog/backlog-drive-hold.ts +3 -3
- package/scripts/backlog/backlog-drive-idle.ts +10 -0
- package/scripts/backlog/backlog-drive-launch-pass.ts +90 -0
- package/scripts/backlog/backlog-drive-launch.ts +8 -2
- package/scripts/backlog/backlog-drive-named-offer.ts +73 -30
- package/scripts/backlog/backlog-drive-named.ts +28 -7
- package/scripts/backlog/backlog-drive-paused.ts +5 -4
- package/scripts/backlog/backlog-drive-restore.ts +11 -3
- package/scripts/backlog/backlog-drive.ts +21 -60
- package/scripts/backlog/backlog-gate-scope.ts +61 -0
- package/scripts/backlog/backlog-measure-close.ts +112 -0
- package/scripts/backlog/backlog-next.ts +39 -49
- package/scripts/backlog/backlog-occupied.ts +2 -2
- package/scripts/backlog/backlog-overlap.ts +42 -8
- package/scripts/backlog/backlog-plan-cli.ts +4 -1
- package/scripts/backlog/backlog-plan-comment.ts +81 -0
- package/scripts/backlog/backlog-plan-read.ts +19 -6
- package/scripts/backlog/backlog-pool.ts +50 -12
- package/scripts/backlog/backlog-rank.ts +60 -13
- package/scripts/backlog/backlog-stalled-detect.ts +2 -1
- package/scripts/backlog/backlog-waves.ts +17 -2
- package/scripts/backlog/backlogrun-launch.ts +7 -4
- package/scripts/cost-runtime/context-cut-payback.ts +27 -25
- package/scripts/cost-runtime/cost-cli.ts +37 -16
- package/scripts/cost-runtime/cost-pricing.ts +9 -0
- package/scripts/cost-runtime/cost-verdict.ts +4 -1
- package/scripts/delegation/delegation-policy.ts +2 -2
- package/scripts/delegation/duplicate-read-guard.ts +1 -0
- package/scripts/delegation/investigation-guard.ts +14 -2
- package/scripts/delegation/investigation-reads.ts +45 -23
- package/scripts/dependabot/dependabot-cooldown.ts +3 -2
- package/scripts/discovery/repo-party.ts +80 -20
- package/scripts/discovery/session-owner-pin.ts +51 -0
- package/scripts/document/capped-print.ts +1 -1
- package/scripts/document/command-reference-line-budget.ts +42 -0
- package/scripts/document/document-byte-budget.ts +17 -7
- package/scripts/document/document-checks.ts +20 -0
- package/scripts/document/document-ratchet-check.ts +101 -0
- package/scripts/document/document-section.ts +1 -0
- package/scripts/document/entry-read-budget.ts +7 -3
- package/scripts/document/issue-citation-budget.ts +94 -0
- package/scripts/epic/epic-cli-argv.ts +2 -2
- package/scripts/epic/epic-fetch.ts +4 -2
- package/scripts/epic/epic-graph.ts +7 -2
- package/scripts/epic/epic-issue.ts +3 -1
- package/scripts/epic/epic-rank.ts +5 -0
- package/scripts/exports/unused-members-check.ts +62 -0
- package/scripts/exports/unused-members-cli.ts +6 -51
- package/scripts/followup/followup-ci-path.ts +67 -0
- package/scripts/followup/followup-coderabbit-retrigger.ts +261 -0
- package/scripts/followup/followup-coderabbit-wait.ts +13 -10
- package/scripts/followup/followup-failed-tests.ts +160 -0
- package/scripts/followup/followup-job-needs.ts +100 -0
- package/scripts/followup/followup-job-rerun.ts +303 -0
- package/scripts/followup/followup-main-move.ts +113 -0
- package/scripts/followup/git-followup-finish.ts +43 -11
- package/scripts/followup/git-followup-pending.ts +3 -3
- package/scripts/followup/git-followup-stages.ts +41 -11
- package/scripts/followup/git-pr-followup-checks.ts +55 -16
- package/scripts/followup/git-pr-followup-wrapup.ts +24 -5
- package/scripts/followup/git-pr-followup.ts +62 -27
- package/scripts/fresh-machine/fresh-machine-script.ts +5 -9
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +2 -2
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +2 -2
- package/scripts/gate/busy-average.ts +34 -2
- package/scripts/gate/check-related-pinned.ts +43 -0
- package/scripts/gate/check-related-reuse.ts +64 -0
- package/scripts/gate/check-related-section.ts +57 -0
- package/scripts/gate/check-related-unplanned.ts +34 -0
- package/scripts/gate/check-related.ts +265 -0
- package/scripts/gate/command-memory.ts +1 -1
- package/scripts/gate/core-admission.ts +24 -6
- package/scripts/gate/core-budget-timing.ts +20 -6
- package/scripts/gate/core-budget.ts +40 -11
- package/scripts/gate/core-wait-record.ts +3 -2
- package/scripts/gate/core-wait.ts +25 -2
- package/scripts/gate/core-weights.ts +15 -7
- package/scripts/gate/gate-labels.ts +46 -0
- package/scripts/gate/gate-ledger.ts +14 -6
- package/scripts/gate/gate-plan.ts +103 -58
- package/scripts/gate/gate-report.ts +9 -7
- package/scripts/gate/gate-run-steps.ts +26 -3
- package/scripts/gate/gate-skip.ts +45 -6
- package/scripts/gate/gate-static-group.ts +60 -0
- package/scripts/gate/gate-steps.ts +2 -1
- package/scripts/gate/gate-tree.ts +4 -2
- package/scripts/gate/hook-gate-reuse.ts +19 -2
- package/scripts/gate/metrics-totals.ts +59 -0
- package/scripts/gate/scoped-green.ts +68 -15
- package/scripts/gate/since-green.ts +14 -6
- package/scripts/gate/structural-checks.ts +96 -0
- package/scripts/gate/verification-gate.ts +51 -16
- package/scripts/gate/verification-inputs.ts +21 -6
- package/scripts/gate/verification-tail.ts +52 -0
- package/scripts/gh/gh-author-association.ts +23 -2
- package/scripts/gh/git-ai-review-scan.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +12 -3
- package/scripts/gh/git-gh-comments-unreadable.ts +36 -0
- package/scripts/gh/git-gh-exec.ts +32 -2
- package/scripts/gh/git-gh-issue-read.ts +4 -2
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +8 -2
- package/scripts/gh/git-gh-issue.ts +12 -5
- package/scripts/gh/git-gh-pr-auto-merge.ts +13 -6
- package/scripts/gh/git-gh-pr-graphql-state.ts +56 -0
- package/scripts/gh/git-gh-pr-read.ts +74 -13
- package/scripts/gh/git-gh-pr-rest.ts +3 -1
- package/scripts/gh/git-gh-pr-snapshot.ts +22 -7
- package/scripts/gh/git-gh-pr-too-large.ts +20 -0
- package/scripts/gh/git-gh-pr.ts +21 -7
- package/scripts/gh/git-gh-retry.ts +141 -0
- package/scripts/gh/git-pr-ai-review.ts +15 -6
- package/scripts/gh/git-pr-checks-eval.ts +3 -0
- package/scripts/gh/git-pr-checks.ts +5 -5
- package/scripts/git/base-tree.ts +30 -0
- package/scripts/git/change-base.ts +4 -10
- package/scripts/git/changed-paths-sync.ts +63 -0
- package/scripts/git/changed-paths.ts +16 -1
- package/scripts/git/git-common-directory.ts +11 -1
- package/scripts/git/git-diff-reads.ts +66 -20
- package/scripts/git/git-error.ts +9 -2
- package/scripts/git/git-schemas.ts +13 -0
- package/scripts/git/git-worktree.ts +13 -0
- package/scripts/git/gone-branch.ts +4 -1
- package/scripts/git/main-merge-budget-conflict.ts +89 -0
- package/scripts/git/main-merge-guard.ts +55 -18
- package/scripts/git/main-merge-regenerate.ts +59 -25
- package/scripts/git/main-merge.ts +53 -5
- package/scripts/git/no-base-checkout.ts +127 -0
- package/scripts/git/stash/git-stash.ts +11 -2
- package/scripts/git/stash/stash-push-cli.ts +10 -0
- package/scripts/hooks/batch-guard.ts +40 -21
- package/scripts/hooks/edited-cspell.ts +37 -11
- package/scripts/hooks/format-edited-file.ts +22 -2
- package/scripts/hooks/lane-plan-guard.ts +50 -0
- package/scripts/hooks/pre-commit-lint-switch.ts +9 -0
- package/scripts/hooks/pre-commit-lint.ts +14 -1
- package/scripts/hooks/pre-push-related-switch.ts +10 -0
- package/scripts/hooks/pre-push-unit.ts +76 -10
- package/scripts/hooks/pretool-guard.ts +2 -0
- package/scripts/hooks/reserved-run.ts +14 -1
- package/scripts/hooks/run-hook.sh +23 -8
- package/scripts/hooks/step-zero-notice.ts +6 -1
- package/scripts/hooks/stop-actions.ts +3 -15
- package/scripts/hooks/stop-guard.ts +7 -6
- package/scripts/init/distributed-paths.ts +1 -0
- package/scripts/init/hook-command-rewrite.ts +5 -1
- package/scripts/init/hook-launch.ts +4 -2
- package/scripts/issue/aggregation-split.ts +52 -0
- package/scripts/issue/defect-origin-line.ts +19 -1
- package/scripts/issue/defect-rate-cli.ts +5 -102
- package/scripts/issue/defect-report.ts +4 -4
- package/scripts/issue/effect-audit-cli.ts +178 -0
- package/scripts/issue/effect-audit.ts +185 -0
- package/scripts/issue/expected-effect-lint.ts +64 -9
- package/scripts/issue/git-next-issues.ts +5 -0
- package/scripts/issue/issue-body-or-comment.ts +38 -4
- package/scripts/issue/issue-cite-cli.ts +1 -3
- package/scripts/issue/issue-classification.ts +1 -0
- package/scripts/issue/issue-closing-pr.ts +8 -1
- package/scripts/issue/issue-evidence-exit.ts +4 -2
- package/scripts/issue/issue-file-cap.ts +58 -0
- package/scripts/issue/issue-file-cli.ts +111 -38
- package/scripts/issue/issue-file-deferral.ts +52 -0
- package/scripts/issue/issue-file-fold.ts +29 -10
- package/scripts/issue/issue-file-interrupt.ts +85 -0
- package/scripts/issue/issue-file-lane-hint.ts +30 -0
- package/scripts/issue/issue-file.ts +43 -6
- package/scripts/issue/issue-labels.ts +19 -2
- package/scripts/issue/issue-lint-cli.ts +27 -2
- package/scripts/issue/issue-measured-cli.ts +13 -35
- package/scripts/issue/issue-measured-close.ts +58 -0
- package/scripts/issue/issue-not-before-label.ts +2 -2
- package/scripts/issue/issue-not-before.ts +4 -1
- package/scripts/issue/issue-priority-cli.ts +60 -0
- package/scripts/issue/issue-priority-raise.ts +55 -0
- package/scripts/issue/issue-priority.ts +174 -43
- package/scripts/issue/issue-rank.ts +21 -4
- package/scripts/issue/issue-read-cli.ts +32 -6
- package/scripts/issue/issue-read.ts +37 -12
- package/scripts/issue/issue-sample-gate.ts +95 -74
- package/scripts/issue/issue-sample-prime.ts +127 -0
- package/scripts/issue/issue-sample-required.ts +57 -0
- package/scripts/issue/issue-sample-source.ts +12 -11
- package/scripts/issue/issue-search.ts +124 -0
- package/scripts/issue/issue-state.ts +13 -1
- package/scripts/issue/issue-template-section.ts +43 -0
- package/scripts/issue/issue-watch-diff.ts +31 -1
- package/scripts/issue/issue-watch-hook.ts +11 -2
- package/scripts/issue/issue-watch.ts +55 -12
- package/scripts/issue/markdown-section.ts +1 -0
- package/scripts/issue/measure-declaration.ts +121 -0
- package/scripts/issue/measure-rerun-cli.ts +7 -70
- package/scripts/issue/plan-consumers-section.ts +22 -1
- package/scripts/issue/reproduction-measure.ts +3 -1
- package/scripts/issue/size-estimate.ts +90 -0
- package/scripts/issue/trusted-measure.ts +84 -0
- package/scripts/josh/command-usage.ts +3 -2
- package/scripts/josh/durable-state-migrate.ts +105 -0
- package/scripts/josh/durable-state.ts +112 -0
- package/scripts/josh/josh-aliases.ts +95 -0
- package/scripts/josh/josh-command-map.ts +1 -82
- package/scripts/josh/josh-commands-agent-hooks.ts +6 -6
- package/scripts/josh/josh-commands-ai.ts +5 -5
- package/scripts/josh/josh-commands-development.ts +59 -58
- package/scripts/josh/josh-commands-issue-write.ts +23 -4
- package/scripts/josh/josh-commands-issue.ts +32 -0
- package/scripts/josh/josh-commands-lane.ts +87 -4
- package/scripts/josh/josh-commands-lint.ts +16 -3
- package/scripts/josh/josh-commands-maintenance.ts +15 -0
- package/scripts/josh/josh-commands-review.ts +41 -6
- package/scripts/josh/josh-commands-ship.ts +56 -8
- package/scripts/josh/josh-commands-test-check.ts +80 -0
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/josh-environment-file.ts +43 -3
- package/scripts/josh/josh-in-process.ts +2 -2
- package/scripts/josh/josh-logic.ts +5 -3
- package/scripts/josh/josh-run.ts +19 -1
- package/scripts/josh/run-record-path.ts +15 -0
- package/scripts/josh/stamp-file.ts +11 -2
- package/scripts/lane/lane-adopt-cli.ts +98 -0
- package/scripts/lane/lane-adopt.ts +208 -0
- package/scripts/lane/lane-await.ts +5 -8
- package/scripts/lane/lane-baseline.ts +123 -0
- package/scripts/lane/lane-breakdown-cli.ts +64 -0
- package/scripts/lane/lane-breakdown-implement.ts +170 -0
- package/scripts/lane/lane-breakdown-laps.ts +107 -0
- package/scripts/lane/lane-breakdown-pinned.ts +76 -0
- package/scripts/lane/lane-breakdown-text.ts +145 -0
- package/scripts/lane/lane-breakdown.ts +239 -0
- package/scripts/lane/lane-check-stats.ts +29 -8
- package/scripts/lane/lane-child-invocation.ts +9 -2
- package/scripts/lane/lane-child-mark-keys.ts +12 -0
- package/scripts/lane/lane-child-marker.ts +20 -1
- package/scripts/lane/lane-ci-path-stats.ts +73 -0
- package/scripts/lane/lane-claim-stats.ts +84 -0
- package/scripts/lane/lane-close.ts +8 -3
- package/scripts/lane/lane-dispatch-log.ts +3 -3
- package/scripts/lane/lane-dispatch.ts +2 -2
- package/scripts/lane/lane-gap-stats.ts +7 -6
- package/scripts/lane/lane-guard-policy.ts +7 -1
- package/scripts/lane/lane-implement-stats.ts +207 -0
- package/scripts/lane/lane-implement-subagents.ts +90 -0
- package/scripts/lane/lane-investigation-switch.ts +16 -0
- package/scripts/lane/lane-ledger-kind.ts +31 -0
- package/scripts/lane/lane-ledger-schema-ship.ts +49 -0
- package/scripts/lane/lane-ledger-schema.ts +119 -36
- package/scripts/lane/lane-ledger-write.ts +257 -0
- package/scripts/lane/lane-ledger.ts +31 -177
- package/scripts/lane/lane-load.ts +1 -1
- package/scripts/lane/lane-measure-cli.ts +176 -59
- package/scripts/lane/lane-net-read.ts +44 -0
- package/scripts/lane/lane-net-time.ts +212 -0
- package/scripts/lane/lane-open.ts +16 -7
- package/scripts/lane/lane-output.ts +2 -4
- package/scripts/lane/lane-overrun-prompt.ts +147 -0
- package/scripts/lane/lane-overrun.ts +274 -0
- package/scripts/lane/lane-paths.ts +24 -1
- package/scripts/lane/lane-pause-cli.ts +4 -1
- package/scripts/lane/lane-paused-spans.ts +97 -0
- package/scripts/lane/lane-plan-check.ts +207 -0
- package/scripts/lane/lane-plan-cli.ts +41 -0
- package/scripts/lane/lane-plan.ts +144 -0
- package/scripts/lane/lane-registry.ts +14 -1
- package/scripts/lane/lane-relaunch.ts +1 -1
- package/scripts/lane/lane-round-one-stats.ts +51 -0
- package/scripts/lane/lane-sampler.ts +23 -4
- package/scripts/lane/lane-session-action.ts +93 -18
- package/scripts/lane/lane-session-broker.ts +49 -21
- package/scripts/lane/lane-session-reread-main.ts +14 -0
- package/scripts/lane/lane-session-reread.ts +51 -0
- package/scripts/lane/lane-ship-lap-stats.ts +74 -0
- package/scripts/lane/lane-sleep.ts +58 -0
- package/scripts/lane/lane-spent.ts +1 -1
- package/scripts/lane/lane-split-stats.ts +28 -0
- package/scripts/lane/lane-stage-stats.ts +13 -1
- package/scripts/lane/lane-state.ts +41 -9
- package/scripts/lane/lane-stats-tables.ts +58 -0
- package/scripts/lane/lane-stats.ts +21 -5
- package/scripts/lane/lane-stop-stats.ts +51 -19
- package/scripts/lane/lane-tail-stats.ts +32 -0
- package/scripts/lane/lane-transcript-calls.ts +67 -10
- package/scripts/lane/lane-transcript-stats.ts +44 -12
- package/scripts/lane/lane-value-cell.ts +72 -0
- package/scripts/lane/lane-value.ts +118 -0
- package/scripts/lane/lane-withdraw-closed.ts +124 -0
- package/scripts/lane/lane-withdraw.ts +108 -31
- package/scripts/lane/lane-yield.ts +85 -0
- package/scripts/lane/openai-lane-ship.ts +12 -11
- package/scripts/lane/openai-lane-supervisor-decision.ts +6 -8
- package/scripts/lane/openai-lane-supervisor-owner.ts +5 -8
- package/scripts/lane/openai-lane-supervisor.ts +5 -4
- package/scripts/lib/poll.ts +38 -9
- package/scripts/lib/settled-together.ts +10 -0
- package/scripts/lib/shell-quote.ts +21 -0
- package/scripts/lib/token-shape.ts +111 -0
- package/scripts/lint/eslint-daemon-sources.ts +79 -0
- package/scripts/lint/eslint-daemon.ts +45 -6
- package/scripts/lint/eslint-warm-cli.ts +7 -0
- package/scripts/lint/eslint-warm.ts +66 -0
- package/scripts/lint/import-graph.ts +141 -11
- package/scripts/lint/lint-gate-scope.ts +2 -2
- package/scripts/lint/lint-parallel.ts +54 -6
- package/scripts/lint/lint-related.ts +154 -33
- package/scripts/lint/rename-cli.ts +179 -0
- package/scripts/lint/rename-identifier.ts +192 -0
- package/scripts/lint/type-only-imports.ts +58 -0
- package/scripts/notify/telegram-notify.ts +12 -3
- package/scripts/observations/observation-record.ts +42 -16
- package/scripts/observations/observations-flush.ts +32 -9
- package/scripts/overrides/overrides-check.ts +9 -1
- package/scripts/release/release-approval-prune.ts +7 -1
- package/scripts/repo/required-checks-logic.ts +4 -1
- package/scripts/repo/ruleset-check.ts +4 -3
- package/scripts/report/markdown-shape.ts +28 -0
- package/scripts/report/report-format-reference.ts +15 -1
- package/scripts/report/report-labels.ts +12 -1
- package/scripts/report/report-lint-child-summary.ts +94 -0
- package/scripts/report/report-lint-cli.ts +26 -7
- package/scripts/report/report-lint.ts +2 -20
- package/scripts/review/prose-stale-cli.ts +88 -0
- package/scripts/review/prose-stale-scan.ts +152 -0
- package/scripts/review/review-attest.ts +73 -23
- package/scripts/review/review-brief-cli.ts +68 -19
- package/scripts/review/review-brief-paths.ts +22 -0
- package/scripts/review/review-brief.ts +14 -7
- package/scripts/review/review-comment-carry.ts +47 -0
- package/scripts/review/review-comment-round.ts +85 -22
- package/scripts/review/review-finding-ledger.ts +109 -7
- package/scripts/review/review-finding-text.ts +43 -0
- package/scripts/review/review-interaction.ts +11 -0
- package/scripts/review/review-lane-handover.ts +68 -0
- package/scripts/review/review-lint-cli.ts +57 -0
- package/scripts/review/review-lint-findings.ts +92 -0
- package/scripts/review/review-lint-sections.ts +80 -0
- package/scripts/review/review-lint.ts +221 -0
- package/scripts/review/review-prior-findings.ts +102 -0
- package/scripts/review/review-readers-scan.ts +4 -2
- package/scripts/review/review-record-cli.ts +177 -54
- package/scripts/review/review-record-code-round.ts +55 -0
- package/scripts/review/review-record-comment.ts +60 -0
- package/scripts/review/review-record-interaction.ts +35 -0
- package/scripts/review/review-record-pinned.ts +108 -0
- package/scripts/review/review-record.ts +25 -1
- package/scripts/review/review-reviewed-tree.ts +307 -0
- package/scripts/review/review-round-one-closure.ts +62 -0
- package/scripts/review/review-round-reuse.ts +106 -0
- package/scripts/review/review-round2-cli.ts +91 -29
- package/scripts/review/review-round2-skip-comment.ts +55 -0
- package/scripts/review/review-round2.ts +24 -8
- package/scripts/review/review-stamps.ts +7 -3
- package/scripts/review/review-stop-log.ts +20 -6
- package/scripts/review/review-stops-cli.ts +2 -1
- package/scripts/review/review-submit-cli.ts +101 -0
- package/scripts/rules/agent-model.ts +1 -1
- package/scripts/rules/bash-triggers.ts +3 -3
- package/scripts/rules/concise-reply.ts +88 -0
- package/scripts/rules/credential-body.ts +77 -0
- package/scripts/rules/decision-oracle.ts +1 -1
- package/scripts/rules/delivered-rules.ts +36 -17
- package/scripts/rules/destructive-command.ts +3 -11
- package/scripts/rules/direct-issue-comment.ts +34 -12
- package/scripts/rules/direct-issue-read.ts +191 -0
- package/scripts/rules/direct-pr-create.ts +4 -24
- package/scripts/rules/early-heartbeat.ts +2 -0
- package/scripts/rules/edit-tool.ts +27 -0
- package/scripts/rules/file-edit-rows.ts +17 -0
- package/scripts/rules/file-rewrite.ts +146 -0
- package/scripts/rules/firing-point.ts +3 -2
- package/scripts/rules/gh-api.ts +128 -7
- package/scripts/rules/gh-repo-selector.ts +84 -0
- package/scripts/rules/git-force.ts +2 -2
- package/scripts/rules/guard-remedy.ts +14 -5
- package/scripts/rules/implementation-cut.ts +61 -28
- package/scripts/rules/investigator-foreground.ts +231 -0
- package/scripts/rules/issue-citation.ts +15 -60
- package/scripts/rules/issue-comments.ts +9 -4
- package/scripts/rules/josh-git-bare.ts +1 -1
- package/scripts/rules/lane-background.ts +41 -13
- package/scripts/rules/lane-direct-tool.ts +107 -9
- package/scripts/rules/lane-interactive-ask.ts +4 -1
- package/scripts/rules/lane-park.ts +4 -2
- package/scripts/rules/lane-spilled-read.ts +90 -0
- package/scripts/rules/lane-split-park.ts +1 -1
- package/scripts/rules/lane-switch-main.ts +4 -4
- package/scripts/rules/last-prompt.ts +20 -47
- package/scripts/rules/oracle-consulted.ts +1 -1
- package/scripts/rules/permission-guards.ts +5 -1
- package/scripts/rules/piped-verification-shapes.ts +110 -0
- package/scripts/rules/piped-verification.ts +67 -17
- package/scripts/rules/poll-loop.ts +72 -9
- package/scripts/rules/pr-merge.ts +5 -5
- package/scripts/rules/pre-gate-cut.ts +3 -3
- package/scripts/rules/protected-files.ts +88 -24
- package/scripts/rules/reply-language.ts +3 -17
- package/scripts/rules/reply-prose.ts +34 -0
- package/scripts/rules/repo-admin.ts +132 -0
- package/scripts/rules/reviewer-foreground.ts +88 -0
- package/scripts/rules/round-one-check-related.ts +120 -0
- package/scripts/rules/rule-body-guard.ts +5 -15
- package/scripts/rules/rule-value-cache.ts +53 -5
- package/scripts/rules/rule-value-candidates.ts +84 -0
- package/scripts/rules/rule-value-cli.ts +59 -11
- package/scripts/rules/rule-value.ts +17 -4
- package/scripts/rules/run-tail-rule.ts +1 -1
- package/scripts/rules/sed-in-place.ts +196 -0
- package/scripts/rules/shell-segments.ts +10 -2
- package/scripts/rules/stop-rule-rows.ts +1 -13
- package/scripts/rules/stop-rules.ts +33 -58
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +110 -23
- package/scripts/rules/timed-rerun.ts +1 -1
- package/scripts/rules/turn-filings.ts +90 -0
- package/scripts/rules/worktree-guard.ts +22 -7
- package/scripts/run/board/run-board-ending-reason.ts +6 -2
- package/scripts/run/board/run-board-fit.ts +24 -1
- package/scripts/run/board/run-board-found.ts +134 -0
- package/scripts/run/board/run-board-header.ts +8 -0
- package/scripts/run/board/run-board-labels.ts +11 -1
- package/scripts/run/board/run-board-lane-time.ts +1 -0
- package/scripts/run/board/run-board-link.ts +15 -2
- package/scripts/run/board/run-board-notes.ts +7 -1
- package/scripts/run/board/run-board-operation.ts +4 -2
- package/scripts/run/board/run-board-phase.ts +2 -5
- package/scripts/run/board/run-board-plan.ts +1 -1
- package/scripts/run/board/run-board-read.ts +46 -1
- package/scripts/run/board/run-board-reason.ts +20 -8
- package/scripts/run/board/run-board-render-checks.ts +3 -2
- package/scripts/run/board/run-board-render-drawn.ts +11 -0
- package/scripts/run/board/run-board-render-found.ts +157 -0
- package/scripts/run/board/run-board-render-lead.ts +9 -0
- package/scripts/run/board/run-board-render-legend.ts +19 -0
- package/scripts/run/board/run-board-render-tail.ts +1 -1
- package/scripts/run/board/run-board-render.ts +82 -18
- package/scripts/run/board/run-board-spin.ts +1 -3
- package/scripts/run/board/run-board-status.ts +2 -0
- package/scripts/run/board/run-board-tick.ts +39 -10
- package/scripts/run/carry/run-carry-ended.ts +3 -2
- package/scripts/run/carry/run-carry.ts +3 -2
- package/scripts/run/cut/run-cut-cli.ts +33 -133
- package/scripts/run/cut/run-cut-digest.ts +152 -0
- package/scripts/run/cut/run-cut-handoff.ts +52 -8
- package/scripts/run/cut/run-cut-report.ts +24 -3
- package/scripts/run/cut/run-cut-resume.ts +129 -0
- package/scripts/run/cut/run-cut-review.ts +105 -0
- package/scripts/run/cut/run-cut.ts +18 -7
- package/scripts/run/detached-launch.ts +1 -1
- package/scripts/run/entry/run-entry-cli.ts +88 -19
- package/scripts/run/entry/run-entry-spill.ts +83 -0
- package/scripts/run/entry/run-entry-stop.ts +5 -1
- package/scripts/run/entry/run-entry-trust.ts +91 -0
- package/scripts/run/event/run-event-baseline.ts +56 -0
- package/scripts/run/event/run-event-filed.ts +9 -3
- package/scripts/run/event/run-event-overrun.ts +197 -0
- package/scripts/run/event/run-event-render.ts +4 -0
- package/scripts/run/event/run-event-stream.ts +25 -3
- package/scripts/run/hold/run-stop-notify.ts +3 -8
- package/scripts/run/merge/run-merge-cap.ts +57 -0
- package/scripts/run/merge/run-merge-cli.ts +66 -23
- package/scripts/run/merge/run-merge-outcome.ts +2 -0
- package/scripts/run/merge/run-merge-ship.ts +13 -3
- package/scripts/run/merge/run-merge-signals.ts +40 -23
- package/scripts/run/merge/run-merge-steps.ts +56 -36
- package/scripts/run/merge/run-merge-usage-limit.ts +53 -0
- package/scripts/run/merge/run-merge-withdrawn.ts +53 -0
- package/scripts/run/merge/run-merge.ts +41 -14
- package/scripts/run/review/run-review-cli.ts +306 -20
- package/scripts/run/review/run-review-early-push.ts +121 -0
- package/scripts/run/review/run-review-join-read.ts +94 -0
- package/scripts/run/review/run-review-pinned-accepted.ts +126 -0
- package/scripts/run/review/run-review-pinned-join.ts +216 -0
- package/scripts/run/review/run-review-pinned-steps.ts +383 -0
- package/scripts/run/review/run-review-pinned-tree.ts +37 -0
- package/scripts/run/review/run-review-pinned.ts +53 -0
- package/scripts/run/review/run-review-steps.ts +70 -34
- package/scripts/run/review/run-review.ts +26 -6
- package/scripts/run/run-parent-cut-hook.ts +3 -4
- package/scripts/run/run-prep.ts +1 -0
- package/scripts/run/run-stage-read.ts +2 -6
- package/scripts/run/run-step-cli.ts +17 -5
- package/scripts/run/run-step-lane-plan.ts +27 -0
- package/scripts/run/run-step-section.ts +26 -7
- package/scripts/run/run-step.ts +5 -2
- package/scripts/run/ship/run-ship-args.ts +19 -0
- package/scripts/run/ship/run-ship-brokered-review.ts +106 -0
- package/scripts/run/ship/run-ship-cli.ts +131 -39
- package/scripts/run/ship/run-ship-conflict-probe.ts +59 -0
- package/scripts/run/ship/run-ship-detach.ts +10 -4
- package/scripts/run/ship/run-ship-handover.ts +106 -0
- package/scripts/run/ship/run-ship-infra-retry.ts +16 -1
- package/scripts/run/ship/run-ship-lap.ts +63 -0
- package/scripts/run/ship/run-ship-next.ts +27 -26
- package/scripts/run/ship/run-ship-overlap.ts +8 -3
- package/scripts/run/ship/run-ship-place.ts +9 -2
- package/scripts/run/ship/run-ship-planned.ts +92 -0
- package/scripts/run/ship/run-ship-pre-detach-pinned.ts +197 -0
- package/scripts/run/ship/run-ship-pre-detach-timed.ts +7 -8
- package/scripts/run/ship/run-ship-pre-detach.ts +77 -23
- package/scripts/run/ship/run-ship-preflight.ts +16 -4
- package/scripts/run/ship/run-ship-probe.ts +23 -9
- package/scripts/run/ship/run-ship-relaunch-cap.ts +43 -7
- package/scripts/run/ship/run-ship-relaunch.ts +51 -0
- package/scripts/run/ship/run-ship-return.ts +103 -29
- package/scripts/run/ship/run-ship-review-reason.ts +24 -0
- package/scripts/run/ship/run-ship-review-steps.ts +230 -59
- package/scripts/run/ship/run-ship-review.ts +171 -51
- package/scripts/run/ship/run-ship-reviewer.ts +138 -42
- package/scripts/run/ship/run-ship-scoped.ts +39 -10
- package/scripts/run/ship/run-ship-stage.ts +49 -13
- package/scripts/run/ship/run-ship-steps.ts +24 -4
- package/scripts/run/ship/run-ship-stop-cause.ts +43 -2
- package/scripts/run/ship/run-ship-stop-context.ts +50 -13
- package/scripts/run/ship/run-ship-sync.ts +171 -30
- package/scripts/run/ship/run-ship-synced-scope.ts +178 -0
- package/scripts/run/ship/run-ship-wait-cli.ts +145 -0
- package/scripts/run/ship/run-ship-waiter.ts +114 -0
- package/scripts/run/ship/run-ship.ts +16 -2
- package/scripts/run/wake/run-wake-caffeinate.ts +48 -0
- package/scripts/run/wake/run-wake-cli.ts +6 -113
- package/scripts/run/wake/run-wake-code.ts +53 -11
- package/scripts/run/wake/run-wake-driver.ts +5 -3
- package/scripts/run/wake/run-wake-finish.ts +137 -0
- package/scripts/run/wake/run-wake-loop.ts +5 -3
- package/scripts/run/wake/run-wake-ports.ts +11 -3
- package/scripts/run/wake/run-wake-session.ts +2 -0
- package/scripts/run/wake/run-wake.ts +3 -2
- package/scripts/safe-chain/ci-installer-pin.ts +49 -8
- package/scripts/safe-chain/project-config.ts +3 -2
- package/scripts/security/secretlint-scan.ts +42 -9
- package/scripts/security/security-audit-provision-main.ts +9 -1
- package/scripts/security/security-audit-provision.ts +1 -1
- package/scripts/security/security-audit.ts +21 -1
- package/scripts/security/sonar-file.ts +10 -5
- package/scripts/split/split-assess.ts +12 -3
- package/scripts/split/split-early-notice.ts +116 -0
- package/scripts/split/split-measure.ts +20 -2
- package/scripts/split/split-resolution.ts +107 -0
- package/scripts/test/direct-importers.ts +185 -0
- package/scripts/test/pure-files-entries.ts +83 -0
- package/scripts/test/related-heavy-tests.ts +81 -0
- package/scripts/test/test-no-base.ts +88 -0
- package/scripts/test/test-pinned-cache-logic.ts +363 -0
- package/scripts/test/test-pinned-cache.ts +337 -0
- package/scripts/test/test-pinned-emit.ts +49 -0
- package/scripts/test/test-pinned-functions.ts +116 -0
- package/scripts/test/test-pinned-ledger.ts +80 -0
- package/scripts/test/test-pinned-logic.ts +208 -20
- package/scripts/test/test-pinned-main.ts +84 -18
- package/scripts/test/test-pinned-pool.ts +73 -0
- package/scripts/test/test-pinned-probe.ts +254 -0
- package/scripts/test/test-pinned-prune-logic.ts +118 -0
- package/scripts/test/test-pinned-reach.ts +194 -0
- package/scripts/test/test-pinned-record.ts +196 -0
- package/scripts/test/test-pinned-rewire.ts +148 -0
- package/scripts/test/test-pinned-spawn.ts +81 -0
- package/scripts/test/test-pinned-stage.ts +70 -0
- package/scripts/test/test-pinned.ts +258 -47
- package/scripts/test/test-reach-cli.ts +61 -0
- package/scripts/test/test-read-map.ts +35 -11
- package/scripts/test/test-read-recording.ts +17 -5
- package/scripts/test/test-read-trace.ts +26 -8
- package/scripts/test/test-red-logic.ts +46 -7
- package/scripts/test/test-red.ts +34 -14
- package/scripts/test/test-related-claim.ts +37 -0
- package/scripts/test/test-related-main.ts +4 -1
- package/scripts/test/test-related-moved.ts +91 -0
- package/scripts/test/test-related-record.ts +43 -23
- package/scripts/test/test-related-scope.ts +99 -34
- package/scripts/test/test-related-synced.ts +135 -0
- package/scripts/test/test-related-touched.ts +84 -0
- package/scripts/test/test-related.ts +167 -83
- package/scripts/test/test-unit-guard.ts +28 -5
- package/scripts/test/unit-durations.ts +41 -0
- package/scripts/test/unit-worker-share.ts +5 -4
- package/scripts/test/vitest-cache-directory.ts +19 -0
- package/scripts/test/vitest-cli-excludes.ts +14 -0
- package/scripts/test/vitest-failure-summary.ts +111 -0
- package/scripts/test/whole-suite-files.ts +12 -1
- package/scripts/time-runtime/time-batch-guard.ts +42 -4
- package/scripts/time-runtime/time-bundle-call.ts +1 -1
- package/scripts/time-runtime/time-bundles.ts +36 -5
- package/scripts/time-runtime/time-markers.ts +2 -2
- package/scripts/time-runtime/time-search-call.ts +38 -0
- package/scripts/time-runtime/time-shell.ts +1 -1
- package/scripts/time-runtime/time-transcript-line.ts +17 -5
- package/scripts/version/development-engines-verdict.ts +124 -0
- package/scripts/version/latest-corepack.ts +2 -0
- package/templates/gitignore +2 -0
- package/templates/workflows/ci.yml +41 -0
- package/dist/hooks/chunk-AZX4FGQ3.js +0 -207
- package/dist/hooks/chunk-PT5R6UJD.js +0 -7131
- package/dist/hooks/chunk-TUIFS5E7.js +0 -72
- package/dist/hooks/chunk-YCDOIR3I.js +0 -3456
- package/scripts/cost-runtime/context-cut-threshold.ts +0 -11
- package/scripts/rules/filing-cap.ts +0 -139
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
|
|
2
|
+
import {
|
|
3
|
+
git_gh_pr_read,
|
|
4
|
+
read_pull_or_listed,
|
|
5
|
+
read_pull as read_rest_pull,
|
|
6
|
+
} from '#scripts/gh/git-gh-pr-read'
|
|
7
|
+
import { git_gh_pr_rest } from '#scripts/gh/git-gh-pr-rest'
|
|
8
|
+
import { git_command } from '#scripts/git/git-command'
|
|
9
|
+
import { issue_state, type IssueState } from '#scripts/issue/issue-state'
|
|
10
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
11
|
+
import { PROCESS_ALIVE, PROCESS_NONE, type ProcessTrace } from '#scripts/run/run-liveness'
|
|
12
|
+
import { lane_await } from './lane-await'
|
|
13
|
+
import type { LaneInfo } from './lane-registry'
|
|
14
|
+
import { lane_spent } from './lane-spent'
|
|
15
|
+
import {
|
|
16
|
+
lane_state,
|
|
17
|
+
type LaneChange,
|
|
18
|
+
type LaneRecords,
|
|
19
|
+
type LaneState,
|
|
20
|
+
type RecordOutcome,
|
|
21
|
+
} from './lane-state'
|
|
22
|
+
|
|
23
|
+
// `josh lane:adopt` (joshuafolkken/kit#4744): give a lane whose state record was lost — a restart, a
|
|
24
|
+
// usage limit, an interrupted run — a record again, from what can be read off it, without touching its
|
|
25
|
+
// branch, its work tree or its pull request.
|
|
26
|
+
//
|
|
27
|
+
// **Nothing is guessed.** A lane is written `open` — opened, no child working in it — only when its
|
|
28
|
+
// process probe answers that no child is there and its work tree status, its unpushed commits, its pull
|
|
29
|
+
// request and its issue all read; any one unread leaves it unknown, counted in use as before
|
|
30
|
+
// (`backlog-occupied.ts`). `open` rather than `paused`: nobody suspended it, and a paused lane is one
|
|
31
|
+
// `run:liveness` says not to recover. The next launch moves it to `running` (`lane-state.ts`), and
|
|
32
|
+
// the next `backlogrun` takes the lane back while its issue still carries `in-progress`
|
|
33
|
+
// (`backlog-drive-carried.ts`).
|
|
34
|
+
|
|
35
|
+
const ADOPT_COMMAND = 'lane:adopt'
|
|
36
|
+
const ISSUE_FIELDS = 'state,labels'
|
|
37
|
+
const SEPARATOR = ' · '
|
|
38
|
+
|
|
39
|
+
// The branch's pull request — the open one, else the newest (`git_gh_pr_rest.select_pull`) — with its
|
|
40
|
+
// gh state, since a reopened lane's branch can still carry the merged one.
|
|
41
|
+
interface Pull {
|
|
42
|
+
number: number
|
|
43
|
+
state: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// A pull request read: the branch's pull request, or none.
|
|
47
|
+
interface PullRead {
|
|
48
|
+
pull: Pull | undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
interface LaneFacts {
|
|
52
|
+
branch: string
|
|
53
|
+
is_dirty: boolean
|
|
54
|
+
unpushed: number
|
|
55
|
+
pull: Pull | undefined
|
|
56
|
+
issue: IssueState
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Each read answers `undefined` when it could not be made.
|
|
60
|
+
interface AdoptPorts {
|
|
61
|
+
process_trace: (issue: string) => ProcessTrace
|
|
62
|
+
tree_status: (directory: string) => Promise<string | undefined>
|
|
63
|
+
unpushed_commits: (branch: string) => Promise<number | undefined>
|
|
64
|
+
pull_request: (branch: string) => Promise<PullRead | undefined>
|
|
65
|
+
issue: (issue: string) => Promise<IssueState | undefined>
|
|
66
|
+
record: (change: LaneChange) => Promise<RecordOutcome>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
type Adoption =
|
|
70
|
+
| { kind: 'adopted'; facts: LaneFacts }
|
|
71
|
+
| { kind: 'kept'; state: LaneState }
|
|
72
|
+
| { kind: 'left'; reason: string }
|
|
73
|
+
|
|
74
|
+
async function read_tree_status(directory: string): Promise<string | undefined> {
|
|
75
|
+
try {
|
|
76
|
+
return await git_command.status(directory)
|
|
77
|
+
} catch {
|
|
78
|
+
return undefined
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function read_pull(branch: string): Promise<Pull | undefined> {
|
|
83
|
+
const number = await git_gh_pr_read.pr_get_number(branch)
|
|
84
|
+
|
|
85
|
+
if (number === undefined) return undefined
|
|
86
|
+
|
|
87
|
+
// The listing row carries `state` and `merged_at` too, so it stands in for a detail GitHub refuses
|
|
88
|
+
// as too many files changed.
|
|
89
|
+
const pull = await read_pull_or_listed(branch, number, read_rest_pull)
|
|
90
|
+
const state = git_gh_pr_rest.to_pr_state(pull)
|
|
91
|
+
|
|
92
|
+
return state === undefined ? undefined : { number, state }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// `undefined` when anything could not be read, including a pull request that exists but whose number
|
|
96
|
+
// or state did not resolve.
|
|
97
|
+
async function read_pull_request(branch: string): Promise<PullRead | undefined> {
|
|
98
|
+
try {
|
|
99
|
+
if (!(await git_gh_pr_read.pr_exists(branch))) return { pull: undefined }
|
|
100
|
+
|
|
101
|
+
const pull = await read_pull(branch)
|
|
102
|
+
|
|
103
|
+
return pull === undefined ? undefined : { pull }
|
|
104
|
+
} catch {
|
|
105
|
+
return undefined
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function read_issue(issue: string): Promise<IssueState | undefined> {
|
|
110
|
+
const json = await git_gh_issue_read.issue_view_json(issue, ISSUE_FIELDS)
|
|
111
|
+
|
|
112
|
+
return json === undefined ? undefined : issue_state.parse_issue_state(json)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function record_open(change: LaneChange): Promise<RecordOutcome> {
|
|
116
|
+
return await lane_state.record_adopted(change)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const LIVE_PORTS: AdoptPorts = {
|
|
120
|
+
process_trace: lane_await.process_trace_default,
|
|
121
|
+
tree_status: read_tree_status,
|
|
122
|
+
unpushed_commits: lane_spent.read_unpushed_commits,
|
|
123
|
+
pull_request: read_pull_request,
|
|
124
|
+
issue: read_issue,
|
|
125
|
+
record: record_open,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function left(reason: string): Adoption {
|
|
129
|
+
return { kind: 'left', reason }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function process_reason(lane: LaneInfo, ports: AdoptPorts): string | undefined {
|
|
133
|
+
if (lane.is_stranded) return 'its work tree is gone'
|
|
134
|
+
|
|
135
|
+
const trace = ports.process_trace(lane.issue)
|
|
136
|
+
|
|
137
|
+
if (trace === PROCESS_ALIVE) return 'a child is working in it'
|
|
138
|
+
|
|
139
|
+
return trace === PROCESS_NONE ? undefined : 'its process probe did not answer'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// What each fact is called where it could not be read, in the order `facts_of` reads them.
|
|
143
|
+
const FACT_NAMES = ['work tree status', 'unpushed commits', 'pull request', 'issue'] as const
|
|
144
|
+
|
|
145
|
+
function unread_names(reads: ReadonlyArray<unknown>): string {
|
|
146
|
+
return FACT_NAMES.filter((_name, index) => reads[index] === undefined).join(', ')
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function facts_of(lane: LaneInfo, ports: AdoptPorts): Promise<LaneFacts | string> {
|
|
150
|
+
const reads = await Promise.all([
|
|
151
|
+
ports.tree_status(lane.directory),
|
|
152
|
+
ports.unpushed_commits(lane.branch),
|
|
153
|
+
ports.pull_request(lane.branch),
|
|
154
|
+
ports.issue(lane.issue),
|
|
155
|
+
])
|
|
156
|
+
const [status, unpushed, pull, issue] = reads
|
|
157
|
+
|
|
158
|
+
if (status === undefined || unpushed === undefined || pull === undefined || issue === undefined) {
|
|
159
|
+
return `could not read its ${unread_names(reads)}`
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return { branch: lane.branch, is_dirty: status.trim() !== '', unpushed, pull: pull.pull, issue }
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
async function written(issue: string, facts: LaneFacts, ports: AdoptPorts): Promise<Adoption> {
|
|
166
|
+
const outcome = await ports.record({ issue, state: 'open', command: ADOPT_COMMAND })
|
|
167
|
+
|
|
168
|
+
return outcome.kind === 'written' ? { kind: 'adopted', facts } : left(outcome.reason)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** Write an `open` record for `lane` when it has none and every fact about it reads. */
|
|
172
|
+
async function adopt(
|
|
173
|
+
lane: LaneInfo,
|
|
174
|
+
records: LaneRecords,
|
|
175
|
+
ports: AdoptPorts = LIVE_PORTS,
|
|
176
|
+
): Promise<Adoption> {
|
|
177
|
+
const recorded = records.get(lane.issue)
|
|
178
|
+
|
|
179
|
+
if (recorded !== undefined) return { kind: 'kept', state: recorded.state }
|
|
180
|
+
|
|
181
|
+
const blocked = process_reason(lane, ports)
|
|
182
|
+
|
|
183
|
+
if (blocked !== undefined) return left(blocked)
|
|
184
|
+
|
|
185
|
+
const facts = await facts_of(lane, ports)
|
|
186
|
+
|
|
187
|
+
return typeof facts === 'string' ? left(facts) : await written(lane.issue, facts, ports)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** `branch 4744-lane · uncommitted changes · 2 unpushed commit(s) · PR [#4801](…) OPEN · issue OPEN (in-progress)` */
|
|
191
|
+
function facts_text(facts: LaneFacts): string {
|
|
192
|
+
const labels = facts.issue.labels.length > 0 ? ` (${facts.issue.labels.join(', ')})` : ''
|
|
193
|
+
|
|
194
|
+
return [
|
|
195
|
+
`branch ${facts.branch}`,
|
|
196
|
+
facts.is_dirty ? 'uncommitted changes' : 'clean tree',
|
|
197
|
+
`${String(facts.unpushed)} unpushed commit(s)`,
|
|
198
|
+
facts.pull === undefined
|
|
199
|
+
? 'no PR'
|
|
200
|
+
: `PR ${session_cite.issue(facts.pull.number)} ${facts.pull.state}`,
|
|
201
|
+
`issue ${facts.issue.state}${labels}`,
|
|
202
|
+
].join(SEPARATOR)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const lane_adopt = { ADOPT_COMMAND, adopt, facts_text, read_pull_request }
|
|
206
|
+
|
|
207
|
+
export { lane_adopt }
|
|
208
|
+
export type { AdoptPorts, Adoption, LaneFacts }
|
|
@@ -2,6 +2,7 @@ import { spawnSync } from 'node:child_process'
|
|
|
2
2
|
import { setTimeout as sleep } from 'node:timers/promises'
|
|
3
3
|
import { parseArgs } from 'node:util'
|
|
4
4
|
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
5
|
+
import { poll } from '#scripts/lib/poll'
|
|
5
6
|
import { MS_PER_SECOND, PROBE_TIMEOUT_MS } from '#scripts/lib/timeouts'
|
|
6
7
|
import {
|
|
7
8
|
PROCESS_ALIVE,
|
|
@@ -290,14 +291,10 @@ async function wait_for_any(
|
|
|
290
291
|
const config = resolve_options(options)
|
|
291
292
|
const states = await make_states(issues, config.is_settled)
|
|
292
293
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
// eslint-disable-next-line no-await-in-loop -- polling: each read waits on the state the previous one saw
|
|
299
|
-
await config.sleep(config.poll_ms)
|
|
300
|
-
}
|
|
294
|
+
return await poll.wait_for(() => check_any(states, config.now(), config), {
|
|
295
|
+
interval_ms: config.poll_ms,
|
|
296
|
+
sleeper: config.sleep,
|
|
297
|
+
})
|
|
301
298
|
}
|
|
302
299
|
|
|
303
300
|
const lane_await = {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { detached_launch } from '#scripts/run/detached-launch'
|
|
2
|
+
import { run_event_baseline } from '#scripts/run/event/run-event-baseline'
|
|
3
|
+
import { run_event_stream, type RunEvent } from '#scripts/run/event/run-event-stream'
|
|
4
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
5
|
+
import { lane_investigation_switch } from './lane-investigation-switch'
|
|
6
|
+
import { lane_ledger } from './lane-ledger'
|
|
7
|
+
import { lane_overrun } from './lane-overrun'
|
|
8
|
+
import { lane_overrun_prompt } from './lane-overrun-prompt'
|
|
9
|
+
import { lane_stage_stats } from './lane-stage-stats'
|
|
10
|
+
|
|
11
|
+
// Every `BASELINE_MERGES`-th merge the median lane itself is investigated (joshuafolkken/kit#4887).
|
|
12
|
+
// The overrun investigation (`lane-overrun.ts`) reads only a lane slower than the threshold, so the time
|
|
13
|
+
// every lane spends is never a candidate for a cut. `run:merge` asks at each merge: the last multiple the
|
|
14
|
+
// ledger's merge count reached, when no note has it yet, launches a detached worker session that reads
|
|
15
|
+
// `lane:stats`, takes the stages and sub-stages that spend the most per merge, and files their causes
|
|
16
|
+
// by the overrun investigation's filing rules — the same prompt part, a cause's reducible minutes cut
|
|
17
|
+
// from one median merge rather than one lane (joshuafolkken/kit#4928). Its filings name no lane they
|
|
18
|
+
// were found during. The launch and the session's result go on the run's event stream as notes, which
|
|
19
|
+
// `run:board` shows. It runs only while `JOSH_LANE_INVESTIGATION` is on (`lane-investigation-switch.ts`);
|
|
20
|
+
// off by default, a due bucket launches nothing and notes nothing (joshuafolkken/kit#5044).
|
|
21
|
+
|
|
22
|
+
const { EVENT_KIND } = run_event_stream
|
|
23
|
+
const BASELINE_MERGES = 30
|
|
24
|
+
const LOG_PREFIX = 'josh-lane-baseline-'
|
|
25
|
+
const STATS_PERIOD_DAYS = 3
|
|
26
|
+
const MEDIAN_PLACEHOLDER = '<median lane minutes>'
|
|
27
|
+
const SCOPE = 'the median merge, judged from the per-merge minutes `lane:stats` prints'
|
|
28
|
+
|
|
29
|
+
// The last multiple of `BASELINE_MERGES` the count reached: two merges recorded between two asks, or an
|
|
30
|
+
// ask that failed, still leave the bucket due at the next merge.
|
|
31
|
+
function due_bucket(merges: number): number {
|
|
32
|
+
return Math.floor(merges / BASELINE_MERGES) * BASELINE_MERGES
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// A count investigated already — a retried merge finds its note — launches no second session. A
|
|
36
|
+
// failure names no count, so it never answers for one.
|
|
37
|
+
function is_noted(events: ReadonlyArray<RunEvent>, merges: number): boolean {
|
|
38
|
+
return events.some((event) => {
|
|
39
|
+
const note = event.kind === EVENT_KIND.NOTE ? run_event_baseline.parse(event.text) : undefined
|
|
40
|
+
|
|
41
|
+
return note !== undefined && note.kind !== 'failed' && note.merges === merges
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// The due bucket of the ledger's merge count, else `undefined` before the first.
|
|
46
|
+
async function due_merges(): Promise<number | undefined> {
|
|
47
|
+
const path = await lane_ledger.target()
|
|
48
|
+
|
|
49
|
+
if (path === undefined) return undefined
|
|
50
|
+
|
|
51
|
+
const merges = lane_ledger.read_entries(path).filter((entry) => lane_stage_stats.is_merge(entry))
|
|
52
|
+
const bucket = due_bucket(merges.length)
|
|
53
|
+
|
|
54
|
+
return bucket > 0 ? bucket : undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function reading(merges: number): string {
|
|
58
|
+
return [
|
|
59
|
+
`Investigate the median lane after ${String(merges)} merges: not an overrun, but the time every lane`,
|
|
60
|
+
'spends. Leave this checkout as it is: write any file, an issue body included, under the system temp',
|
|
61
|
+
'directory, and never stage, commit or push.',
|
|
62
|
+
`Read \`pnpm josh lane:stats --period ${String(STATS_PERIOD_DAYS)}\` — its stage table and its`,
|
|
63
|
+
'implement sub-stage table — and take the several stages and sub-stages with the largest per-merge',
|
|
64
|
+
"time, not just the one largest. Read the period lanes' transcripts (the lane directories `lane:stats`",
|
|
65
|
+
"reads) and the run events (`pnpm josh run:event --from 0`) for where each one's time goes, and find",
|
|
66
|
+
'the causes a fix could cut.',
|
|
67
|
+
'Trace each cause to what can fix it: the minutes it spends per merge, the signal that led to the',
|
|
68
|
+
'spend (which command printed what), the `file:line` of the code or document that decided it, and',
|
|
69
|
+
'where to fix it.',
|
|
70
|
+
].join(' ')
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// One line: `detached_launch` lets a prompt break lines, but a single line keeps the log header whole.
|
|
74
|
+
function prompt(issue: number, merges: number): string {
|
|
75
|
+
const handling = lane_overrun_prompt.cause_handling({
|
|
76
|
+
origin: undefined,
|
|
77
|
+
loss_lines: lane_overrun_prompt.loss_lines_of(issue, MEDIAN_PLACEHOLDER),
|
|
78
|
+
template: run_event_baseline.ended_text(merges, '<result>'),
|
|
79
|
+
scope: SCOPE,
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
return `${reading(merges)} ${handling}`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function note_failure(note: string): void {
|
|
86
|
+
void run_event_stream_emit.emit(EVENT_KIND.NOTE, run_event_baseline.failed_text(note))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// The launch at merge `issue`, the `merges`-th; its filings count against that lane.
|
|
90
|
+
function launched(issue: number, merges: number): string {
|
|
91
|
+
return lane_overrun.launch({
|
|
92
|
+
env: {},
|
|
93
|
+
prompt: prompt(issue, merges),
|
|
94
|
+
log_prefix: `${LOG_PREFIX}${String(merges)}-`,
|
|
95
|
+
on_failure: note_failure,
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async function investigate_baseline(issue: number): Promise<void> {
|
|
100
|
+
const merges = await due_merges()
|
|
101
|
+
|
|
102
|
+
if (merges === undefined || is_noted(await run_event_stream_emit.all_events(), merges)) return
|
|
103
|
+
|
|
104
|
+
await run_event_stream_emit.emit(
|
|
105
|
+
EVENT_KIND.NOTE,
|
|
106
|
+
run_event_baseline.started_text(merges, launched(issue, merges)),
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Never fails the merge it follows: an error is a note on the stream, not a refused merge.
|
|
111
|
+
async function investigate(issue: number): Promise<void> {
|
|
112
|
+
if (!lane_investigation_switch.is_on()) return
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
await investigate_baseline(issue)
|
|
116
|
+
} catch (error) {
|
|
117
|
+
note_failure(detached_launch.note_of(error))
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const lane_baseline = { due_bucket, investigate }
|
|
122
|
+
|
|
123
|
+
export { lane_baseline }
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { issue_number_shape } from '#scripts/issue/issue-number-shape'
|
|
4
|
+
import { session_cite } from '#scripts/issue/session-cite'
|
|
5
|
+
import { run_event_stream_emit } from '#scripts/run/event/run-event-stream-emit'
|
|
6
|
+
import { lane_breakdown } from './lane-breakdown'
|
|
7
|
+
import { lane_breakdown_text } from './lane-breakdown-text'
|
|
8
|
+
import { lane_ledger } from './lane-ledger'
|
|
9
|
+
import { lane_net_time } from './lane-net-time'
|
|
10
|
+
|
|
11
|
+
// `josh lane:breakdown <issue>` — a merged lane's net time by stage (joshuafolkken/kit#4995), the same
|
|
12
|
+
// breakdown its overrun investigation comments on its Issue.
|
|
13
|
+
|
|
14
|
+
const ARGV_OFFSET = 2
|
|
15
|
+
const FAILURE_EXIT_CODE = 1
|
|
16
|
+
const USAGE = 'Usage: josh lane:breakdown <issue>'
|
|
17
|
+
|
|
18
|
+
async function read_ledger(): Promise<ReturnType<typeof lane_ledger.read_entries>> {
|
|
19
|
+
const path = await lane_ledger.target()
|
|
20
|
+
|
|
21
|
+
return path === undefined ? [] : lane_ledger.read_entries(path)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function missing(issue: string): number {
|
|
25
|
+
const lane = session_cite.issue(issue)
|
|
26
|
+
|
|
27
|
+
console.error(`josh lane:breakdown ${issue}: the ledger holds no dispatch and merge of ${lane}`)
|
|
28
|
+
|
|
29
|
+
return FAILURE_EXIT_CODE
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function print(issue: string): Promise<number> {
|
|
33
|
+
const [entries, events] = [await read_ledger(), await run_event_stream_emit.all_events()]
|
|
34
|
+
const minutes = lane_net_time.net_minutes(entries, events, Number(issue))
|
|
35
|
+
const breakdown = lane_breakdown.of(entries, events, Number(issue))
|
|
36
|
+
|
|
37
|
+
if (minutes === undefined || breakdown === undefined) return missing(issue)
|
|
38
|
+
|
|
39
|
+
const report = lane_breakdown_text.report_of(Number(issue), breakdown, entries)
|
|
40
|
+
|
|
41
|
+
console.info(lane_breakdown_text.comment(Number(issue), minutes, report))
|
|
42
|
+
|
|
43
|
+
return 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
47
|
+
const [issue = ''] = argv
|
|
48
|
+
|
|
49
|
+
if (argv.length === 1 && issue_number_shape.is_issue_number(issue)) return await print(issue)
|
|
50
|
+
|
|
51
|
+
console.error(USAGE)
|
|
52
|
+
|
|
53
|
+
return FAILURE_EXIT_CODE
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function main(argv: ReadonlyArray<string>): Promise<void> {
|
|
57
|
+
process.exitCode = await run(argv)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const lane_breakdown_cli = { USAGE, run }
|
|
61
|
+
|
|
62
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
|
|
63
|
+
|
|
64
|
+
export { lane_breakdown_cli }
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { cost_transcript } from '#scripts/cost-runtime/cost-transcript'
|
|
2
|
+
import { lane_breakdown, type Breakdown, type Stage } from './lane-breakdown'
|
|
3
|
+
import type { LaneSpan } from './lane-net-time'
|
|
4
|
+
import type { Subagent, ToolCall } from './lane-transcript-calls'
|
|
5
|
+
import { lane_transcript_stats } from './lane-transcript-stats'
|
|
6
|
+
|
|
7
|
+
// The implementation stage of a lane's breakdown (joshuafolkken/kit#4995) split by what its tool calls
|
|
8
|
+
// spent, read off the lane's transcripts: the main josh commands, the subagents, the reads and the rest
|
|
9
|
+
// of Bash, and what no call spent — the edits and the thinking. A backgrounded call has no duration
|
|
10
|
+
// (`lane-transcript-calls.ts`), so the wait on its result falls in the remainder; only its count shows.
|
|
11
|
+
//
|
|
12
|
+
// **The subagents split by the agent dispatched** — `subagent: investigator`, `subagent: reviewer`, …
|
|
13
|
+
// — and a backgrounded subagent call still names its kind, at no time, with its count beside it
|
|
14
|
+
// (joshuafolkken/kit#5297). `run:review` and `ship` / `ship:wait` count apart from other bash
|
|
15
|
+
// (joshuafolkken/kit#5293).
|
|
16
|
+
|
|
17
|
+
const REMAINDER = 'editing & thinking'
|
|
18
|
+
const OTHER_BASH = 'other bash'
|
|
19
|
+
const BASH_TOOL = 'Bash'
|
|
20
|
+
const READ = 'read'
|
|
21
|
+
|
|
22
|
+
const TOOL_KINDS: ReadonlyMap<string, string> = new Map([
|
|
23
|
+
['Read', READ],
|
|
24
|
+
['Grep', READ],
|
|
25
|
+
['Glob', READ],
|
|
26
|
+
])
|
|
27
|
+
|
|
28
|
+
const COMMAND_KINDS: ReadonlyArray<readonly [RegExp, string]> = [
|
|
29
|
+
[/\bjosh main:merge\b/u, 'main:merge'],
|
|
30
|
+
[/\bjosh check:related\b/u, 'check:related'],
|
|
31
|
+
[/\bjosh gate\b/u, 'gate'],
|
|
32
|
+
[/\bjosh run:review\b/u, 'run:review'],
|
|
33
|
+
[/\bjosh ship(?::wait)?\b/u, 'ship / ship:wait'],
|
|
34
|
+
[/\bjosh test(?::[\w-]+)?\b/u, 'test'],
|
|
35
|
+
[/\bjosh (?:lint|cspell)(?::[\w-]+)?\b/u, 'lint / cspell'],
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
interface ImplementDetail {
|
|
39
|
+
// Longest first, the remainder among them.
|
|
40
|
+
kinds: ReadonlyArray<Stage>
|
|
41
|
+
// The calls backgrounded inside the implementation.
|
|
42
|
+
background: number
|
|
43
|
+
// Each subagent kind's backgrounded calls, counted at no time.
|
|
44
|
+
untimed: ReadonlyMap<string, number>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function command_kind(command: string): string {
|
|
48
|
+
return COMMAND_KINDS.find(([pattern]) => pattern.test(command))?.[1] ?? OTHER_BASH
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function subagent_kind(subagent: Subagent): string {
|
|
52
|
+
return `subagent: ${subagent.type}`
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// The kind a call counts under, `undefined` for one that falls in the remainder (an edit included).
|
|
56
|
+
function kind_of(call: ToolCall): string | undefined {
|
|
57
|
+
if (call.tool === BASH_TOOL) return command_kind(call.command ?? '')
|
|
58
|
+
if (call.subagent !== undefined) return subagent_kind(call.subagent)
|
|
59
|
+
|
|
60
|
+
return TOOL_KINDS.get(call.tool ?? '')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface TimedPart extends Stage {
|
|
64
|
+
from_ms: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function is_untimed_subagent(call: ToolCall): boolean {
|
|
68
|
+
return call.background && call.subagent !== undefined
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// A call's own milliseconds, cut at the end of the span it started in; a backgrounded subagent call's none.
|
|
72
|
+
function timed_part(call: ToolCall, span: LaneSpan): ReadonlyArray<TimedPart> {
|
|
73
|
+
const name = kind_of(call)
|
|
74
|
+
|
|
75
|
+
if (name === undefined) return []
|
|
76
|
+
|
|
77
|
+
const ms = Math.min(call.duration_ms ?? 0, span.to_ms - call.started_ms)
|
|
78
|
+
const is_counted = call.duration_ms !== undefined || is_untimed_subagent(call)
|
|
79
|
+
|
|
80
|
+
return is_counted ? [{ name, ms, from_ms: call.started_ms }] : []
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function untimed_of(placed: ReadonlyArray<readonly [ToolCall, LaneSpan]>): Map<string, number> {
|
|
84
|
+
const counts = new Map<string, number>()
|
|
85
|
+
const kinds = placed.filter(([call]) => is_untimed_subagent(call)).map(([call]) => kind_of(call))
|
|
86
|
+
|
|
87
|
+
for (const kind of kinds) if (kind !== undefined) counts.set(kind, (counts.get(kind) ?? 0) + 1)
|
|
88
|
+
|
|
89
|
+
return counts
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// What neither a timed call nor a wait covers of the implementation's spans, each millisecond once.
|
|
93
|
+
function remainder_ms(parts: ReadonlyArray<TimedPart>, breakdown: Breakdown): number {
|
|
94
|
+
const busy = parts.map((part) => ({ from_ms: part.from_ms, to_ms: part.from_ms + part.ms }))
|
|
95
|
+
const covering = [...busy, ...breakdown.waits]
|
|
96
|
+
const idle = breakdown.implement.map(
|
|
97
|
+
(span) => span.to_ms - span.from_ms - lane_breakdown.covered_ms(span, covering),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
return idle.reduce((sum, ms) => sum + ms, 0)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function span_of(call: ToolCall, spans: ReadonlyArray<LaneSpan>): LaneSpan | undefined {
|
|
104
|
+
return spans.find((span) => call.started_ms >= span.from_ms && call.started_ms < span.to_ms)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function placed_of(
|
|
108
|
+
calls: ReadonlyArray<ToolCall>,
|
|
109
|
+
spans: ReadonlyArray<LaneSpan>,
|
|
110
|
+
): Array<readonly [ToolCall, LaneSpan]> {
|
|
111
|
+
return calls.flatMap((call) => {
|
|
112
|
+
const span = span_of(call, spans)
|
|
113
|
+
|
|
114
|
+
return span === undefined ? [] : [[call, span] as const]
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The implementation split by the calls made inside it — parallel calls each count their own time, so
|
|
119
|
+
// the kinds can add up to more — and the remainder, the time no call and no wait covered.
|
|
120
|
+
function of(calls: ReadonlyArray<ToolCall>, breakdown: Breakdown): ImplementDetail {
|
|
121
|
+
const placed = placed_of(calls, breakdown.implement)
|
|
122
|
+
const parts = placed.flatMap(([call, span]) => timed_part(call, span))
|
|
123
|
+
const remainder = { name: REMAINDER, ms: remainder_ms(parts, breakdown) }
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
kinds: lane_breakdown.ranked([...parts, remainder]),
|
|
127
|
+
background: placed.filter(([call]) => call.background).length,
|
|
128
|
+
untimed: untimed_of(placed),
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// The Bash calls started inside `spans`, by the implementation's kinds — the fixes, re-ships and checks
|
|
133
|
+
// a lane child ran between two ship stages (joshuafolkken/kit#5294).
|
|
134
|
+
function bash_kinds(calls: ReadonlyArray<ToolCall>, spans: ReadonlyArray<LaneSpan>): Array<Stage> {
|
|
135
|
+
const placed = placed_of(
|
|
136
|
+
calls.filter((call) => call.tool === BASH_TOOL),
|
|
137
|
+
spans,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
return lane_breakdown.ranked(placed.flatMap(([call, span]) => timed_part(call, span)))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// The lane's own transcript directories — `<lane root slug>-<issue>` under `~/.claude/projects`.
|
|
144
|
+
function transcript_directories(issue: number): ReadonlyArray<string> {
|
|
145
|
+
const main_cwd = cost_transcript.session_cwd(process.cwd())
|
|
146
|
+
const home = cost_transcript.home_directory()
|
|
147
|
+
const suffix = `-${String(issue)}`
|
|
148
|
+
|
|
149
|
+
return cost_transcript
|
|
150
|
+
.lane_transcript_directories(main_cwd, home)
|
|
151
|
+
.filter((directory) => directory.endsWith(suffix))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// The tool calls of `issue`'s lane sessions still written to once its implementation began, up to the
|
|
155
|
+
// end of its last ship stage.
|
|
156
|
+
function read(issue: number, breakdown: Breakdown): Array<ToolCall> {
|
|
157
|
+
const [first] = breakdown.implement
|
|
158
|
+
const last = breakdown.ship.at(-1) ?? breakdown.implement.at(-1)
|
|
159
|
+
|
|
160
|
+
if (first === undefined || last === undefined) return []
|
|
161
|
+
|
|
162
|
+
const window = { since_ms: first.from_ms, until_ms: last.to_ms }
|
|
163
|
+
|
|
164
|
+
return lane_transcript_stats.read_calls(transcript_directories(issue), window)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const lane_breakdown_implement = { bash_kinds, of, read, transcript_directories }
|
|
168
|
+
|
|
169
|
+
export { lane_breakdown_implement }
|
|
170
|
+
export type { ImplementDetail }
|