feat: session DAG with fork detection and subagent linking#43
feat: session DAG with fork detection and subagent linking#43
Conversation
roborev: Combined Review (
|
roborev: Combined Review (
|
Build a uuid/parentUuid DAG from Claude Code JSONL entries to detect conversation forks and link Task tool calls to their spawned subagent sessions. Fork detection splits large-gap branches (>3 user turns) into separate session records with relationship_type="fork", while small-gap retries are treated as the latest branch of the main session. Subagent linking parses queue-operation enqueue entries (JSON and XML formats) to map tool_use IDs to subagent session IDs, then annotates Task tool calls with the linked session. Adds relationship_type and subagent_session_id columns, child sessions API endpoint, and inline subagent conversation expansion in the frontend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…timestamps Restore ExcludeProject filter on SessionFilter and server handler -- the frontend still sends exclude_project for the hide-unknown toggle, which is a separate concern from relationship_type filtering. Fix nested fork parent linkage: pass each fork branch's computed session ID as ownerID during recursive DAG traversal so nested forks point to their immediate fork parent, not the root session. Widen session startedAt/endedAt to include timestamps from non-message events (queue-operation, etc.) by tracking global min/max across all valid JSONL lines in the first pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add handler-level test asserting exclude_project query param filters session results in the HTTP response. Add StartedAt widening test with a leading non-message event, and a DAG fixture test verifying main session bounds are widened while fork session bounds are not. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Suppress false positives from roborev about DAG cycle detection, recursion depth limits, unreachable node checks, and cross-session write atomicity. These are adversarial-input concerns that don't apply to a local tool parsing trusted agent output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
Extract InferRelationshipTypes into parser package and call it from both the sync engine and the upload handler. Previously uploaded sessions with a parent could be stored with empty relationship_type, causing them to appear in default session listings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roborev: Combined Review (
|
|
"Both are valid observations but neither warrants blocking the merge. Subagent inline 1000-message cap — This is a pragmatic limit, not a bug. Subagent sessions with Stats include subagent/fork sessions — This is intentional. The stats endpoint counts total Neither is a regression introduced by this PR — the 1000-message limit predates these changes, and |


Closes #17
Summary
End-User Impact
Design
DAG from uuid/parentUuid: Every Claude Code JSONL entry carries
uuidandparentUuidfields forming a tree. The parser builds a parent→children adjacency map in a single pass, then walks from root following first-child links. At fork points (nodes with multiple children), a heuristic counts user turns remaining on the first branch: >3 turns = real fork (split into separateParseResult), ≤3 turns = retry (follow latest child, discard older branch).Subagent linking from queue-operation: Claude Code writes
queue-operationentries withoperation: "enqueue"when spawning subagents. Thecontentfield mapstool_use_id→task_id. Two formats exist in the wild: JSON ({"task_id":"...","tool_use_id":"..."}) and XML (<task-id>...</task-id><tool-use-id>...</tool-use-id>). Parser tries JSON first viagjson.Get, falls back to regex for XML tags.Data model — relationship_type: Sessions gain a
relationship_typecolumn ("","continuation","subagent","fork"). Fork sessions get ID{parent}-{first-uuid}withparent_session_idpointing to main session. Tool calls gainsubagent_session_idlinking to the agent session.API — child sessions endpoint:
GET /api/v1/sessions/{id}/childrenreturns fork/continuation/subagent sessions for a parent.Test plan
go test ./internal/parser/ -run TestForkDetection)go test ./internal/parser/ -run TestSubagent)go test ./internal/sync/ -run TestSync)🤖 Generated with Claude Code