Skip to content

v0.20.0

Latest

Choose a tag to compare

@github-actions github-actions released this 15 May 13:15

v0.20.0 — Pi parity fixes, mid-turn cache stability, key-files redesign

What's new

Fixed Pi parity gaps with OpenCode

  • Long-running Pi sessions durably compact. Pi's compaction marker now writes correctly across the visible message branch, so historian publications actually shrink getBranch() on every run instead of accumulating forever. Tool-heavy sessions that previously grew without bound until provider overflow now stay healthy through normal scheduled compaction.
  • Pi understands its own context pressure. Scheduler thresholds, force-materialization at 85%, and emergency block at 95% now compute pressure from input tokens only (matching the wire payload), respect provider-reported overflow limits, and reset stale persisted state on restart and model switch.
  • Pi has a built-in todowrite tool. Magic Context registers a todowrite tool for Pi sessions matching OpenCode's wire shape. Synthetic todowrite injection on cache-busting passes preserves your task list across compaction the same way it does on OpenCode.
  • Pi gets project orientation content. <key-files>, <project-docs>, and <user-profile> blocks now render in Pi's system prompt the same way they do on OpenCode, using the same project-scoped state.

This required a major refactor of the Pi context handler. The full Pi e2e suite (37 active scenarios) passes end to end.

Mid-turn execute decisions defer to turn boundaries

Anthropic prompt-cache continuity matters most during the multi-step tool-use turns that fill the middle of a long session. Previously, if the scheduler decided to execute heuristic cleanup and queued tool drops mid-turn, that cleanup ran on the very next defer pass while the assistant was still working through its tool calls — busting the cache and forcing the rest of the turn through a cold prompt.

Mid-turn execute decisions are now deferred until the turn ends. The scheduler still detects when execute would normally fire and records the intent durably; at the end of the next pass that finishes execute-gated work successfully, the deferred flag is cleared. Safety paths (force-materialize at 85%, explicit /ctx-flush, subagents) bypass the deferral as before.

Net effect: multi-step turns now keep their cached prefix through tool calls instead of each step paying a cache-rebuild cost.

Key files are now project-scoped, symbol-stitched, and version-invalidated

The pinned-key-files system has been redesigned end to end:

  • Project-scoped. Key files live in a project table, not session storage, so every session in the same project sees the same orientation set without re-evaluation.
  • AFT-stitched content. The dreamer asks an AFT-enabled subagent to produce one structured stitched block per file — outline plus selected full implementations — instead of dumping raw bytes. Files you read frequently get accurate symbol-level context, not whole-file dumps that blow the budget.
  • Version-invalidated cache. A shared version counter coordinates injection caches across OpenCode and Pi. Dreamer updates atomically replace the rows and bump the version in one transaction; running sessions pick up the new content on their next cache-busting pass.
  • Pi parity. Pi sessions render the same <key-files> block as OpenCode.

Disk drift is handled gracefully: stale content updates queue without busting the in-memory rendered block. Unreadable files start with stale_reason='missing' and stay out of injection until they're available.

Pi 0.74 is the new minimum

Pi has moved to the @earendil-works/* package scope and github.com/earendil-works/pi-mono. Pi 0.74 or newer is required for the v0.20 plugin. The unified CLI ships with engines.node >= 24 to match Pi's runtime.

If you're on an older Pi:

# Update Pi
pi update --self
# Or via npm
npm install -g @earendil-works/pi-coding-agent@latest

What's fixed

  • magic-context doctor --force on cold caches. When OpenCode's plugin cache had a populated node_modules/ but no root package.json (e.g. an interrupted install), the auto-update path failed to resolve the install context and silently skipped the upgrade. Doctor now seeds a minimal root package file so subsequent updates succeed (issue #73).

  • OpenCode session deletes no longer pass a directory query. The client.session.delete call for hidden child sessions (historian, dreamer, sidekick, compressor) was passing a directory parameter that OpenCode middleware used for plugin context selection, creating a small risk of cross-session deletion on unusual path-normalization cases (issue #72).

  • Dreamer key-files lease. The post-task key-files phase ran a long AFT-and-LLM pipeline outside the dreamer's lease-renewal loop, so on slower models the lease could expire mid-task and the final commit would be rejected. Lease renewal now wraps that phase.

  • ensureColumn race under concurrent startup. When OpenCode and Pi started simultaneously against a pre-upgrade database, the column-add path could fail with duplicate column if both processes raced. The helper now treats a sibling-won race as success.

  • Pi restart no longer leaves a stuck historian flag. If Pi was killed mid-historian, the compartment_in_progress flag would survive restart and block future historian runs. The flag now clears on init when no historian is actually in flight.

  • Context usage caching staleness. Persisted pressure was preferred even when it predated a model change, occasionally causing scheduler decisions against the wrong context limit on the first turn after switching models. First-pass and model-switch invalidation now clear stale state before the scheduler reads.

  • todowrite priority is now genuinely optional. Pi sessions where the model omitted priority in a todowrite call had their snapshots silently dropped because the normalizer required priority. Missing priority now defaults to "medium" (matching OpenCode behavior) so capture and replay always work.

  • Auto-update install context resolution. Same as doctor --force above — applies to the in-session auto-update hook too.

Upgrade

# OpenCode
npx @cortexkit/magic-context@latest doctor --force

# Pi (requires Pi >= 0.74)
pi update --self
npx @cortexkit/magic-context@latest setup --harness pi

If you're upgrading from a version older than 0.19, run doctor --force to refresh the cached plugin install.