Skip to content

ADR-223: Implement ModifierStage[T_in, T_out] abstract base class - #216

Merged
jodavis merged 3 commits into
feature/ADR-191-oop-ml-pipelinefrom
dev/claude/ADR-223-implement-modifierstage-abstract-base
Jun 10, 2026
Merged

ADR-223: Implement ModifierStage[T_in, T_out] abstract base class#216
jodavis merged 3 commits into
feature/ADR-191-oop-ml-pipelinefrom
dev/claude/ADR-223-implement-modifierstage-abstract-base

Conversation

@jodavis-claude

@jodavis-claude jodavis-claude commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Implements ModifierStage[T_in, T_out] — the abstract base class for all per-sample file-transformation stages — with the transform() three-case algorithm (skip / regen-with-stored-seed / new sample), GC, seed persistence, and _compute_content_hash static helper.
  • Also implements randomization.py (ADR-222 prerequisite): PassFilter ABC, MinMaxFilter, NormalFilter, VariationGenerator.
  • 30 unit tests across 6 test classes; all validate-build and validate-tests checks pass.

Files created

  • ml/pipeline/core/randomization.pyPassFilter ABC, MinMaxFilter, NormalFilter, VariationGenerator (ADR-222)
  • ml/pipeline/core/modifier_stage.pyModifierStage[T_in, T_out] with transform(), _compute_content_hash(), and three abstract methods
  • ml/test/pipeline/core/test_modifier_stage.py — 30 unit tests

Key decisions

  • ADR-222 implemented in full as a prerequisite (brief gave explicit license).
  • ValueError from ManifestStore.read() propagates — hard error for unreadable/unsupported manifests (conservative default).
  • output_dir creation is caller's responsibility. GC guards with output_dir.exists() to avoid raising on first run.
  • _FakeStage in tests uses av_by_content_hash map keyed on input_sample.content_hash — makes skip/regen/split-behavior tests fully deterministic.

Test coverage

  • TestComputeContentHash (5 tests): hash stability, seed/parent/applied-values differentiation
  • TestSkipPath (4 tests): file preservation, no _generate_output call, manifest written
  • TestRegenPath (5 tests): new id via _derive_id, stored seed preserved, content_hash updated, old file GC'd
  • TestNewSamplePath (6 tests): _derive_id called, non-zero seed, no previous manifest → all new
  • TestDeterministicStage (3 tests): _is_deterministic=True → seed 0 for all new samples
  • TestGarbageCollection (6 tests): orphan removal, manifest.json preserved, current output preserved
  • TestSplitBehavior (1 test): skip and regen in same transform() call

Jira: ADR-223

@jodavis-claude jodavis-claude left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test

@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

Test Results

401 tests  ±0   401 ✅ ±0   2m 21s ⏱️ -44s
  5 suites ±0     0 💤 ±0 
  5 files   ±0     0 ❌ ±0 

Results for commit aaf03ff. ± Comparison against base commit 86c6f27.

♻️ This comment has been updated with latest results.

Comment thread .claude/settings.json Outdated
@jodavis
jodavis marked this pull request as ready for review June 10, 2026 03:53
@jodavis
jodavis force-pushed the dev/claude/ADR-223-implement-modifierstage-abstract-base branch from 575775b to 121044e Compare June 10, 2026 04:25
ElwoodMoves and others added 3 commits June 10, 2026 06:12
Adds ModifierStage[T_in, T_out] with the three-case transform() algorithm
(skip / regen-with-stored-seed / new sample), _compute_content_hash() static
helper, GC of orphaned output files, and manifest read/write integration.

Also adds randomization.py (ADR-222 prerequisite) containing PassFilter,
MinMaxFilter, NormalFilter, and VariationGenerator — required for
modifier_stage.py to compile and for the regen path to construct generators
from stored seeds.

Key decisions:
- ValueError from ManifestStore.read() propagates (hard error); no fallback
  to "no previous manifest" for unreadable/unsupported manifests.
- output_dir creation is caller's responsibility; transform() does not call
  mkdir (consistent with DVC/entry-point owning directory setup per spec).
- GC guards with output_dir.exists() so an empty first run does not raise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bound T_in TypeVar to Sample so mypy can verify content_hash access at all
four call sites in transform(); removes four type: ignore[arg-type] suppressions.
@jodavis
jodavis force-pushed the dev/claude/ADR-223-implement-modifierstage-abstract-base branch from 121044e to aaf03ff Compare June 10, 2026 13:18
@jodavis
jodavis enabled auto-merge (squash) June 10, 2026 13:21
@jodavis
jodavis merged commit 1dffa03 into feature/ADR-191-oop-ml-pipeline Jun 10, 2026
3 checks passed
@jodavis
jodavis deleted the dev/claude/ADR-223-implement-modifierstage-abstract-base branch June 10, 2026 13:24
@jodavis-claude
jodavis-claude restored the dev/claude/ADR-223-implement-modifierstage-abstract-base branch June 10, 2026 16:12
jodavis pushed a commit that referenced this pull request Jun 28, 2026
* Use dev-team plugin from feature branch

* ADR-223: Implement ModifierStage abstract base class

Adds ModifierStage[T_in, T_out] with the three-case transform() algorithm
(skip / regen-with-stored-seed / new sample), _compute_content_hash() static
helper, GC of orphaned output files, and manifest read/write integration.

Also adds randomization.py (ADR-222 prerequisite) containing PassFilter,
MinMaxFilter, NormalFilter, and VariationGenerator — required for
modifier_stage.py to compile and for the regen path to construct generators
from stored seeds.

Key decisions:
- ValueError from ManifestStore.read() propagates (hard error); no fallback
  to "no previous manifest" for unreadable/unsupported manifests.
- output_dir creation is caller's responsibility; transform() does not call
  mkdir (consistent with DVC/entry-point owning directory setup per spec).
- GC guards with output_dir.exists() so an empty first run does not raise.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* ADR-223: address review feedback

Bound T_in TypeVar to Sample so mypy can verify content_hash access at all
four call sites in transform(); removes four type: ignore[arg-type] suppressions.

---------

Co-authored-by: Joe Davis <ElwoodMoves@hotmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

3 participants