13 KiB
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
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.pyis the stable command/import facade.backend/application.pyis the narrow composition root forDashboardService,RequestHandler, and the process-wide service instance; dependency construction remains inbackend/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.pyowns 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 tobackend/features/<feature>/routes.py.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/data/providers/tushare_client.pyis the stable publicTushareClientfacade and owns only its dataclass fields and shared cache state. Tushare HTTP transport belongs totushare_transport.py; market overview and realtime breadth belong totushare_dashboard.py; indices belong totushare_indices.py; Shenwan membership and industry snapshots belong totushare_industries.py; generic sector snapshots belong totushare_sectors.py; hot-money and dragon-tiger data belong totushare_dragon_tiger.py; stock detail and intraday data belong totushare_stocks.py; trading-calendar, daily, and limit-list access belong totushare_daily.py; small shared deterministic conversions belong totushare_helpers.py.backend/database/owns connection management, ordered migrations, and narrow repository adapters. Rootdatabase.pyremains 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.pyis 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.htmlowns only the login layer, application Shell, overview strip, status bar, global dialogs, and the single page-fragment mount point.frontend/bootstrap.jsloads the registered page fragments before the unchanged application runtime starts.frontend/pages.config.jsis the only runtime owner of page-fragment paths and script execution order. Do not add page scripts directly toindex.htmlor create another loader.frontend/app.jsis 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.jsowns application state and DOM handles,application.jsowns API/Shell/page lifecycle composition,feedback.jsowns common feedback and motion,dashboard.jsowns market-dashboard refresh and date coordination,session.jsowns authentication/account access,admin.jsowns system administration,theme.jsowns theme switching, andtable.jsowns generic table behavior. The Bootstrap fetch is limited to registered same-origin static HTML fragments.frontend/pages/owns page-local markup, behavior, and styles throughpage.html,page.js, andfoundation.css. Each feature registers its own one-time control binder with the page runtime; feature selectors and event handlers must not be added toapp.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, andbindings.js.runtime.jsis retired; do not recreate a combined market runtime or a compatibility loader.pages.config.jsis the sole owner of their execution order.backend/features/screener/engine.pyis the stable screener compatibility facade only. Screener declarations belong tocatalog.py; external factor synchronization belongs todata_sync.py; deterministic technical and statistical helpers belong toindicators.py; factor construction belongs tofactors.py; formula validation, scoring, and local strategy compilation belong toformula.py; market-phase identification belongs toregime.py; screening execution and result persistence belong toselection.py; historical evaluation belongs tobacktest.py.backend/features/heaven/service.pyis the stable Wentian service facade only. Manual six-line input validation and safety gates belong tomanual.py; trend setup, market mode, source disclosure, and quality checks belong totrend.py; stock, index, and sector context collection belongs tomarket_context.py; personal fields, hexagrams, saved readings, and model interpretation belong toreadings.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 tobackend/features/accounts/application.py. They are composed intoDashboardServiceand must not return to the composition root. backend/features/market/insights.pyis the stable publicMarketInsightsServicefacade only. Shared construction, trading context, stock master access, and concept parsing belong toinsights_context.py; auction scoring and candidate construction belong toinsights_auction_scoring.py; auction session, amount history, watchlist enrichment, and live snapshots belong toinsights_auction_data.py; auction result orchestration belongs toinsights_auction.py; theme library/detail behavior belongs toinsights_themes.py; and hot ranking behavior belongs toinsights_popularity.py.frontend/shared/tokens.cssowns global design semantics. Shared foundations live infrontend/shared/*.cssandfrontend/shared/components/*.css; page foundations live beside their page infrontend/pages/<feature>/foundation.css. These 22 files replace the retiredfrontend/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
- Preserve account ownership in every user-private query and test it with two accounts.
- Browser business-data requests go through
frontend/shared/api.js; onlyfrontend/bootstrap.jsmay fetch registered static page fragments. Provider calls go through the data boundary; model calls go throughbackend/llm/. - Calculation datasets fail closed when required source, date, unit, freshness, or coverage evidence is missing. Display fallbacks do not silently enter calculations.
- Do not create root-level feature compatibility modules; import the canonical
backend/owner directly. - Do not remove uncertain code without reference scanning, old/new differential evidence, browser checks, and manual acceptance.
- Run
python tools/verify_baseline.pyfor every change and add--e2ewhen runtime or frontend behavior can be affected. - 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. - Do not put
workspace-viewroots back intofrontend/index.html. Add or change page DOM only in its registeredfrontend/pages/<feature>/page.html, without introducing a second fragment or runtime-script registry. - 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. - 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.
- 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.pyas a compatibility facade and preserve one canonical owner for each responsibility. - 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.pyas the single public class facade, and do not duplicate provider method bodies in that facade or another compatibility module. - Do not merge Wentian manual validation, trend orchestration, market-context collection,
and reading/LLM behavior back into one service. Keep
backend/features/heaven/service.pyas a method-free composition facade and preserve one canonical owner for every Wentian service method. - 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.pyas a method-free public facade and preserve one canonical owner for every market-insight method. - 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 inbackend/http/dispatch.py; and keep endpoint-specific parsing and responses in the correspondingbackend/features/<feature>/routes.py. - 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.