feat(trace): unified per-conversation forensic recorder for chat + search#139
Merged
quiet-node merged 14 commits intomainfrom May 7, 2026
Merged
feat(trace): unified per-conversation forensic recorder for chat + search#139quiet-node merged 14 commits intomainfrom
quiet-node merged 14 commits intomainfrom
Conversation
…arch Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
…ge-off commands Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
…t duplicate ConversationStart Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
Signed-off-by: Logan Nguyen <lg.131.dev@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
app_data_dir()/traces/{chat,search}/<conversation_id>.jsonl.[debug] trace_enabled = true(also exposed as a Settings panel switch). Off by default. Legacy fieldsearch_trace_enabledcontinues to work viaserde(alias).What changed
Backend (
src-tauri/src/trace/) — new module:trace::ids::ConversationIdnewtype +new_turn_id()(moved fromsearch/recorder.rs).trace::recorder::TraceRecordertrait (wasPipelineRecorder),RecorderEventenum (existing search variants unchanged + new chat variants:ConversationStart,UserMessage,AssistantThinking,AssistantTokens,AssistantComplete,ScreenCaptured,ConversationEnd),TraceDomain { Chat, Search },FileRecorder::for_conversation(root, domain, conv_id),NoopRecorder, test-onlyMockRecorder.trace::registry::RegistryRecorder— production composition:parking_lot::RwLock<HashMap<(TraceDomain, ConversationId), Arc<FileRecorder>>>with lazy insert, hot-path Arc caching,ConversationEnd-triggered flush + evict, and append-mode late-event tolerance.trace::BoundRecorder— wrapsArc<dyn TraceRecorder>+ConversationIdso existingrecorder.record(event)callsites stay unchanged through the search pipeline.Schema bump v1 → v2. Each JSONL line now carries top-level
domainandconversation_id. Search-event variant names and fields are unchanged. File location moves fromtraces/turn-<id>.jsonl(one per search turn) totraces/{chat,search}/<conversation_id>.jsonl(one per conversation, per domain).IPC contract changes.
ask_ollamagainsconversation_id: String,is_first_turn: bool,slash_command: Option<String>.search_pipelinegainsconversation_id: String.capture_full_screen_commandgainsconversation_id: String. Newrecord_conversation_end(conversation_id, reason)command lets the frontend signal user-perceived end-of-conversation (used byuseOllama.reset()anduseOllama.loadMessages()) so the chat-domain trace gets a clean closing line.Frontend.
useOllamamints a stable trace conversation id per session (lazy viaensureTraceConversationId), threads it through every invoke, firesrecord_conversation_endonreset()andloadMessages(). Settings UI label updated from "Search trace" → "Trace recording"; helper text reflects both domains.Coverage gate. 100% lines + 100% functions across both Rust (
cargo +nightly llvm-cov --fail-under-lines 100) and TypeScript (Vitest 100% threshold). 750 Rust tests + 1166 frontend tests all pass.Design doc
~/.gstack/projects/quiet-node-thuki/logan-worktree-gentle-dancing-wave-design-20260506-135848.md(Status: APPROVED, post 2 rounds of adversarial spec review, 9/10 quality, 15 issues caught and fixed). Plus eng-review pass that surfaced the Settings-UI propagation scope.Test plan
bun run validate-buildclean (zero warnings, zero errors)bun run test:all:coverageclean (100% line / function gate)config.toml, set[debug] trace_enabled = true, launch Thuki, run a conversation that includes/searchand/screen, verify:traces/chat/<id>.jsonlandtraces/search/<id>.jsonlfiles appearconversation_start,user_message,assistant_tokens,screen_captured,assistant_completeconversation_idfieldconversation_endline appears with reason"user_reset"[debug] search_trace_enabled = trueline, launch, confirmserde(alias)accepts it (file is rewritten astrace_enabledonly on next settings save)Notes
/code-reviewwill run before merge.