# KOPR R133 – WAnalyzer formula/render separation release gate

**Base build:** `KOPR_CLEAN_BUILD_20260729_R132_WANALYZER_AXIS_INDEPENDENT_GEOMETRY.zip`  
**Implementation date:** 2026-07-29  
**Scope:** final R133 batch from the R131–R133 WAnalyzer compute-once/render-many remediation. WComparison, WPlanner, WVisual, WCCD and WStack scientific behaviour are unchanged.

## 1. Completed objective

WAnalyzer now treats H0/n, the geocentric-distance term and dust phase correction as a cheap formula layer above the canonical physical geometry introduced in R132. A formula-only change is resolved locally before any asynchronous operation is created.

The retained physical rows remain:

- Date;
- days from perihelion T;
- heliocentric distance r;
- log(r);
- geocentric distance delta;
- raw phase angle.

## 2. Production changes

### Local formula resolver

Added the R133 local formula path in `analysis_jobs.py`:

- `canonical_geometry_key_for_job()` resolves the exact canonical geometry entry;
- `materialize_cached_curve_result()` applies a formula only when the required T intervals and canvas sampling bucket are already covered;
- `resolve_cached_curve_results()` partitions requests into immediately available local formula results and jobs that require genuine physical geometry work.

The resolver does not call `compute_curve_jobs()`, does not create a Qt worker and does not evaluate an ephemeris point.

### Worker submission narrowed to missing geometry

`wanalyzer.py::_analysis_start_plot()` now performs the partition before calling `_analysis_start_job()`.

- all requests locally materialized → immediate transactional commit and render;
- partial coverage → only `geometry_jobs` are submitted;
- formula validity extension → the existing R132 canonical geometry machinery computes only uncovered T intervals;
- material canvas-width increase → only required geometry refinement is submitted.

### Formula edits reuse prepared physical coverage

Prepared segments are matched by line, apparition, source, formula position, validity interval and exact element line. H0/n and dust changes create new formula bindings over the same physical segment instead of discarding coverage.

This applies to:

- regular H0/n edits;
- phase parameter changes;
- formulas produced by **Analyse**;
- multiple previously extended segments of one formula.

### Vector formula transformation

`koprobs.ApplyCurveFormula()` now evaluates arrays locally:

```text
H0 + 2.5 n log10(r)
5 log10(delta)
composite dust correction(raw phase, dust parameter)
```

`npfunc.CompositeDustFArray()` is the vector form of the unchanged scalar phase equation. The output row layout consumed by existing renderers remains unchanged.

### Compute snapshots no longer capture view state

Production `AnalyzerPlotSnapshot` instances no longer store the selected axis, visible limits, return/type/observer filters or compare state. Compatibility fields remain optional only for older QA fixtures.

A background result remains stale only when its compute job ID/revision is stale. After commit, the current formula and current view are rendered.

### Recovery and transactionality

The one-shot missing-result recovery also runs the local resolver first. Only genuinely unresolved geometry jobs enter recovery. Existing guarantees remain:

- Cancel preserves the previous graph;
- worker failure preserves the previous graph;
- stale data/element work is ignored;
- geometry is committed only after the complete operation succeeds;
- formula/view changes do not invalidate valid physical work.

## 3. Acceptance results

| Scenario | Result |
|---|---|
| H0/n edit inside prepared coverage | local formula update; no analytical worker |
| Dust phase parameter change | local phase-array update; no analytical worker |
| Phase correction on/off or correction display mode | render-only |
| Analyse formula inside prepared coverage | local additional formula; no analytical worker |
| Analyse/formula validity extension | only missing physical T interval submitted |
| Axis/filter/Compare/asymmetry change | no analytical job |
| View change during physical computation | valid geometry accepted; current view rendered |
| Data/element change during computation | stale result rejected |
| Cancel/error/incomplete result | previous graph preserved |
| WComparison | established request-scoped route unchanged |

## 4. Verification

Focused analytical regression was run in two cleanly terminating groups:

- R100/R110/R111/R112: **48 passed**;
- R113/R114/R123/R125/R131/R132/R133: **55 passed, 1 skipped**.

Combined result:

- **103 passed**;
- **1 skipped** because PyQt5 runtime is unavailable for the Qt heartbeat/background-widget test;
- no failures.

R133-specific module:

- **8 passed**.

Release validators passed in CLEAN and QA trees:

- `analysis_release_gate.py` – PASS with R133 invariants;
- `modal_ephemeris_release_gate.py` – PASS;
- `wplanner_performance_release_gate.py` – PASS;
- `documentation_hygiene.py` – PASS.

The final archives were checked with ZIP integrity testing and regenerated SHA256 manifests.

## 5. Files changed

Production:

- `analysis_jobs.py`
- `analysis_plot_state.py`
- `analysis_release_gate.py`
- `koprobs.py`
- `npfunc.py`
- `wanalyzer.py`
- `README.md`
- `docs/CHANGELOG.md`

QA/developer:

- `tests/test_r133_wanalyzer_formula_render_release_gate.py`
- `docs/developer/WANALYZER_WCOMPARISON_ANALYSIS_ARCHITECTURE.md`
- `RUN_R130_FOCUSED_QA.md`
- `README_QA.md`

## 6. Completion status

The R131–R133 remediation is complete:

```text
load/compute physical data once
→ retain Date, T, r, log(r), delta and raw phase
→ apply requested formulas locally
→ select/mask stored arrays for ordinary view changes
→ run background ephemeris work only for new data or missing physical coverage
```
