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:main

The 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

LayerResponsibilityImportant boundary
kopr.coreScientific/domain logic, numerical algorithms, astronomy/ephemerides, photometry, observation and Planner core contracts.Qt-free; no dependency on features, application or UI.
kopr.infrastructurePersistence, files, FITS/RAW, networking, MPC/COBS/VizieR, catalogues, PDF and other external adapters.No dependency on features, application or UI.
kopr.featuresFeature orchestration/state for Analyzer, Planner, WCCD, WStack, Visual and ephemeris workflows.Cross-feature use only through intentional public APIs.
kopr.uiShared presentation components. kopr.ui.common is the cross-feature shared UI boundary.Must not own scientific/domain decisions.
kopr.applicationTop-level composition, lifecycle, wiring and application entry.Reusable science does not belong here.
kopr.compatExplicit compatibility contracts/adapters.Never a destination for new product behavior.
kopr.configConfiguration definitions and config-facing contracts.Not a global mutable-state hub.
kopr.legacyQuarantined 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/kopr

The 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 ZIP

The 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

  1. Start from the latest qualified canonical build.
  2. Read the current development policy and current machine-readable architecture policy.
  3. Identify the canonical owner under src/kopr/.
  4. Run the architecture guard before editing.
  5. Implement one coherent capability in the correct layer; do not create flat-root helpers or duplicate implementations.
  6. 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.
  7. Run risk-appropriate focused/regression/package/GUI/scientific qualification and the architecture guard again.

See the exact normative rules in Development policy.