Skip to content

A1 — ADR-003 E2 load-time stamp guard (D-18, closes #86) - #92

Open
Polichinel wants to merge 2 commits into
developmentfrom
fix/a1-load-time-stamp-guard
Open

Polichinel wants to merge 2 commits into
developmentfrom
fix/a1-load-time-stamp-guard

Conversation

@Polichinel

Copy link
Copy Markdown
Collaborator

A1 — ADR-003 E2 load-time stamp guard

Closes #86 · part of EPIC #85 (Workstream A) · resolves risk D-18.

Problem

Unpickling a model artifact that predates the target-transform contract — one with no _target_transform_name stamp — proceeded silently. Its prediction space is unknown and cannot be safely inverted, the exact frozen-artifact ambiguity ADR-003 E2 exists to close. There was no load-time guard.

Change

  • New StepshifterManager._guard_loaded_artifact(model, path_artifact) (stepshifter_manager.py:29-49): raises PreContractArtifactError when a loaded artifact lacks _target_transform_name.
  • Called after each pickle.load — _evaluate_model_artifact and _forecast_model_artifact — placed after the FileNotFoundError handler so the guard-raise is not swallowed.
  • New PreContractArtifactError(ReproducibilityError) in infrastructure/exceptions.py.

Presence-only, not value-policing: the guard fires on the stamp being absent, per ADR-003 E2's wording. A legitimate artifact carrying a non-identity transform (e.g. log1p) loads fine — no false positive.

Tests (authored fresh — the old falsify P4 stub was never committed)

  • test_load_guard_rejects_pre_contract_artifact_on_evaluate — stamp-less artifact → PreContractArtifactError; predict never reached.
  • test_load_guard_rejects_pre_contract_artifact_on_forecast — same on the forecast path.
  • test_load_guard_accepts_stamped_artifact — a log1p-stamped artifact loads and predicts normally.

Verification

  • pytest tests/ → 94 passed, 7 xfailed (3 new). ruff check . clean.
  • review-diff → CLEAN (0 critical / 0 warning; 2 suggestions, both declined as module-consistent).

Salvage fit

Pure salvage: fail-loud on a silently-corrupting condition; no model-behaviour change on good artifacts.

Register

D-18 resolved (its last residual was E2; the gate key + E1 test already shipped) and moved to Resolved. Counts updated (Open 31 / Resolved 2).

🤖 Generated with Claude Code

Polichinel and others added 2 commits June 21, 2026 11:59
Unpickling a model artifact that predates the target-transform contract
(no `_target_transform_name` stamp) previously proceeded silently, with an
unknown prediction scale that cannot be safely inverted — the frozen-artifact
ambiguity ADR-003 E2 was written to close.

Add `StepshifterManager._guard_loaded_artifact`, called after each
`pickle.load` in `_evaluate_model_artifact` and `_forecast_model_artifact`
(placed after the FileNotFoundError handler so the guard-raise is not
swallowed). A missing stamp raises the new `PreContractArtifactError`. The
guard is presence-only, not value-policing: a legitimate artifact carrying a
non-identity transform (e.g. `log1p`) loads fine.

Tests: guard fires on a pre-contract artifact on both load paths and predict
is never reached; a stamped artifact loads and predicts normally.

Resolves D-18 — its last residual was exactly E2 (the gate `target_transform`
key and the E1 characterization test already shipped). Register updated:
D-18 moved to Resolved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	reports/technical_risk_register.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant