Skip to content

v0.27.0

Choose a tag to compare

@github-actions github-actions released this 24 Jun 17:52
· 2578 commits to master since this release

v0.27.0: Dreamer V2, Primers, and the CortexKit config move

The biggest release since the V2 historian. The background dreamer is rebuilt into independently-scheduled tasks, two new memory capabilities ship (Primers and friction-learning), embedding storage stops throwing away your vectors on a config change, and configuration moves to a shared CortexKit location. Plus a deep correctness, security, and cross-harness hardening pass.

Dreamer V2: per-task scheduling

The dreamer is no longer one monolithic nightly run. Each maintenance task has its own cron schedule and its own model, configurable in the setup wizard, the dashboard, or magic-context.jsonc:

"dreamer": {
  "tasks": {
    "verify":            { "schedule": "0 3 * * *" },
    "curate":            { "schedule": "0 4 * * 0" },
    "classify-memories": { "schedule": "0 6 * * *" },
    "retrospective":     { "schedule": "0 5 * * *" },
    "maintain-docs":     { "schedule": "" }
  }
}

Point a lightweight model at the routine tasks and a stronger one at just the task that needs it. Set a schedule to "" to turn a task off. Every dreamer task is cache-safe by design: it never busts your prompt cache, no matter when it runs.

Each task now also runs with a dedicated prompt and a least-privilege toolset, so a memory-classification pass can't read files and a docs pass can't touch memory.

New: memory importance scoring (classify-memories)

Scores each memory's importance by blending how durable the fact is with what your project is actively working on, plus its scope and whether it is safe to share with teammates. When the injected memory block is over budget, the most relevant memories stay in context and the least relevant drop first (they remain fully searchable via ctx_search). Runs in the background, completely cache-neutral.

New: learning from friction (retrospective)

Learns from the moments you had to correct or re-explain something and records the durable lesson as a project memory, so the same friction does not recur. It is cheap by default: it only does real work when a cheap pass detects a genuine correction pattern, and it reads only your own typed messages (never tool output or other content), with the learning distilled into a third-person rule rather than your raw words. On by default; turn it off anytime.

New: Primers

Primers are durable, standing answers to the questions that keep coming up about how your project works ("how does the transform pipeline stay cache-stable?", "where does session state live?"). The historian notices when the same question recurs across days and promotes it to a Primer; the dreamer then keeps the answer current by investigating the actual code (an open-book read of the relevant files), not by re-summarizing what is already in context. Stale Primers sink out of the render budget over time but stay in the database.

Smart notes that check their own condition, cheaply

A smart note (ctx_note with a surface_condition) resurfaces when its condition becomes true. Until now the dreamer re-checked that condition by asking an LLM every single time it ran, all the way up until the condition was finally met. For something like "resurface when PR #42 is merged," that meant paying for a full model call on every check, possibly for days.

Now, for a deterministic condition like a GitHub PR being merged, a release tag being published, or a file appearing on disk, the dreamer writes a small reusable check once and then simply runs that script on each cycle. The repeated, open-ended LLM evaluation becomes a cheap, deterministic run that verifies the real-world signal (PR state, release tag, file contents) and surfaces the note at the right moment. The script runs in a locked-down WASM sandbox with a read-only, SSRF-guarded capability API, so a note's condition can safely reach out to check the world without ever touching anything it should not.

Memory maintenance, split so neither task starves

The old combined memory task is now focused tasks:

  • verify checks memories against their backing files and fixes or removes stale ones, but only when those files actually changed (a one-time map-memories backfill records which files back which memory).
  • verify-broad periodically re-checks the whole pool to catch drift.
  • curate deduplicates, tightens, and prunes. Cross-category merges are now structurally rejected: a memory has exactly one category.

Beyond the split, every dreamer task was re-tooled to do more with less. Each task now gets a focused prompt and only the tools it needs, and the heaviest passes (classify, verify) were reworked to emit a single structured result instead of grinding through many small tool calls. The result is noticeably fewer tokens per run for better, more consistent output, which matters most if you point the dreamer at a paid model.

Embedding storage no longer wipes your vectors on a config change

Previously, changing your embedding model or endpoint could trigger a full, destructive re-embed of every memory, commit, and history chunk. Now vectors for different models coexist in storage, keyed per model. Switching providers (or testing one) keeps your existing vectors intact; the old set is garbage-collected lazily and only once a trusted new config has registered. A degraded or mid-migration config never drives deletion. Also adds a guard that refuses vectors when an endpoint silently serves a different model than requested (wrong-dimension corruption), and supports asymmetric query/passage input_type.

Configuration moves to a shared CortexKit location

Magic Context configuration now lives in one shared place per machine instead of per-harness:

  • User config: ~/.config/cortexkit/magic-context.jsonc
  • Project config: <project>/.cortexkit/magic-context.jsonc

This is automatic. On first run after upgrading, your existing magic-context.jsonc (from the OpenCode or Pi location) is moved to the new path, and the old file is renamed to *.MOVED_READPLEASE with a short note inside so nothing is silently left behind. If the migrator finds two legacy files that disagree, it refuses to merge them and asks you to consolidate (it never clobbers your settings). Project-local runtime artifacts (historian error dumps) move under <project>/.cortexkit/magic-context/, and a scoped .gitignore keeps them out of your repo.

Workspaces: selective memory sharing

Workspace members can now share memory by category rather than all-or-nothing. Toggle which of the five categories cross into sibling projects (defaults to sharing only CONSTRAINTS), so global truths travel while project-local controls stay private.

Reliability and hardening

  • Plugin-load resilience. The plugin entry is hardened against an OpenCode Desktop multi-instance boot-order issue that could leave the transform disabled and balloon a session's context. A failure registering hidden agents can no longer take down the whole plugin.
  • /ctx-* commands no longer leak an error into the TUI or log on OpenCode 1.17.x. The handled-command signal is now a clean 204 response.
  • Resilient dreamer leases. Transient database contention during a long task no longer aborts it as a permanent failure, and a genuine multi-minute stall is detected correctly instead of risking a split-brain run.
  • A multi-wave correctness and security review across storage permissions, config recovery, the embedding pipeline, the dashboard backend, SSRF guards, and migration safety. Storage directories are tightened to 0700/0600.
  • toast_duration_ms: 0 now disables Magic Context toasts entirely.

Thanks to our contributors

This release includes community contributions from:

  • @kecsap: a configurable toast duration, including toast_duration_ms: 0 to turn Magic Context toasts off entirely (#92).
  • @tracycam: security hardening, including tighter storage-directory permissions, SQLite ATTACH path escaping, and project-config privilege fixes (#143).

Thanks also to everyone who filed detailed bug reports, and to Dependabot for the dependency bumps (#170, #171).

Upgrading

Upgrading is automatic. Your dreamer config is migrated to the new per-task schema in place, your configuration file is moved to the CortexKit location, and the database migrates to schema v49 on first load. No manual steps.