Skip to content

fix(agent-history): ignore sessions untouched before agent first seen - #3

Open
dorokuma wants to merge 1 commit into
ryonakae:mainfrom
dorokuma:fix/discovery-stale-session-pollution
Open

fix(agent-history): ignore sessions untouched before agent first seen#3
dorokuma wants to merge 1 commit into
ryonakae:mainfrom
dorokuma:fix/discovery-stale-session-pollution

Conversation

@dorokuma

Copy link
Copy Markdown

What & why

When a pane agent is first observed, its authoritative session ref (herdr detection or shepherd-pi registration) may not have landed yet, so history resolution falls back to discoverAgentHistory. Discovery scans fixed roots (~/.pi/agent/sessions and peers) and ranks candidates by cwd match plus mtime. If an unrelated, stale session file happens to share the pane's cwd, it gets picked as the "best" candidate; its content is then persisted into the agent's status events and delivered to the orchestrator's wake messages — misattributing another run's output to the new pane agent.

Observed signature: the first status events for a pane carry historyRef.kind === "discovered_file" whose content comes from an unrelated run; once the real registration lands, subsequent events use historyRef.kind === "agent_session" and are clean.

Fix principle

A session file untouched since before the agent's first_seen_at cannot be that agent's live session. Better to report no history than wrong history. Discovery now drops candidates whose mtime is older than firstSeenAtMs - DISCOVERY_RECENCY_GRACE_MS.

  • The authoritative agentSession.kind === "path" branch is untouched — it is not a cwd-based guess.
  • Grace window is 10 minutes. Herdr observation delay is on the second scale, so 10 minutes is far more generous than needed; it only discards sessions that had already stopped being written well before the agent appeared (the stale candidate in the repro was over an hour older than first_seen).
  • firstSeenAtMs is optional. When omitted, behaviour is exactly as before, so cwd-guessing agents that don't pass it (claude / codex / gemini / …) are unaffected.

Changes

  • src/agent-history/discovery.ts: add optional firstSeenAtMs to the lookup input, export DISCOVERY_RECENCY_GRACE_MS, and filter stale candidates before ranking.
  • src/observability/agent-context-service.ts and src/daemon/observability-server.ts: pass agent.firstSeenAt into the history lookup.
  • Tests: stale/grace/boundary/backward-compat cases in test/unit/agent-history-discovery.test.ts, plus a resolveCompactHistory passthrough test in test/unit/agent-history-service.test.ts.

Validation

  • pnpm typecheck
  • pnpm lint / pnpm format:check
  • pnpm test: all tests pass except one pre-existing, unrelated failure in test/unit/shepherd-pi-extension.test.ts ("does not connect outside a complete Herdr environment"), which also fails on pristine origin/main in this environment.

When a pane agent is first observed, its authoritative session ref
(herdr detection or shepherd-pi registration) may not have landed
yet, so history resolution falls back to cwd-based discovery.
Discovery scans fixed roots (~/.pi/agent/sessions and peers) and
ranks by cwd match and mtime, which can select an unrelated stale
session that happens to share the cwd. That session's content is
then persisted into status events and delivered to the
orchestrator's wake messages, misattributing another run's output.

A session file untouched since before the agent's first_seen_at
cannot be that agent's live session, so discovery now drops
candidates older than first_seen_at (10 min grace) and reports no
history rather than a guessed one.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant