Repository navigation
v0.44.2
This patch release is mostly about Windows and OpenCode 2. Magic Context no longer opens console windows that steal focus (#553), OpenCode 2 stays responsive while Magic Context's storage opens (#554), a git project can no longer split into two identities, and doctor merge-identities repairs existing splits (#555). It also deletes finished hidden sessions on OpenCode 2 (#558), restores the historian and dreamer on some OpenCode 1 setups after a 0.44.1 regression (#560), unwedges Rust-mode sessions stuck on a compaction marker (#561), stops a reply made only of Magic Context's markers from stalling a session (#563), keeps OpenCode responsive while history embeddings catch up (#564, #565), and never sends an unreduced conversation when the database is busy.
Upgrading
- No schema change. The database stays at v91, so hosts on 0.44.0, 0.44.1 and 0.44.2 can share it and no coordinated restart is needed.
- If you pinned 0.43.2 because of #554: 0.44.2 fixes the boot stall 0.44.0 could cause, but the restart storms in #554 also happened on 0.43.2 and are still being investigated. If your database is still at v90, the first 0.44.2 start migrates it to v91, after which 0.43.x refuses to open it, so upgrade every host that shares the database.
- OpenCode 2 does not install plugin updates on its own. Open
/plugins, select Magic Context and press ctrl+u, or runopencode plugin update. - Existing identity splits are not merged automatically. Run
npx @cortexkit/magic-context@latest doctor merge-identitiesto list them, then follow "Project identities" below. - OpenCode 2 under plain
opencode serve: leftover hidden sessions are removed bydoctor --fixwith OpenCode closed (see "Hidden sessions on OpenCode 2" below).
Windows (#553, @devsiac; #554, @morpheus9393)
- No more console windows. Process lists, git calls, update checks, Pi's historian and dreamer runs and
doctoropened PowerShell and CMD windows that took keyboard focus. Every child process Magic Context starts is now hidden. - OpenCode 2 answers
/healthwhile Magic Context's storage opens. 0.44.0 checked for other running hosts with synchronous process lists before opening the database, which on Windows could stall the server long enough for a supervisor to kill and restart it. (The restart storms reported in #554 also occurred on 0.43.2, with many OpenCode instances sharing one database; that part is still under investigation.) Those checks are now asynchronous and time-limited, so the server keeps answering while Magic Context starts. A slow but healthy open still registers Magic Context's tools if it finishes within 15 seconds. If storage stays unavailable longer, turns are refused with a notice until it opens, and restarting OpenCode brings the tools back. - The "another Magic Context RPC server is active" log line now appears only when that server is actually running. Before, it appeared for any recorded server, live or not.
Project identities (#555, @morpheus9393)
- A git project keeps its
git:identity across restarts. If git failed right after a restart (dubious ownership, a slowgit rev-list, a file not yet readable), the directory got adir:identity, and memories written then were invisible to the project's normal sessions. Magic Context now records each project's git identity in its storage folder. A directory with git metadata never gets adir:identity: if git fails, the recorded identity is used, and if none is recorded yet, memory features pause for that session. allow_home_projectrecognizes Windows spellings of the home directory (drive-letter case, forward and back slashes,\\?\prefixes), so a home session no longer slips past the check. A home directory that is a git repository uses itsgit:identity.doctorreports split projects. It warns when one directory has more than one identity and shows what is stored under each.doctor merge-identitiesrepairs a split. Without arguments it lists the splits it finds.--from <identity> --to <identity>previews exactly what would move without writing anything, and adding--applyperforms the merge. It refuses while OpenCode, Pi or ck-mc has the database open, prints the backup location and restore commands, backs upcontext.db, and merges in one transaction. Identical memories are combined, and different memories are both kept. Running it twice is safe. Projects in Rust mode are refused because their memories live in the module's store. The oldermerge-identityspelling still works. Details: Merge split project identities.
Busy database
- Magic Context never sends an unreduced conversation because the database is busy. Before, a locked
context.dbcould make a turn go to the model without Magic Context's changes, and in Rust mode an unreachable module could do the same whenever the raw history happened to fit. Now a turn retries the lock for up to about 16 seconds, then replays the last request Magic Context built for the session. If neither works, the turn stops with "Magic Context's database is busy (another process held it too long); send your message again." OpenCode 2 also shows a toast. This applies on OpenCode 1, OpenCode 2 and in Rust mode. With compaction off, turns pass through as before. - Background work doesn't retry the lock. Only the turn being sent retries; the historian, embeddings and other background jobs try once and pick the work up on their next run, so a held lock stalls the host for less time.
- The last good request replays more often. On OpenCode it was checked against messages Magic Context had already edited, so it was rejected as changed. It is now checked against the original messages. An assistant turn that starts with two thinking blocks from the same message is now accepted for Anthropic models, as is a turn after an empty errored assistant message. The thinking-block checks are shared by OpenCode, Pi and Rust mode.
Rust mode
- A compaction marker no longer wedges a session (#561, @iceteaSA). When the marker landed on a notice another plugin had added as a synthetic user message, every full pass failed with a coverage gap and every turn was refused. The marker no longer changes how that message is classified, and it is never placed on a synthetic message. Sessions already in this state recover on their next full pass. The raw-fallback refusal log line now shows whether its size estimate was trusted.
- Slow module responses are retried, not failed. A request that times out while the module is still working gets one more wait of up to 45 seconds. A full resync after
need_full_syncgets its own 45-second budget instead of whatever the first request left. A session parked after repeated failures tries the module again on the next turn when it has no last good request to replay. - Images are counted by their size in pixels. The historian trigger counted an inline image by the length of its base64 data, so a session with a few screenshots looked millions of tokens over budget. Images now count as width × height / 750 tokens (1 to 4,500 per image, 1,200 when the size can't be read), the same rule TypeScript mode uses. Sessions without images are unchanged.
- Passes on long sessions use less time and memory. They no longer copy stored tag contents, repeat block and timestamp lookups, or count tokens for attachments they don't need.
Embeddings (#564, #565, @null-axiom)
- Embedding catch-up no longer freezes OpenCode. After history embeddings were turned on, or the embedding provider or model changed, Magic Context re-embedded the history on OpenCode's main thread, and the app stopped responding for seconds at a time, Stop button included. The catch-up now runs after the turn in short slices that yield in between, paced so it can't take over the host. It is slower as a result. In a test with 1,500 compartments on OpenCode 1, the server answered every health check during catch-up (at most 323 ms).
- A fully embedded session isn't checked again every turn. The coverage check re-chunked and re-counted a session's whole history on each pass. It now remembers a finished session until new history is written or the embedding model changes, and counts without re-reading everything.
- Compartments that fail to embed back off. Instead of being retried every turn, they wait longer between attempts.
- The local embedding model still runs inside OpenCode's process. It's paced now, but a large catch-up with the local model can still slow the app. Leaving the app idle until catch-up finishes, or setting
embedding.provider: "off"while you work, avoids it.
Replies made only of markers (#563, @kido5217)
- A reply that is only Magic Context's markers no longer stalls the session. Some models, especially small local ones, end a turn with nothing but notation such as
§672§ [dropped §672§]or[cleared]. The check that neutralizes such replies missed a leading§N§tag and didn't know[cleared], so the reply was sent back to the model and encouraged more of the same. It now recognizes these forms, and the same rule applies in TypeScript mode, Pi and Rust mode. It still leaves prose that merely mentions a marker alone, and it changes a reply only on a pass that already rebuilds the prompt cache. In Rust mode, an assistant reply that is only whitespace is now replaced the same way, as TypeScript mode already did.
OpenCode 1
- The historian and dreamer get the model's output limit again (#560, @Sugaroverdose). 0.44.1 removed it when
historian.maxTokensordreamer.maxTokenswas unset, and some providers then returned no output at all. An unset cap now leaves OpenCode's own limit in place. OpenCode 2 and Pi were not affected.
Hidden sessions on OpenCode 2 (#558, @morpheus9393)
- Finished historian and dreamer sessions are deleted. Deletion now targets the session's own directory, and a failed delete is logged and kept for a later attempt instead of being counted as done.
- Plain
opencode serve(for example under OpenChamber) gives plugins no way to delete sessions. Magic Context now logs how many finished sessions are waiting, once.doctorreports the same count, anddoctor --fix, run with OpenCode closed, backs up the OpenCode store and deletes only sessions Magic Context marked and recorded as its own. It checks running processes and database locks first (on Windows too) and refuses if it can't confirm OpenCode is closed.
Dreamer
verifyworks from the git diff. In git projects, it now receives what changed in each memory's files since that memory was last verified: the diff itself when it's small, or the changed line ranges when it's large. A memory whose files didn't change in a way that affects it is confirmed without re-reading files. Memories never verified before, and projects without git, are checked as before.- The dreamer's file reads are capped on OpenCode. A
readin averifyor memory-mapping run returns a bounded amount of text and says how to read further by line range, instead of loading whole large files into the run. curategets its whole category up front. It no longer lists memories page by page and re-reads the same lists; large categories are split into parts, with likely duplicates across parts found beforehand.- Tool-using tasks have a token budget.
verify, memory mapping,curateand the other tasks that loop over tools now stop at a per-task budget of prompt tokens (input plus cache reads and writes). Near the budget, the run is asked to report what it has checked so far, and that partial result is kept. Further tool calls are refused. A run that keeps going stops withtoken_budget(MC-D11 in/ctx-status). The tool list never changes mid-run, so the prompt cache survives. Where the host can't refuse tool calls (OpenCode 2's hidden sessions, Pi without Magic Context's own extension), the run is stopped at the budget instead. Setdreamer.tasks.<task>.token_budgetto change a task's budget. maintain-docsreviews only what changed. In git projects, it now reads the diff since its last run againstARCHITECTURE.mdandSTRUCTURE.md, and doesn't start when nothing relevant changed. It still only writes proposals, never the files themselves.
Dreamer settings and /ctx-dream (#556, #557, @G0-0000)
promotion_thresholdkeeps its default when a task sets only a schedule. Apromote-primersblock with just ascheduleneeded 3 candidates instead of the documented 2.review-user-memoriesdefaults to 3 andpromote-primersto 2./ctx-dreamshows the real backlog. On OpenCode and Pi, retrospective and maintain-docs counted the whole project instead of the work since their last run, so the numbers never went down. The end panel now lists the same tasks as the start panel, once, and recorded dream runs keep the backlog left after the run.
Search
- Every OpenCode session is recorded under its project. Sessions that never ran a Magic Context pass (some child sessions) had no project record, so history search and the Dashboard couldn't place them. They're recorded when created now, and a one-time pass fills in older ones.
- Long questions find results again.
ctx_searchrequired every word of a long natural-language query to match, so some returned nothing. When no result matches every word, it now falls back to matching any of them.
Smart notes
- A condition that can't be checked backs off for a week. When a note's check fails in a way that will repeat, such as a source response over the size limit, Magic Context retries weekly instead of on the usual schedule. It records the reason on the note ("Condition can't be checked: …; rewrite it"), and
ctx_noteshows it when the note is read in Rust mode. Temporary failures keep the usual retries.
Pi
- Historian and dreamer runs stop at the same step limits as on OpenCode. A run that exceeds its limit is ended and reported instead of continuing. Each run also logs a summary of its steps, tool calls and prompt size, and a warning when another Pi extension changed its system prompt.
Dashboard (#559, @dai1012)
- Converted OpenCode 1 to 2 stores show every session. The Dashboard read only the OpenCode 1 tables when both were present, which hid newer OpenCode 2 sessions. It now reads both and merges them by session. The Dashboard is released separately, so this arrives with the next Dashboard release.
Known limitation
ctx_reducedrops don't follow Pi's/treeor OpenCode's/undoyet (#562, @tenshiak). A drop requested on a branch you left can still hide a message on the new one. Nothing is deleted:ctx_expandrestores the content. See Context reduction.
Other
- Clearer logs in Rust mode: a full resync now logs why it was needed, and slow passes log at info level.
Credits
Thanks to @devsiac (#553), @morpheus9393 (#554, #555, #558), @G0-0000 (#556, #557), @dai1012 (#559), @Sugaroverdose (#560), @iceteaSA (#561), @tenshiak (#562), @kido5217 (#563) and @null-axiom (#564, #565) for the reports.