# KOPR R102 – Ephemeris dead-code cleanup report

**Base build:** `KOPR_CLEAN_BUILD_20260728_R101_GLOBAL_EPHEMERIS_CUTOVER_ENFORCEMENT.zip`  
**Date:** 2026-07-28  
**Scope:** remove proven dead/duplicate ephemeris code after the R101 global cutover, without changing physical calculations or widget outputs.

## 1. Result

R102 completes the planned cleanup phase after ephemeris unification.

The application still has exactly one production ephemeris boundary:

```text
compute_comet_ephemeris()
```

and exactly one permitted application call to `engine.compute_application()`,
inside `CometEphemerisService._compute_internal_point()`.

No orbital propagation, light-time, topocentric correction, frame conversion,
N-body force model, element-selection policy or widget result contract was
changed.

## 2. Removed private WStack adapters

The following functions had no production callers after R101 and were removed:

```text
stack_normalize_comet_designation()
stack__load_kopr_comet()
stack__observer_location()
stack__kopr_topocentric_radec()
```

WStack now imports the shared designation and observer normalizers directly.
Its astrometry seeds, preview, COMETTRK and stacking trajectory continue to use
the unified batch service.

The public WStack export `normalize_comet_designation` remains available, but it
now refers directly to the shared implementation rather than to a WStack
wrapper.

## 3. Removed production-only shadow helper

`ephemeris_shadow_validation.py` was introduced for the R96 comparison stage.
It had no production imports after cutover and was removed from the application
root. Its small comparison utilities were moved to:

```text
tests/ephemeris_shadow_validation_support.py
```

so historical R96 QA remains reproducible without shipping the helper as
production code.

## 4. Removed dead imports

Imports made unused by the R97–R101 migration were removed:

```text
koprhand.py: comephem
npfunc.py: alb3, time
comet_ephemeris_service.py: datetime.timezone
```

## 5. Public compatibility surfaces retained intentionally

A zero internal call graph is not sufficient proof that an old public API is
safe to delete. R102 therefore retains:

```text
koprfunc.CometObsInf()
koprclass.comet.FindElements()
alb3.finddt()
ephemeris_position.topocentric_engine_radec_icrs()
ephemeris_position.internal_comet_position()
```

`CometObsInf()` is already a thin adapter over the unified typed service.
`FindElements()` and `finddt()` are not used by any KOPR production route, but
may be used by third-party scripts. Their compatibility status is now explicit
in their docstrings.

## 6. Static architecture after cleanup

The R102 schema-5 inventory reports:

```text
engine_application_compute: 1
engine_direct_compute: 0
legacy_observation_wrapper calls: 0
element_selection (FindElements calls): 0
two_body_range_solver (finddt calls): 0
unified_ephemeris_service: 13
unified_distance_solver: 8
widget_ephemeris_entry: 4
```

The release policy still fails on any new direct engine call, widget-era element
selector, two-body range solver or non-allowlisted topocentric conversion.

## 7. Files changed against R101

Changed production Python files:

```text
alb3.py
comet_ephemeris_service.py
koprclass.py
koprfunc.py
koprhand.py
npfunc.py
wstack_functions.py
```

The changes in `alb3.py`, `koprclass.py` and `koprfunc.py` are compatibility
documentation only. `comet_ephemeris_service.py`, `koprhand.py` and `npfunc.py`
only lose unused imports. Functional cleanup is confined to
`wstack_functions.py`.

Removed production Python file:

```text
ephemeris_shadow_validation.py
```

No new production Python module was added.

## 8. QA

The full test suite was executed in four non-overlapping groups:

```text
1509 passed
6 skipped
0 failed
```

The six skips require the optional complete Astropy FITS/time runtime and are
unchanged from previous builds.

The cumulative ephemeris sequence R84–R102 passed 254 focused tests, including:

- the frozen R83/R84 two-body and legacy fallback baseline;
- osculating state conversion;
- Cowell force model and DOP853 propagation;
- light-time, cache and controlled fallback;
- automatic N-body activation;
- shared repository and typed service;
- WStack, WCCD, WVisual, Planner, Analyzer and Comparison cutovers;
- the R101 global enforcement contract;
- R102 dead-code and manifest checks.

## 9. Definition of Done

R102 is accepted because:

1. only proven private duplicates were removed;
2. potentially external compatibility APIs remain available;
3. no production route bypasses the unified service;
4. no physics or numeric output contract changed;
5. CLEAN and QA production modules are identical;
6. manifests and ZIP integrity checks pass;
7. runtime caches, backups and temporary migration files are absent.
