pi-fold 3.1.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -28
- package/extensions/active-context.ts +645 -412
- package/extensions/index.js +11 -2
- package/extensions/lib/brief-text.ts +116 -0
- package/extensions/lib/canonical.ts +3 -18
- package/extensions/lib/curation.ts +208 -74
- package/extensions/lib/editor-ui.ts +595 -66
- package/extensions/lib/folding.ts +20 -2
- package/extensions/lib/instrumentation.ts +3 -1
- package/extensions/lib/live-settings.ts +73 -0
- package/extensions/lib/measurement.ts +47 -0
- package/extensions/lib/persistence.ts +42 -39
- package/extensions/lib/policy.ts +72 -51
- package/extensions/lib/selection.ts +9 -44
- package/extensions/lib/tool-surface.ts +2 -32
- package/extensions/lib/transcript.ts +43 -0
- package/extensions/settings.ts +200 -32
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Rotate stale text out of the context window without losing it, and spend the prefix cache once per commit instead of continuously.** The oldest part of a session collapses into short briefs while the exact originals stay on disk, one tool call away. Folding is automatic and needs no agent participation. The shipped shape is deterministic briefs paired with a durable memory store, which is the cheapest configuration measured that kept recall intact.
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|
|
|
9
9
|
*Marks outline spans as they complete and move nothing; the next commit applies every standing mark in one rewrite. Expanding a brief brings the exact messages back byte for byte. Illustrative animation drawn on the 2.x surface, where the agent laid the marks; since 3.0 the runtime lays them.*
|
|
10
10
|
|
|
@@ -16,15 +16,15 @@ pi install npm:pi-fold
|
|
|
16
16
|
|
|
17
17
|
Node 22 or later, Pi 0.83 or later. MIT licensed.
|
|
18
18
|
|
|
19
|
-
Folding does not require a memory store, but every best result measured came from pairing it with one. The campaigns used [pi-canon](https://github.com/shaneconner/
|
|
19
|
+
Folding does not require a memory store, but every best result measured came from pairing it with one. The campaigns used [pi-canon](https://github.com/shaneconner/canon), installed separately. The two began as a single working setup and were split into separate extensions for modularity, and the experiments are what established that they work better as complements than either does alone. Only that pairing has been measured. Any durable long-term memory store is expected to compose the same way, though that is a suspicion rather than a result.
|
|
20
20
|
|
|
21
21
|
## What it does
|
|
22
22
|
|
|
23
23
|
Compaction replaces the transcript with a summary and discards the originals. Folding replaces stale spans with briefs and keeps the originals retrievable.
|
|
24
24
|
|
|
25
25
|
<picture>
|
|
26
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/shaneconner/
|
|
27
|
-
<img alt="Compaction turns the transcript into a summary and discards the originals, so the session starts over. pi-fold turns it into a brief and keeps the exact originals on disk, one peek or expand away, so the session keeps going." src="https://raw.githubusercontent.com/shaneconner/
|
|
26
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/shaneconner/fold/main/media/fold-vs-compaction-dark.svg">
|
|
27
|
+
<img alt="Compaction turns the transcript into a summary and discards the originals, so the session starts over. pi-fold turns it into a brief and keeps the exact originals on disk, one peek or expand away, so the session keeps going." src="https://raw.githubusercontent.com/shaneconner/fold/main/media/fold-vs-compaction-light.svg">
|
|
28
28
|
</picture>
|
|
29
29
|
|
|
30
30
|
A fold takes a contiguous span of session entries and replaces it, in the window only, with a short brief. The entries go to a fold store byte for byte, addressed by their SHA-256 hash. The brief carries a handle, the handle resolves to the original, and expansion restores the exact bytes after verifying the hash.
|
|
@@ -51,7 +51,7 @@ Compaction alone abstained nine times and was wrong three, so its dominant failu
|
|
|
51
51
|
|
|
52
52
|
Agent-written briefs scored worst of anything measured, which is why that invitation ships off.
|
|
53
53
|
|
|
54
|
-
Four papers with figure sources, redacted per-request ledgers and campaign logs are on Zenodo: [design and trace evaluation](https://doi.org/10.5281/zenodo.21856873), [working memory under context shedding](https://doi.org/10.5281/zenodo.21980746), [ephemeral retrieval](https://doi.org/10.5281/zenodo.22142454), and [rotation and retention](https://doi.org/10.5281/zenodo.22142456), which is the campaign above. Narrative versions on [Medium](https://medium.com/@shane.conner/a-compaction-summary-is-one-record-doing-a-stores-job-3f46212ef059), interactive versions at [shaneconner.com](https://shaneconner.com/projects/pi-fold/), and the full chronology in [the experiment log](https://github.com/shaneconner/
|
|
54
|
+
Four papers with figure sources, redacted per-request ledgers and campaign logs are on Zenodo: [design and trace evaluation](https://doi.org/10.5281/zenodo.21856873), [working memory under context shedding](https://doi.org/10.5281/zenodo.21980746), [ephemeral retrieval](https://doi.org/10.5281/zenodo.22142454), and [rotation and retention](https://doi.org/10.5281/zenodo.22142456), which is the campaign above. Narrative versions on [Medium](https://medium.com/@shane.conner/a-compaction-summary-is-one-record-doing-a-stores-job-3f46212ef059), interactive versions at [shaneconner.com](https://shaneconner.com/projects/pi-fold/), and the full chronology in [the experiment log](https://github.com/shaneconner/fold/blob/main/docs/fold_vs_compaction/experiment-log.md).
|
|
55
55
|
|
|
56
56
|
## Limits
|
|
57
57
|
|
|
@@ -59,6 +59,25 @@ Four papers with figure sources, redacted per-request ledgers and campaign logs
|
|
|
59
59
|
- **The benchmark is narrow by construction.** It was built to reproduce specific things compaction handles badly, one to four runs per condition, and it says nothing about production behavior.
|
|
60
60
|
- **Folding is not a memory store.** It rotates transcript source out of the window; durable placement of what a session learned is a separate job, and the pairing is where the measured value sat.
|
|
61
61
|
|
|
62
|
+
## Configuration
|
|
63
|
+
|
|
64
|
+
`registerPiFold(pi)` works with no arguments, and the defaults are the configuration the campaign above actually ran: deterministic briefs, the invitation off, the tool-call diet at half the window, and a 0.80/0.20 band. Nothing here needs tuning.
|
|
65
|
+
|
|
66
|
+
The one thing worth adding is a long-term memory store. Rotation and retention are different jobs: folding gets stale material out of the window, a store keeps what the session learned. A handoff summary tries to do both in one record, written once under time pressure, bounded by the window it has to fit in. Folding is the rotation half and only that half.
|
|
67
|
+
|
|
68
|
+
Six options, and every other name is refused.
|
|
69
|
+
|
|
70
|
+
| Option | Default | Effect |
|
|
71
|
+
| --- | --- | --- |
|
|
72
|
+
| `thresholds` | `{ maxTarget: 0.80, minTarget: 0.20, consolidateAfter: 10, minFoldChars: 8000 }` | The band, set whole or not at all. The first two are proportions of the serving budget. `consolidateAfter` is how many visible roots a parent is owed. `minFoldChars` is the size a fold has to reach to be worth making, and the floor a gap between folds has to clear to stay raw. Validated atomically; an impossible policy is refused by name rather than clamped. |
|
|
73
|
+
| `providerInputBudget` | the transport's descriptor | The tokens this deployment may actually put in a request, already net of any output reservation. Every ratio, fence and budget on this page is a share of this one number. |
|
|
74
|
+
| `blacklistAutoFoldTools` | `new Set()` | The exception list. Every completed tool batch is foldable without an agent mark; name a tool here and its results stay raw. |
|
|
75
|
+
| `toolFoldThreshold` | `0.50` | The tool-call diet: a share in `[0, 1)` naming the oldest fraction of the window whose tool results are clipped in view. `0` turns it off. |
|
|
76
|
+
| `preCommitNotice` | `false` | The notice switch. False is the shape that won the campaign above: no carrier reaches the projection and every fold ships the runtime's own words. `true` states the window's status to the agent once per approach to a commit: where the commit fires, how far away it is, what is staged, what that frees, what is pinned and what the pin costs, with the verbs listed and no argument made for using any of them. |
|
|
77
|
+
| `noticeLeadShare` | `0.10` | How far below the commit trigger that notice speaks, as a share of the serving budget. A distance rather than a point, so it follows a band that moves. Read only when `preCommitNotice` is on. |
|
|
78
|
+
|
|
79
|
+
Four commands ship for the human: `/fold-status`, `/fold` (commit every staged mark now), `/fold-editor` (the interactive map of the window) and `/fold-settings` (edit the options above; each change is saved to `~/.config/pi-fold/settings.json` and takes effect in the running session).
|
|
80
|
+
|
|
62
81
|
## How it works
|
|
63
82
|
|
|
64
83
|
### The cache invariant
|
|
@@ -70,8 +89,8 @@ Four papers with figure sources, redacted per-request ledgers and campaign logs
|
|
|
70
89
|
### Marks and commits
|
|
71
90
|
|
|
72
91
|
<picture>
|
|
73
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/shaneconner/
|
|
74
|
-
<img alt="A completed unit becomes a pending mark that leaves the window and its cached prefix untouched. Marks repeat for free below maxTarget; at maxTarget one commit applies every standing mark in a single rewrite. From the brief, peek appends the exact bytes and expand restores them in place, both after verifying the SHA-256." src="https://raw.githubusercontent.com/shaneconner/
|
|
92
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/shaneconner/fold/main/media/marks-and-commits-dark.svg">
|
|
93
|
+
<img alt="A completed unit becomes a pending mark that leaves the window and its cached prefix untouched. Marks repeat for free below maxTarget; at maxTarget one commit applies every standing mark in a single rewrite. From the brief, peek appends the exact bytes and expand restores them in place, both after verifying the SHA-256." src="https://raw.githubusercontent.com/shaneconner/fold/main/media/marks-and-commits-light.svg">
|
|
75
94
|
</picture>
|
|
76
95
|
|
|
77
96
|
A mark moves nothing. The moment a tool batch or chapter closes, the runtime cuts it into a pending mark, up to eight cuts per pass, stalest first. The mark lives in durable state outside the window, so the projection stays byte-identical and the cached prefix survives. Marks accumulate for free until one commit applies all of them in a single rewrite.
|
|
@@ -110,27 +129,6 @@ Pi's automatic compaction stays enabled underneath and is intercepted by kind. A
|
|
|
110
129
|
|
|
111
130
|
Evidence ingestion writes read-only artifacts under the session directory's `pi-fold-evidence/` at mode `0444`, under a 512 MB session cap. It is always on: the artifacts are what an oversized result folds against, so a deployment that stopped writing them would keep its folds and lose what makes them lossless.
|
|
112
131
|
|
|
113
|
-
## Configuration
|
|
114
|
-
|
|
115
|
-
`registerPiFold(pi)` works with no arguments, and the defaults are the configuration the campaign above actually ran: deterministic briefs, the invitation off, the tool-call diet at half the window, and a 0.80/0.20 band. Nothing here needs tuning.
|
|
116
|
-
|
|
117
|
-
The one thing worth adding is a long-term memory store. Rotation and retention are different jobs: folding gets stale material out of the window, a store keeps what the session learned. A handoff summary tries to do both in one record, written once under time pressure, bounded by the window it has to fit in. Folding is the rotation half and only that half.
|
|
118
|
-
|
|
119
|
-
Six options, and every other name is refused.
|
|
120
|
-
|
|
121
|
-
| Option | Default | Effect |
|
|
122
|
-
| --- | --- | --- |
|
|
123
|
-
| `thresholds` | `{ maxTarget: 0.80, minTarget: 0.20, consolidateAfter: 10, minFoldChars: 8000 }` | The band, set whole or not at all. The first two are proportions of the serving budget. `consolidateAfter` is how many visible roots a parent is owed. `minFoldChars` is the size a fold has to reach to be worth making, and the floor a gap between folds has to clear to stay raw. Validated atomically; an impossible policy is refused by name rather than clamped. |
|
|
124
|
-
| `providerInputBudget` | the transport's descriptor | The tokens this deployment may actually put in a request, already net of any output reservation. Every ratio, fence and budget on this page is a share of this one number. |
|
|
125
|
-
| `blacklistAutoFoldTools` | `new Set()` | The exception list. Every completed tool batch is foldable without an agent mark; name a tool here and its results stay raw. |
|
|
126
|
-
| `toolFoldThreshold` | `0.50` | The tool-call diet: a share in `[0, 1)` naming the oldest fraction of the window whose tool results are clipped in view. `0` turns it off. |
|
|
127
|
-
| `postFoldNotice` | `false` | The invitation switch. False is the shape that won the campaign above: no carrier invites a brief and every fold ships the runtime's own words. `true` appends a standing invitation to improve a pending brief. |
|
|
128
|
-
| `workingMemory` | off | An in-window keyed dictionary the agent maintains beside the fold index, with `remember` and `recall` added to the tool. Offered to one run, which never called it. |
|
|
129
|
-
|
|
130
|
-
Four commands ship for the human: `/fold-status`, `/fold` (commit every staged mark now), `/fold-editor` (the interactive map of the window) and `/fold-settings`.
|
|
131
|
-
|
|
132
|
-
Upgrading from 2.x: the `fold` action is gone from the tool surface, since the runtime stages every completed unit itself; `guidance` is refused by name and `postFoldNotice` replaces it; `thresholds.freshTail` is gone, and a settings file carrying it is migrated with every tuned value kept. Existing sessions stay readable, folds and briefs included.
|
|
133
|
-
|
|
134
132
|
## Prior work
|
|
135
133
|
|
|
136
134
|
Two recent lines inform this one. Lossless hierarchical compaction, exemplified by LCM ([arXiv:2605.04050](https://arxiv.org/abs/2605.04050)) with a walkthrough at [losslesscontext.ai](https://www.losslesscontext.ai/), builds a summary DAG over older messages with lossless pointers to every original. Agentic context management, exemplified by [Letta](https://github.com/letta-ai/letta) and by [arXiv:2510.11967](https://arxiv.org/abs/2510.11967), gives the agent tools over its own memory. See also [arXiv:2607.00692](https://arxiv.org/abs/2607.00692).
|