Indexed memory search candidate evidence¶
Task: 59129a4a-9160-4cfd-a9c4-b58a073a848c, frozen version 26, read through
HeyAira MCP before resuming work.
Repository: h8v6/heyaira. Branch: heyaira/59129a4a.
Base commit: 4f487bbdf9006cf0a37390205f1721d7c6bbeb71.
Continued from candidate 6126ee56dcfacb00c11d97c4aa937ec9e67fa0c5.
The memory-search implementation and database regressions are unchanged.
This revision additionally fixes the deployment-test fixture's inheritance
of the verifier's read-only Git object cache and adds a targeted regression.
The fixes and evidence are amended into the single local candidate commit.
The candidate is the local commit containing this evidence file; its SHA is
recorded in the task_result receipt. No push, PR, merge, installation or deploy
was performed. The only external write is the authorized task_result
note/receipt.
Implementation and criterion evidence¶
- summary-searchable:
migrations/036_memories_search_vector.sqladds a stored generatedsearch_vectorusingto_tsvector('simple', ...)over title, summary, body and rationale. Nullable summary/rationale usecoalesce.tests/test_memory_search_e2e.pycreates an entry through the real MCPmemory_addtool withSummaryneedleonly in its summary, then asserts that both MCPmemory_searchand the HTTP Bridge memory feed find exactly that entry. A foreign project's matching entry stays excluded. - index-used: The migration creates
memories_search_vector_ginonmemories USING GIN (search_vector). Both queries insrc/heyaira/server.pyfilter directly on this column. The migration regression runs prior migrations in an isolated schema, inserts existing rows (including NULL summary/rationale), applies the new migration using the real migration runner, and asserts stored-generated tsvector metadata, a valid GIN index, backfilled values, summary matches, repeated startup, and automatic regeneration after a summary update. - results-unchanged: Existing memory-search tests are untouched. A static comparison
against the base server file confirms exactly two replacements of the
inline
to_tsvectorexpressions with column references. Theplainto_tsquery('simple', ...)calls, ordering clauses, projections, filters and pagination are unchanged. The new E2E regression compares both endpoints to the original SQL for title/body/rationale matches, case and multiword queries, no matches, kind filters, pagination, empty queries and timestamp ties. It also checks MCP tag filtering. - suite: passed locally. The literal frozen v26 command exited 0: 290 passed, 109 skipped, 3 deselected in 453.36s (0:07:33). Only its two ignored Server Beat files and three deselected cases are excluded. The added fixture regression ran successfully; the two memory-search database regressions skipped. Database behavior remains for PostgreSQL CI.
Actual checks on the Mac¶
Python 3.12.7 and the installed Python packages are readable in this resumed session. No packages were installed. The full validation uses the literal frozen command from the repository root, with no worker-side environment overrides:
PYTHONPATH=src python -m pytest -q -p no:cacheprovider \
--ignore=tests/test_server_beat_audit.py \
--ignore=tests/test_server_beat_corrections.py \
--deselect tests/test_deployment_guard.py::test_required_override_passes_preflight \
--deselect tests/test_deployment_guard.py::test_missing_extra_compose_file_is_rejected \
--deselect tests/test_ios_companion_contract.py::test_inbox_logic_check_passes_with_the_swift_toolchain
The frozen exclusions are unchanged. The deployment tests still invoke real Git against standalone synthetic repositories. Their child processes now receive a copy of the caller's environment with Git repository-location variables removed, so Git uses the fixture's own repository and object directory. The normal test environment is unchanged outside those child processes. The existing deployment assertions are unchanged. The new regression supplies a fake Docker availability check that exits 99 if called; the dry-run must never invoke it. No Docker daemon, deployment or production operation ran.
Actual full-suite output includes:
SKIPPED [2] tests/test_memory_search_e2e.py:35: set HEYAIRA_SUMMARY_E2E_DATABASE_URL for isolated PostgreSQL
290 passed, 109 skipped, 3 deselected in 453.36s (0:07:33)
Static comparison against the base exited 0:
PASS: exactly two server predicate replacements; all other server text unchanged from base.
git diff --check passed. Existing memory-search tests are unchanged.
The only modified existing test file is tests/test_deployment_guard.py,
for the requested verifier correction. Git maintenance checks use the
Xcode Git binary directly. An AST comparison against 6126ee5 also passed:
PASS: all existing deployment test bodies unchanged; one read-only-cache regression added.
Verifier finding addressed¶
The latest verifier reported 7 failed, 282 passed, 109 skipped, 3 deselected
on 6126ee5, with all seven failures at deployment-fixture git init.
The harness exports GIT_OBJECT_DIRECTORY and
GIT_ALTERNATE_OBJECT_DIRECTORIES for its candidate checkout. A verifier's
cache can be read-only, so a synthetic repository inherits that location
and attempts to create its object directories there. Selecting a writable
temporary directory alone does not isolate this inherited Git state.
tests/test_deployment_guard.py now removes GIT_DIR, GIT_COMMON_DIR,
GIT_WORK_TREE, GIT_INDEX_FILE, GIT_OBJECT_DIRECTORY,
GIT_ALTERNATE_OBJECT_DIRECTORIES and GIT_NAMESPACE from the environments
of fixture Git commands and the deployment script tested against them.
The parent environment, production script and search code are unchanged.
The new regression
test_fixture_and_preflight_use_local_objects_with_read_only_parent_cache
sets an inherited read-only synthetic object cache. It checks that the
fixture commit is stored locally, the real dry-run resolves that commit,
and the read-only cache and marker remain untouched. Before the fixture
fix, running this regression failed at git init:
parent-objects/pack: Permission denied
1 failed in 0.14s
After the fix, the focused deployment-file run with its two frozen deselects passed:
9 passed, 2 deselected in 3.36s
That focused run used installed Xcode Git on PATH for speed; the full frozen
command above uses the caller's PATH, including /usr/bin/git. A complete
parent suite baseline was not run; the failing targeted regression provides
the before-fix control.
Remaining verification¶
The two new database tests use the existing
HEYAIRA_SUMMARY_E2E_DATABASE_URL, already supplied by
scripts/test_postgres.py. They skip when that URL is unset in a provisioned
local pytest environment. Both were collected and skipped in the successful
local run. Independent review and the complete PostgreSQL CI suite remain
pending; no acceptance is claimed by this worker.
PostgreSQL follow-up (after CI failure)¶
CI failed the migration regression: asyncpg returns PostgreSQL's "char"
type (pg_attribute.attgenerated) as b's'. The test now selects
attgenerated::text. It also applies every other migration before this one,
not only those that sort before it, because 036_project_notification_events
and 037_publication_missing_alert are already applied on deployed databases.
With those changes scripts/test_postgres.py on a local PostgreSQL passed:
623 passed, zero skipped. Plain pytest: 395 passed, 228 skipped.
Query plans on 50,000 synthetic memories in one project (rare term, LIMIT 20):
the stored column removes per-row to_tsvector (98 ms before, 17 ms after),
but the planner still walks memories_project_created in order and filters,
so the GIN index is not chosen for this query shape. In a generic plan,
$2 = '' OR search_vector @@ ... cannot use it at all. With ordered index
scans disabled, the GIN bitmap scan answers in about 1 ms. Results and ordering
are unaffected; making the planner prefer the GIN index is a separate change.