Skip to content

feat(celery Wave 6 #33 chunk 2): cross-backend keyword + traversal + chunk 1 amend#1741

Merged
earayu merged 2 commits into
mainfrom
bryce/celery-wave6
Apr 27, 2026
Merged

feat(celery Wave 6 #33 chunk 2): cross-backend keyword + traversal + chunk 1 amend#1741
earayu merged 2 commits into
mainfrom
bryce/celery-wave6

Conversation

@earayu

@earayu earayu commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Wave 6 PR-A "graphindex elimination" — chunk 2 of 3 per §K.11.11 + architect Option A ruling msg=54eac595.

Scope (narrowed per architect ruling):

  • Implement query_entities_by_keyword + expand_neighbors_n_hops on Postgres, Neo4j, Nebula backends.
  • Drop query_entities_by_vector Protocol method (was in chunk 1) — Wave 4 lineage schema has no entity-vector column. Wave 7+ may re-introduce via separate LightRAGQueryService.
  • InMemoryLineageGraphStore ships matching semantics for unit tests.

Out of scope (chunk 3)

  • Caller migration: retrieval/pipeline.py + knowledge_graph/service.py + graph_curation/*
  • Legacy aperag/domains/knowledge_graph/graphindex/ package hard-cut delete + legacy tests delete + grep-zero verify

Test plan

  • 169/169 indexing unit tests pass (10 query-protocol + 159 existing)
  • ruff check + format clean
  • Postgres: ILIKE substring + BFS via SQL IN lists
  • Neo4j: toLower(...) CONTAINS toLower(...) + Cypher name IN $names traversal
  • Nebula: scan-and-filter (no text index, no edge type — relations are tag-vertices)
  • In-memory: substring + BFS frontier walk
  • Edge cases: empty query, top_k <= 0, empty seeds, unknown seed, 0-hop, 2-hop, multi-hop expansion

🤖 Generated with Claude Code

earayu and others added 2 commits April 27, 2026 19:49
…pls + chunk 1 amend (drop vector-recall)

Per architect Option A ruling msg=54eac595 — chunk 2 is narrowed to
`query_entities_by_keyword` + `expand_neighbors_n_hops` across all
three backends. `query_entities_by_vector` is dropped: the Wave 4
lineage schema has no entity-vector column, and adding either an
entity vector index or a Qdrant cross-concern coupling violates the
simple-stable-directive separation of concerns. Wave 7 may
re-introduce vector recall via a separate `LightRAGQueryService` if
real evidence surfaces.

`aperag/indexing/graph.py`:
* Drop `query_entities_by_vector` Protocol method declaration (was
  in chunk 1) + replace with explicit dropped-by-design comment
  pointing at the architect ruling.
* `InMemoryLineageGraphStore` ships REAL implementations of the two
  remaining methods (substring match + BFS frontier traversal) so
  unit tests can exercise the canonical semantics without standing up
  a database.

`aperag/indexing/graph_storage/postgres.py`:
* `query_entities_by_keyword`: `WHERE name ILIKE '%query%'` ordered
  by name, limit `top_k`. ILIKE is the canonical case-insensitive
  substring idiom on Postgres.
* `expand_neighbors_n_hops`: BFS-style frontier expansion. Per hop:
  fetch relations where `source IN $names OR target IN $names`,
  collect unseen endpoints as next frontier, fetch their entity rows.
  Bounded by `hops`. Single connection across all hops.

`aperag/indexing/graph_storage/neo4j.py`:
* `query_entities_by_keyword`: `MATCH (n:aperag_LineageEntity ...)`
  + `WHERE toLower(n.name) CONTAINS toLower($query)` + `ORDER BY
  n.name LIMIT $top_k`. Cypher 5.x has no built-in case-insensitive
  CONTAINS, so this is the canonical idiom.
* `expand_neighbors_n_hops`: Same BFS pattern as Postgres but
  expressed as two Cypher MATCH queries per hop (entities by name
  IN list, relations by source/target IN list). Relations are stored
  as labelled nodes (not edges) per the Wave 4 schema, so traversal
  is JOIN-style not Cypher-pattern-style.

`aperag/indexing/graph_storage/nebula.py`:
* `query_entities_by_keyword`: enumerate all entity VIDs via the
  existing `_list_all_entity_vids` helper, read each lineage by VID,
  filter substring-match in Python, sort by name, return top_k.
  Nebula has no JSON / text-search index on tag string properties so
  this is necessarily a scan — acceptable per simple-stable directive
  (no per-collection text-index infra to manage).
* `expand_neighbors_n_hops`: same scan-and-filter pattern as
  `find_relation_keys_with_lineage`. Per hop, scan all relation VIDs
  and filter by source/target ∈ current frontier. Read each matching
  relation + its endpoints. Wrapped in `asyncio.to_thread` since
  Nebula's Python driver is sync.

`tests/unit_test/indexing/test_lineage_query_protocol.py`: replaces
the chunk-1 Protocol-stub tests with real semantic tests against
`InMemoryLineageGraphStore` (10 total):
* Protocol surface declares 2 read methods (vector-recall removed).
* Signature contract: kw-only args + `hops=1` default.
* `query_entities_by_keyword`: substring matches (Alice / Bob / Carol
  fixture) + `top_k <= 0` and empty/whitespace query return `[]`.
* `expand_neighbors_n_hops`: 1-hop / 2-hop / 0-hop / empty seeds /
  unknown seed cases.

Production-readiness 三类 (chunk 2):
- must-be-real: real keyword + real BFS traversal across 3 production
  backends; in-memory store ships matching semantics.
- may-be-gated: vector recall NOT shipped (per architect Option A);
  Protocol surface intentionally narrowed.
- fully-resolves: §K.11.11 chunk 2 narrowed acceptance + chunk 1
  amend rolled into same commit per architect msg=54eac595.

Tests + local gates:
* 169/169 indexing unit tests pass (10 query-protocol + 159 existing).
* ruff check + format clean.

chunk 3 (caller migration: 5 files in retrieval/pipeline.py +
knowledge_graph/service.py + graph_curation/* + legacy graphindex
package hard-cut delete + grep-zero verify) lands separately.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…y_vector + add Pattern 3

Per architect Option A ruling msg=54eac595, fold spec amend into Bryce's
chunk 2 PR #1741 (per "由 architect 在 Bryce chunk 2 PR push 后 同 chunk
2 fold 进 spec amend (single PR-A continuation)").

Three §K.11 sub-section edits:

1. §K.11.4 row #33 must-be-real layer:
   - Removed "vector-recall" from query layer scope
   - Added explicit "Graph entity vector recall NOT in Wave 6 scope —
     deferred to Wave 7+ if real evidence" with link to ruling
   - Cited reason: lineage schema 没承担 entity vector storage; inline
     coupling 违反 simple-stable directive #3

2. §K.11.5 pre-check pattern lock (renamed from "双 pattern" to "三
   pattern"):
   - Added Pattern 3 (state binding — Protocol method reads from state X)
   - Pattern 3 trigger: "spec acceptance lock form 'Protocol method
     reads from state X' must grep-verify state X schema 现存在"
   - Documented #33 chunk 1 retrospective miss as lesson
   - Forward template: 4 sub-options when state X schema absent
     (in-chunk add / prior chunk add / separate service taking state
     dep / defer to next Wave)

3. §K.11.11 PR-A 3-chunk decomposition:
   - Added Status column (chunk 1 ✅ MERGED `20b9071b` / chunk 2 🔄
     PR #1741 / chunk 3 ⏳ post-chunk-2)
   - Added "Chunk 1 → chunk 2 amend note" explicit subsection citing
     architect ruling msg=54eac595 + Pattern 3 sediment
   - Updated PR-A acceptance items reference: §K.10 (1-5) + amended
     #33 must-be-real per §K.11.4

Companion memory sediment in
`feedback_spec_lock_grep_verify_caller.md` (Pattern 3 added) — keeps
spec ↔ memory feedback aligned per
`feedback_announce_equals_landed.md` narrative-truth invariant.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@earayu earayu merged commit 472ed55 into main Apr 27, 2026
5 checks passed
@earayu earayu deleted the bryce/celery-wave6 branch April 27, 2026 12:05
@earayu earayu added the 何凯明 Work touched or reviewed by @何凯明 label Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

何凯明 Work touched or reviewed by @何凯明

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant