tumwater 0.4.0 → 0.4.2
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 +4 -6
- package/dist/build-info.json +2 -2
- package/dist/src/agent/agent-backend.js +5 -2
- package/dist/src/agent/backend-traits.js +21 -0
- package/dist/src/agent/claude/claude-backend.js +1 -1
- package/dist/src/agent/claude/claude-stream.js +181 -182
- package/dist/src/agent/claude/{write-guard-hook.js → claude-write-guard-hook.js} +1 -1
- package/dist/src/agent/claude/claude-write-guard.js +5 -4
- package/dist/src/agent/codex/codex-backend.js +1 -1
- package/dist/src/agent/codex/codex-rollout.js +48 -45
- package/dist/src/agent/codex/codex-stream.js +269 -215
- package/dist/src/agent/codex/{write-guard-hook.js → codex-write-guard-hook.js} +2 -1
- package/dist/src/agent/codex/codex-write-guard.js +3 -3
- package/dist/src/agent/image-input.js +18 -87
- package/dist/src/agent/notes-shim.js +2 -2
- package/dist/src/agent/opencode/opencode-backend.js +2 -2
- package/dist/src/agent/opencode/opencode-catalog.js +2 -2
- package/dist/src/agent/opencode/opencode-config.js +2 -2
- package/dist/src/agent/opencode/opencode-stream.js +101 -92
- package/dist/src/agent/run-agent.js +76 -382
- package/dist/src/agent/run-settle.js +25 -15
- package/dist/src/agent/run-spawn.js +226 -0
- package/dist/src/agent/run-stream.js +185 -0
- package/dist/src/agent/session-ledger.js +16 -0
- package/dist/src/agent/write-guard.js +5 -3
- package/dist/src/backlog/backlog-archive.js +86 -170
- package/dist/src/backlog/backlog-cli-view.js +89 -70
- package/dist/src/backlog/backlog-eligibility.js +51 -59
- package/dist/src/backlog/backlog-file-bugs.js +133 -0
- package/dist/src/backlog/backlog-index-data.js +159 -0
- package/dist/src/backlog/backlog-index.js +7 -5
- package/dist/src/backlog/backlog-md.js +39 -28
- package/dist/src/backlog/backlog-release.js +21 -36
- package/dist/src/backlog/backlog-render.js +1 -1
- package/dist/src/backlog/backlog-structure.js +14 -145
- package/dist/src/backlog/backlog-write.js +31 -18
- package/dist/src/backlog/backlog.js +14 -4
- package/dist/src/backlog/question-answer.js +33 -15
- package/dist/src/baseline/main-baseline.js +71 -26
- package/dist/src/baseline/main-guardrails.js +76 -15
- package/dist/src/baseline/main-red.js +45 -94
- package/dist/src/baseline/main-watch.js +9 -3
- package/dist/src/brief/brief.js +40 -0
- package/dist/src/budget/budget-fallback-view.js +50 -8
- package/dist/src/budget/budget-wiring.js +15 -11
- package/dist/src/budget/budget.js +3 -2
- package/dist/src/build/build-check-events.js +4 -2
- package/dist/src/build/build-check-report.js +2 -1
- package/dist/src/build/build-check-scoped.js +70 -41
- package/dist/src/change/change-data.js +4 -2
- package/dist/src/cli/cli-args.js +9 -0
- package/dist/src/cli/cli-command-args.js +199 -98
- package/dist/src/cli/cli-flag-specs.js +6 -4
- package/dist/src/cli/cli-marker-commands.js +2 -2
- package/dist/src/cli/cli-query-commands.js +41 -6
- package/dist/src/cli/cli-review-commands.js +2 -1
- package/dist/src/cli/cli-role-command.js +46 -92
- package/dist/src/cli/cli-start.js +123 -47
- package/dist/src/cli/follow-view.js +3 -1
- package/dist/src/cli/help.js +19 -12
- package/dist/src/cli/log-commands.js +128 -107
- package/dist/src/cli/question-commands.js +82 -63
- package/dist/src/cli.js +396 -343
- package/dist/src/collections.js +46 -9
- package/dist/src/config/config-fallbacks.js +0 -4
- package/dist/src/config/config-live.js +179 -147
- package/dist/src/config/config-request.js +176 -51
- package/dist/src/config/config-validation-roles.js +271 -0
- package/dist/src/config/config-validation.js +10 -205
- package/dist/src/config/config-views.js +2 -7
- package/dist/src/config/config-write.js +205 -175
- package/dist/src/config/config.js +2 -1
- package/dist/src/doctor/doctor-backlog-bugs.js +24 -122
- package/dist/src/doctor/doctor-backlog-plans.js +24 -25
- package/dist/src/doctor/doctor-backlog.js +34 -42
- package/dist/src/doctor/doctor-check-names.js +4 -2
- package/dist/src/doctor/doctor-checks.js +16 -4
- package/dist/src/doctor/doctor-claude-checks.js +2 -2
- package/dist/src/doctor/doctor-codex-checks.js +9 -20
- package/dist/src/doctor/doctor-contention-checks.js +52 -19
- package/dist/src/doctor/doctor-holds.js +22 -20
- package/dist/src/doctor/doctor-model-checks.js +8 -184
- package/dist/src/doctor/doctor-notify.js +2 -5
- package/dist/src/doctor/doctor-opencode-checks.js +90 -41
- package/dist/src/doctor/doctor-principles.js +26 -0
- package/dist/src/doctor/doctor-project-checks.js +69 -19
- package/dist/src/doctor/doctor-role-notes.js +33 -0
- package/dist/src/doctor/doctor.js +13 -6
- package/dist/src/doctor/probe.js +1 -1
- package/dist/src/events/event-format.js +307 -162
- package/dist/src/events/event-labels.js +0 -1
- package/dist/src/events/event-legacy.js +1 -1
- package/dist/src/events/event-window.js +1 -1
- package/dist/src/events/events.js +15 -2
- package/dist/src/events/notify.js +1 -1
- package/dist/src/failure/failure-cluster.js +4 -3
- package/dist/src/failure/failure-data.js +126 -94
- package/dist/src/failure/failure-render.js +58 -17
- package/dist/src/failure/failure-state-change.js +308 -27
- package/dist/src/failure/time-spend.js +139 -106
- package/dist/src/files/files.js +7 -0
- package/dist/src/files/json-object.js +15 -2
- package/dist/src/gates/budget-gates.js +90 -68
- package/dist/src/gates/gate-polls.js +92 -61
- package/dist/src/gates/role-cap-gates.js +1 -1
- package/dist/src/gates/startup-gate.js +28 -28
- package/dist/src/gates/streak-gate.js +1 -1
- package/dist/src/git/git.js +1 -1
- package/dist/src/git/slot-salvage.js +9 -9
- package/dist/src/git/slots-state.js +12 -3
- package/dist/src/git/worktree-pool-startup.js +127 -0
- package/dist/src/git/worktree-pool.js +1 -120
- package/dist/src/gui/gui-admin-endpoints.js +3 -4
- package/dist/src/gui/gui-args.js +1 -1
- package/dist/src/gui/gui-backlog-commands.js +20 -11
- package/dist/src/gui/gui-backlog-endpoints.js +2 -8
- package/dist/src/gui/gui-config-commands.js +51 -76
- package/dist/src/gui/gui-endpoint-commands.js +4 -2
- package/dist/src/gui/gui-endpoint-common.js +4 -3
- package/dist/src/gui/gui-history-endpoints.js +36 -27
- package/dist/src/gui/gui-operator-commands.js +43 -17
- package/dist/src/gui/gui-prompt-commands.js +27 -21
- package/dist/src/gui/gui-quarantine-commands.js +30 -0
- package/dist/src/gui/gui-report-endpoints.js +13 -9
- package/dist/src/gui/gui-server.js +5 -3
- package/dist/src/gui/gui-team-commands.js +1 -1
- package/dist/src/history/history-data.js +7 -1
- package/dist/src/history/history-render.js +15 -10
- package/dist/src/history/history.js +103 -68
- package/dist/src/inbox/inbox-submit.js +1 -5
- package/dist/src/inbox/pending-prompt.js +3 -2
- package/dist/src/inbox/prompt-commands.js +194 -161
- package/dist/src/init/init.js +104 -25
- package/dist/src/merge/merge-core.js +1 -1
- package/dist/src/merge/merge-drain.js +1 -1
- package/dist/src/merge/merge-git.js +5 -5
- package/dist/src/merge/{merge-post-review.js → merge-post-review-drain.js} +1 -1
- package/dist/src/merge/merge-queue.js +2 -1
- package/dist/src/merge/merge-to-main.js +1 -1
- package/dist/src/merge/merge-verify.js +3 -2
- package/dist/src/operator/operator-commands.js +84 -52
- package/dist/src/operator/operator-intent.js +26 -3
- package/dist/src/operator/retire.js +2 -1
- package/dist/src/operator/revert.js +18 -12
- package/dist/src/orchestrator/orchestrator-poll.js +2 -2
- package/dist/src/orchestrator/orchestrator.js +1 -1
- package/dist/src/orchestrator/retention.js +6 -5
- package/dist/src/paths.js +10 -10
- package/dist/src/pi/pi-bin.js +2 -2
- package/dist/src/pi/pi-models.js +9 -0
- package/dist/src/pi/pi-stream.js +63 -41
- package/dist/src/pi/pi-watchdogs.js +84 -49
- package/dist/src/pi-extension/context-shake.js +55 -31
- package/dist/src/pi-extension/full-output.js +2 -3
- package/dist/src/process/process.js +24 -1
- package/dist/src/process/run-marker.js +2 -2
- package/dist/src/process/supervisor.js +24 -5
- package/dist/src/prompt/gate-notes.js +41 -16
- package/dist/src/prompt/notes-backlog.js +22 -29
- package/dist/src/prompt/principles.js +11 -0
- package/dist/src/prompt/prompt-followup.js +4 -12
- package/dist/src/prompt/prompt.js +15 -12
- package/dist/src/redeploy/redeploy-probes.js +11 -1
- package/dist/src/redeploy/redeployer.js +54 -7
- package/dist/src/redeploy/self-reload.js +7 -2
- package/dist/src/report/report-data.js +224 -320
- package/dist/src/report/report-fold.js +23 -231
- package/dist/src/report/report-main-red.js +70 -3
- package/dist/src/report/report-render.js +181 -48
- package/dist/src/report/report-since-data.js +218 -0
- package/dist/src/report/report-usage-fold.js +288 -0
- package/dist/src/report/report.js +2 -1
- package/dist/src/review/known-flakes.js +22 -3
- package/dist/src/review/post-merge-review-accept.js +3 -2
- package/dist/src/review/post-merge-review.js +16 -14
- package/dist/src/review/quarantine-render.js +29 -11
- package/dist/src/review/review-precheck.js +2 -1
- package/dist/src/roles/role-catalog.js +30 -29
- package/dist/src/roles/role-guidance.js +26 -43
- package/dist/src/roles/role-render.js +19 -0
- package/dist/src/roles/role-view.js +19 -5
- package/dist/src/roles/roles.js +2 -22
- package/dist/src/run/ci-parity.js +5 -6
- package/dist/src/run/feedback-filings.js +10 -1
- package/dist/src/run/qa-coverage.js +4 -4
- package/dist/src/run/run-apply.js +14 -2
- package/dist/src/run/run-detail-data.js +50 -10
- package/dist/src/run/run-detail-render.js +32 -1
- package/dist/src/run/run-detail.js +44 -22
- package/dist/src/run/run-dismiss.js +43 -0
- package/dist/src/run/run-finalize.js +75 -46
- package/dist/src/run/run-prompt.js +271 -187
- package/dist/src/run/run-resume.js +32 -31
- package/dist/src/run/run-stage.js +116 -64
- package/dist/src/run/run-timing.js +18 -4
- package/dist/src/run/run-verdict.js +119 -83
- package/dist/src/run/stage-backlog-checks.js +4 -31
- package/dist/src/run/stage-check.js +4 -12
- package/dist/src/run/stage-checks-shared.js +15 -0
- package/dist/src/run/stage-name-checks.js +3 -13
- package/dist/src/run/stage-path-checks.js +26 -29
- package/dist/src/runner/leftover.js +13 -4
- package/dist/src/runner/revision.js +2 -2
- package/dist/src/runner/runner-fallback.js +1 -1
- package/dist/src/runner/runner-outcome.js +0 -5
- package/dist/src/runner/runner-pi.js +72 -49
- package/dist/src/runner/runner-run.js +19 -102
- package/dist/src/runner/runner-state-load.js +0 -10
- package/dist/src/runner/runner.js +1 -32
- package/dist/src/scheduling/claims.js +4 -11
- package/dist/src/status/status-data.js +140 -91
- package/dist/src/status/status-polls.js +41 -5
- package/dist/src/status/status-role-notes.js +53 -0
- package/dist/src/status/status-roles.js +10 -37
- package/dist/src/text/datetime.js +8 -1
- package/dist/src/text/format.js +13 -1
- package/dist/src/text/phrases.js +16 -2
- package/dist/src/text/text.js +12 -0
- package/dist/src/ui/alert-feeds.js +115 -0
- package/dist/src/ui/badges.js +3 -4
- package/dist/src/ui/gui/gui-client-boot.js +78 -57
- package/dist/src/ui/gui/gui-client-drawer-config.js +8 -3
- package/dist/src/ui/gui/gui-client-drawer.js +18 -2
- package/dist/src/ui/gui/gui-client-feed.js +3 -8
- package/dist/src/ui/gui/gui-client-history.js +16 -16
- package/dist/src/ui/gui/gui-client-model.js +9 -9
- package/dist/src/ui/gui/gui-client-operator.js +6 -10
- package/dist/src/ui/gui/gui-client-pending.js +4 -4
- package/dist/src/ui/gui/gui-client-report-chart.js +111 -10
- package/dist/src/ui/gui/gui-client-report.js +70 -11
- package/dist/src/ui/gui/gui-client-roles.js +52 -12
- package/dist/src/ui/gui/gui-client-settings.js +31 -26
- package/dist/src/ui/gui/gui-client-team.js +28 -2
- package/dist/src/ui/gui/gui-client.js +33 -4
- package/dist/src/ui/gui/gui-icons.js +7 -1
- package/dist/src/ui/progress-data.js +2 -2
- package/dist/src/ui/run-progress-model.js +2 -2
- package/dist/src/ui/status-model.js +26 -16
- package/dist/src/ui/status-payload.js +149 -326
- package/dist/src/ui/status-render.js +131 -80
- package/dist/src/ui/team-alert-backlog.js +236 -0
- package/dist/src/ui/team-alert-shared.js +92 -0
- package/dist/src/ui/team-alert-status.js +326 -0
- package/dist/src/ui/team-alert-tail.js +238 -0
- package/dist/src/ui/team-alerts.js +16 -984
- package/dist/src/ui/transcript-tail.js +137 -94
- package/dist/src/ui/tui/tui-backlog.js +1 -1
- package/dist/src/ui/tui/tui-editor-answer.js +54 -44
- package/dist/src/ui/tui/tui-editor-attach.js +74 -63
- package/dist/src/ui/tui/tui-editor-backends.js +62 -56
- package/dist/src/ui/tui/tui-editor-brief.js +64 -54
- package/dist/src/ui/tui/tui-editor-budget.js +106 -89
- package/dist/src/ui/tui/tui-editor-config.js +2 -4
- package/dist/src/ui/tui/tui-editor-ctx.js +12 -1
- package/dist/src/ui/tui/tui-editor-entry.js +171 -153
- package/dist/src/ui/tui/tui-editor-instances.js +2 -1
- package/dist/src/ui/tui/tui-editor-instructions.js +50 -107
- package/dist/src/ui/tui/tui-editor-interval.js +39 -112
- package/dist/src/ui/tui/tui-editor-notes.js +28 -84
- package/dist/src/ui/tui/tui-editor-pause.js +210 -183
- package/dist/src/ui/tui/tui-editor-prompt.js +46 -35
- package/dist/src/ui/tui/tui-editor-queued.js +74 -64
- package/dist/src/ui/tui/tui-editor-quiet.js +122 -108
- package/dist/src/ui/tui/tui-editor-release.js +85 -0
- package/dist/src/ui/tui/tui-editor-retire.js +57 -46
- package/dist/src/ui/tui/tui-editor-role-enabled.js +90 -80
- package/dist/src/ui/tui/tui-editor-role-file.js +87 -0
- package/dist/src/ui/tui/tui-editor-role-key.js +50 -42
- package/dist/src/ui/tui/tui-editor-search.js +70 -58
- package/dist/src/ui/tui/tui-editor-session.js +3 -0
- package/dist/src/ui/tui/tui-editors.js +4 -1
- package/dist/src/ui/tui/tui-frame.js +7 -3
- package/dist/src/ui/tui/tui-history.js +12 -10
- package/dist/src/ui/tui/tui-keys.js +6 -1
- package/dist/src/ui/tui/tui-pane-activity.js +62 -50
- package/dist/src/ui/tui/tui-pane-backlog.js +4 -4
- package/dist/src/ui/tui/tui-pane-ctx.js +1 -1
- package/dist/src/ui/tui/tui-pane-health.js +45 -26
- package/dist/src/ui/tui/tui-pane-history.js +296 -264
- package/dist/src/ui/tui/tui-pane-report.js +74 -57
- package/dist/src/ui/tui/tui-pane-session.js +6 -2
- package/dist/src/ui/tui/tui-pane-transcript.js +158 -131
- package/dist/src/ui/tui/tui-pane.js +201 -174
- package/dist/src/ui/tui/tui-panes.js +211 -148
- package/dist/src/ui/tui/tui.js +4 -4
- package/dist/src/verdict/fix-claim.js +18 -6
- package/dist/src/verdict/refusal.js +32 -7
- package/package.json +1 -1
- package/dist/src/doctor/image-probe.js +0 -257
- /package/dist/src/gui/{http-body.js → gui-http-body.js} +0 -0
- /package/dist/src/merge/{backlog-conflicts.js → merge-backlog-conflicts.js} +0 -0
|
@@ -8,21 +8,23 @@
|
|
|
8
8
|
import { runRowCells } from "../../history/history-data.js";
|
|
9
9
|
/** The pane body for a set of run rows: `time role #run result duration`, then `model`
|
|
10
10
|
* (between the result and the duration), and `usage` and `detail` when they carry anything,
|
|
11
|
-
* joined newest-first by newlines.
|
|
12
|
-
* home the CLI's table builds on too, so a
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
11
|
+
* joined newest-first by newlines. Both the result and the duration cells come from
|
|
12
|
+
* history-data.ts's runRowCells, the one home the CLI's table builds on too, so a run cut
|
|
13
|
+
* off at its model's context ceiling reads `no change (cut off)` here the way it does in
|
|
14
|
+
* `history`, and a null `durationMs` (the run's start sits outside the scanned window)
|
|
15
|
+
* shows the em dash the same way; an empty `model` (the start named none or sat outside
|
|
16
|
+
* the window), an empty `usage` (neither tokens nor cost), and an empty `detail` are
|
|
17
|
+
* omitted rather than leaving a gap. No rows renders `""`, which the pane's `emptyNote`
|
|
18
|
+
* replaces. The result cell goes through eventTypeLabel exactly as the CLI table's does,
|
|
19
|
+
* so a merged run's resolved verdict and a `no_change` read the same label in both. */
|
|
18
20
|
export function historyPaneText(rows) {
|
|
19
21
|
return rows
|
|
20
22
|
.map((row) => {
|
|
21
|
-
const
|
|
22
|
-
const parts = [row.time, `${row.role} #${row.run}`,
|
|
23
|
+
const cells = runRowCells(row);
|
|
24
|
+
const parts = [row.time, `${row.role} #${row.run}`, cells.result];
|
|
23
25
|
if (row.model)
|
|
24
26
|
parts.push(row.model);
|
|
25
|
-
parts.push(duration);
|
|
27
|
+
parts.push(cells.duration);
|
|
26
28
|
if (row.usage)
|
|
27
29
|
parts.push(row.usage);
|
|
28
30
|
if (row.detail)
|
|
@@ -4,7 +4,9 @@ import { runDoctor } from "../../doctor/doctor.js";
|
|
|
4
4
|
import { killOrphans } from "../../doctor/doctor-orphans.js";
|
|
5
5
|
import { dropBrokenPins, retireLeftovers } from "../../doctor/doctor-contention-checks.js";
|
|
6
6
|
import { commitUncommittedBacklog } from "../../doctor/doctor-backlog.js";
|
|
7
|
+
import { archiveFinishedOnMain } from "../../backlog/backlog-archive.js";
|
|
7
8
|
import { loadConfigSafe } from "../../config/config.js";
|
|
9
|
+
import { MERGE_LOCK_WAIT_MS } from "../../paths.js";
|
|
8
10
|
import { commitOperatorBacklogEdit } from "../../backlog/backlog-commit.js";
|
|
9
11
|
import { stampedSubject } from "../../git/commit-message.js";
|
|
10
12
|
import { previewRevert, revertMergedCommit } from "../../operator/revert.js";
|
|
@@ -35,11 +37,12 @@ export function createTuiKeys(deps) {
|
|
|
35
37
|
const { root } = deps;
|
|
36
38
|
const collectPending = deps.collectPending ?? collectTeamChanges;
|
|
37
39
|
const collectOverlaps = deps.collectOverlaps ?? collectChangeOverlaps;
|
|
38
|
-
const runDoctorSeam = deps.runDoctor ?? ((r
|
|
40
|
+
const runDoctorSeam = deps.runDoctor ?? ((r) => runDoctor(r));
|
|
39
41
|
const killOrphansSeam = deps.killOrphans ?? ((r) => killOrphans(r));
|
|
40
42
|
const dropBrokenPinsSeam = deps.dropBrokenPins ?? ((r) => dropBrokenPins(r));
|
|
41
43
|
const retireLeftoversSeam = deps.retireLeftovers ?? ((r) => retireLeftovers(r, loadConfigSafe(r).config));
|
|
42
44
|
const commitBacklogSeam = deps.commitBacklog ?? ((r) => commitUncommittedBacklog(r, loadConfigSafe(r).config));
|
|
45
|
+
const archiveBacklogSeam = deps.archiveBacklog ?? ((r) => archiveFinishedOnMain(r, { lockTimeoutMs: MERGE_LOCK_WAIT_MS }));
|
|
43
46
|
const previewRevertSeam = deps.previewRevert ?? previewRevert;
|
|
44
47
|
const revertCommit = deps.revertCommit ?? revertMergedCommit;
|
|
45
48
|
const collectChange = deps.collectChange ?? collectRoleChange;
|
|
@@ -89,6 +92,7 @@ export function createTuiKeys(deps) {
|
|
|
89
92
|
dropBrokenPins: dropBrokenPinsSeam,
|
|
90
93
|
retireLeftovers: retireLeftoversSeam,
|
|
91
94
|
commitBacklog: commitBacklogSeam,
|
|
95
|
+
archiveBacklog: archiveBacklogSeam,
|
|
92
96
|
previewRevert: previewRevertSeam,
|
|
93
97
|
revertCommit,
|
|
94
98
|
collectChange,
|
|
@@ -108,6 +112,7 @@ export function createTuiKeys(deps) {
|
|
|
108
112
|
refreshQueued: panes.refreshQueued,
|
|
109
113
|
refreshNotes: panes.refreshNotes,
|
|
110
114
|
refreshBrief: panes.refreshBrief,
|
|
115
|
+
refreshReport: panes.refreshReport,
|
|
111
116
|
clearBacklogSelection: panes.clearBacklogSelection,
|
|
112
117
|
applyHistorySearch: panes.applyHistorySearch,
|
|
113
118
|
applyActivitySearch: panes.applyActivitySearch,
|
|
@@ -39,58 +39,70 @@ export function createActivityPane(session) {
|
|
|
39
39
|
activityGrep = pattern;
|
|
40
40
|
activityScroll = null;
|
|
41
41
|
};
|
|
42
|
+
/** Ctrl+G arm: the Activity feed scopes over the same raw roster ids, so `feature-2` is its
|
|
43
|
+
* own slot; the filter reads exact role ids through eventRole. The scroll resets because its
|
|
44
|
+
* offset indexed the old (unfiltered or differently filtered) list. */
|
|
45
|
+
const activityScopeCycle = (ctx) => {
|
|
46
|
+
if (!promptLineFree(ctx.es))
|
|
47
|
+
return false;
|
|
48
|
+
const slots = [null, ...session.roleIds];
|
|
49
|
+
const slot = slots.indexOf(activityRole);
|
|
50
|
+
activityRole = slots[(slot + 1) % slots.length] ?? null;
|
|
51
|
+
activityScroll = null;
|
|
52
|
+
session.requestRender();
|
|
53
|
+
return true;
|
|
54
|
+
};
|
|
55
|
+
/** Ctrl+O arm: the Activity type/notable cycle: all → notable → first present type → … → last
|
|
56
|
+
* present type → all. `present` is built from the pre-type read (type `null`, no notable
|
|
57
|
+
* cull), so every type stays reachable once one is selected — the same reason the dashboard
|
|
58
|
+
* builds its chip set before its type filter. The scroll resets because its offset indexed
|
|
59
|
+
* the old filtered list. */
|
|
60
|
+
const activityTypeCycle = (ctx) => {
|
|
61
|
+
if (!promptLineFree(ctx.es))
|
|
62
|
+
return false;
|
|
63
|
+
const present = [...new Set(activityEvents(session.root, activityRole, activityGrep, null).map((e) => e.type))].sort();
|
|
64
|
+
const slots = [
|
|
65
|
+
{ notable: false, type: null },
|
|
66
|
+
{ notable: true, type: null },
|
|
67
|
+
...present.map((t) => ({ notable: false, type: t })),
|
|
68
|
+
];
|
|
69
|
+
const idx = slots.findIndex((s) => s.notable === activityNotable && s.type === activityType);
|
|
70
|
+
const next = slots[(idx + 1) % slots.length] ?? slots[0];
|
|
71
|
+
activityNotable = next.notable;
|
|
72
|
+
activityType = next.type;
|
|
73
|
+
activityScroll = null;
|
|
74
|
+
session.requestRender();
|
|
75
|
+
return true;
|
|
76
|
+
};
|
|
77
|
+
/** PgUp/PgDn arm: the Activity pane keeps the live tail by default; PgUp pauses follow and
|
|
78
|
+
* pages back through the loaded event tail, PgDn returns toward it and re-enables follow once
|
|
79
|
+
* the window reaches the tail. Both directions clamp to [0, total - rows], and a log with
|
|
80
|
+
* rows or fewer events stays on the tail. `rows` is the feed's window height — one body
|
|
81
|
+
* line short of eventBudget while the tally line is drawn (its paneBody twin, the
|
|
82
|
+
* `rows = Math.max(1, eventBudget - tallyLine.length)` in tui-pane.ts) — so each page
|
|
83
|
+
* advances exactly as far as the feed displays and no event is skipped or unreachable
|
|
84
|
+
* while paging. The read is the pane's own fixed tail term (and active role/text
|
|
85
|
+
* filter), so it hits readEvents' stat cache rather than rescanning the log. */
|
|
86
|
+
const activityTailPage = (page) => {
|
|
87
|
+
if (session.view !== 0)
|
|
88
|
+
return false;
|
|
89
|
+
const total = activityEvents(session.root, activityRole, activityGrep, activityType, activityNotable).length;
|
|
90
|
+
const rows = total === 0 ? session.eventBudget : Math.max(1, session.eventBudget - 1);
|
|
91
|
+
const maxStart = Math.max(0, total - rows);
|
|
92
|
+
const current = activityScroll ?? maxStart;
|
|
93
|
+
const next = stepEntryScroll(current, total, rows, page);
|
|
94
|
+
activityScroll = next >= maxStart ? null : next;
|
|
95
|
+
session.requestRender();
|
|
96
|
+
return true;
|
|
97
|
+
};
|
|
42
98
|
const handleKey = (key, ctx) => {
|
|
43
|
-
if (key.ctrl && key.name === "g"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const slots = [null, ...session.roleIds];
|
|
48
|
-
const slot = slots.indexOf(activityRole);
|
|
49
|
-
activityRole = slots[(slot + 1) % slots.length] ?? null;
|
|
50
|
-
activityScroll = null;
|
|
51
|
-
session.requestRender();
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
if (key.ctrl && key.name === "o" && promptLineFree(ctx.es)) {
|
|
55
|
-
// The Activity type/notable cycle: all → notable → first present type → … → last present
|
|
56
|
-
// type → all. `present` is built from the pre-type read (type `null`, no notable cull), so
|
|
57
|
-
// every type stays reachable once one is selected — the same reason the dashboard builds
|
|
58
|
-
// its chip set before its type filter. The scroll resets because its offset indexed the
|
|
59
|
-
// old filtered list.
|
|
60
|
-
const present = [...new Set(activityEvents(session.root, activityRole, activityGrep, null).map((e) => e.type))].sort();
|
|
61
|
-
const slots = [
|
|
62
|
-
{ notable: false, type: null },
|
|
63
|
-
{ notable: true, type: null },
|
|
64
|
-
...present.map((t) => ({ notable: false, type: t })),
|
|
65
|
-
];
|
|
66
|
-
const idx = slots.findIndex((s) => s.notable === activityNotable && s.type === activityType);
|
|
67
|
-
const next = slots[(idx + 1) % slots.length] ?? slots[0];
|
|
68
|
-
activityNotable = next.notable;
|
|
69
|
-
activityType = next.type;
|
|
70
|
-
activityScroll = null;
|
|
71
|
-
session.requestRender();
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
99
|
+
if (key.ctrl && key.name === "g")
|
|
100
|
+
return activityScopeCycle(ctx);
|
|
101
|
+
if (key.ctrl && key.name === "o")
|
|
102
|
+
return activityTypeCycle(ctx);
|
|
74
103
|
const page = pageDir(key.name);
|
|
75
|
-
if (page !== null
|
|
76
|
-
|
|
77
|
-
// through the loaded event tail, PgDn returns toward it and re-enables follow once the
|
|
78
|
-
// window reaches the tail. Both directions clamp to [0, total - rows], and a log with
|
|
79
|
-
// rows or fewer events stays on the tail. `rows` is the feed's window height — one body
|
|
80
|
-
// line short of eventBudget while the tally line is drawn (its paneBody twin, the
|
|
81
|
-
// `rows = Math.max(1, eventBudget - tallyLine.length)` in tui-pane.ts) — so each page
|
|
82
|
-
// advances exactly as far as the feed displays and no event is skipped or unreachable
|
|
83
|
-
// while paging. The read is the pane's own fixed tail term (and active role/text
|
|
84
|
-
// filter), so it hits readEvents' stat cache rather than rescanning the log.
|
|
85
|
-
const total = activityEvents(session.root, activityRole, activityGrep, activityType, activityNotable).length;
|
|
86
|
-
const rows = total === 0 ? session.eventBudget : Math.max(1, session.eventBudget - 1);
|
|
87
|
-
const maxStart = Math.max(0, total - rows);
|
|
88
|
-
const current = activityScroll ?? maxStart;
|
|
89
|
-
const next = stepEntryScroll(current, total, rows, page);
|
|
90
|
-
activityScroll = next >= maxStart ? null : next;
|
|
91
|
-
session.requestRender();
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
104
|
+
if (page !== null)
|
|
105
|
+
return activityTailPage(page);
|
|
94
106
|
return false;
|
|
95
107
|
};
|
|
96
108
|
return {
|
|
@@ -137,7 +137,7 @@ export function createBacklogPane(session) {
|
|
|
137
137
|
session.flashMessage(outcome.status === "released"
|
|
138
138
|
? `released ${kind} #${position}: ${outcome.title} (lifted ${liftedNotePhrase(outcome.lifted)})${heldTail}`
|
|
139
139
|
: outcome.status === "not_refused"
|
|
140
|
-
? `that ${kind} carries no Refused
|
|
140
|
+
? `that ${kind} carries no Refused note`
|
|
141
141
|
: `that ${kind} was already removed or moved — nothing released`);
|
|
142
142
|
}
|
|
143
143
|
catch (err) {
|
|
@@ -202,7 +202,7 @@ export function createBacklogPane(session) {
|
|
|
202
202
|
if (key.ctrl && key.name === "r" &&
|
|
203
203
|
promptLineFree(ctx.es) &&
|
|
204
204
|
session.view === session.roleIds.length + 1) {
|
|
205
|
-
// Ctrl+R twice releases the Refused
|
|
205
|
+
// Ctrl+R twice releases the Refused
|
|
206
206
|
// note on the selected plan or bug through the non-exiting core the dashboard drawer
|
|
207
207
|
// uses; the title check inside tryReleaseEntry refuses a stale selection. Releasing is the
|
|
208
208
|
// terminal twin of `tumwater plan|bug --release <n>`: it lifts the note, commits the file
|
|
@@ -212,8 +212,8 @@ export function createBacklogPane(session) {
|
|
|
212
212
|
const kind = selected.kind;
|
|
213
213
|
const position = selected.position;
|
|
214
214
|
const target = { kind, position, title: selected.picked.title };
|
|
215
|
-
if (selected.picked.hold !== "refused"
|
|
216
|
-
session.flashMessage(`that ${kind} carries no Refused
|
|
215
|
+
if (selected.picked.hold !== "refused") {
|
|
216
|
+
session.flashMessage(`that ${kind} carries no Refused note`);
|
|
217
217
|
}
|
|
218
218
|
else if (session.armedRelease !== null && session.armedRelease.kind === kind && session.armedRelease.position === position) {
|
|
219
219
|
// The armed title (not the re-read one) goes to tryReleaseEntry, so an entry that
|
|
@@ -6,6 +6,6 @@
|
|
|
6
6
|
export function promptLineFree(es) {
|
|
7
7
|
return (!es.budgetMode && !es.rolePromptFor && !es.searchMode &&
|
|
8
8
|
!es.pauseEditMode && !es.queuedEditFor && !es.answerFor && !es.entryEditFor &&
|
|
9
|
-
!es.notesEditFor && !es.briefEditMode && !es.retireMode && !es.roleEnabledMode && !es.quietMode && !es.intervalMode &&
|
|
9
|
+
!es.notesEditFor && !es.briefEditMode && !es.retireMode && !es.releaseMode && !es.roleEnabledMode && !es.quietMode && !es.intervalMode &&
|
|
10
10
|
!es.roleModelMode && !es.instructionsEditFor && !es.claudeReserveMode);
|
|
11
11
|
}
|
|
@@ -5,11 +5,13 @@ import { runManualReclaim } from "../../operator/operator-intent.js";
|
|
|
5
5
|
import { testNotifyHook } from "../../cli/notify-command.js";
|
|
6
6
|
import { resyncRootInstall, rootInstallResyncLines } from "../../build/dep-install.js";
|
|
7
7
|
import { brokenPinDropLines, leftoverRetireLines } from "../../doctor/doctor-contention-checks.js";
|
|
8
|
+
import { describeArchivedFile } from "../../backlog/backlog-archive.js";
|
|
9
|
+
import { shortSha } from "../../text/format.js";
|
|
8
10
|
import { promptLineFree } from "./tui-pane-ctx.js";
|
|
9
11
|
/** The Health pane (view roleIds.length + 7) of the TUI (src/ui/tui/tui.tsx): the problems-only
|
|
10
|
-
* Ctrl+O toggle, the Ctrl+
|
|
11
|
-
* collector it re-reads on every entry. Split out of the
|
|
12
|
-
* problems flag and the last resolved report. */
|
|
12
|
+
* Ctrl+O toggle, the Ctrl+A commit-backlog, the Ctrl+B
|
|
13
|
+
* backlog archive, and the runDoctor collector it re-reads on every entry. Split out of the
|
|
14
|
+
* pane-navigation monolith; it owns the problems flag and the last resolved report. */
|
|
13
15
|
export function createHealthPane(session) {
|
|
14
16
|
// Within the Health pane (Ctrl+O), whether the cached report paints only its warn and fail
|
|
15
17
|
// checks, the same problems-only trim `tumwater doctor --problems` applies. Session-only
|
|
@@ -24,16 +26,14 @@ export function createHealthPane(session) {
|
|
|
24
26
|
// current. Extracted so both the enter half of the Ctrl+T cycle and the Ctrl+R in-place
|
|
25
27
|
// refresh run the same body; a run already in flight is superseded by the new read.
|
|
26
28
|
let runGen = 0;
|
|
27
|
-
|
|
28
|
-
let reprobing = false;
|
|
29
|
-
const run = (probeImages = "never") => {
|
|
29
|
+
const run = () => {
|
|
30
30
|
// Generation guard: each run bumps the counter, and a resolution paints only if it is
|
|
31
31
|
// the latest request's — Ctrl+R held twice, or a re-run raced with a re-entry, must not
|
|
32
32
|
// let an out-of-order older resolution overwrite the newer report.
|
|
33
33
|
const gen = ++runGen;
|
|
34
34
|
session.paneCache = null;
|
|
35
35
|
lastDoctorReport = null;
|
|
36
|
-
return session.runDoctor(session.root
|
|
36
|
+
return session.runDoctor(session.root).then((report) => {
|
|
37
37
|
if (gen !== runGen || session.view !== session.roleIds.length + 7)
|
|
38
38
|
return;
|
|
39
39
|
lastDoctorReport = report;
|
|
@@ -57,25 +57,6 @@ export function createHealthPane(session) {
|
|
|
57
57
|
session.requestRender();
|
|
58
58
|
return true;
|
|
59
59
|
}
|
|
60
|
-
if (key.ctrl && key.name === "p" && promptLineFree(ctx.es) && session.view === session.roleIds.length + 7) {
|
|
61
|
-
// Ctrl+P on the Health pane (mnemonic: **P**robe) is the terminal twin of `tumwater doctor
|
|
62
|
-
// --reprobe` and the dashboard's Re-probe models: it re-runs the checks with every claimed
|
|
63
|
-
// pi image-input model re-probed, spending one model call each and rewriting
|
|
64
|
-
// .tumwater/state/image-probes.json. Every other view keeps its own Ctrl+P.
|
|
65
|
-
if (reprobing) {
|
|
66
|
-
session.flashMessage("a re-probe is already running");
|
|
67
|
-
session.requestRender();
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
reprobing = true;
|
|
71
|
-
session.flashMessage("re-probing image-input models (one model call each) …");
|
|
72
|
-
void run("all").finally(() => {
|
|
73
|
-
reprobing = false;
|
|
74
|
-
});
|
|
75
|
-
session.paneScroll = 0;
|
|
76
|
-
session.requestRender();
|
|
77
|
-
return true;
|
|
78
|
-
}
|
|
79
60
|
if (key.ctrl && key.name === "e" && promptLineFree(ctx.es) && session.view === session.roleIds.length + 7) {
|
|
80
61
|
// Ctrl+E on the Health pane runs one manual reclaim pass now — the terminal twin of the
|
|
81
62
|
// dashboard disk row's reclaim button and the core `tumwater reclaim`, both reached
|
|
@@ -253,6 +234,44 @@ export function createHealthPane(session) {
|
|
|
253
234
|
});
|
|
254
235
|
return true;
|
|
255
236
|
}
|
|
237
|
+
if (key.ctrl && key.name === "b" && promptLineFree(ctx.es) && (ctx.es.input ?? "") === "" && session.view === session.roleIds.length + 7) {
|
|
238
|
+
// Ctrl+B on the Health pane, pressed twice, archives the finished entries still under
|
|
239
|
+
// PLANS.md's ## Done and BUGS.md's ## Fixed into PLANS-DONE.md and BUGS-FIXED.md and
|
|
240
|
+
// commits them on the base branch — the terminal twin of `tumwater archive` and the
|
|
241
|
+
// dashboard Health card's Archive backlog, all reached through the same archiveFinished-.
|
|
242
|
+
// OnMain. The first press only arms (beginKey disarms on any other key) and flashes what
|
|
243
|
+
// a second press does; the second flashes the same lines the CLI prints, joined with
|
|
244
|
+
// "; " (the nothing line verbatim when there is nothing to archive), then re-runs the
|
|
245
|
+
// checks so the `backlog archive` row reflects the move. A failure flashes instead of
|
|
246
|
+
// killing the TUI. Ctrl+B stays the prompt-line editor's line-kill (budget editor) while
|
|
247
|
+
// text is typed or an editor holds the line, and is unbound on every other view.
|
|
248
|
+
if (!session.armedArchiveBacklog) {
|
|
249
|
+
session.archiveBacklogArmed = true;
|
|
250
|
+
session.flashMessage("press Ctrl+B again to archive the finished entries under PLANS.md ## Done and BUGS.md ## Fixed — any other key keeps them");
|
|
251
|
+
session.requestRender();
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
session.flashMessage("archiving finished backlog entries …");
|
|
255
|
+
session.requestRender();
|
|
256
|
+
void session.archiveBacklog(session.root).then((outcome) => {
|
|
257
|
+
if (outcome.status === "nothing") {
|
|
258
|
+
session.flashMessage("nothing to archive: PLANS.md ## Done and BUGS.md ## Fixed hold no finished entries");
|
|
259
|
+
}
|
|
260
|
+
else if (outcome.status === "skipped") {
|
|
261
|
+
session.flashMessage(`nothing archived: ${outcome.reason}`);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
session.flashMessage([...outcome.moved.map(describeArchivedFile), `committed ${shortSha(outcome.commit)}`].join("; "));
|
|
265
|
+
}
|
|
266
|
+
void run();
|
|
267
|
+
session.paneScroll = 0;
|
|
268
|
+
session.requestRender();
|
|
269
|
+
}, (err) => {
|
|
270
|
+
session.flashError(err);
|
|
271
|
+
session.requestRender();
|
|
272
|
+
});
|
|
273
|
+
return true;
|
|
274
|
+
}
|
|
256
275
|
if (key.ctrl && key.name === "o" && promptLineFree(ctx.es) && session.view === session.roleIds.length + 7) {
|
|
257
276
|
// Ctrl+O on the Health pane toggles the problems-only view (mnemonic: **O**nly
|
|
258
277
|
// problems) — the same warn/fail trim `tumwater doctor --problems` applies — so an
|