fix: honest session_state source label — "compaction" only after real compaction - #996
Open
donwellsav wants to merge 1 commit into
Open
fix: honest session_state source label — "compaction" only after real compaction#996donwellsav wants to merge 1 commit into
donwellsav wants to merge 1 commit into
Conversation
buildAutoInjection hardcoded source="compaction" while the pi adapter
injects the block on every agent start, causing models to falsely believe
their context was destroyed (false-loss cascade).
- source is now a REQUIRED parameter (fail-safe, no silent default)
- fidelity line ("full history persists in the session transcript") only
on genuine compaction; routine injection carries no extra line
- pi adapter tracks session_compact via _pendingCompactLabel: the first
post-compact turn is labeled "compaction", routine turns "active_memory";
flag read-and-cleared at handler top (never strands) and reset on
session_shutdown (never leaks across sessions)
- genuine compact paths pass "compaction" explicitly:
hooks/sessionstart.mjs, opencode plugin (experimental.session.compacting)
- tests: tests/auto-injection-label.test.ts (5 cases)
Full suite: 4721 passed, 1 pre-existing env failure (tests/core/server.test.ts
CONTEXT_MODE_PROJECT_DIR cascade — fails on clean base too).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
hooks/auto-injection.mjshardcodes the wrapper label:but the pi adapter injects that block on every
before_agent_start— notjust after a real compaction (the code comment says so itself: "Pi-3 + Pi-4:
Always build active_memory (not just post-compact)"). The file header of
auto-injection.mjsstill documents the original invariant ("Only fires onsource === 'compact'"), which the pi adapter silently broke.
Observed impact (2026-07-24): a pi session with context-mode active had
zero compaction events in its transcript, yet the standing
source="compaction"marker led two different models to declare theircontext destroyed and ask the user to re-provide decisions that were fully
visible in context — a false "context loss" cascade.
Fix
The label now tells the truth, on every path:
buildAutoInjection(events, source)—sourceis a requiredparameter (fail-safe: no default, so no present or future caller can
silently emit the wrong label).
"Context was compacted; full history persists in the session transcript."tells the agent whathappened and where its history lives (the two facts missing in the
incident). Routine per-turn injection carries no extra line, so the
~500-token content budget and per-turn token cost are unaffected.
session_compactvia_pendingCompactLabel: thefirst
before_agent_startafter a real compaction is labeled"compaction"; all routine turns are labeled"active_memory". The flagis read-and-cleared at the top of the handler (can never strand
trueandmislabel a later unrelated turn) and reset in
session_shutdown(can neverleak across sessions in the same process).
"compaction"explicitly:hooks/sessionstart.mjs(source === "compact") and the opencode plugin(
experimental.session.compacting) — the latter would otherwise have beenrelabeled
active_memory, inverting the bug on that platform.Tests
New
tests/auto-injection-label.test.ts(5 cases): both labels, fidelityline presence/absence, empty-events path, required-parameter loudness, and an
honest budget assertion (content ≤ 500 tokens + unbudgeted wrapper/fidelity
overhead; P2-overflow fixtures excluded by design).
tests/pi-extension.test.ts+tests/opencode-plugin.test.ts: 125/125 passtsc --noEmit: clean(
tests/core/server.test.ts›CONTEXT_MODE_PROJECT_DIRenv cascade) ispre-existing and environment-related: it fails identically on a clean
checkout of
mainin the same environment and does not touch this codepath.
Notes for review
build/pi-extension.jsin the published tarball contains a stale duplicateof the per-turn injection call site. Nothing in the package references it
(
package.json→pi.extensionspoints atbuild/adapters/pi/extension.js);it may be worth deleting in a separate cleanup.
compactions; no event-selection, priority, or budget logic was modified.