Skip to content

Agent prompt history: pin Claude session UUID to avoid sibling-transcript misattribution #17

Description

@ovdmar

Context

PR #7 introduced on-demand parsing of Claude Code .jsonl transcripts to merge user-typed prompts into Citadel's per-session prompt history. The merge picks the transcript whose first user-prompt timestamp is closest to the agent session's createdAt.

Problem

If a user runs two claude invocations against the same workspace in quick succession, both produce .jsonl files in the same ~/.claude/projects/<dasherized-cwd>/ folder. The closest-timestamp heuristic almost always picks the right one, but with overlapping or near-simultaneous starts the merge could attribute a sibling Claude session's prompts to the wrong Citadel agent session.

Mitigation (substantial — deferred from PR #7)

Record the Claude session UUID inside the Citadel agent_sessions row at startup (probably by tailing the project dir for a moment after claude launches, picking up the new .jsonl filename, and persisting the UUID). Then findClaudeTranscriptForSession becomes a deterministic lookup by filename instead of a heuristic.

This requires (a) a new column / migration on agent_sessions, (b) a watcher in the runtime-launch path, and (c) reconciliation behavior when the watcher misses the new file. Not appropriate as a follow-up commit inside PR #7's scope.

Scope

  • Schema: add runtime_session_id (nullable) to agent_sessions.
  • Runtime adapter: claude-code launcher waits up to a few seconds for the new .jsonl, records the UUID.
  • findClaudeTranscriptForSession: prefer the pinned UUID's file when set; fall back to the heuristic when null (older sessions).
  • Tests: unit test for the watcher's timeout fallback; integration test for the pinned lookup.

Acceptance

readAgentHistory against two overlapping claude-code sessions in the same workspace returns each session's own prompts, never the sibling's.

Tracked from PR #7 (#7).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions