tumwater 0.2.0 → 0.3.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/README.md +27 -13
- package/dist/build-info.json +2 -2
- package/dist/src/agent/agent-args.js +8 -9
- package/dist/src/agent/agent-backend.js +8 -6
- package/dist/src/agent/backend-traits.js +42 -25
- package/dist/src/agent/claude/claude-account.js +71 -204
- package/dist/src/agent/claude/claude-args.js +9 -6
- package/dist/src/agent/claude/claude-backend.js +10 -10
- package/dist/src/agent/claude/claude-env.js +1 -1
- package/dist/src/agent/claude/claude-stream.js +4 -3
- package/dist/src/agent/claude/claude-write-guard.js +49 -0
- package/dist/src/agent/claude/write-guard-hook.js +13 -0
- package/dist/src/agent/codex/codex-account.js +119 -0
- package/dist/src/agent/codex/codex-args.js +181 -0
- package/dist/src/agent/codex/codex-backend.js +279 -0
- package/dist/src/agent/codex/codex-catalog.js +97 -0
- package/dist/src/agent/codex/codex-env.js +18 -0
- package/dist/src/agent/codex/codex-hook-trust.js +246 -0
- package/dist/src/agent/codex/codex-patch-paths.js +36 -0
- package/dist/src/agent/codex/codex-rollout.js +179 -0
- package/dist/src/agent/codex/codex-stream.js +402 -0
- package/dist/src/agent/codex/codex-write-guard.js +86 -0
- package/dist/src/agent/codex/write-guard-hook.js +12 -0
- package/dist/src/agent/image-input.js +29 -24
- package/dist/src/agent/notes-shim.js +11 -12
- package/dist/src/agent/opencode/opencode-args.js +0 -1
- package/dist/src/agent/opencode/opencode-backend.js +12 -9
- package/dist/src/agent/opencode/opencode-catalog.js +55 -29
- package/dist/src/agent/opencode/opencode-config.js +19 -14
- package/dist/src/agent/opencode/opencode-env.js +0 -1
- package/dist/src/agent/opencode/opencode-session-id.js +1 -2
- package/dist/src/agent/opencode/opencode-stream.js +1 -1
- package/dist/src/agent/opencode/write-guard-plugin/index.js +48 -0
- package/dist/src/agent/role-notes-write.js +5 -6
- package/dist/src/agent/run-agent.js +465 -448
- package/dist/src/agent/run-settle.js +214 -0
- package/dist/src/agent/session-ledger.js +86 -16
- package/dist/src/agent/subscription-account.js +220 -0
- package/dist/src/agent/write-guard.js +148 -0
- package/dist/src/backlog/backlog-archive.js +246 -55
- package/dist/src/backlog/backlog-cli-view.js +280 -0
- package/dist/src/backlog/backlog-cli.js +85 -274
- package/dist/src/backlog/backlog-commit.js +4 -5
- package/dist/src/backlog/backlog-eligibility.js +175 -242
- package/dist/src/backlog/backlog-index.js +149 -0
- package/dist/src/backlog/backlog-md.js +54 -6
- package/dist/src/backlog/backlog-parts.js +254 -0
- package/dist/src/backlog/backlog-release.js +117 -0
- package/dist/src/backlog/backlog-render.js +27 -0
- package/dist/src/backlog/backlog-structure.js +99 -156
- package/dist/src/backlog/backlog-write.js +40 -127
- package/dist/src/backlog/backlog.js +21 -6
- package/dist/src/backlog/question-answer.js +21 -15
- package/dist/src/baseline/main-baseline.js +89 -20
- package/dist/src/baseline/main-culprit.js +94 -0
- package/dist/src/baseline/main-guardrails.js +209 -0
- package/dist/src/baseline/main-red.js +139 -32
- package/dist/src/baseline/main-revert.js +133 -0
- package/dist/src/baseline/main-watch.js +184 -0
- package/dist/src/brief/brief-edit.js +9 -11
- package/dist/src/brief/brief.js +31 -51
- package/dist/src/budget/budget.js +30 -20
- package/dist/src/budget/fallback-breaker.js +26 -27
- package/dist/src/build/build-check-detect.js +23 -15
- package/dist/src/build/build-check-events.js +25 -6
- package/dist/src/build/build-check-report.js +49 -9
- package/dist/src/build/build-check-scoped.js +18 -11
- package/dist/src/build/build-check.js +2 -1
- package/dist/src/build/build-info.js +2 -3
- package/dist/src/build/build-stage.js +9 -14
- package/dist/src/build/dep-install.js +1 -2
- package/dist/src/change/change-data.js +123 -31
- package/dist/src/change/change-render.js +46 -5
- package/dist/src/cli/brief-command.js +3 -4
- package/dist/src/cli/cli-args.js +118 -33
- package/dist/src/cli/cli-command-args.js +46 -18
- package/dist/src/cli/cli-editor.js +2 -1
- package/dist/src/cli/cli-flag-specs.js +150 -45
- package/dist/src/cli/cli-init.js +51 -0
- package/dist/src/cli/cli-marker-commands.js +4 -4
- package/dist/src/cli/cli-query-commands.js +308 -590
- package/dist/src/cli/cli-repo-gate.js +11 -1
- package/dist/src/cli/cli-role-command.js +420 -0
- package/dist/src/cli/cli-start-summary.js +160 -0
- package/dist/src/cli/{cli-run.js → cli-start.js} +165 -237
- package/dist/src/cli/completion.js +149 -22
- package/dist/src/cli/config-commands.js +41 -18
- package/dist/src/cli/follow-view.js +75 -0
- package/dist/src/cli/help.js +189 -73
- package/dist/src/cli/log-commands.js +148 -82
- package/dist/src/cli/question-commands.js +205 -10
- package/dist/src/cli.js +106 -43
- package/dist/src/collections.js +26 -10
- package/dist/src/concurrency/check-permit.js +20 -3
- package/dist/src/concurrency/lock.js +17 -13
- package/dist/src/concurrency/provider-lease.js +44 -8
- package/dist/src/concurrency/semaphore.js +102 -26
- package/dist/src/config/config-aliases.js +0 -1
- package/dist/src/config/config-editable-keys.js +13 -1
- package/dist/src/config/config-fallbacks.js +93 -56
- package/dist/src/config/config-field-checks.js +40 -10
- package/dist/src/config/config-keys.js +30 -8
- package/dist/src/config/config-live.js +63 -24
- package/dist/src/config/config-request.js +137 -0
- package/dist/src/config/config-schema.js +31 -24
- package/dist/src/config/config-selector-checks.js +123 -0
- package/dist/src/config/config-validation-agents.js +80 -0
- package/dist/src/config/config-validation-model.js +116 -0
- package/dist/src/config/config-validation.js +141 -199
- package/dist/src/config/config-views.js +127 -53
- package/dist/src/config/config-write-core.js +135 -0
- package/dist/src/config/config-write.js +131 -264
- package/dist/src/config/config.js +48 -38
- package/dist/src/config/model-selector.js +34 -34
- package/dist/src/doctor/doctor-backlog-bugs.js +287 -0
- package/dist/src/doctor/doctor-backlog-plans.js +263 -0
- package/dist/src/doctor/doctor-backlog.js +100 -496
- package/dist/src/doctor/doctor-check-names.js +81 -0
- package/dist/src/doctor/doctor-checks.js +52 -579
- package/dist/src/doctor/doctor-claude-checks.js +145 -0
- package/dist/src/doctor/doctor-codex-checks.js +279 -0
- package/dist/src/doctor/doctor-contention-checks.js +380 -0
- package/dist/src/doctor/doctor-holds.js +82 -66
- package/dist/src/doctor/doctor-install.js +2 -1
- package/dist/src/doctor/doctor-model-checks.js +236 -402
- package/dist/src/doctor/doctor-notify.js +3 -4
- package/dist/src/doctor/doctor-opencode-checks.js +162 -0
- package/dist/src/doctor/doctor-orphans.js +182 -63
- package/dist/src/doctor/doctor-project-checks.js +303 -0
- package/dist/src/doctor/doctor.js +121 -77
- package/dist/src/doctor/image-probe.js +21 -8
- package/dist/src/doctor/outcome.js +3 -2
- package/dist/src/doctor/probe.js +7 -11
- package/dist/src/events/event-format.js +181 -86
- package/dist/src/events/event-labels.js +12 -5
- package/dist/src/events/event-legacy.js +39 -15
- package/dist/src/events/event-read.js +39 -39
- package/dist/src/events/event-tally.js +16 -0
- package/dist/src/events/event-window.js +60 -24
- package/dist/src/events/events.js +30 -13
- package/dist/src/events/notify.js +7 -7
- package/dist/src/failure/failure-cluster.js +12 -12
- package/dist/src/failure/failure-data.js +56 -56
- package/dist/src/failure/failure-render.js +31 -23
- package/dist/src/failure/failure-state-change.js +17 -12
- package/dist/src/failure/time-spend.js +99 -35
- package/dist/src/files/files.js +111 -35
- package/dist/src/files/json-files.js +3 -3
- package/dist/src/files/json-object.js +28 -7
- package/dist/src/files/stat-cache.js +2 -2
- package/dist/src/files/tail.js +1 -1
- package/dist/src/gates/bootstrap-gates.js +4 -5
- package/dist/src/gates/budget-gates.js +177 -84
- package/dist/src/gates/disk-gate.js +1 -1
- package/dist/src/gates/gate-polls.js +108 -58
- package/dist/src/gates/maintenance-quota.js +10 -13
- package/dist/src/gates/pause-gates.js +28 -10
- package/dist/src/gates/readiness.js +7 -3
- package/dist/src/gates/role-cap-gates.js +8 -8
- package/dist/src/gates/startup-gate.js +94 -32
- package/dist/src/gates/streak-gate.js +54 -30
- package/dist/src/git/commit-message.js +77 -46
- package/dist/src/git/git-diff.js +16 -10
- package/dist/src/git/git-run.js +79 -38
- package/dist/src/git/git.js +36 -34
- package/dist/src/git/slot-salvage.js +253 -0
- package/dist/src/git/slots-state.js +6 -6
- package/dist/src/git/worktree-pool.js +132 -38
- package/dist/src/git/worktree-use.js +4 -11
- package/dist/src/git/worktree.js +94 -37
- package/dist/src/gui/gui-admin-endpoints.js +96 -0
- package/dist/src/gui/gui-args.js +79 -8
- package/dist/src/gui/gui-backlog-commands.js +42 -18
- package/dist/src/gui/gui-backlog-endpoints.js +155 -0
- package/dist/src/gui/gui-command.js +8 -13
- package/dist/src/gui/gui-config-commands.js +94 -72
- package/dist/src/gui/gui-endpoint-commands.js +4 -3
- package/dist/src/gui/gui-endpoint-common.js +4 -4
- package/dist/src/gui/gui-endpoints.js +11 -380
- package/dist/src/gui/gui-history-endpoints.js +301 -0
- package/dist/src/gui/gui-operator-commands.js +108 -13
- package/dist/src/gui/gui-prompt-commands.js +11 -14
- package/dist/src/gui/gui-report-endpoints.js +90 -0
- package/dist/src/gui/gui-server.js +11 -4
- package/dist/src/gui/gui-team-commands.js +7 -7
- package/dist/src/gui/http-body.js +1 -1
- package/dist/src/history/history-data.js +122 -234
- package/dist/src/history/history-queued.js +147 -0
- package/dist/src/history/history-render.js +42 -22
- package/dist/src/history/history.js +193 -49
- package/dist/src/inbox/inbox-attachments.js +29 -30
- package/dist/src/inbox/inbox-cancel.js +10 -11
- package/dist/src/inbox/inbox-edit.js +9 -9
- package/dist/src/inbox/inbox-submit.js +18 -18
- package/dist/src/inbox/inbox-top.js +25 -9
- package/dist/src/inbox/inbox.js +42 -43
- package/dist/src/inbox/pending-prompt.js +26 -26
- package/dist/src/inbox/prompt-commands.js +62 -49
- package/dist/src/inbox/prompt-not-before.js +2 -2
- package/dist/src/init/init-templates.js +1 -2
- package/dist/src/init/init.js +28 -23
- package/dist/src/merge/backlog-conflicts.js +215 -35
- package/dist/src/merge/merge-batch.js +14 -8
- package/dist/src/merge/merge-cancel.js +53 -0
- package/dist/src/merge/merge-check-failures.js +44 -22
- package/dist/src/merge/merge-core.js +81 -32
- package/dist/src/merge/merge-diff.js +5 -4
- package/dist/src/merge/merge-drain.js +150 -11
- package/dist/src/merge/merge-git.js +177 -38
- package/dist/src/merge/merge-pipeline.js +15 -3
- package/dist/src/merge/merge-post-review.js +90 -0
- package/dist/src/merge/merge-queue-render.js +49 -11
- package/dist/src/merge/merge-queue.js +31 -15
- package/dist/src/merge/merge-requeue.js +102 -0
- package/dist/src/merge/merge-slot.js +61 -16
- package/dist/src/merge/merge-stack.js +33 -11
- package/dist/src/merge/merge-to-main.js +86 -27
- package/dist/src/merge/merge-top.js +69 -0
- package/dist/src/merge/merge-verify.js +12 -10
- package/dist/src/notes-cli.js +30 -15
- package/dist/src/operator/operator-commands.js +192 -81
- package/dist/src/operator/operator-intent.js +69 -42
- package/dist/src/operator/operator-requests.js +35 -40
- package/dist/src/operator/retire.js +5 -6
- package/dist/src/operator/revert.js +142 -34
- package/dist/src/orchestrator/orchestrator-launch.js +60 -52
- package/dist/src/orchestrator/orchestrator-poll.js +320 -0
- package/dist/src/orchestrator/orchestrator-scheduling.js +68 -369
- package/dist/src/orchestrator/orchestrator.js +128 -369
- package/dist/src/orchestrator/retention.js +42 -8
- package/dist/src/orchestrator/scheduling-admit.js +116 -0
- package/dist/src/orchestrator/scheduling-scope.js +201 -0
- package/dist/src/orchestrator/scheduling-skip.js +185 -0
- package/dist/src/orchestrator/startup-migration-steps.js +8 -7
- package/dist/src/orchestrator/startup-migrations.js +11 -7
- package/dist/src/paths.js +116 -49
- package/dist/src/pi/command-shape.js +12 -1
- package/dist/src/pi/pi-args.js +6 -4
- package/dist/src/pi/pi-backend.js +6 -6
- package/dist/src/pi/pi-bin.js +54 -63
- package/dist/src/pi/pi-listed-models.js +53 -0
- package/dist/src/pi/pi-models.js +63 -30
- package/dist/src/pi/pi-run-result.js +1 -1
- package/dist/src/pi/pi-settings.js +1 -1
- package/dist/src/pi/pi-stream.js +6 -6
- package/dist/src/pi/pi-watchdogs.js +18 -19
- package/dist/src/pi-extension/bounded-output.js +5 -3
- package/dist/src/pi-extension/context-budget.js +2 -2
- package/dist/src/pi-extension/context-shake.js +1 -1
- package/dist/src/pi-extension/context-window.js +0 -1
- package/dist/src/pi-extension/full-output.js +3 -10
- package/dist/src/pi-extension/strip-thinking.js +0 -1
- package/dist/src/pi-extension/trim-system-prompt.js +3 -4
- package/dist/src/pi-extension/write-guard.js +37 -0
- package/dist/src/process/launch-services.js +1 -2
- package/dist/src/process/node-bin.js +16 -0
- package/dist/src/process/process-group.js +8 -18
- package/dist/src/process/process.js +41 -2
- package/dist/src/process/run-marker.js +18 -6
- package/dist/src/process/supervisor.js +22 -21
- package/dist/src/prompt/dialect.js +17 -2
- package/dist/src/prompt/gate-notes.js +203 -0
- package/dist/src/prompt/gate-prompts.js +121 -211
- package/dist/src/prompt/notes-backlog.js +181 -0
- package/dist/src/prompt/principles.js +1 -2
- package/dist/src/prompt/prompt-followup.js +19 -14
- package/dist/src/prompt/prompt.js +129 -204
- package/dist/src/redeploy/redeploy-policy.js +24 -19
- package/dist/src/redeploy/redeploy-probes.js +1 -1
- package/dist/src/redeploy/redeploy.js +2 -3
- package/dist/src/redeploy/redeployer.js +20 -20
- package/dist/src/redeploy/self-reload.js +2 -1
- package/dist/src/report/report-data.js +161 -77
- package/dist/src/report/report-fold.js +129 -52
- package/dist/src/report/report-main-red.js +55 -0
- package/dist/src/report/report-render.js +133 -64
- package/dist/src/report/report-types.js +1 -0
- package/dist/src/report/report.js +26 -9
- package/dist/src/request-timeouts.js +2 -2
- package/dist/src/review/known-flakes.js +100 -1
- package/dist/src/review/post-merge-review.js +106 -0
- package/dist/src/review/protected-edits.js +4 -5
- package/dist/src/review/review-followup.js +8 -8
- package/dist/src/review/review-precheck.js +66 -23
- package/dist/src/review/review-run.js +395 -0
- package/dist/src/review/review-verdict.js +2 -2
- package/dist/src/review/review.js +155 -360
- package/dist/src/review/secret-leaks.js +36 -16
- package/dist/src/review/suite-rerun.js +0 -1
- package/dist/src/roles/legacy-role-migration.js +80 -7
- package/dist/src/roles/role-catalog.js +69 -12
- package/dist/src/roles/role-guidance.js +55 -20
- package/dist/src/roles/role-labels.js +1 -2
- package/dist/src/roles/role-render.js +67 -50
- package/dist/src/roles/role-view.js +59 -47
- package/dist/src/roles/roles.js +31 -31
- package/dist/src/roles/runner-ids.js +97 -0
- package/dist/src/run/acceptance-greps.js +119 -0
- package/dist/src/run/feedback-filings.js +51 -0
- package/dist/src/{tick → run}/qa-coverage.js +9 -27
- package/dist/src/{tick/tick-apply.js → run/run-apply.js} +95 -94
- package/dist/src/run/run-detail-data.js +179 -0
- package/dist/src/run/run-detail-render.js +98 -0
- package/dist/src/run/run-detail.js +168 -0
- package/dist/src/{tick/tick-finalize.js → run/run-finalize.js} +72 -60
- package/dist/src/{tick/tick-outcome.js → run/run-outcome.js} +6 -7
- package/dist/src/{tick/tick-prompt.js → run/run-prompt.js} +108 -73
- package/dist/src/{tick/tick-resume.js → run/run-resume.js} +55 -26
- package/dist/src/{tick/tick-stage.js → run/run-stage.js} +108 -50
- package/dist/src/{tick/tick-timing.js → run/run-timing.js} +43 -41
- package/dist/src/{tick/tick-usage.js → run/run-usage.js} +45 -37
- package/dist/src/{tick/tick-verdict.js → run/run-verdict.js} +91 -56
- package/dist/src/run/selfcheck-digest.js +40 -0
- package/dist/src/run/stage-backlog-checks.js +249 -0
- package/dist/src/run/stage-check.js +172 -0
- package/dist/src/run/stage-path-checks.js +730 -0
- package/dist/src/{loop → runner}/leftover.js +80 -25
- package/dist/src/{loop → runner}/model-fallback.js +12 -12
- package/dist/src/runner/revision.js +202 -0
- package/dist/src/{loop/loop-fallback.js → runner/runner-fallback.js} +8 -8
- package/dist/src/runner/runner-outcome.js +107 -0
- package/dist/src/{loop/loop-pi.js → runner/runner-pi.js} +140 -131
- package/dist/src/{loop/loop-recovery.js → runner/runner-recovery.js} +21 -15
- package/dist/src/{loop/loop-tick.js → runner/runner-run.js} +218 -240
- package/dist/src/{loop/loop-state.js → runner/runner-state-load.js} +61 -114
- package/dist/src/runner/runner-state.js +102 -0
- package/dist/src/{loop/loop.js → runner/runner.js} +123 -120
- package/dist/src/scheduling/backoff.js +38 -38
- package/dist/src/scheduling/claims.js +35 -22
- package/dist/src/scheduling/once-round.js +22 -22
- package/dist/src/scheduling/quiet-hours.js +5 -6
- package/dist/src/scheduling/scheduling.js +74 -64
- package/dist/src/scheduling/work-merged-cache.js +2 -2
- package/dist/src/status/status-budget.js +55 -47
- package/dist/src/status/status-data.js +43 -16
- package/dist/src/status/status-inbox.js +2 -2
- package/dist/src/status/status-install.js +0 -1
- package/dist/src/status/status-polls.js +28 -28
- package/dist/src/status/status-roles.js +39 -13
- package/dist/src/team/error-storm.js +8 -8
- package/dist/src/team/failure-spread.js +2 -2
- package/dist/src/team/orchestrator-info.js +15 -9
- package/dist/src/team/reclaim.js +5 -6
- package/dist/src/team/team-hold.js +7 -7
- package/dist/src/team/team-polls.js +91 -50
- package/dist/src/team/team-state.js +8 -2
- package/dist/src/text/datetime.js +63 -17
- package/dist/src/text/format.js +48 -11
- package/dist/src/text/markdown.js +8 -5
- package/dist/src/text/phrases.js +57 -23
- package/dist/src/text/suggest.js +1 -1
- package/dist/src/text/text.js +67 -13
- package/dist/src/ui/badges.js +65 -37
- package/dist/src/ui/gui/gui-client-backlog.js +292 -0
- package/dist/src/ui/gui/gui-client-boot.js +32 -26
- package/dist/src/ui/gui/gui-client-composer.js +8 -9
- package/dist/src/ui/gui/gui-client-drawer-config.js +212 -0
- package/dist/src/ui/gui/gui-client-drawer.js +126 -285
- package/dist/src/ui/gui/gui-client-feed.js +271 -0
- package/dist/src/ui/gui/gui-client-history.js +434 -67
- package/dist/src/ui/gui/gui-client-labels.js +1 -2
- package/dist/src/ui/gui/gui-client-markdown.js +1 -2
- package/dist/src/ui/gui/gui-client-model.js +27 -36
- package/dist/src/ui/gui/gui-client-operator.js +55 -51
- package/dist/src/ui/gui/gui-client-pending.js +227 -23
- package/dist/src/ui/gui/gui-client-report-chart.js +464 -0
- package/dist/src/ui/gui/gui-client-report.js +87 -427
- package/dist/src/ui/gui/{gui-client-loops.js → gui-client-roles.js} +43 -44
- package/dist/src/ui/gui/gui-client-settings.js +56 -4
- package/dist/src/ui/gui/gui-client-team.js +25 -465
- package/dist/src/ui/gui/gui-client.js +27 -25
- package/dist/src/ui/gui/gui-icons.js +0 -2
- package/dist/src/ui/gui/gui-page.js +9 -7
- package/dist/src/ui/gui/gui-styles.js +34 -34
- package/dist/src/ui/progress-data.js +9 -11
- package/dist/src/ui/{tick-progress-model.js → run-progress-model.js} +31 -31
- package/dist/src/ui/status-model.js +133 -125
- package/dist/src/ui/status-payload.js +136 -49
- package/dist/src/ui/status-render.js +101 -82
- package/dist/src/ui/team-alerts.js +248 -57
- package/dist/src/ui/tone.js +5 -6
- package/dist/src/ui/transcript-run.js +58 -0
- package/dist/src/ui/transcript-tail.js +28 -20
- package/dist/src/ui/transcript.js +63 -23
- package/dist/src/ui/tui/tui-app.js +0 -1
- package/dist/src/ui/tui/tui-backlog.js +51 -14
- package/dist/src/ui/tui/tui-editor-answer.js +27 -31
- package/dist/src/ui/tui/tui-editor-attach.js +3 -5
- package/dist/src/ui/tui/tui-editor-backends.js +132 -0
- package/dist/src/ui/tui/tui-editor-brief.js +10 -12
- package/dist/src/ui/tui/tui-editor-budget.js +35 -31
- package/dist/src/ui/tui/tui-editor-claude-reserve.js +24 -0
- package/dist/src/ui/tui/tui-editor-concurrency.js +24 -0
- package/dist/src/ui/tui/tui-editor-config.js +86 -0
- package/dist/src/ui/tui/tui-editor-entry.js +36 -47
- package/dist/src/ui/tui/tui-editor-fallback.js +31 -0
- package/dist/src/ui/tui/tui-editor-instances.js +37 -0
- package/dist/src/ui/tui/tui-editor-instructions.js +136 -0
- package/dist/src/ui/tui/tui-editor-interval.js +11 -9
- package/dist/src/ui/tui/tui-editor-model.js +29 -0
- package/dist/src/ui/tui/tui-editor-notes.js +3 -5
- package/dist/src/ui/tui/tui-editor-notify.js +25 -0
- package/dist/src/ui/tui/tui-editor-pause.js +48 -59
- package/dist/src/ui/tui/tui-editor-prompt.js +11 -16
- package/dist/src/ui/tui/tui-editor-provider-caps.js +27 -0
- package/dist/src/ui/tui/tui-editor-queued.js +5 -9
- package/dist/src/ui/tui/tui-editor-quiet.js +99 -35
- package/dist/src/ui/tui/tui-editor-retire.js +4 -6
- package/dist/src/ui/tui/tui-editor-role-key.js +76 -0
- package/dist/src/ui/tui/tui-editor-role-model.js +28 -0
- package/dist/src/ui/tui/tui-editor-search.js +45 -33
- package/dist/src/ui/tui/tui-editor-session.js +60 -34
- package/dist/src/ui/tui/tui-editor-slots.js +23 -0
- package/dist/src/ui/tui/tui-editors.js +35 -2
- package/dist/src/ui/tui/tui-frame.js +56 -11
- package/dist/src/ui/tui/tui-history.js +8 -9
- package/dist/src/ui/tui/tui-input.js +13 -11
- package/dist/src/ui/tui/tui-keymap.js +0 -1
- package/dist/src/ui/tui/tui-keys.js +24 -9
- package/dist/src/ui/tui/tui-pane-activity.js +14 -11
- package/dist/src/ui/tui/tui-pane-backlog.js +171 -126
- package/dist/src/ui/tui/tui-pane-brief.js +0 -1
- package/dist/src/ui/tui/tui-pane-ctx.js +2 -2
- package/dist/src/ui/tui/tui-pane-health.js +58 -8
- package/dist/src/ui/tui/tui-pane-history.js +402 -82
- package/dist/src/ui/tui/tui-pane-pending.js +308 -13
- package/dist/src/ui/tui/tui-pane-queued.js +71 -55
- package/dist/src/ui/tui/tui-pane-report.js +46 -14
- package/dist/src/ui/tui/tui-pane-session.js +25 -6
- package/dist/src/ui/tui/tui-pane-transcript.js +111 -37
- package/dist/src/ui/tui/tui-pane.js +80 -23
- package/dist/src/ui/tui/tui-panes.js +100 -30
- package/dist/src/ui/tui/tui.js +14 -14
- package/dist/src/verdict/fix-claim.js +82 -32
- package/dist/src/verdict/no-change.js +4 -4
- package/dist/src/verdict/refusal.js +40 -16
- package/dist/src/verdict/reply-contract.js +42 -31
- package/dist/src/version.js +0 -1
- package/package.json +2 -1
- package/dist/src/loop/revision.js +0 -70
- package/dist/src/roles/loop-ids.js +0 -77
- package/dist/src/tick/stage-check.js +0 -419
- package/dist/src/tick/telemetry-digest.js +0 -25
- package/dist/src/tick/tick-detail-data.js +0 -108
- package/dist/src/tick/tick-detail.js +0 -163
- package/dist/src/ui/gui/gui-client-sound.js +0 -53
|
@@ -1,32 +1,33 @@
|
|
|
1
|
-
// vocabulary: plain
|
|
2
1
|
/** Collection half of the usage report: read the harness's event log (through the shared
|
|
3
2
|
* event-folding layer in src/report/report-fold.ts) and the backlog history over a window of
|
|
4
3
|
* local calendar days and distill it into a `ReportData` / `SinceReport` — per-day
|
|
5
|
-
*
|
|
4
|
+
* run/token/commit/cost counts plus features-done and bugs-fixed tallies from PLANS.md and
|
|
6
5
|
* BUGS.md. The Markdown rendering of this data lives in src/report/report-render.ts, a pure
|
|
7
6
|
* function of it; the split mirrors the failure report's (src/failure/failure-data.ts /
|
|
8
7
|
* src/failure/failure-render.ts) and keeps "what happened" (window math, aggregation, bounds)
|
|
9
8
|
* apart from "how it prints" (bars, cell wording), which change for different reasons — and
|
|
10
9
|
* keeps core data collection out of the presentation layer, so a core consumer (as
|
|
11
10
|
* /api/report already is) never forces a core→ui import. This file holds the two window
|
|
12
|
-
* collectors
|
|
13
|
-
* per-window cache
|
|
14
|
-
|
|
15
|
-
import {
|
|
11
|
+
* collectors; the report shapes they produce live in src/report/report-types.ts, and the
|
|
12
|
+
* event-log folding and its memoized per-window cache in src/report/report-fold.ts (its own
|
|
13
|
+
* test, report-fold-cache). */
|
|
14
|
+
import { assertReportSinceMs, eventWindowCovers, readWindowEvents, sinceWindowTiming } from "../events/event-window.js";
|
|
15
|
+
import { DONE_DATE_RE, FIXED_DATE_RE, completionDate, finishedFiles, fixedBugEntries, sectionCompletionDates, sectionCompletionLags, sectionFilingDates, } from "../backlog/backlog.js";
|
|
16
16
|
import { validationGapTag } from "../backlog/backlog-md.js";
|
|
17
17
|
import { dayAt, dayKey, dayWindow, formatDate } from "../text/datetime.js";
|
|
18
18
|
import { addTo, lowerMedian } from "../collections.js";
|
|
19
|
-
import { baseRoleOf } from "../roles/loop-ids.js";
|
|
20
19
|
import { commitTier } from "../roles/roles.js";
|
|
21
|
-
import { foldUsageEvent, foldWindowEvents, narrowToRole, roleSum, scopedByRole, zeroCommitCounts, zeroMergeCounts, } from "./report-fold.js";
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
import { foldUsageEvent, foldWindowEvents, narrowToRole, roleSum, scopeBases, scopedByRole, zeroCommitCounts, zeroMergeCounts, } from "./report-fold.js";
|
|
21
|
+
import { mainRedMinutesByDay } from "./report-main-red.js";
|
|
22
|
+
/** Aggregate team usage over the trailing `sinceMs` window ending now (or `untilMs` ago, which
|
|
23
|
+
* drops events at or after that end; `coversFullWindow` still judges the far edge
|
|
24
|
+
* only), from the event log only (run_end/merged — see SinceReport for why the backlog files
|
|
25
|
+
* are not read). Kept a
|
|
24
26
|
* separate function rather than a `collectReport` variant flag: the day collector's
|
|
25
27
|
* zero-filled series and backlog-file reads have no place in a window totals view. */
|
|
26
|
-
export function collectReportSince(root, sinceMs, role) {
|
|
28
|
+
export function collectReportSince(root, sinceMs, role, untilMs) {
|
|
27
29
|
assertReportSinceMs(sinceMs);
|
|
28
|
-
const now =
|
|
29
|
-
const cutoff = now - sinceMs;
|
|
30
|
+
const { now, cutoff, end, slice } = sinceWindowTiming(sinceMs, untilMs);
|
|
30
31
|
// The window key is the cutoff's local calendar day, from the shared dayKey helper
|
|
31
32
|
// eventDayKey buckets events with, so the read's day keys cannot disagree with the ts
|
|
32
33
|
// filter below; the day-keyed read may include earlier hours of that day, which the ts
|
|
@@ -40,11 +41,16 @@ export function collectReportSince(root, sinceMs, role) {
|
|
|
40
41
|
rejectionsByRole: {},
|
|
41
42
|
revisionsByRole: {},
|
|
42
43
|
refusalsByRole: {},
|
|
44
|
+
revertsByRole: {},
|
|
43
45
|
checkDurationsMs: [],
|
|
44
46
|
checkFailures: 0,
|
|
45
47
|
mergeWaitsMs: [],
|
|
48
|
+
mergeDurationsMs: [],
|
|
49
|
+
runDurationsMs: [],
|
|
46
50
|
providerWaitsMs: [],
|
|
47
51
|
slotWaitsMs: [],
|
|
52
|
+
checkWaitsMs: [],
|
|
53
|
+
reviewDurationsMs: [],
|
|
48
54
|
failedRunsByRole: {},
|
|
49
55
|
fallbacksByRole: {},
|
|
50
56
|
imageReroutesByRole: {},
|
|
@@ -61,11 +67,12 @@ export function collectReportSince(root, sinceMs, role) {
|
|
|
61
67
|
mergeFailedByReason: {},
|
|
62
68
|
costByProvider: {},
|
|
63
69
|
notionalByProvider: {},
|
|
70
|
+
notionalByBackend: {},
|
|
64
71
|
runsByModel: {},
|
|
65
72
|
deferredByReason: {},
|
|
66
73
|
};
|
|
67
74
|
for (const ev of raw.events) {
|
|
68
|
-
if (typeof ev.ts !== "number" || ev.ts < cutoff || ev.ts > now)
|
|
75
|
+
if (typeof ev.ts !== "number" || ev.ts < cutoff || ev.ts > now || (untilMs !== undefined && ev.ts >= end))
|
|
69
76
|
continue;
|
|
70
77
|
foldUsageEvent(acc, ev);
|
|
71
78
|
}
|
|
@@ -74,18 +81,19 @@ export function collectReportSince(root, sinceMs, role) {
|
|
|
74
81
|
// history that never existed. When neither proof holds, the oldest retained event lies inside
|
|
75
82
|
// the window and the render notes the possible truncation.
|
|
76
83
|
const coversFullWindow = eventWindowCovers(raw, cutoff);
|
|
77
|
-
// Role scope: every total derives from the fold's per-role maps for the named base
|
|
84
|
+
// Role scope: every total derives from the fold's per-role maps for the named base roles alone
|
|
78
85
|
// — merge usage (the merge slot's, not the role's) and the team-only fields stay out, so
|
|
79
86
|
// a scoped --since report sums exactly the same events the scoped day report would. The scope
|
|
80
|
-
// is the base
|
|
81
|
-
const
|
|
82
|
-
const scopedTotals =
|
|
87
|
+
// is the base roles, so instances (`feature-2`) aggregate into their group as the cap does.
|
|
88
|
+
const bases = scopeBases(role);
|
|
89
|
+
const scopedTotals = bases === undefined
|
|
83
90
|
? {
|
|
84
91
|
tokensOut: acc.tokensOut + (acc.mergeTokens ?? 0),
|
|
85
92
|
runs: acc.runs ?? 0,
|
|
86
93
|
commits: acc.commits,
|
|
87
94
|
costUsd: acc.costUsd + (acc.mergeCostUsd ?? 0),
|
|
88
95
|
...(acc.notionalCostUsd > 0 ? { notionalCostUsd: acc.notionalCostUsd } : {}),
|
|
96
|
+
...(Object.keys(acc.notionalByBackend).length > 0 ? { notionalByBackend: acc.notionalByBackend } : {}),
|
|
89
97
|
mergeRuns: acc.mergeRuns ?? 0,
|
|
90
98
|
mergeTokens: acc.mergeTokens ?? 0,
|
|
91
99
|
mergeCostUsd: acc.mergeCostUsd ?? 0,
|
|
@@ -94,12 +102,12 @@ export function collectReportSince(root, sinceMs, role) {
|
|
|
94
102
|
: (() => {
|
|
95
103
|
// The role's own notional spend, from its run_end events; the merge slot's
|
|
96
104
|
// notional is team-wide and stays out like its cost.
|
|
97
|
-
const notional = roleSum(acc.notionalByRole,
|
|
105
|
+
const notional = roleSum(acc.notionalByRole, bases);
|
|
98
106
|
return {
|
|
99
|
-
tokensOut: roleSum(acc.tokensByRole,
|
|
100
|
-
runs: roleSum(acc.runsByRole,
|
|
101
|
-
commits: roleSum(acc.commitsByRole,
|
|
102
|
-
costUsd: roleSum(acc.costByRole,
|
|
107
|
+
tokensOut: roleSum(acc.tokensByRole, bases),
|
|
108
|
+
runs: roleSum(acc.runsByRole, bases),
|
|
109
|
+
commits: roleSum(acc.commitsByRole, bases),
|
|
110
|
+
costUsd: roleSum(acc.costByRole, bases),
|
|
103
111
|
...(notional > 0 ? { notionalCostUsd: notional } : {}),
|
|
104
112
|
...zeroMergeCounts(),
|
|
105
113
|
};
|
|
@@ -108,49 +116,67 @@ export function collectReportSince(root, sinceMs, role) {
|
|
|
108
116
|
// notional spend, scoped to base when a role is given — the same conditional the day
|
|
109
117
|
// collector applies to ReportDay.notionalByRole (line ~573), so a role-scoped window
|
|
110
118
|
// whose role spent no notional carries no notionalByRole instead of an empty map.
|
|
111
|
-
const notionalByRole = scopedByRole(acc.notionalByRole,
|
|
119
|
+
const notionalByRole = scopedByRole(acc.notionalByRole, bases);
|
|
112
120
|
// Deferred runs are bucketed by a reason code (not a role), so a role-scoped window
|
|
113
121
|
// carries no entries — the same team-only rule runsByModel follows. Only set when the
|
|
114
122
|
// window actually deferred (zero means absent), so a deferral-free --since JSON omits it.
|
|
115
|
-
const deferred = scopedByRole(acc.deferredByReason,
|
|
123
|
+
const deferred = scopedByRole(acc.deferredByReason, bases);
|
|
116
124
|
return {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
...(base === undefined ? {} : { role: base }),
|
|
125
|
+
...slice,
|
|
126
|
+
...(bases === undefined ? {} : { role: bases.join(",") }),
|
|
120
127
|
totals: scopedTotals,
|
|
121
|
-
runsByRole: scopedByRole(acc.runsByRole,
|
|
122
|
-
costByRole: scopedByRole(acc.costByRole,
|
|
123
|
-
rejectionsByRole: scopedByRole(acc.rejectionsByRole,
|
|
124
|
-
revisionsByRole: scopedByRole(acc.revisionsByRole,
|
|
125
|
-
refusalsByRole: scopedByRole(acc.refusalsByRole,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
runsByRole: scopedByRole(acc.runsByRole, bases),
|
|
129
|
+
costByRole: scopedByRole(acc.costByRole, bases),
|
|
130
|
+
rejectionsByRole: scopedByRole(acc.rejectionsByRole, bases),
|
|
131
|
+
revisionsByRole: scopedByRole(acc.revisionsByRole, bases),
|
|
132
|
+
refusalsByRole: scopedByRole(acc.refusalsByRole, bases),
|
|
133
|
+
revertsByRole: scopedByRole(acc.revertsByRole, bases),
|
|
134
|
+
failedRunsByRole: scopedByRole(acc.failedRunsByRole, bases),
|
|
135
|
+
fallbacksByRole: scopedByRole(acc.fallbacksByRole, bases),
|
|
136
|
+
imageReroutesByRole: scopedByRole(acc.imageReroutesByRole, bases),
|
|
137
|
+
tokensByRole: scopedByRole(acc.tokensByRole, bases),
|
|
138
|
+
commitsByRole: scopedByRole(acc.commitsByRole, bases),
|
|
139
|
+
mergedByRole: scopedByRole(acc.mergedByRole, bases),
|
|
140
|
+
mergeFailedByRole: scopedByRole(acc.mergeFailedByRole, bases),
|
|
133
141
|
// A result code is not a role, so a role-scoped window carries an empty map (a code
|
|
134
142
|
// never baseRoleOf to the role) — the render gates the reason line to the team report.
|
|
135
|
-
mergeFailedByReason: scopedByRole(acc.mergeFailedByReason,
|
|
143
|
+
mergeFailedByReason: scopedByRole(acc.mergeFailedByReason, bases),
|
|
136
144
|
...(Object.keys(notionalByRole).length > 0 ? { notionalByRole } : {}),
|
|
137
145
|
// Provider spend is a team attribution (a provider is not a role), so a role-scoped
|
|
138
146
|
// window carries empty maps — providers never baseRoleOf to the role — and the render
|
|
139
147
|
// gates the provider lines to the team report anyway. Always present, empty when none.
|
|
140
|
-
costByProvider: scopedByRole(acc.costByProvider,
|
|
141
|
-
notionalByProvider: scopedByRole(acc.notionalByProvider,
|
|
148
|
+
costByProvider: scopedByRole(acc.costByProvider, bases),
|
|
149
|
+
notionalByProvider: scopedByRole(acc.notionalByProvider, bases),
|
|
150
|
+
// Backend spend is a team attribution (a backend is not a role), so a role-scoped window
|
|
151
|
+
// omits it — the same absent-when-empty rule the day collector applies.
|
|
152
|
+
...(Object.keys(scopedByRole(acc.notionalByBackend, bases)).length > 0
|
|
153
|
+
? { notionalByBackend: scopedByRole(acc.notionalByBackend, bases) }
|
|
154
|
+
: {}),
|
|
142
155
|
// Model attribution is team-only (a model is not a role, so no model folds to the
|
|
143
156
|
// scoped role), the same full-map-for-team / empty-for-scoped rule costByProvider
|
|
144
157
|
// follows. Always present so the render can gate on the window's own events.
|
|
145
|
-
runsByModel: scopedByRole(acc.runsByModel,
|
|
158
|
+
runsByModel: scopedByRole(acc.runsByModel, bases),
|
|
146
159
|
...(Object.keys(deferred).length > 0 ? { deferredByReason: deferred } : {}),
|
|
160
|
+
// Main's red time is main's own (G1's rule), not any role's, so a role-scoped window
|
|
161
|
+
// carries 0 — the type's always-present default for the team-only field.
|
|
162
|
+
mainRedMs: bases === undefined
|
|
163
|
+
? [...mainRedMinutesByDay(raw.events, cutoff, end).values()].reduce((a, b) => a + b, 0)
|
|
164
|
+
: 0,
|
|
147
165
|
coversFullWindow,
|
|
148
166
|
};
|
|
149
167
|
}
|
|
168
|
+
/** Set one per-day median cell only when the day actually has samples (`ms` non-empty), so a
|
|
169
|
+
* medians-free day keeps its exact pre-feature shape (the field stays absent). The single home
|
|
170
|
+
* of that guard — the day collector's eight `…MedianMs` cells all followed it inline before. */
|
|
171
|
+
function setLowerMedian(day, key, ms) {
|
|
172
|
+
if (ms.length > 0)
|
|
173
|
+
day[key] = lowerMedian(ms);
|
|
174
|
+
}
|
|
150
175
|
/** Aggregate team usage over exactly `days` local calendar days ending today, from the event
|
|
151
176
|
* log (run_end/merged) and the backlog history (`## Done` in PLANS.md and PLANS-DONE.md,
|
|
152
177
|
* `## Fixed` in BUGS.md and BUGS-FIXED.md). */
|
|
153
178
|
export function collectReport(root, days, role) {
|
|
179
|
+
const bases = scopeBases(role);
|
|
154
180
|
const now = new Date();
|
|
155
181
|
// One captured instant for the whole window, so every day key derives from the same day.
|
|
156
182
|
const { from, to } = dayWindow(days, now);
|
|
@@ -175,7 +201,7 @@ export function collectReport(root, days, role) {
|
|
|
175
201
|
const day = byDate.get(dayKey);
|
|
176
202
|
if (!day)
|
|
177
203
|
continue; // Out-of-window day key (e.g. future-dated) — no series slot to fill.
|
|
178
|
-
if (
|
|
204
|
+
if (bases === undefined) {
|
|
179
205
|
day.tokensOut = fold.tokensOut;
|
|
180
206
|
day.runsByRole = fold.runsByRole;
|
|
181
207
|
day.tokensByRole = fold.tokensByRole;
|
|
@@ -187,19 +213,23 @@ export function collectReport(root, days, role) {
|
|
|
187
213
|
day.revisionsByRole = fold.revisionsByRole;
|
|
188
214
|
if (Object.keys(fold.refusalsByRole).length > 0)
|
|
189
215
|
day.refusalsByRole = fold.refusalsByRole;
|
|
216
|
+
if (Object.keys(fold.revertsByRole).length > 0)
|
|
217
|
+
day.revertsByRole = fold.revertsByRole;
|
|
190
218
|
// Checks belong to the merge slot, so only the team series carries the median.
|
|
191
|
-
|
|
192
|
-
day.checkMedianMs = lowerMedian(fold.checkDurationsMs);
|
|
193
|
-
}
|
|
219
|
+
setLowerMedian(day, "checkMedianMs", fold.checkDurationsMs);
|
|
194
220
|
if (fold.checkFailures > 0)
|
|
195
221
|
day.checkFailures = fold.checkFailures;
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
222
|
+
setLowerMedian(day, "mergeWaitMedianMs", fold.mergeWaitsMs);
|
|
223
|
+
setLowerMedian(day, "mergeSlotMedianMs", fold.mergeDurationsMs);
|
|
224
|
+
setLowerMedian(day, "runMedianMs", fold.runDurationsMs);
|
|
225
|
+
setLowerMedian(day, "providerWaitMedianMs", fold.providerWaitsMs);
|
|
200
226
|
// A workspace wait is the pool's, not a role's, so only the team series carries it.
|
|
201
|
-
|
|
202
|
-
|
|
227
|
+
setLowerMedian(day, "slotWaitMedianMs", fold.slotWaitsMs);
|
|
228
|
+
// A check permit is the team's, not a role's, so only the team series carries it.
|
|
229
|
+
setLowerMedian(day, "checkWaitMedianMs", fold.checkWaitsMs);
|
|
230
|
+
// A review belongs to the merge slot/reviewer, not the author role, so only the team
|
|
231
|
+
// series carries the median, mirroring checkMedianMs.
|
|
232
|
+
setLowerMedian(day, "reviewMedianMs", fold.reviewDurationsMs);
|
|
203
233
|
// Only set when nonzero, so a failure-free day keeps its exact pre-feature shape.
|
|
204
234
|
if (Object.keys(fold.failedRunsByRole).length > 0)
|
|
205
235
|
day.failedRunsByRole = fold.failedRunsByRole;
|
|
@@ -223,6 +253,11 @@ export function collectReport(root, days, role) {
|
|
|
223
253
|
day.costByProvider = fold.costByProvider;
|
|
224
254
|
if (Object.keys(fold.notionalByProvider).length > 0)
|
|
225
255
|
day.notionalByProvider = fold.notionalByProvider;
|
|
256
|
+
// Backends are a team attribution (a backend is not a role), so only the team series
|
|
257
|
+
// carries the map; only set when a backend actually spent (zero means absent), so a
|
|
258
|
+
// backend-free day keeps its exact pre-feature shape.
|
|
259
|
+
if (Object.keys(fold.notionalByBackend).length > 0)
|
|
260
|
+
day.notionalByBackend = fold.notionalByBackend;
|
|
226
261
|
// Models are a team attribution (a model is not a role), so only the team series
|
|
227
262
|
// carries the map; only set when a modelled start happened (zero means absent), so a
|
|
228
263
|
// model-less day keeps its exact pre-feature shape.
|
|
@@ -254,53 +289,55 @@ export function collectReport(root, days, role) {
|
|
|
254
289
|
}
|
|
255
290
|
else {
|
|
256
291
|
// Role scope: derive this day from the fold's per-role maps, so the series carries only
|
|
257
|
-
// the named role's
|
|
292
|
+
// the named role's runs/tokens/cost and (base-role-keyed) commits. The scope is the
|
|
258
293
|
// base role, so an instance id's usage and its siblings' commits fold into one group and
|
|
259
294
|
// the numbers match the per-role cap, which is base-role keyed too. The merge fields
|
|
260
295
|
// stay unset — merge runs are the merge slot's, not this role's — and the work /
|
|
261
296
|
// maintenance split follows the base role's own tier rather than the day's whole split.
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
day.
|
|
266
|
-
day.
|
|
267
|
-
|
|
268
|
-
day.costByRole = narrowToRole(fold.costByRole, base);
|
|
269
|
-
const rejs = narrowToRole(fold.rejectionsByRole, base);
|
|
297
|
+
const commits = roleSum(fold.commitsByRole, bases);
|
|
298
|
+
day.tokensOut = roleSum(fold.tokensByRole, bases);
|
|
299
|
+
day.runsByRole = narrowToRole(fold.runsByRole, bases);
|
|
300
|
+
day.tokensByRole = narrowToRole(fold.tokensByRole, bases);
|
|
301
|
+
day.costByRole = narrowToRole(fold.costByRole, bases);
|
|
302
|
+
const rejs = narrowToRole(fold.rejectionsByRole, bases);
|
|
270
303
|
if (Object.keys(rejs).length > 0)
|
|
271
304
|
day.rejectionsByRole = rejs;
|
|
272
|
-
const revs = narrowToRole(fold.revisionsByRole,
|
|
305
|
+
const revs = narrowToRole(fold.revisionsByRole, bases);
|
|
273
306
|
if (Object.keys(revs).length > 0)
|
|
274
307
|
day.revisionsByRole = revs;
|
|
275
|
-
const refusals = narrowToRole(fold.refusalsByRole,
|
|
308
|
+
const refusals = narrowToRole(fold.refusalsByRole, bases);
|
|
276
309
|
if (Object.keys(refusals).length > 0)
|
|
277
310
|
day.refusalsByRole = refusals;
|
|
278
|
-
const
|
|
311
|
+
const reverts = narrowToRole(fold.revertsByRole, bases);
|
|
312
|
+
if (Object.keys(reverts).length > 0)
|
|
313
|
+
day.revertsByRole = reverts;
|
|
314
|
+
const fails = narrowToRole(fold.failedRunsByRole, bases);
|
|
279
315
|
if (Object.keys(fails).length > 0)
|
|
280
316
|
day.failedRunsByRole = fails;
|
|
281
|
-
const falls = narrowToRole(fold.fallbacksByRole,
|
|
317
|
+
const falls = narrowToRole(fold.fallbacksByRole, bases);
|
|
282
318
|
if (Object.keys(falls).length > 0)
|
|
283
319
|
day.fallbacksByRole = falls;
|
|
284
|
-
const reroutes = narrowToRole(fold.imageReroutesByRole,
|
|
320
|
+
const reroutes = narrowToRole(fold.imageReroutesByRole, bases);
|
|
285
321
|
if (Object.keys(reroutes).length > 0)
|
|
286
322
|
day.imageReroutesByRole = reroutes;
|
|
287
323
|
day.commits = commits;
|
|
288
|
-
day.commitsByRole = narrowToRole(fold.commitsByRole,
|
|
289
|
-
|
|
290
|
-
day.
|
|
291
|
-
day.
|
|
292
|
-
|
|
324
|
+
day.commitsByRole = narrowToRole(fold.commitsByRole, bases);
|
|
325
|
+
const tierCommits = (tier) => bases.filter((b) => commitTier(b) === tier).reduce((n, b) => n + roleSum(fold.commitsByRole, b), 0);
|
|
326
|
+
day.workCommits = tierCommits("work");
|
|
327
|
+
day.maintenanceCommits = tierCommits("maintenance");
|
|
328
|
+
day.costUsd = roleSum(fold.costByRole, bases);
|
|
329
|
+
const notional = roleSum(fold.notionalByRole, bases);
|
|
293
330
|
if (notional > 0) {
|
|
294
331
|
day.notionalCostUsd = notional;
|
|
295
|
-
day.notionalByRole = narrowToRole(fold.notionalByRole,
|
|
332
|
+
day.notionalByRole = narrowToRole(fold.notionalByRole, bases);
|
|
296
333
|
}
|
|
297
334
|
// Merge runs belong to the merge slot, not this role, so the role-scoped series
|
|
298
335
|
// keeps them unset (matching the merge-share fields) — the render omits the merge
|
|
299
336
|
// line for a scoped report, so these are carried only for shape consistency.
|
|
300
|
-
const mergeDone = narrowToRole(fold.mergedByRole,
|
|
337
|
+
const mergeDone = narrowToRole(fold.mergedByRole, bases);
|
|
301
338
|
if (Object.keys(mergeDone).length > 0)
|
|
302
339
|
day.mergedByRole = mergeDone;
|
|
303
|
-
const mergeDoneFailed = narrowToRole(fold.mergeFailedByRole,
|
|
340
|
+
const mergeDoneFailed = narrowToRole(fold.mergeFailedByRole, bases);
|
|
304
341
|
if (Object.keys(mergeDoneFailed).length > 0)
|
|
305
342
|
day.mergeFailedByRole = mergeDoneFailed;
|
|
306
343
|
}
|
|
@@ -312,6 +349,19 @@ export function collectReport(root, days, role) {
|
|
|
312
349
|
d.tokensOut += d.mergeTokens ?? 0;
|
|
313
350
|
d.costUsd += d.mergeCostUsd ?? 0;
|
|
314
351
|
}
|
|
352
|
+
// Main's red wall-clock per day, from G1's rule (main_red_hold / failed ran main_check open a
|
|
353
|
+
// spell, a passing ran main_check closes it, an open spell runs to now). Team-only: main's
|
|
354
|
+
// red time is main's own, not any role's, so a role-scoped series leaves every day unset —
|
|
355
|
+
// exactly as checkFailures is team-only. Only set when a day actually was red (zero-absent,
|
|
356
|
+
// like checkMedianMs).
|
|
357
|
+
if (bases === undefined) {
|
|
358
|
+
const redByDay = mainRedMinutesByDay(foldEntry.redEvents, dayAt(days - 1, now).getTime(), now.getTime());
|
|
359
|
+
for (const d of series) {
|
|
360
|
+
const ms = redByDay.get(d.date);
|
|
361
|
+
if (ms !== undefined)
|
|
362
|
+
d.mainRedMs = ms;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
315
365
|
const countOn = (date, field) => {
|
|
316
366
|
const day = byDate.get(date);
|
|
317
367
|
if (day)
|
|
@@ -366,6 +416,36 @@ export function collectReport(root, days, role) {
|
|
|
366
416
|
}
|
|
367
417
|
}
|
|
368
418
|
}
|
|
419
|
+
// The per-day backlog lag median: how long each finished plan or bug waited from its filing
|
|
420
|
+
// stamp to its done/fixed stamp, folded per completion day — the median backlog age at
|
|
421
|
+
// which the day's items closed. Team-only (a lag has no role, like the validation tally
|
|
422
|
+
// and the filing stamps above) and zero-means-absent: a day with no lag-carrying completion
|
|
423
|
+
// keeps its exact pre-feature shape, and an out-of-window completion date drops out (it
|
|
424
|
+
// must be a byDate key, the same drop countOn applies). The same entry detection and date
|
|
425
|
+
// rules (sectionCompletionLags / entryLags) the completion and filing reads use, so the
|
|
426
|
+
// spans pair the days `featuresDone`/`bugsFixed` count.
|
|
427
|
+
if (role === undefined) {
|
|
428
|
+
const lagsByDay = new Map();
|
|
429
|
+
const foldLag = (date, lagDays) => {
|
|
430
|
+
const list = lagsByDay.get(date);
|
|
431
|
+
if (list)
|
|
432
|
+
list.push(lagDays);
|
|
433
|
+
else
|
|
434
|
+
lagsByDay.set(date, [lagDays]);
|
|
435
|
+
};
|
|
436
|
+
for (const file of finishedFiles("PLANS.md")) {
|
|
437
|
+
for (const { date, lagDays } of sectionCompletionLags(root, file, "Done", DONE_DATE_RE))
|
|
438
|
+
if (byDate.has(date))
|
|
439
|
+
foldLag(date, lagDays);
|
|
440
|
+
}
|
|
441
|
+
for (const file of finishedFiles("BUGS.md")) {
|
|
442
|
+
for (const { date, lagDays } of sectionCompletionLags(root, file, "Fixed", FIXED_DATE_RE))
|
|
443
|
+
if (byDate.has(date))
|
|
444
|
+
foldLag(date, lagDays);
|
|
445
|
+
}
|
|
446
|
+
for (const [date, lags] of lagsByDay)
|
|
447
|
+
byDate.get(date).backlogLagMedianDays = lowerMedian(lags);
|
|
448
|
+
}
|
|
369
449
|
const totals = {
|
|
370
450
|
tokensOut: 0,
|
|
371
451
|
runs: 0,
|
|
@@ -383,6 +463,7 @@ export function collectReport(root, days, role) {
|
|
|
383
463
|
let mergeFailed = 0;
|
|
384
464
|
let plansAdded = 0;
|
|
385
465
|
let bugsFiled = 0;
|
|
466
|
+
const notionalByBackend = {};
|
|
386
467
|
for (const d of series) {
|
|
387
468
|
totals.tokensOut += d.tokensOut;
|
|
388
469
|
for (const n of Object.values(d.runsByRole))
|
|
@@ -394,6 +475,8 @@ export function collectReport(root, days, role) {
|
|
|
394
475
|
totals.maintenanceCommits += d.maintenanceCommits ?? 0;
|
|
395
476
|
totals.costUsd += d.costUsd;
|
|
396
477
|
notionalCostUsd += d.notionalCostUsd ?? 0;
|
|
478
|
+
for (const [backend, c] of Object.entries(d.notionalByBackend ?? {}))
|
|
479
|
+
addTo(notionalByBackend, backend, c);
|
|
397
480
|
totals.featuresDone += d.featuresDone;
|
|
398
481
|
totals.bugsFixed += d.bugsFixed;
|
|
399
482
|
plansAdded += d.plansAdded ?? 0;
|
|
@@ -419,11 +502,12 @@ export function collectReport(root, days, role) {
|
|
|
419
502
|
days,
|
|
420
503
|
from,
|
|
421
504
|
to,
|
|
422
|
-
...(
|
|
505
|
+
...(bases === undefined ? {} : { role: bases.join(",") }),
|
|
423
506
|
series,
|
|
424
507
|
totals: {
|
|
425
508
|
...totals,
|
|
426
509
|
...(notionalCostUsd > 0 ? { notionalCostUsd } : {}),
|
|
510
|
+
...(Object.keys(notionalByBackend).length > 0 ? { notionalByBackend } : {}),
|
|
427
511
|
...(mergeFailed > 0 ? { mergeFailed } : {}),
|
|
428
512
|
...(plansAdded > 0 ? { plansAdded } : {}),
|
|
429
513
|
...(bugsFiled > 0 ? { bugsFiled } : {}),
|