Files
maka/docs/archive/maka-memory-whitebox-contract.md
agent-radar 7be535059e
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 19:05:14 +08:00

9.5 KiB

Maka memory — white-box contract anchor (2026-05-29)

Archived on 2026-07-13. This snapshot no longer owns the current memory contract.

Owner: yuejing. Anchor for the team's evolving local-memory feature once xuan's transparent-file MVP landed at c06e13f. Aligned to:

  • packages/core/src/local-memory.ts (xuan)
  • apps/desktop/src/main/local-memory-service.ts (xuan)
  • Settings → 记忆 UI (xuan)
  • external reference deep-dive note notes/external reference-deep-dive-2026-05-29.md §3.5
  • PilotDeck deep-dive note notes/pilotdeck-deep-dive-2026-05-29.md §2.2
  • kenji 19b0996f boundary: local transparent file MUST NOT become implicit durable memory; agent-read default-off.

This note is a contract anchor, not a PR. It freezes the field names

  • status semantics so V0.2 / V0.3 PRs can extend predictably without breaking V0.1 disk format. If reality changes, edit here first.

V0.1 — what xuan shipped (c06e13f)

Settings shape (live)

interface LocalMemorySettings {
  enabled: boolean;          // file feature on/off (default ON)
  agentReadEnabled: boolean; // agent may consume in system prompt
                             // (default OFF)
}

Two switches were the right scope:

  • enabled ON + agentReadEnabled OFF — the file lives on disk, user can edit, agent gets NOTHING.
  • enabled ON + agentReadEnabled ON — file appears in system prompt as a dedicated section. Incognito context fails closed.
  • enabled OFF — file untouched on disk; reads return disabled state.

File location + permissions

  • Directory mode 0700, file mode 0600.
  • Lives under the workspace directory.
  • LOCAL_MEMORY_MAX_BYTES = 128 KB enforced at parse time.

Disk format (live)

Each entry is a Markdown H2 section followed by an HTML-comment metadata line:

# Maka Memory

## <title or slug>
<!-- maka-memory: id=<id> origin=manual createdAt=<unix-ms> -->
<content lines>

## <next title>
<!-- maka-memory: id=<id2> origin=manual createdAt=<unix-ms> -->
...

Parser is fail-open: an entry with a malformed comment still renders its content. The HTML-comment metadata is intentionally hidden from human readers in most Markdown viewers.

Parse output (live)

interface LocalMemoryEntryPreview {
  id: string;
  origin: 'manual' | 'unknown';
  title: string;
  content: string;
  createdAt?: number;
}

interface LocalMemoryState {
  path: string;
  enabled: boolean;
  agentReadEnabled: boolean;
  status: 'ok' | 'disabled' | 'safe_mode' | 'incognito_blocked' | 'error';
  content: string;
  entryCount: number;
  latestEntry?: LocalMemoryEntryPreview;
  reason?: string;
}

Status enum invariants:

  • disabled — settings.enabled === false. UI shows the toggle.
  • incognito_blocked — workspace privacy context active. Even when enabled, no read happens.
  • safe_mode — file is over LOCAL_MEMORY_MAX_BYTES. Returns empty entry list with a banner; user can still open + edit.
  • error — IO error. Generalized copy in reason.
  • ok — normal read.

V0.2 — extensions on top of the V0.1 disk format

V0.2 extends the metadata comment with optional fields. Parser MUST stay fail-open for unknown fields so V0.1 readers never crash on a V0.2-written file.

<!-- maka-memory: id=<id> origin=<origin> createdAt=<ms> updatedAt=<ms> status=<status> tags=<csv> decayTtlMs=<ms> -->

Origin (V0.2)

type MemoryOrigin = 'manual' | 'extracted' | 'imported' | 'unknown';
  • manual — user typed it. V0.1 only writes this.
  • extracted — written by a future extract_memory agent tool. That tool MUST be permissionRequired: true with its own user approval prompt, gated on agentReadEnabled (you cannot extract what you said the agent cannot read), gated on !incognitoActive.
  • imported — bulk-imported (Honcho / mem0 / supermemory export / OpenAI ChatGPT memory JSON / etc.).

Status (V0.2)

type MemoryEntryStatus = 'active' | 'archived';
  • active — surfaces in agent prompt + UI list.
  • archived — stays in the file (user can re-activate) but does not enter the prompt. UI lists archived entries in a separate pane.

decayTtlMs is the auto-archive timer: when now > createdAt + decayTtlMs, the next parse promotes the entry to archived. The file is rewritten with status=archived in-line — a write the user can see, not a hidden background mutation.

Tags (V0.2)

tags=foo,bar — string CSV. Used for filtering in the UI and optional system-prompt section grouping.

Stable id (V0.2)

Currently V0.1 uses manual-<unix-ms>. V0.2 switches new entries to sha256(content + createdAt).slice(0, 16) so id is stable across edits of the title. Old manual-* ids remain valid; the parser accepts both.

Settings additions (V0.2)

interface LocalMemorySettings {
  enabled: boolean;
  agentReadEnabled: boolean;
  // V0.2:
  defaultDecayDays?: number;     // entries created without an
                                 // explicit decay inherit this
  extractToolEnabled?: boolean;  // gates the extract_memory tool
                                 // registration; default false
}

extractToolEnabled is the third switch that makes the extract_memory agent tool surface. It is OFF by default and disabled when agentReadEnabled is OFF (you cannot extract memory the agent cannot use).

V0.3 — open questions (NOT contract; revisit when relevant)

These are explicitly OPEN questions. Recording them here so the next person who picks up the lane knows the field is not settled.

Provider abstraction

external reference ships plugins/memory/{honcho,mem0,supermemory}. PilotDeck has EdgeClawMemoryProvider. reference implementation is built-in MemoryService + sqlite-vec. Three-way convergence is NOT present — kenji's finding 7749c411 #3. Defer abstraction until a real external backend lands (a paying user wants Honcho or a vector store).

If we adopt:

  • MemoryProvider interface in @maka/core/memory
  • Built-in LocalMarkdownProvider (today's file)
  • Plugin path for HonchoProvider etc.

Embedding generation is a separate provider lane (reference implementation's __local__ / OpenAI / aihubmix / openrouter / Google selector). Independent of the memory storage backend. Defer.

Cross-session recall

V0.1 / V0.2 always returns the whole memory file. V0.3 may implement retrieval — emit only top-K relevant entries based on a query. Requires a retrieval algorithm choice; vector vs FTS5 vs LLM-judge. Defer.

Dream Mode (PilotDeck term)

Idle-window memory consolidation: when the app sits idle for X minutes, summarize chat sessions into new memory entries. Has serious privacy implications. Even with extractToolEnabled ON this would be an additional opt-in. Defer.

Multi-workspace memory

PilotDeck's pitch is per-workspace memory + cross-workspace aggregation. Maka has workspaces. V0.3 could expose a memory.scope: 'workspace' | 'global' field per entry. Defer.

Contract test surface (suggested, not shipped)

When V0.2 lands, the following invariants should be enforced by contract tests:

  1. parseLocalMemoryMarkdown is fail-open on unknown comment fields — never throws, never drops a known entry.
  2. agentReadEnabled === false ⇒ system prompt NEVER contains the memory section, regardless of enabled.
  3. Workspace privacy context incognitoActive === true ⇒ LocalMemoryState.status === 'incognito_blocked' even when both switches are ON.
  4. extract_memory agent tool registration is gated on extractToolEnabled === true && agentReadEnabled === true.
  5. The token-boundary contract is preserved: memory content crosses the renderer↔main IPC; raw tokens / API keys never leak into a memory entry via redactSecrets on the write path.

Decisions log

Date Decision Source
2026-05-29 Two-switch model (file enabled / agent-read enabled) xuan c06e13f
2026-05-29 agentReadEnabled defaults OFF kenji 19b0996f boundary
2026-05-29 Defer provider plugin abstraction (no 3-way) kenji 7749c411 #3
2026-05-29 extract_memory agent tool: future, permission-gated this note
2026-05-29 Dream Mode / vector / cross-session: V0.3+ open this note

Pointers

  • xuan implementation: packages/core/src/local-memory.ts + apps/desktop/src/main/local-memory-service.ts.
  • Settings UI: apps/desktop/src/renderer/settings/ (find the memory section).
  • Test: packages/core/src/__tests__/local-memory.test.ts.
  • external reference inspiration: notes/external reference-deep-dive-2026-05-29.md §3.5 (warns against plugin abstraction without external demand).
  • PilotDeck inspiration: notes/pilotdeck-deep-dive-2026-05-29.md §2.2 (white-box memory) and §3.2 (extension proposal).