Skip to content

feat(tools): generate the differential harness a CONVERGED pair still needs - #3425

Merged
gHashTag merged 1 commit into
masterfrom
tool/ring-differential
Sep 7, 2026
Merged

feat(tools): generate the differential harness a CONVERGED pair still needs#3425
gHashTag merged 1 commit into
masterfrom
tool/ring-differential

Conversation

@gHashTag

@gHashTag gHashTag commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Closes #3424 · Refs #3420

check_ring_spec_drift.py reports CONVERGED on identical signatures, and carries a warning it earned:

ring-090 measured CONVERGED at 16 of 16 identical signatures and still disagreed with its spec on 126 of 1190 cases.

That harness was written by hand, for one pair. This writes it.

Results

pair cases agree covered refused
ring-090 / simulator.t27 936 936 16 of 16 0
ring-099 / e2e_test.t27 25 25 4 of 4 0

The control ran on the live pair, not only a fixture

Re-introducing the exact defect #3421 repaired — deleting the saturation guard from the spec:

cases 936  agree 864  disagree 72
first disagreement: sim_time_ms

exit 1. Restoring it: 936/936, exit 0.

--self-check proves two synthetic properties besides: modules differing by construction are reported as disagreeing, and an unsynthesisable parameter is REFUSED rather than passed over.

Three design points, each because the naive version would have lied

  1. It refuses rather than skips. Any parameter or return type it cannot synthesise is named, and the run exits 2. A harness covering eight of sixteen functions and printing "agree" is worse than no harness — the eight it dropped are exactly where a difference hides.
  2. A panic is a disagreement, not a crash. Both calls run under catch_unwind with -C overflow-checks=on. Without it the process dies with no output at all, which reads as "no cases run" rather than as the sharpest difference there is; a release build would wrap silently in both and hide it.
  3. Structs are built by their producers. SimConfig comes from calling sim_config with the same grid, so the generator needs no knowledge of fields — which is how the hand-written harness did it.

Stated, not hidden

ring-099s 25 cases are thin. Its functions take &mut [u8], &mut [bool], &mut usize, and the generator passes zero-initialised buffers: values are compared after the call, but the inputs are not varied. 25 is not the evidence 936 is, and a buffer grid is the obvious next step.

It also reports that it strips inner doc comments and attributes from the ring crate — 55 lines for ring-090, 3 for ring-099 — because include! inside a mod rejects them. Editing someone elses file to run a test should be visible.

One process note

Fifth time this session I wrote exit=$? after a pipe and read greps status. It told me the tool exited 0 while printing 72 disagreements. Measured without the pipe, it exits 1.

… needs

Closes #3424
Refs #3420

check_ring_spec_drift.py reports CONVERGED when every shared function has an
identical signature, and carries a warning it earned: ring-090 measured
CONVERGED at 16 of 16 identical and still disagreed with its spec on 126 of
1190 differential cases. Only running both found it, and that harness was
written by hand for one pair.

This writes it. For a CONVERGED pair it emits a Rust program including both
modules, calls every shared function on the same synthesised inputs, and
compares.

  ring-090 / specs/fpga/simulator.t27    936 cases, all agree, 16 of 16, 0 refused
  ring-099 / specs/pipeline/e2e_test.t27  25 cases, all agree,  4 of 4,  0 refused

The control ran on the live pair, not only a fixture: re-introducing the exact
defect #3421 repaired -- deleting the saturation guard from the spec -- makes
the tool report `936 cases, agree 864, disagree 72`, name sim_time_ms, and exit
1. Restoring it returns 936/936 and exit 0.

Three design points, each because the naive version would have lied:

  * It REFUSES rather than skips. A parameter or return type it cannot
    synthesise is named and the run exits 2. A harness covering eight of
    sixteen functions and printing "agree" is worse than no harness, because
    the eight it dropped are where a difference hides.
  * A panic is a DISAGREEMENT. Both calls run under catch_unwind with
    -C overflow-checks=on. Without it the process dies with no output, which
    reads as "no cases run" rather than as the sharpest difference there is;
    a release build would wrap silently in both and hide it.
  * Structs are built by their PRODUCERS -- SimConfig comes from calling
    sim_config with the same grid -- so the generator needs no knowledge of
    fields, which is how the hand-written harness did it.

Stated rather than hidden: ring-099's 25 cases are thin. Its functions take
&mut slices and the generator passes zero-initialised buffers, so values are
compared after the call but the inputs are not varied. 25 is not the evidence
936 is.

Also reported rather than done silently: 55 inner doc-comment and attribute
lines are stripped from ring-090 (3 from ring-099) so the crate can be
`include!`d as a module.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gHashTag
gHashTag enabled auto-merge (squash) September 7, 2026 22:19
@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-09-07 22:19:52 UTC

Summary

Status Count
Total Open PRs 16
PRs with Failing Checks 14
PRs with All Checks Green 2
READY 2
FAILING 14
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=1d58d30ea13e != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

github-actions Bot commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@gHashTag
gHashTag merged commit 74fc665 into master Sep 7, 2026
26 of 28 checks passed
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.

CONVERGED is a hint, not a verdict: nothing runs a ring and its spec on the same inputs

1 participant