Repository navigation
[pi-plugin] expose ctx-flush and ctx-wrapup triggers + results via the pi.events bus. #679
Copy link
Copy link
Closed
Labels
feature requestNew feature or capability requestNew feature or capability request
Description
Short description
Expose the /ctx-flush and /ctx-wrapup actions on the Pi event bus so other extensions can request them and read a structured result.
What problem does this solve?
- Both ctx-flush and ctx-wrapup actions are only reachable as slash commands. An extension cannot trigger either, and cannot tell whether a request was applied, refused (
compaction-off, nothing to wrap up) or failed without parsing chat output. - The right moment or trigger is often known outside Magic Context: a task or workflow boundary, a handoff, an idle or scheduled window, a session being parked, a provider or model switch, an orchestrator choice. Concretely, as an example, any cache bust presents an opportunity to flush - and this allows more complex cache aware behaviour (variable thinking/tool change behaviour, dynamic costs/TTL) without embedding a cache tracker.
- Virtual models make this concrete. Pi's
registerVirtualModelhides the physical model from extensions (earendil-works/pi#10318), so Magic Context's per-model cache assumptions (cache_ttl, thresholds) resolve against the virtual model, and a physical switch that invalidates the cache is not observable. Only the registrar knows when it happens. - Pi's own cache warming hits the same virtual/physical mismatch (earendil-works/pi#10536).
Proposed solution
Listen on pi.events for magic-context:flush and magic-context:wrapup, run the same code as the commands, and answer on magic-context:flush-result and magic-context:wrapup-result.
- Request: optional
{ sessionId?, messagesToKeep? }. NosessionIdmeans the active session;messagesToKeepfollows the command's rule (positive integer, default 20); anything else is rejected. - Result:
{ sessionId?, status: "success" | "skipped" | "failed", reason? }pluspendingOps(flush) ormessagesWrappedandcompartmentsWritten(wrapup).reasonis machine-readable (compaction-off,no-live-context,nothing-to-wrapup,invalid-request, ...). - Only the session with a live Pi context can be targeted; any other session is refused with
no-live-context. - The command bodies move into shared functions, so the slash commands behave as before. Nothing runs unless a request arrives, subagents register no listeners, and there is no schema, migration or cache-stability change.
Harness coverage: Pi and OMP (shared pi-plugin). OpenCode 1, OpenCode 2 and the Rust module are not applicable: they have no in-process event bus.
Alternatives considered
- Resolve per-model settings against the physical model inside Magic Context. Pi does not expose it where Magic Context runs (#10318, open), and even once it does, which identity governs TTL and thresholds, and whether retries, failovers or sticky routes count as one cache, is the registrar's routing policy rather than Magic Context's.
pi.sendUserMessage("/ctx-flush", { expandPromptTemplates: true }). It returnsvoid, so there is no outcome, it triggers a turn, and it cannot name a session.- Magic Context inferring the moment itself (for example flushing on every model change). It cannot know whether the caller treats that as a boundary, and it would change default behaviour and risks exceeding scope of this plugin.
Area
Pi plugin
Additional context
- Implementation with tests exists and will be opened as a draft PR once this is
design-approved. Has been tested live with virtual model router triggered compaction. - Files:
packages/pi-plugin/src/ctx-lifecycle-events.ts,commands/ctx-flush.ts,commands/ctx-wrapup.ts; docs indocs/architecture/pi.mdandPARITY.md. - Open questions: should the event names and
reasonstrings be a documented public contract, and should results echo an optional caller-suppliedrequestIdso concurrent requests for one session can be told apart?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
feature requestNew feature or capability requestNew feature or capability request
Activity
Shrub24 commentedon Oct 14, 2026
Ah, my mistake - I missed that Magic Context already observes the physical model through assistant metadata. That exposes a deeper issue:
The next context pass compares that physical identity with the selected virtual route, incorrectly detects a model switch, and clears reasoning-replay state. Previously removed thinking then returns and causes another cache rebuild, even though the physical model hasn’t changed.
I’ll close this issue and open a separate one for that bug first.