tumwater 0.4.2 → 0.4.4
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 +6 -6
- package/dist/build-info.json +2 -2
- package/dist/src/agent/agent-backend.js +6 -6
- package/dist/src/agent/{run-agent.js → agent-run.js} +27 -13
- package/dist/src/agent/{run-settle.js → agent-settle.js} +48 -24
- package/dist/src/agent/{run-spawn.js → agent-spawn.js} +21 -12
- package/dist/src/agent/{run-stream.js → agent-stream.js} +4 -4
- package/dist/src/agent/backend-traits.js +2 -2
- package/dist/src/agent/claude/claude-account.js +6 -27
- package/dist/src/agent/claude/claude-backend.js +3 -3
- package/dist/src/agent/claude/claude-env.js +27 -31
- package/dist/src/agent/claude/claude-stream.js +111 -54
- package/dist/src/agent/codex/codex-account.js +8 -0
- package/dist/src/agent/codex/codex-args.js +5 -5
- package/dist/src/agent/codex/codex-backend.js +2 -2
- package/dist/src/agent/codex/codex-env.js +28 -15
- package/dist/src/agent/codex/codex-hook-trust.js +39 -20
- package/dist/src/agent/codex/codex-rollout.js +93 -56
- package/dist/src/agent/codex/codex-stream.js +1 -1
- package/dist/src/agent/env-scrub.js +18 -0
- package/dist/src/agent/image-input.js +68 -11
- package/dist/src/agent/notes-shim.js +2 -2
- package/dist/src/agent/opencode/opencode-backend.js +26 -24
- package/dist/src/agent/opencode/opencode-catalog.js +85 -36
- package/dist/src/agent/opencode/opencode-config.js +32 -14
- package/dist/src/agent/opencode/opencode-env.js +12 -13
- package/dist/src/agent/opencode/opencode-stream.js +47 -25
- package/dist/src/agent/session-ledger.js +23 -27
- package/dist/src/agent/subscription-account.js +2 -83
- package/dist/src/backlog/backlog-archive.js +3 -4
- package/dist/src/backlog/backlog-cli-view.js +81 -41
- package/dist/src/backlog/backlog-cli.js +57 -26
- package/dist/src/backlog/backlog-eligibility.js +56 -122
- package/dist/src/backlog/backlog-md.js +5 -5
- package/dist/src/backlog/backlog-parts.js +65 -27
- package/dist/src/backlog/{question-answer.js → backlog-question-answer.js} +1 -1
- package/dist/src/backlog/backlog-release.js +12 -12
- package/dist/src/backlog/backlog-structure.js +114 -61
- package/dist/src/backlog/backlog.js +3 -2
- package/dist/src/baseline/main-baseline.js +148 -84
- package/dist/src/baseline/main-guardrails.js +2 -2
- package/dist/src/baseline/main-watch.js +84 -50
- package/dist/src/brief/brief.js +26 -13
- package/dist/src/budget/budget-fallback-view.js +100 -243
- package/dist/src/budget/budget-wiring.js +29 -65
- package/dist/src/budget/budget.js +4 -5
- package/dist/src/budget/fallback-breaker.js +2 -2
- package/dist/src/build/build-check-detect.js +43 -14
- package/dist/src/build/build-check-events.js +2 -2
- package/dist/src/build/build-check-report.js +10 -0
- package/dist/src/build/build-check-scoped.js +40 -18
- package/dist/src/build/build-check.js +13 -5
- package/dist/src/build/build-stage.js +6 -4
- package/dist/src/change/change-data.js +1 -4
- package/dist/src/cli/cli-command-args.js +89 -52
- package/dist/src/cli/cli-completion-command.js +75 -0
- package/dist/src/cli/{config-commands.js → cli-config-commands.js} +82 -71
- package/dist/src/cli/cli-doctor-command.js +103 -0
- package/dist/src/cli/cli-flag-specs.js +42 -22
- package/dist/src/cli/cli-init.js +36 -14
- package/dist/src/cli/{log-commands.js → cli-log-commands.js} +43 -23
- package/dist/src/cli/{notify-command.js → cli-notify-command.js} +2 -2
- package/dist/src/cli/cli-query-commands.js +2 -2
- package/dist/src/cli/{question-commands.js → cli-question-commands.js} +86 -60
- package/dist/src/cli/cli-repo-gate.js +2 -2
- package/dist/src/cli/cli-role-command.js +2 -41
- package/dist/src/cli/cli-start-summary.js +4 -3
- package/dist/src/cli/cli-start-supervisor.js +190 -0
- package/dist/src/cli/cli-start.js +94 -244
- package/dist/src/cli/completion.js +85 -49
- package/dist/src/cli/follow-view.js +20 -2
- package/dist/src/cli/help.js +6 -13
- package/dist/src/cli.js +70 -176
- package/dist/src/collections.js +39 -27
- package/dist/src/concurrency/check-slots.js +70 -0
- package/dist/src/concurrency/lock.js +23 -1
- package/dist/src/concurrency/run-permit.js +49 -0
- package/dist/src/concurrency/semaphore.js +46 -250
- package/dist/src/config/config-editable-keys.js +4 -7
- package/dist/src/config/config-fallbacks.js +81 -101
- package/dist/src/config/config-field-checks.js +66 -37
- package/dist/src/config/config-keys.js +66 -40
- package/dist/src/config/config-live.js +4 -28
- package/dist/src/config/{model-selector.js → config-model-selector.js} +4 -4
- package/dist/src/config/config-request.js +163 -102
- package/dist/src/config/config-schema.js +10 -12
- package/dist/src/config/config-selector-checks.js +1 -1
- package/dist/src/config/config-validation-agents.js +2 -2
- package/dist/src/config/config-validation-roles.js +8 -72
- package/dist/src/config/config-validation.js +4 -39
- package/dist/src/config/config-views.js +26 -50
- package/dist/src/config/config-write.js +128 -102
- package/dist/src/config/config.js +5 -14
- package/dist/src/doctor/doctor-backlog-bugs.js +7 -6
- package/dist/src/doctor/doctor-backlog-plans.js +53 -120
- package/dist/src/doctor/doctor-backlog.js +16 -14
- package/dist/src/doctor/doctor-check-names.js +3 -6
- package/dist/src/doctor/doctor-checks.js +8 -8
- package/dist/src/doctor/doctor-claude-checks.js +70 -36
- package/dist/src/doctor/doctor-codex-checks.js +6 -6
- package/dist/src/doctor/doctor-contention-checks.js +57 -117
- package/dist/src/doctor/doctor-fallback-checks.js +48 -26
- package/dist/src/doctor/doctor-holds.js +8 -47
- package/dist/src/doctor/doctor-install.js +1 -1
- package/dist/src/doctor/doctor-launch-services.js +1 -1
- package/dist/src/doctor/doctor-model-checks.js +178 -94
- package/dist/src/doctor/doctor-notify.js +2 -2
- package/dist/src/doctor/doctor-opencode-checks.js +5 -4
- package/dist/src/doctor/doctor-orphans.js +122 -21
- package/dist/src/doctor/{outcome.js → doctor-outcome.js} +7 -0
- package/dist/src/doctor/doctor-pi-checks.js +2 -2
- package/dist/src/doctor/doctor-principles.js +3 -3
- package/dist/src/doctor/doctor-project-checks.js +24 -11
- package/dist/src/doctor/doctor-role-notes.js +1 -1
- package/dist/src/doctor/doctor.js +8 -11
- package/dist/src/events/event-format.js +44 -64
- package/dist/src/events/event-labels.js +1 -5
- package/dist/src/events/event-legacy.js +3 -5
- package/dist/src/events/{notify.js → event-notify.js} +6 -6
- package/dist/src/events/event-read.js +1 -1
- package/dist/src/events/event-window.js +1 -1
- package/dist/src/events/events.js +8 -0
- package/dist/src/failure/failure-cluster.js +9 -18
- package/dist/src/failure/failure-data.js +12 -8
- package/dist/src/failure/failure-render.js +46 -36
- package/dist/src/failure/failure-state-change.js +54 -120
- package/dist/src/failure/{time-spend.js → failure-time-spend.js} +117 -84
- package/dist/src/files/files.js +30 -0
- package/dist/src/files/json-object.js +8 -8
- package/dist/src/files/stat-cache.js +12 -8
- package/dist/src/gates/budget-gates.js +85 -84
- package/dist/src/gates/gate-polls.js +32 -74
- package/dist/src/gates/pause-gates.js +16 -2
- package/dist/src/gates/readiness.js +1 -1
- package/dist/src/gates/role-cap-gates.js +44 -35
- package/dist/src/gates/{startup-gate.js → startup-gates.js} +9 -8
- package/dist/src/gates/{streak-gate.js → streak-gates.js} +75 -52
- package/dist/src/git/git-diff.js +6 -2
- package/dist/src/git/git.js +75 -45
- package/dist/src/git/worktree-pool.js +3 -6
- package/dist/src/gui/gui-admin-endpoints.js +3 -3
- package/dist/src/gui/gui-args.js +12 -0
- package/dist/src/gui/gui-backlog-commands.js +4 -4
- package/dist/src/gui/gui-backlog-endpoints.js +61 -41
- package/dist/src/gui/gui-command.js +43 -24
- package/dist/src/gui/gui-config-commands.js +2 -64
- package/dist/src/gui/gui-endpoint-commands.js +1 -1
- package/dist/src/gui/gui-endpoint-common.js +19 -1
- package/dist/src/gui/gui-history-endpoints.js +100 -52
- package/dist/src/gui/gui-operator-commands.js +43 -48
- package/dist/src/gui/gui-prompt-commands.js +25 -25
- package/dist/src/gui/gui-report-endpoints.js +1 -1
- package/dist/src/gui/gui-server.js +1 -2
- package/dist/src/gui/gui-team-commands.js +2 -1
- package/dist/src/history/history-data.js +71 -44
- package/dist/src/history/history-queued.js +49 -27
- package/dist/src/history/history.js +54 -36
- package/dist/src/inbox/prompt-commands.js +59 -42
- package/dist/src/init/init.js +88 -40
- package/dist/src/merge/merge-backlog-conflicts.js +1 -1
- package/dist/src/merge/merge-check-failures.js +12 -9
- package/dist/src/merge/merge-core.js +7 -32
- package/dist/src/merge/merge-drain.js +11 -13
- package/dist/src/merge/merge-pipeline.js +6 -7
- package/dist/src/merge/merge-post-review-drain.js +11 -14
- package/dist/src/merge/merge-queue-render.js +3 -3
- package/dist/src/merge/merge-requeue.js +1 -1
- package/dist/src/merge/merge-slot.js +0 -8
- package/dist/src/merge/merge-stack.js +17 -18
- package/dist/src/merge/merge-to-main.js +13 -58
- package/dist/src/merge/merge-verify.js +12 -21
- package/dist/src/notes-cli.js +52 -42
- package/dist/src/operator/operator-commands.js +80 -47
- package/dist/src/operator/operator-intent.js +3 -3
- package/dist/src/orchestrator/orchestrator-launch.js +31 -63
- package/dist/src/orchestrator/orchestrator-poll.js +44 -69
- package/dist/src/orchestrator/orchestrator-scheduling.js +5 -9
- package/dist/src/orchestrator/orchestrator.js +8 -21
- package/dist/src/orchestrator/scheduling-admit.js +101 -68
- package/dist/src/orchestrator/scheduling-scope.js +18 -27
- package/dist/src/orchestrator/scheduling-skip.js +10 -14
- package/dist/src/orchestrator/startup-migrations.js +1 -1
- package/dist/src/paths.js +10 -9
- package/dist/src/pi/pi-args.js +5 -2
- package/dist/src/pi/pi-backend.js +2 -2
- package/dist/src/pi/pi-bin.js +3 -3
- package/dist/src/pi/pi-event-line.js +28 -1
- package/dist/src/pi/pi-listed-models.js +13 -0
- package/dist/src/pi/pi-models.js +43 -29
- package/dist/src/pi/pi-settings.js +43 -20
- package/dist/src/pi/pi-stream.js +41 -8
- package/dist/src/pi/pi-watchdogs.js +43 -15
- package/dist/src/pi/pi.js +2 -2
- package/dist/src/pi-extension/context-shake.js +32 -20
- package/dist/src/pi-extension/kill-guard.js +69 -0
- package/dist/src/process/process-group.js +51 -26
- package/dist/src/process/process.js +20 -12
- package/dist/src/process/run-marker.js +33 -15
- package/dist/src/process/supervisor.js +40 -28
- package/dist/src/prompt/dialect.js +1 -1
- package/dist/src/prompt/gate-notes.js +2 -2
- package/dist/src/prompt/gate-prompts.js +1 -44
- package/dist/src/prompt/notes-backlog.js +66 -37
- package/dist/src/prompt/principles.js +6 -4
- package/dist/src/prompt/prompt-followup.js +12 -4
- package/dist/src/prompt/prompt.js +88 -38
- package/dist/src/redeploy/redeployer.js +21 -1
- package/dist/src/report/report-data.js +53 -37
- package/dist/src/report/report-fold.js +16 -9
- package/dist/src/report/report-render.js +21 -194
- package/dist/src/report/report-since-data.js +4 -3
- package/dist/src/report/report-since-render.js +173 -0
- package/dist/src/report/report-usage-fold.js +8 -8
- package/dist/src/report/report.js +46 -22
- package/dist/src/review/diff-rules.js +35 -21
- package/dist/src/review/post-merge-review-render.js +9 -3
- package/dist/src/review/post-merge-review.js +48 -41
- package/dist/src/review/review-precheck.js +14 -4
- package/dist/src/review/review.js +48 -170
- package/dist/src/review/secret-leaks.js +26 -16
- package/dist/src/roles/legacy-role-migration.js +6 -3
- package/dist/src/roles/role-catalog.js +11 -3
- package/dist/src/roles/role-guidance.js +16 -12
- package/dist/src/roles/role-render.js +7 -46
- package/dist/src/roles/role-view.js +10 -33
- package/dist/src/run/acceptance-greps.js +88 -45
- package/dist/src/run/ci-parity.js +19 -8
- package/dist/src/run/run-apply.js +12 -15
- package/dist/src/run/run-detail-data.js +121 -68
- package/dist/src/run/run-detail-render.js +92 -35
- package/dist/src/run/run-detail.js +72 -41
- package/dist/src/run/run-prompt.js +63 -50
- package/dist/src/run/run-resume.js +76 -29
- package/dist/src/run/run-stage.js +141 -90
- package/dist/src/run/run-timing.js +8 -2
- package/dist/src/run/run-usage.js +31 -1
- package/dist/src/run/run-verdict.js +128 -50
- package/dist/src/run/stage-check.js +60 -50
- package/dist/src/run/stage-checks-shared.js +28 -0
- package/dist/src/run/stage-name-checks.js +111 -92
- package/dist/src/run/stage-path-checks.js +69 -42
- package/dist/src/run/stage-prose-checks.js +55 -40
- package/dist/src/runner/{leftover.js → runner-leftover.js} +9 -26
- package/dist/src/runner/runner-outcome.js +7 -2
- package/dist/src/runner/runner-pi.js +9 -22
- package/dist/src/runner/runner-recovery.js +5 -13
- package/dist/src/runner/{revision.js → runner-revision.js} +1 -2
- package/dist/src/runner/runner-run.js +103 -50
- package/dist/src/runner/runner-state-load.js +18 -28
- package/dist/src/runner/runner-state.js +0 -14
- package/dist/src/runner/runner.js +41 -25
- package/dist/src/scheduling/backoff.js +8 -3
- package/dist/src/scheduling/claim-entries.js +2 -1
- package/dist/src/scheduling/claims.js +0 -4
- package/dist/src/scheduling/scheduling.js +53 -66
- package/dist/src/status/status-budget.js +4 -43
- package/dist/src/status/status-data.js +35 -39
- package/dist/src/status/status-role-notes.js +2 -2
- package/dist/src/status/status-roles.js +9 -18
- package/dist/src/team/{error-storm.js → team-error-storm.js} +1 -1
- package/dist/src/team/{failure-spread.js → team-failure-spread.js} +5 -5
- package/dist/src/team/team-hold.js +105 -70
- package/dist/src/team/{orchestrator-info.js → team-orchestrator-info.js} +55 -36
- package/dist/src/team/team-polls.js +53 -201
- package/dist/src/team/{reclaim.js → team-reclaim.js} +61 -31
- package/dist/src/team/team-state.js +4 -13
- package/dist/src/text/datetime.js +16 -7
- package/dist/src/text/markdown.js +1 -1
- package/dist/src/text/phrases.js +29 -15
- package/dist/src/text/suggest.js +1 -1
- package/dist/src/text/text.js +6 -5
- package/dist/src/ui/alert-feeds.js +46 -111
- package/dist/src/ui/badges.js +17 -88
- package/dist/src/ui/gui/gui-client-boot.js +2 -8
- package/dist/src/ui/gui/gui-client-composer.js +1 -1
- package/dist/src/ui/gui/gui-client-drawer-config.js +8 -33
- package/dist/src/ui/gui/gui-client-drawer.js +1 -1
- package/dist/src/ui/gui/gui-client-feed.js +1 -1
- package/dist/src/ui/gui/gui-client-history.js +28 -14
- package/dist/src/ui/gui/gui-client-model.js +0 -12
- package/dist/src/ui/gui/gui-client-operator.js +7 -5
- package/dist/src/ui/gui/gui-client-pending.js +7 -6
- package/dist/src/ui/gui/gui-client-report-chart.js +5 -5
- package/dist/src/ui/gui/gui-client-report.js +1 -1
- package/dist/src/ui/gui/gui-client-roles.js +0 -1
- package/dist/src/ui/gui/gui-client-settings.js +43 -84
- package/dist/src/ui/gui/gui-client-team.js +12 -6
- package/dist/src/ui/gui/gui-client.js +7 -1
- package/dist/src/ui/progress-data.js +107 -44
- package/dist/src/ui/run-progress-model.js +20 -4
- package/dist/src/ui/status-model.js +2 -24
- package/dist/src/ui/status-payload.js +11 -30
- package/dist/src/ui/status-render.js +13 -24
- package/dist/src/ui/team-alert-backlog.js +14 -204
- package/dist/src/ui/team-alert-shared.js +6 -29
- package/dist/src/ui/team-alert-status.js +9 -170
- package/dist/src/ui/team-alert-tail.js +19 -215
- package/dist/src/ui/team-alerts.js +8 -15
- package/dist/src/ui/transcript-run.js +27 -16
- package/dist/src/ui/tui/tui-backlog.js +2 -2
- package/dist/src/ui/tui/tui-editor-answer.js +12 -10
- package/dist/src/ui/tui/tui-editor-attach.js +4 -3
- package/dist/src/ui/tui/tui-editor-backends.js +4 -3
- package/dist/src/ui/tui/tui-editor-brief.js +6 -9
- package/dist/src/ui/tui/tui-editor-budget.js +4 -3
- package/dist/src/ui/tui/tui-editor-config.js +80 -68
- package/dist/src/ui/tui/tui-editor-entry.js +12 -20
- package/dist/src/ui/tui/tui-editor-pause.js +51 -57
- package/dist/src/ui/tui/tui-editor-prompt.js +9 -13
- package/dist/src/ui/tui/tui-editor-queued.js +11 -14
- package/dist/src/ui/tui/tui-editor-quiet.js +4 -3
- package/dist/src/ui/tui/tui-editor-release.js +4 -3
- package/dist/src/ui/tui/tui-editor-retire.js +7 -7
- package/dist/src/ui/tui/tui-editor-role-enabled.js +4 -3
- package/dist/src/ui/tui/tui-editor-role-file.js +4 -4
- package/dist/src/ui/tui/tui-editor-role-key.js +4 -3
- package/dist/src/ui/tui/tui-editor-role-model.js +97 -15
- package/dist/src/ui/tui/tui-editor-search.js +4 -3
- package/dist/src/ui/tui/tui-editor-session.js +17 -4
- package/dist/src/ui/tui/tui-editors.js +5 -10
- package/dist/src/ui/tui/tui-frame.js +182 -134
- package/dist/src/ui/tui/tui-guard.js +20 -0
- package/dist/src/ui/tui/tui-input.js +167 -98
- package/dist/src/ui/tui/tui-keymap.js +51 -29
- package/dist/src/ui/tui/tui-keys.js +1 -1
- package/dist/src/ui/tui/tui-pane-activity.js +5 -4
- package/dist/src/ui/tui/tui-pane-backlog.js +74 -36
- package/dist/src/ui/tui/tui-pane-ctx.js +1 -1
- package/dist/src/ui/tui/tui-pane-health.js +252 -230
- package/dist/src/ui/tui/tui-pane-history.js +67 -74
- package/dist/src/ui/tui/tui-pane-pending.js +288 -247
- package/dist/src/ui/tui/tui-pane-queued.js +25 -27
- package/dist/src/ui/tui/tui-pane-report.js +2 -1
- package/dist/src/ui/tui/tui-pane-session.js +15 -10
- package/dist/src/ui/tui/tui-pane-transcript.js +19 -31
- package/dist/src/ui/tui/tui-pane.js +14 -11
- package/dist/src/ui/tui/tui-panes.js +38 -33
- package/dist/src/ui/tui/tui.js +4 -7
- package/dist/src/verdict/fix-claim.js +107 -56
- package/dist/src/verdict/refusal.js +1 -1
- package/dist/src/verdict/reply-contract.js +3 -4
- package/package.json +5 -5
- package/dist/src/concurrency/provider-lease.js +0 -105
- package/dist/src/review/review-followup.js +0 -87
- package/dist/src/review/review-run.js +0 -395
- package/dist/src/runner/model-fallback.js +0 -76
- package/dist/src/runner/runner-fallback.js +0 -66
- package/dist/src/ui/tui/tui-editor-claude-reserve.js +0 -24
- package/dist/src/ui/tui/tui-editor-provider-caps.js +0 -27
- /package/dist/src/cli/{brief-command.js → cli-brief-command.js} +0 -0
- /package/dist/src/doctor/{probe.js → doctor-probe.js} +0 -0
- /package/dist/src/gates/{disk-gate.js → disk-gates.js} +0 -0
- /package/dist/src/operator/{retire.js → operator-retire.js} +0 -0
- /package/dist/src/operator/{revert.js → operator-revert.js} +0 -0
|
@@ -44,88 +44,12 @@ export function tabStrip(view, width) {
|
|
|
44
44
|
spans.push({ text: " Ctrl+T next", tone: "dim" });
|
|
45
45
|
return clipSpans(spans, width);
|
|
46
46
|
}
|
|
47
|
-
/** The footer's key hints for what the keys do right now: keys bright, words dim.
|
|
47
|
+
/** The footer's key hints for what the keys do right now: keys bright, words dim. Which
|
|
48
|
+
* keys each editor offers is one table read (modeKeyHints), and which keys each pane offers is
|
|
49
|
+
* another (viewKeyHints); this function only looks those up, then spreads the chosen keys into
|
|
50
|
+
* the span line and clips it to the width. */
|
|
48
51
|
export function hintLine(view, mode, width) {
|
|
49
|
-
|
|
50
|
-
if (mode.entryEditFor?.position === null)
|
|
51
|
-
keys = [["Enter", `file ${mode.entryEditFor.kind}`], ["Ctrl+N", `switch to ${mode.entryEditFor.kind === "plan" ? "bug" : "plan"}`], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
52
|
-
else if (mode.entryEditFor)
|
|
53
|
-
keys = [["Enter", "save title"], ["Ctrl+E", "body file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
54
|
-
else if (mode.answerFor)
|
|
55
|
-
keys = [["Enter", "record answer"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
56
|
-
else if (mode.queuedEditFor)
|
|
57
|
-
keys = [["Enter", "save the edit"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
58
|
-
else if (mode.pauseEditMode && mode.pauseEditStop)
|
|
59
|
-
keys = [["Enter", "schedule stop"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
60
|
-
else if (mode.pauseEditMode)
|
|
61
|
-
keys = [["Enter", mode.pauseEditRole ? `${mode.pauseEditWake ? "wake" : "pause"} ${mode.pauseEditRole}` : "pause"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
62
|
-
else if (mode.attachMode)
|
|
63
|
-
keys = [["Enter", "attach image path"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
64
|
-
else if (mode.notesEditFor)
|
|
65
|
-
keys = [["Enter", "replace notes from file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
66
|
-
else if (mode.retireMode)
|
|
67
|
-
keys = [["Enter", "retire role"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
68
|
-
else if (mode.releaseMode)
|
|
69
|
-
keys = [["Enter", "release test"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
70
|
-
else if (mode.roleEnabledMode)
|
|
71
|
-
keys = [["Enter", "enable/disable role"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
72
|
-
else if (mode.budget)
|
|
73
|
-
keys = [["Enter", "save the daily cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
74
|
-
else if (mode.concurrencyMode)
|
|
75
|
-
keys = [["Enter", "save the run cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
76
|
-
else if (mode.checksMode)
|
|
77
|
-
keys = [["Enter", "save the check cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
78
|
-
else if (mode.checkMode)
|
|
79
|
-
keys = [["Enter", "save the declared check"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
80
|
-
else if (mode.modelMode)
|
|
81
|
-
keys = [["Enter", "save the model"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
82
|
-
else if (mode.quietMode)
|
|
83
|
-
keys = [["Enter", mode.quietTeam ? "save team quiet hours" : "save quiet hours"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
84
|
-
else if (mode.intervalMode)
|
|
85
|
-
keys = [["Enter", "save interval"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
86
|
-
else if (mode.roleModelMode)
|
|
87
|
-
keys = [["Enter", "save role model"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
88
|
-
else if (mode.instancesMode)
|
|
89
|
-
keys = [["Enter", "save instances"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
90
|
-
else if (mode.providerCapsMode)
|
|
91
|
-
keys = [["Enter", "save provider caps"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
92
|
-
else if (mode.claudeReserveMode)
|
|
93
|
-
keys = [["Enter", "save claude reserve"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
94
|
-
else if (mode.notifyMode)
|
|
95
|
-
keys = [["Enter", "save the notify hook"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
96
|
-
else if (mode.fallbackMode)
|
|
97
|
-
keys = [["Enter", "save the fallback"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
98
|
-
else if (mode.instructionsEditFor)
|
|
99
|
-
keys = [["Enter", "save instructions"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
100
|
-
else if (mode.slotsMode)
|
|
101
|
-
keys = [["Enter", "save worktree slots"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
102
|
-
else if (mode.backendsMode)
|
|
103
|
-
keys = [["Enter", "save agent backends"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
104
|
-
else if (mode.rolePromptFor)
|
|
105
|
-
keys = [["Enter", `send to ${mode.rolePromptFor}`], ["↑↓", "history"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
106
|
-
else if (mode.briefEditMode)
|
|
107
|
-
keys = [["Enter", "replace brief from file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]];
|
|
108
|
-
else if (view.kind === "transcript") {
|
|
109
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["Ctrl+R", `prompt ${view.role}`], ["Ctrl+N", view.note ? "change" : view.change ? "transcript" : "notes"], ...(view.change ? [["Ctrl+Y", view.changeStat ? "full patch" : "stat only"]] : []), ...(view.note ? [["Ctrl+X", "clear notes"], ["Ctrl+E", "edit notes"]] : [["Ctrl+X", "role model"]]), ["Ctrl+P", "pause/resume"], ["Ctrl+W", "wake"], ["Ctrl+A", "stop run"], ["Ctrl+V", "reset counters"], ["Ctrl+B", "daily cap"], ["Ctrl+O", "quiet hours"], ["Ctrl+G", "instances"], ["Ctrl+S", "min run interval"], ["Ctrl+L", "instructions"],
|
|
110
|
-
...(!view.note && !view.change ? [["/", view.grep ? `search: ${view.grep}` : "search"]] : []),
|
|
111
|
-
["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
112
|
-
}
|
|
113
|
-
else if (view.kind === "backlog")
|
|
114
|
-
keys = [["Enter", "send"], ["↑↓", "open entries"], ["/", "search entries"], ["Ctrl+O", "ready only"], ["Ctrl+X", "cancel entry"], ["Ctrl+R", "release entry"], ["Ctrl+V", "top entry"], ["Ctrl+E", "edit entry"], ["Ctrl+N", "new plan/bug"], ["Ctrl+A", "answer question"], ["PgUp/PgDn", "scroll"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
115
|
-
else if (view.kind === "usage" || view.kind === "failures")
|
|
116
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+G", view.scope ? `scope: ${view.scope}` : "scope: team"], ["Ctrl+E", view.window ? `window: ${view.window}` : "window: default"], ...(view.window ? [["Ctrl+P", "earlier window"]] : []), ...(view.kind === "failures" ? [["Ctrl+X", "release test"]] : []), ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
117
|
-
else if (view.kind === "history")
|
|
118
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["Ctrl+L", "newest failure"], ["PgUp/PgDn", "scroll"], ["Ctrl+G", view.role ? `scope: ${view.role}` : "scope: team"], ["Ctrl+S", view.since ? `window: ${view.since}` : "window: default"], ...(!view.trail && view.since ? [["Ctrl+P", "earlier window"]] : []), ["Ctrl+O", view.result ? `result: ${view.result}` : "result: all"], ["Ctrl+X", view.model ? `model: ${view.model}` : "model: all"], ["Ctrl+Y", view.summary === "model" ? "rows" : view.summary === "role" ? "by model" : "summary"], ["Ctrl+N", view.trail ? "history" : "run trail"], ...(view.trail ? [["Ctrl+P", "older run"], ["Ctrl+R", view.trailTranscript === "plain" ? "prompts" : view.trailTranscript === "prompts" ? "hide transcript" : "transcript"], ["Ctrl+W", view.trailPatch ? "hide patch" : "patch"], ["Ctrl+V", "revert run"]] : []), ["/", view.trail && view.trailTranscript !== undefined && view.trailTranscript !== "off" ? (view.trailGrep ? `transcript search: ${view.trailGrep}` : "search transcript") : (view.grep ? `search: ${view.grep}` : "search")], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
119
|
-
else if (view.kind === "pending")
|
|
120
|
-
keys = [["Enter", "send"], ["↑↓", "select merge/review"], ["PgUp/PgDn", "scroll"], ["Ctrl+R", "refresh"], ["Ctrl+N", "overlaps"], ["Ctrl+G", "overlap role"], ["Ctrl+O", "review state"], ["Ctrl+X", "cancel merge"], ["Ctrl+V", "move to top"], ["Ctrl+A", "accept review"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
121
|
-
else if (view.kind === "health")
|
|
122
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+O", view.problems ? "problems only" : "all checks"], ["Ctrl+R", "re-run checks"], ["Ctrl+A", "commit backlog"], ["Ctrl+U", "re-sync install"], ["Ctrl+E", "reclaim disk"], ["Ctrl+N", "test notify"], ["Ctrl+K", "kill orphans"], ["Ctrl+S", "drop broken pins"], ["Ctrl+X", "retire role"], ["Ctrl+L", "retire leftovers"], ["Ctrl+B", "archive backlog"], ["Ctrl+V", "enable/disable role"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
123
|
-
else if (view.kind === "brief")
|
|
124
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+E", "edit brief"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
125
|
-
else if (view.kind === "queued")
|
|
126
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["Ctrl+V", "top"], ["Ctrl+E", "edit"], ["Ctrl+X", "cancel"], ["/", view.grep ? `search: ${view.grep}` : "search"], ["PgUp/PgDn", "scroll"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
127
|
-
else
|
|
128
|
-
keys = [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+B", "daily cap"], ["Ctrl+E", "notify hook"], ["Ctrl+A", "model"], ["Ctrl+N", "run cap"], ["Ctrl+K", "check cap"], ["Ctrl+U", "declared check"], ["Ctrl+S", "quiet hours"], ["Ctrl+W", "worktree slots"], ["Ctrl+O", view.notable ? "notable only" : view.type ? `type: ${eventTypeLabel(view.type)}` : "type: all"], ["Ctrl+G", view.role ? `scope: ${view.role}` : "scope: team"], ["/", view.grep ? `search: ${view.grep}` : "search"], ["Ctrl+P", "provider caps"], ["Ctrl+X", "agent backends"], ["Ctrl+T", "next view"], ["Ctrl+L", "fallback"], ["Ctrl+Y", "claude reserve"], ["Ctrl+F", "pause team"], ["Ctrl+Q", "stop later"], ["Ctrl+C", "interrupt director"], ["Ctrl+V", "attach image"], ["Ctrl+R", "restart"], ["Ctrl+D", "quit"]];
|
|
52
|
+
const keys = modeKeyHints(mode) ?? viewKeyHints(view);
|
|
129
53
|
// The mode branches above name their own keys and keep the line, so every remaining
|
|
130
54
|
// view hint always shows the send affordance. This comment marks that ordering.
|
|
131
55
|
const spans = [];
|
|
@@ -136,60 +60,184 @@ export function hintLine(view, mode, width) {
|
|
|
136
60
|
});
|
|
137
61
|
return clipSpans(spans, width);
|
|
138
62
|
}
|
|
139
|
-
/** The
|
|
63
|
+
/** The ordered table that owns footer key-hint precedence among editors: each row's first
|
|
64
|
+
* element is one editor/mode arm and the second the keys it shows; the first truthy row wins,
|
|
65
|
+
* so "which keys does this editor offer?" is one read of the table's order. The order is the
|
|
66
|
+
* old `if (mode.…)` chain, from the new-entry editor to the brief editor. Returns undefined
|
|
67
|
+
* when no editor is active, so the caller falls through to the view table. */
|
|
68
|
+
function modeKeyHints(mode) {
|
|
69
|
+
// The object-armed rows below dereference their target (entry/answer/queued), so each
|
|
70
|
+
// captures the value and guards its keys against the null case — the array is built eagerly
|
|
71
|
+
// for every row, but only ever returned when its row's flag is truthy.
|
|
72
|
+
const entry = mode.entryEditFor;
|
|
73
|
+
const answer = mode.answerFor;
|
|
74
|
+
const queued = mode.queuedEditFor;
|
|
75
|
+
const rows = [
|
|
76
|
+
[entry?.position === null, entry ? [["Enter", `file ${entry.kind}`], ["Ctrl+N", `switch to ${entry.kind === "plan" ? "bug" : "plan"}`], ["Esc", "cancel"], ["Ctrl+D", "quit"]] : []],
|
|
77
|
+
[entry, entry ? [["Enter", "save title"], ["Ctrl+E", "body file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]] : []],
|
|
78
|
+
[answer, answer ? [["Enter", "record answer"], ["Esc", "cancel"], ["Ctrl+D", "quit"]] : []],
|
|
79
|
+
[queued, queued ? [["Enter", "save the edit"], ["Esc", "cancel"], ["Ctrl+D", "quit"]] : []],
|
|
80
|
+
[mode.pauseEditMode && mode.pauseEditStop, [["Enter", "schedule stop"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
81
|
+
[mode.pauseEditMode, [["Enter", mode.pauseEditRole ? `${mode.pauseEditWake ? "wake" : "pause"} ${mode.pauseEditRole}` : "pause"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
82
|
+
[mode.attachMode, [["Enter", "attach image path"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
83
|
+
[mode.notesEditFor, [["Enter", "replace notes from file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
84
|
+
[mode.retireMode, [["Enter", "retire role"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
85
|
+
[mode.releaseMode, [["Enter", "release test"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
86
|
+
[mode.roleEnabledMode, [["Enter", "enable/disable role"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
87
|
+
[mode.budget, [["Enter", "save the daily cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
88
|
+
[mode.concurrencyMode, [["Enter", "save the run cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
89
|
+
[mode.checksMode, [["Enter", "save the check cap"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
90
|
+
[mode.checkMode, [["Enter", "save the declared check"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
91
|
+
[mode.modelMode, [["Enter", "save the model"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
92
|
+
[mode.quietMode, [["Enter", mode.quietTeam ? "save team quiet hours" : "save quiet hours"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
93
|
+
[mode.intervalMode, [["Enter", "save interval"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
94
|
+
[mode.roleModelMode, [["Enter", "save model overrides"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
95
|
+
[mode.instancesMode, [["Enter", "save instances"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
96
|
+
[mode.notifyMode, [["Enter", "save the notify hook"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
97
|
+
[mode.fallbackMode, [["Enter", "save the fallback"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
98
|
+
[mode.instructionsEditFor, [["Enter", "save instructions"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
99
|
+
[mode.slotsMode, [["Enter", "save worktree slots"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
100
|
+
[mode.backendsMode, [["Enter", "save agent backends"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
101
|
+
[mode.rolePromptFor, [["Enter", `send to ${mode.rolePromptFor}`], ["↑↓", "history"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
102
|
+
[mode.briefEditMode, [["Enter", "replace brief from file"], ["Esc", "cancel"], ["Ctrl+D", "quit"]]],
|
|
103
|
+
];
|
|
104
|
+
for (const [active, keys] of rows)
|
|
105
|
+
if (active)
|
|
106
|
+
return keys;
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
/** The ordered table that owns footer key-hint precedence among panes: each row's first element
|
|
110
|
+
* is one view predicate and the second the keys that pane shows; the first truthy row wins, so
|
|
111
|
+
* "which keys does this pane offer?" is one read of the table's order. The order is the old
|
|
112
|
+
* `else if (view.kind === …)` chain, from transcript to the default activity row. */
|
|
113
|
+
function viewKeyHints(view) {
|
|
114
|
+
// Each row's second element is guarded by the same predicate as its first so the viewer is
|
|
115
|
+
// narrowed to that pane's variant when the keys are built (the array is eager), mirroring
|
|
116
|
+
// the object-armed rows in modeKeyHints.
|
|
117
|
+
const rows = [
|
|
118
|
+
[view.kind === "transcript", view.kind === "transcript" ? transcriptKeyHints(view) : []],
|
|
119
|
+
[view.kind === "backlog", backlogKeyHints()],
|
|
120
|
+
[view.kind === "usage" || view.kind === "failures", (view.kind === "usage" || view.kind === "failures") ? usageKeyHints(view) : []],
|
|
121
|
+
[view.kind === "history", view.kind === "history" ? historyKeyHints(view) : []],
|
|
122
|
+
[view.kind === "pending", pendingKeyHints()],
|
|
123
|
+
[view.kind === "health", view.kind === "health" ? healthKeyHints(view) : []],
|
|
124
|
+
[view.kind === "brief", briefKeyHints()],
|
|
125
|
+
[view.kind === "queued", view.kind === "queued" ? queuedKeyHints(view) : []],
|
|
126
|
+
[true, activityKeyHints(view)],
|
|
127
|
+
];
|
|
128
|
+
for (const [active, keys] of rows)
|
|
129
|
+
if (active)
|
|
130
|
+
return keys;
|
|
131
|
+
return activityKeyHints(view);
|
|
132
|
+
}
|
|
133
|
+
/** The transcript pane's keys: the send/history affordance, the per-role prompt, and the
|
|
134
|
+
* toggles and editors that act on the open transcript or change. */
|
|
135
|
+
function transcriptKeyHints(view) {
|
|
136
|
+
return [["Enter", "send"], ["↑↓", "history"], ["Ctrl+R", `prompt ${view.role}`], ["Ctrl+N", view.note ? "change" : view.change ? "transcript" : "notes"], ...(view.change ? [["Ctrl+Y", view.changeStat ? "full patch" : "stat only"]] : []), ...(view.note ? [["Ctrl+X", "clear notes"], ["Ctrl+E", "edit notes"]] : [["Ctrl+X", "model overrides"]]), ["Ctrl+P", "pause/resume"], ["Ctrl+W", "wake"], ["Ctrl+A", "stop run"], ["Ctrl+V", "reset counters"], ["Ctrl+B", "daily cap"], ["Ctrl+O", "quiet hours"], ["Ctrl+G", "instances"], ["Ctrl+S", "min run interval"], ["Ctrl+L", "instructions"],
|
|
137
|
+
...(!view.note && !view.change ? [["/", view.grep ? `search: ${view.grep}` : "search"]] : []),
|
|
138
|
+
["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
139
|
+
}
|
|
140
|
+
/** The backlog pane's keys: entry selection, search, and the per-entry actions. */
|
|
141
|
+
function backlogKeyHints() {
|
|
142
|
+
return [["Enter", "send"], ["↑↓", "open entries"], ["/", "search entries"], ["Ctrl+O", "ready only"], ["Ctrl+X", "cancel entry"], ["Ctrl+R", "release entry"], ["Ctrl+V", "top entry"], ["Ctrl+E", "edit entry"], ["Ctrl+N", "new plan/bug"], ["Ctrl+A", "answer question"], ["PgUp/PgDn", "scroll"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
143
|
+
}
|
|
144
|
+
/** The usage/failures pane's keys: the history navigation, scope and window, and the failure
|
|
145
|
+
* digest's release affordance. */
|
|
146
|
+
function usageKeyHints(view) {
|
|
147
|
+
return [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+G", view.scope ? `scope: ${view.scope}` : "scope: team"], ["Ctrl+E", view.window ? `window: ${view.window}` : "window: default"], ...(view.window ? [["Ctrl+P", "earlier window"]] : []), ...(view.kind === "failures" ? [["Ctrl+X", "release test"]] : []), ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
148
|
+
}
|
|
149
|
+
/** The completed-run history pane's keys: outcome filters, the run trail's navigation, and
|
|
150
|
+
* the search pair delegated to historySearchHint so this table stays under the threshold. */
|
|
151
|
+
function historyKeyHints(view) {
|
|
152
|
+
return [["Enter", "send"], ["↑↓", "history"], ["Ctrl+L", "newest failure"], ["PgUp/PgDn", "scroll"], ["Ctrl+G", view.role ? `scope: ${view.role}` : "scope: team"], ["Ctrl+S", view.since ? `window: ${view.since}` : "window: default"], ...(!view.trail && view.since ? [["Ctrl+P", "earlier window"]] : []), ["Ctrl+O", view.result ? `result: ${view.result}` : "result: all"], ["Ctrl+X", view.model ? `model: ${view.model}` : "model: all"], ["Ctrl+Y", view.summary === "model" ? "rows" : view.summary === "role" ? "by model" : "summary"], ["Ctrl+N", view.trail ? "history" : "run trail"], ...(view.trail ? [["Ctrl+P", "older run"], ["Ctrl+R", view.trailTranscript === "plain" ? "prompts" : view.trailTranscript === "prompts" ? "hide transcript" : "transcript"], ["Ctrl+W", view.trailPatch ? "hide patch" : "patch"], ["Ctrl+V", "revert run"]] : []), historySearchHint(view), ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
153
|
+
}
|
|
154
|
+
/** The history pane's trailing search pair: `/[search]` naming what the forward slash searches,
|
|
155
|
+
* the transcript search while a run trail is open and its transcript is readable, else the
|
|
156
|
+
* plain entry search. Kept as its own helper so the history table stays under the threshold. */
|
|
157
|
+
function historySearchHint(view) {
|
|
158
|
+
return ["/", view.trail && view.trailTranscript !== undefined && view.trailTranscript !== "off" ? (view.trailGrep ? `transcript search: ${view.trailGrep}` : "search transcript") : (view.grep ? `search: ${view.grep}` : "search")];
|
|
159
|
+
}
|
|
160
|
+
/** The pending-change roster's keys: merge/review selection and the review actions. */
|
|
161
|
+
function pendingKeyHints() {
|
|
162
|
+
return [["Enter", "send"], ["↑↓", "select merge/review"], ["PgUp/PgDn", "scroll"], ["Ctrl+R", "refresh"], ["Ctrl+N", "overlaps"], ["Ctrl+G", "overlap role"], ["Ctrl+O", "review state"], ["Ctrl+X", "cancel merge"], ["Ctrl+V", "move to top"], ["Ctrl+A", "accept review"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
163
|
+
}
|
|
164
|
+
/** The health pane's keys: the checks, install, and backlog maintenance actions. */
|
|
165
|
+
function healthKeyHints(view) {
|
|
166
|
+
return [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+O", view.problems ? "problems only" : "all checks"], ["Ctrl+R", "re-run checks"], ["Ctrl+A", "commit backlog"], ["Ctrl+U", "re-sync install"], ["Ctrl+E", "reclaim disk"], ["Ctrl+N", "test notify"], ["Ctrl+K", "kill orphans"], ["Ctrl+S", "drop broken pins"], ["Ctrl+X", "retire role"], ["Ctrl+L", "retire leftovers"], ["Ctrl+B", "archive backlog"], ["Ctrl+V", "enable/disable role"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
167
|
+
}
|
|
168
|
+
/** The brief pane's keys: the send affordance and the brief editor. */
|
|
169
|
+
function briefKeyHints() {
|
|
170
|
+
return [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+E", "edit brief"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
171
|
+
}
|
|
172
|
+
/** The queued-prompt pane's keys: the queue navigation, the edit/cancel actions, and search. */
|
|
173
|
+
function queuedKeyHints(view) {
|
|
174
|
+
return [["Enter", "send"], ["↑↓", "history"], ["Ctrl+V", "top"], ["Ctrl+E", "edit"], ["Ctrl+X", "cancel"], ["/", view.grep ? `search: ${view.grep}` : "search"], ["PgUp/PgDn", "scroll"], ["Ctrl+T", "next view"], ["Ctrl+D", "quit"]];
|
|
175
|
+
}
|
|
176
|
+
/** The default activity pane's keys (the old `else` arm): the run controls, the scope/type
|
|
177
|
+
* filters, search, and the team-wide actions every other pane's hints sit on top of. */
|
|
178
|
+
function activityKeyHints(view) {
|
|
179
|
+
// notable/type exist only on the activity view, so each access is narrowed by kind before
|
|
180
|
+
// use — the array is built eagerly for the table's last (always-matching) row, but the
|
|
181
|
+
// default activity arm is the only caller that reads these fields.
|
|
182
|
+
const activity = view.kind === "activity";
|
|
183
|
+
return [["Enter", "send"], ["↑↓", "history"], ["PgUp/PgDn", "scroll"], ["Ctrl+B", "daily cap"], ["Ctrl+E", "notify hook"], ["Ctrl+A", "model"], ["Ctrl+N", "run cap"], ["Ctrl+K", "check cap"], ["Ctrl+U", "declared check"], ["Ctrl+S", "quiet hours"], ["Ctrl+W", "worktree slots"], ["Ctrl+O", activity && view.notable ? "notable only" : activity && view.type ? `type: ${eventTypeLabel(view.type)}` : "type: all"], ["Ctrl+G", activity && view.role ? `scope: ${view.role}` : "scope: team"], ["/", activity && view.grep ? `search: ${view.grep}` : "search"], ["Ctrl+X", "agent backends"], ["Ctrl+T", "next view"], ["Ctrl+L", "fallback"], ["Ctrl+F", "pause team"], ["Ctrl+Q", "stop later"], ["Ctrl+C", "interrupt director"], ["Ctrl+V", "attach image"], ["Ctrl+R", "restart"], ["Ctrl+D", "quit"]];
|
|
184
|
+
}
|
|
185
|
+
/** The brand-tone label pair that names the prompting target on the prompt line, with the
|
|
186
|
+
* ` › ` separator nearly every editor arm uses — the budget arm is the lone exception, its
|
|
187
|
+
* trailing space keeping the input in the cap field's own line. */
|
|
188
|
+
function labeledPrefix(label) {
|
|
189
|
+
return [{ text: label, tone: "brand" }, { text: " › " }];
|
|
190
|
+
}
|
|
191
|
+
/** The ordered label table that owns prompt-line prefix precedence: each row's first element is
|
|
192
|
+
* one editor/mode arm and the second the prefix it shows; the first truthy row wins, so "which
|
|
193
|
+
* editor owns the prefix, and if two flags are set which one?" is one read of the table's
|
|
194
|
+
* order. The order is the old `if (mode.…)` chain, from the daily-cap editor to the pause
|
|
195
|
+
* editor. */
|
|
196
|
+
function editorPromptPrefix(mode) {
|
|
197
|
+
// The three object-armed rows below dereference their target (entry/answer/queued), so each
|
|
198
|
+
// captures the value and guards its label against the null case — the label is built eagerly
|
|
199
|
+
// for every row, but only ever returned when its row's flag is truthy.
|
|
200
|
+
const entry = mode.entryEditFor;
|
|
201
|
+
const answer = mode.answerFor;
|
|
202
|
+
const queued = mode.queuedEditFor;
|
|
203
|
+
const prompts = [
|
|
204
|
+
[mode.budget, [{ text: "daily cap $", tone: "brand" }, { text: " " }]],
|
|
205
|
+
[mode.concurrencyMode, labeledPrefix("run cap")],
|
|
206
|
+
[mode.checksMode, labeledPrefix("check cap")],
|
|
207
|
+
[mode.checkMode, labeledPrefix("declared check")],
|
|
208
|
+
[mode.modelMode, labeledPrefix("model")],
|
|
209
|
+
[mode.quietMode, labeledPrefix(mode.quietTeam ? "team quiet hours" : "quiet hours")],
|
|
210
|
+
[mode.slotsMode, labeledPrefix("worktree slots")],
|
|
211
|
+
[mode.backendsMode, labeledPrefix("agent backends")],
|
|
212
|
+
[mode.intervalMode, labeledPrefix("min run interval")],
|
|
213
|
+
[mode.roleModelMode, labeledPrefix("model overrides")],
|
|
214
|
+
[mode.instancesMode, labeledPrefix("instances")],
|
|
215
|
+
[mode.notifyMode, labeledPrefix("notify hook")],
|
|
216
|
+
[mode.fallbackMode, labeledPrefix("fallback")],
|
|
217
|
+
[mode.instructionsEditFor, labeledPrefix(`instructions for ${mode.instructionsEditFor}`)],
|
|
218
|
+
[mode.briefEditMode, labeledPrefix("brief")],
|
|
219
|
+
[mode.retireMode, labeledPrefix("retire")],
|
|
220
|
+
[mode.releaseMode, labeledPrefix("release")],
|
|
221
|
+
[mode.roleEnabledMode, labeledPrefix("role state")],
|
|
222
|
+
[mode.notesEditFor, labeledPrefix(`notes for ${mode.notesEditFor}`)],
|
|
223
|
+
[entry, entry ? labeledPrefix(entry.position === null ? `new ${entry.kind}` : `edit ${entry.kind} #${entry.position}`) : []],
|
|
224
|
+
[answer, answer ? labeledPrefix(`answer #${answer.position}`) : []],
|
|
225
|
+
[queued, queued ? labeledPrefix(`edit ${queued.role}`) : []],
|
|
226
|
+
[mode.pauseEditMode && mode.pauseEditStop, labeledPrefix("stop in")],
|
|
227
|
+
[mode.pauseEditMode, labeledPrefix(mode.pauseEditRole ? `${mode.pauseEditWake ? "wake" : "pause"} ${mode.pauseEditRole}` : "pause")],
|
|
228
|
+
];
|
|
229
|
+
for (const [active, spans] of prompts)
|
|
230
|
+
if (active)
|
|
231
|
+
return spans;
|
|
232
|
+
return undefined;
|
|
233
|
+
}
|
|
234
|
+
/** The prompt line's target, like the dashboard composer's: who Enter sends to, read from the
|
|
235
|
+
* ordered label table in editorPromptPrefix and falling back to the director/role target (with
|
|
236
|
+
* its image count) when no editor owns the prefix. */
|
|
140
237
|
export function promptPrefix(mode) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return [{ text: "run cap", tone: "brand" }, { text: " › " }];
|
|
145
|
-
if (mode.checksMode)
|
|
146
|
-
return [{ text: "check cap", tone: "brand" }, { text: " › " }];
|
|
147
|
-
if (mode.checkMode)
|
|
148
|
-
return [{ text: "declared check", tone: "brand" }, { text: " › " }];
|
|
149
|
-
if (mode.modelMode)
|
|
150
|
-
return [{ text: "model", tone: "brand" }, { text: " › " }];
|
|
151
|
-
if (mode.quietMode)
|
|
152
|
-
return [{ text: mode.quietTeam ? "team quiet hours" : "quiet hours", tone: "brand" }, { text: " › " }];
|
|
153
|
-
if (mode.slotsMode)
|
|
154
|
-
return [{ text: "worktree slots", tone: "brand" }, { text: " › " }];
|
|
155
|
-
if (mode.backendsMode)
|
|
156
|
-
return [{ text: "agent backends", tone: "brand" }, { text: " › " }];
|
|
157
|
-
if (mode.intervalMode)
|
|
158
|
-
return [{ text: "min run interval", tone: "brand" }, { text: " › " }];
|
|
159
|
-
if (mode.roleModelMode)
|
|
160
|
-
return [{ text: "role model", tone: "brand" }, { text: " › " }];
|
|
161
|
-
if (mode.instancesMode)
|
|
162
|
-
return [{ text: "instances", tone: "brand" }, { text: " › " }];
|
|
163
|
-
if (mode.providerCapsMode)
|
|
164
|
-
return [{ text: "provider caps", tone: "brand" }, { text: " › " }];
|
|
165
|
-
if (mode.claudeReserveMode)
|
|
166
|
-
return [{ text: "claude reserve", tone: "brand" }, { text: " › " }];
|
|
167
|
-
if (mode.notifyMode)
|
|
168
|
-
return [{ text: "notify hook", tone: "brand" }, { text: " › " }];
|
|
169
|
-
if (mode.fallbackMode)
|
|
170
|
-
return [{ text: "fallback", tone: "brand" }, { text: " › " }];
|
|
171
|
-
if (mode.instructionsEditFor)
|
|
172
|
-
return [{ text: `instructions for ${mode.instructionsEditFor}`, tone: "brand" }, { text: " › " }];
|
|
173
|
-
if (mode.briefEditMode)
|
|
174
|
-
return [{ text: "brief", tone: "brand" }, { text: " › " }];
|
|
175
|
-
if (mode.retireMode)
|
|
176
|
-
return [{ text: "retire", tone: "brand" }, { text: " › " }];
|
|
177
|
-
if (mode.releaseMode)
|
|
178
|
-
return [{ text: "release", tone: "brand" }, { text: " › " }];
|
|
179
|
-
if (mode.roleEnabledMode)
|
|
180
|
-
return [{ text: "role state", tone: "brand" }, { text: " › " }];
|
|
181
|
-
if (mode.notesEditFor)
|
|
182
|
-
return [{ text: `notes for ${mode.notesEditFor}`, tone: "brand" }, { text: " › " }];
|
|
183
|
-
if (mode.entryEditFor)
|
|
184
|
-
return [{ text: mode.entryEditFor.position === null ? `new ${mode.entryEditFor.kind}` : `edit ${mode.entryEditFor.kind} #${mode.entryEditFor.position}`, tone: "brand" }, { text: " › " }];
|
|
185
|
-
if (mode.answerFor)
|
|
186
|
-
return [{ text: `answer #${mode.answerFor.position}`, tone: "brand" }, { text: " › " }];
|
|
187
|
-
if (mode.queuedEditFor)
|
|
188
|
-
return [{ text: `edit ${mode.queuedEditFor.role}`, tone: "brand" }, { text: " › " }];
|
|
189
|
-
if (mode.pauseEditMode && mode.pauseEditStop)
|
|
190
|
-
return [{ text: "stop in", tone: "brand" }, { text: " › " }];
|
|
191
|
-
if (mode.pauseEditMode)
|
|
192
|
-
return [{ text: mode.pauseEditRole ? `${mode.pauseEditWake ? "wake" : "pause"} ${mode.pauseEditRole}` : "pause", tone: "brand" }, { text: " › " }];
|
|
238
|
+
const prefix = editorPromptPrefix(mode);
|
|
239
|
+
if (prefix)
|
|
240
|
+
return prefix;
|
|
193
241
|
// The pending image count (e.g. `director (2 images) › `) is named beside the target, so
|
|
194
242
|
// the user sees what the next Enter will send before pressing it. The image count names the
|
|
195
243
|
// director prompt only: session.images ride into the next director submit (submitPrompt),
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Run `fn` and, on a throw, flash the reason on the session instead of letting it escape a
|
|
2
|
+
* keypress or sync handler and kill the TUI. The one home of the try/catch every TUI editor
|
|
3
|
+
* or pane with a disk or marker write used to declare locally, so their guards cannot drift;
|
|
4
|
+
* the session is structural — any widget exposing `flashError(err: unknown)`. */
|
|
5
|
+
export function guardError(session, fn) {
|
|
6
|
+
try {
|
|
7
|
+
fn();
|
|
8
|
+
}
|
|
9
|
+
catch (err) {
|
|
10
|
+
session.flashError(err);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** The rejection handler every TUI async write passes as the second argument of `.then(onOk, …)`:
|
|
14
|
+
* flash the thrown reason on the session instead of dropping it. The one home of the
|
|
15
|
+
* `(err: unknown) => session.flashError(err)` arrows the editors and panes used to inline per
|
|
16
|
+
* call site, so their guards cannot drift; the session is structural — any widget exposing
|
|
17
|
+
* `flashError(err: unknown)` (same contract as guardError). */
|
|
18
|
+
export function flashReject(session) {
|
|
19
|
+
return (err) => session.flashError(err);
|
|
20
|
+
}
|