Skip to content

fix(core): refresh pending relations from accepted content - #1161

Merged
phernandez merged 1 commit into
mainfrom
codex/fix-pending-relation-refresh
Jul 27, 2026
Merged

fix(core): refresh pending relations from accepted content#1161
phernandez merged 1 commit into
mainfrom
codex/fix-pending-relation-refresh

Conversation

@phernandez

Copy link
Copy Markdown
Member

Why

An accepted write_note can schedule relation resolution before its Markdown
projection has been materialized. Relation resolution then refreshes affected
source search rows through a disk-backed path and raises FileNotFoundError
during a valid accepted-but-pending state.

This fixes #1159 without moving materialization back onto the request path, so
durable write acceptance keeps its current performance characteristics.

What Changed

  • Load accepted NoteContent alongside source entities after relation targets
    are resolved.
  • Refresh non-synchronized sources from their accepted Markdown content.
  • Keep synchronized and legacy sources on the existing disk-backed refresh
    path so genuine missing-file inconsistencies still surface.
  • Wire project-scoped NoteContentRepository instances into every shared and
    local relation-resolution composition root.
  • Add unit and end-to-end SQLite regressions for both sides of the state
    boundary.

Implementation Details

RepositoryRelationResolutionRuntime performs one additional batch
NoteContent lookup only when relation resolution changed source entities.
Rows whose file_write_status is not synced are converted through
accepted_search_content_from_markdown() and passed to
SearchService.index_entities() as an explicit per-entity content mapping.

An entity absent from that mapping keeps the existing content=None behavior,
which reads the Markdown projection from disk. This avoids broadly swallowing
FileNotFoundError and preserves detection of real projection inconsistencies.
Materialization remains asynchronous and off the acceptance path.

Testing

Automated

  • source .venv/bin/activate && just fast-check: passed; reported nine existing
    Python 3.14 asyncio deprecation warnings.
  • source .venv/bin/activate && BASIC_MEMORY_ENV=test LOGFIRE_IGNORE_NO_CONFIG=1 pytest -q tests/index/test_local_project_index.py:
    44 passed.
  • source .venv/bin/activate && BASIC_MEMORY_ENV=test LOGFIRE_IGNORE_NO_CONFIG=1 pytest -q tests/indexing/test_relation_resolution.py tests/services/test_project_service_composition.py tests/index/test_local_schedulers.py:
    30 passed.
  • just doctor: passed the end-to-end file, database, and search loop.
  • git diff --check: passed.

Manual

  • Reproduced the pre-fix interleaving with an accepted source whose Markdown
    file did not yet exist.
  • Verified the regression refreshes accepted searchable content and resolved
    relation metadata while preserving the synchronized-source missing-file
    failure.

Risks / Follow-ups

  • The refresh adds one project-scoped batch NoteContent read only when
    relations changed.
  • Basic Memory Cloud should consume the fixed Core revision and add hosted
    lifecycle coverage; it does not need duplicate production policy.
  • The full 4,985-test suite was not completed locally; CI provides the broader
    SQLite/Postgres matrix.

Signed-off-by: phernandez <paul@basicmachines.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Background relation resolution reads notes before async materialization

1 participant