Keep clone and GC regressions plus a standalone traversal benchmark. Archive the discarded graph experiment and baseline comparisons in durable docs, including the remaining transient-memory and traversal-speed costs.
Fall back to the latest safe assistant boundary when trailing tool results exceed the retained-token budget, allowing older history to compact before the next provider request.
Closes#9740
A wrapper baked its path at creation, so a reference held across a
structural mutation kept addressing its old index: unshift then a write
through a held element edited its neighbour, and a write after a splice
could produce a path the replica cannot resolve. The baseline diff this
tracker replaced was immune, because its dirty paths were only hints and
the ops came from comparing values.
A wrapper now holds a cell (parent link plus segment) and the path is
walked at use time, so renumbering an element corrects every descendant.
pop/shift/unshift/splice and length truncation shift live children by the
delta and mark removed ones dead; sort/reverse/fill/copyWithin relocate
them by identity. Renumbering iterates a set of live cells rather than the
lookup cache, which is keyed by index and can evict a child that is still
held. Writes through an element that left the document mutate it and
record nothing, as plain JS and the baseline diff both do.
One object can occupy several positions in the tree. A wrapper is now
shared per target and holds a cell per position, and a write emits an op
for each, which is what the baseline diff produced for the same shape.
Positions are registered when a path is read, when a tracked value is
assigned elsewhere, and when one is inserted by an array mutator (only the
inserted range is examined; scanning the array made every structural
mutation O(n)). A blocked view of an object gets its own wrapper so the
reserved-key guard cannot be bypassed through a safe alias.
Paths are cached per cell against a counter that only structural mutation
bumps, and the per-write cell walk is skipped until a document actually
aliases something.
Remove SystemMessage.replace. A prompt forced from before_agent_start is a rendering
of the current prompt for the run, not conversation state: persisting it as a
replacing system message wrote the full prompt and tool list on every change,
lost the structured sections while forced, and disabled mid-conversation system
messages for the rest of the session once a replacement existed.
The transcript now always records section patches. AgentSession wraps
transformContext and, when a forced prompt is active, collapses the system
messages into one head carrying the forced text and the current tools. Providers
receive the same request as before; nothing is persisted and the projection ends
with the run.
The evals harness validated the without_docs variant from the transcript, which
relied on the persisted replacement. Its transform extension now records the
prompt it forced and validates that instead.
Map signal termination to conventional nonzero exit codes and reject null exit codes from custom shell operations while preserving partial output.
fixes#9577