Repository navigation
Moved session: stale history boundary → MC-H04 blocks every request #702
Description
Short description
A session moved to another project directory gets every request blocked with MC-H04: the cached history boundary exists but no longer sorts before the first live message, and /ctx-recomp cannot repair it from the old project's instance.
What happened?
Environment at incident time: MC 0.47.0, OpenCode v2.0.26, macOS arm64. Verified against 0.49.0 dist: classifyAbsentBoundary and the re-anchor path are byte-identical — still reproduces.
Case 1 (main): session moved between projects
Session moved once via OpenCode 2 session_move (previous directory ~/Ansible, new ~/Programming/trainings/ai-class, one location-switched row in session_message).
- The boundary row
msg_12a9337e30012hQvQHjukAWwcWexists insession_message(seq 144), but in the moved session's view the first live message ismsg_12a938311002ikUeRMPynNWKFG— the boundary does not sort before it.boundaryPrecedesWindowis false, so classification goes torefused:
[2026-10-11T16:23:33] prefix trim: boundary msg_12a9337e30012hQvQHjukAWwcW absent from current messages; pass=priced; no in-pass trim applied (degraded pass N; boundary does not sort before the first live message msg_12a938311002ikUeRMPynNWKFG; whole window served until a cache-busting pass moves the boundary into the window)
[2026-10-11T16:23:33] history boundary unresolved: prefix trim refused and the untrimmed request estimate 188048 (trusted=true) exceeds the context limit 187500; not sending it
[2026-10-11T16:23:33] v2 refusal: ... UnresolvedHistoryBoundaryError: ... (MC-H04)
- 9 refusals over ~15 h (degraded pass reached 235). User-visible MC-H04 text says the boundary "is missing from the OpenCode store" — it isn't:
select count(*) from session_message where id='msg_12a9337e...'= 1. The misleading text sends the user to/ctx-recomp, which then fails:
[2026-10-12T07:39:36] historian prompt failed: HiddenCompletionRefusal message="hidden_prompt_unrecognized: hidden child ses_ed0f27f2fffemAIRqjii0mfhc3 is bound to ~/Programming/trainings/ai-class, not to this instance's ~/Ansible" code=hidden_prompt_unrecognized
So the instance that would advance the boundary refuses the repair, and the instance whose directory matches isn't asked.
- The 0.45.0 re-anchor (OpenCode 2: a converted session whose compartment boundary is missing from the store serves the whole window on every pass (provider HTTP 400, no self-recovery) #590) doesn't help:
findVisibleReanchorIndexhandles boundary rows deleted from the store; here the row is present-but-out-of-order, so it classifies asrefused, notmissing.
Recovery: reopening the session in its new directory triggered historian recovery on load from the matching instance (child bound correctly, publish completed, new boundary), healthy since:
[2026-10-12T08:12:36] transform: historian recovery triggered on session load after 2 failure(s)
[2026-10-12T08:13:17] historian publish completed: compartments=1 range=20-25
[2026-10-12T08:39:32] prefix trim: boundary msg_12ae31746001HSzXX7cLUrFeID precedes the first remaining message ...; nothing to cut
doctor still records the failure reason on the session (historian_runs: 8 total, 6 success, 2 failed, lastFailureReason: ... hidden_prompt_unrecognized ...).
Case 2: same refusal arm without a move
Same day, a never-moved session hit the identical refusal (estimate 344916 vs limit 187500): rows were deleted out of session_message (sparse seq gaps), so the first live message ended up older than the boundary — same refused arm, self-healed after historian recovery advanced the boundary.
Diagnostics
Plugin version
0.47.0 at incident time (current 0.49.6; logic byte-identical in 0.49.0)
OpenCode version
v2.0.26 at incident time (current v2.0.31)
Platform
macOS 27.0.1 arm64
Client
OpenCode TUI (CLI)
Log output (optional)
[2026-10-11T16:23:33] prefix trim: boundary msg_12a9337e30012hQvQHjukAWwcW absent from current messages; pass=priced; no in-pass trim applied (degraded pass 235; boundary does not sort before the first live message msg_12a938311002ikUeRMPynNWKFG; whole window served until a cache-busting pass moves the boundary into the window)
[2026-10-11T16:23:33] history boundary unresolved: prefix trim refused and the untrimmed request estimate 188048 (trusted=true) exceeds the context limit 187500; not sending it
[2026-10-12T07:39:36] historian prompt failed: HiddenCompletionRefusal message="hidden_prompt_unrecognized: hidden child ses_ed0f27f2fffemAIRqjii0mfhc3 is bound to ~/Programming/trainings/ai-class, not to this instance's ~/Ansible" code=hidden_prompt_unrecognized
[2026-10-12T08:12:36] transform: historian recovery triggered on session load after 2 failure(s)
[2026-10-12T08:13:17] historian publish completed: compartments=1 range=20-25
Activity
magic-alfonso commentedon Oct 16, 2026
Thanks for the detailed report, including the store check and the recovery log. That's enough to start without more data from you.
We see two problems here, and are looking at both:
/ctx-recomp./ctx-recompfrom the old project's instance can't repair it, because the hidden historian child belongs to the session's new directory.Your second case, with rows deleted out of
session_messagein a session that never moved, hits the same refused path, so the fix needs to cover that too. We'll reproduce both on a real OpenCode 2 host and post here when a fix is ready.magic-alfonso commentedon Oct 17, 2026
Fixed in v0.49.8. When a session's summarized-history boundary still exists in the OpenCode database but falls outside the loaded message window (a moved session, or deleted old rows), Magic Context now places it using its stored order instead of refusing the turn. Recovery commands (
/ctx-recomp,/ctx-wrapup) also reach the plugin instance for the session's current folder. Both of your scenarios go through on a real OpenCode 2.0.31 host.One upgrade note: some OpenCode 2 sessions see a one-time change in the cached request prefix after updating, because previously dropped host instruction updates are now kept. Thanks for the detailed evidence.