pi-fold Part 2 · Working Memory Under Context Shedding

A long task can survive on what is written in the repository. What kills it is losing the one value that was only ever said out loud. This page plants exactly those values, forces decisions onto the record, withholds the recall test until the work is done, and watches which remedy for a full window still knows what happened.

Scroll to explore

← pi-fold Part 2

The Question

The task survives shedding. Does the transcript?

Part 1 priced folding against native compaction and ended on an honest loose thread: one recall probe the folding arm answered wrongly, twice, while holding a verified copy of the right answer the whole time. That miss pointed at a distinction the cost numbers never touch. Most of what an agent needs lives in the repository, and any session can recover it by re-reading files. But a long session also accumulates facts that exist nowhere on disk: the value a tool returned once, the decision made at stage 23, the continuation key handed over in a single tool result. That is the session's working memory, and it is precisely what context shedding, folding and compaction alike, puts at risk.

So Part 2 is a stress instrument rather than a benchmark. It manufactures transcript-only facts on purpose, plants them in a real 64-stage repository workload, and then asks for them back at the worst possible moment: after the window has been shed repeatedly, in a final block the session never saw coming. The values are seeded tokens generated from a frozen seed committed before any measured run existed, and they appear nowhere in the checkout, so a session that answers correctly can only have gotten the bytes through whatever its shedding mechanism preserved. There is no partial credit and no way to re-derive an answer from the code. The failure it hunts is simple to state: a value exists only in one earlier tool result, shedding rewrites the window, and whatever replaces the original either carries the value forward or does not.

The instrument: values planted only in the transcript

The seeded ledger weaves values into the first half of the 64-stage workload through three channels. Sixteen reconstruction table rows ride one per designated stage on the odd stages 1 through 31. Ten checksum values are stated in single sentences at their own stages; four of them are restated at stages 28 through 31 in a sentence byte-identical in shape to the original, so order is the only thing separating the current value from the withdrawn one. Four three-hop joins each gather links planted at three earlier stages, and the task at stages 23 through 26 must be recorded through the ledger_record tool before the stage tool will hand over the next key. The end block, thirty cells covering every planted value, is withheld until all 64 stages are delivered and then asked in one message, byte-identical across arms.

Three channels weave seeded values into the first half of the workload, and the second half is payload only: every planted fact must cross at least 32 stages of context shedding before it is asked for. The joins are the strict channel: the stage tool refuses to hand over the next continuation key until the decision is recorded, any value is accepted including unknown, and the echo restates the record verbatim with no verdict riding back. The end block is withheld until delivery finishes, so no session can rehearse for it. Hover a channel to trace it. Geometry from the frozen plan.

The Sessions

Two finished. Two never got to the test.

Four sessions ran under seal: two per arm, same frozen plan, same seeded values, same model at the same setting. Both pi-fold sessions delivered all 64 stages and reached the withheld block. Neither native session did. The bounded one, repetition 2, compacted three times and stopped at stage 56 of 64, re-prompted three times at the same undelivered stage without progress. Repetition 1 is the ugly one, and it is disclosed rather than averaged away: the session lost stage 40's continuation key, delivered in stage 39's result, to a compaction, correctly reported it unrecoverable on every pass, and a defective resume loop in the experiment harness re-prompted it every nine seconds for about 4.4 hours and 1,761 provider responses, until the run was killed from outside; the run's totals came to 1,764 provider calls, 280.4 minutes and $128.93. That failure belongs to the harness, not the model, and it bought a permanent repair: the harness now latches a named failure after three resume prompts that buy no progress, which is exactly how repetition 2 came to stop honestly.

Two sessions per arm is a sequential case series, and this page treats it as one. Nothing here estimates a population failure rate, and the excluded runaway means there is no clean cross-arm cost comparison in this campaign at all; the cost claim lives in Part 1. What the four sessions do establish is a mechanism, witnessed end to end under seal, twice.

Four sessions against one workload

pi-fold repetition 1: 64 of 64 stages, nine fold commits, 127 provider calls, 42.7 minutes, completed. pi-fold repetition 2: 64 of 64 stages, seven fold commits, 104 calls, 24.6 minutes, completed. Native repetition 1: three compactions, at stage 23 and twice at stage 40, stopped delivering at stage 39, then a defective harness resume loop ran about 4.4 hours and 1,761 provider responses before the run was terminated from outside; excluded from cost readings. Native repetition 2: compactions at stages 23, 40 and 57, stopped at 56 of 64 after three resume prompts bought no progress.

Every session sheds context; the difference is what shedding keeps. Triangles are fold commits, in-place window rewrites that pause nothing. Diamonds are native compactions, stop-the-world summaries: 4.0 minutes of pause across repetition 2's three, with the key glyph marking where each native session's continuation key was last stated before a compaction took it. The hatched tail on native repetition 1 is the harness runaway, which ran about 4.4 hours and 1,761 provider responses at a standstill after stage 39; it is excluded from every cost reading on these pages, and every call, token and minute shown here is disclosed as observed, never compared as a treatment effect. Hover a row or a mark for its numbers. Measured from the sealed run artifacts.

The Records

Four decisions, forced onto the record

The joins exist to remove the usual excuse. A recall miss can always be waved off as a question the agent never engaged with, so the instrument makes engagement mandatory: at stages 23 through 26 the stage tool refuses to hand over the next continuation key until the session records its answer through ledger_record. Any value is accepted, including an explicit unknown. The record is an event, fixed at record time, so what a session knew mid-task and what it recalls at the end can be graded separately.

The split could not be cleaner. The pi-fold sessions recorded the correct joined value eight times out of eight. The native sessions recorded unknown eight times out of eight. The link values had been planted at stages 1 through 19, both native sessions' first compaction fired at stage 23, and each session answered that it did not know the joined value; the gate accepted the honest record and released the stage. Because any accepted value releases the next stage and no verdict rides back, nothing forced that difference and nothing corrected it mid-run. One native call was refused as a duplicate of an already-recorded task and is counted beside the eight accepted records, not among them.

Accepted ledger records, by session and join task
join taskpi-fold rep 1pi-fold rep 2native rep 1native rep 2
lt-01, recorded at stage 23correctcorrectunknownunknown
lt-02, recorded at stage 24correctcorrectunknownunknown
lt-03, recorded at stage 25correctcorrectunknownunknown
lt-04, recorded at stage 26correctcorrectunknownunknown

Eight of eight correct against eight accepted unknown records; one native duplicate call refused. The same four task identities repeat in each session, so these are task-session records, not replications.

The Withheld Block

Sixty cells, sixty answers, and where the bytes were

After a session delivers stage 64 and ends its turn cleanly, one final user message arrives: thirty cells covering every planted value, in an order shuffled by a second frozen seed, byte-identical across arms. Nothing in the workload announces it. Both pi-fold sessions answered all thirty correctly, sixty of sixty, including every reconstruction row, every checksum through its correction, and every join answered with what the session had recorded. During the runs themselves the periodic probes came in at 40 of 42.

The instrument then attributes every expected value at the exact request that answered it: was the raw statement still visible in the projection, was it inside a fold and recoverable but not visible, or was it gone? Fifty-three of the sixty were visible raw at the answering request; the attribution records where the bytes stood, not why. Seven were recoverable but not visible at the answering request, and all seven were answered correctly. The page states the honest limit alongside: the attribution shows those seven answers could not have been read raw off the window, but it does not identify the carrier that put the bytes into the answer. The recovery that preceded the block was visible in-band: one session made 5 context recovery calls first, the other 9, and recording a ledger decision never counts as recovery; there is no no-call control to price what those calls bought.

The end block, cell by cell

Each session's thirty cells: ten checksums, four joins, sixteen reconstruction rows. All sixty answered correctly. In repetition 1, five checksum values and the last two reconstruction rows were recoverable but not visible at the answering request; the other twenty-three cells were visible raw. In repetition 2 all thirty were visible raw. Four checksum cells in each session had a withdrawn earlier value that was also still present, and both sessions answered with the current value every time, so order really was the only separator.

Every cell is an answered question; fill says where the bytes stood at the moment of answering. Solid cells were visible raw in the projection. Ringed cells were inside a fold: recoverable byte for byte, not visible, and still answered correctly, which is the result the lossless half of the design exists to make possible, and also the cells whose exact carrier the attribution cannot name. The dotted corner marks cells whose withdrawn earlier value was still in play; both sessions chose the current value all eight times. Hover a cell for its identity and carriage. Measured from the sealed run artifacts.

Where the Key Went

Stated once, summarized away, provably gone

Both native sessions died the same death, and the instrument can narrate it request by request because the evidence is sealed. The workload is pull-based: each stage's tool result carries the continuation key for the next stage, stated exactly once. Native repetition 2 received stage 57's key inside stage 56's result. The very next request overflowed the window, compaction fired, 92.5 seconds of stop-the-world, and the summary that replaced the transcript does not contain the key. The entry that carried it was omitted from the projection. A read-only reconstruction of that projection matches the sealed live projection's SHA-256 and its 13-message count exactly, and it holds zero occurrences of the key. The session was then re-prompted three times, reported the key unrecoverable each time, and the run stopped by the named rule those three no-progress resumes trip.

This is the working-memory failure in its purest form. Nothing the session needed was in the repository, nothing it could have done would have worked, and no amount of re-reading files could bring the key back, because the key never existed anywhere but in one tool result that a summary judged unremarkable. The folding arm ran the same workload against the same window budget, and the difference is mechanical: a fold's original bytes remain addressable from inside the session after the window rewrite, and a compaction's are reachable only from outside it.

Anatomy of the loss

Native repetition 2, step by step: the stage 57 key is stated once, in stage 56's tool result. The next request overflows and compaction fires, 92.5 seconds of pause. The summary does not contain the key; the entry carrying it is omitted from the projection. The reconstructed post-compaction projection matches the sealed live projection's SHA-256 and message count and holds zero occurrences of the key. Three resume prompts buy no progress and the run stops by the named rule. Repetition 1 followed the same path at stage 40, key stated at stage 39, except the harness then re-prompted it for about 4.4 hours before the run was terminated from outside.

The chain of custody for one missing value, read from the sealed artifacts rather than inferred. The reconstruction step is what makes the claim exact: rebuilding the post-compaction projection read-only and matching the sealed live projection's SHA-256 and message count proves the zero count describes the very message list the live request was built from. Switch sessions to see the same mechanism at the other boundary. Hover each step for the evidence behind it.

What This Does Not Show

A case series, priced honestly

Two assigned attempts per arm do not estimate a population failure rate, and this page never treats them as if they did. Neither native session reached the withheld block, so there is no cross-arm end-block score, only the mechanism that explains the absence. The seven recoverable cells were answered correctly, but the attribution does not identify how their bytes reached the answer, both end blocks followed context recovery calls with no no-call control, and the sequence was allocated and stopped adaptively, so even the clean separation is a replication target rather than an arm-level effect estimate. Native repetition 1 is excluded from every cost reading because the runaway was the harness's defect, which also means this campaign carries no cross-arm cost ratio at all. And the whole result covers one model, one frozen plan, and one repository workload. These cases motivate preregistered replication; they do not substitute for it. The claim that survives all of those limits is narrow and, within them, exact: under identical shedding pressure, the folding sessions kept their working memory and the compacting sessions each lost the one value they could not re-derive.

The Paper

Sealed, hashed, and recomputable

The full report is published as pi-fold: Working Memory Under Context Shedding, Zenodo, August 2026, DOI 10.5281/zenodo.21980747. The deposit beside the PDF carries a self-contained HTML reading edition, all five figures in source and rendered forms, the frozen plan and both seeds, the analysis-complete sealed evidence set for all four sessions, correction audits, the exact source with Git history, the pinned workload archive, and SHA-256 manifests over everything. Verification checks consistency inside the declared evidence boundary; it does not recreate the original provider interactions.

Citations

The trail behind this page

This paper. Shane Conner, "pi-fold: Working Memory Under Context Shedding", Zenodo, August 2026. DOI: 10.5281/zenodo.21980747.

Part 1's paper. Shane Conner, "pi-fold: Agent-Governed Lossless Context Folding. Design, and a single-workload trace evaluation against native compaction", Zenodo, August 2026. DOI: 10.5281/zenodo.21856874. The design, and the cost pairing this page leans on: shaneconner.com/projects/pi-fold/part-1.

pi-fold. The runtime, its gate suite, and the experiment harness that produced every number above: github.com/shaneconner/pi-fold. On npm as pi-fold, MIT licensed.

Pi. The coding agent this runtime lives inside: github.com/badlogic/pi-mono.

Tech Stack

TypeScript D3.js Pi Context Management Benchmark Design Agent Tooling
View Source → ← All Projects