Skip to content

Close memory durability and retrieval audit - #14

Merged
RMANOV merged 4 commits into
mainfrom
agent/memory-firstwave
Aug 2, 2026
Merged

Close memory durability and retrieval audit#14
RMANOV merged 4 commits into
mainfrom
agent/memory-firstwave

Conversation

@RMANOV

@RMANOV RMANOV commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • close audit 924b7796a000 findings in retrieval/search fallbacks, service liveness, and debate-pump durability
  • enforce a directory-wide dead-process log budget
  • make backup publication collision-safe and WAL recovery verifiable, including concurrent same-process staging
  • add isolated regression coverage for every repaired seam
  • carry the two preceding schema reconciliation commits already used by the live hardening branch

Local verification

  • python3 -m pytest -q: 1538 passed, 19 skipped
  • ruff check .: passed
  • manifest tests: 22 passed
  • registry smoke: passed (9 tools)

Draft only. No merge or deployment is authorized by this PR.

@RMANOV
RMANOV marked this pull request as ready for review August 2, 2026 23:17
Copilot AI review requested due to automatic review settings August 2, 2026 23:17
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@RMANOV
RMANOV merged commit 74ded79 into main Aug 2, 2026
3 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR closes a durability/retrieval audit by tightening “live vs finished” semantics in task querying/lookup, hardening backup/logging durability behaviors, and adding broad regression coverage to lock the fixes in across the MCP servers.

Changes:

  • Make query_tasks live-by-default (unless an explicit status is requested or include_completed=True) and ensure find_by_title keeps finished rows reachable while consistently ranking live work first.
  • Improve search fallback behavior/performance (FTS overfetch, literal top-up gates) and refine ready-context classification with word-boundary + inflection-aware marker matching.
  • Add extensive regression tests for liveness, search fallbacks, backup collision/WAL verification, directory-wide log budgets, schema migrations, and test-suite filesystem isolation.

Reviewed changes

Copilot reviewed 30 out of 30 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
unified_server.py Updates tool instructions to document the new liveness defaults and lookup ranking behavior.
tray_dialogs.py Passes a live DB connection into tray search to enable FTS and avoid expensive in-memory fallback work.
tests/test_task_server_liveness.py New regression suite for query_tasks liveness defaults and find_by_title liveness-first ordering.
tests/test_server_imports.py Fixes logger fallback test to patch the handler type actually used (RotatingFileHandler).
tests/test_schema_task_field_versions.py Adds integrity tests for orphan pruning + FK cascade behavior around task field versions.
tests/test_schema_role_binding_migration.py Adds regression coverage for deterministic retirement of duplicate active bindings before creating unique index.
tests/test_recover_literal_matches_thin.py Adds differential tests ensuring recovery passes don’t suppress each other for thin answers.
tests/test_ready_context_word_boundary.py Adds large regression suite for ready-context marker matching, intent scoping, and ordering invariants.
tests/test_query_tasks_search_shape.py Ensures query_tasks(search=...) preserves recall and row shape in core-only installs.
tests/test_log_directory_budget.py Adds tests for directory-level log budget enforcement without harming live processes.
tests/test_fts_token_selection.py Verifies longest-first token selection so FTS caps don’t drop non-Latin content (Cyrillic).
tests/test_find_by_title_reachability.py Ensures finished rows remain reachable on every find_by_title path and rank below live work.
tests/test_debate_pump_worker_census.py Adds coverage for correct worker census identity (topic+role+session) and downstream projections.
tests/test_db_utils_durability.py Adds durability + logging + DF-stopword tests for backups, bounded logs, and tokenization behavior.
tests/test_backup_generation_collision.py Adds tests for collision-safe backup publishing and WAL recovery retry semantics.
tests/fixtures/retrieval_eval_corpus.json Updates expected retrieval evaluation fixture outputs.
tests/conftest.py Introduces session-wide HOME/filesystem isolation to prevent tests touching operator’s live state.
task_tray.py Clarifies bounded index admission policy and intent (fresh rows stay reachable via on-disk/substring passes).
task_server.py Implements include_completed, liveness filtering, and liveness-first ordering for lookup results.
task_search.py Adds FTS overfetch + literal recovery/top-up behavior and bounded-index recency admission.
smart_retrieval.py Reworks marker matching with compiled regex + inflections and reorders ready-state precedence rules.
schema.py Adds migrations for orphan pruning, role/session binding reconciliation, FK-baseline handling, and log noise reduction.
pyproject.toml Bumps project version to 3.13.2.
memory_thread_clustering.py Switches FTS token cap selection to longest-first for non-Latin fairness.
link_suggestions.py Switches safe FTS query token selection to longest-first for non-Latin fairness.
hooks/debate_pump.py Fixes worker census identity to avoid undercounting across topics/roles; projects to bare ids where needed.
entity_server.py Switches token cap selection for overlap computation to longest-first for non-Latin fairness.
db_utils.py Adds crash-consistent backups, bounded rotating logs with directory budget sweeping, and DF-based stopwords.
CHANGELOG.md Documents fixes for v3.13.1–v3.13.2.
init.py Bumps __version__ to 3.13.2.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread task_search.py
Comment on lines +73 to +83
merged: list[dict] = []
seen: set[str | None] = set()
for row in (*projected, *_scored_fallback(tasks, query, limit)):
task_id = row.get("id")
if task_id in seen:
continue
seen.add(task_id)
merged.append(row)
if len(merged) >= limit:
break
return merged
Comment thread hooks/debate_pump.py
Comment on lines +839 to 845
def _live_worker_session_ids(topic_id: str) -> set[tuple[str, str, str]]:
"""Resolve live derived workers from their durable real-spawn receipts.

Returns ``(topic_id, role, worker_session_id)`` claim keys — the identity
``debate_worker_claims`` is actually unique on. Callers that need bare
session ids for a single topic project the third element."""
con = sqlite3.connect(DB_PATH)
RMANOV pushed a commit that referenced this pull request Aug 3, 2026
Both defects were found by Copilot's review of #14, after that PR had
already merged to main and been deployed here.

1. `_live_worker_session_ids` silently changed shape. The census fix
   needed the full claim key `(topic_id, role, worker_session_id)` and
   the helper's return type was changed in place to supply it — but
   callers treat the result as a set of bare ids:

     * `tests/test_debate_windows_adapter.py` asserts
       `_live_worker_session_ids("T1") == {"cc-x-W1"}`
     * `recover_stale_worker_claims()` scans one topic and matches ids

   The Windows test is `@windows_only`, so it skips on Linux and the
   suite stayed green while the contract was broken — one of the 19
   skips was covering the regression.

   Split instead of overload: `_live_worker_session_ids()` returns
   `set[str]` as it always did, and `_live_worker_claim_keys()` returns
   the triple for the cross-topic census. Within one topic the id alone
   is already unique, so the projection is exact.

   `test_debate_zero_paste_recovery.py` patched the bare-id helper and
   passed for the wrong reason: the census unions whatever the stub
   returns, so a set holding one string counted as one worker even
   though the census's identity is the triple. It now patches the
   claim-key helper, which is what the census actually calls.

2. `_project_and_top_up` evaluated `_scored_fallback()` eagerly.
   Spelling the merge as `(*projected, *_scored_fallback(...))`
   computes the fallback before the loop runs, so every query paid an
   O(n_tasks) lower-casing pass over the whole pool even when the
   ranked hits already filled the quota and the first `break` threw the
   result away. Costliest on core-only installs, where this is the only
   search path.

   Measured: quota filled by FTS -> fallback called 0 times (was 1);
   quota short -> called once; output byte-identical to the eager
   version in both cases.

Full suite 1538 passed, 19 skipped. Ruff clean. Operator log inodes
unchanged across the run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Po7GZbvPSVjr16bSBBmhA
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.

2 participants