Remove or shorten comment blocks that:
- explain where code used to live (impl history)
- duplicate rationale already in docs/web-ui.md
- contain speculative/future-work notes
Changes:
- tabs.js: drop "SYST3M tab used to render this" history; keep badge purpose
- schedules.js: drop "used to be a card layout" history + speculative nit note
- stream-worker.js: replace 10-line problem-statement with docs pointer
(rationale already in docs/web-ui.md SSE multiplexing section); trim
future-work parenthetical from subscription-tracking comment
- system-sections.css: drop extraction-history prose; keep what it does
- core.css: drop move-history prose; keep what it imports and why
Part of issue cleanup per operator feedback.
Adds pause/resume support for scheduled prompts.
Backend:
- New paused_at_unix column on scheduled_prompts table (added via
ALTER TABLE migration so existing databases are upgraded on first
start). The due-rows index is dropped and recreated to also exclude
paused rows so the worker never fires them while paused.
- Worker's due() query gains AND paused_at_unix IS NULL filter.
- New pause(id) and resume(id) methods on ScheduledPrompts; both are
idempotent and refuse cancelled rows.
- New POST /api/schedules/{id}/pause and /api/schedules/{id}/resume
dashboard endpoints (operator-direct, no approval gate). Both emit
a schedules snapshot on success so the tab updates live.
- WireSchedule gains paused_at_unix: Option<i64> so the frontend can
render the state without an extra fetch.
Frontend:
- Paused rows render with a distinct row class + muted opacity.
- The next-fire cell shows a yellow pause glyph + tooltip with the
paused-since timestamp and the would-have-fired time.
- Actions column: pause/resume toggle button (⏸/▶) beside fire/edit/cancel.
Fire-now is disabled while paused (resume first).
- Sort order: active → paused → cancelled (paused slot keeps schedules
visible without mixing them into the active top section).
- pauseSchedule() / resumeSchedule() async functions POST to the new
endpoints and refresh the table on success.
renderReminders() calls appendLinkified() (for the reminder file_path
and message bodies) but schedules.js only imported { $, el } from
common.js, so the reminders_changed SSE handler threw
'ReferenceError: appendLinkified is not defined' and the reminders
pane failed to render. appendLinkified is exported from common.js;
add it to the import. Fixes#1909.
Manually firing a recurring schedule now offers a "reset timer" checkbox
(default on) in the confirm dialog: when checked, the fire-now POST sends
{reset_timer:true} and the backend re-arms next_fire_at to now + interval.
Unchecking keeps today's behaviour (extra out-of-band pulse, cadence
intact). One-shot schedules omit the checkbox — they're consumed regardless.
The result flash shows "— timer reset" when the backend reports timer_reset.
Pairs with the backend reset_timer/timer_reset work. Closes#1848.
Phase 2 of the dashboard route consolidation. The backend now double-registers
every bare top-level route (approve/deny/kill/restart/start/rebuild/destroy/
update-all/answer-question/cancel-question/purge-tombstone/matrix-account-login/
cancel-reminder/retry-reminder/request-spawn/op-send/meta-update/dashboard-stream/
dashboard-history) at an additional /api/<same> path. Switch every dashboard-pkg
fetch / EventSource / form action to the /api/ form so "backend = /api/*" holds
on the frontend side too.
Bare paths still answer, so this is independently deployable; once it ships the
backend can drop the bare registrations (phase 3). webhook/knowledge stays a
distinct webhook prefix (forge-driven, no SPA caller). app.js's /rebuild,/start
are the agent harness UI (different server) and are untouched.
Part of #1846 (phase 2).
Follow-up to the themed-modal component: route every remaining native
browser dialog through modal.js so nothing falls back to the OS chrome.
- modal.js: add themedPrompt (input dialog) + themedToast (non-blocking
transient notification, info/error/ok) alongside openDialog/themedConfirm.
- Migrate call sites: bindAsyncForms confirm/prompt/alerts (common.js),
the answer-validation alert (call.js), the M0V3 reparent confirm + action
toasts (tabs.js), and the schedule form/cancel/fire confirms + validation
and error alerts (schedules.js).
- UX: blocking modal for confirms/prompts; non-blocking toast for transient
errors + validation. Destructive confirms keep the danger styling.
- CSS for the toast stack + prompt input.
common.js <-> modal.js is a safe deferred import cycle (usage is call-time
only); esbuild bundles it clean.
The schedules table builds a column per target, including agents that
have since been destroyed (their past schedules linger). Those columns
showed identically to live agents, so the operator couldn't tell a
schedule still targets something that no longer exists.
Flag them: renderSchedulesTableHead now checks each agent column against
the live roster (containersState) and, for any that isn't there (and
isn't 'operator', which is always valid), greys + strikes through the
column label and titles it 'no longer exists (gone)'. The rows stay
visible + cancellable — the operator can see the stale targets and clear
them rather than be surprised by phantom columns. Build green.
Largest step of the tabs.js split: the SCH3DUL3S tab — reminders +
scheduled-prompts (the lists, inline create row, per-row edit form, and
fire-now / cancel actions) — moves into a new schedules.js, ~1060 lines
out of tabs.js. It owns its own module state (schedules list +
edit-in-progress tracking) and reads the shared agent roster from
state.js for the target-chip pickers; render + format helpers come from
util.js, so the keystones (state.js, util.js) paid off here.
Exports the four entry-wired functions — applySchedulesChanged /
applyRemindersChanged (mutation dispatch), refreshSchedules /
refreshReminders (tab activation + cold-load) — plus activeScheduleCount
(the count pill). The 19 other functions stay module-private. Also drops
the now-unused paintAtomic import from tabs.js (its only callers were in
this block).
Behaviour-preserving code motion; esbuild inlines schedules.js into the
tabs.js bundle. Build green; tabs.js drops ~1060 lines (4323 → 2969).