# KOPR R164 — Comet Analyzer style-artist invariance hotfix

**Base build:** `KOPR_CLEAN_BUILD_20260801_R163_COMET_ANALYZER_AUTOMATIC_RANGE_INVALIDATION.zip`  
**Date:** 2026-08-01  
**Scope:** Point-style switcher must change presentation only; observation coordinates and visibility must remain invariant.

## Reported symptom

For C/2011 W3 (Lovejoy), switching from `Comet colour / channel marker` to `Channel colour / comet marker` appeared to add some points and hide others, although the selected channels and plot range were unchanged.

## Confirmed cause

The committed observation visibility mask was already identical in both encoding modes. The visual discrepancy was caused by artist composition:

1. in reverse encoding, regular formula curves carried sparse black target markers;
2. formula curves were rendered after observation artists;
3. the formula markers therefore looked like additional observations and could cover coloured observation points at nearby or identical coordinates.

This was especially misleading for a single selected comet, because formula target markers carried no additional identity information.

## Production fix

Changed production files:

- `light_curve_rendering.py`
- `wlightcurves.py`

Implemented contracts:

- explicit formula artist z-order: `2.0`;
- explicit observation artist z-order: `4.0`;
- observation points therefore always remain above formula lines and formula markers;
- reverse-mode formula markers are disabled when only one comet is selected;
- single-target formula legend entries are line-only;
- multi-target reverse mode retains sparse formula target markers because they still disambiguate neutral model curves;
- visibility selection remains applied before any colour/marker resolution.

No observation loading, filtering, magnitude reduction, ephemeris, fit or range calculation was changed.

## Scientific and data invariance

The new regression test renders the same pre- and post-perihelion coordinate arrays in both point-style modes and compares the complete X/Y coordinate sequences. The sequences are identical. Only Matplotlib style properties differ.

## Validation

- R164 targeted tests: **6 passed**
- focused R159/R162/R163/R164 tests: **40 passed**
- cumulative R130–R164 regression: **266 passed, 2 skipped**
- R159 release gate: **PASS**
- R161 headless release gate: **PASS_HEADLESS**
- R162 release gate: **PASS**
- R163 release gate: **PASS**
- R164 release gate: **6/6 PASS**
- aggregate performance/release validator: **PASS**
- Python syntax: CLEAN and QA **PASS**
- CLEAN distribution hygiene: **PASS**
- SHA-256 manifests: **PASS**
- ZIP integrity: **PASS**

The two skips are the existing PyQt5 offscreen tests R154 and R161; PyQt5 is not installed on the build host.

## Expected result

Switching `Point style` now:

- preserves exactly the same observation rows and X/Y coordinates;
- changes only colour and marker encoding;
- does not create formula markers that resemble observations for a single comet;
- cannot hide observation points behind model curves;
- preserves the current plot range and data selection.
