Skip to content

Carry an incarnation identifier on tool results so a citation cannot open a replacement #250

Description

@hellices

Follow-up from #248 (review of the #192 navigable-citation slice).

Problem

get_events scopes its read to the live object's UID, precisely so
events belong to one incarnation rather than to anything sharing the name:

# tools/executor.py, _get_events
manifest = await self._kube.get_object(meta, namespace, name)
uid = str(raw_uid) if raw_uid else None
events = await self._kube.list_events_for(namespace, name, kind=meta.kind, uid=uid)

The citation that opens it re-fetches by kind and name only. If a pod
is deleted and recreated under the same name between the read and the
user selecting [E1], korvid shows the replacement's manifest and its
name-scoped events as though they were the cited evidence.

The window is small but the failure is quiet: nothing tells the user the
object on screen is not the one the claim was about. That is the same
class as the findings #248 fixed by not claiming — here the honest fix
is to detect it.

Why it was not fixed in #248

The UID exists only inside ToolExecutor._get_events. Carrying it to the
agent layer means adding an incarnation identifier to ToolOutcome, which
is a change to the tools/agent/ contract, not something
agent/evidence.py can recover on its own. Doing it inside a slice about
routing would have buried a contract change in an unrelated review.

The same argument applies to get_logs resolving an omitted container:
#248 resolves the pod's first container independently, which matches
what the executor does but is a second implementation of the same rule.

Suggested approach

  • add an optional incarnation identifier to ToolOutcome (UID, and
    resourceVersion where it is meaningful);
  • populate it where the executor already knows it — _get_events,
    get_resource, the diagnose family;
  • record it on Evidence;
  • at open time, compare and tell the user plainly when the object was
    replaced, rather than showing the replacement silently.

Acceptance

  • Opening a citation for a replaced object reports the replacement
    instead of presenting it as the cited evidence.
  • The container an omitted get_logs resolved travels with the result
    rather than being re-derived.
  • The identifier is optional: reads that have no meaningful incarnation
    (listings) are unaffected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: agentEmbedded agent runtime, tools, prompts, and providersconcern: reliabilityGraceful degradation, lifecycle safety, and operational correctnessenhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions