From 421de47f014e049e063830076976381f68053d50 Mon Sep 17 00:00:00 2001 From: Polichinl Date: Fri, 18 Sep 2026 23:46:00 +0200 Subject: [PATCH] =?UTF-8?q?docs(register):=20views-evaluation=202.0.0=20pu?= =?UTF-8?q?blished=20=E2=80=94=20re-qualified,=20floor=20held=20pending=20?= =?UTF-8?q?vpc#515?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cluster H re-qualification trigger fired (2.0.0 on PyPI 2026-09-18). Evidence recorded: suite green on 2.0.0 in isolation; a 2.0.0-emitted frame round-trips through MetricFrameFileSource + mean_metric_value exactly. Floor deliberately NOT raised: vpc 3.2.0 pins views-evaluation<2.0.0 and its evaluation stage still calls report.to_dataframe() — a >=2.0.0 floor here would make the shared env unsatisfiable. Sequence fixed: vpc#515 → our >=2.0.0 floor → our 0.3.4 publish. Lock unchanged (1.0.0). Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01N7YBtiS2kSVj27spMKDYfh --- reports/technical_risk_register.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reports/technical_risk_register.md b/reports/technical_risk_register.md index 92ec49b..caaae40 100644 --- a/reports/technical_risk_register.md +++ b/reports/technical_risk_register.md @@ -30,7 +30,7 @@ Root causes shared by multiple concerns. Resolving the root tends to dissolve or | **E — Legacy transform machinery** | RESOLVED (2026-06-20, #119) — `DatasetTransformationModule` removed + direct `polars` declaration dropped (polars stays transitive via pipeline-core) | C-25 ✓ (+ resolved C-10, C-04, C-02) | ✓ Resolved | | **F — Value-correctness & contract assurance** | The load → compute → render → reconcile chain is tested for shape / does-not-crash, not for value equality, contract conformance, or input completeness | C-29 ✓ (render fidelity), C-35 ✓ (MAP/HDI correctness — render path + PosteriorDistributionAnalyzer both on the views-frames tower + law tests; RESOLVED, ADR-019 / #157), C-185 (`*_map` is a tower tip, not a MAP — naming debt), C-39 ✓ (metadata accessors untested — resolved, `tests/test_metadata_accessors.py`), C-41 ✓ (canonical-token contract test), C-116 ✓ (multi-match → silent wrong value — RESOLVED: fail-loud default + visible "ambiguous" cell + collision contract test), C-111 ✓ (input completeness — RESOLVED 2026-07-31, S4 #266), C-113 (actuals provenance), C-112 (bundled-data staleness — forward, pairs with C-22), C-186 ✓ (views-frames version → forecast-output drift), C-208 ✓ (gapped-lattice cell stretch/misplacement — rendering-geometry faithfulness, RESOLVED 2026-07-16), C-192 ✓ (cross-repo eval contract untested — RESOLVED 2026-07-31, executable seam test), C-227 ✓ (CM choropleth silently drew the dead country on duplicate ISO codes — RESOLVED 2026-09-17, loud guard at the merge chokepoint; latent, never observed) (+ resolved C-01, C-11) | Open — highest latent severity; mostly "write the missing correctness/contract test" (an assurance sprint). Phase 1 (correctness/contract core) landed 2026-06-28: C-29 ✓ (render==source fidelity test), C-41 ✓ (canonical-metric contract test), C-111 values-half guarded. C-186 ✓ (tower behavioural-regime tests, Phase 2, 2026-06-28). Remaining: C-112 (guards live — watch the regen cadence), C-113 / C-185 (non-test); C-111 ✓ resolved (coverage checks, S4 #266); C-192 ✓ resolved (seam test landed, S2 #264); C-39 ✓ resolved (accessor tests landed, 2026-07). | | **G — Partner-deliverable readiness** | Reports are built for internal preview, not yet hardened as a standalone, traceable, decision-appropriate *partner artifact* | C-28 ✓ (offline / self-contained — RESOLVED, vendored Tailwind, #132), C-34 ✓ (provenance / auditability — RESOLVED, footer stamp, #131), C-187 ✓ (vendored-CSS class coverage — RESOLVED, #132), C-188 ✓ (machine-readable provenance — RESOLVED, #132), C-109 (decision-appropriate uncertainty), C-214 ✓ (plotly-injection heuristics — RESOLVED 2026-07-31, S3 #265) | Open — C-109 (decision-appropriate uncertainty, partially delivered 2026-07: the #230 P(any) exceedance map layer) is the live remainder; C-214 ✓ resolved (S3 #265); offline + provenance now shipped | -| **H — Published-state qualification gap (dev-tandem ↔ PyPI seam)** | Contracts, pins, and names are qualified against dev branches moving in tandem, never against **published** artifacts — the coordinated publish (#179) is the single event where every deferred qualification fires at once | C-213 ✓ (root — vpc pin outran PyPI; import surface canonicalized + guarded 2026-07-31 S1 #263; ordering half resolved 2026-08-03 when vpc 3.0.0 published pre-qualified), C-192 ✓ (cross-repo seam untested — resolved S2 #264), C-36 (upstream transitive pins — re-probed at vpc's 2026-08-03 publish: envelope matches ours, ingester3==2.1.1 unchanged so the levenshtein wall persists), C-185 (rename waits on a coordinated cross-repo change), C-186 ✓ residual (b) (exact-pin views-frames for release), C-211 (partial — cross-repo decision, not publish-gated) | Open (added review-rr 2026-07-31) — mitigation is the #179 release-gate runbook (largely written); C-192's executable contract test landed (S2 #264); C-36 stays upstream-blocked regardless. **SECOND CONFIRMED FIRING (2026-08-02, v0.3.3):** 0.3.2's published `requires_dist` pin `views-evaluation>=0.4.0,<1.0.0` — qualified only against the dev-tandem git source — excluded views-evaluation **1.0.0** the day it hit PyPI, breaking platform co-resolution at the coordinated publish (caught by a sibling-repo agent). Fixed same-day: pin `>=1.0.0,<2.0.0`, interim git-source retired (its documented trigger fired), suite green against the RELEASED 1.0.0. The root cause has now bitten in production twice (vpc pin C-213(a) + this); every remaining dev-tandem git source (vpc, until their 3.0.0 publishes) carries the same latent defect until re-qualified at its publish. **CYCLE CLOSED (2026-08-03, #279):** vpc 3.0.0 published to PyPI carrying the pre-qualified pins (the vpc#313 warning worked — no third firing); the last dev-tandem git source retired, `views-reporting==0.3.3` co-resolves from PyPI alone, suite green against the released 3.0.0. **No dev-tandem git sources remain anywhere in pyproject/uv.lock** — the cluster's generating condition is discharged for this release cycle; it re-arises only if a future unreleased-dependency tandem is reintroduced. **THIRD EXPOSURE — of the published-metadata facet only, caught as a prediction (2026-09-17, #289):** no dev-tandem was reintroduced and the `<2.0.0` ceiling WAS correctly qualified against the released 1.0.0; what is Cluster-H-shaped is the second half below. views-evaluation's pandas-free 2.0.0 (their #66/#72) and vpc's coming `^2.0.0` pin (vpc#515) would make our `<2.0.0` ceiling unsatisfiable in the shared env. Source widened to a SPAN pin `>=1.0.0,<3.0.0` — deliberately NOT the requested `>=2.0.0`, because 2.0.0 was unpublished at fix time (PyPI latest 1.0.0) and a floor naming an unpublished version is exactly C-213(a)'s mistake. Safety evidence: everything we import lives in `evaluation.metric_frame` (+ `metric_catalog` in one test), and no 2.0.0 story changes the MetricFrame format or the names we import (S8's gate: "MetricFrame format unchanged"; `[frames]` survives; the only merged changes to that module since 1.0.0 are to the provenance stamp's value — the `+g` suffix and S1's bounding of it — which we treat as opaque text). **Not yet pre-empted at the seam that matters:** the shared env resolves from PyPI, where 0.3.3's immutable metadata still says `<2.0.0` — vpc#515's "after views-reporting has widened" precondition is met only by a **0.3.4 publish**, which collides with the publish-last rule and is therefore a decision, not a mechanical step. Re-qualification trigger: views-evaluation 2.0.0 on PyPI → re-lock, suite, then the `>=2.0.0` floor + 0.3.4. | +| **H — Published-state qualification gap (dev-tandem ↔ PyPI seam)** | Contracts, pins, and names are qualified against dev branches moving in tandem, never against **published** artifacts — the coordinated publish (#179) is the single event where every deferred qualification fires at once | C-213 ✓ (root — vpc pin outran PyPI; import surface canonicalized + guarded 2026-07-31 S1 #263; ordering half resolved 2026-08-03 when vpc 3.0.0 published pre-qualified), C-192 ✓ (cross-repo seam untested — resolved S2 #264), C-36 (upstream transitive pins — re-probed at vpc's 2026-08-03 publish: envelope matches ours, ingester3==2.1.1 unchanged so the levenshtein wall persists), C-185 (rename waits on a coordinated cross-repo change), C-186 ✓ residual (b) (exact-pin views-frames for release), C-211 (partial — cross-repo decision, not publish-gated) | Open (added review-rr 2026-07-31) — mitigation is the #179 release-gate runbook (largely written); C-192's executable contract test landed (S2 #264); C-36 stays upstream-blocked regardless. **SECOND CONFIRMED FIRING (2026-08-02, v0.3.3):** 0.3.2's published `requires_dist` pin `views-evaluation>=0.4.0,<1.0.0` — qualified only against the dev-tandem git source — excluded views-evaluation **1.0.0** the day it hit PyPI, breaking platform co-resolution at the coordinated publish (caught by a sibling-repo agent). Fixed same-day: pin `>=1.0.0,<2.0.0`, interim git-source retired (its documented trigger fired), suite green against the RELEASED 1.0.0. The root cause has now bitten in production twice (vpc pin C-213(a) + this); every remaining dev-tandem git source (vpc, until their 3.0.0 publishes) carries the same latent defect until re-qualified at its publish. **CYCLE CLOSED (2026-08-03, #279):** vpc 3.0.0 published to PyPI carrying the pre-qualified pins (the vpc#313 warning worked — no third firing); the last dev-tandem git source retired, `views-reporting==0.3.3` co-resolves from PyPI alone, suite green against the released 3.0.0. **No dev-tandem git sources remain anywhere in pyproject/uv.lock** — the cluster's generating condition is discharged for this release cycle; it re-arises only if a future unreleased-dependency tandem is reintroduced. **THIRD EXPOSURE — of the published-metadata facet only, caught as a prediction (2026-09-17, #289):** no dev-tandem was reintroduced and the `<2.0.0` ceiling WAS correctly qualified against the released 1.0.0; what is Cluster-H-shaped is the second half below. views-evaluation's pandas-free 2.0.0 (their #66/#72) and vpc's coming `^2.0.0` pin (vpc#515) would make our `<2.0.0` ceiling unsatisfiable in the shared env. Source widened to a SPAN pin `>=1.0.0,<3.0.0` — deliberately NOT the requested `>=2.0.0`, because 2.0.0 was unpublished at fix time (PyPI latest 1.0.0) and a floor naming an unpublished version is exactly C-213(a)'s mistake. Safety evidence: everything we import lives in `evaluation.metric_frame` (+ `metric_catalog` in one test), and no 2.0.0 story changes the MetricFrame format or the names we import (S8's gate: "MetricFrame format unchanged"; `[frames]` survives; the only merged changes to that module since 1.0.0 are to the provenance stamp's value — the `+g` suffix and S1's bounding of it — which we treat as opaque text). **Not yet pre-empted at the seam that matters:** the shared env resolves from PyPI, where 0.3.3's immutable metadata still says `<2.0.0` — vpc#515's "after views-reporting has widened" precondition is met only by a **0.3.4 publish**, which collides with the publish-last rule and is therefore a decision, not a mechanical step. Re-qualification trigger: views-evaluation 2.0.0 on PyPI → re-lock, suite, then the `>=2.0.0` floor + 0.3.4. **TRIGGER FIRED 2026-09-18 — re-qualified, floor deliberately NOT raised:** 2.0.0 published (21:29). Our suite is green on it (442) in isolation and a 2.0.0-emitted frame round-trips through `MetricFrameFileSource` + `mean_metric_value` exactly. But `uv lock --upgrade-package views-evaluation` resolves only 1.1.0: **views-pipeline-core 3.2.0 pins `views-evaluation<2.0.0`**, and its evaluation stage still calls `report.to_dataframe()` (stage.py:375-377) — their ceiling is protecting a live call, not stale. A `>=2.0.0` floor here today would make views-reporting + vpc mutually unsatisfiable (the C-115-shape shared-env trap). Sequencing is therefore fixed: vpc#515 lands (removing their `to_dataframe` egress, vpc#512) → our floor `>=2.0.0` → our 0.3.4 publish. The lock stays on 1.0.0 until then; the span admits 2.0.0 the moment vpc's ceiling lifts. | | **I — Post-B2 eval-report comparison seam (the baselines-vanishing braid)** | The B2 inversion shipped with its production wiring unverified end-to-end: consumer and producer disagree on frame location, declarations/targets/pins/envs each independently blank comparison rows, and every failure mode is silenced or mislabeled — so the deliverable degraded for months with green CI | C-215 (root, Tier 1 — subject-rooted source + seam test pinning it), C-216 (target drift + stranded fixes), C-217 (pins/envs make the seam unreachable), C-218 (Tier 1 — zero-report silence), C-219 (declaration/announce layer), C-220 (post-fix detonation), C-221 (corruption path), C-222 (vintage semantics dropped), C-223 (cache short-circuit / no baseline orchestrator), C-224 (3.0.0 classification drop), C-225/C-226 (ride-alongs) | Open (registered 2026-08-17 from /code-review max on the baselines-vanishing mystery; reconstruction VERIFIED). Fix sequencing constraint: C-220/C-225(AP-sort) must land WITH the C-215/C-216 resolution fix; C-192's locked seam contract must be corrected in the same change. Cross-repo: vpc stage + views-models configs/branches own most mechanisms; this repo owns the template/source/announce layers and the seam test. | C-34 (provenance) and C-28 (offline) now anchor **Cluster G** (partner-deliverable readiness) rather than standing alone; the C-108 inversion does not fix C-28 (the exported HTML's view-time CDN dependency), which is why C-28 moved out of Cluster A.