Skip to content

fix(mapping): generator-aware side_effect_type mapping in infer_side_effect_type - #15

Merged
jflowers merged 1 commit into
mainfrom
opsx/generator-aware-effect-mapping
Sep 1, 2026
Merged

fix(mapping): generator-aware side_effect_type mapping in infer_side_effect_type#15
jflowers merged 1 commit into
mainfrom
opsx/generator-aware-effect-mapping

Conversation

@jflowers

@jflowers jflowers commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the generator-aware side_effect_type mapping bug in infer_side_effect_type (issue #13).

The value-type assertion fallback chain (equality, comparison, identity, membership) previously mapped to ReturnValue → first P0 effect → ReturnValue (fallback). Generator functions produce GeneratorYield (P1 tier) as their primary effect, not ReturnValue (P0 tier). Since the chain only checked P0 effects, generator functions fell through to the ReturnValue fallback — a type not present in their effect list. This caused Gaze's findSideEffectID to find no match, sending all test assertions to UnmappedAssertions with 0% contract coverage.

The fix inserts GeneratorYield and AsyncGeneratorYield checks after the P0 scan and before the ReturnValue fallback, producing the expanded chain: ReturnValue → first P0 → GeneratorYield → AsyncGeneratorYield → ReturnValue (fallback).

Closes #13

Note: This branch is rebased on opsx/test-mapping (issue #6) which introduces quality/mapping.py. The diff from main includes both the test-mapping base and this fix.

How to Test

# Run the full test suite
uv run pytest --cov=snake_eyes --cov-report=term-missing --cov-fail-under=85

# Run only the generator-aware mapping tests
uv run pytest tests/test_test_mapping_method.py -k "generator_yield" -v

Verification scenarios from the spec:

  1. Value-type assertion with only GeneratorYield effect → maps to GeneratorYield (was ReturnValue)
  2. Value-type assertion with only AsyncGeneratorYield effect → maps to AsyncGeneratorYield (was ReturnValue)
  3. ReturnValue still takes precedence when both ReturnValue and GeneratorYield are present
  4. P0 effects still take precedence over GeneratorYield
  5. Empty effects still fall back to ReturnValue
  6. Generic assertion chain is unaffected (regression guard)

How to Demo

# Show the 7 new tests passing
uv run pytest tests/test_test_mapping_method.py::TestEffectTypeInference -v

The key tests test_value_generator_yield_only and test_value_async_generator_yield_only demonstrate the fix — on unfixed code these return ReturnValue, on fixed code they return GeneratorYield/AsyncGeneratorYield.

Key Files Changed

Source (fix):

  • src/snake_eyes/quality/mapping.py — Added generator-yield check (7 lines) to the value-type fallback chain in infer_side_effect_type; updated docstring

Tests:

  • tests/test_test_mapping_method.py — Added 7 new tests: 2 regression tests (GeneratorYield, AsyncGeneratorYield), 3 precedence tests (ReturnValue beats generator, P0 beats generator, GeneratorYield beats AsyncGeneratorYield), 1 fallback guard, 1 generic chain regression guard

Spec artifacts:

  • openspec/changes/generator-aware-effect-mapping/ — proposal, design (3 decisions), spec (6 scenarios), tasks (12 items, all complete)

This PR was generated by /uf.finale (AI-assisted).

…13)

- Insert GeneratorYield/AsyncGeneratorYield checks in the value-type
  assertion chain after the P0 scan and before the ReturnValue fallback
- Generator functions's test assertions now correctly map to their yield
  effect type instead of falling through to ReturnValue (0% coverage)
- Add 7 regression and precedence tests covering all spec scenarios
- Add OpenSpec change artifacts (proposal, design, spec, tasks)

Assisted-by: claude-opus
Generated with AI assistance (claude-opus)
@jflowers
jflowers force-pushed the opsx/generator-aware-effect-mapping branch from 2d1f7f6 to 8990bf1 Compare September 1, 2026 20:42

@jflowers jflowers left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Council Verdict: APPROVE

Note: Could not post as APPROVE due to GitHub's self-review prohibition (PR author cannot approve their own PR). Posted as COMMENT instead. Original verdict: APPROVE.

Reviewers: Adversary, Architect, Guard, Tester, Operator, Curator, Envoy, Herald, Scribe
Iterations: 1

Adversary (APPROVE)

No findings.

Architect (APPROVE)

Alignment Score: 9/10. 1 LOW finding omitted.

Guard (APPROVE)

No findings.

Tester (APPROVE)

No findings.

Operator (APPROVE)

No findings.

Curator (APPROVE)

No findings.

Envoy (APPROVE)

No findings.

Herald (APPROVE)

3 LOW findings omitted.

Scribe (APPROVE)

  • [MEDIUM] Dense context paragraph in design.md (FT-004)
  • [MEDIUM] Missing H1 heading in delta spec spec.md (FT-006)
  • [MEDIUM] Minor terminology variation in test docstrings (VB-003)
  • 2 LOW findings omitted.

Linked Issues

  • #13: fix: generator-aware side_effect_type mapping in infer_side_effect_type

This review was generated by /review-council (AI-assisted).

@jflowers
jflowers merged commit c35d262 into main Sep 1, 2026
2 checks passed
@jflowers

jflowers commented Sep 2, 2026

Copy link
Copy Markdown
Contributor Author

PR Cost Report: #15

Session: Propose change with artifacts

ID: ses_fa1873b55ffezIRGr7LSY7thRU

Metric Value
Cost (parent only) $9.92
Input tokens 140
Output tokens 51,490
Cache read tokens 9,556,534
Cache write tokens 616,944

Timeline: 2026-09-01 15:36:08 — 2026-09-01 16:43:54

Child sessions: 12 — additional cost: $8.26
Session tree total: $18.19

Child session breakdown
Session Cost Output Tokens
Read mapping source files (@explore subagent) $0.03 1,467
Find test-mapping specs (@explore subagent) $0.22 10,874
Spec review: architect (@divisor-architect subagent) $1.75 8,051
Spec review: guard (@divisor-guard subagent) $0.68 4,684
Spec review: testing (@divisor-testing subagent) $0.94 5,569
Spec review: adversary (@divisor-adversary subagent) $0.80 3,838
Spec review: SRE (@divisor-sre subagent) $0.53 2,622
Spec review: curator (@divisor-curator subagent) $0.49 2,637
Architect code review (@divisor-architect subagent) $0.69 4,329
Testing code review (@divisor-testing subagent) $0.84 5,223
Guard code review (@divisor-guard subagent) $0.71 4,379
Adversary code review (@divisor-adversary subagent) $0.60 2,944

Session: Code and spec review council

ID: ses_fa14435a3ffeVZTRIGVH9mfb6r

Metric Value
Cost (parent only) $4.08
Input tokens 74
Output tokens 21,573
Cache read tokens 3,813,715
Cache write tokens 307,879

Timeline: 2026-09-01 16:49:20 — 2026-09-01 17:25:09

Child sessions: 10 — additional cost: $9.41
Session tree total: $13.49

Child session breakdown
Session Cost Output Tokens
Gaze full quality report (@gaze-reporter subagent) $1.65 12,645
Adversary review (@divisor-adversary subagent) $0.78 2,658
Architect review (@divisor-architect subagent) $0.94 4,119
Guard review (@divisor-guard subagent) $1.04 3,466
Testing review (@divisor-testing subagent) $0.93 4,335
SRE review (@divisor-sre subagent) $0.95 3,187
Curator review (@divisor-curator subagent) $0.91 3,140
Envoy review (@divisor-envoy subagent) $0.67 1,607
Herald review (@divisor-herald subagent) $0.72 2,517
Scribe review (@divisor-scribe subagent) $0.82 3,801

Grand Total: $31.67 across 2 session tree(s) (24 sessions)

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.

fix: generator-aware side_effect_type mapping in infer_side_effect_type

1 participant