Canonical application architecture
KOPR is a fully canonical src/kopr package application. All active product implementation is owned inside the package; retained top-level Python files form a non-owning compatibility/source-launcher perimeter.
R515 / C8 canonical baseline R515, not R410, is the final canonical-convergence baseline. The current public release line is owned by kopr.config.release_identity and is displayed dynamically on the project home page.
Canonical baseline and architecture evidence
R515/C8 remains the canonical architecture baseline: all active implementation belongs under src/kopr/, and flat-root Python is a non-owning compatibility/launcher perimeter.
The previously supplied Theta-38 report recorded 84 root Python surfaces, 316 canonical src/kopr Python files, 400 production Python files, 772 canonical import edges, 0 canonical SCCs and 0 architecture violations. The Theta-38→Theta-60 documentation summary does not supply a newer exact architecture inventory, so those counts are retained as dated Theta-38 evidence rather than relabelled as current Theta-60 counts. Hard-zero ownership/cycle/violation invariants remain the governing contract.
Entry points and packaging
source checkout: python3 kopr.py
installed CLI: kopr
canonical target: kopr.application.main:mainThe root kopr.py is a minimal historical source-checkout launcher. It does not own application behavior. Application composition and MainWindow are canonically owned by kopr.application.main. An installed wheel/package contains the complete active application and does not require root-only implementation modules.
The retired _kopr_src_bootstrap.py mechanism is not part of the current architecture and must not be recreated.
Canonical package layers
| Layer | Responsibility | Important boundary |
|---|---|---|
kopr.core | Scientific/domain logic, numerical algorithms, astronomy/ephemerides, photometry, observation and Planner core contracts. | Qt-free; no dependency on features, application or UI. |
kopr.infrastructure | Persistence, files, FITS/RAW, networking, MPC/COBS/VizieR, catalogues, PDF and other external adapters. | No dependency on features, application or UI. |
kopr.features | Feature orchestration/state for Analyzer, Planner, WCCD, WStack, Visual and ephemeris workflows. | Cross-feature use only through intentional public APIs. |
kopr.ui | Shared presentation components. kopr.ui.common is the cross-feature shared UI boundary. | Must not own scientific/domain decisions. |
kopr.application | Top-level composition, lifecycle, wiring and application entry. | Reusable science does not belong here. |
kopr.compat | Explicit compatibility contracts/adapters. | Never a destination for new product behavior. |
kopr.config | Configuration definitions and config-facing contracts. | Not a global mutable-state hub. |
kopr.legacy | Quarantined historical behavior. | Not a target for new features. |
kopr.tools / repository tools/ | Diagnostics, architecture, QA and maintenance. | Production runtime must not depend on QA/migration tooling. |
Hard architectural invariants
active_root_implementation_modules = 0
partial_legacy_facades_with_implementation = 0
root_to_root_import_edges = 0
src_kopr_to_flat_root_imports = 0
src_kopr_SCC = 0
architecture_violations = 0- All new implementation belongs under
src/kopr/. - One capability has one canonical owner.
- Canonical code never imports a KOPR flat-root compatibility module.
- The canonical package dependency graph remains acyclic.
- Architecture budgets/allowlists are not weakened merely to make a change pass.
flat-root compatibility / launcher
↓
canonical src/koprThe dependency arrow is one-way. The reverse direction is forbidden.
Root compatibility perimeter
R515 retained 86 top-level Python surfaces, all explicitly classified and non-owning. They can preserve historical import paths, module/class/function identity, pickle GLOBAL resolution, monkeypatch/rebinding semantics, historical CLI behavior or source-checkout compatibility.
They are not a second implementation layer. New scientific, persistence, networking, orchestration or GUI behavior must not be added to them. Compatibility removal or semantic retargeting requires a separate compatibility-breaking plan and qualification.
Canonical ownership and public APIs
Documentation should describe capabilities and canonical package ownership rather than old flat-root filenames. When a historical release page names modules such as wplanner.py, wlightcurves.py or koprhand.py, interpret those names as historical implementation evidence. Current code ownership is defined by src/kopr/ and the machine-readable package/API policies.
Examples of intentional current boundaries include kopr.features.analyzer.api, kopr.features.ephemeris.api, kopr.core.lightcurves.observations and kopr.core.lightcurves.projection. Internal modules are not public merely because Python can import them.
Current architecture and QA tooling
tools/architecture/architecture_guard.py
tools/architecture/architecture_policy.json
tools/architecture/compatibility_perimeter.json
tools/architecture/legacy_compatibility_identity_contract.json
tools/architecture/package_api_policy.json
tools/qa/Run python3 tools/architecture/architecture_guard.py before and after production or structural work. Active tools/migration/ is intentionally absent. Historical migration reports, per-release migration gates and source-layout budgets are audit evidence only, not current development instructions.
Public release identity
canonical owner: src/kopr/config/release_identity.py
website display: refreshed from the downloaded Python 3 repository ZIPThe current user-facing release is not copied into the documentation as a fixed value. koprgit.py reads the canonical release source from the newly downloaded repository archive without importing or executing it, and publishes the resulting KOPR Live <Series>-<Revision> label on the project home page. When present, the technical package version is read separately from pyproject.toml.
R515/C8 remains the structural baseline; internal Rxxx identifiers are engineering evidence only. Theta-specific release values in historical source reports remain provenance, not strings to copy forward. Documentation-only revisions do not advance the KOPR product release. The homepage release/download label continues to be derived from the downloaded canonical repository archive.
Why R515, not R410, is the structural baseline
R410 completed an earlier seven-phase behavior-neutral plan but left a hybrid architecture. A later runtime audit proved that 67/67 actual root implementation modules remained launcher-reachable. The end-state contract was therefore tightened to zero root implementation ownership.
R515/C8 is the first baseline that proves the full canonical end state. Any older wording such as “R410 completed migration”, “root implementation owners are acceptable” or “use tools/migration/ as the current source of truth” is historical and must not guide new development.
WCCD helper ownership
This retained documentation anchor points to the current canonical rule: WCCD helper/scientific behavior has one owner under src/kopr/. Use integration contracts and the current package/API policy for the exact canonical boundary; do not implement shared helper logic in flat-root compatibility files.
Rules for extending KOPR
- Start from the latest qualified canonical build.
- Read the current development policy and current machine-readable architecture policy.
- Identify the canonical owner under
src/kopr/. - Run the architecture guard before editing.
- Implement one coherent capability in the correct layer; do not create flat-root helpers or duplicate implementations.
- If unexpected path/global-state/Qt/multiprocessing/serialization/scientific coupling appears and needs a complex solution, re-plan the next bounded batch rather than adding an architecture exception.
- Run risk-appropriate focused/regression/package/GUI/scientific qualification and the architecture guard again.
See the exact normative rules in Development policy.