What happened?
The New Memory dialog in the dashboard has a required Primary Sector select (semantic, episodic, procedural, emotional, reflective). Picking a value there has no effect. The memory is saved with whatever sector the keyword classifier picks, which for most content is semantic.
The cause is a key mismatch between the dashboard and the server.
The dashboard posts the choice under metadata.primary_sector:
|
async function handleAddMemory(content: string, sector: string, tags: string, scope: 'project' | 'global') { |
|
try { |
|
const res = await fetch(`${API_BASE_URL}/memory/add`, { |
|
method: 'POST', |
|
headers: getHeaders(), |
|
body: JSON.stringify({ |
|
content, |
|
tags: tags.split(',').map((t) => t.trim()).filter(Boolean), |
|
metadata: { primary_sector: sector }, |
|
// Explicitly set project_id based on user selected scope |
|
project_id: scope === 'project' ? currentProject : 'system_global' |
/memory/add validates metadata as a generic object and forwards it unchanged to add_hsg_memory, which calls classify_content(content, metadata). classify_content reads only metadata.sector:
|
export function classify_content( |
|
content: string, |
|
metadata?: any, |
|
): sector_class { |
|
if (metadata?.sector && sectors.includes(metadata.sector)) { |
metadata.primary_sector is never read as a request-side override anywhere in the tree. Every other occurrence of primary_sector is the stored column or a response field. The Python backend has the same contract: openmemory-py/src/openmemory/memory/hsg.py also reads metadata['sector'].
The write returns success, so nothing signals that the selection was dropped. The list view then renders the stored column back, which is why the card shows a sector the user did not choose.
Expected: the sector selected in the dialog is the sector the memory is stored under.
Steps to Reproduce
- Start the backend and open the dashboard at
/memories.
- Click New Memory.
- Enter content that does not match a procedural keyword pattern, for example
Prefer dark mode in the editor.
- Set Primary Sector to
procedural.
- Save. The request succeeds.
- Look at the new card in the list, or
GET /memory/list. Its sector reads semantic, not procedural.
Component
Frontend (React/UI)
Why it matters beyond the label
The stored sector is not cosmetic. It drives:
- sector counts and filtering on the memories page, and
GET /memory/list?sector=
- procedural-only retrieval in the IDE route (
routes/ide.ts filters primary_sector === 'procedural')
- per-sector decay, since
sector_configs.decay_lambda is keyed on the sector
So a memory filed under the wrong sector decays at the wrong rate and is missed by sector-scoped retrieval.
Suggested fix
The backend override already exists and works; only the client key is wrong. In handleAddMemory, send:
Alternatively, accept both keys in classify_content if primary_sector should stay a valid input for compatibility with anything already posting it.
Attribution
The flagged line entered main in PR #143, which restored the dashboard sources that PR #138 merged without. The hsg.ts side is pre-existing and untouched.
Code of Conduct
Automated report: this issue was produced and filed automatically, with no human review before posting. Two independent checks agreed it is a real bug, but if it misreads the code please say so and we will close it.
Found while running Ito (AI code review that runs your application, free for open source) against recently merged PRs. Full analysis.
What happened?
The New Memory dialog in the dashboard has a required Primary Sector select (semantic, episodic, procedural, emotional, reflective). Picking a value there has no effect. The memory is saved with whatever sector the keyword classifier picks, which for most content is
semantic.The cause is a key mismatch between the dashboard and the server.
The dashboard posts the choice under
metadata.primary_sector:OpenMemory/dashboard/app/memories/page.tsx
Lines 110 to 120 in 0761b62
/memory/addvalidatesmetadataas a generic object and forwards it unchanged toadd_hsg_memory, which callsclassify_content(content, metadata).classify_contentreads onlymetadata.sector:OpenMemory/packages/openmemory-js/src/memory/hsg.ts
Lines 249 to 253 in 0761b62
metadata.primary_sectoris never read as a request-side override anywhere in the tree. Every other occurrence ofprimary_sectoris the stored column or a response field. The Python backend has the same contract:openmemory-py/src/openmemory/memory/hsg.pyalso readsmetadata['sector'].The write returns success, so nothing signals that the selection was dropped. The list view then renders the stored column back, which is why the card shows a sector the user did not choose.
Expected: the sector selected in the dialog is the sector the memory is stored under.
Steps to Reproduce
/memories.Prefer dark mode in the editor.procedural.GET /memory/list. Its sector readssemantic, notprocedural.Component
Frontend (React/UI)
Why it matters beyond the label
The stored sector is not cosmetic. It drives:
GET /memory/list?sector=routes/ide.tsfiltersprimary_sector === 'procedural')sector_configs.decay_lambdais keyed on the sectorSo a memory filed under the wrong sector decays at the wrong rate and is missed by sector-scoped retrieval.
Suggested fix
The backend override already exists and works; only the client key is wrong. In
handleAddMemory, send:Alternatively, accept both keys in
classify_contentifprimary_sectorshould stay a valid input for compatibility with anything already posting it.Attribution
The flagged line entered
mainin PR #143, which restored the dashboard sources that PR #138 merged without. Thehsg.tsside is pre-existing and untouched.Code of Conduct
Automated report: this issue was produced and filed automatically, with no human review before posting. Two independent checks agreed it is a real bug, but if it misreads the code please say so and we will close it.
Found while running Ito (AI code review that runs your application, free for open source) against recently merged PRs. Full analysis.