Fork a per-class exploration anchor for dynamic-access attempts#8937
Open
kimeta wants to merge 1 commit into
Open
Fork a per-class exploration anchor for dynamic-access attempts#8937kimeta wants to merge 1 commit into
kimeta wants to merge 1 commit into
Conversation
kimeta
force-pushed
the
mm/snapshotting-class-level-sessions
branch
3 times, most recently
from
July 3, 2026 10:52
1d91c52 to
81bd621
Compare
The dynamic-access iterative strategy previously ran every attempt for a class on one shared session, so each attempt re-sent the full static context and dragged the prior attempts' turns forward. Now each class is explored once in a read-only anchor turn (new dynamic-access-explore prompt) that plans coverage without writing files. Every attempt forks that anchor and sends only a slim generation prompt (dynamic-access-iteration, rewritten) carrying the latest report delta. Because a fork branches the conversation but not the working tree, the slim prompt tells the fork to read the on-disk tests and extend them additively so it does not clobber coverage authored by a sibling attempt it has no memory of. A discarded fork child would otherwise drop its tokens from run metrics. The fork child is now a context manager: on block exit it folds its token delta (current total minus the baseline captured at fork, before its first turn) into the anchor's fork-usage accumulator, and the token properties report own plus forked usage. Call sites just wrap the fork in `with`, so no per-site accounting is needed.
kimeta
force-pushed
the
mm/snapshotting-class-level-sessions
branch
from
July 3, 2026 11:14
81bd621 to
87a6a2d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #8936
What this does
The
dynamic_access_iterativestrategy used to run every attempt for a class onone shared agent session, so each attempt re-sent the full static context and
carried the previous attempts' turns forward — the class exploration was paid
for again as the conversation grew. This reworks the per-class loop so each
class is explored once into an anchor session, and every attempt forks
that anchor with only a slim prompt carrying the latest report delta
(§WF-dynamic-access-iterative-strategy in
forge/docs/workflows/dynamic-access.md).
How the design was chosen
The shape came out of working through the trade-offs of forking — a
conversation-branch primitive already implemented on both agents but so far
unused:
one checkout, so per-attempt forks can't run in parallel, and even
sequentially a fork's memory drifts from disk: once one attempt commits a
passing test, the next fork (branched from the pre-generation anchor) has no
memory of it. Rather than re-anchoring after every commit — which would defeat
the reuse — the slim prompt tells the fork to read the on-disk tests first
and extend them additively, never rewrite, so it can't clobber coverage it
didn't author.
available to every attempt. The trade-off is a larger cached prefix per fork,
and the token win is only realized if the provider serves that shared prefix
from cache across forked threads; for a class resolved in a single attempt the
extra explore turn is net cost.
Fork token accounting
A fork child inherits the anchor's counters, spends its own tokens, and is then
discarded — so without help its tokens vanish from run metrics (which read
totals off the single agent object). The fold is built into the fork lifecycle
rather than bolted onto each call site:
child_total − baseline, wherebaselineis captured at fork time beforethe first turn — into the parent's fork-usage accumulator. Subtracting the
baseline is what prevents double-counting the inherited history.
own-thread counter stays clean.
with agent.fork(prompt) as child:— adding a forkanywhere else needs no bespoke accounting.
What changed
dynamic-access-explore.md(new)dynamic-access-iteration.mddynamic_access_iterative_strategy.pyclear_context→ explore anchor →with agent.fork(...)per attempt; the inner test-repair loop runs on the fork.agent.pyadd_forked_usage, fork-child baseline stamping, and the context-manager fold in__exit__.codex_agent.py/pi_agent.pyfork/compact_forkstamp the child's baseline.Existing strategy bundles need no config change: the explore prompt is
auto-defaulted in the strategy (
prompts.setdefault) and stays overridable.