Skip to content

Dreamer policy is hardcoded to software-development workflows — make per-project policy configurable (task prompts, memory categories, maintained docs) #358

Open

Description

@Ema-prowler

Short description

Magic Context's memory machinery (historian, dreamer, injection) works well as a mechanism, but its policy layer is hardcoded to software development: the dreamer task prompts, the memory taxonomy, and the maintained docs list are compiled into the plugin and cannot be adapted to non-code projects (security, research, operations, writing, etc.). For a project that is not a code repository, the system still classifies memories with development-oriented categories and maintains ARCHITECTURE.md / STRUCTURE.md as if every project were a repo.

What problem does this solve?

The plugin manages each project's memory with a fixed policy designed for
software repositories. That policy shows up in three places:

  1. The dreamer runs its tasks (curation, verification, user-memory review,
    documentation maintenance) with internal prompts written in development
    language. For a project that is not code, the agent classifies and
    organizes memory with the wrong perspective: it looks for "testing
    conventions", "releases" or "commits" where none exist.

  2. Memory categories are locked to a development taxonomy (PROJECT_RULES,
    ARCHITECTURE, CONSTRAINTS, CONFIG_VALUES, NAMING). Memories from other
    domains get forced into categories that do not represent their real
    work, degrading curation usefulness.

  3. Documentation maintenance is fixed to ARCHITECTURE.md and STRUCTURE.md,
    software architecture files. Projects that are not code repositories
    receive documentation that does not fit them, or cannot maintain the
    documentation that would actually serve them.

The result: the memory mechanism (historian, compaction, injection) works
for any project, but the policy layer limits it to development projects.
Users from other domains end up with less useful classification, irrelevant
documentation, and dreamer prompts that do not understand their work.

Proposed solution

Decouple the MECHANISM (historian, compaction, injection, storage — the core
of how the plugin stores, organizes and recalls memory) from the POLICY (how
the dreamer should think about THIS project). The core must remain intact;
the proposal is to open the policy layer to configuration so each project
can adapt it to its domain:

  1. Project awareness for the dreamer.
    The dreamer runs tasks (curation, verification, user-memory review, doc
    maintenance, etc.), each with an internal system prompt. Today those
    prompts are fixed and speak in development language (codebase, repo,
    releases, testing). The proposal: let the user give the dreamer an
    orientation about what this project is and how it should treat its
    memories, without replacing the task mechanism — only adapting the
    perspective with which tasks are executed.

  2. Configurable memory categories.
    The category taxonomy is fixed (PROJECT_RULES, ARCHITECTURE, CONSTRAINTS,
    CONFIG_VALUES, NAMING) and oriented to software repositories. The
    proposal: let the user define the categories their project uses, so
    curation classifies memories into the categories that actually exist in
    their work.

  3. Configurable maintained docs.
    Documentation maintenance is fixed to ARCHITECTURE.md and STRUCTURE.md.
    The proposal: let the user choose which documentation files should be
    maintained (and with what content instructions for each), instead of a
    fixed list.

  4. Non-code project mode (optional).
    A convenience mode that pre-configures the points above for projects
    that are not code repositories: disables development-oriented language
    and repo doc maintenance, keeps memory curation with user-defined
    categories, and focuses historian/review prompts on the project's real
    work type. It would solve the root problem for those who want it, but
    it is optional.

graph TD;
    A[TODAY - Policy welded to code] --> B[Dreamer task prompts fixed with dev-oriented language];
    A --> C[Memory categories fixed to dev taxonomy];
    A --> D[Maintained docs fixed to ARCHITECTURE.md and STRUCTURE.md];
    B --> E[Dreamer agent thinks in codebase / repo / releases];
    C --> E;
    D --> E;
    E --> F[Result: less useful curation and irrelevant docs for non-code projects];
    G[PROPOSAL - Configurable per-project policy] --> H[Project awareness - user tells the dreamer what this project is];
    G --> I[Memory categories defined by the user];
    G --> J[Maintained docs chosen by the user with content rules];
    G --> K[Non-code project mode - optional, pre-configures everything];
    H --> L[Dreamer agent understands your domain];
    I --> L;
    J --> L;
    L --> M[Result: useful curation and relevant docs for any project];
    E --> N{Transition};
    N -->|decouple mechanism from policy| H;
Loading

Alternatives considered

  1. Fork the plugin and maintain it ourselves.
    Rejected: a fork forces perpetual sync with upstream for what is a
    configurability change.

  2. Externalize dreamer prompts to files (templates/).
    Viable as an implementation, but less discoverable than the existing
    magic-context.jsonc configuration, which is the pattern the plugin
    already uses (schedules, models, thresholds).

  3. Do nothing and use the plugin with defaults only.
    Rejected for non-dev projects: classifying into development categories
    and maintaining repo docs adds noise and tokens to projects that don't
    need them.

  4. Hardcode a domain-specific category set as an additional option.
    Rejected: it would solve one specific case but reproduce the same
    problem for the next domain. The right fix is letting the user define
    their own categories.

Area

OpenCode plugin

Additional context

Real use case: a work project that is not a code repository — it contains
per-topic work folders, findings, operational data and methodology, with no
source code, commits or releases. Current behavior:

  • Curation classifies memories into development categories that do not map
    to the project's real work (result: less useful curation, forced or
    skipped classification).
  • Doc maintenance keeps ARCHITECTURE.md and STRUCTURE.md in sync even
    though those files describe software layers the project does not have.
  • User memories accumulate slowly because the review prompt is tuned for
    recurring dev workflows, not for other types of work sessions.

Acceptance criteria:

  • The dreamer receives configurable orientation about the project type
  • Memory categories are user-configurable
  • The maintained docs list and their content instructions are configurable
  • Default behavior unchanged when no custom config is present
  • Documented in the config schema and README

Activity

  1. Ema-prowler commented on Aug 22, 2026

    @Ema-prowler
    Author

    Efficiency impact
    The development-oriented policy does not only produce less useful
    classification — it also consumes resources unnecessarily:

    1. Wasted tokens. The dreamer runs its tasks with long system prompts
      written for software development. For a non-code project, much of that
      context does not apply: the agent reads, analyzes and classifies
      memories looking for concepts that do not exist in the project
      (releases, commits, testing). Every run spends tokens on a frame that
      does not fit.

    2. Fewer iterations. By aligning the dreamer prompt with the project's
      real domain, the agent classifies and decides correctly the first
      time: no back-and-forth to reinterpret memories that do not fit dev
      categories, and no corrective re-curation.

    3. Less dreamer workload. By disabling what does not apply (repo doc
      maintenance, dev categories) and focusing tasks on what does, each run
      processes less volume with more accuracy.

    4. More speed. Shorter, focused prompts = faster model responses on every
      dreamer task.

    5. Dreamer at higher frequency. By reducing the per-run cost (tokens and
      time), running the dreamer more often becomes viable — for example on
      active projects where today it makes sense to space runs out because
      each one spends too much on context that does not apply.

    The result: the same memory quality with less consumption, or more
    maintenance frequency with the same token budget.

  2. magic-alfonso commented on Aug 23, 2026

    @magic-alfonso

    You've read the architecture correctly, and we're committing to fixing it the way you suggest: the compaction/memory/dreamer machinery is genuinely domain-neutral, and the software-development shape lives in a thin, enumerable policy layer (the memory taxonomy, the historian's fact-extraction fragment, the dreamer task set and its maintained-docs targets, commit detection). That layer will become configurable.

    The shape we've settled on is versioned policy packs rather than per-field configuration:

    • A pack bundles a memory taxonomy, the historian/classifier prompt fragments, the dreamer task set, and doc-maintenance targets as one coherent, versioned unit selected per project.
    • The default pack reproduces today's behavior byte-for-byte, so existing projects see zero change.
    • We will ship at least one non-software pack ourselves to prove the seam, and custom user-authored packs are part of the commitment — that's the real enabler for domains we'd never think to ship.
    • Two hard constraints, stated early: pack selection can live in project config, but pack content (prompts especially) is user-level or shipped-with-the-plugin only — repository-supplied prompt text for the hidden agents is an injection surface we deliberately strip today, and that stays. And switching a project's pack is an explicit migration event (we have precedent machinery from an earlier taxonomy migration), never a silent config read, because a taxonomy drifting under a live memory pool corrupts classification and sharing quietly.

    Why free-form categories lose to packs: category names look like display strings but actually key memory dedup, workspace sharing gates, cross-category merge protection, and classification calibration. An open set fragments memory pools and silently breaks sharing semantics; a closed per-pack set keeps every project internally coherent.

    On timing, honestly: no date. This lands after an engine consolidation we're mid-way through — Magic Context's transform and background machinery is moving into a shared native engine (the Rust workspace in this repo), with the TypeScript plugin reducing to thin host hooks. Policy packs will be implemented once, in that engine, served identically to every harness — rather than twice in a layer that's being retired. When the pack format spec is written we'll link it here; design input on it is welcome, and a domain pack authored by someone who actually lives in that domain would be a first-class contribution.

  3. coleleavitt commented on Sep 13, 2026

    @coleleavitt
    Contributor

    Current-baseline audit against v0.42.3 (5bf26e65): keep open. The accepted policy-pack seam is still absent: memory/types.ts exposes the closed five-category taxonomy, compartment parsing expects those fixed tags, Dreamer prompts retain repository/testing/release policy, and maintain-docs protection remains tied to ARCHITECTURE.md / STRUCTURE.md. dreamer.inject_docs only toggles injection and does not make policy or maintained targets configurable.

  4. G0-0000 commented on Sep 16, 2026

    @G0-0000

    Our Experience with Custom 6-Category Taxonomy

    We've been using a custom 6-category taxonomy (OPS_RULES / ENV_STATE / CONFIG_VALUES / INCIDENTS / RESEARCH / MODEL_KNOWLEDGE) based on this issue for ~2 weeks. Here's what we learned:

    1. Adoption Status

    • Write-side: 92.7% adoption (38/41 new memories in last 7 days use new categories)
    • Tool-recognition side: 0% — installed package dist/index.js contains 0 occurrences of our new category strings; CATEGORY_PRIORITY still hardcodes default programming-oriented 5 categories
    • MODEL_KNOWLEDGE: 0 active memories (7 historical, all archived, last write 2026-09-08)

    2. Key Findings

    • classify-memories task name is misleading — it's actually a scoring task (writes importance/scope/shareable/classified_at), never writes category
    • category is 100% free-text from ctx_memory write — no automated pipeline manages it
    • retrospective task prompt still uses old 5-category names (PROJECT_RULES/NAMING), causing 3 legacy memories to persist

    3. Runtime Status

    • Since 2026-09-09: classify all green, zero failures
    • Earlier: 10× incomplete failures + 2× manifest parse errors (self-healed)

    4. Suggestions for Upstream

    • To support custom taxonomies, CATEGORY_PRIORITY constant needs to be configurable (currently hardcoded)
    • Or provide a config option for user-defined category lists
    • Consider renaming classify-memories or documenting that it doesn't classify categories

    Hope this helps! Happy to share more details if needed.

  5. G0-0000 commented on Sep 19, 2026

    @G0-0000

    Follow-up: 6-category field report + an idea for the pack-format spec

    Continuing from my field report above. Three pain points emerged after ~2 more weeks on the custom 6-category taxonomy, and they point at what I'd like to put on the table as design input for the policy-pack format — not an implementation request.

    Pain points

    1. The taxonomy feels rigid. A single mutually-exclusive dimension forces every memory into exactly one slot, and the right granularity only becomes visible after use.

    2. Cross-cutting is the norm, not the exception. Memories behave more like entities than wiki pages. "A model-config issue discovered during an incident" is simultaneously INCIDENTS, ENV_STATE, CONFIG_VALUES and MODEL_KNOWLEDGE. One-dimensional classification is a mismatch for entity-like content: it creates write-time friction (which slot?) and recall misses (the memory is only reachable from 1/N of the entry points it belongs to).

    3. The dreamer lacks tools for restructuring. Today it has free-text ctx_memory write and embedding search, but no way to relate memories: no link creation, no grouping, no graph traversal. As noted above, category is 100% free-text from write-time and no automated pipeline maintains it afterwards — classification quality depends entirely on the writer's momentary judgment.

    The idea: links and composites as first-class, self-managed memory blocks

    The diagnosis is "only one organizational dimension exists", not "the categories are wrong" (92.7% write-side adoption says they're roughly right). So rather than refining the taxonomy dimension, add derived dimensions on top:

    • Link blocks: typed, directed edges with optional properties (part-of / caused-by / supersedes / sequence-of / alternative-to, a small closed vocabulary). Bidirectionality is a query-time view, not double storage. Derived by the dreamer, not hand-maintained.
    • Composite blocks: an ordered set of memory IDs + relation + metadata. Arrays (timelines, procedures), trees (nested outlines) and rings (rotations, cyclic processes — where a cursor metadata field is arguably the valuable part: where in the cycle am I now) are all special cases of one primitive, not three block types.

    Crucially, both primitives would live outside the mechanisms your earlier comment reserved for the closed taxonomy: they don't key dedup, workspace sharing gates, or cross-category merge protection — the "open set fragments memory pools" argument doesn't apply to them. And they'd be managed by the existing machinery: links and composites get compressed, expired and merged by the historian/dreamer like any memory (e.g. 50 fragments + 100 links → one summary block + one summary edge). No new subsystem; the graph maintains itself.

    This is the hippocampus model rather than a wiki: structure as a product of consolidation, derived by the dreamer after the fact, with cue-driven associative recall — not a hierarchy that must be decided before writing.

    Open questions (for the maintainers, when the pack spec is written)

    1. Should the relation vocabulary live in the pack (versioned per pack) while the link/composite mechanism lives in the engine (universal across packs)? My inclination is yes.
    2. Auto-derived links will occasionally be wrong and pollute associative recall — is confidence scoring / periodic verification needed, or is dreamer self-correction enough?
    3. Graph-traversal recall adds latency and cost on the query path. Bounded depth + edge-type filters make it predictable, but how should it compose/rank with embedding recall? Worth noting it would be a third recall path, not a replacement — and composites should reduce latency for ordered retrieval (fetching a timeline as one block instead of re-deriving order).
    4. Relation to Feature request / design discussion: task-scoped memory prefetch by ID for subagent delegation #449: a composite block (ordered ID set) looks like a natural unit to hand to a child agent as a frozen reference set.
    5. Does moving a ring's cursor count as a memory write (sync/share implications)?

    Happy to freeze this here as material — I can adapt to whatever shape the spec takes, or help author a pack for non-software operational domains once the format exists.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestNew feature or capability request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions