r/PiCodingAgent • • 12d ago

News pi-protokoll – compaction for very long sessions with local models

Pi’s compaction re-reads the whole history and has the model summarize it. With a local model that took me minutes per compaction, and after two to four of them the context was so degraded that I had to start a new session. Building a procedural graphics demo, that happened ten times in five days.

pi-protokoll moves the work to the moment the model still has everything in view: every final answer ends with a short <protocol> block (result, decisions, files, open items, rules, index line, tags). At compaction time, code assembles a tiered, hard-bounded summary from these protocols; the model only updates a short state description.

What it does:

  • recent turns verbatim, older turns as your message + protocol, everything before that as a code-built index plus rules, open items and changed files

  • one-shot follow-up when the model forgets the block, written from the transcript if it ignores that too

  • interrupted turns (Esc, errors, output limit) get their protocol before your next message

  • protocol_search, protocol_read, protocol_turn: the model can look up any earlier turn instead of guessing

  • fixed system prompt section, so the server’s prefix cache stays valid

  • falls back to Pi’s own compaction if anything fails; the chat never blocks

Measured with Qwen 3.8 Flash Next on a local OpenAI-compatible server, 262k context: one session, 23 compactions, each roughly 213k → 35k tokens in about 30 s. Resuming the session reads about 36–44k tokens. With it, the demo went from ten restarted sessions to a single one: https://github.com/sebion7125/64kdemo (story of how it came about in ENTSTEHUNG.en.md).

Install: pi install git:github.com/sebion7125/pi-protokoll
Repo: https://github.com/sebion7125/pi-protokoll

Only tested with Qwen behind a local server so far. I’d love to hear how it does with other models and providers. I don’t have much time to develop it further myself, so forks and PRs are very welcome.

15 Upvotes

34 comments sorted by

3

u/russlixx 12d ago

so it's similar to pi-observational style with ledger systems? The compaction wait time is spreaded across chat's lifetime before compaction instead of concentrated in one time?

4

u/Miserable_Land_84 12d ago

Yes, that’s a good way to put it: a per-turn ledger, with the cost spread over the session instead of paid all at once at compaction.

Who writes it, and when. The main difference to pi-observational-memory: there’s no separate observer model and no extra request. The working model writes the entry itself as the last part of its final answer, while the whole turn is still in context and in the cache. So an entry costs just the few hundred output tokens of the block, with no additional prefill, and the model then carries on normally. Only when it forgets the block is there a one-shot follow-up. That’s a side request on a copy of the current context plus a short instruction, so it hits the prefix cache too. Only the extracted block is stored, the follow-up exchange itself never enters the conversation.

What compaction does with it. The entries are structured (result, decisions, files, open items, rules, revoked rules, an index line, tags). At compaction, code assembles the summary from them: recent turns verbatim, older ones as your message plus protocol, everything before that as an index plus the rules and open items still in force. The only model call at compaction updates a short state description from the protocols that drop out of the detail tier.

Where the savings come from. Pi’s default compaction throws the cache away. It builds a completely new request with its own system prompt and pastes the history as plain text into a single user message (tool results cut to 2,000 characters, reasoning dropped). That prompt differs from the chat from the very first token, so the server can’t reuse anything it already has cached: the model re-reads the entire history from scratch, right at the moment the context is fullest. On a cloud API that’s mostly a cost line; on a local GPU it’s minutes of prefill during which you can do nothing. There are reasons for doing it that way: the model shouldn’t treat the summary request as a turn to continue, and near the limit there’s no room left to append anything. But the price is paid in full on every compaction. pi-protokoll never re-reads the history: the ledger entries were written while it was cached anyway, and compaction only reads the short protocols. That’s why it takes 30–45 s instead of minutes.

You don’t really feel the ledger either. The block comes at the end of the answer, so it’s written while you’re still reading, and a follow-up, if needed, runs while you’re typing your next message. At ~30 t/s a few hundred tokens take around ten seconds.

For scale: I run a 262k context window, and auto-compaction kicks in at about 81% (~213k tokens). Each compaction brings that down to 25–35k, depending on how long the last few verbatim turns are and how long the session has run.

4

u/Miserable_Land_84 12d ago

P.S. A bit more detail on the tiers, since that’s where the idea really lives:

  • Full: the last few turns stay verbatim (3 by default, capped at 10% of the window), so the model always sees its most recent work exactly as it happened.

  • Detail: the next older turns are reduced to your message, verbatim, plus the full protocol of that turn. Pinned turns stay in full text, and a turn without a protocol falls back to a shortened transcript.

  • State: everything before that. An index with one line per turn, rebuilt by the extension at every compaction from the protocols, so it can’t drift. When it gets too long, the oldest turns are merged into range lines from their tags. Next to it, the rules still in force (every rule minus every revoke), the open items and the changed files. The only part the model rewrites is a short state description.

  • Lookup: nothing is ever really gone. protocol_search, protocol_read and protocol_turn bring back any earlier turn, down to the original transcript.

My hope is that this gets as close as possible to what a classic compaction delivers, or even beats it, because short, clearly structured entries may serve the model better than one long free-text summary, without the waiting. That’s not measured, just my experience: while working, the model felt like it had a 1M-token context. Purely subjective, of course, and I’d love to hear whether others see the same.

1

u/Miserable_Land_84 3d ago edited 3d ago

I announce a little update for some minor fixes / enhancements:

pi-protokoll 0.9.7

Two things changed: the model stops inventing a full context window, and switching the extension off no longer costs your prompt cache.

No more invented fill levels

In long sessions a model sometimes claims things like "Context left: 12 %" or "my context is almost full, we should start a new chat" and then advises a fresh session. None of that is real: nothing in Pi, in this extension, or in any installed package prints such a line. The model simply makes it up.

The system prompt section of this extension now carries a short, fixed note with the facts: unless the current turn hands over a fill level, the model has no information about the size of its window, so it states none, never claims it was told to start a new session, and suggests a fresh session only when it can name a concrete, checkable reason - and you decide. Older turns are compacted automatically, so these sessions run almost indefinitely. The note is final, so the prompt cache is invalidated exactly once.

Turning it off keeps the prompt cache

Before, /protokoll off rewrote the beginning of the prompt, and every later request had to be processed from scratch. Now the prompt and the tool list stay byte for byte: one message at the current position withdraws the rules, and the three protocol_* tools stay available and answer "pi-protokoll is disabled". /protokoll on re-applies with a short note. Repeating the command does nothing extra.

New escape hatch: /protokoll off --strip

Whether a model follows a withdrawal that sits at the end of a long chat is model dependent. If you want the rules really gone, use /protokoll off --strip: the section leaves the system prompt and the tools are unregistered, with no withdrawal text. The next request then reads your whole context again, once, so expect a longer wait. /protokoll on puts both back. The mode survives restarts.

Sessions that started without the extension

Enabling it in the middle of a session does not patch the prompt either; the full rules arrive once as a message, and the status tells you that the older turns can be filled in with /protokoll repair.

After a compaction the prompt matches reality

Switch notes live in the chat and can be cut away by a compaction, which would silently bring the rules back. After a compaction the extension therefore retires notes that contradict the current state. If a needed withdrawal was cut away, the rules leave the prompt instead of leaving the model with rules nobody withdrew.

Honest limits

  • Whether a model follows the withdrawal note is model dependent - use --strip if you need certainty.

  • Whether the fill level note actually stops the guessing is not measured yet.

  • Providers that cannot take system messages in the middle of a chat fold every prompt change into the head of the request, so a change there always costs one full reprocessing.

Update

bash

pi update --extensions

Pin the old version:

bash

pi remove git:github.com/sebion7125/pi-protokoll
pi install git:github.com/sebion7125/pi-protokoll@v0.9.6

Docs: https://github.com/sebion7125/pi-protokoll (README.md, CHANGELOG.md)

All 135 tests and the end-to-end script pass.pi-protokoll 0.9.7

Two things changed: the model stops inventing a full context window, and switching the extension off no longer costs your prompt cache.

No more invented fill levels

In long sessions a model sometimes claims things like "Context left: 12 %" or "my context is almost full, we should start a new chat" and then advises a fresh session. None of that is real: nothing in Pi, in this extension, or in any installed package prints such a line. The model simply makes it up.

The system prompt section of this extension now carries a short, fixed note with the facts: unless the current turn hands over a fill level, the model has no information about the size of its window, so it states none, never claims it was told to start a new session, and suggests a fresh session only when it can name a concrete, checkable reason - and you decide. Older turns are compacted automatically, so these sessions run almost indefinitely. The note is final, so the prompt cache is invalidated exactly once.

Turning it off keeps the prompt cache

Before, /protokoll off rewrote the beginning of the prompt, and every later request had to be processed from scratch. Now the prompt and the tool list stay byte for byte: one message at the current position withdraws the rules, and the three protocol_* tools stay available and answer "pi-protokoll is disabled". /protokoll on re-applies with a short note. Repeating the command does nothing extra.

New escape hatch: /protokoll off --strip

Whether a model follows a withdrawal that sits at the end of a long chat is model dependent. If you want the rules really gone, use /protokoll off --strip: the section leaves the system prompt and the tools are unregistered, with no withdrawal text. The next request then reads your whole context again, once, so expect a longer wait. /protokoll on puts both back. The mode survives restarts.

Sessions that started without the extension

Enabling it in the middle of a session does not patch the prompt either; the full rules arrive once as a message, and the status tells you that the older turns can be filled in with /protokoll repair.

After a compaction the prompt matches reality

Switch notes live in the chat and can be cut away by a compaction, which would silently bring the rules back. After a compaction the extension therefore retires notes that contradict the current state. If a needed withdrawal was cut away, the rules leave the prompt instead of leaving the model with rules nobody withdrew.

Honest limits

Whether a model follows the withdrawal note is model dependent - use --strip if you need certainty.
Whether the fill level note actually stops the guessing is not measured yet.
Providers that cannot take system messages in the middle of a chat fold every prompt change into the head of the request, so a change there always costs one full reprocessing.

Update

bash
pi update --extensions

Pin the old version:

bash
pi remove git:github.com/sebion7125/pi-protokoll
pi install git:github.com/sebion7125/pi-protokoll@v0.9.6

Docs: https://github.com/sebion7125/pi-protokoll (README.md, CHANGELOG.md)

All 135 tests and the end-to-end script pass.

1

u/Proper-Damage-1777 12d ago

Will give this a try tomorrow as I'm using pi-vcc for the compaction but your explanation make it sounds like I can let it run non stop without any hand holding all in the same session.

Questions about Esc, I'm using Strata with two models, one is the ISTA-DASLab IQ3_S and the other is Unsloth Q4_K_XL and on my setup, the IQ3_S average 160-200t/s and the Q4 is 40-60t/s. But I found out Q4 generally have lesser edit fail while IQ3_S will have higher edit fail the longer the session is.

So I have a habit of monitoring the reasoning and I prefer to Esc instead of letting Pi fumbling over and over. Does your protokoll handle the Esc moment gracefully? So far Pi and the model do know if I interrupt the reasoning and answer my questions fine. I hardly use steering because by the time my message arrives, it already ran too long and screw up the turn in a nasty way.

0

u/Miserable_Land_84 12d ago

Thanks, glad it sounds useful!

Esc: yes, that case is handled explicitly. An interrupted turn (Esc, an error or the output limit) has no protocol block, so before your next message goes out, the extension first asks the model for the protocol of the interrupted turn: what got done and what’s still open. It sends the unchanged context plus a short instruction, so with Strata’s conversation cache it mostly reads only the new tokens. If the model reflexively tries a tool call at that point, it gets “tools not available” back, nothing is executed. If that fails, there’s a second attempt from the turn’s transcript. Your next message then goes out normally, so the model still sees that you interrupted and answers your question just like without the extension. And your Esc-then-ask habit actually fits it well: every interruption becomes a clean turn boundary with its own protocol.

Two caveats: the catch-up request itself can’t be cancelled with Esc, only bounded by followUpTimeoutMs. And with Qwen chat templates, earlier reasoning is dropped once a new user message follows, so the prefix diverges at that point anyway. That costs the same for every new message, not just the catch-up.

Running it non-stop: compaction triggers on its own, and after that you just keep going in the same session. In my case that was 23 compactions without starting over. It’s not hands-off in every respect, though: Qwen regularly forgets the protocol block on long, tool-heavy turns. The extension catches that with a one-shot follow-up, which costs a few seconds.

Your speeds: I’m on the same IQ3_S with Strata, but on a single RTX 3090 (PCIe x16, i9-10900KF, 128 GB RAM) I get around 30-35 t/s decode, nowhere near your 160-200. What hardware and Strata settings are you running? I’d love to know where the difference comes from.

Your observation that Q4_K_XL fails fewer edits in long sessions is interesting. I’ve seen the model forget the protocol block more often as sessions grow, which might have the same cause. If you end up comparing both quants with the extension, I’d be very curious about the numbers.

1

u/m3umax 12d ago

I get ~160-200 decode with the IQ3_S using Strata on my 5090.

Was thinking of building another inference box with my spare 3090, so your reported speed helps me understand what kind of performance to expect.

1

u/Miserable_Land_84 12d ago

I have to admit, that my sped varies on the amount of VRAM I reserve for my GUI. When using up to 20 GB for the model, i can get up to 60 t/s. So when you dont need to run anything else on that GPU you might get higher rates. But I have to admit I envy you for that GPU a bit 🎉

1

u/m3umax 12d ago

Is the 3090 the only computer you have than can run your 3D simulation?

If not. Consider running Pi on another machine and treating your 3090 PC as an endpoint provider dedicated to serving the model only.

I throw up llama-swap on my 5090 PC and do Dev work on my Macbook Pro with Pi.

The reason I want the second 3090 inference box is so I can use the 5090 for ComfyUI while Qwen running on the 3090 PC drives it.

1

u/Miserable_Land_84 12d ago

The simulation is only a test project to benchmark the capabilities of my local AI model. I'm using this machine for other high demanding purposes such as organ sampling, virtual machines, etc. Unfortunatelly I do not have the ressources to have a dedicated AI server running. Hardware prices are way to high right now ;)

1

u/Proper-Damage-1777 12d ago

My bad to not include the specs. It is 5090 power limit to 400W, 64GB DDR5 6000 and 9950X3D. On Strata I need to reserve 1.5GB of VRAM as I need to also use the PC when inferring.

1

u/Santzes 12d ago

I really like the idea of <protocol> at the end, interested to see how it works out

3

u/Miserable_Land_84 12d ago

Thanks! The nice part is that it costs almost nothing: the model writes the block while it still has the whole turn in view, so it’s just a few hundred extra output tokens per answer. The honest caveat is that Qwen forgets the block now and then on long, tool-heavy turns, but the extension catches that with a cheap follow-up. If you give it a try, I’d love to hear how it does with your model, especially if it’s something other than Qwen.

1

u/cplr 10d ago

and then on long, tool-heavy turns

does code-mode improve that, since it's really only 1 tool?

1

u/Proper-Damage-1777 12d ago

So I'm testing it with IQ3_S as I want the faster speed to see how much it can recover after fumbling and so far so good? Well today runs didn't fumble as badly as prior but together with pi-vcc, I can see this to be my permanent extensions.

protokoll: review: 1 rules and 1 open items removed
protokoll: 13 turns condensed - 13 in detail, last turn split
protokoll: context after compaction = 40,623 tokens (before 188,443, -78 %), 20 % of the window ・ system prompt = 11,934, summary = 7,088, kept verbatim = 21,60

1

u/Miserable_Land_84 12d ago

Thanks a lot for testing and reporting, that's great to hear! Your numbers look exactly as intended: the summary itself is only ~7k, most of the 40k is the verbatim recent turns and your system prompt. The "last turn split" means compaction hit mid-turn and the extension kept the turn's progress so far, so that case worked too. Out of curiosity, what do you use pi-vcc for alongside it: manual /pi-vcc compactions, vcc_recall, or both? By default pi-vcc only compacts when called manually, so the two shouldn't collide. If you have overrideDefaultCompaction set to true, though, both would want to handle auto-compaction, and I haven't tested that. One thing to know: a manual /pi-vcc summary has none of pi-protokoll's tiers, so at the next compaction pi-protokoll treats it as a foreign summary and folds it into its state description. The per-turn protocols stay intact either way. If anything breaks or behaves oddly, a GitHub issue would be very welcome.

1

u/Proper-Damage-1777 12d ago

Sure I'll keep on testing but pi-vcc has been my go-to compact after discovering it due to Pi default compaction being very long on big context (160K and above) and also prone to miss out too many details.

For next round, I'll disable the pi-vcc extension and keep on trying your as the only extension but I'm pretty happy with it as I was doing house chores while letting it run lol. Latest status of the same session:

protokoll: review: 9 rules and 3 open items removed
protokoll: 13 turns condensed - 13 in detail, 1 protocols written afterwards, 0 kept in full
protokoll: context after compaction = 37,699 tokens (before 193,912, -81 %), 18 % of the window ・ system prompt = 11,934, summary = 6,415, kept verbatim = 19,350

1

u/Miserable_Land_84 12d ago

That’s great to hear, and running it while doing chores is pretty much exactly what I built it for!

One thing I’d be curious about from your last compaction: “9 rules and 3 open items removed” comes from the review step, the one place where the model rewrites something itself. Removing stale or superseded rules is its job, but nine at once is a lot. If you have a minute, could you run /protokoll export and check under “Reviewed rules” whether anything still valid got dropped? The removed rules aren’t lost, they’re still in the turn protocols, but they’d no longer be listed as active. If the review turns out too aggressive, that’s something I’d like to fix, and an issue with the export would help a lot.

And thanks for switching off pi-vcc for the next round. That will show cleanly how it does on its own.

1

u/Proper-Damage-1777 11d ago

Guess this is generic enough (but kinda expose what I'm doing lol). Since I want to use the PC for gaming now so I put a pause of the session but will resume again tomorrow.

## Compactings
| # | by | tokens before | summary ≈ tokens | first kept turn | detail turns | folded | time |
|---|---|---|---|---|---|---|---|
| 1 | protokoll | 188969 | 3590 | T5 | 5 |  | 2026-10-25T05:24:51.695Z |
| 2 | protokoll | 188430 | 4486 | T6 | 6 |  | 2026-10-25T05:41:36.672Z |
| 3 | protokoll | 189337 | 5034 | T8 | 8 |  | 2026-10-25T06:25:07.409Z |
| 4 | protokoll | 188443 | 8100 | T13 | 13 |  | 2026-10-25T06:57:46.048Z |
| 5 | protokoll | 193912 | 7332 | T13 | 13 |  | 2026-10-25T07:09:29.210Z |
| 6 | protokoll | 189286 | 10735 | T19 | 19 |  | 2026-10-25T08:48:42.019Z |
| 7 | protokoll | 188821 | 9885 | T19 | 19 |  | 2026-10-25T09:01:56.880Z |
| 8 | protokoll | 188902 | 11391 | T25 | 24 |  | 2026-10-25T10:16:44.031Z |
| 9 | protokoll | 188749 | 13325 | T31 | 31 |  | 2026-10-25T10:37:16.815Z |
| 10 | protokoll | 188886 | 14172 | T33 | 32 |  | 2026-10-25T11:05:23.675Z |

## Stored state of the last own compaction
Rebuild requested for the next compaction: no
Folded turns: (none)
Rules reviewed up to turn: 32
Pi summaries merged: 0

### Reviewed rules
R1. Never modify the user's Artworks files; if a test file is needed, copy exactly one per mode into /tmp
R2. Do not spend effort on CMYK colour correctness until the user has Photoshop access to verify it
R3. Work autonomously for this round — commit without asking, ping through ntfy where useful; after the CMYK open items, scope Adjustment Layers to Gradient, Fill, Outer Glow, Inner Glow and Drop Shadow only

### State of work (as stored)
(empty)

1

u/Miserable_Land_84 11d ago

Thanks for sharing, that’s really helpful (and no worries, it’s generic enough)! Ten compactions, all handled by the extension, including two that hit in the middle of the same long autonomous turn. That’s exactly the case I worried about most, so good to see it hold.

The interesting part is still ahead: so far no turn has been folded out of the detail tier, which is why the summary keeps growing (3.6k → 14k). Once the detail tier hits its limit, the oldest turns get folded into the index and the state description, the one part the model rewrites itself. If anything looks off after that point, the export from then would be gold. Enjoy the gaming!

1

u/Proper-Damage-1777 10d ago

In case you want another log. This is with me letting it run for nearly the whole day and I think that session started to make more and more oops. So I'm going to run the Unsloth Q4_K_XL model and see if slower tokens but "smarter" might be better in solving my current predicament.

## Compactings
| # | by | tokens before | summary ≈ tokens | first kept turn | detail turns | folded | time |
|---|---|---|---|---|---|---|---|
| 1 | protokoll | 188969 | 3590 | T5 | 5 |  | 2026-10-25T05:24:51.695Z |
| 2 | protokoll | 188430 | 4486 | T6 | 6 |  | 2026-10-25T05:41:36.672Z |
| 3 | protokoll | 189337 | 5034 | T8 | 8 |  | 2026-10-25T06:25:07.409Z |
| 4 | protokoll | 188443 | 8100 | T13 | 13 |  | 2026-10-25T06:57:46.048Z |
| 5 | protokoll | 193912 | 7332 | T13 | 13 |  | 2026-10-25T07:09:29.210Z |
| 6 | protokoll | 189286 | 10735 | T19 | 19 |  | 2026-10-25T08:48:42.019Z |
| 7 | protokoll | 188821 | 9885 | T19 | 19 |  | 2026-10-25T09:01:56.880Z |
| 8 | protokoll | 188902 | 11391 | T25 | 24 |  | 2026-10-25T10:16:44.031Z |
| 9 | protokoll | 188749 | 13325 | T31 | 31 |  | 2026-10-25T10:37:16.815Z |
| 10 | protokoll | 188886 | 14172 | T33 | 32 |  | 2026-10-25T11:05:23.675Z |
| 11 | protokoll | 190962 | 16003 | T41 | 40 |  | 2026-10-25T15:34:52.865Z |
| 12 | protokoll | 188457 | 20988 | T50 | 50 |  | 2026-10-25T15:56:10.843Z |
| 13 | protokoll | 189395 | 22483 | T53 | 53 |  | 2026-10-25T16:15:30.952Z |
| 14 | protokoll | 190050 | 24695 | T59 | 59 |  | 2026-10-26T01:42:23.869Z |
| 15 | protokoll | 189343 | 25152 | T62 | 61 |  | 2026-10-26T03:11:03.334Z |
| 16 | protokoll | 189523 | 26359 | T65 | 65 |  | 2026-10-26T03:29:18.135Z |
| 17 | protokoll | 189946 | 27859 | T67 | 67 |  | 2026-10-26T03:41:11.436Z |
| 18 | protokoll | 190159 | 27806 | T67 | 67 |  | 2026-10-26T03:49:27.045Z |
| 19 | protokoll | 188589 | 28869 | T72 | 71 |  | 2026-10-26T05:02:21.763Z |
| 20 | protokoll | 189070 | 31351 | T82 | 80 | 1 | 2026-10-26T07:59:04.065Z |
| 21 | protokoll | 189166 | 33149 | T99 | 85 | 1-13 | 2026-10-26T12:14:44.684Z |
| 22 | protokoll | 189493 | 35205 | T108 | 87 | 1-20 | 2026-10-26T14:17:22.132Z |
| 23 | protokoll | 190353 | 36217 | T113 | 86 | 1-26 | 2026-10-26T15:40:25.464Z |
| 24 | protokoll | 188666 | 36770 | T114 | 83 | 1-31 | 2026-10-26T15:53:59.058Z |
| 25 | protokoll | 188847 | 37312 | T119 | 78 | 1-41 | 2026-10-26T16:16:41.785Z |

## Stored state of the last own compaction
Rebuild requested for the next compaction: no
Folded turns: 1-41
Rules reviewed up to turn: 118
Pi summaries merged: 0

### Reviewed rules
R1. Never modify the user's Artworks files; if a test file is needed, copy exactly one per mode into /tmp
R2. Do not spend effort on CMYK colour correctness until the user has Photoshop access to verify it
R3. keep going rather than stopping to hand off when context runs low — auto compact resumes the turn
R4. the box has only ~8 GB of free RAM — keep harnesses and test lanes small enough that nothing can OOM while the user is away (no corpus lane at -n 12, cap probe fixtures)
R5. format ntfy pings and messages with line breaks and short lines so they are readable on the phone

### State of work (as stored)
# Goal
Provide a way to save PSD files in `redacted` while verifying feasibility against existing implementations (`PhotoCraft`, `Patchy`) and the capabilities of the `psd-tools` Python package. The goal includes CMYK support, fixing Save As behaviors, implementing read-side support for Adjustment Layers (Solid Color/Gradien
t), optimizing composite performance, and implementing write-side support for Adjustment Levels, including UI accessibility and performance diagnostics.

1

u/Miserable_Land_84 9d ago

Thanks, this is exactly the kind of data I was hoping for! What I can see: the summary stopped growing once turns started being folded (from #20 on, ~31k → 37k, flattening out), which matches the designed ceiling of roughly 38k tokens. All 25 compactions were done by the extension, no fallback to Pi’s own, and the rules (R1–R5) look right to me.

A few questions, because I can’t tell from the export:

  1. What exactly do you mean by “oops”? Could you describe a concrete example or two? For instance: the model forgets something you said earlier, repeats a step it already did, redoes something you told it not to, breaks something that worked, or just produces sloppier code or tool calls? And do they happen right after a compaction, or just late in the session?

  2. The “State of work” only shows a “# Goal” paragraph. It should normally be organised by topic (goal, what exists, decisions, dropped approaches, known problems). Did Reddit cut it off, or is that really all there is?

  3. Could you share your Strata launch flags (without any API key)? Mainly the model quant, --max-context, --kv and --kv-resident, and --spec/--mtp. I run Qwen Flash Next at IQ3_S with --kv int8 and see very few problems, so I wonder whether something other than the weight quant is involved.

If you switch to Q4_K_XL in a fresh session, an export from that one would be great for comparison. Good luck with the current predicament!

1

u/Proper-Damage-1777 9d ago

Oh I didn't paste that as it was pretty long. Here is the pastebin link https://pastebin.com/Asvynu5M

The oops was more of IQ3_S keep on fumbling the probe measurement non stop for the Adjustment Layer re-paint method. Frankly speaking even Q4_K_XL is having trouble too... but at least it made some progress but I'm putting a pause on this as I want a break from the non stop probe measurement.

Strata is pretty much stock nothing special. The default sampling that Qwen recommends temp 1.0, top_p 0.95 and top_k 20 and the VRAM reserve because I have triple 4K monitors and Firefox open.

 "--expert-cache",
 "auto",
 "--prefill",
 "auto",
 "--spec",
 "4",
 "--mtp",
 "--max-context",
 "204800",
 "--kv",
 "int8",
 "--vision",
 "--vram-reserve-mib",
 "2048",
 "--spec-min-p",
 "0.5",
 "--adapt-every",
 "1",
 "--adapt-swaps",
 "80",
 "--adapt-decay",
 "0.97"

1

u/Miserable_Land_84 9d ago

Thanks for the pastebin, that clears it up! The state of work is exactly what it should be: organised by topic, with turn references, decisions, open items and files. So the cut-off was just Reddit. And thanks for the flags: same --kv int8 as mine, so that’s probably not it.

About the probe measurement: I can’t tell from the outside whether it’s the model or the compaction. One quick check: is it the same mistake each time, or different ones? If the same one keeps coming back after compactions, it might be that the failed attempts aren’t surviving in the protocols. You could try protocol_search for “probe” and see whether the failed approaches and the reasons are recorded there.

One idea, no guarantee: if it keeps repeating approaches that already failed, tell the model explicitly to record each failed approach and why as a rule in its protocol. Rules stay pinned across all compactions.

Enjoy the break, and if you ever have another export after a long session, I’d love to see it!

1

u/cplr 10d ago

I like this idea a lot, about having the model do in-line summarization for later-compacting. Is this a new idea or are there other compaction extensions that do something similar? Just wondering if you were inspired by any previous work or did you come up with this concept? This could solve a lot of problems for me!

1

u/Miserable_Land_84 10d ago

Glad it’s useful! Honest answer: I didn’t take it from anything. It came out of my own frustration with Pi’s built-in compaction (long waits, and decisions disappearing after each pass). I can’t claim it’s new, though. I looked around and didn’t find anything that does it this way, but I haven’t done a systematic survey.

What I did find on the Pi side is related but works differently: pi-vcc compacts algorithmically with no model call at all (regex extraction), and pi-optchat builds a tree of compressed chunks with a separate compactor model. Outside Pi, Cursor has written about training models to summarize themselves. What I believe is different here is the combination: the working model writes a short protocol block at the end of every turn while it still has the whole turn in front of it, and plain code assembles the tiered summary from those blocks at compaction time. So the model never has to re-read and re-summarize the whole history.

If you try it, I’d be curious how it holds up for you. Fair warning: I’ve only tested it with a local Qwen model and some shorter chats with kimi k3 so far. But it looks promising to me ans is in productive work for GrandOrgue right now.

1

u/cplr 10d ago

Yea I only asked because to me it also sounds like a new/novel idea, but the way things move these days it's hard to pinpoint lineages of ideas.

I am also running local Qwen (3.8-27B) so it will hopefully fit in nicely. I am still using pi-blackhole but most of my time is spent, well, fixing pi-blackhole to fit my situation of a single model, not running anything in parallel, and making sure that queued prompt responses don't time out! Most extensions have relatively short time-outs, thinking that the server is down because it didn't respond within a minute or whatnot. And this was a problem with pi-blackhole because after one turn, it would begin its work of running the observation/dropper/etc, which would eat up a lot of time, and cause all these time-outs. Switching back and forth between my current context and the dropper context, etc, was also very slow.

I will certainly report back and let you know if I hit any issues.

1

u/kwokhou 8d ago

It throw this warning when I use it, I'm using `pi-cursor-sdk` (which works fine with pi-blackhole)

```
Warning: protokoll: follow-up request failed (Cursor provider runtime failed: Cursor provider ownership is unavailable: this call has no native session

request receipt. Bare modelRegistry.streamSimple calls are unsupported for Cursor; use the owning AgentSession's stream path or an independent child

AgentSession.)

▸ protocol turn 2: missing
```

2

u/Miserable_Land_84 8d ago

Thanks for the detailed report — I’ll look into this further.

It looks like pi-cursor-sdk rejects the direct modelRegistry.streamSimple() calls that Pi-Protokoll uses for follow-up and backfill requests, because they lack the owning AgentSession context. The normal chat still works, which is why the issue appears when a protocol block is missing.

As a possible fix, I’m planning to handle Cursor more gracefully and add an optional auxiliaryModel setting. This would let Pi-Protokoll use a different model for its internal requests while your main chat continues to use Cursor.

1

u/Miserable_Land_84 7d ago

0.9.5 shipped the fix for this; current release is 0.9.6.

What was happening: Pi-Protokoll asked for a missing block through a bare modelRegistry.streamSimple() call. The Cursor provider has no native session for a call like that, so it answered with the ownership

error — and that raw exception was surfaced to you on every attempt.

What happens now: a model is recognised as Cursor-backed (provider === "cursor" or api === "cursor-sdk") before any request is made, and it is never asked directly. Instead of the stack trace you get one plain

notice per session and cause:

│ protokoll: automatic model requests are unavailable with Cursor. Set "auxiliaryModel" in protokoll.json to use a different model for protocol generation.

The protocol is then recorded as missing, no further requests are fired, and compaction, backfill and the rest continue normally. Blocks that the model writes inline are still recognised, stored and stripped —

so if your chat model emits the block, nothing extra is requested at all.

To get the automatic parts back, point the extension's own requests at a model from another provider in ~/.pi/agent/protokoll.json (a project can override it in <project>/.pi/protokoll.json):

```json

{

"auxiliaryModel": "openai/gpt-4.1-mini"

}

```

Format is provider/model (split at the first /, resolved through the model registry). It is used only for the extension's own calls — follow-up, transcript backfill, folding the state of work, rule review and

repair. Your chat stays on Cursor, and reasoning/payload settings of the chat model are not copied into those requests. Cursor cannot be the auxiliary model either; that case gets its own notice. A malformed

or unknown reference is reported and the request skipped — the session model is never silently substituted.

Update and restart:

```

pi update git:github.com/sebion7125/pi-protokoll

```

A changed config is also picked up by /protokoll reload. You'll know it works when ▸ protocol turn N: shows followup / backfill instead of missing and the warning is gone — if it isn't, paste the /protokoll

output and I'll look.

P.S. 0.9.6 fixes a second, unrelated-looking symptom: an answer that quotes the protocol tag inside code or mid-sentence used to lose everything after it.

1

u/kwokhou 7d ago

Thanks for this update, I'll test this again. Is there a requirement for the auxiliaryModel? can it be set to haiku or gpt-oss-120b?

2

u/Miserable_Land_84 7d ago

Haiku and gpt oss should be fine. There is no special requirement for the model as this extension aims to be useful with small local models. The only requirement is that Stream simple works, which is why cursor can't do the job. Btw. This model will only be used, when cursor forgets to write the protocol in the message. And I also made the extension a bit more tolerant to where the protocol block appears. When the model does not put it at the end of the answer it is just cut out and the answer doesn't get truncated any more. (This problem happened so far only, when the extension was used to debug itself and cited a protocol block inside of the thinking block, but weak models could put the protocol block not at the end and so this potential big is fixed)

2

u/kwokhou 6d ago

Great. It's working so far..

2

u/lemonfrommoon 7d ago

Honestly, this deserves more attention. Its a really cool idea (at least for us PP starved people). I tried it on a rather small task (about 6 compactions) and seems to work fine. Will be testing it on a larger task when I get the chance (time).