Skip to content

fix: explain why an element reference stopped resolving - #84

Merged
yashranaway merged 1 commit into
mainfrom
t3code/ref-lifetime
Aug 5, 2026
Merged

fix: explain why an element reference stopped resolving#84
yashranaway merged 1 commit into
mainfrom
t3code/ref-lifetime

Conversation

@yashranaway

Copy link
Copy Markdown
Collaborator

Closes #16.

The problem

snapshot() reissues element references on every call, so a reference from an earlier inspection silently stops resolving. The common case is nasty: run --context full (200+ controls), then --context summary (8 controls), and every reference from the first call is now dead. The agent received:

ELEMENT_NOT_FOUND:@e137

Nothing there distinguishes "this expired, re-inspect" from "this never existed" — which is exactly the difference between recovering and retrying a dead reference forever.

The fix

Failures name the cause:

Cause Meaning
expired issued earlier, superseded by a later inspection — inspect again
unknown never issued — do not guess or invent references
detached the element or region has left the page

Both ELEMENT_NOT_FOUND and REGION_NOT_FOUND carry it. Host error-code mapping is unchanged (it matches on the prefix), so this is additive on the wire.

The asymmetry is deliberate

I kept element and region lifetimes different, and documented why rather than "fixing" it:

  • @eN is latest-inspection-only. That is already what the skill teaches, and making references durable would mean holding every control on every page.
  • @rN stays resolvable across inspections, because the documented outline-then-scope workflow depends on it — take @r4 from an outline, then scope repeated text/actions calls to it. An existing test covers that workflow; changing it would have broken a shipped contract.

What was wrong with regions is that the map was never cleared, holding strong references to detached nodes for the lifetime of the page. It is now bounded at 256, oldest-first — a leak fix, not a semantic change.

Verification

Ran the runtime suite locally (this one I can run — it is Node-only): stale reference reports expired, unknown reference reports unknown, a fresh reference still resolves, and the cross-inspection region workflow still works. The pruning numbers are unchanged (48,428 → 895 bytes), so the headline metric did not regress.

P1 gains a Reference lifetime section so this is documented behaviour rather than folklore.

Closes #16.

Element references are reissued by every inspection, so a reference from an
earlier call silently stops working — including the common case where a
narrow --context summary returns eight controls after a --context full
returned two hundred. The agent got a bare ELEMENT_NOT_FOUND with nothing to
distinguish 'this expired, re-inspect' from 'this never existed', which is the
difference between recovering and retrying a dead reference.

Failures now name the cause: expired, unknown, or detached. Region lookups do
the same.

Region references keep their existing lifetime on purpose. They stay
resolvable across inspections because the documented outline-then-scope
workflow depends on it, but the map holding them was never cleared and kept
strong references to detached nodes for the lifetime of the page. It is now
bounded at 256, oldest first.

P1 documents the asymmetry rather than leaving it as folklore, and the runtime
suite asserts each failure mode plus the cross-inspection region workflow.
@yashranaway
yashranaway requested a review from SarthakWade August 5, 2026 20:06
@yashranaway
yashranaway merged commit c2f5dd7 into main Aug 5, 2026
7 checks passed
@yashranaway
yashranaway deleted the t3code/ref-lifetime branch August 5, 2026 20:08
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.

A5 — @eN refs silently invalidated by every snapshot

1 participant