feat(compiler): expose versioned OPY compile surface - #84
Conversation
Teakowa
left a comment
There was a problem hiding this comment.
Blocker
The new native corpus runner derives expected gaps from the implementation under test, so regressions can be downgraded to non-blocking results.
compatibility/run_native.py::compare() classifies every oracle-success/native-failure pair as known-gap and every oracle-failure/native-failure pair as expected-failure. fixture.json.expectedStatus is only copied into the report, and the existing independent compatibility/differential-expectations.json contract is not consulted. The runner then blocks only unexpected-success plus (by default) inconclusive, so a fixture that was independently expected to compile can regress to a native failure and still be reported as a non-blocking known-gap.
This bypasses the existing compatibility/diff.py safeguards: that runner validates independent native status/classification/evidence, turns expectation mismatches into unexpected-divergence/regression, compares failure diagnostics, and verifies that the producer input hash matches the pinned oracle input. run_native.py also omits that input-hash equality check, so a changed fixture can be compared against stale oracle evidence without a hard contract error.
That conflicts with #38's acceptance criteria that remaining failures be independently evidenced/tracked as concrete gaps and that the end-to-end report contain no hidden success cases. The compiler result being tested must not create its own expected baseline.
Please make the native path produce result records and reuse the existing differential expectation/comparison contract (or extract one shared comparator/expectation loader). Only an explicit durable expectation with evidence should be allowed to classify a case as known-gap/unsupported; mismatches must remain blocking unexpected-divergence/regression, and oracle/native input hashes should be required to match.
|
Addressed in
Validation: compatibility tests pass (21 tests). Running the native corpus through the shared comparator produces blocking results ( |
Teakowa
left a comment
There was a problem hiding this comment.
Blocker
The previous runner-self-baselining issue is fixed, but the replacement still does not satisfy #38's end-to-end evidence contract: run_native.py now reuses differential-expectations.json/diff.py, yet those expectations describe the existing OPY source/frontend outcome contract rather than the new compiler outcome contract.
The PR's own current verification makes the mismatch observable: running the native compiler through the shared comparator reports 26 regressions, 10 unexpected divergences, 8 inconclusive cases, and only 7 declared known gaps. diff.run() correctly treats both regression and unexpected-divergence as blocking and returns non-zero, so this is not a passing end-to-end corpus baseline. --allow-inconclusive does not change that.
This matters beyond the exit code. Existing expectations intentionally encode source-level invariants such as “the native semantic model resolves this fixture” even when Workshop lowering is not part of that source contract. Reusing nativeStatus as the compiler expectation therefore turns legitimate, separately scoped lowering gaps into unexpected-divergence; conversely, changing those existing expectations to make the compiler green would weaken the already-established source regression contract. The two producer surfaces need independently evidenced expectations.
#38 requires the compatibility corpus to produce an end-to-end report with no hidden/inconclusive success cases, and requires every remaining failure outside the declared baseline to be independently evidenced and tracked as a concrete gap. A report containing 36 blocking regression/divergence results does not meet that acceptance criterion, and #8 cannot close from this evidence.
Please establish a compiler-specific durable expectation/baseline (or extend the expectation schema with a separate compiler outcome/classification) and run the native compiler against that contract. Do not overwrite the source/frontend expectations. Any compiler failure accepted as a gap must have independent evidence/provenance and a concrete owning follow-up; unexpected compiler regressions/divergences must remain blocking. The resulting #38 end-to-end run should pass for the declared baseline (with only explicitly accepted/tracked gaps, and inconclusive results handled according to the issue contract) before this PR is merged.
|
Addressed the second blocker in The background/goal distinction is now explicit:
The existing source/frontend expectation contract remains independent, so compiler lowering gaps are not downgraded into or promoted from source-level expectations. |
Teakowa
left a comment
There was a problem hiding this comment.
Blocker
1. semantic-wir is currently a declared match, not an executed comparison
compare_compiler_fixture() checks the producer compile status, but the semantic-wir branch then unconditionally appends a semantic-wir: match stage and sets the fixture status to match; it does not compare any WIR/semantic value from the producer with pinned evidence. run_native.py only records the opy-cli compile --format json report, which contains Workshop text/diagnostics but no WIR semantic payload, and the runner does not execute or consume the referenced Rust test result.
That means a fixture can keep returning compile.status = success while its lowering semantics regress and the compiler corpus still reports it as a semantic-WIR match. Nine of the 17 declared compiler matches currently use this path, so more than half of the baseline is not actually checked by the machine-readable corpus gate.
This conflicts with #38's scope to compare the native compiler against pinned OverPy evidence using observable semantic/normalized contracts and with the acceptance criterion that the end-to-end report contain no hidden/inconclusive success cases.
Please make semantic-wir an executable comparison tied to the same fixture/input hash (for example, produce/consume a canonical WIR semantic representation or fingerprint and compare it with pinned evidence). If the referenced Rust tests are intentionally the independent evidence instead, the corpus runner must not fabricate a runtime semantic-wir: match; it needs a contract that actually verifies/consumes that evidence before counting the fixture as a corpus match.
2. The remaining gaps are still not tracked as concrete independently evidenced gaps
The separate compiler expectation file is the right boundary, but its non-match entries do not yet satisfy #38's tracking requirement. All 31 known-gap cases and all 3 unsupported cases point owner at aggregate parent opy-rs#8. #8 itself says the execution order ends with #38 → close #8, and #38 explicitly requires that #8 can close after the final gate. Therefore #8 cannot simultaneously be the durable owner for 34 remaining gaps after #38 closes.
Several of the new evidence entries are also only the fixture itself (for example the real-world parse/lexical failures) or a support-matrix:* entry. Those are useful repro/status references, but they are not independent evidence or concrete gap tracking; the support matrix is the declaration being justified. load_compiler_expectations() currently validates only that evidence and owner are non-empty strings, so these circular/self references are accepted as if they satisfied the policy.
Please reassess the failures as #38 requires and route each real failure mode to a concrete owning follow-up (multiple fixtures can share one issue; do not create one issue per fixture). Reuse existing follow-ups where they genuinely own the gap and route Workshop/WIR-owned deficiencies to workshop-rs. The expectation should reference durable regression/oracle/provenance evidence plus that concrete owner, rather than using #8/support-matrix as a catch-all.
Major
The compiler report advertises the wrong stage contract
run_compiler() calls the shared build_report(), but build_report() always declares the source-differential stages compile-status, diagnostics, exact-output, normalized-output, and semantic. Compiler results actually use compile-status plus normalized-output, semantic-wir, diagnostic-code, or compiler-contract depending on the expectation. The report's summary.byStage therefore describes one set of stages while the top-level comparison.stages advertises another.
Because #38 establishes this as a machine-readable end-to-end report, the metadata must describe the actual compiler comparison contract. Please parameterize the report metadata (or provide a compiler-specific report builder) so source and compiler reports each advertise the stages they really execute.
Summary
CompileReportfromopy-compilerwith compiler/catalog identity, stable status and failure classes, exact/normalized Workshop output, and source-attributed diagnosticsopy-cli compilewith deterministic text/JSON output, locale selection, and exit codes for success, compiler failure, and I/O/usage errorsdifferential-expectations.jsoncontract unchangedVerification
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo test -q --workspace --all-targets --all-featurespython3 -B -m unittest discover -s compatibility/tests(24 tests)The compiler baseline requires independent evidence per fixture. Status, comparison-contract, and input-hash mismatches remain blocking; the native runner completed with no regression, divergence, or inconclusive result.
Refs #38