# KOPR R121 — final modal ephemeris release gate

**Base build:** `KOPR_CLEAN_BUILD_20260729_R120_WPLANNER_PERSISTENT_NBODY_SEGMENTS.zip`  
**Date:** 2026-07-29  
**Scope:** final cross-widget modal-ephemeris enforcement, deterministic workload fixtures, informational benchmark and documentation cleanup; no scientific-model change.

## Summary

R121 closes the R115–R121 modal ephemeris sequence. The release does not alter
the two-body equations introduced in R116, the R117 point scheduler, the
R118/R119 Planner interval model or the validated R120 persistent segments.
Instead it makes those choices an enforceable cross-widget contract.

The authoritative routing is now:

| Widget | Dynamics | Output | Scheduling | Cache |
|---|---|---|---|---|
| WVisual | N-body | astrometric position | serial series | memory trajectory |
| WCCD | N-body | astrometric position | serial series | memory trajectory |
| WStack | N-body | astrometric position | serial series | memory trajectory |
| WPlanner | N-body | planner full | comet intervals | persistent validated segments |
| WAnalyzer | two-body | photometric geometry | point batches | memory geometry |
| WComparison | two-body | photometric geometry | point batches | memory geometry |

## New release gate

`modal_ephemeris_release_gate.py` is a standard-library-only AST/source gate. It
can run without Qt, NumPy, Astropy, jplephem or DE440s and rejects:

- a widget using a policy other than its approved constant;
- process scheduling or persistent N-body segments in WStack;
- N-body, DOP853 or astrometric calculation in the analytical two-body kernel;
- RA/Dec-capable output in the photometric geometry profile;
- loss of the global point-batch route in Analyzer/Comparison;
- loss of interval preparation, dynamic comet jobs or persistent segment fitting in Planner;
- a process worker starting another process scheduler;
- Qt or Matplotlib objects in process payload modules;
- loss of stale-result, transactional cache, shared-Cancel or atomic-write guards.

The existing `analysis_release_gate.py` remains the GUI/QThread-specific
Analyzer/Comparison gate. `validate_performance_release.py` now runs both gates.

## Deterministic workload fixture

`tests/data/modal_ephemeris_performance_reference_r121.json` records stable,
hardware-independent limits:

```text
ordinary analytical workload:       10,000 points, local batch
process threshold:                  200,000 missing points
point batch bounds:                 256–2,048 points
one large 10,000-point apparition:  at least 16 batches
12 × 20-point small apparitions:    one coalesced batch
cosmetic redraw:                    0 new physical calls
Planner forward interval:           500 points
cold Planner integration count:     1
warm Planner integration count:     0
Planner maximum workers:            4, while reserving one CPU
WStack process jobs:                0
```

The tests additionally verify the exact policy matrix, deterministic ordering,
absence of nested pools and the platform-neutral benchmark contract.

## Informational benchmark

`benchmark_modal_ephemeris.py` reports wall time, throughput, peak RSS,
scheduler shapes and synthetic Planner cold/warm call counts. On the available
headless build machine the median results were:

```text
10 points:       0.00016 s
1,000 points:    0.0149 s
10,000 points:   0.1489 s
100,000 points:  1.4972 s
```

The 10,000-point workload produced 24 deterministic internal batches with a
largest batch of 417 points but stayed local, as intended. The synthetic
500-point Planner probe performed one cold integration and zero warm
integrations after reopening the persistent cache.

These values are observations from one machine. They are not CI acceptance
limits and are not claimed as representative of a complete Astropy/jplephem/
DE440s installation.

## Documentation cleanup

- updated the `ephemeris_policy.py` module description from the historical R115
  shadow state to the final production matrix;
- added `docs/developer/EPHEMERIS_MODAL_ARCHITECTURE.md`;
- added `docs/developer/EPHEMERIS_R121_MODAL_RELEASE_GATE.md`;
- extended `PERFORMANCE_REFERENCE_GUIDE.md` with the modal gate and benchmark;
- updated the changelog and QA entry point;
- made the historical AUTOPHOT flux-flow test independently collectable in a
  headless runtime instead of relying on another test's import order.

## Preserved scientific contract

R121 does not change:

- WVisual/WCCD/WStack Cowell forces, DOP853 tolerances, DE440s use or light time;
- WAnalyzer/WComparison two-body conic propagation, solar model, light time,
  distance or phase equations;
- date-aware element/apparition selection;
- adaptive model-curve sampling or photometric H0/n and phase corrections;
- Planner best-time logic, topocentric conversion or displayed fields;
- persistent segment degree, validation tolerances, schema or disk limit.

## Validation

Focused R111/R114–R121 gate:

```text
71 passed
1 skipped
0 failed
```

Complete deterministic QA, including the final manifest group:

```text
1720 passed
7 skipped
0 failed
```

The seven skips require a complete optional PyQt5 or Astropy FITS/time runtime.
Final SHA-256 manifests contain 495 QA files and 153 CLEAN files. The build
environment did not provide a real DE440s analytical corpus or a live Qt
display, so target-system cold/warm timing, CPU utilization and GUI Cancel
remain smoke checks rather than unsupported release claims.
