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.
|
Implemented review fixes in b6442dc: semantic-wir now compares native lowered WIR directly with the pinned oracle WIR and verifies both input hashes; reference parse failures remain inconclusive. The compiler baseline now requires concrete oracle/provenance evidence, uses owners opy-rs#88/#89 and workshop-rs#10/#123, and no longer uses parent #8. The compiler report advertises its actual stages, including compiler-contract. Local validation: cargo fmt --check, clippy -D warnings, workspace tests, 26 compatibility tests, and the 51-fixture native compiler gate all pass with 0 regression and 0 inconclusive results. |
Teakowa
left a comment
There was a problem hiding this comment.
Blockers
1. The corpus input identity is still only the main-file hash, so multi-file oracle evidence can go stale without being rejected
The new semantic-WIR path correctly records and checks input hashes, but both sides still define the input as only fixture.json.source. run_native.py hashes source.read_bytes(), CompileReport::semanticWIR.inputSha256 hashes the same main source string, and load_compiler_expectations() validates the oracle by hashing only that one source path.
That is not a complete compilation input for multi-file fixtures. For example, synthetic/preprocessing/source.opy includes shared.opy, and that included file defines the Phase enum and double macro that materially determine the compiled result. oracle.json records only the main source.opy SHA. Changing shared.opy without refreshing the oracle therefore leaves every current input-hash check green even though the project being compiled is no longer the project that produced the pinned oracle.
#38 is establishing the final end-to-end evidence gate and explicitly relies on reproducible pinned evidence. The producer/oracle identity needs to cover the complete resolved source graph (or an equivalent deterministic project digest / per-file hash set), not only the entry file. The same project-wide identity should be present in the oracle and native result and compared before accepting status/output/WIR evidence.
2. Several remaining non-match entries still do not point to an issue that actually owns the declared gap
The new #88/#89 and workshop-rs#123 issues are the right direction, and most entries now have concrete oracle/provenance evidence. However the expectation-to-owner mapping is still incomplete:
real-world/overpy-pixelart,synthetic/declarations-rules, andsynthetic/expressions-valuesare assigned toopy-rs#88, but #88 explicitly enumerates its tracked fixture scope and does not include those three cases.real-world/overpy-cakeandsynthetic/chase-condition-agentlabare assigned toworkshop-rs#10with notes saying #10 owns canonical parser/domain disambiguation forVisible To/None. #10 is the Workshop conformance-corpus/seasonal-census parent; its scope does not own that parser/domain-disambiguation defect.
A non-empty owner string is not enough for #38's acceptance criterion that every remaining failure be independently evidenced and tracked as a concrete gap. Please either amend the relevant owning issues so their Goal/Scope/AC actually cover these failure modes, or point the expectations at/create the concrete existing Workshop/OPY issue that does. Do not use a broad corpus parent as the implementation owner for a parser semantic defect.
Major
1. Compatibility-only oracle machinery has leaked into the supported public compiler/CLI contract
To make the corpus executable, this patch adds CompileResult.semanticWIR, public Compiler::compile_source_report_with_semantic_reference(...), and user-visible opy-cli compile --semantic-reference. The CLI now knows how to deserialize a pinned oracle snapshot and inject it into the production compiler report. The documentation likewise presents this as part of the compile API.
This machinery exists to let compatibility/run_native.py inspect native WIR against test/oracle evidence; it is not part of ordinary OPY compilation. Making it a public versioned report field and user CLI flag turns compatibility-test plumbing into durable production API surface. That conflicts with the repository/testing boundary: tests and corpus verification should consume the production contract, not expand it with oracle-specific architecture.
Please keep the supported compile API/report focused on compilation. The compatibility harness can compare CompilationArtifact.wir with the pinned oracle through a dedicated internal compatibility binary/helper/test target (or another non-public support path) without making semantic-reference injection part of opy-cli compile or the public compile schema.
2. The new end-to-end gate is still manual-only; CI does not execute it
The current workflow runs the reusable Rust quality jobs and cross-platform opy-macro-js tests, but it never runs python3 -m unittest compatibility/tests or compatibility/run_native.py. The latest CI is therefore green without executing the machine-readable compiler corpus gate that this PR is intended to establish.
Once #38 closes, changes to lowering, compiler expectations, oracle handling, or the comparator can regress while ordinary PR CI remains green. This should be a durable compatibility/conformance gate after the cheap Rust correctness jobs: build the native CLI, run the compatibility unit tests, then run the native compiler corpus with the blocking comparator. Heavy compatibility work can depend on the existing Rust gate; it should not remain a manual verification step.
Minor
The PR verification summary is stale after the direct-WIR reclassification
The PR body still reports 51 fixtures; 17 matches, 31 tracked known gaps, and 3 explicit unsupported cases. The current compiler expectation file has 12 match, 36 known-gap, and 3 unsupported entries after the direct native-WIR comparison exposed the residual gaps. Update the PR verification text so the human status agrees with the current machine-readable baseline, as #38 requires.
The previous findings themselves are otherwise fixed: semantic-WIR is now executed against native lowered WIR, the compiler report advertises the correct stage contract, and the support matrix correctly downgraded the newly exposed lowering overclaims rather than hiding them.
Complete project input provenance, assign concrete gap owners, and keep canonical-WIR evidence in the internal compatibility target. Fixes #38
|
Review follow-up on commit |
Record the merged macro-lowering implementation as a normalized-output match. Refs #85
Keep the issue-85 compile success while recording the remaining pinned-oracle WIR divergence as an owned known gap. Refs #85
Record the public CLI and internal evidence target commands used by CI.
Keep semantic-WIR evidence rejected from the public compile result shape.
Expose the complete compatibility gate through workflow dispatch for explicit current-head verification.
# Conflicts: # crates/opy-compiler/Cargo.toml
Keep serde available after merging the macro-lowering implementation from main.
|
Final hosted verification for head |
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 errorsopy-compattarget; the public compiler API andopy-cli compileremain oracle-freeopy-rsorworkshop-rsissue, includingworkshop-rs#124for canonical enum-domain ambiguityVerification
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo test -q --locked --workspace --all-targets --all-featurespython3 -B -m unittest discover -s compatibility/tests(28 tests)33239736836: Rust stable/1.85, compiler compatibility, macOS, and Windows all passedThe compiler baseline requires independent evidence per fixture. Complete project-input, status, comparison-contract, and compatibility-evidence mismatches remain blocking; the native runner completed with no regression, divergence, or inconclusive result. The oracle snapshot verifier requires the pinned
compatibility/oracledependencies and is run in the dedicated oracle environment.Fixes #38