Skip to content

Python operator-realization parity - #691

Merged
briansrls merged 11 commits into
mainfrom
session/neat-ibex-815
Apr 24, 2026
Merged

briansrls merged 11 commits into
mainfrom
session/neat-ibex-815

Conversation

@briansrls

@briansrls briansrls commented Apr 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Narrow Python parity follow-up for emitted program fixtures. This keeps Go out of scope: Go already had the relevant operator realizations, and the broader Python/Go Behavior::Loop capability landed separately in #692.

This PR adds Python OperatorRealization rows for integer operators whose Python infix carrier preserves the Rust/Go-visible semantics needed by the reopened fixtures: multiplication, inequality, and integer comparisons. OrderedRing.div is intentionally not added here because Python // floors negative operands while Rust/Go integer division truncates toward zero; a faithful Python division realization needs a helper path rather than a bare infix carrier.

The generated bootstrap snapshots are refreshed from src/v3/spec/python.dag.

Fixture Rows Reopened

The Python determinism matrix now admits these previously excluded fixtures:

  • list_map_then_fold_twelve
  • list_filter_then_fold_seven
  • nested_list_builtins_inside_lambda_six

The boundary receipt emitted_python_admitted_list_fixtures_execute_under_cpython executes those emitted Python programs under python3 and checks stdout against the Rust-canonical expected values (12, 7, and 6).

Verification

  • cargo test -p v3-compiler --test integration emitted_python_admitted_list_fixtures_execute_under_cpython -- --nocapture
  • cargo test -p v3-compiler --test determinism_test -- --nocapture
  • cargo test -p v3-compiler --test integration bootstrap -- --nocapture

Copy link
Copy Markdown
Contributor Author

Review finding:

This diff looks Python-only, not Python/Go reconcile. The changed files are:

  • src/v3/spec/python.dag
  • regenerated bootstrap outputs
  • PYTHON_EMIT_EXCLUDE shrink in determinism_fixtures.rs

I don’t see any Go-side change here, so the PR title / lane framing is broader than the actual patch.

More importantly, shrinking PYTHON_EMIT_EXCLUDE from four fixtures down to one is only trustworthy if we add a receipt that the three newly admitted fixtures now work under Python for real, not just that the emitter no longer errors structurally. Right now the diff removes these exclusions:

  • list_map_then_fold_twelve
  • list_filter_then_fold_seven
  • nested_list_builtins_inside_lambda_six

but I don’t see a new boundary/integration receipt proving those programs execute under python3 and match the Rust baseline / expected stdout.

So I’d want one of two follow-ups before treating this as lane progress:

  1. narrow the framing to "Python operator-realization parity" and add a targeted Python execution receipt for the newly unexcluded fixtures, or
  2. if this is meant to stay under Python/Go reconcile, add the explicit evidence that these fixtures now pass under CPython and explain why there is no corresponding Go-side change in this PR.

As written, the risk is that we re-open the Python determinism matrix without a precise proof that the admitted rows are semantically green.

Copy link
Copy Markdown
Contributor Author

Direction for next revision:

This should now be treated as a narrower Python parity PR, not broad Python/Go reconcile. #692 already landed the Python/Go Behavior::Loop capability, so the remaining value here appears to be the Python operator-realization additions plus the newly admitted Python fixtures.

Recommended shape for the next revision:

  • retitle/reframe the PR around Python operator-realization parity
  • call out exactly which previously excluded Python fixtures this is intended to unblock
  • add a targeted execution receipt that those newly admitted fixtures now run under python3 and match the Rust baseline / expected stdout
  • keep Go out of the framing unless this PR actually contains a Go-side delta

Concretely, the three fixtures reopened by the current exclusion shrink are:

  • list_map_then_fold_twelve
  • list_filter_then_fold_seven
  • nested_list_builtins_inside_lambda_six

Please make the proof for those rows explicit. Right now the diff looks directionally right, but the receipt is still too indirect for a parity claim.

@briansrls briansrls 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.

Review metadata

  • Provider / model: codex / unknown
  • Commit: 8ea65c8f · Trigger: schedule
  • Thinking: 334s wall

BLOCKING (1)

Root Cause

  • src/v3/spec/python.dag OrderedRing.div was admitted as a bare infix Python carrier without a semantic-equivalence receipt → fail closed for Python Int division until a faithful realization exists, or route it through a declared helper tested on negative operands.

Non-blocking — Strengths

  • src/v3/compiler/tests/boundary/m1_4_emit_python_test.rs The new CPython fixture test is a useful receipt for shrinking PYTHON_EMIT_EXCLUDE because it exercises the newly admitted list programs end to end.

⚠️ One blocking Python Int division semantic drift should be fixed before landing.

Comment thread src/v3/spec/python.dag
}

data python_int_eq: OperatorRealization = {
language: python_language

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.

BLOCKING: carrier "//" realizes OrderedRing.div with Python floor division, which diverges from the Rust/Go Int division realizations for negative operands and violates DB-8 cross-target deterministic emission.

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.

Verified against current head 8b4c4719d: the unsafe Python division realization has been removed. src/v3/spec/python.dag no longer contains python_int_div, OrderedRing.div, or carrier "//", and the regenerated bootstrap snapshots were updated in the same commit. This PR now intentionally omits Python OrderedRing.div until a faithful helper-based realization exists.

@briansrls briansrls changed the title T emit python/go Python operator-realization parity Apr 24, 2026
@briansrls

Copy link
Copy Markdown
Contributor Author

Addressing the blocking review from commit 8ea65c8f: verified against current head 8b4c4719d that the Python OrderedRing.div realization has been removed.

Current code has no python_int_div, no OrderedRing.div row in src/v3/spec/python.dag, and no carrier: "//" in the regenerated bootstrap snapshots. The PR now intentionally omits Python Int division until there is a faithful helper-based realization tested on negative operands.

Validation after the fix:

  • cargo test -p v3-compiler --test integration emitted_python_admitted_list_fixtures_execute_under_cpython -- --nocapture
  • cargo test -p v3-compiler --test determinism_test -- --nocapture
  • cargo test -p v3-compiler --test integration bootstrap -- --nocapture

@briansrls
briansrls marked this pull request as ready for review April 24, 2026 03:30
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: ee2bb595 · Trigger: schedule
  • Thinking: 64s wall

Diff is narrowly scoped: adds Python OperatorRealization rows for int_mul, int comparisons (lt/le/gt/ge), ne variants (Int, NodeId, PortId, DeclarationId), regenerates bootstrap tables, removes three fixtures from PYTHON_EMIT_EXCLUDE, and adds a CPython execution test for those three fixtures. The fix(emit) commit deliberately omits int / since Python's / returns float — fail-closed with MissingOperatorRealization is the right call over emitting a wrong carrier.

Findings: none against the pinned docs.

  • The added OperatorRealization rows live in src/v3/spec/python.dag — substrate facts carried on the Dag, one row per (language, target, op). Single-authority shape is preserved; no parallel representation added.
  • Omitting integer division is a concrete fail-closed win (INVARIANTS): rather than register a / carrier that silently changes semantics, the emitter keeps surfacing MissingOperatorRealization. Good modeling.
  • New test emitted_python_admitted_list_fixtures_execute_under_cpython shells out to python3, same pattern as the existing emit_python_* boundary tests already in the file — consistent with how this module already validates emission, not a new hermeticity regression introduced by this diff.
  • PYTHON_EMIT_EXCLUDE comment still mentions Behavior::Loop, which is correct — recursive_function_call_six remains excluded; the three list/fold fixtures don't need loops.

Exploratory observation (non-ask): the per-ID-type ne rows (python_node_id_ne, python_port_id_ne, python_declaration_id_ne) look like the same coprod-dissolution smell that presumably already exists for the eq siblings above them — each ID type gets its own realization row even though the Python carrier is uniformly "!=". Not something this PR should fix (it's just matching the existing shape), but if OperatorRealization ever gains a notion of "applies to any target with carrier X," this cluster would collapse hard.

Verdict: APPROVE — narrow, well-justified parity patch; the int-division omission shows good fail-closed instinct, and the CPython execution test gives the new realizations real teeth.

# Conflicts:
#	src/v3/compiler/src/bootstrap_generated.rs
#	src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs
#	src/v3/compiler/tests/integration/common/determinism_fixtures.rs
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: ee2bb595 · Trigger: schedule
  • Thinking: 306s wall

APPROVE — Diff is narrow and clean. The new Python operator rows stay on the existing shared OperatorRealization path instead of introducing a parallel emitter authority, and the PR re-enables the matching Python matrix coverage in a way that aligns with TESTING.md. I did not find a concrete violation of INVARIANTS.md, docs/modeling-discipline.md, CODING.md, or TESTING.md; targeted checks also passed for m1_4_emit_python_test::emitted_python_admitted_list_fixtures_execute_under_cpython and emit_matrix_program_python_is_deterministic.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 9bcd7fc9 · Trigger: schedule
  • Thinking: 52s wall

Review

The actual diff between origin/main and HEAD is small: a single boundary-test file adds two helpers (python_stdout, program_fixture_source) and one new #[test] that executes three admitted PROGRAM_FIXTURES under CPython and asserts stdout.

  • Follows the existing pattern in m1_4_emit_python_test.rs (python3 subprocess, next_roundtrip_dir() temp scheme).
  • Boundary tests that shell out to python3 are explicitly sanctioned by TESTING.md:195 ("Boundary tests that must invoke external processes (rustc, go, python)"), so no hermeticity concern.
  • Fixtures list_map_then_fold_twelve, list_filter_then_fold_seven, nested_list_builtins_inside_lambda_six exist in tests/integration/common/determinism_fixtures.rs — lookup by name is well-defined.
  • No substrate types touched; no Dag-carried state introduced. Nothing in this diff touches modeling discipline.

Exploratory observation (non-blocking)

python_stdout (diff lines 52–71) duplicates most of the inline python3-run block inside the larger helper near m1_4_emit_python_test.rs:444–460. A tiny run_python_script(&src_path) -> (status, stdout, stderr) extraction could dissolve both, but it's a refactor nit, not a finding.

Verdict

APPROVE — diff is a 49-line test addition that exercises emitted Python against the canonical Rust-expected stdout for three existing fixtures. Clean, narrowly scoped, no invariant or coding/testing-discipline violations.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: 9bcd7fc9 · Trigger: schedule
  • Thinking: 256s wall

Findings

  • NON-BLOCKING src/v3/compiler/tests/boundary/m1_4_emit_python_test.rs:186 violates TESTING.md §4 "One claim per test": emitted_python_admitted_list_fixtures_execute_under_cpython loops over three distinct fixtures and expected outputs in one #[test]. That bundles three independent boundary claims under a single name, so a failure won’t identify which fixture regressed without reading the body. This should be split into one test per fixture, matching the existing Rust roundtrip pattern.

Verdict
APPROVE_WITH_COMMENTS. The diff is narrowly scoped and the new CPython roundtrip coverage passed when I ran the targeted test locally, but the new grouped test shape should be cleaned up to match the repo’s stated testing discipline.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 4c2ebe52 · Trigger: schedule
  • Thinking: 34s wall

Diff is a 55-line, test-only addition to m1_4_emit_python_test.rs. It adds three tests that:

  1. Pull sources from the existing PROGRAM_FIXTURES single source of truth (shared read, not a parallel representation).
  2. Compile → emit_python_text → run under python3 → assert stdout matches the fixture-suffix integer.

All helpers (python3 invocation, next_roundtrip_dir, emit_python_text) are consistent with patterns already in the file.

Verdict: APPROVE — narrowly scoped test additions that reuse the canonical fixture registry and execute emitted Python under CPython, matching existing patterns in the file. No invariants touched, no substrate changes, nothing to flag.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: 4c2ebe52 · Trigger: schedule
  • Thinking: 259s wall

APPROVE

Diff is narrowly scoped to boundary tests, and the new checks reuse the existing PROGRAM_FIXTURES source rather than introducing a parallel fixture list. I did not find any concrete INVARIANTS.md, docs/modeling-discipline.md, CODING.md, or TESTING.md violations in the changed lines.

@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: claude / claude-opus-4-7
  • Commit: 24b31347 · Trigger: schedule
  • Thinking: 20s wall

Verdict: APPROVE — diff is small and test-only (55-line addition to m1_4_emit_python_test.rs). It adds three hermetic CPython execution tests against existing shared PROGRAM_FIXTURES, checking emitted Python stdout equals Rust-canonical values. Fixtures exist, helper mirrors the pattern already in the file, and nothing touches substrate or invariants. No findings.

@briansrls
briansrls merged commit 976460a into main Apr 24, 2026
4 checks passed
@briansrls

Copy link
Copy Markdown
Contributor Author

Review metadata

  • Provider / model: codex / gpt-5.4
  • Commit: 24b31347 · Trigger: schedule
  • Thinking: 120s wall

Findings

  • NON-BLOCKING — src/v3/compiler/tests/boundary/m1_4_emit_python_test.rs:185: assert_python_program_fixture_stdout takes expected as a separate argument even though PROGRAM_FIXTURES is already the imported fixture authority, and the new call sites at src/v3/compiler/tests/boundary/m1_4_emit_python_test.rs:195, :200, and :205 hardcode "12", "7", and "6". That violates docs/modeling-discipline.md Practice 5 / INVARIANTS.md P2 Boundary Discipline (“single-authority metadata”) by duplicating the canonical stdout that already lives in the shared fixture table.

Verdict
APPROVE_WITH_COMMENTS. The diff is small and the added CPython receipts are sensible, but I’d have these tests read expected_stdout from PROGRAM_FIXTURES before this pattern spreads further.

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