feat: agent background edits on notebooks#586
Conversation
5e89510 to
5012b6f
Compare
Address review findings on the agent-passive-edit path: - #8 archived preview: seed a read-only preview from the persisted view instead of erroring; NotebookProvider gains a `preview` prop that skips live-controller registration and persistence; key <Notebook> on archived so restore remounts cleanly. Also fixes the restore-from-search stale archived flag this surfaced. - #6 archive/commit race: commitView re-reads the row inside a Dexie transaction and returns committed|archived|deleted, rejecting archived and deleted rows atomically with the write. - #3 reconnect freshness: per-generation guard so an in-flight read that spans a reconnect reset no longer seeds freshness for the new connection. - #7 apply_notebook_state: report state_applied + post_apply_aborted on a post-commit abort instead of a generic failure. - #9 hide-result: bump the freshness seq so a stale agent read is caught. - #15 agent-change toast a11y: persistent live announcer, return focus to the pill, split hover/focus auto-hide pause. - Surface the active tab's archived state to the agent (workspace + digest). Tests: freshness generation guard, commitView archived/deleted, and the apply_notebook_state post-commit abort path. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Buffer name limit: - Add MAX_BUFFER_NAME_LENGTH (100) and exceedsBufferNameLimit in the buffer store. Enforce on the SQL/Metrics tab rename (clamp on commit), the notebook rename input (maxLength), and the create_notebook agent tool (schema maxLength + dispatch validation). Existing longer names are never re-validated. Headless notebook runs: - Replace the generation-counter supersession with an AbortController so a newer run cancels the older one mid-flight, not just discards its result — this stops a superseded multi-statement script from executing later statements. Guarantee slot cleanup via finally. - Distinguish a notebook archived mid-run from one deleted mid-run, with a dedicated agent note (NOTEBOOK_ARCHIVED_MID_RUN_NOTE). - Wrap long agent-change labels in the footer popovers. - Add coverage for the above. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Review: PR #586 — feat: agent background edits on notebooksReviewed at level 3 (the full mission-critical pass, all 13 agents + per-finding verification). Local HEAD This is a large, genuinely well-engineered PR. The core concurrency machinery — per-buffer FIFO queue, mount-claim/epoch model, Issues
False-positives
SummaryVerdict: approve with minor changes. No critical or data-loss-on-the-happy-path defects. The architecture is sound and the core is well tested. Fix the small cluster that's genuinely user-facing before ship: #1 (one dismiss kills the popper for the session), #2 (stale rows under agent-rewritten SQL — a data-trust issue), #3 (server notice hidden), and #4 (loading state announces nothing). The rest are edge-case/perf/polish follow-ups.
|
Depends on #581
Tandem PR: questdb/mcp-bridge#1
What
Agents could previously only edit the notebook the user had open, and was stealing focus of the users while editing a notebook. This PR lets the MCP bridge and the built-in assistant work on any notebook in the background.
activate_notebooktool for navigating the user if requestedHow it works
notebookDexieController.ts): every op on an unmounted buffer is a queued read → pure transition → write on the persisted buffer row. No mounting, no hidden React tree.notebookBufferQueue.ts): all writers (agent ops, mount seed read, unmount flush, debounced persists) are strictly ordered per buffer — no lost updates at the mount/unmount boundaries.mounted_mid_editerror telling the agent to re-sync and retry.run_cell(notebookHeadlessRun.ts): runs cells on unmounted notebooks with a verification outcome machine (notebook/cell deleted, user mounted mid-run, cell changed mid-run, superseded) — results are persisted and reported asunverifiedwith a note when the run can't be attributed cleanly.STATE_STALEif the user edited the notebook after the agent's last read (per-buffer action sequence, baseline captured before the read).apply_notebook_stateis deliberately not up-front gated — it's a wholesale PUT; it keeps its internal mid-apply staleness re-check.activate_notebooktool: brings a buffer to the foreground and reveals a cell (used on user request; intentionally ungated — accepted risk).Testing
agentBackgroundEdits.spec.js+ sharedmcpFakeWebSocket.jstest util.