# Application architecture `app/` is the standalone, behavior-preserving modular source tree accepted by the user on 2026-08-01. It is the only production source boundary and must not read or import a parent checkout, a retired baseline, or a failed implementation. 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. `backend/application.py` is the narrow composition root for `DashboardService`, `RequestHandler`, and the process-wide service instance; dependency construction remains in `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. `backend/http/dispatch.py` owns only public versus authenticated guard order, named POST dispatch, feature-route traversal, static fallback, and final 404 responses. Exact POST maps live there; endpoint parsing, response fields, and feature-specific exceptions belong to `backend/features//routes.py`. - `backend/features//` 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/data/providers/tushare_client.py` is the stable public `TushareClient` facade and owns only its dataclass fields and shared cache state. Tushare HTTP transport belongs to `tushare_transport.py`; market overview and realtime breadth belong to `tushare_dashboard.py`; indices belong to `tushare_indices.py`; Shenwan membership and industry snapshots belong to `tushare_industries.py`; generic sector snapshots belong to `tushare_sectors.py`; hot-money and dragon-tiger data belong to `tushare_dragon_tiger.py`; stock detail and intraday data belong to `tushare_stocks.py`; trading-calendar, daily, and limit-list access belong to `tushare_daily.py`; small shared deterministic conversions belong to `tushare_helpers.py`. - `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/jobs/service.py` is the application-facing owner of scheduler start/stop, manual refresh submission, and periodic refresh coordination. - `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/index.html` owns only the login layer, application Shell, overview strip, status bar, global dialogs, and the single page-fragment mount point. `frontend/bootstrap.js` loads the registered page fragments before the unchanged application runtime starts. - `frontend/pages.config.js` is the only runtime owner of page-fragment paths and script execution order. Do not add page scripts directly to `index.html` or create another loader. - `frontend/app.js` is only the browser startup coordinator: initialize controls, resolve the initial route, start the authenticated application, and invoke registered binding owners. It must not own feature event handlers, dashboard rendering, account/admin behavior, theme behavior, table behavior, or application state definitions. - `frontend/shared/` is the only browser data-API/state/Shell/component boundary. Within it, `context.js` owns application state and DOM handles, `application.js` owns API/Shell/page lifecycle composition, `feedback.js` owns common feedback and motion, `dashboard.js` owns market-dashboard refresh and date coordination, `session.js` owns authentication/account access, `admin.js` owns system administration, `theme.js` owns theme switching, and `table.js` owns generic table behavior. The Bootstrap fetch is limited to registered same-origin static HTML fragments. - `frontend/pages/` owns page-local markup, behavior, and styles through `page.html`, `page.js`, and `foundation.css`. Each feature registers its own one-time control binder with the page runtime; feature selectors and event handlers must not be added to `app.js`. The original DOM and runtime were split mechanically during migration. Current maintenance is governed by the runtime registry, unique symbol owners, DOM/API contracts, JavaScript syntax checks, and Playwright behavior rather than embedded historical source ranges. - `frontend/pages/market/` owns cross-page market presentation through narrow runtime modules: `breadth.js`, `charts.js`, `entity-detail.js`, `stock-detail.js`, `preview.js`, `search.js`, and `bindings.js`. `runtime.js` is retired; do not recreate a combined market runtime or a compatibility loader. `pages.config.js` is the sole owner of their execution order. - `backend/features/screener/engine.py` is the stable screener compatibility facade only. Screener declarations belong to `catalog.py`; external factor synchronization belongs to `data_sync.py`; deterministic technical and statistical helpers belong to `indicators.py`; factor construction belongs to `factors.py`; formula validation, scoring, and local strategy compilation belong to `formula.py`; market-phase identification belongs to `regime.py`; screening execution and result persistence belong to `selection.py`; historical evaluation belongs to `backtest.py`. - `backend/features/heaven/service.py` is the stable Wentian service facade only. Manual six-line input validation and safety gates belong to `manual.py`; trend setup, market mode, source disclosure, and quality checks belong to `trend.py`; stock, index, and sector context collection belongs to `market_context.py`; personal fields, hexagrams, saved readings, and interpretation orchestration belong to `readings.py`; deterministic Jing Fang Na Jia, eight palaces, six relatives, self/response, six spirits, calendar relations, and hidden spirits belong to `six_yao.py`; source-traceable Wentian knowledge retrieval and the only LLM-bound context projection belong to `knowledge.py`; prompt construction and answer validation remain in `agent.py`. These owners cooperate through the composed service object and do not duplicate or delegate method bodies through the facade. - Application-facing system credentials, data/LLM status, and administrator settings belong to `backend/features/system/service.py`; account-context delegation belongs to `backend/features/accounts/application.py`. They are composed into `DashboardService` and must not return to the composition root. - `backend/features/market/insights.py` is the stable public `MarketInsightsService` facade only. Shared construction, trading context, stock master access, and concept parsing belong to `insights_context.py`; auction scoring and candidate construction belong to `insights_auction_scoring.py`; auction session, amount history, watchlist enrichment, and live snapshots belong to `insights_auction_data.py`; auction result orchestration belongs to `insights_auction.py`; theme library/detail behavior belongs to `insights_themes.py`; and hot ranking behavior belongs to `insights_popularity.py`. - `frontend/shared/tokens.css` owns global design semantics. Shared foundations live in `frontend/shared/*.css` and `frontend/shared/components/*.css`; page foundations live beside their page in `frontend/pages//foundation.css`. These 22 files replace the retired `frontend/styles/styles.css`, four historical refinement layers, and the former Wentian page stylesheet. Production loads only this canonical stack: every selector/context pair has one owner, shared roots stay in shared files, and page-scoped rules stay beside their page. - `config/` is the versioned registry for pages, features, APIs, datasets, quality rules, jobs, and the generated candidate architecture inventory. The source root has four Python entry modules only: `server.py` starts and exports the process surface, `database.py` remains the documented schema/composition anchor, `api_access.py` owns the route-access registry entry, and `sync_data.py` is the manual synchronization command. The 19 migration-only import aliases were retired after all internal and test consumers moved to canonical `backend/` owners. Do not recreate root-level feature import shims. Generated local artifacts belong under `runtime/`: server output in `runtime/logs`, Python cache in `runtime/cache`, and browser artifacts in `runtime/test-results`. Docker continues to emit logs through its configured logging driver instead of writing into the source tree. ## Non-negotiable maintenance rules 1. Preserve account ownership in every user-private query and test it with two accounts. 2. Browser business-data requests go through `frontend/shared/api.js`; only `frontend/bootstrap.js` may fetch registered static page fragments. 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 create root-level feature compatibility modules; import the canonical `backend/` owner directly. 5. Do not remove 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. 7. Do not recreate late-loading `legacy.css`, `override.css`, `fix.css`, or page-wide patch layers. Change the canonical shared or page owner and keep the CSS ownership tests green. 8. Do not put `workspace-view` roots back into `frontend/index.html`. Add or change page DOM only in its registered `frontend/pages//page.html`, without introducing a second fragment or runtime-script registry. 9. Do not add feature selectors, feature event listeners, shared state declarations, or shared service implementations to `frontend/app.js`; extend the existing unique owner and keep the startup-entry boundary tests green. 10. Do not merge market charts, previews, search, stock details, entity details, breadth, and event binding back into one runtime file. Keep each definition in its registered owner and keep the market runtime ownership test green. 11. Do not merge screener catalogs, data synchronization, indicators, factor construction, formulas, regime detection, selection, and backtesting back into one engine. Keep `backend/features/screener/engine.py` as a compatibility facade and preserve one canonical owner for each responsibility. 12. Do not merge Tushare transport, dashboard, indices, Shenwan industries, sectors, dragon-tiger data, stock detail, and daily-market access back into one client. Keep `backend/data/providers/tushare_client.py` as the single public class facade, and do not duplicate provider method bodies in that facade or another compatibility module. 13. Do not merge Wentian manual validation, trend orchestration, market-context collection, and reading/LLM behavior back into one service. Keep `backend/features/heaven/service.py` as a method-free composition facade and preserve one canonical owner for every Wentian service method. 14. Do not merge auction scoring, auction data preparation, auction orchestration, themes, popularity, and shared insight context back into one market-insights service. Keep `backend/features/market/insights.py` as a method-free public facade and preserve one canonical owner for every market-insight method. 15. Do not put feature route bodies, system settings behavior, account delegation, or job lifecycle methods back into `backend/application.py`. Keep it as a composition root; keep common HTTP guard/404 behavior in `backend/http/dispatch.py`; and keep endpoint-specific parsing and responses in the corresponding `backend/features//routes.py`. 16. Do not add preservation source-range markers, copied historical CSS fragments, or a tool that reconstructs the retired monolithic frontend. Historical maps remain evidence only; current owners and behavior tests are the maintenance boundary. Current maintenance rules are in `AGENTS.md` and `docs/maintenance/人工维护指南.md`. Historical migration constraints and evidence remain under `docs/migration/` for audit only.