Approved design · implemented and accepted

Settings UI proposal

One consistent shell, one clear settings entry, and only settings that map to real runtime behavior.

Memory
OpenProgram Memorytopics/projects/openprogram-memory.md · modified today

OpenProgram Memory

4 records · Git history available

Memory operations

Models can edit Topic files directly or submit structured changes through the Memory API. Runtime validation and derived views are shared by both paths.

The Scheduler agent may create a durable Memory record while planning, update it during execution, and close or delete it when the task ends.
^7a12e4c9 · source refs 3

Current retrieval

Keyword retrieval uses BM25 over Topic and Source events. Semantic retrieval remains unavailable until its embedding model is installed and selected.

▤

No memory has been written yet

OpenProgram writes durable topics after enough conversation has accumulated. You can configure the writer model and recall method first.

Settings

Memory

Choose how OpenProgram writes, stores, and recalls long-term memory.

Capture Conversation archive
Write MiniMax-M3
Store Local + Git
Recall BM25 only

Memory service

Enable MemoryTurns on recall, background writing, organization, and Memory tools. Changing this switch requires restarting OpenProgram.
StorageTopic Markdown with derived views and Git history.
Local workspace · Git enabled

Background writing

Writer modelUses the default chat model unless you select an enabled model here.
Live
Automatic writingTurn completed conversations into Topic records in the background.
Write frequencyControls how much conversation accumulates before a background write.

Retrieval

Recall methodSelect automatic ranked recall or let the Agent inspect Memory only when needed.
Live
Embedding modelRequired only for semantic and hybrid retrieval.
Not installed
Recall depthMaximum number of matching records added to a turn.
Search Source evidenceInclude archived evidence alongside curated Topic records.

Context and history

Core Memory in every chatInject the compact Core view into each system prompt.
Recent view sizeNumber of latest records kept in the Recent derived view.
WorkspaceCurrent Memory data location. Runtime-managed files remain read-only.
~/.openprogram/memory

Implemented interface contract

  • Memory keeps the standard 64px title bar and exposes a direct /settings/memory link.
  • Topics, Timeline, Recent, and Core form a vertical section list above the Topic tree.
  • At a 720px viewport the section list, tree, and content stack without removing Memory navigation.
  • Settings reads and writes the same schema used by the CLI and TUI.
  • Memory reuses the shared Settings fixed header, body gutter, typography, section-card, and compact row contracts. The lifecycle summary is the only Memory-specific visual structure.
  • Every editable Memory control persists through POST /api/settings immediately after the user changes it. The page has no separate Save button; a rejected write restores the previous value and exposes an inline error.
  • The Memory backend switch explains that changing it requires an OpenProgram restart, but does not show a permanent “Next start” status badge because the settings API does not expose a pending-restart state.
  • Opening /settings/memory requests only the declared memory.* rows and renders them as soon as that bounded request finishes; workspace status and writer-model choices load independently and never gate the editable page.
  • GET /api/memory/status?settings=true returns only the workspace path and fixed embedding snapshot availability. It does not parse Topics, walk Sources, compute revisions, or scan sessions and writer state.
  • The status path checks whether every required file in the fixed embedding snapshot exists and is non-empty, without importing numerical retrieval code, constructing the encoder, or loading model weights. Encoder initialization belongs to semantic retrieval, not Settings.
  • Intel macOS keeps the core Memory and BM25 paths available but reports semantic embeddings as unavailable even when a model snapshot is cached. The Install action fails before any download with an actionable BM25 or supported-platform message.
  • Memory Settings does not request agent runtime settings on entry. Enabled models are requested separately to populate writer choices, and /api/models/enabled runs in FastAPI's worker thread rather than blocking the server event loop; slow or unavailable provider/model enumeration cannot delay the editable Memory rows.
  • Entering Settings does not speculatively fetch Providers, Search, or Channels data; each page requests its own data when opened.
  • Agent · On demand performs no automatic BM25, embedding, or hybrid query. The Agent may inspect Memory explicitly with memory_browse, memory_get, and memory_grep; ranked memory_search reports that it is disabled in this mode.
  • An unavailable embedding snapshot exposes an explicit Install action. The product runtime does not include sentence-transformers or torch. POST /api/memory/embedding/install downloads only the fixed encoder configuration, tokenizer, and safetensors weights in a worker thread, then verifies every required file. It does not construct the encoder and returns a retryable error without changing the active recall method. Semantic and Hybrid stay unavailable until a source checkout installs the optional embedding extra and the snapshot is present.

Implementation and acceptance

  • Public entries: /memory, /settings/memory, immediate GET/POST /api/settings updates, automatic recall, memory_search, and Topic/API writes.
  • Runtime settings cover automatic writing, write frequency, recall method including agent, recall depth, Source scope, Core injection, and Recent size.
  • Semantic and Hybrid remain disabled until the local embedding snapshot is present; saving either method still performs the existing full availability validation.
  • In Agent mode, automatic turn recall is empty and depth/Source controls are disabled because they do not participate in that mode. Core Memory injection remains an independent setting.
  • The four lifecycle cards remain visible at their intrinsic height inside the scrollable settings column; they must not flex-shrink behind overflow: hidden when the page contains more sections than the viewport.
  • Acceptance checks fail if the settings status path calls store.ensure() or the complete workspace inspector, initializes the encoder, remains inside the page's blocking request group, if enabled-model discovery blocks the settings rows, or if Settings entry triggers sibling-page prefetch.
  • Cold-process verification resolves the local embedding snapshot without importing numpy, BM25, or sentence_transformers; editable settings, model choices, and bounded status have separate completion boundaries.
  • A long writer-model label shrinks inside the right control cluster; it must not reduce the left title or description to one-character lines at narrow Settings content widths.
  • Focused Memory selects keep a single neutral border and do not draw an accent-colored outer outline.
  • No external API permission controls are added to this page.
  • Accepted with focused and affected tests, TypeScript validation, independent specification and quality reviews, and visible default-App checks at normal and 720px widths.