Skip to content

S1: Read regression_targets in the catalog; migrate the 46 fixture sites #86

Closed

Description

@Polichinel

Epic: #85 · Order: Story 1 of 8 · Gate: blocks S2, S3, S6 · Closes: #84

Background

views_baseline/model/catalog.py reads self.config["targets"] at 7 sites — lines 57, 62, 67,
75, 85, 98, 112, one per _get_* builder. views-pipeline-core retired that key on 2026-08-02
(507ae11, refs #380/#381, shipped in 3.0.0); the replacement vocabulary is regression_targets
(+ classification_targets, which no baseline uses). Every baseline model has raised
KeyError: 'targets' since. See #85 for the full incident.

The reason the suite did not catch it is tests/conftest.py:12-13, which supplies both keys:

"targets": ["synth_target"],
"regression_targets": ["synth_target"],

That fixture is not merely stale — it is illegal upstream. pipeline-core's combined_targets()
raises ValueError on any config carrying targets, and the manager's config reaches the forecast
stage (manager.config is a property aliasing self.configs, passed as context.configs and read
by combined_targets(context.configs) at forecasting/stage.py:153,173). A fixture that pipeline-core
would reject is not a realistic merged config, and leaving it in reproduces the exact blind spot
that caused this outage.

Work

  1. views_baseline/model/catalog.py — derive the target list once in __init__:

    def __init__(self, config: dict, partition_dict: dict, loa: str):
        """Catalog of available baseline models.
    
        Reads the views-pipeline-core config vocabulary: `regression_targets`.
        (`targets` was retired in pipeline-core #380 and is now rejected by
        `combined_targets()`.) Classification targets are not read — no baseline
        is wired for them; see ADR-012 when that changes.
        """
        self.config = config
        self.partition_dict = partition_dict
        self.loa = loa
        self.targets = list(config["regression_targets"])
        ...

    Then replace all seven targets=self.config["targets"] with targets=self.targets.

    Do not import combined_targets — model/ may not import views-pipeline-core at module
    level (ADR-013). See [EPIC] Restore baseline runnability — migrate off the retired targets config key #85 for why the manager-passes-it-down variant was also rejected.

  2. tests/conftest.py — delete line 12 ("targets": ["synth_target"],). Line 13
    ("regression_targets") already exists and stays. MANAGER_BASE_CONFIG is then the only
    already-compliant fixture in the suite.

  3. Migrate the 46 config-key sites. Rename the dict key "targets" → "regression_targets" in:

    • tests/test_catalog.py — 17 configs (lines 14, 31, 45, 59, 74, 91, 101, 111, 123, 144, 162,
      179, 191, 203, 215, 241, 276)
    • tests/test_baseline_manager.py — 11 configs (29, 55, 87, 120, 272, 285, 310, 336, 374, 403, 432)
    • tests/test_reproducibility_gate.py — 12 inert configs (37, 48, 64, 79, 97, 115, 126, 139, 205,
      219, 231, 244) plus the manager config at 172
    • tests/test_baseline.py — 5 configs (572, 581, 591, 600, 609)
    • tests/test_falsification_seed_wiring.py — 2 configs (38, 76)
  4. Do NOT touch the ~115 non-config uses. These are a different thing that happens to share the
    word:

    • the targets pytest fixture — tests/conftest.py:73-75
    • model constructor kwargs — ZeroModel(targets=...) etc., ~50 sites in test_baseline.py
      plus test_golden.py, test_parametric.py, test_pooling.py, test_dual_input.py,
      test_grid.py, test_helpers.py, test_closeness.py, test_ensemble_consumption.py
    • to_feature_frame(..., targets=...) — throughout test_input.py, test_pooling.py
    • tests/test_protocol.py:13 — _BASE is a **kwargs bag for direct model construction
      (it contains partition_dict and loa, which no real config does). Leave it alone.
    • parameter names — _frame_config(targets=…) at test_baseline_manager.py:115,
      make_dummy_ff(targets=…) at conftest.py:59, _pandas_pool_reference(…, targets, …)
  5. Five assertions read both sides — tests/test_catalog.py:39, 53, 67, 82, 133 assert
    model.targets == config["targets"]. The model attribute keeps its name; only the config
    subscript changes.

Order within the PR (this is the point of the story)

Do step 2 and 3 first and run the suite. It must go red. That red is the evidence the tests
now describe the config shape production actually has. Only then apply step 1 and watch it go green.
A PR that was never red at this commit has not proved anything.

Acceptance criteria

  • grep -rn 'config\["targets"\]' views_baseline/ returns nothing
  • grep -rn '"targets"' tests/ returns nothing (all remaining uses are targets= kwargs or the fixture)
  • grep -n 'targets' tests/test_protocol.py still shows _BASE unchanged
  • conda run -n views_pipeline python -m pytest -q → 248 passed, 1 xfailed
  • ruff check . clean
  • The PR description records that the suite was red between the fixture commit and the catalog commit

Validation

conda run -n views_pipeline python -m pytest -q
ruff check .
# the fix, proven directly:
conda run -n views_pipeline python -c "
from views_baseline.model.catalog import BaselineModelCatalog
c = BaselineModelCatalog(config={'regression_targets':['lr_os_best'],'window_months':18,'lambda_mix':0.05,'n_samples':256,'seed':42}, partition_dict={'test':(493,540)}, loa='pgm')
m = c.get_model('MixtureBaseline'); print('OK', m.targets)
"

Relevant files

views_baseline/model/catalog.py, tests/conftest.py, tests/test_catalog.py,
tests/test_baseline_manager.py, tests/test_reproducibility_gate.py, tests/test_baseline.py,
tests/test_falsification_seed_wiring.py

Labels: story, implementation, bug

Activity

  1. added
    bugSomething isn't working
    storyA single story within an epic
    on Sep 9, 2026
  2. Polichinel commented on Sep 9, 2026

    @Polichinel
    ContributorAuthor

    Implemented in the working tree (not yet committed).

    The red step, which is the point of the story. After migrating the fixtures and deleting the
    retired key from conftest.py, but before touching catalog.py:

    34 failed, 214 passed, 1 xfailed in 2.05s
    FAILED tests/test_catalog.py::test_catalog_returns_parametric_hurdle - KeyError: 'targets'
    FAILED tests/test_falsification_seed_wiring.py::test_catalog_forwards_seed[MixtureBaseline]
    ...
    

    Those 34 failures are the production failure, reproduced in the suite for the first time. The
    fixture was the blindfold.

    After the catalog fix: 248 passed, 1 xfailed in 1.56s, ruff check . clean.

    Direct proof of the path that was dead:

    $ python -c "... BaselineModelCatalog(config={'regression_targets': ['lr_os_best'], ...}).get_model('MixtureBaseline')"
    OK -> MixtureBaseline ['lr_os_best']
    

    What changed

    • views_baseline/model/catalog.py — self.targets = list(config["regression_targets"]) derived
      once in __init__; all seven _get_* factories now forward targets=self.targets. Docstring
      records the vocabulary, the #380 retirement, and why classification_targets is not read.
    • tests/conftest.py — deleted "targets": ["synth_target"]. MANAGER_BASE_CONFIG is now a config
      pipeline-core would actually accept (combined_targets() raises on the old shape).
    • 48 config-key renames across test_catalog.py (17 keys + 5 config["targets"] assertions),
      test_baseline_manager.py (11), test_reproducibility_gate.py (13), test_baseline.py (5),
      test_falsification_seed_wiring.py (2).
    • tests/test_catalog.py:179 re-wrapped — the longer key pushed the line past the 99-char limit.

    Correction to one acceptance criterion

    I wrote "grep -rn '"targets"' tests/ returns nothing". That is not achievable and should not be:
    tests/test_protocol.py:13 keeps _BASE = {"targets": ["y"], "partition_dict": ..., "loa": ...},
    which is a constructor **kwargs bag, not a config — it carries partition_dict and loa,
    which no real config does. The correct criterion is "no config-key "targets" remains", and that
    holds: the only surviving occurrence in tests/ is that one line, deliberately.

    The other criteria are met as written.

  3. Polichinel commented on Sep 9, 2026

    @Polichinel
    ContributorAuthor

    Closed by #94, merged to development (2b3d3b4). CI green: check (3.11), lint, build, check-branch all pass — the first green Lint and Test since 2026-08-02. Suite 248 → 295 passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingimplementationCode implementation workstoryA single story within an epic

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions