Skip to content

cleanup(phase7): backend destructive cleanup — B1-B6 + partial §3.2 audit migration#1665

Merged
earayu merged 14 commits into
mainfrom
bryce/phase7-backend-cleanup
Apr 24, 2026
Merged

cleanup(phase7): backend destructive cleanup — B1-B6 + partial §3.2 audit migration#1665
earayu merged 14 commits into
mainfrom
bryce/phase7-backend-cleanup

Conversation

@earayu

@earayu earayu commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

Phase 7 Backend destructive cleanup — task #31

Per docs/modularization/cleanup-inventory.md v1 (hard-cut口径) and PM msg=b55ca803 / msg=b2f621b6.

Scope completed

Batch Status Commit
B1 17 aperag/service/* shim delete + caller migrate 919a6cea
B2 12 aperag/views/* shim + empty __init__ delete 5df80898
B3 aperag/agent_runtime/ 5-file re-export package delete 7e4a1e59
B4 aperag/evaluation_v2/ 7-file re-export package delete (Celery task 字符串 aperag.tasks.evaluation.* preserved) adfcacf7
B5 aperag/db/models.py cross-domain re-export block strip (Invitation Role top-level import preserved per §1 Layer C) 3225e23f
B5 test Phase3 G11 audit updated for post-B5 canonical paths 25bbb25d
B6 aperag/schema/view_models.py 7 dual-hook blocks strip + _bind_view_models_reexports() hooks removed + callers migrated to aperag.domains.<d>.schemas;also removed v2-covered v1 views (collections.py / main.py / chat_documents.py / test.py) 61c071d1
B-audit §3.2 partial 5 migrations + 4 direct rm (see below) 27c756ef 07e790bf 00deafc1 880edb81 1c5c86b8
B7 No-op — v0 drift (v1 clarified: chat/history/ is ACTIVE code, misc/stopwords.txt is data, graph/ already absent)

§3.2 ACTIVE_LEGACY migrations done

  • aperag/service/chat_completion_service.pyaperag/domains/conversation/service/chat_completion_service.py
  • aperag/service/setting_service.pyaperag/domains/governance/service/setting_service.py
  • aperag/service/test_mcp_agent.pytests/fixtures/mcp_agent.py
  • aperag/views/config.pyaperag/domains/identity/api/config_routes.py (mount /api/v1/config preserved)
  • aperag/views/openai.pyaperag/domains/conversation/api/openai_routes.py (mount /v1/chat/completions preserved)
  • aperag/views/{collections,main,chat_documents,test}.py → rm (v2 已覆盖 / dev-only / empty stub)

§3.2 deferred with canonical reasons (need 主架构师 SSoT decision)

以下 migrations 触达 v1 legacy ORM 的 canonical-home 决策或 Layer A PERMANENT Protocol 边界,不属于单个 coding lane scope。

File Defer reason
aperag/service/evaluation_service.py imports Evaluation / EvaluationItem / EvaluationItemStatus / EvaluationStatus ORM from aperag/db/models.py;legacy v1 tables 未 migrate 到 aperag/domains/evaluation/db/models.py
aperag/service/export_service.py imports ExportTask / ExportTaskStatus ORM;同样无 knowledge_base domain canonical home
aperag/service/question_set_service.py imports Question / QuestionSet / User ORM;同样 canonical home issue
aperag/views/auth.py + aperag/views/utils.py auth.py 依赖 Invitation ORM(§1 Layer C);views/utils.py 跨域 helper
aperag/views/export.py transitively depends on deferred aperag.service.export_service
aperag/views/prompts.py imports §1 Layer A PERMANENT prompt_template_service;G1 forbids domain→aperag/service/*
aperag/views/quota.py 同上,依赖 §1 Layer A quota_service
aperag/views/settings.py imports Settings Pydantic LOCAL to view_models.py;needs canonical home decision (governance vs KB)
aperag/views/graph.py file absent in this worktree (already removed);inventory entry stale

§1 PERMANENT 白名单 self-check (all preserved)

  • Layer A (G18 alt Protocol+DI seams, 2):quota_service.py + prompt_template_service.py 未动
  • Layer B (cross-domain standalone-infra, 1):search_pipeline_service.py 未动
  • Layer C (Invitation Role binding):aperag/db/models.py top-level Role import 保留
  • Layer D (G17/G18-alt CRITICAL_WIRINGS, 9):app.py wiring 字节保留
  • Layer E (misc shared-infra dirs):未动

Gates (per inventory §3.4)

  • uv run pytest tests/unit_test/test_modularization_boundaries.py -x -q20 pass / 0 fail (G1-G19 all green)
  • uv run ruff check aperag/ tests/ config/ → clean
  • uv run pytest tests/unit_test/ -x --ignore tests/unit_test/objectstore -q577 pass / 29 skip / 0 fail (1 pre-existing FE adapter-boundary test deselected — listUserQuotas trimmed by chore(fe-cleanup): Phase 7 destructive cleanup — F3/F4/F5/F6 (#32) #1664,not introduced by this PR)

OpenAPI byte-check 未跑 — per v1 §0 hard-cut 口径 accept byte changes.

Net diff

~4 300 deletions / ~550 insertions / net ~3 750 LOC deleted

Ghost-check

Ghost-check: none — §1 Layer A/B/C/D/E whitelist untouched; G1-G19 20/20 green; deferred §3.2 items documented above with canonical rationale requiring 主架构师 SSoT decision.

🤖 Generated with Claude Code

earayu and others added 14 commits April 25, 2026 03:10
…allers

Delete the Phase 3/4/5 pure re-export shims under ``aperag/service/``:
api_key_service, audit_service, bot_service, chat_collection_service,
chat_document_service, chat_service, chat_title_service,
collection_service, collection_summary_service, default_model_service,
document_service, graph_service, llm_available_model_service,
llm_provider_service, marketplace_collection_service, marketplace_service,
turn_feedback_service.

All consumer imports rewritten to the canonical
``aperag.domains.<d>.service.<name>`` paths (app.py wire-up, views/main.py,
views/collections.py, utils/audit_decorator.py, graph_curation/service.py,
the two remaining ACTIVE_LEGACY services chat_completion_service.py /
question_set_service.py, config/celery_tasks.py, and 9 test modules
including the monkeypatch target in tests/unit_test/tasks/test_reconciler.py).

PERMANENT (§1.1): quota_service, prompt_template_service,
search_pipeline_service remain untouched.

Gate: tests/unit_test/test_modularization_boundaries.py 20 passed.

Ghost-check: none — batch B1; no PERMANENT §1.1 files touched;
G17/G18-alt wirings in app.py lines 101–145 unchanged.

Per docs/modularization/cleanup-inventory.md §B1.

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

Delete the Phase 3/4/5 pure router re-export shims under
``aperag/views/``: agent_runtime, api_key, audit, bots_v2, chat,
collections_v2, documents_v2, evaluation_v2, llm, marketplace,
marketplace_collections, providers_v2, plus the empty ``__init__.py``
(no consumers do ``from aperag.views import …``).

All consumer imports rewritten to the canonical domain router paths
across 6 OpenAPI-contract test modules and the llm rerank helper test.

Do not touch §3.2 ACTIVE_LEGACY views (auth.py, main.py, prompts.py,
settings.py, config.py, export.py, quota.py, openai.py, collections.py,
test.py, utils.py, chat_documents.py). app.py mount list already uses
canonical domain routers (lines 227–250) — no wiring change.

Gate: tests/unit_test/test_modularization_boundaries.py 20 passed.

Ghost-check: none — batch B2; no PERMANENT §1.1 files touched;
G17/G18-alt wirings in app.py lines 101–145 unchanged.

Per docs/modularization/cleanup-inventory.md §B2.

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

Delete the Phase 5 step 5-S5b shim package ``aperag/agent_runtime/``
(__init__.py + runtime.py + schemas.py + services.py + storage.py),
all of which were pure re-exports of ``aperag.domains.agent_runtime.*``.

Migrated the 2 remaining live callers:
- ``aperag/service/chat_completion_service.py`` (ACTIVE_LEGACY) now
  imports runtime/schemas/services from the domain path.
- ``tests/unit_test/agent_runtime/test_agent_runtime_v3.py`` now
  imports schemas/services from the domain path.

Gate: tests/unit_test/test_modularization_boundaries.py 20 passed.
G17 / G18-alt CRITICAL_WIRINGS still pass — app.py already uses
``aperag.domains.agent_runtime.*`` for wire-up.

Ghost-check: none — batch B3; no PERMANENT §1.1 files touched.

Per docs/modularization/cleanup-inventory.md §B3.

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

Delete the Phase 5 step 5-S6 shim package ``aperag/evaluation_v2/``
(__init__.py + constants.py + judges.py + schemas.py + services.py +
tasks.py + worker.py). All were pure re-exports of
``aperag.domains.evaluation.*``. The orphaned
``EVALUATION_V2_SCHEMA_VERSION`` constant at the shim ``__init__`` had
zero consumers.

Celery task registry: Celery task NAME ``aperag.evaluation_v2.tasks.run_evaluation_run``
stays unchanged (preserved at the domain ``tasks.py`` ``@app.task(name=...)``),
so in-flight messages keep routing. The ``include=`` list in
``config/celery.py`` is updated to ``aperag.domains.evaluation.tasks``
so Celery loads the module that registers the task.

Migrated call sites:
- ``aperag/domains/evaluation/tasks.py`` lazy import of
  ``execute_evaluation_run`` now from domain path
- ``aperag/domains/evaluation/services.py`` ``launch_run`` lazy import
  of ``run_evaluation_run`` now from domain path
- ``tests/unit_test/test_evaluation_v2_worker.py`` imports + monkeypatch
  module aliases now point at domain path

Gate: tests/unit_test/test_modularization_boundaries.py 20 passed.

Ghost-check: none — batch B4; no PERMANENT §1.1 files touched.

Per docs/modularization/cleanup-inventory.md §B4.

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

Drop the ~70 LOC per-domain DB re-export block at
``aperag/db/models.py`` lines 395–462. Physical owners have been at
``aperag/domains/<d>/db/models.py`` since Phase 3/4/5 — this removes the
back-compat aggregate.

Kept unchanged (per inventory §1.2 + §1.4 + B5 local-models list):
- Top-level ``from aperag.domains.identity.db.models import OAuthAccount, Role, User``
  (Invitation class body binds Role at load time — G15-exempt).
- Local models: ConfigModel, UserQuota, ModelServiceProvider,
  ModelServiceProviderStatus, QuestionType, EvaluationStatus,
  EvaluationItemStatus, QuestionSet, Question, Evaluation,
  EvaluationItem, Setting, ExportTaskStatus, ExportTask, PromptTemplate,
  Invitation.
- ``Base = declarative_base()`` anchor and the ``from aperag.db.base``
  re-export.

Migrated 43 import blocks across 30 files to route moved symbols
through ``aperag.domains.<d>.db.models``: app.py, views (auth/main/
collections/quota/test/export/prompts/openai — ACTIVE_LEGACY imports
updated in place), service (chat_completion/quota/question_set/export/
evaluation — ACTIVE_LEGACY imports updated in place), all
``aperag/db/repositories/*``, domain lazy imports, llm helpers, tasks,
graph_curation, config/celery_tasks, config/export_tasks, and the
corresponding test modules. ``User`` / ``Role`` / ``OAuthAccount``
imports remain on ``aperag.db.models`` path per §1.2.

Alembic metadata: ``aperag/migration/env.py`` now explicitly imports
every domain's ``db.models`` module so all mappers register against
``Base.metadata`` before autogen runs (previously they rode on the
aggregate re-export block's side effects).

Ruff-I001 import-sort: ``ruff check --fix`` applied uniformly.

Gates:
- tests/unit_test/test_modularization_boundaries.py: 20 passed.
- Spot-check of 15 B1-B5 affected test modules: 117 passed.
- ruff check aperag/ tests/ config/: clean.

Ghost-check: none — batch B5; §1.1 PERMANENT files unchanged;
§1.2 Invitation/Role binding preserved; G17/G18-alt wirings unchanged.

Per docs/modularization/cleanup-inventory.md §B5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 7 B5 stripped the cross-domain re-export block from
``aperag.db.models``; the old G11 audit at
``tests/unit_test/test_phase3_reexport_audit.py`` asserted symbols
remained importable from that legacy aggregate. Rewrite the audit to
assert every Phase 3 symbol resolves from its canonical
``aperag.domains.<d>.db.models`` path AND every Phase 3 table is still
registered on ``Base.metadata`` (so Alembic autogen keeps seeing them).

G13 single-definition audit is unchanged.

Gate: tests/unit_test/test_phase3_reexport_audit.py 2 passed.
Full unit_test suite: 578 passed, 29 skipped, 0 failed.

Per docs/modularization/cleanup-inventory.md §B5 (delete gate).

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

Strips the 7 dual-hook `try:`/`except ImportError:` re-export blocks at
the bottom of `aperag/schema/view_models.py` (KB / identity / governance
/ marketplace / model_platform / conversation / agent_runtime) and the
symmetric `_bind_view_models_reexports()` write-back hooks inside each
of the 7 domain `schemas.py` modules.

All callers are rewritten to import directly from the canonical
`aperag.domains.<d>.schemas` path. `CollectionConfig` / `ModelSpec`
callers migrate to `aperag.schema.common` (their actual home since
Phase 3 Step 4b).

`view_models.py` retains its local schemas only (FailResponse, Settings,
ParserHealth*, Prompt*, Quota*, Question*, Evaluation*, ExportTask*,
LLMConfig, TargetEntityData*, NodeMerge*, ChatSuccessResponse,
EvaluationChatWith*) plus the Phase 2 retrieval / knowledge_graph
re-export block (not a dual-hook).

The 4 v2-covered v1 view files that depended on dual-hook-resolved
symbols are removed here as a unit (they cannot survive dual-hook strip
and have no migration destination per §3.2):

* `aperag/views/collections.py` (v1 upload flow; v2 provides
  `/api/v2/collections/{id}/documents/{upload,confirm,fetch-url,staged}`)
* `aperag/views/main.py` (v1 llm_providers + default_models +
  available_models; v2 providers_v2_routes covers equivalent under
  `/api/v2/providers/*` + `/api/v2/default-models`)
* `aperag/views/chat_documents.py` (empty stub, no mount)
* `aperag/views/test.py` (dev-only test-admin-register helper)

`aperag/app.py` drops the 4 imports + 3 include_router calls + the
now-unused `import os` / DEPLOYMENT_MODE dev guard.

Per hard-cut口径: `X is view_models.X is domain.schemas.X` identity
invariant is intentionally broken; every caller has migrated to the
canonical per-domain path so the invariant is no longer load-bearing.

Ghost-check: none — §1 permanent whitelist untouched (quota_service,
prompt_template_service, search_pipeline_service, db/models.py line 36,
G17/G18-alt CRITICAL_WIRINGS in app.py:~101-145, shared-infra dirs);
G1-G19 boundary gate green (20/20); broad unit test sweep 577 passed /
29 skipped / 1 pre-existing FE-only test deselected
(test_phase1_fe_complete_identity_auth_admin_audit_adapter_boundary —
flags missing `listUserQuotas` in features/admin/client-api.ts, same
failure on `origin/bryce/phase7-backend-cleanup` HEAD, not introduced
by B6); ruff clean.

See `docs/modularization/cleanup-inventory.md §3.1 F` (dual-hook strip)
+ §3.2 (v2-covered view direct-rm entries).

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

Moves `aperag/service/chat_completion_service.py` (468 LOC) to its
canonical location `aperag/domains/conversation/service/chat_completion_service.py`.
The OpenAI-compat chat completions stream belongs to the conversation
domain (chats + agent runtime integration).

Rewires the two callers:
* `aperag/views/openai.py` — import path update
* `tests/unit_test/chat/test_chat_completion_service.py` — module path
  update

Also drops the `from aperag.schema import view_models` + sole
`view_models.ModelSpec` use-site in favor of a direct
`from aperag.schema.common import ModelSpec` import (canonical home).

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20 + targeted completion tests).

See `docs/modularization/cleanup-inventory.md §3.2` row 1.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Moves `aperag/service/setting_service.py` (86 LOC) to
`aperag/domains/governance/service/setting_service.py` — global settings
(MinerU token, parser toggles) belong with governance / quota / audit.

Only imports `aperag.db.ops`, no view_models or legacy db.models
dependency, so the move is purely a path rename. Rewires two callers:
* `aperag/views/settings.py` — import path
* `aperag/tasks/utils.py` — local import inside indexing task

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20).

See `docs/modularization/cleanup-inventory.md §3.2` row 5.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Moves `aperag/service/test_mcp_agent.py` (332 LOC) to
`tests/fixtures/mcp_agent.py` — it is a standalone multi-agent RAG
smoke script, not runtime service code, and has never been imported by
the rest of the backend (zero call sites under aperag/ or tests/). Per
§3.2 row 6 its canonical home is the test-fixtures tree.

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20).

See `docs/modularization/cleanup-inventory.md §3.2` row 6.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Moves `aperag/views/config.py` (55 LOC) to
`aperag/domains/identity/api/config_routes.py`. The `/api/v1/config`
mount in `aperag/app.py` is updated to point at the new module; URL
contract is byte-preserved (same prefix, same handler, same response
shape).

`aperag/views/utils.py::get_available_login_methods` stays at its
current path for now — it is shared by auth.py (still legacy) and
several other consumers; moving it to identity requires resolving the
`views/utils.py` co-owner question (mask_api_key / validate_source_connect_config
are used by governance / KB / model_platform domains). Deferred along
with auth.py in the same follow-up.

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20).

See `docs/modularization/cleanup-inventory.md §3.2` row 10.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Moves `aperag/views/openai.py` (83 LOC) to
`aperag/domains/conversation/api/openai_routes.py`. OpenAI-compat
`/v1/chat/completions` belongs with the conversation domain (it routes
into `chat_completion_service` which landed in the same domain two
commits ago).

Replaces the `from aperag.db.models import User` dependency with a
narrow `AuthenticatedUser` `Protocol` (lesson 9a-ter / G1 boundary
pattern used by `aperag/domains/knowledge_graph/api/routes.py`). The
handler only reads `user.id` so the minimal ``id: object`` protocol is
sufficient; the fastapi-users ``User`` row structurally satisfies it.

`aperag/app.py` mount for `/v1` prefix updates to the new module; URL
contract preserved.

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20).

See `docs/modularization/cleanup-inventory.md §3.2` row 13.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`ruff check --fix` whipped three files into shape after the preceding
six migration commits; no logical change, just import-order
re-sorting that ruff's stable-sort requires and ``pre-commit`` didn't
auto-run in my worktree.

Ghost-check: none — §1 permanent whitelist untouched; G1-G19 gate green
(20/20); ruff clean.

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

Weston blocker-level CR (msg=ffe45a23) found 2 mechanical `git diff --check`
blockers from the B6 `_bind_view_models_reexports()` hook removal — both
`aperag/domains/{agent_runtime,conversation}/schemas.py` ended with three
trailing newlines after the closing bracket. Normalize to single newline.

No logic change; diff is whitespace-only.

Ghost-check: none — §1 Layer A/B/C/D/E untouched; whitespace-only EOF fix.
@earayu earayu merged commit 613514c into main Apr 24, 2026
0 of 2 checks passed
@earayu earayu deleted the bryce/phase7-backend-cleanup branch April 24, 2026 20:04
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