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
|
@@ -1,99 +1,36 @@
|
|
|
1
1
|
import { setConfigKey, unsetConfigKey } from "../../config/config-write.js";
|
|
2
2
|
import { checkMinRunInterval } from "../../config/config-keys.js";
|
|
3
|
-
import { baseRoleOf } from "../../roles/runner-ids.js";
|
|
4
3
|
import { rawRoleField } from "../../roles/role-view.js";
|
|
5
4
|
import { gotSuffix } from "../../text/text.js";
|
|
5
|
+
import { createRoleKeyEditor } from "./tui-editor-role-key.js";
|
|
6
6
|
/** The Ctrl+S min-run-interval editor on the shared prompt line, the terminal twin of
|
|
7
7
|
* `tumwater role <id> --min-run-interval` and the dashboard role drawer's `Min run interval`
|
|
8
|
-
* row
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* (naming `roles.<base>.minRunIntervalSeconds`)
|
|
12
|
-
* non-plain-decimal spelling (hex/exponent,
|
|
13
|
-
*
|
|
14
|
-
* Esc, Ctrl+S again, and Ctrl+T cancel by
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* session's held registry. */
|
|
8
|
+
* row, from the same createRoleKeyEditor factory the role-model and instance-count editors
|
|
9
|
+
* share. It owns its held-marker slot and the role pinned when it opened, so a roster shift
|
|
10
|
+
* cannot redirect the write. Enter writes through the shared setConfigKey/unsetConfigKey family
|
|
11
|
+
* the CLI and the drawer use — so checkMinRunInterval (naming `roles.<base>.minRunIntervalSeconds`)
|
|
12
|
+
* and validateConfig own the value's truth — a non-plain-decimal spelling (hex/exponent,
|
|
13
|
+
* negative, or non-numeric) flashes the editor's own shape message first, mirroring the budget
|
|
14
|
+
* editor's plain-decimal rule, and stays open — and Esc, Ctrl+S again, and Ctrl+T cancel by
|
|
15
|
+
* restoring the prompt draft. Unlike the quiet editor there is no director refusal:
|
|
16
|
+
* `tumwater role director --min-run-interval` is accepted, so the director edits too. Mutually
|
|
17
|
+
* exclusive with the other editors on the one prompt line via the session's held registry. */
|
|
18
18
|
export function createIntervalEditor(session) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
lockedRole = null;
|
|
32
|
-
};
|
|
33
|
-
const handleKey = (_str, key, ctx) => {
|
|
34
|
-
if (key.ctrl && key.name === "s") {
|
|
35
|
-
// Ctrl+S edits the viewed role's own min-run-interval override on its Transcript view.
|
|
36
|
-
// Every non-transcript view keeps Ctrl+S — the guard below lets the key fall through to
|
|
37
|
-
// the pane arms (History's trailing-window cycle) unless the interval editor already
|
|
38
|
-
// holds the line, in which case Ctrl+S is the toggle-out arm. Entering pre-fills the
|
|
39
|
-
// override from the FILE's raw `roles.<base>.minRunIntervalSeconds` (empty when unset —
|
|
40
|
-
// empty means "clear it, fall back to the team-wide interval" on save) and saves the
|
|
41
|
-
// prompt text; leaving restores it. There is no director exemption: the director runs
|
|
42
|
-
// on the same clock, so `--min-run-interval` is accepted for it too.
|
|
43
|
-
if (!intervalMode && !(ctx.view >= 1 && ctx.view <= ctx.roleIds.length))
|
|
44
|
-
return false;
|
|
45
|
-
const role = ctx.roleIds[ctx.view - 1];
|
|
46
|
-
if (session.editorEntryDenied("interval"))
|
|
47
|
-
return true;
|
|
48
|
-
if (intervalMode) {
|
|
49
|
-
exitIntervalMode();
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
// Pin the role first so the write below is safe against a mid-edit roster shift, then
|
|
53
|
-
// pre-fill from the file's own entry — one fresh read per open is the smallest honest
|
|
54
|
-
// source; a broken config degrades to no pre-fill and the write reports the error. The
|
|
55
|
-
// FILE (rawRoleField) is the source of truth, not the merged config: overlayDefaults
|
|
56
|
-
// seeds every built-in role's minRunIntervalSeconds from the catalog, so the merged
|
|
57
|
-
// value cannot tell an operator override from a seeded default, and clearing a role that
|
|
58
|
-
// only has the seed would otherwise be a no-op the operator could not see.
|
|
59
|
-
lockedRole = role;
|
|
60
|
-
const base = baseRoleOf(role);
|
|
61
|
-
const existing = rawRoleField(session.root, base, "minRunIntervalSeconds");
|
|
62
|
-
restoreDraft = session.takeDraft();
|
|
63
|
-
intervalMode = true;
|
|
64
|
-
session.held.interval = true;
|
|
65
|
-
session.input = typeof existing === "number" ? String(existing) : "";
|
|
66
|
-
session.cursor = session.input.length;
|
|
67
|
-
session.flashMessage(`edit ${role}'s min run interval in seconds (0 allows back-to-back runs, empty clears): Enter to save, Esc to cancel`);
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
if (key.name === "escape" && intervalMode) {
|
|
71
|
-
// Esc cancels min-run-interval mode, restoring the previous prompt text.
|
|
72
|
-
exitIntervalMode();
|
|
73
|
-
return true;
|
|
74
|
-
}
|
|
75
|
-
if (key.name === "return" && intervalMode) {
|
|
76
|
-
// Enter commits the override through the shared setter family the CLI's
|
|
77
|
-
// `--min-run-interval` and the dashboard drawer use: an empty or whitespace-only line
|
|
78
|
-
// clears the key (`unsetConfigKey`), otherwise checkMinRunInterval (naming the dotted
|
|
79
|
-
// key) screens the value and `setConfigKey` writes `roles.<base>.minRunIntervalSeconds`
|
|
80
|
-
// as a JSON number. An invalid or rejected value flashes and STAYS in edit mode so the
|
|
81
|
-
// operator can fix it; success restores the saved prompt text.
|
|
82
|
-
const role = lockedRole;
|
|
83
|
-
const cfgKey = `roles.${baseRoleOf(role)}.minRunIntervalSeconds`;
|
|
84
|
-
const text = session.input.trim();
|
|
19
|
+
return createRoleKeyEditor(session, {
|
|
20
|
+
mode: "interval",
|
|
21
|
+
openCtrl: "s",
|
|
22
|
+
prefill: (s, base) => {
|
|
23
|
+
const existing = rawRoleField(s.root, base, "minRunIntervalSeconds");
|
|
24
|
+
return typeof existing === "number" ? String(existing) : "";
|
|
25
|
+
},
|
|
26
|
+
openFlash: (role) => `edit ${role}'s min run interval in seconds (0 allows back-to-back runs, empty clears): Enter to save, Esc to cancel`,
|
|
27
|
+
commit: (s, base, text) => {
|
|
28
|
+
const cfgKey = `roles.${base}.minRunIntervalSeconds`;
|
|
29
|
+
// An empty or whitespace-only line clears the override (a no-op success when the file
|
|
30
|
+
// never set it, so the operator sees "is not set").
|
|
85
31
|
if (text === "") {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
exitIntervalMode();
|
|
89
|
-
session.flashMessage(result.oldValue === undefined
|
|
90
|
-
? `${role}: min run interval is not set in tumwater.json, so nothing was cleared`
|
|
91
|
-
: `${role}: min run interval cleared`);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
session.flashMessage(result.error); // broken config or write failure — stay in edit mode
|
|
95
|
-
}
|
|
96
|
-
return true;
|
|
32
|
+
const r = unsetConfigKey(s.root, cfgKey);
|
|
33
|
+
return r.ok && r.oldValue === undefined ? { ok: true, noop: true } : r;
|
|
97
34
|
}
|
|
98
35
|
// Plain decimal seconds only — bare Number() would also read hex ("0x10" → 16) and
|
|
99
36
|
// exponent ("1e2" → 100) as an interval, neither of which an operator means when
|
|
@@ -105,31 +42,21 @@ export function createIntervalEditor(session) {
|
|
|
105
42
|
// editor was about to write — and STAY in edit mode (negative and non-numeric text hit
|
|
106
43
|
// this shape arm too, so the operator sees one consistent message).
|
|
107
44
|
if (!/^\d*\.?\d+$/.test(text)) {
|
|
108
|
-
|
|
109
|
-
|
|
45
|
+
return {
|
|
46
|
+
ok: false,
|
|
47
|
+
error: `${cfgKey} must be a plain second count like 300, 0.5, or .5 — no +/-, exponent, or hex notation${gotSuffix(text)}`,
|
|
48
|
+
};
|
|
110
49
|
}
|
|
111
50
|
const value = Number(text);
|
|
112
51
|
const invalid = checkMinRunInterval(value, cfgKey);
|
|
113
|
-
if (invalid)
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
session.flashMessage(result.error); // broken config or write failure — stay in edit mode
|
|
126
|
-
}
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
return false;
|
|
130
|
-
};
|
|
131
|
-
return {
|
|
132
|
-
handleKey,
|
|
133
|
-
exit: exitIntervalMode,
|
|
134
|
-
};
|
|
52
|
+
if (invalid)
|
|
53
|
+
return { ok: false, error: invalid };
|
|
54
|
+
const result = setConfigKey(s.root, cfgKey, JSON.stringify(value));
|
|
55
|
+
return result.ok && result.unchanged ? { ok: true, noop: true } : result;
|
|
56
|
+
},
|
|
57
|
+
savedFlash: (role, text) => text === "" ? `${role}: min run interval cleared` : `${role}: min run interval set to ${text}s`,
|
|
58
|
+
noopFlash: (role, text) => text === ""
|
|
59
|
+
? `${role}: min run interval is not set in tumwater.json, so nothing was cleared`
|
|
60
|
+
: `${role}: min run interval is already ${text}s, so tumwater.json was not written`,
|
|
61
|
+
});
|
|
135
62
|
}
|
|
@@ -1,94 +1,38 @@
|
|
|
1
1
|
import { saveRoleNote } from "../../agent/role-notes-write.js";
|
|
2
2
|
import { roleNotesPath } from "../../paths.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createRoleFileEditor } from "./tui-editor-role-file.js";
|
|
4
4
|
/** The notes view's Ctrl+E replace-notes-from-a-file editor on the shared prompt line, the
|
|
5
5
|
* terminal twin of `tumwater role <id> --notes-file <path>` and the dashboard drawer's
|
|
6
|
-
* textarea.
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* so the
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* make), so the 4 KB cap and its wording cannot drift; the fresh read is repainted through the
|
|
15
|
-
* session's refreshNotes seam. */
|
|
6
|
+
* textarea. Guarded to the notes view (`ctx.noteMode`), so the Report window's Ctrl+E arm keeps
|
|
7
|
+
* the key on its own views. The prompt line is single-line and a note may be multiline up to
|
|
8
|
+
* ROLE_NOTES_MAX_BYTES, so the editor takes a file path and reads it verbatim — exactly the
|
|
9
|
+
* CLI's own non-interactive replacement, the way the Activity view's Ctrl+V attach editor also
|
|
10
|
+
* takes a path. The write goes through saveRoleNote (the same write the CLI and the dashboard
|
|
11
|
+
* drawer make), so the 4 KB cap and its wording cannot drift; the fresh read is repainted
|
|
12
|
+
* through the session's refreshNotes seam. The open/exit/read framing lives in the shared
|
|
13
|
+
* createRoleFileEditor helper that also serves the instructions editor. */
|
|
16
14
|
export function createNotesEditor(session) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const handleKey = (_str, key, ctx) => {
|
|
29
|
-
if (key.ctrl && key.name === "e" && ctx.noteMode &&
|
|
30
|
-
// The pane's noteMode closure goes stale when syncRoster shrinks the roster past the
|
|
31
|
-
// viewed role (it never resets the pane's flags), so the same in-range guard every
|
|
32
|
-
// transcript editor arm carries must hold here too before its view indexes roleIds.
|
|
33
|
-
ctx.roleIds.length > 0 && ctx.view >= 1 && ctx.view <= ctx.roleIds.length) {
|
|
34
|
-
// Ctrl+E toggles the replace-notes editor on the notes view's prompt line (mnemonic:
|
|
35
|
-
// **e**dit notes — the same key the Report window's window-cycle arm and the Queued
|
|
36
|
-
// pane's row-edit arm use on their own views, guarded away here by ctx.noteMode). The
|
|
37
|
-
// line edits one file path that becomes the role's whole note through the same
|
|
38
|
-
// saveRoleNote write the CLI and the dashboard drawer use. Entering saves the prompt
|
|
39
|
-
// draft and blanks the line; leaving restores it.
|
|
40
|
-
if (session.editorEntryDenied("notes"))
|
|
41
|
-
return true;
|
|
42
|
-
if (notesEditFor !== null) {
|
|
43
|
-
exitNotesMode();
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
// Mid-recall, hand the arrows' saved draft back before the notes editor takes the
|
|
47
|
-
// line — the same settle the role editors do — so leaving restores the
|
|
48
|
-
// draft, not a history entry, with no stale recall state riding along.
|
|
49
|
-
const role = ctx.roleIds[ctx.view - 1]; // defined: the open-arm range guard above pins the view into roleIds
|
|
50
|
-
restoreDraft = session.takeDraft();
|
|
51
|
-
notesEditFor = role;
|
|
52
|
-
session.held.notes = role;
|
|
53
|
-
session.input = "";
|
|
54
|
-
session.cursor = 0;
|
|
55
|
-
session.flashMessage(`replace ${role}'s notes from a file — Enter to save, Esc to cancel`);
|
|
56
|
-
}
|
|
57
|
-
return true;
|
|
58
|
-
}
|
|
59
|
-
if (key.name === "escape" && notesEditFor !== null) {
|
|
60
|
-
// Esc cancels the notes editor, restoring the previous prompt text and writing nothing.
|
|
61
|
-
exitNotesMode();
|
|
62
|
-
session.flashMessage("notes edit cancelled");
|
|
63
|
-
return true;
|
|
64
|
-
}
|
|
65
|
-
if (key.name === "return" && notesEditFor !== null) {
|
|
66
|
-
// Enter reads the typed path whole and saves it through saveRoleNote — the shared write
|
|
67
|
-
// the CLI's `--notes-file` and the dashboard drawer make, so the 4 KB cap and its wording
|
|
68
|
-
// cannot drift. An empty path, a missing file, an unreadable file, and an over-cap note
|
|
69
|
-
// all flash and STAY in the editor so the operator can fix the path; an empty file
|
|
70
|
-
// clears the note. On success the notes view repaints the new note without leaving and
|
|
71
|
-
// re-entering, and the editor exits with the shared success wording.
|
|
72
|
-
const role = notesEditFor;
|
|
73
|
-
// The trim/read/refuse prologue is shared with the brief, instructions and backlog-entry
|
|
74
|
-
// editors (readEditorPath), which read one typed path the same way.
|
|
75
|
-
const text = readEditorPath(session);
|
|
76
|
-
if (text === null)
|
|
77
|
-
return true;
|
|
15
|
+
return createRoleFileEditor(session, {
|
|
16
|
+
held: "notes",
|
|
17
|
+
openCtrl: "e",
|
|
18
|
+
mayOpen: (ctx) =>
|
|
19
|
+
// The pane's noteMode closure goes stale when syncRoster shrinks the roster past the
|
|
20
|
+
// viewed role (it never resets the pane's flags), so the same in-range guard every
|
|
21
|
+
// transcript editor arm carries must hold here too before its view indexes roleIds.
|
|
22
|
+
ctx.noteMode && ctx.roleIds.length > 0 && ctx.view >= 1 && ctx.view <= ctx.roleIds.length,
|
|
23
|
+
openFlash: (role) => `replace ${role}'s notes from a file — Enter to save, Esc to cancel`,
|
|
24
|
+
cancelFlash: "notes edit cancelled",
|
|
25
|
+
commit: (s, role, text) => {
|
|
78
26
|
try {
|
|
79
|
-
|
|
80
|
-
session.refreshNotes(role);
|
|
81
|
-
exitNotesMode();
|
|
82
|
-
session.flashMessage(message);
|
|
27
|
+
return { ok: true, message: saveRoleNote(roleNotesPath(s.root, role), text) };
|
|
83
28
|
}
|
|
84
29
|
catch (err) {
|
|
85
|
-
// The write or the 4 KB cap refused the note:
|
|
86
|
-
//
|
|
87
|
-
|
|
30
|
+
// The write or the 4 KB cap refused the note: return the reason so the caller flashes
|
|
31
|
+
// it and stays in the editor for the operator to fix the path.
|
|
32
|
+
return { ok: false, reason: err };
|
|
88
33
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
};
|
|
93
|
-
return { handleKey, exit: exitNotesMode };
|
|
34
|
+
},
|
|
35
|
+
flashFailure: (s, reason) => s.flashError(reason),
|
|
36
|
+
refresh: (s, role) => s.refreshNotes(role),
|
|
37
|
+
});
|
|
94
38
|
}
|