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.
Follow-up from #248 (review of the #192 navigable-citation slice).
Problem
get_eventsscopes its read to the live object's UID, precisely soevents belong to one incarnation rather than to anything sharing the name:
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 itsname-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 theagent layer means adding an incarnation identifier to
ToolOutcome, whichis a change to the
tools/→agent/contract, not somethingagent/evidence.pycan recover on its own. Doing it inside a slice aboutrouting would have buried a contract change in an unrelated review.
The same argument applies to
get_logsresolving an omitted container:#248resolves the pod's first container independently, which matcheswhat the executor does but is a second implementation of the same rule.
Suggested approach
ToolOutcome(UID, andresourceVersion where it is meaningful);
_get_events,get_resource, the diagnose family;Evidence;replaced, rather than showing the replacement silently.
Acceptance
instead of presenting it as the cited evidence.
get_logsresolved travels with the resultrather than being re-derived.
(listings) are unaffected.