83 lines
4.7 KiB
Markdown
83 lines
4.7 KiB
Markdown
# Candidate architecture
|
|
|
|
`app/` is the behavior-preserving modular source tree accepted by the user on 2026-08-01.
|
|
The original `webapp/` runtime remains the deployment rollback baseline until an explicitly
|
|
approved switch. `next/` is a rejected, frozen implementation and is not a source for this
|
|
directory.
|
|
|
|
The application deliberately remains a modular monolith: one Python process, one SQLite WAL
|
|
database, and a build-free HTML/CSS/JavaScript client. The migration changed source ownership
|
|
and imports, not the technology stack or observable product behavior.
|
|
|
|
## Runtime path
|
|
|
|
```text
|
|
browser
|
|
-> frontend/shared/api.js
|
|
-> backend HTTP transport and feature HTTP mixins
|
|
-> feature services
|
|
-> repositories / DataGateway / LLMGateway
|
|
-> SQLite / market providers / model providers
|
|
|
|
background scheduler
|
|
-> backend/jobs
|
|
-> the same feature services and repositories
|
|
```
|
|
|
|
## Source ownership
|
|
|
|
- `server.py` is the stable command/import facade. Runtime composition lives in
|
|
`backend/application.py` and `backend/bootstrap/`.
|
|
- `backend/bootstrap/` owns process configuration, dependency construction, startup, and
|
|
shared input/display-format contracts. It does not own feature behavior.
|
|
- `backend/http/` owns common authentication, request IDs, JSON/NDJSON responses, static
|
|
delivery, streaming connection lifecycle, and error normalization. Feature-specific
|
|
transport handlers live beside their feature.
|
|
Exact POST endpoints that only delegate to one of those handlers use the explicit maps in
|
|
`backend/application.py`; endpoints with path parameters, body handling, or special error
|
|
semantics remain visible control flow in `RequestHandler`.
|
|
- `backend/features/<feature>/` owns the mechanically moved service, repository, HTTP, agent,
|
|
or deterministic calculation code for that product area.
|
|
- `backend/data/` owns provider construction, source policy, provenance, units, freshness,
|
|
coverage, display-versus-calculation eligibility, and shared numeric normalization policies.
|
|
- `backend/database/` owns connection management, ordered migrations, and narrow repository
|
|
adapters. Root `database.py` remains the legacy schema/composition anchor and combines the
|
|
feature repository mixins; do not add feature queries to it.
|
|
- `backend/jobs/` owns job definitions, locks, retries, idempotency, and persisted run state.
|
|
- `backend/llm/` owns model selection, membership/quota checks, fallback, provider transport,
|
|
streaming rules, and call audit. Feature agents only prepare messages and interpret
|
|
feature-specific results.
|
|
- `frontend/shared/` is the only browser API/state/Shell/component boundary.
|
|
- `frontend/pages/` owns page-local behavior. The original runtime was split mechanically;
|
|
source markers and preservation tests prove that the pieces reassemble to the audited
|
|
original, apart from explicitly registered trial retirements.
|
|
- `frontend/styles/`, `frontend/shared/tokens.css`, and the Wentian page stylesheet preserve
|
|
the approved cascade and light/dark/mobile behavior.
|
|
- `config/` is the versioned registry for pages, features, APIs, datasets, quality rules,
|
|
jobs, and the generated candidate architecture inventory.
|
|
|
|
Root modules such as `screener.py`, `tushare_client.py`, and `mentor_agent.py` are compatibility
|
|
aliases to canonical modules. They contain no second implementation and remain only because
|
|
the original public import surface is part of the preservation contract. Canonical backend
|
|
modules must import other canonical modules directly rather than routing through these aliases.
|
|
The remaining `api_access` import in `backend/application.py` and preserved lazy
|
|
`sentiment_engine` import in the screener repository are registered transition boundaries;
|
|
the root `database.py` remains the documented schema/composition anchor.
|
|
|
|
## Non-negotiable maintenance rules
|
|
|
|
1. Preserve account ownership in every user-private query and test it with two accounts.
|
|
2. Browser requests go through `frontend/shared/api.js`; provider calls go through the data
|
|
boundary; model calls go through `backend/llm/`.
|
|
3. Calculation datasets fail closed when required source, date, unit, freshness, or coverage
|
|
evidence is missing. Display fallbacks do not silently enter calculations.
|
|
4. Do not implement logic in both a root compatibility module and a canonical module.
|
|
5. Do not remove compatibility or uncertain code without reference scanning, old/new
|
|
differential evidence, browser checks, and manual acceptance.
|
|
6. Run `python tools/verify_baseline.py` for every change and add `--e2e` when runtime or
|
|
frontend behavior can be affected.
|
|
|
|
The authoritative migration constraints and handoff procedure are in
|
|
`../docs/migration/原版保真迁移总纲.md` and
|
|
`../docs/migration/人工维护与本地切换指南.md`.
|