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,21 +1,25 @@
|
|
|
1
|
-
// vocabulary: plain
|
|
2
1
|
import { fail, say, sayJsonLine } from "./cli-output.js";
|
|
3
|
-
import {
|
|
2
|
+
import { hasFollowFlag, LOGS_TRANSCRIPT_VALUE_ERROR } from "./cli-flag-specs.js";
|
|
3
|
+
import { durationLabel, failRivalShapes, flagValue, parseCountFlag, parseGrepFlag, parseRoleListScope, parseRoleScope, parseSinceFlag, parseTypeFlag } from "./cli-args.js";
|
|
4
4
|
import { LOGS_SINCE_MAX_MS, readEventsSince, SPARSE_WINDOW_NOTE, } from "../events/event-window.js";
|
|
5
|
-
import { compareCodeUnits, increment
|
|
6
|
-
import {
|
|
5
|
+
import { compareCodeUnits, increment } from "../collections.js";
|
|
6
|
+
import { eventTypeTally } from "../events/event-tally.js";
|
|
7
|
+
import { eventRole, parseEventLine, readEventsTailWithEnd } from "../events/event-read.js";
|
|
7
8
|
import { eventMatchesGrep, formatEvent } from "../events/event-format.js";
|
|
8
9
|
import { canonicalEventType } from "../events/event-legacy.js";
|
|
9
10
|
import { EVENT_TYPE_LABELS, eventTypeLabel } from "../events/event-labels.js";
|
|
10
11
|
import { followFile } from "../files/tail.js";
|
|
12
|
+
import { roleInScope } from "../roles/runner-ids.js";
|
|
13
|
+
import { startParentDeathWatch } from "../process/supervisor.js";
|
|
11
14
|
import { typoSuffix } from "../text/suggest.js";
|
|
12
|
-
import {
|
|
15
|
+
import { splitCommaList } from "../text/text.js";
|
|
16
|
+
import { createTranscriptFilter, createTranscriptRenderer } from "../ui/transcript.js";
|
|
13
17
|
import { readTranscriptTail } from "../ui/transcript-tail.js";
|
|
14
18
|
import { eventsLogPath, piLogPath } from "../paths.js";
|
|
15
19
|
/** The read-only observing half of the CLI's non-dispatch commands: `tumwater logs` and its
|
|
16
|
-
* `--
|
|
20
|
+
* `--transcript` view, split out of cli.ts so the entry point stays a dispatch table. Unlike
|
|
17
21
|
* operator/operator-commands.ts these write nothing but stdout — they only read the event log and
|
|
18
|
-
* each
|
|
22
|
+
* each role's agent transcript. It lives beside the other CLI command bodies (history.ts,
|
|
19
23
|
* cli/cli-query-commands.ts, operator/operator-commands.ts), which may import the ui/ rendering
|
|
20
24
|
* layer they drive — here the event formatter and the transcript renderer — while src/ui/
|
|
21
25
|
* itself stays off src/ module boundaries it does not own. */
|
|
@@ -36,28 +40,30 @@ function sayEventLine(e, json) {
|
|
|
36
40
|
* In `--json` mode it emits one compact object mapping `type → count` with keys sorted, the
|
|
37
41
|
* machine-readable twin of the prose tally. */
|
|
38
42
|
function sayTally(events, json) {
|
|
39
|
-
const counts = new Map();
|
|
40
|
-
for (const e of events)
|
|
41
|
-
increment(counts, e.type);
|
|
42
43
|
if (json) {
|
|
44
|
+
// The machine-readable twin keeps its own alphabetical key sort; the prose tally uses the
|
|
45
|
+
// shared eventTypeTally ordering.
|
|
46
|
+
const counts = new Map();
|
|
47
|
+
for (const e of events)
|
|
48
|
+
increment(counts, e.type);
|
|
43
49
|
const obj = {};
|
|
44
50
|
for (const [type] of [...counts.entries()].sort((a, b) => compareCodeUnits(a[0], b[0])))
|
|
45
51
|
obj[type] = counts.get(type);
|
|
46
52
|
sayJsonLine(obj);
|
|
47
53
|
return;
|
|
48
54
|
}
|
|
49
|
-
for (const [type, n] of
|
|
55
|
+
for (const [type, n] of eventTypeTally(events))
|
|
50
56
|
say(`${n} × ${eventTypeLabel(type)} (${type})`);
|
|
51
57
|
}
|
|
52
58
|
/** The shared rival-shape guard for logs flags that only apply to the event-log feed:
|
|
53
|
-
* `--
|
|
54
|
-
* it is excluded with it), so each such flag fails naming both. One wording
|
|
55
|
-
* the --json, --
|
|
56
|
-
* is the flag's own presence
|
|
57
|
-
*
|
|
58
|
-
function
|
|
59
|
-
if (active && (rest.includes("--
|
|
60
|
-
failRivalShapes(`logs ${flag}`, "--
|
|
59
|
+
* `--transcript` swaps in a transcript rather than the event log (--prompt requires
|
|
60
|
+
* --transcript, so it is excluded with it), so each such flag fails naming both. One wording
|
|
61
|
+
* for all of them — the --json, --count, --type and --since checks cannot drift apart in what
|
|
62
|
+
* they say or why. `active` is the flag's own presence. --grep is not one of them: it also
|
|
63
|
+
* filters the transcript view. */
|
|
64
|
+
function rejectTranscriptViewRival(rest, flag, active) {
|
|
65
|
+
if (active && (rest.includes("--transcript") || rest.includes("--prompt")))
|
|
66
|
+
failRivalShapes(`logs ${flag}`, "--transcript", "the --transcript view is the role's agent transcript, not the event log; --prompt requires --transcript");
|
|
61
67
|
}
|
|
62
68
|
/** The missing-pattern error cmdLogs prints for a valueless `--grep`, exported so cli.ts's
|
|
63
69
|
* rejectUnknownArgs spec for --grep can fail a trailing `logs --grep` with the same wording
|
|
@@ -73,97 +79,140 @@ export const TYPE_VALUE_ERROR = "logs --type needs an event type";
|
|
|
73
79
|
* completion already offers the valid codes, so a bare no-match for a near-miss reads as a silent
|
|
74
80
|
* mystery) — while a VALID type that merely has no matching events stays hint-free, a legitimate
|
|
75
81
|
* empty result rather than a typo. A valid type or a legacy alias (canonicalEventType maps the
|
|
76
|
-
* alias onto the current code, which is a label key) never hints.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
: typoSuffix(type, Object.keys(EVENT_TYPE_LABELS));
|
|
82
|
+
* alias onto the current code, which is a label key) never hints. For a comma list the hint
|
|
83
|
+
* is for the first piece that is not a valid type; the prose names the value as typed. */
|
|
84
|
+
function typeEmpty(type, pieces) {
|
|
85
|
+
const bad = pieces.find((p) => !Object.hasOwn(EVENT_TYPE_LABELS, canonicalEventType(p)));
|
|
86
|
+
const hint = bad === undefined ? "" : typoSuffix(bad, Object.keys(EVENT_TYPE_LABELS));
|
|
82
87
|
return `no events matching "${type}"${hint}`;
|
|
83
88
|
}
|
|
84
|
-
/** `
|
|
85
|
-
*
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
/** Follow `file` until Ctrl+C or until the process that started this one is gone (the shape of
|
|
90
|
+
* a `logs -f` leaked to PPID 1 that polled for days). Resolves once the parent is gone. */
|
|
91
|
+
export function followUntilParentGone(file, offset, onLines, seams) {
|
|
92
|
+
const stop = followFile(file, offset, onLines);
|
|
93
|
+
return new Promise((resolve) => {
|
|
94
|
+
startParentDeathWatch(() => {
|
|
95
|
+
stop();
|
|
96
|
+
resolve();
|
|
97
|
+
}, {
|
|
98
|
+
...(seams.ppid ? { ppid: seams.ppid } : {}),
|
|
99
|
+
...(seams.intervalMs !== undefined ? { intervalMs: seams.intervalMs } : {}),
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/** `tumwater logs [-f] [-n <count>] [--since <duration>] [--until <duration>]
|
|
104
|
+
* [--role <id>[,<id>...]] [--transcript <id>] [--prompt]
|
|
105
|
+
* [--grep <text>]`: follow or dump the harness event log, with `--since` a bounded
|
|
106
|
+
* past window of it and `--role` keeping only the listed roles' events (a base role id takes its
|
|
107
|
+
* instances too),
|
|
108
|
+
* or with `--transcript` one role's agent transcript (see cmdLogsTranscript). `-f` follows until
|
|
109
|
+
* Ctrl+C or until its parent process exits. */
|
|
110
|
+
export async function cmdLogs(root, args, seams = {}) {
|
|
111
|
+
// `--grep <text>` filters the event feed (the -n view and its follow) and, with --transcript,
|
|
112
|
+
// the transcript's entries (see cmdLogsTranscript): case-insensitive
|
|
89
113
|
// substring against `${e.type} ${formatEvent(e)}` — the rendered line is what the operator
|
|
90
114
|
// would otherwise read (WYSIWYG), and prefixing the raw type id lets stable ids
|
|
91
115
|
// (review_rejected, merge_failed) be filtered even where the rendering paraphrases them.
|
|
92
|
-
//
|
|
93
|
-
// (--prompt requires --role, so it is excluded with it), and --since is a filter of its own
|
|
94
|
-
// rather than a window to filter — and each failure names both flags. The flag scan itself
|
|
116
|
+
// --grep filters the --since window like --type and --role do. The flag scan itself
|
|
95
117
|
// (the value lookup, the `rest` construction that keeps a flag-shaped pattern from
|
|
96
118
|
// impersonating a rival flag, and the empty-value fail) is cli/cli-args.ts's parseGrepFlag,
|
|
97
119
|
// the one home shared with history's identical preamble.
|
|
98
120
|
const { rest: grepped, pattern: grepPattern } = parseGrepFlag(args, GREP_VALUE_ERROR);
|
|
99
121
|
// `--type <eventType>` filters the event feed by EXACT event type (e.type === value):
|
|
100
122
|
// deterministic where --grep substrings — a merge_failed whose rendered line quotes
|
|
101
|
-
// "merge_failed" matches --grep but not --type.
|
|
102
|
-
// (the window
|
|
103
|
-
// it is a rival only of the --
|
|
123
|
+
// "merge_failed" matches --grep but not --type. It composes with --since
|
|
124
|
+
// (the window it filters) as well as -n, -f, --json, and --grep; like --json
|
|
125
|
+
// it is a rival only of the --transcript/--prompt transcript view. A comma list matches any
|
|
126
|
+
// of its types. The value scan (keeping a
|
|
104
127
|
// flag-shaped value like --since as text, the empty-value fail) mirrors parseGrepFlag via
|
|
105
128
|
// parseTypeFlag, so the two cannot drift; `rest` here has both flags' value tokens removed.
|
|
106
129
|
const { rest, type } = parseTypeFlag(grepped, TYPE_VALUE_ERROR);
|
|
107
130
|
const grepLower = grepPattern === null ? null : grepPattern.toLowerCase();
|
|
108
131
|
// An older event name matches its current one; the empty-match prose still names what was typed.
|
|
109
|
-
const
|
|
110
|
-
|
|
132
|
+
const typePieces = type === null ? [] : splitCommaList(type);
|
|
133
|
+
if (type !== null && typePieces.length === 0)
|
|
134
|
+
fail(TYPE_VALUE_ERROR);
|
|
135
|
+
const wantedTypes = new Set(typePieces.map(canonicalEventType));
|
|
136
|
+
const typeFilter = type === null ? null : (e) => wantedTypes.has(e.type);
|
|
111
137
|
// The composed feed rule every emit site threads today's grep-only predicate through:
|
|
112
138
|
// an event passes when it is absent-or-matches the --grep substring AND absent-or-equals
|
|
113
139
|
// the --type id, held in one place so the --since window, the -n tally, and the follow
|
|
114
140
|
// cannot drift on what an event must satisfy.
|
|
141
|
+
// `--role <id>[,<id>...]` joins them: an event passes when the role it was filed under, or
|
|
142
|
+
// that role's base id (so `--role feature` takes `feature-2` too), is listed. It
|
|
143
|
+
// composes with --since. The value scan reads `rest`, which holds no --grep/--type value tokens.
|
|
144
|
+
const roles = parseRoleListScope(root, rest);
|
|
145
|
+
const roleFilter = roles === null
|
|
146
|
+
? null
|
|
147
|
+
: (e) => roleInScope(eventRole(e), roles);
|
|
148
|
+
if (roles !== null)
|
|
149
|
+
rejectTranscriptViewRival(rest, "--role", true);
|
|
115
150
|
const feedFilter = (e) => (grepLower === null || eventMatchesGrep(e, grepLower)) &&
|
|
116
|
-
(typeFilter === null || typeFilter(e))
|
|
117
|
-
|
|
151
|
+
(typeFilter === null || typeFilter(e)) &&
|
|
152
|
+
(roleFilter === null || roleFilter(e));
|
|
153
|
+
// Empty-match prose: grep/type keep their wording when given; a role-only filter names the roles.
|
|
154
|
+
const roleEmpty = roles === null ? "" : `no events from ${roles.join(", ")}`;
|
|
155
|
+
const filtersGrepOrType = grepPattern !== null || type !== null;
|
|
156
|
+
const follow = hasFollowFlag(rest);
|
|
118
157
|
// `--json` switches the feed from formatEvent rendering to one JSON.stringify(e) per line —
|
|
119
158
|
// the raw HarnessEvent objects exactly as stored in the log — so scripts read the canonical
|
|
120
159
|
// schema instead of parsing a rendering that changes shape whenever the formatter evolves.
|
|
121
160
|
// It composes with -n, --grep, --since and -f (the grep filter applies before serialization,
|
|
122
|
-
// the follow streams JSON lines as events land), but not with --
|
|
123
|
-
// transcript of human-oriented prose, not the event log (--prompt requires --
|
|
161
|
+
// the follow streams JSON lines as events land), but not with --transcript: that view is a pi
|
|
162
|
+
// transcript of human-oriented prose, not the event log (--prompt requires --transcript, so it is
|
|
124
163
|
// excluded with it).
|
|
125
164
|
const json = rest.includes("--json");
|
|
126
|
-
|
|
165
|
+
rejectTranscriptViewRival(rest, "--json", json);
|
|
127
166
|
// `--count` tallies the window's present event types instead of printing the rows. Rival
|
|
128
167
|
// shapes stay exclusive: counting implies a bounded window (so -f/--follow is rejected)
|
|
129
|
-
// and the --
|
|
168
|
+
// and the --transcript view is the role's agent transcript rather than the event log.
|
|
130
169
|
const count = rest.includes("--count");
|
|
131
|
-
|
|
170
|
+
rejectTranscriptViewRival(rest, "--count", count);
|
|
132
171
|
if (count && follow)
|
|
133
172
|
failRivalShapes("logs --count", "-f/--follow", "counting implies a bounded window; -f follows from now on");
|
|
134
173
|
if (type !== null)
|
|
135
|
-
|
|
136
|
-
if (grepPattern !== null) {
|
|
137
|
-
rejectRoleViewRival(rest, "--grep", true);
|
|
138
|
-
if (rest.includes("--since"))
|
|
139
|
-
failRivalShapes("logs --grep", "--since", "--since is a filter of its own; --grep filters the -n view and its follow");
|
|
140
|
-
}
|
|
174
|
+
rejectTranscriptViewRival(rest, "--type", true);
|
|
141
175
|
// `--since <duration>` is the window-shaped view over the same event log the -n view dumps:
|
|
142
176
|
// it reads a bounded past window (event-window.ts's day-keyed backwards scan) and prints the
|
|
143
177
|
// survivors oldest-first, so an operator can ask for "the hour around that 429 storm" without
|
|
144
178
|
// guessing a count. Rival shapes stay exclusive — follow means "from now on", -n means "last
|
|
145
|
-
// N", and --
|
|
146
|
-
// both flags. (--prompt requires --
|
|
179
|
+
// N", and --transcript swaps in a transcript rather than this log — and each failure names
|
|
180
|
+
// both flags. (--prompt requires --transcript, so it is excluded with it.)
|
|
147
181
|
const ms = parseSinceFlag(rest, "logs --since", LOGS_SINCE_MAX_MS);
|
|
182
|
+
const untilMs = parseSinceFlag(rest, "logs --until", LOGS_SINCE_MAX_MS, "--until");
|
|
183
|
+
if (untilMs !== null && ms === null)
|
|
184
|
+
fail("logs --until requires --since");
|
|
185
|
+
if (untilMs !== null && ms !== null && untilMs >= ms)
|
|
186
|
+
fail(`logs --until (${durationLabel(untilMs)}) must be shorter than --since (${durationLabel(ms)})`);
|
|
148
187
|
if (ms !== null) {
|
|
149
188
|
if (follow)
|
|
150
189
|
failRivalShapes("logs --since", "-f/--follow", 'follow means "from now on"; --since shows a bounded past window');
|
|
151
190
|
if (rest.includes("-n"))
|
|
152
191
|
failRivalShapes("logs --since", "-n", "a count and a window are rival shapes");
|
|
153
|
-
|
|
192
|
+
rejectTranscriptViewRival(rest, "--since", true);
|
|
154
193
|
// covered is only consulted below when the window has rows (an empty window returns
|
|
155
194
|
// earlier), so the helper's vacuous empty-log branch never reaches the note here.
|
|
156
|
-
const { events, covered } = readEventsSince(root, ms);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
//
|
|
195
|
+
const { cutoff, events: windowEvents, covered } = readEventsSince(root, ms);
|
|
196
|
+
const events = untilMs === null ? windowEvents : windowEvents.filter((e) => e.ts < cutoff + ms - untilMs);
|
|
197
|
+
const windowPhrase = untilMs === null ? `in ${durationLabel(ms)}` : `between ${durationLabel(ms)} and ${durationLabel(untilMs)} ago`;
|
|
198
|
+
// `--grep`, `--type` and `--role` all filter the window through feedFilter: only the
|
|
199
|
+
// window events that pass are printed, and an all-filtered window answers with the
|
|
200
|
+
// no-match prose (the filter's own line) instead of the generic empty-window one —
|
|
160
201
|
// "which merge_failed in the last hour" filters the same as it would the -n view.
|
|
161
|
-
const filtered =
|
|
202
|
+
const filtered = events.filter(feedFilter);
|
|
162
203
|
if (filtered.length === 0) {
|
|
163
204
|
// In JSON mode an empty result answers silently — an empty output IS the machine-readable
|
|
164
205
|
// answer, and prose would corrupt a consumer's NDJSON stream.
|
|
165
|
-
if (!json)
|
|
166
|
-
|
|
206
|
+
if (!json) {
|
|
207
|
+
if (grepPattern !== null && type !== null)
|
|
208
|
+
say(`no events matching "${grepPattern}" or ${typeEmpty(type, typePieces)}`);
|
|
209
|
+
else if (type !== null)
|
|
210
|
+
say(typeEmpty(type, typePieces));
|
|
211
|
+
else if (grepPattern !== null)
|
|
212
|
+
say(`no events matching "${grepPattern}" ${windowPhrase}`);
|
|
213
|
+
else
|
|
214
|
+
say(roles !== null ? `${roleEmpty} ${windowPhrase}` : `no events ${windowPhrase}`);
|
|
215
|
+
}
|
|
167
216
|
return;
|
|
168
217
|
}
|
|
169
218
|
// `--count` composes with the window: the tally covers exactly the filtered window rows
|
|
@@ -187,14 +236,14 @@ export async function cmdLogs(root, args) {
|
|
|
187
236
|
}
|
|
188
237
|
const nRaw = flagValue(rest, "-n");
|
|
189
238
|
const limit = nRaw !== null ? parseCountFlag("-n", nRaw) : 50;
|
|
190
|
-
// The event feed (no --
|
|
239
|
+
// The event feed (no --transcript) never needs the config at all: parseRoleScope reads it only
|
|
191
240
|
// when the flag is present.
|
|
192
|
-
const role = parseRoleScope(root, rest);
|
|
241
|
+
const role = parseRoleScope(root, rest, "--transcript", LOGS_TRANSCRIPT_VALUE_ERROR);
|
|
193
242
|
const showPrompts = rest.includes("--prompt");
|
|
194
243
|
if (showPrompts && role === null)
|
|
195
|
-
fail("logs --prompt needs --
|
|
244
|
+
fail("logs --prompt needs --transcript <id>");
|
|
196
245
|
if (role !== null) {
|
|
197
|
-
await cmdLogsTranscript(root, role, limit, follow, showPrompts);
|
|
246
|
+
await cmdLogsTranscript(root, role, limit, follow, showPrompts, grepLower, grepPattern, seams);
|
|
198
247
|
return;
|
|
199
248
|
}
|
|
200
249
|
// -n bounds the scan, not the print: the matched subset of the last `limit` events is what
|
|
@@ -202,7 +251,7 @@ export async function cmdLogs(root, args) {
|
|
|
202
251
|
// the tail-with-end shape (not the per-poll cached readEvents) so the follow below can seed
|
|
203
252
|
// from the byte end this very read covered instead of a later stat of the file.
|
|
204
253
|
const tail = readEventsTailWithEnd(root, limit);
|
|
205
|
-
const shown = grepLower !== null || type !== null ? tail.events.filter(feedFilter) : tail.events;
|
|
254
|
+
const shown = grepLower !== null || type !== null || roleFilter !== null ? tail.events.filter(feedFilter) : tail.events;
|
|
206
255
|
// `--count` over the -n view answers with the tally of exactly the filtered rows the plain
|
|
207
256
|
// view would print, and carries over the plain view's empty-match prose below (a `--type`
|
|
208
257
|
// or `--grep` that matches nothing names its value; an empty unfiltered -n view prints
|
|
@@ -210,13 +259,15 @@ export async function cmdLogs(root, args) {
|
|
|
210
259
|
if (count) {
|
|
211
260
|
if (shown.length !== 0)
|
|
212
261
|
sayTally(shown, json);
|
|
213
|
-
else if (!json && (
|
|
262
|
+
else if (!json && (filtersGrepOrType || roles !== null)) {
|
|
214
263
|
if (grepPattern !== null && type !== null)
|
|
215
|
-
say(`no events matching "${grepPattern}" or ${typeEmpty(type)}`);
|
|
264
|
+
say(`no events matching "${grepPattern}" or ${typeEmpty(type, typePieces)}`);
|
|
216
265
|
// Type-empty gets the hint (only the type branch); a grep-only empty stays the bare
|
|
217
266
|
// no-match line, because a free-text pattern is not an event type to suggest against.
|
|
267
|
+
else if (!filtersGrepOrType)
|
|
268
|
+
say(roleEmpty);
|
|
218
269
|
else
|
|
219
|
-
say(type !== null ? typeEmpty(type) : `no events matching "${grepPattern ?? ""}"`);
|
|
270
|
+
say(type !== null ? typeEmpty(type, typePieces) : `no events matching "${grepPattern ?? ""}"`);
|
|
220
271
|
}
|
|
221
272
|
return;
|
|
222
273
|
}
|
|
@@ -226,13 +277,15 @@ export async function cmdLogs(root, args) {
|
|
|
226
277
|
// The empty-match line is prose: in JSON mode the empty output is the answer. It fires
|
|
227
278
|
// for either filter, naming the flag's value(s) whose match came up empty so the operator
|
|
228
279
|
// knows what to loosen.
|
|
229
|
-
if (shown.length === 0 && !json && (
|
|
280
|
+
if (shown.length === 0 && !json && (filtersGrepOrType || roles !== null)) {
|
|
230
281
|
if (grepPattern !== null && type !== null)
|
|
231
|
-
say(`no events matching "${grepPattern}" or ${typeEmpty(type)}`);
|
|
282
|
+
say(`no events matching "${grepPattern}" or ${typeEmpty(type, typePieces)}`);
|
|
232
283
|
// Type-empty gets the hint (only the type branch); a grep-only empty stays the bare
|
|
233
284
|
// no-match line, because a free-text pattern is not an event type to suggest against.
|
|
285
|
+
else if (!filtersGrepOrType)
|
|
286
|
+
say(roleEmpty);
|
|
234
287
|
else
|
|
235
|
-
say(type !== null ? typeEmpty(type) : `no events matching "${grepPattern ?? ""}"`);
|
|
288
|
+
say(type !== null ? typeEmpty(type, typePieces) : `no events matching "${grepPattern ?? ""}"`);
|
|
236
289
|
}
|
|
237
290
|
return;
|
|
238
291
|
}
|
|
@@ -245,7 +298,7 @@ export async function cmdLogs(root, args) {
|
|
|
245
298
|
// log scans to coveredEnd 0, and followFile tolerates a missing file (its poll re-stats
|
|
246
299
|
// every interval), so a read-only command never leaves a harness state file behind — the
|
|
247
300
|
// module contract above promises writes to stdout only.
|
|
248
|
-
|
|
301
|
+
await followUntilParentGone(file, tail.coveredEnd, (lines) => {
|
|
249
302
|
for (const line of lines.filter(Boolean)) {
|
|
250
303
|
const e = parseEventLine(line);
|
|
251
304
|
// The filter holds across rotation: every event the follow callback sees goes through
|
|
@@ -253,19 +306,31 @@ export async function cmdLogs(root, args) {
|
|
|
253
306
|
if (e && feedFilter(e))
|
|
254
307
|
sayEventLine(e, json);
|
|
255
308
|
}
|
|
256
|
-
});
|
|
257
|
-
await new Promise(() => { }); // Follow until Ctrl+C.
|
|
309
|
+
}, seams);
|
|
258
310
|
}
|
|
259
|
-
/** `tumwater logs --
|
|
311
|
+
/** `tumwater logs --transcript <id>`: print (and optionally follow) one role's agent transcript —
|
|
260
312
|
* run separators, abbreviated thinking, assistant text, and tool calls; with `--prompt` also
|
|
261
313
|
* each run's exact prompt text. Read-only; the raw log is pi's streaming event stream, so only
|
|
262
|
-
* complete renderable events are shown.
|
|
263
|
-
|
|
314
|
+
* complete renderable events are shown. With `--grep`, only entries with a rendered line
|
|
315
|
+
* containing the text (case-insensitively) print, each under its run's separator; `-n` still
|
|
316
|
+
* bounds the entries scanned, not printed. */
|
|
317
|
+
async function cmdLogsTranscript(root, role, limit, follow, showPrompts, needle, pattern, seams) {
|
|
264
318
|
const file = piLogPath(root, role);
|
|
265
319
|
const opts = { includePrompts: showPrompts };
|
|
320
|
+
const filter = needle === null ? null : createTranscriptFilter(needle);
|
|
321
|
+
let matched = 0;
|
|
266
322
|
const printEntry = (lines) => {
|
|
267
|
-
if (lines.length
|
|
323
|
+
if (lines.length === 0)
|
|
324
|
+
return;
|
|
325
|
+
if (filter === null) {
|
|
268
326
|
say(lines.join("\n"));
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
329
|
+
const out = filter(lines);
|
|
330
|
+
if (out === null)
|
|
331
|
+
return;
|
|
332
|
+
matched++;
|
|
333
|
+
say(out.join("\n"));
|
|
269
334
|
};
|
|
270
335
|
// Initial window: the last `limit` entries of what is on disk. readTranscriptTail scans back
|
|
271
336
|
// from EOF only as far as needed instead of re-reading the whole (up to logMaxBytes) file,
|
|
@@ -280,6 +345,8 @@ async function cmdLogsTranscript(root, role, limit, follow, showPrompts) {
|
|
|
280
345
|
for (const entry of tail.entries)
|
|
281
346
|
printEntry(entry);
|
|
282
347
|
offset = tail.end;
|
|
348
|
+
if (needle !== null && matched === 0)
|
|
349
|
+
say(`no transcript entries matching "${pattern ?? ""}" for ${role}`);
|
|
283
350
|
}
|
|
284
351
|
if (!follow)
|
|
285
352
|
return;
|
|
@@ -288,9 +355,8 @@ async function cmdLogsTranscript(root, role, limit, follow, showPrompts) {
|
|
|
288
355
|
// readTranscriptTail's formatTranscript already flushed any pending separator for what
|
|
289
356
|
// was on disk.
|
|
290
357
|
const renderer = createTranscriptRenderer(opts);
|
|
291
|
-
|
|
358
|
+
await followUntilParentGone(file, offset, (lines) => {
|
|
292
359
|
for (const line of lines)
|
|
293
360
|
printEntry(renderer.feed(line));
|
|
294
|
-
});
|
|
295
|
-
await new Promise(() => { }); // Follow until Ctrl+C.
|
|
361
|
+
}, seams);
|
|
296
362
|
}
|