Repository navigation
Release → main: v1.0.2 — restore all 29 baseline models (#85) - #96
Merged
Merged
Conversation
…CORE_GENOME views-pipeline-core retired the synthesised `targets` config key on 2026-08-02 (507ae11, refs #380/#381, shipped in 3.0.0) and migrated its own 13 read sites. views-baseline was never swept, so catalog.py kept reading config["targets"] at seven sites and every get_model() raised KeyError. All 29 baseline models in views-models have been unrunnable since that date. The suite could not catch it: tests/conftest.py manufactured the retired key, so 248 tests passed against a config shape that cannot exist in production — and which pipeline-core's combined_targets() now actively raises on. The fixture, not the dependency, defined the contract. Migrating the fixtures first turns 34 tests red with the production KeyError; the catalog fix turns them green. The target list is derived once in __init__ rather than re-read at each of the seven factory sites, so the next rename of the platform's target vocabulary is one edit. combined_targets() is deliberately not called: catalog.py sits under model/, which ADR-013 forbids from importing views-pipeline-core at module level, and passing targets down from the manager would leave one of seven config keys arriving by a different mechanism than the other six. classification_targets is not read — 0 of 29 baseline configs declare one, and the decision when one does is per-model, not catalog-wide. regression_targets and level are promoted to CORE_GENOME so their absence is a named contract violation at the boundary rather than a bare KeyError deeper in. ADR-009 recorded this exact gap as accepted debt in March 2026; it is what the outage was made of. Verified against all 29 shipped configs before promoting (29/29 declare both), so no coordinated views-models change is required — unlike the C-24 seed promotion. Two guards added after the #89 mutation audit found that deleting either new key from CORE_GENOME left the whole suite green. They assert the keys by name: a test parametrized over CORE_GENOME cannot catch a key being removed from it, because the parametrize list simply shrinks. Tightening two loose `match="steps"` assertions exposed a pre-existing defect: one config omitted prediction_format while its own comment claimed only steps was missing. The substring match had concealed that. Refs #85. Closes #84, #86, #87, #89. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
The conformance check that did not exist on 2026-08-02, and whose absence let every baseline model stay dead for five weeks. Seven configs copied from the shipped views-models baselines — zero_pgmbaseline, locf_pgmbaseline, average_pgmbaseline, light_strider, black_ranger, doctorish_dwarf (nb/none), bashful_dwarf (gamma/log1p) — merged the way get_combined_config merges them, with provenance and a refresh note in the docstring. Copied, never imported: nothing here reads across the views-models boundary. Per algorithm: audit_manifest accepts it, get_model constructs the right class, model.targets matches regression_targets, the target list is not aliased from the config, and the fixture carries no retired evaluation key — the property the old conftest fixture violated, and the reason a guard built on it proved nothing. test_every_catalogued_algorithm_has_a_conformance_fixture fails if an algorithm is added without a real config, so the guard cannot silently shrink as the catalog grows. Verified by reverting the catalog fix: 15 of 29 tests fail. No importorskip. The story proposed following the test_ensemble_consumption idiom, but this needs only the catalog and the gate, both numpy-only at import; skipping it where views_frames is absent would make it a no-op in exactly the environment (CI) where it matters most. Known limitation, stated in the docstring: a checked-in copy can drift. It catches a key rename — the failure that happened — not a value change. pipeline-core's own governance puts this check here: it registered the blindness (C-289, "cannot see a consumer") and its conformance suite explicitly exempts views-baseline. Refs #85. Closes #88. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
CI has been red since 2026-08-02. The header note in run_tests.yml blamed
views-pipeline-core not being on PyPI, and said the workflow was expected red
until it published. pipeline-core 3.0.0 published on 2026-08-03 — the day after —
and the workflow was never re-run, so the note went stale and the real cause went
unseen. Re-running it now (run 34331888893) takes 2m22s instead of the old 13s:
lint and build pass, and check fails for a different reason entirely.
Because pywin32{sys_platform == 'win32'}==227 has no wheels with a matching
Python version tag (e.g. cp311) and docker>=5.0.0,<=5.0.3 depends on
pywin32==227 ... and viewser>=6.6.4 depends on docker>=5.0.0,<6.0.0 ...
and views-pipeline-core>=3.0.0 depends on viewser>=6.6.4 ...
your project's requirements are unsatisfiable.
uv resolves a universal lockfile across every platform its markers admit,
including win32, so the win32 split fails on Linux CI for a platform CI never
runs on. Publishing pipeline-core would not have fixed this; the workflow would
have stayed red and nobody would have known, which is the same silence that hid
the retired-key outage.
[tool.uv] environments = ["sys_platform == 'linux'"] is uv's own documented remedy
— it is the hint uv emits. Verified locally: uv lock --python 3.11 resolves 118
packages in 1.32s, previously unsatisfiable. The published wheel is unaffected: it
stays py3-none-any. This bounds the dev/CI resolution, not the distribution.
No lockfile is committed. That would make CI deterministic and is arguably worth
doing, but it is a separate decision with its own maintenance cost and belongs to
#26.
Refs #85. Closes #90.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
…igration ADR-009's "what is not validated" bullet is struck through rather than deleted. What it recorded is the most useful thing in the document: in March 2026 it predicted, precisely, the failure that arrived in August — a KeyError from inside a factory method rather than from the validation check, with the audit reporting success one line earlier. Accepted debt in a boundary contract is a prediction, not an observation. Deleting it would erase the evidence that the register worked and the follow-through did not. Also in ADR-009: the MODEL_GENOMES snippet was stale twice over (it predated seed and both parametric algorithms), Boundary 2's mapping now reads regression_targets, and the gap table narrows to value-ranges. CICs: BaselineModelCatalog (parameter and error tables, all usage examples, evolution notes, known deviations), ReproducibilityGate (CORE_GENOME verbatim, and four examples that were wrong — the "passes silently" one omitted prediction_format and would have raised), BaselineForecastingModelManager (three configs and the self.config contract row). One deviation is now partly fixed and the CIC says exactly how much: post-construction config mutation still reaches the model-specific keys read lazily in get_model(), but no longer reaches targets, which are copied in __init__. Documented as partial rather than quietly upgraded. Register: C-42's tier is corrected in public. It was registered hours earlier as Tier 3 "diagnostics" with a hypothetical trigger; it was a live outage whose trigger had fired five weeks before. The entry records why it was mis-read — presence was assumed because the fixture supplied it, which is the trap C-44 describes one entry earlier. C-38's discharge condition is met (pipeline-core 3.0.0 on 2026-08-03 through 3.2.0 on 09-08). C-44 gains the confirmed instance. publishing-to-pypi.md: the dependency-not-on-PyPI warning is now historical, and the pending-publisher setup step is marked as done — views-baseline has been on PyPI since 2026-07-31. Noted, not fixed: docs/validate_docs.sh still never checks that a source path cited by a doc exists on disk. That is why the epic #47 reorg left eight ADRs pointing at deleted files. It stays C-40's job. Refs #85. Closes #91. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
…ort claim The first CI run of the #85 branch got far enough to resolve dependencies and revealed a second, unrelated blocker: views-pipeline-core -> viewser 6.6.4 pins pandas<2.0.0, and pandas 1.5.3 (the last 1.x) publishes wheels for cp38-cp311 only. On 3.12/3.13 the resolver must build pandas from source and fails with ModuleNotFoundError: No module named 'pkg_resources'. views-baseline therefore cannot be installed on Python 3.12 or 3.13 at all. This is not a regression from this epic — it has been true since the >=3.0.0 pipeline-core floor was adopted, and only became visible now that CI resolves far enough to hit it. pyproject.toml still declares requires-python = ">=3.11,<3.14" and 3.12/3.13 classifiers. That claim is false, and it is registered as C-47 rather than quietly narrowed: what a distribution claims to support is a release decision with downstream visibility, the constraint lives two hops upstream, and narrowing then re-widening requires-python across releases is worse than stating the gap once. The matrix is narrowed instead, so CI is honestly green rather than permanently two-thirds red — a permanently-red pipeline being the exact condition that let the retired-key outage survive five weeks unnoticed. Restore the full matrix when viewser drops the pandas<2 pin. Refs #85, #90. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
…value holes Review of #94 found that the rename silently disabled the guard that exists to catch exactly this class of bug, plus two validation holes the PR's own ADR-009 edit declares closed. 1. The C-10 forwarding guard stopped checking `targets` (finding 1). It skips any constructor param whose name is not a config key, and the config key had just been renamed, so `targets` fell out of the loop while the test stayed green — a test whose own failure message names "a silently dropped parameter (C-10 class)". Fixed with an explicit param->config-key map. Verified by mutation: dropping targets from a builder now fails the guard. 2. `regression_targets: []` passed the whole gate (finding 2). Presence yes, non-None yes — so every model was built with no targets and the run reported success having written no PredictionFrames. It is reachable in production precisely because check 4 is not: pipeline-core's `get_combined_config` rewrites `regression_targets: None` to `[]` before the manager sees it. The gate now rejects empty values for every required key; scalars have no length and are skipped. 3. `regression_targets: "lr_ged_sb"` was laundered into nine one-character targets (finding 11). The catalog now rejects a bare string. 4. Deriving targets in `__init__` broke `list_models()` (finding 3/A3), which ADR-004 declares Stable and the CIC declares side-effect-free — enumerating the catalog must not require a config carrying targets. It is a property now. 5. `match=re.escape(missing_key)` re-introduced the substring looseness this same commit removed 100 lines below: "steps" matches a message naming only "time_steps" (finding 5). Tightened to the exact list. 6. The conformance fixtures were not configs pipeline-core would accept (finding 7), falsifying the module docstring: `CoreConfigSniffer` rejected all seven for missing name/creator/rolling_origin_stride/deployment_status/metrics and skip_predictions_delivery. They are complete now, and a new test hands each to the sniffer so the claim is enforced rather than asserted in prose. 7. The retired-key guard never covered `MANAGER_BASE_CONFIG` (finding 9) — the fixture that actually caused #84. It does now. 8. `_KEYS_DEREFERENCED_ON_EVERY_RUN` claimed a uniform justification that is not uniform (finding 3, addendum A1): `prediction_format` is never dereferenced in this package and pipeline-core reads it as `.get(..., "dataframe")`, so its absence is a silent fallback, not a KeyError. Corrected, and `run_type`'s deliberate exclusion is now recorded there rather than left implicit (C-48). 295 passed (was 283), ruff clean. Refs #85, #94. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
… short The sweep in e406920 missed four contributor-facing files and left two register rows contradicting entry bodies edited in the same commit — the same incomplete- sweep failure mode this epic is about. - README.md:154 still told readers the input "must contain target columns specified in config['targets']" — on the file pyproject ships as the PyPI front page, advising a key that now makes combined_targets() raise. - publish_package.yml carried the third copy of the "views-pipeline-core is not yet on PyPI" claim; the same PR rewrote the other two to say the opposite and to instruct the releaser to exercise the install-back. - hardened_protocol_template.md told contributors `targets` is "a known gap documented in ADR-009", citing an ADR this PR rewrote to say it is closed. - The manager CIC's usage examples were executably false: they omitted the core keys, so they raise MissingHyperparameterError, not the documented ValueError. - ADR-012 still said "beyond `targets`". - The ReproducibilityGate CIC ships the downstream static check as `CORE_PARAMS - set(hp.keys())`. With `level` and `prediction_format` in the genome and living in config_meta.py, that now reports all 29 healthy models as broken. Corrected to validate the merged config. - Register K5/K7 cluster rows still said the gate omits level/targets and that C-38 is live and gating the suite — both contradicted by their own entry bodies. The workflow header's "REAL merge gate" claim is also removed: the jobs run and pass, but neither branch declares required status checks, so red still does not block a merge. Registered as C-49 rather than silently overstated. C-41's trigger is corrected: it claimed a clean install raises ModuleNotFoundError because pipeline-core declares no scipy. Directly true and misleading — views-baseline -> views-pipeline-core -> views-evaluation requires scipy>=1.11,<2, so scipy is installed on any real install (verified at 1.15.1). The residual defect is smaller and different: we import scipy directly while declaring nothing. New: C-48 (run_type read past the gate), C-49 (CI not a required check), C-50 (catalog reimplements the platform's target vocabulary — a recorded consequence of the ADR-013 decision, including that the new conformance guard cannot detect the failure it was built for), C-51 (unpinned ruff), C-52 (fixture keyed by algorithm). Refs #85, #94. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
…-key Fix the retired `targets` config key — restore all 29 baseline models (S1–S6 of #85)
Fixes the retired `targets` config key (#84, #85). Every baseline model in views-models has been unrunnable since 2026-08-02; this is the release that carries the fix to them. 1.0.2 is also the first views-baseline release that can actually be installed. 1.0.0 and 1.0.1 were published while views-pipeline-core >=3.0.0 had no PyPI release, so they resolved for nobody (C-38). pipeline-core reached PyPI on 2026-08-03, so the clean-room install-back in docs/guides/publishing-to-pypi.md §A is worth running for the first time as part of this release. Refs #85. Closes #92. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS
release: v1.0.2
16 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release PR for v1.0.2. 9 commits,
development→main.Why this release exists
Every baseline model in views-models has been unrunnable since 2026-08-02. views-pipeline-core retired the synthesised
targetsconfig key (#380);catalog.pykept reading it; everyget_model()raisedKeyError: 'targets'. All 29 models. views-models installs views-baseline from PyPI, so nothing reaches the team until this publishes.What is in it
Stories S1–S6 of epic #85 (PR #94), plus the version bump:
catalog.pyreadsregression_targets, derived once behind a propertyregression_targetsandlevelpromoted toCORE_GENOME; empty values now rejectedCoreConfigSniffer[tool.uv] environments) — first green Lint and Test since 2026-08-02248 → 295 tests passing. ruff clean.
validate_docs.shgreen. A/code-review maxpass ran before merge; 11 findings fixed, 5 registered (C-48…C-52).Also the first installable release
1.0.0 and 1.0.1 were published while
views-pipeline-core>=3.0.0had no PyPI release, so they resolved for nobody (C-38). pipeline-core reached PyPI 2026-08-03. The clean-room install-back indocs/guides/publishing-to-pypi.md§A has therefore never been exercised — it will be, as part of this release.Known and deliberate
viewser → pandas<2, no wheels above cp311). Pre-existing, not a regression; CI matrix narrowed to 3.11 and registered as C-47.requires-pythonmetadata deliberately left alone.After merge
gh release create v1.0.2 --target maintriggers the publish workflow (Trusted Publishing, OIDC).🤖 Generated with Claude Code
https://claude.ai/code/session_01PoczAeeAcC81UVMGMSiAvS