Ver código fonte

docs: plan atomic session transcript fixes

Problem: existing sessions can switch modes, direct tool rounds persist partially across disconnects, migration races across stores, and empty protocol assistants render as chat bubbles.

Risk: atomic persistence and recovery filtering must preserve visible conversation while never synthesizing incomplete provider tool transcripts.
zhenyu.hu 2 semanas atrás
pai
commit
eaff2fa9b3

+ 47 - 0
docs/plans/todo-49.1-session-mode-and-atomic-transcript-safety.md

@@ -0,0 +1,47 @@
+# Todo 49.1 Session Mode and Atomic Transcript Safety Plan
+
+**Status:** in_progress
+
+## Goal
+
+Prevent session restoration from changing architecture semantics or persisting invalid provider transcripts.
+
+## Scope
+
+- Before updating an existing session config, read its persisted `tool_invocation_mode` (default `dual_agent` for legacy config) and reject an incoming mismatch with a stable error; do not overwrite config.
+- Add `SessionStore.append_messages()` and implement one SQLite transaction for a direct assistant tool-call message plus all matching tool replies.
+- In direct mode with tool calls:
+  - keep the assistant/tool transcript in active memory immediately;
+  - persist the complete protocol group only after batch execution returns all replies;
+  - cancellation/disconnect before completion leaves no partial protocol group.
+- Restore defensively from sessions created by earlier experimental code: drop an incomplete trailing assistant tool-call group or orphan tool replies rather than sending an invalid transcript.
+- Make SQLite column migration safe across concurrent store/process initialization using serialized migration and/or duplicate-column recheck.
+- UI replay skips assistant records whose content is empty and whose only purpose is tool protocol; tool rows retain existing tool styling.
+
+## Files
+
+- Modify: `src/agent_lab/application/session_store.py`
+- Modify: `src/agent_lab/infrastructure/sqlite_store.py`
+- Modify: `src/agent_lab/application/runtime.py`
+- Modify: `src/agent_lab/presentation/static/app.js`
+- Modify: `tests/test_sqlite_store.py`
+- Modify: `tests/test_debug_runtime.py`
+- Modify: `tests/test_websocket_api.py`
+
+## Requirement Execution Loop
+
+### Plan
+
+1. Add RED mode-mismatch tests proving config/history remain unchanged.
+2. Add RED cancellation tests proving no partial assistant/tool group is stored and reconnect remains valid.
+3. Add RED incomplete-tail repair and concurrent migration stress tests.
+4. Add RED static replay test for tool-call-only assistant suppression.
+5. Implement atomic persistence, restore repair, migration serialization, and UI filtering.
+6. Run focused/node/full verification and final reviews.
+
+## Verification
+
+- `UV_CACHE_DIR=.uv-cache uv run pytest tests/test_sqlite_store.py tests/test_debug_runtime.py tests/test_websocket_api.py -q`
+- `node --check src/agent_lab/presentation/static/app.js`
+- `UV_CACHE_DIR=.uv-cache uv run pytest`
+- `git diff --check`

+ 1 - 0
docs/plans/todos.md

@@ -93,5 +93,6 @@
 | 48.2 | done | `docs/plans/todo-48.2-outcome-cache-and-sync-resource-lifecycle.md` | Preserve full replay outcomes, generation-scope cleanup, invalid-key isolation, sync worker resource leases, and deduplicated result correlation/policy cardinality. | Outcome cache, scope invalidation, deferred sync resource leases, correlation, and single policy messages pass. |
 | 48.3 | done | `docs/plans/todo-48.3-strict-canonical-types-and-scope-token-cleanup.md` | Align canonical-key equality with strict JSON types and replace retained generation tombstones with unique releasable scope tokens. | Strict nested JSON types and 1000-cycle scope cleanup pass; final bounded gate APPROVED. |
 | 49 | in_progress | `docs/plans/todo-49-tool-mode-ui-session-restore.md` | Add UI mode selection, workspace/session restoration, and clear EventAgent applicability feedback. | Static/WebSocket tests prove requests, snapshots, loaded sessions, and audit context preserve the selected mode. |
+| 49.1 | in_progress | `docs/plans/todo-49.1-session-mode-and-atomic-transcript-safety.md` | Enforce persisted mode, atomically store direct tool rounds, repair incomplete legacy tails, serialize SQLite migration, and hide empty protocol bubbles. | Mode mismatches are rejected without config overwrite; disconnect cannot leave unresolved tool calls; concurrent migration succeeds; replay shows only visible assistant content. |
 | 50 | pending | `docs/plans/todo-50-comparable-model-tool-metrics.md` | Record mode-aware model/tool spans and include EventAgent usage so both architectures can be compared fairly. | Persistence/API tests report agent, call kind, tokens, TTFT, tool latency, fallback usage, and total turn wall time without double counting. |
 | 51 | pending | `docs/plans/todo-51-comparison-matrix-closeout.md` | Add repeatable comparison fixtures, update project documentation, and close the experimental implementation. | Both modes pass the same scenario matrix; full tests, JS syntax, app import, and documentation checks pass. |