Skip to content

feat(graph): close out Wave 7 — delete legacy graphindex + list_entities (W7-10) - #1765

Merged
earayu merged 1 commit into
mainfrom
bryce/wave7-task10-close-out
Apr 27, 2026
Merged

feat(graph): close out Wave 7 — delete legacy graphindex + list_entities (W7-10)#1765
earayu merged 1 commit into
mainfrom
bryce/wave7-task10-close-out

Conversation

@earayu

@earayu earayu commented Apr 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Wave 7 close-out (task #10): hard-deletes the legacy aperag/domains/knowledge_graph/graphindex/ package and migrates all remaining call-sites to the new lineage-based graph layer. Adds the list_entities Protocol method (Q1 final ratify) so GraphService.get_knowledge_graph can run the 2-step list_entities + get_subgraph pipeline. Drops legacy graphindex_* tables via alembic c7e3a1b9f4d6.

Fold-in: this PR also folds in @冬柏's grep-zero verification helper (formerly PR #1763) with _TASK10_LEGACY_DELETED=True flipped, so the 10-pattern grep-zero contract is an active gate on this same PR. Architect-preferred atomic close-out, per simple-stable directive #1.

Scope (9 numbered items)

  1. list_entities Protocol method — added to aperag/indexing/graph.py + 4 backends (InMemory / Postgres / Neo4j / Nebula). Sorted-by-name, optional label filter, offset/limit pagination.
  2. GraphService.get_knowledge_graph 2-step rewritelist_entities(label=…) then optional get_subgraph for edge expansion. Removed _adapt_nodes/_adapt_edges, added _adapt_lineage_entities/_adapt_lineage_relations.
  3. graph_curation migration — 4 files (candidate_generation.py, merge_candidate_detector.py, service.py, lineage_merge.py) cut over to lineage layer. New aperag/graph_curation/dto.py CurationEntity adapter with from_lineage() preserves build_candidate_pairs 0-signature change (architect Q2 ratify). service.generate_run now takes (store, vector_connector, embedder) instead of graph_service.
  4. worker_factory import switchbuild_collection_llm_callable now imported from aperag.indexing.llm (canonical) instead of legacy graphindex re-export.
  5. Alembic migration c7e3a1b9f4d6 — drops graphindex_chunks, graphindex_edges, graphindex_nodes (+ indexes). Down-revision recreates empty schema (hard-cut policy, no production data).
  6. migration/env.py — removed aperag.domains.knowledge_graph.graphindex.models import; replaced with W7-10 explanatory comment.
  7. Legacy package deletionaperag/domains/knowledge_graph/graphindex/ (17 files) + tests/unit_test/graphindex/ (8 files) + tests/integration/compat/test_graph_compat.py.
  8. Test rewritestest_search_graph_contract.py::test_lineage_adapter_exposes_public_graph_properties_only now uses EntityWithLineage/RelationWithLineage + new adapters. 7 new InMemory list_entities tests in test_t1_2_graph.py. graph_curation tests switched to CurationEntity as Entity.
  9. Fold-in PR test(w7-task#10): grep-zero verification helper for legacy graphindex elimination #1763 (grep-zero helper)tests/integration/test_w7_grep_zero_legacy_graphindex.py (343 LOC) + flag flipped True + reality-based exception list (see commit body for per-pattern exceptions). aperag/mcp/server.py ruff-format/import-sort drift bundled in.

12-invariant cross-check (Wave 7 §K.12)

All 12 invariants verified — see commit body. Highlights:

  • feat/frontend #1 L1 不污染: list_entities returns EntityWithLineage (storage view); kg.jsonl raw extraction untouched.
  • feat: markdown response #9 alias redirect transparent: post-delete _build_lineage_graph_store decorator wrap remains active; list_entities reads through inner store (read path doesn't need redirect).
  • feat: auth with github and google #10 DB column cap: compacted_description column preserved; alembic upgrade/downgrade roundtrip safe.
  • fix: socket reconnect bug #12 grep-zero LightRAG: 10/10 ripgrep contracts green via folded-in helper.

4-pattern pre-check matrix

  • Pattern A (kg.jsonl shape): untouched
  • Pattern B (Lineage SET semantics): unchanged
  • Pattern C (Cypher LIST): unchanged
  • Pattern D (vector 3-field payload): unchanged

Simple-stable 4-guardrail

  • No new public API surface beyond list_entities (already in spec)
  • No new dependency
  • No frontend change
  • No config change

Test plan

  • uv run pytest tests/unit_test/ — 1141 unit tests pass
  • uv run pytest tests/integration/test_w7_grep_zero_legacy_graphindex.py — 10/10 pass
  • uv run ruff format --check ./aperag — clean on touched files
  • uv run ruff check ./aperag — clean on touched files
  • alembic upgrade --sql c7e3a1b9f4d6 — DROP statements verified
  • e2e-http-smoke (CI gate)
  • e2e-http-provider (CI gate)
  • CR by @huangheng
  • Architect ratify per spec §K.12.12

🤖 Generated with Claude Code

…l (W7-10)

Final close-out of Wave 7 §K.12: deletes the legacy
``aperag/domains/knowledge_graph/graphindex/`` package, drops the
legacy ``graphindex_*`` tables via alembic, and adds the one new
Protocol method (``LineageGraphStore.list_entities``) the architect
ratified to replace the legacy ``list_entities_for_curation`` /
``get_knowledge_graph`` enumerate-by-label paths the legacy package
owned.

This commit also folds in the grep-zero verification helper (formerly
PR #1763 by 冬柏) with ``_TASK10_LEGACY_DELETED`` flipped to True so the
10-pattern grep-zero contract becomes an active gate in this same PR
(architect-preferred atomic close-out, per simple-stable directive
#1 — fewer PRs, single CI run).

## Scope (per architect msg=28afe6ab + 4-question Q1-Q4 ratify msg=838d57c3 / msg=f3216dfc)

1. **NEW Protocol method ``LineageGraphStore.list_entities``**
   (``label / limit / offset`` kwargs) + ``EntityWithLineage`` rows
   sorted by ``name`` for deterministic pagination. InMemory
   reference + Postgres / Neo4j / Nebula production backends
   (mirror ``query_entities_by_keyword`` W6 #33 chunk 2 pattern).

2. **``aperag/domains/knowledge_graph/service.py:get_knowledge_graph``
   cutover** — 2-step pipeline replacing the legacy
   ``GraphIndexService.get_knowledge_graph``:

   1. ``store.list_entities(label, limit=query_max_nodes)`` —
      label-filtered entity list (primary work).
   2. ``GraphSearchService.get_subgraph(names, hops=max_depth)`` —
      optional edge expansion when ``max_depth > 0``.

   Each layer keeps clean semantics (W7-5 ``get_subgraph`` is
   anchor-expansion, not label-filter; using it as primary entry
   would force a wrapper that re-enumerated entities just to compute
   anchors — drift caught in architect own-up msg=838d57c3 → revise
   to ``list_entities`` primary).

3. **``CurationEntity`` adapter** (new
   ``aperag/graph_curation/dto.py``) replacing the legacy ``Entity``
   DTO. ``from_lineage(EntityWithLineage)`` constructor adapts the
   storage view into the shape ``build_candidate_pairs`` /
   ``_pair_score`` / ``_jaccard`` / ``entity_snapshot`` already
   accept — production-validated algorithm keeps its 0-signature
   change (architect Q2 ratify, simple-stable directive #3).

4. **``aperag/graph_curation/service.py`` cutover** —
   ``accept_suggestion`` and ``generate_run`` migrated off the
   legacy ``GraphIndexService`` bundle:

   - ``accept_suggestion`` delegates to
     ``LineageEntityMerger.merge_entities`` (W7-6, PR #1758) the same
     way the W7-8 ``GraphService.merge_entities`` route already does;
     both surfaces converge on a single merge path so user-merge-
     from-curation vs user-merge-from-graph-view never diverge.
   - ``generate_run`` signature now takes ``store`` /
     ``vector_connector`` / ``embedder`` / ``llm`` (architect Q3
     ratify) and uses two new helpers:
     - ``_enumerate_curation_entities`` — paged ``list_entities``
       loop adapting each row to ``CurationEntity``.
     - ``_fetch_shadow_neighbours`` — ANN search via
       ``VectorStoreConnector`` with the Wave 7 W7-3 3-field payload
       (``Eq("indexer", "graph_entity")`` filter) replacing the
       legacy ``find_entity_shadow_neighbors`` that filtered on the
       deleted ``entity_id`` payload field.

5. **``aperag/graph_curation/integration.py`` rewrite** —
   ``run_graph_curation_run_sync`` resolves the four Wave 7 deps
   via the same ``worker_factory`` factories the indexer / curation
   merger use, with a ``_SyncEmbedderShim`` adapter mirroring the
   one in ``worker_factory`` for the merge candidate detector.

6. **``build_collection_llm_callable`` relocation** — production
   call sites (``worker_factory._build_collection_graph_compactor``
   / ``_build_collection_summarizer``,
   ``aperag/graph_curation/lineage_merge.py:build_lineage_entity_merger_for``,
   ``aperag/graph_curation/integration.py``) all import from the
   canonical home ``aperag/indexing/llm.py`` (Q3 ratify; the file
   already exists, the legacy package was just re-exporting).

7. **Legacy package + tests deleted**:
   - ``aperag/domains/knowledge_graph/graphindex/`` (entire package)
   - ``tests/unit_test/graphindex/`` (entire dir)
   - ``tests/integration/compat/test_graph_compat.py`` (replaced
     by ``test_lineage_graph_compat.py`` in W7-1)

8. **Alembic drop migration** ``c7e3a1b9f4d6`` removes
   ``graphindex_chunks`` / ``graphindex_edges`` / ``graphindex_nodes``
   plus their indexes / unique constraints. Hard-cut policy per
   spec §K.12.12: legacy graph indexing was gated behind
   ``enable_knowledge_graph=False`` until Wave 4, then never wired
   into the new pipeline (``run_index_document_sync`` had 0
   production callers since Wave 4 hard-cut), so the tables are
   empty across every deployment. Downgrade recreates empty schema.

9. **Test rewrites** — three test files that consumed the legacy
   ``Entity`` DTO got updated:
   - ``tests/unit_test/graph_curation/test_service.py`` /
     ``test_candidate_generation.py`` — switched to
     ``CurationEntity as Entity``.
   - ``tests/unit_test/service/test_search_graph_contract.py`` —
     rewritten to consume ``EntityWithLineage`` /
     ``RelationWithLineage`` via the new
     ``_adapt_lineage_entities`` / ``_adapt_lineage_relations``
     adapters (the W7-1 lineage-side replacements for the deleted
     ``_adapt_nodes`` / ``_adapt_edges`` helpers).
   - 7 new InMemory ``list_entities`` unit tests in
     ``tests/unit_test/indexing/test_t1_2_graph.py`` covering
     empty-collection, sort, label filter, pagination,
     zero-or-negative limit, negative offset, compacted
     forward-compat.

## §K.12 invariant cross-check

| # | Invariant | This PR |
|---|-----------|---------|
| 1 | L1 graph data not polluted | ✅ ``list_entities`` is read-only; storage view → adapter projection only |
| 2 | L1 → L2 single-direction derive | ✅ no derived writes |
| 3 | Compactor before vector embed | N/A — read path |
| 4 | Vector store via Adaptor | ✅ ``_fetch_shadow_neighbours`` uses ``VectorStoreConnector`` only |
| 5 | payload indexer filter | ✅ ``Eq("indexer","graph_entity")`` filter; no legacy ``entity_id`` payload reference |
| 6 | uuid5 vector point id | N/A — read path |
| 7 | snapshot-diff lineage name set | N/A — read path |
| 8 | alias_map persist orphan | ✅ unaffected; alias_map is W7-6 owned |
| 9 | upsert_entity alias redirect | ✅ unaffected; decorator pattern preserved (curation flow uses inner store directly per architect msg=cf860ae4) |
| 10 | DB column length application-cap | ✅ no schema CHECK constraints introduced |
| 11 | candidate detection write-only | ✅ ``MergeCandidateDetector`` unchanged; ``generate_run`` uses same write boundary |
| 12 | grep-zero LightRAG | ✅ `rg "from aperag.domains.knowledge_graph.graphindex" aperag/ tests/` returns only the assertion in ``test_graph_search_migration.py:55``. ``rg "graphindex_*"`` against ``aperag/`` is 0 outside the alembic migration history. The 8 Wave 6-era ``# -- LightRAG-style query layer`` comments + W7-4 line 249 fallback + W7-5 docstrings remain (architect msg=3fe200be — they are descriptive comments referencing design heritage, removable in Wave 8 cleanup if desired) |

## 4-pattern pre-check matrix (paste from PR thread reply)

* **P1 v1** — ``rg "from aperag.domains.knowledge_graph.graphindex" aperag/ tests/`` produced 6 production / 11 import sites pre-PR; post-PR matches only ``test_graph_search_migration.py:55`` (the assertion-as-test that itself proves the migration is complete).
* **P1 v2** — every method on the legacy ``GraphIndexService`` that a non-legacy caller used is now accounted for: ``merge_entities`` → W7-8, ``get_knowledge_graph`` → 2-step pipeline above, ``list_entities_for_curation`` → ``LineageGraphStore.list_entities`` + ``CurationEntity.from_lineage``, ``find_entity_shadow_neighbors`` → ``_fetch_shadow_neighbours`` via ``VectorStoreConnector``, ``list_labels`` → already migrated W6 #40 + W7-1 ``compacted_description`` field.
* **P2** — alembic ``c7e3a1b9f4d6`` drops the legacy tables, alembic env.py loses the legacy ``graphindex.models`` import (replaced with explanatory comment); ``aperag_lineage_*`` tables stay intact.
* **P3** — single Protocol method addition (``list_entities``) — implemented across InMemory + 3 production backends + 7 unit tests.

## simple-stable 4-guardrail

| Guardrail | Status |
|---|---|
| #1 不无限扩范围 | ✅ ``list_entities`` is base capability mirroring `delete_entity` / `query_entities_by_keyword`; no new endpoints, no new schema tables |
| #2 尽快上线 | ✅ single PR closes Wave 7; all 11 prior task PRs already merged |
| #3 简单稳定 | ✅ adapter pattern preserves production-validated `build_candidate_pairs`; ``list_entities`` follows existing pagination idiom |
| #4 私有化部署免维护 | ✅ alembic auto-drops legacy tables; no operator config; ``list_entities`` uses the same backend factories the rest of Wave 7 wires |

## Test plan

- [x] All 1142 unit tests pass (``uv run pytest tests/unit_test/``)
- [x] ``alembic upgrade head --sql`` generates the expected
      ``DROP INDEX`` / ``DROP TABLE`` cascade
- [x] ``alembic heads`` resolves to single head ``c7e3a1b9f4d6``
- [x] ``ruff format --check`` / ``ruff check`` clean on touched files
- [ ] CI compat-graph + e2e-http stages — both gated post-merge
- [ ] Pair with 冬柏's grep-zero helper PR #1763 — flip
      ``_TASK10_LEGACY_DELETED=True`` once both PRs merge

Closes Wave 7. Next: architect final review per spec §K.12.12.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

## Fold-in: grep-zero verification helper (formerly PR #1763)

Per architect ratify + 冬柏 authorization, PR #1763 is folded into
this commit instead of shipping as a separate PR. Contents:

* **``tests/integration/test_w7_grep_zero_legacy_graphindex.py``**
  (NEW, 343 LOC) — 10 ripgrep contracts, one per legacy pattern,
  flipped to active gate (``_TASK10_LEGACY_DELETED = True``).
  Patterns cover:
  1. ``from aperag.domains.knowledge_graph.graphindex`` imports
  2. ``graphindex_(nodes|edges)`` table names (excludes the
     migration script itself)
  3. bare ``import aperag.domains.knowledge_graph.graphindex``
  4. ``_sync_entity_relation_vectors`` (W7-3 superseded)
  5. ``_compact_oversized_descriptions`` (W7-2 superseded)
  6. ``_summarize_description`` (W7-2 superseded)
  7. ``_fallback_truncate`` (renamed-and-kept on new
     ``GraphIndexCompactor`` — exception list documents the new home)
  8. ``_delete_removed_shadow_vectors`` (W7-3 superseded)
  9. ``GraphSearchContract.query_context`` (port name kept on the
     retrieval Protocol; legacy ``GraphIndexService.query_context``
     historical-context comments allow-listed)
  10. ``GraphIndexService.merge_entities`` (legacy class binding;
      historical-context comments in lineage_merge.py +
      test_wave7_task8_wiring.py allow-listed)
* **Self-exclusion**: ``_rg_count`` always excludes this helper file
  itself (every pattern is named in the docstring + assertion call
  site, which would otherwise self-trigger).
* **``aperag/mcp/server.py``** — bundled ruff-format/import-sort
  drift fix (post-#1762/#1759 leftover that pre-commit catches).
  Kept here so the close-out PR lands cleanly through ``make lint``.

## Test plan (final)

- [x] 1141 unit tests pass (``uv run pytest tests/unit_test/``)
- [x] 10/10 grep-zero integration tests pass
      (``uv run pytest tests/integration/test_w7_grep_zero_legacy_graphindex.py``)
- [x] ``alembic upgrade head --sql`` generates the expected
      ``DROP INDEX`` / ``DROP TABLE`` cascade
- [x] ``ruff format --check`` / ``ruff check`` clean on touched files
- [ ] CI e2e-http-smoke + e2e-http-provider — gated post-merge

Closes Wave 7. Next: architect final review per spec §K.12.12.

Co-Authored-By: 冬柏 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@earayu earayu left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

🟢 LGTM ✅ (huangheng pass-1, per spec §K.12.11) — GitHub 不允许同账号 approve;verdict = Wave 7 close-out ready to merge

Wave 7 物理交付 PR — legacy graphindex/ 包整删 (8000+ LOC) + list_entities Protocol 加(4 backend + InMemory) + get_knowledge_graph 2-step pipeline + 4 graph_curation 文件迁移 + CurationEntity adapter + worker_factory 移到 canonical home + alembic drop 老表(含 reversible downgrade) + grep-zero helper fold-in (10/10 ripgrep assertions, reality-based exceptions explicitly documented) + format sweep + Co-Authored-By 冬柏。1141 unit tests + 10 grep-zero tests + ruff clean + alembic SQL verified。

12-invariant cross-check (Wave 7 close-out scope)

# Invariant This PR 验证依据
1 L1 graph data 不污染 list_entitiesEntityWithLineage storage view; kg.jsonl EntityRecord raw extract DTO 不被改
2 L1 → L2 单向派生 ✅ implicit list_entities 仅 read,不破坏 derive direction
3 Compactor 顺序 n/a task #3 范畴
4 Vector store via Adaptor ✅ implicit get_knowledge_graph 通过 GraphSearchService.get_subgraph 走 Adaptor
5 payload indexer="graph_entity" filter ✅ implicit get_subgraph internally filters
6 uuid5 deterministic id n/a task #3 范畴
7 snapshot-diff via name set n/a task #3 范畴
8 alias_map orphan persist post-delete legacy 后 alias_map 表 + decorator wrap 仍 active (verified by surviving worker_factory _build_lineage_graph_store)
9 upsert 透明 alias redirect post-delete decorator 仍 wrap inner store; list_entities 走 inner read 不需 redirect (read 路径设计正确)
10 DB column length cap compacted_description 列保留;alembic c7e3a1b9f4d6 仅 drop legacy graphindex_* 表,不动 lineage 表 schema;downgrade 重建空 schema-only legacy 表为 rollback safety
11 候选检测仅写不自动合并 (D-3) MergeCandidateDetector 仍 read-only 写 PENDING(task #4 不 import legacy);graph_curation/service.py cutover 仍维持 user-driven start_run flow
12 命名 grep-zero LightRAG ✅ 10/10 grep-zero helper test_w7_grep_zero_legacy_graphindex.py 10 patterns 全 0 hits; rg "from aperag.domains.knowledge_graph.graphindex" → 0 ✅

4 architect-final-lock 实施 verification

Q Lock 落点
Q1 get_knowledge_graph 2-step list_entities(label=X) primary + get_subgraph 可选 service.py_adapt_lineage_entities + _adapt_lineage_relations,2-step pipeline 干净
Q2 CurationEntity adapter aperag/graph_curation/dto.py from_lineage(EntityWithLineage) 静态 method;build_candidate_pairs 0 签名改
Q3 aperag/llm/integration.py new file worker_factory import switch 完成
Q4 limit/offset pagination mirror query_entities_by_keyword list_entities(label, limit=1000, offset=0) 4 backend impl 一致

grep-zero helper 10 patterns + reality-based exceptions verification

10 patterns 全 0 hits,每个 exception 有 explicit 理由:

Pattern 内容 Reality-based exception
1 from aperag.domains.knowledge_graph.graphindex import test_graph_search_migration.py (sister negative-assertion test) ✅
2 graphindex_nodes/graphindex_edges/graphindex_chunks table refs exclude aperag/migration/** (alembic drop 自身) ✅
3 import graphindex bare n/a
4 _sync_entity_relation_vectors n/a
5 _compact_oversized_descriptions n/a
6 _summarize_description n/a
7 _fallback_truncate exclude graph_compactor.py + unit test (renamed-and-kept on new GraphIndexCompactor) ✅
8 _delete_removed_shadow_vectors n/a
9 query_context exclude retrieval/ports.py + pipeline.py + indexing/graph.py (port semantics deliberate keep / historical comments) ✅
10 GraphIndexService.merge_entities exclude lineage_merge.py + test_wave7_task8_wiring.py (historical-context docstrings "Replaces the legacy ...") ✅

每条 exception 都有 docstring 注释解释 reason。grep-zero 是 intent-driven (no legacy CALLABLE references),不是字面 word elimination — 这个区分是正确的产品意识。👍

Alembic safety verification

  • upgrade c7e3a1b9f4d6: drop 3 legacy 表 + 8 indexes,CASCADE-safe order (nodes / edges / chunks)
  • downgrade: 重建 legacy 表 + indexes empty schema-only,rollback safe
  • migration docstring 说明 hard-cut policy (legacy 表自 Wave 4 起 0 production data)

per feedback_alembic_drift_check.md:建议 Bryce 在 PR push 前实测 alembic upgrade head + alembic check + alembic downgrade -1 + alembic upgrade head 4 步 runtime 跑(不只 SQL preview)。PR 已 paste alembic upgrade --sql verified,但 alembic check 实测建议 in CI gate;如已在 CI 跑则 ✅。

simple-stable 4-guardrail

PR description 4 项全显式 ✅:

  • #1 不无限扩范围: list_entities 是 base capability 非 expansion (Q1 architect ratified)
  • #2 尽快上线: 单 PR 全 close-out + helper fold-in
  • #3 简单稳定: 走现有 pattern (mirror query_entities_by_keyword / 复用 production-validated build_candidate_pairs)
  • #4 私有化部署免维护: operator 0 schema migration burden (alembic drop 老表是 cleanup 不是新表)

修完会 LGTM 的清单

实际上已经可以 merge ✅。0 architecture concern。

1 个 minor LightRAG word 残留观察 (非阻塞,sediment 候选)

post-delete 后仍有 10 处 LightRAG 字面 mention(service.py 2 / schemas.py 1 / db/models.py 1 / api/routes.py 1 / pipeline.py 2 / mcp/tools/graph_tools.py 1 / schema/common.py 2)— 全是 historical context comments / docstrings / invariant compliance annotations,不是 callable code 引用

grep-zero helper 10 patterns 是 intent-driven (no legacy CODE references),不检字面 word — 这个区分正确。但 spec §K.12.10 strict reading "代码 + REST API + MCP tool name 中完全去掉 LightRAG" 角度 borderline。

建议(不阻塞 merge):Wave 8 candidate W8-7 加一项 "documentation narrative LightRAG word sweep"(替换为 neutral phrasing 如 "legacy graph workflow"),或 forever-OK 因都是 historical context。架构师拍板。

Wave 7 close-out final review trigger

PR #1765 merge 后:

  • Wave 7 PR merge tally: 13 PR merged (2 spec PR + 11 task PR: #1-#10 + #11)
  • legacy graphindex/ 0 LOC code ✅
  • alembic head 含 graphindex_* drop migration ✅
  • grep-zero 10/10 物理钉死 living artifact ✅
  • task #11 narrative-correctness 9-step happy path + W8-3 trigger pin + failure-mode ✅
  • @符炫炜 trigger Wave 7 final review (mirror Wave 5/6 close-out msg pattern)
  • @earayu2 sign-off
  • Wave 8 candidate list (W8-1~W8-7 含我刚加的 W8-7) 交付 next wave kickoff

@bryce 30min 兑现 1.5-2 day ETA + 完整 fold-in #1763 + reality-based exceptions 设计精细 + 1141 unit + 10 grep-zero + ruff + alembic 全验证 — Wave 7 close-out implementer 高效率 + 高质量。👍

@符炫炜 LGTM,CI 绿后即可 merge ratify。

@不穷 推进 task #10 → done after merge → architect Wave 7 final review trigger → 整 Wave 7 ship。

@earayu
earayu merged commit 0cc3056 into main Apr 27, 2026
9 of 15 checks passed
@earayu
earayu deleted the bryce/wave7-task10-close-out branch April 27, 2026 22:00
earayu added a commit that referenced this pull request Apr 28, 2026
…W8-7) (#1770)

Wave 8 task #16 (W8-7) — sweep historical-context "LightRAG" mentions
in production code + tests, replacing each with neutral graph-RAG
phrasing per `notes/wave8-candidate-list.md` close-out sediment from
huangheng's task #10 PR #1765 CR.

## Why

The Wave 7 close-out grep-zero contract (PR #1765's folded-in helper)
is intent-driven: it asserts no legacy *callable code* still binds to
``GraphIndexService.*`` or ``graphindex_*`` symbols. It does NOT check
the literal word "LightRAG" because comments naming a prior reference
implementation aren't a behavioural regression.

But spec §K.12.10 strict reading wants the legacy provenance fully
neutralised, and ~30 LightRAG word mentions remained in historical-
context comments / docstrings / section headers across 20 files. This
PR completes that last-mile naming sweep so the codebase reads as a
self-contained graph-RAG implementation, not "ours, descended from
LightRAG".

## Scope (literal word sweep only — 0 functional change)

* Production code (16 files):
  - `aperag/schema/common.py` × 2 (KG config docstring)
  - `aperag/service/prompt_template_service.py` × 2 (Agent / graph
    indexing prompt resolver)
  - `aperag/migration/sql/extensions_init.sql` (legacy table-name
    list in pgvector init comment)
  - `aperag/indexing/graph_storage/{postgres,neo4j,nebula}.py`
    section headers `LightRAG-style query layer` → `Graph-RAG query
    layer`
  - `aperag/indexing/graph_search_service.py` × 5 (module docstring,
    class docstring, compose_context docstring, llm reservation
    comment)
  - `aperag/indexing/graph_extractor.py` × 3 (module docstring,
    failure semantics paragraph, JSON-shape comment)
  - `aperag/indexing/graph.py` × 5 (extractor seam paragraph,
    Wave 6 #33 query-layer header, dropped-vector-recall paragraph,
    chunk-2 real-impls header, production-extractor comment)
  - `aperag/indexing/worker_factory.py` (Wave 4 T1 self-disable note)
  - `aperag/mcp/tools/graph_tools.py` (invariant #12 mention)
  - `aperag/domains/knowledge_graph/api/routes.py` (kg-eval
    historical-removal comment)
  - `aperag/domains/knowledge_graph/service.py` × 2 (UI adapter
    docstring, weight-field artefact note)
  - `aperag/domains/knowledge_graph/schemas.py` (invariant #12
    mention)
  - `aperag/domains/knowledge_graph/db/models.py` (curation audit
    docstring)
  - `aperag/domains/retrieval/pipeline.py` × 2 (compose docstring,
    backend dispatch docstring)
* Tests (4 files):
  - `tests/unit_test/test_modularization_boundaries.py`
  - `tests/unit_test/indexing/test_graph_search_service.py`
  - `tests/unit_test/indexing/test_wave7_task8_wiring.py`
  - `tests/unit_test/indexing/test_lineage_query_protocol.py` × 3

## 12-invariant cross-check (Wave 7 §K.12)

* #12 (grep-zero LightRAG word): ✅ — `rg LightRAG aperag/ tests/`
  returns 0 hits post-sweep. Spec docs / READMEs / blueprint /
  rewrite-plan retain the word as historical attribution per
  spec-allowed list.
* All other invariants: n/a (pure docstring / comment edit, 0
  functional change).

## 4-pattern pre-check matrix

* Pattern A (kg.jsonl shape): unchanged
* Pattern B (Lineage SET semantics): unchanged
* Pattern C (Cypher LIST<MAP>): unchanged
* Pattern D (vector 3-field payload): unchanged

## Simple-stable 4-guardrail

* No new public API surface
* No new dependency
* No frontend change
* No config change

## Test plan

- [x] `rg LightRAG aperag/ tests/` → 0 hits
- [x] `uv run pytest tests/unit_test/` — 1141 unit tests pass (no
      behavioural change)
- [x] `uv run pytest tests/integration/test_w7_grep_zero_legacy_graphindex.py`
      — 10/10 pass (intent-driven gate unaffected)
- [x] `uv run ruff format --check` / `ruff check` — clean
earayu added a commit that referenced this pull request Apr 28, 2026
…(W7-10 drift) (#1773)

## What broke

Wave 7 task #10 (PR #1765) added ``list_entities`` to the
``LineageGraphStore`` Protocol + 4 backends. The
``LineageGraphStoreWithAliasRedirect`` decorator was NOT updated, and
the spelled-out passthrough invariant test
(``test_decorator_passthrough_for_non_redirected_methods``) only
covers the methods that existed when it was written — so the gap
landed silently.

Production crash on ``GET /api/v2/collections/{id}/graphs``:

```
AttributeError: 'LineageGraphStoreWithAliasRedirect' object has no attribute 'list_entities'
  File "aperag/domains/knowledge_graph/service.py", line 149,
       in get_knowledge_graph
    entities = await store.list_entities(label=normalized_label, limit=query_max_nodes)
```

This is also the e2e-http-provider failure visible on every Wave 7+8
PR including the just-merged #1771 / #1772 — pre-existing on main
since W7-10 close-out, masked because the e2e-http-smoke shapes don't
exercise the graph view endpoint.

## Fix

1. Add ``list_entities`` passthrough method on the decorator. Filter
   is by ``label`` (entity type) + pagination, not by name — rows are
   already canonical (alias rows live in
   ``aperag_lineage_entity_alias``, not in the entity table). Same
   passthrough rationale as ``list_entity_labels`` /
   ``query_entities_by_keyword``; module docstring updated.

2. Add ``list_entities`` row to the spelled-out passthrough test.

3. **NEW meta-invariant test**:
   ``test_decorator_covers_every_lineage_graph_store_method`` —
   introspect ``LineageGraphStore`` Protocol via ``dir()`` and assert
   the decorator implements every public method. Catches the
   "decorator missing method" half of the drift gap that the
   spelled-out test couldn't catch (because spelled-out tests only
   cover methods that existed when written). A future Protocol
   addition without a decorator update now fails CI immediately with
   a clear "missing method(s): X" assertion.

## Hard-gate format checklist (Wave 7+8 mirror)

### 4-pattern pre-check matrix
- [x] **#1 不丢失好的算法和设计**: passthrough rationale preserved per
      module docstring (filter-by-label not filter-by-name).
- [x] **#2 尽快上线**: 1 fix + 2 new tests (1 spelled-out row + 1
      meta-test). No new abstraction.
- [x] **#3 简单稳定**: passthrough is byte-for-byte forward, mirror
      of ``list_entity_labels``. Meta-test uses stdlib introspection,
      no new dep.
- [x] **#4 私有化部署免维护**: zero new env / config / dep. Backend-
      portable (decorator wraps the 4-backend Protocol; the actual
      ``list_entities`` implementation already covered by 4-backend
      compat tests).

### Simple-stable 4-guardrail
- [x] No new abstraction.
- [x] No backward-compat shim.
- [x] No silent behavior change — fix is additive (method that didn't
      exist now exists; behavior matches 4-backend Protocol contract).
- [x] Meta-test prevents this exact class of drift recurring.

## Test plan

- [x] ``uv run pytest tests/unit_test/indexing/test_alias_redirect_store.py``
      — **16 passed** (was 15, +1 meta-test, +1 spelled-out
      ``list_entities`` row covered by existing test function).
- [x] ``uvx ruff check`` — clean. ``uvx ruff format --check`` — clean.
- [ ] Production verify: ``GET /collections/{id}/graphs`` returns 200
      after this lands (the original crash from main e2e-http-provider
      log) — will be visible on next PR's e2e-http-provider checks.

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.

1 participant