Summary
Make the DB-first accepted-note transaction expose one operation that persists the complete accepted Markdown snapshot: entity fields, NoteContent, observations, outgoing relations, and hot search state.
Why
PR #1079 fixed a real production regression where accepted writes returned success while graph rows remained empty. The immediate bug is fixed, but the API still permits the same incomplete state:
- callers invoke
persist_accepted_note_write() for NoteContent and search;
- create/update/edit callers must separately remember
replace_accepted_note_graph().
That invariant belongs in one operation. A future mutation path can currently omit the second call and recreate #1076.
This was identified while applying the /pythonic-code review lens from #1095 to the shared runtime introduced by #1002.
Proposed Direction
- Introduce one clearly named accepted-snapshot persistence operation for create/update/edit.
- Accept the prepared Markdown value and persist all derived rows through the caller-owned
AsyncSession.
- Keep move as an explicitly narrower operation when it does not replace the note graph.
- Make partial content/search-only persistence private or otherwise impossible to invoke accidentally from a mutation runner.
- Preserve the existing local/cloud transaction and materialization behavior.
Prefer one direct function over a new service hierarchy.
Regression Proof
Add a route-level SQLite test that:
- uses production-style deferred materialization with the worker held or not drained;
- creates or edits a typed note;
- asserts entity,
NoteContent, observations, relations, and search state immediately after the accepted response;
- only then permits materialization/indexing to run.
This ensures a later index_file pass cannot conceal an incomplete accepted transaction.
Acceptance Criteria
- Every accepted create/update/edit transaction persists the complete snapshot through one production call.
- There is no callable production path that writes
NoteContent and search while accidentally omitting the graph.
- The pre-materialization regression test passes for create and at least one replacing mutation.
- Existing materialization, conflict detection, status codes, and queue behavior remain unchanged.
- Any Basic Memory Cloud adaptation is identified and validated against the paired revision.
References
Summary
Make the DB-first accepted-note transaction expose one operation that persists the complete accepted Markdown snapshot: entity fields,
NoteContent, observations, outgoing relations, and hot search state.Why
PR #1079 fixed a real production regression where accepted writes returned success while graph rows remained empty. The immediate bug is fixed, but the API still permits the same incomplete state:
persist_accepted_note_write()forNoteContentand search;replace_accepted_note_graph().That invariant belongs in one operation. A future mutation path can currently omit the second call and recreate #1076.
This was identified while applying the
/pythonic-codereview lens from #1095 to the shared runtime introduced by #1002.Proposed Direction
AsyncSession.Prefer one direct function over a new service hierarchy.
Regression Proof
Add a route-level SQLite test that:
NoteContent, observations, relations, and search state immediately after the accepted response;This ensures a later
index_filepass cannot conceal an incomplete accepted transaction.Acceptance Criteria
NoteContentand search while accidentally omitting the graph.References