Skip to content

release-watch: synth 0.64.0 fixes a silent WRONG-ANSWER bug on every --relocatable compile — pin bumped, proven behaviour-neutral (AFD-114) - #257

Merged
avrabe merged 1 commit into
mainfrom
feat/synth-064-pin
Sep 7, 2026
Merged

release-watch: synth 0.64.0 fixes a silent WRONG-ANSWER bug on every --relocatable compile — pin bumped, proven behaviour-neutral (AFD-114)#257
avrabe merged 1 commit into
mainfrom
feat/synth-064-pin

Conversation

@avrabe

@avrabe avrabe commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

release-watch: synth 0.64.0 fixes a SILENT WRONG-ANSWER bug on every --relocatable compile — pin bumped 0.60.0 -> 0.64.0, proven behaviour-neutral (AFD-114)

synth#1189 / RQ-64-JOINALIAS. On the ARM direct selector — which synth's own PR
calls "every --relocatable compile per #197", i.e. every lowering jess does — an
if/else join register could ALIAS a live register-homed local. local.get of a
register-homed local pushes the home register uncopied; when that is the then-arm
result of a value-carrying if/else, the join mov R_then, R_else on the else path
WRITES THE LOCAL. Exit 0, no decline, wrong answer.

Reproduced on jess's exact invocation (-t cortex-m3 --cortex-m --relocatable):

0.60.0 (jess's pin) 0.64.0
c: mov r0, r2 6: mov r2, r0 <- home copied to a temp
e: adds r3, r0, r0 e: mov r2, r3 <- join writes the TEMP
^ join wrote r0, which 10: adds r4, r2, r0 <- r0 intact
IS local 0's home

ir0(9,0) returns 10 under the pin where 14 is correct.

WAS JESS EXPOSED? No — and the measurement is not vacuous. Every artifact jess
lowers is byte-identical across 0.60.0 -> 0.64.0: the fused cascade on m7dp
(5362d831..., the AFD-106 baseline) and m4f (90e8fa9b...), gale-nano 0.7.0 on m3,
the f100-init and gust:hal probes, and the self-contained passthrough — which also
still matches its COMMITTED .elf (13495328...), i.e. the image that has actually
run on F100 silicon is unchanged. POSITIVE CONTROL: a module carrying the #1189
shape DOES differ (504 -> 510 B). synth's fix changes output only where the bug
fired, so byte-identity across every artifact means the shape does not occur in
anything jess lowers.

THE PIN IS BUMPED, REVERSING THE STANDING POSITION. AFD-106 and AFD-108 declined
bumps because output was byte-identical and a bump widened the varve-layer gap.
Those were no-regression watches. This one is different: the pin CONTAINS a silent
wrong-answer class on jess's exact path, and the bump is provably behaviour-neutral
today — verified end-to-end through tools/deps/fetch.sh + check.sh and a full
cascade rebuild (exit 0, 89,816 B linked, 0 undefined, 5/5 key symbols, fusion
still byte-reproducible). Zero delta now, class excluded later.

Two pieces of accretion removed in the same change:

  • the pin directory was named fg60, encoding 0.60.0 in a path — the
    version-in-a-filename hazard AFD-106 flagged and did not fix. Renamed to
    synthpin across all 16 references in 6 files.
  • CI fetched synth 0.62.0 SEPARATELY, only because the old pin predated
    verify-embedder. The pin now carries it, so that download was a stale version
    left behind by an earlier bump. Removed; one synth builds and checks. Verified
    the pinned binary accepts with --allow-writer (0) and refuses without it (1).

WHAT 0.64.0 DOES NOT FIX: synth#1191 (filed by jess at 14:54, before this 18:42
release) is untouched — gale-nano's lowering is byte-identical to 0.60.0, same six
undefined symbols, still no symbol for the gust:os/time export the component
declares. H3's second half remains blocked there (AFD-113).

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

…--relocatable compile — pin bumped 0.60.0 -> 0.64.0, proven behaviour-neutral (AFD-114)

synth#1189 / RQ-64-JOINALIAS. On the ARM direct selector — which synth's own PR
calls "every --relocatable compile per #197", i.e. every lowering jess does — an
if/else join register could ALIAS a live register-homed local. `local.get` of a
register-homed local pushes the home register uncopied; when that is the then-arm
result of a value-carrying if/else, the join `mov R_then, R_else` on the else path
WRITES THE LOCAL. Exit 0, no decline, wrong answer.

Reproduced on jess's exact invocation (-t cortex-m3 --cortex-m --relocatable):

  0.60.0 (jess's pin)           0.64.0
    c: mov  r0, r2                6: mov  r2, r0    <- home copied to a temp
    e: adds r3, r0, r0            e: mov  r2, r3    <- join writes the TEMP
       ^ join wrote r0, which    10: adds r4, r2, r0 <- r0 intact
         IS local 0's home

ir0(9,0) returns 10 under the pin where 14 is correct.

WAS JESS EXPOSED? No — and the measurement is not vacuous. Every artifact jess
lowers is byte-identical across 0.60.0 -> 0.64.0: the fused cascade on m7dp
(5362d831..., the AFD-106 baseline) and m4f (90e8fa9b...), gale-nano 0.7.0 on m3,
the f100-init and gust:hal probes, and the self-contained passthrough — which also
still matches its COMMITTED .elf (13495328...), i.e. the image that has actually
run on F100 silicon is unchanged. POSITIVE CONTROL: a module carrying the #1189
shape DOES differ (504 -> 510 B). synth's fix changes output only where the bug
fired, so byte-identity across every artifact means the shape does not occur in
anything jess lowers.

THE PIN IS BUMPED, REVERSING THE STANDING POSITION. AFD-106 and AFD-108 declined
bumps because output was byte-identical and a bump widened the varve-layer gap.
Those were no-regression watches. This one is different: the pin CONTAINS a silent
wrong-answer class on jess's exact path, and the bump is provably behaviour-neutral
today — verified end-to-end through tools/deps/fetch.sh + check.sh and a full
cascade rebuild (exit 0, 89,816 B linked, 0 undefined, 5/5 key symbols, fusion
still byte-reproducible). Zero delta now, class excluded later.

Two pieces of accretion removed in the same change:
  - the pin directory was named `fg60`, encoding 0.60.0 in a path — the
    version-in-a-filename hazard AFD-106 flagged and did not fix. Renamed to
    `synthpin` across all 16 references in 6 files.
  - CI fetched synth 0.62.0 SEPARATELY, only because the old pin predated
    verify-embedder. The pin now carries it, so that download was a stale version
    left behind by an earlier bump. Removed; one synth builds and checks. Verified
    the pinned binary accepts with --allow-writer (0) and refuses without it (1).

WHAT 0.64.0 DOES NOT FIX: synth#1191 (filed by jess at 14:54, before this 18:42
release) is untouched — gale-nano's lowering is byte-identical to 0.60.0, same six
undefined symbols, still no symbol for the gust:os/time export the component
declares. H3's second half remains blocked there (AFD-113).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe
avrabe merged commit 8c3280e into main Sep 7, 2026
9 checks passed
@avrabe
avrabe deleted the feat/synth-064-pin branch September 7, 2026 18:53
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