# KOPR R179 — Comet Analyzer formula interactive qualification report

**Base build:** `KOPR_CLEAN_BUILD_20260803_R178_COMET_ANALYZER_FORMULA_LOAD_RESILIENCE_RC.zip`  
**Date:** 2026-08-03  
**Status:** `RC / PASS_HEADLESS`  
**Scope:** final formula editor/load cleanup, compatibility removal and interactive qualification gate.

## 1. Result

R179 completes the planned R177–R179 formula transaction work at the production-code level.

The Comet Analyzer now has one canonical formula parser and two explicit application paths:

```text
manual Regular/Additional editing
→ draft only
→ explicit Refresh validates and atomically commits both documents

Analyse
→ typed fit result
→ immediate atomic commit
→ implicit Refresh/render as part of Analyse
```

Invalid intermediate editor states such as `i`, `in`, `-`, `1e` or an unfinished interval do not mutate committed formulae, formula revision, the graph or stored files.

## 2. Production cleanup

### 2.1 Removed legacy parser island

Removed from `wlightcurves.py`:

```text
_analysis_parse_formula_text()
```

The compatibility method `ParseFormulas()` now calls the canonical typed formula document/state parser directly and remains side-effect free.

Production `wlightcurves.py` contains no call to:

```text
koprobs.magparams()
```

### 2.2 Legacy runtime isolation

`light_curve_runtime.prepare_multi_target_curve_request()` is now explicitly marked compatibility-only. It is not used by the typed Analyzer runtime introduced in R176.

Its default legacy row conversion no longer imports or calls `koprobs.magparams()`. The converter in `koprobs.py` remains only for other historical widgets/external callers and is documented as compatibility-only.

### 2.3 Error and transaction behavior

- Manual editor signals capture draft text only.
- Formula validation errors use formula-specific titles/messages, not `Plot rendering error`.
- Invalid Refresh preserves the last committed formulas and graph.
- Invalid Save leaves `MagParams.dat` byte-identical.
- Valid Save is atomic and does not apply the draft to the graph.
- Analyse commits its typed result immediately and starts one plot update.
- Expected/exceptional iterator exhaustion retains operation and target context; no Analyzer production path prints a bare `StopIteration()`.

## 3. R179 interactive gate

Added:

```text
r179_formula_qt_smoke.py
r179_formula_interactive_release_gate.py
tests/test_r179_formula_interactive_qualification.py
```

The real Qt smoke runner exercises:

1. character-by-character `i → in → inf` editing;
2. no formula revision/model mutation during typing;
3. explicit Refresh committing exactly once;
4. invalid Refresh preserving the prior state;
5. invalid Save preserving file bytes;
6. corrected Save and typed reload round-trip;
7. Analyse implicit Refresh and immediate redraw.

It supports:

```bash
QT_QPA_PLATFORM=offscreen python3 r179_formula_interactive_release_gate.py --require-qt
python3 r179_formula_interactive_release_gate.py --require-qt --native
```

## 4. Verification performed

### Release gates

```text
R177: 9/9 PASS
R178: 9/9 PASS
R179 headless: 13/13 PASS
R179 real Qt: SKIP — PyQt5 unavailable on build host
```

Strict `--require-qt` correctly returns failure when PyQt5 is unavailable. It does not falsely report a qualified GUI release.

### Tests

```text
R177–R179 targeted: 24 passed, 1 skipped
R149–R179 current regression: 236 passed, 3 skipped
```

The three skips are the real PyQt5 state-machine tests R154, R161 and R179.

A broader historical R141–R148 source-assertion run was also attempted. Eight tests fail because they require pre-cutover implementation details such as `obs_list`, the old formula dispatcher and a literal `self.button_click_update()` call after Analyse. Those assertions contradict the typed runtime and implicit Analyse refresh introduced in R176–R178 and are not used as R179 release evidence. Current behavioral gates pass.

### Static and distribution checks

```text
CLEAN Python syntax: 107 files, 0 errors
QA Python syntax: 425 files, 0 errors
CLEAN SHA-256 manifest: 116 entries
QA SHA-256 manifest: 482 entries
aggregate performance/release validator: PASS
ZIP integrity: PASS
```

The CLEAN archive contains no tests, release-gate scripts, pytest cache, Python bytecode or temporary invalid formula files.

## 5. Qualification status

The implementation is complete, but the build remains:

```text
RC / PASS_HEADLESS
```

A final non-RC GUI release requires the R179 strict offscreen gate and one native GUI smoke run on a system with PyQt5.

## 6. Files changed

Production:

```text
wlightcurves.py
light_curve_runtime.py
koprobs.py
```

QA only:

```text
r179_formula_qt_smoke.py
r179_formula_interactive_release_gate.py
tests/test_r179_formula_interactive_qualification.py
validate_performance_release.py
```
