subagent transcript
session 18e25685 · workflow wf_23df5b1c
delegated task
You are an adversarial verifier for a FreeCAD-wasm code review. A reviewer claims: SEVERITY: medium CATEGORY: destructive-leftover-script FILE: /opt/t
▸ Magik
You are an adversarial verifier for a FreeCAD-wasm code review. A reviewer claims:
SEVERITY: medium
CATEGORY: destructive-leftover-script
FILE: /opt/toolchains/fix-freetype-sjlj.sh
SUMMARY: fix-freetype-sjlj.sh is a non-idempotent, destructive leftover from the abandoned JSPI/wasm-longjmp pivot that, if run, silently breaks the current JS-EH build.
DETAIL/EVIDENCE: fix-freetype-sjlj.sh:14-15 runs `embuilder build freetype-legacysjlj --force` then `cp libfreetype-legacysjlj.a libfreetype.a`, overwriting the sysroot base archive in place with the wasm-longjmp (SUPPORT_LONGJMP=wasm) variant. Its own header (lines 5-6) says this is for 'Our JSPI build ... links with -fwasm-exceptions and Qt forces SUPPORT_LONGJMP=wasm' — i.e. the abandoned JSPI/wasm-EH path. The CURRENT ASYNCIFY+JS-EH build compiles with -fexceptions and uses JS/emscripten longjmp; I confirmed the live sysroot libfreetype.a is the emscripten_longjmp variant (`U emscripten_longjmp`, md5 32cf8785..., distinct from the -legacysjlj variant), which is what configure-stage2.sh:60 links. So the script is not currently applied, but it has no revert and clobbers a shared sysroot file; if an operator runs it (name looks like a generic 'fix'), the next FreeCAD link fails with an emscripten_longjmp/__wasm_longjmp symbol mismatch and nothing records that it must be undone.
RECOMMENDATION: Delete or clearly quarantine fix-freetype-sjlj.sh as JSPI-only, or make it reversible and gate it on the wasm-EH posture; document that the ASYNCIFY+JS-EH build requires the stock emscripten-longjmp libfreetype.a.
Independently verify by reading the actual file(s) and running git/grep as needed (repo at /home/magik6k/lcad-wasm/freecad-port/FreeCAD, toolchain at /opt/toolchains, deploy at /home/magik6k/lcad-wasm/freecad-port/deploy-gui). Default to REFUTED if you cannot confirm the evidence. Adjust severity to what the evidence actually supports.
Fable
thinking
I should check the actual file to verify this claim and see what evidence supports it.
Fable
⚙ Read {"file_path": "/opt/toolchains/fix-freetype-sjlj.sh"}
Fable
⚙ Bash {"command": "ls -la /opt/toolchains/ 2>/dev/null | head -50; echo \"---GREP configure-stage2---\"; find /home/magik6k/lcad-wasm -name \"configure-stage2.sh\" 2>/dev/null", "description": "List toolchains and find configure-stage2"}
Fable
thinking
I need to verify the sysroot's libfreetype.a library and check the configure-stage2.sh script to understand the current build configuration, particularly around exception handling and how freetype is being linked.
Fable
⚙ Bash {"command": "C=/opt/toolchains/emsdk/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten\necho \"=== ls freetype archives ===\"; ls -la \"$C\"/libfreetype*.a 2>/dev/null\necho \"=== md5 ===\"; md5sum \"$C\"/libfreetype*.a 2>/dev/null\ne…
Fable
⚙ Bash {"command": "echo \"=== configure-stage2.sh lines 50-70 ===\"; sed -n '50,70p' /home/magik6k/lcad-wasm/freecad-port/toolchain/configure-stage2.sh\necho \"=== grep freetype in configure-stage2 ===\"; grep -n -i freetype /home/magik6k/lcad-wa…
Fable
thinking
I've confirmed the script at /opt/toolchains/fix-freetype-sjlj.sh exists and does exactly what's needed — it builds the legacy SJLJ freetype variant and copies it over the standard libfreetype.a. The header comments confirm this is for JSPI and wasm-exceptions support, and the current sysroot libfreetype.a is still using the emscripten variant.
The key issue is that running this script would overwrite libfreetype.a with the wasm-longjmp variant, which would break the JS-EH build since the current pipeline uses -fexceptions and asyncify for Qt. The script is destructive and non-idempotent with no revert mechanism.
Since this is a leftover script that requires manual invocation and isn't aut …
Fable
⚙ Bash {"command": "echo \"=== references to fix-freetype-sjlj ===\"; grep -rn \"fix-freetype-sjlj\" /opt/toolchains /home/magik6k/lcad-wasm 2>/dev/null\necho \"=== which rebuild script is current? refs to fix-freetype or legacysjlj in rebuild scr…
Fable
thinking
The script isn't used in any active build pipeline—it's only mentioned in a research document that explicitly designates it for wasm-EH builds while leaving JS-EH with defaults. This confirms it's a wasm-EH-specific artifact. The technical evidence is clear: the script is non-idempotent and destructive, overwriting a shared sysroot file without any way to revert the changes.
The reviewer rates this as medium severity, but I'm reconsidering. While the factual claims are all confirmed—the script would break the build if run—the failure mode would actually be a loud link error at build time, not silent corruption. Since this requires deliberate manual invocation and isn't wired into any automa …
Fable
All evidence in the finding is factually confirmed:
1. **File content matches exactly.** `/opt/toolchains/fix-freetype-sjlj.sh:14-15` runs `embuilder build freetype-legacysjlj --force` then `cp "$C/libfreetype-legacysjlj.a" "$C/libfreetype.a"`, overwriting the sysroot base archive in place. Header lines 5-6 confirm it targets the JSPI/`-fwasm-exceptions`/`SUPPORT_LONGJMP=wasm` path.
2. **Live sysroot is the emscripten-longjmp variant.** `libfreetype.a` md5 `32cf8785...` with `U emscripten_longjmp`, distinct from `libfreetype-legacysjlj.a` md5 `475a344b...`. So the script is not currently applied.
3. **configure-stage2.sh:60** links exactly `$SY/lib/wasm32-emscripten/libfreetype.a`, and the current build compiles with `-fexceptions` (lines 22-23) against asyncify Qt — the JS-EH posture. Running the script would swap in the wasm-longjmp variant and break the next link.
4. **No revert / not idempotent / clobbers a shared file**, and it is not wired into any automated pipeline (only referenced in `research/R10-eh-jspi-asyncify-findings.md:62`, which itself notes "for wasm-EH; leave default for JS-EH").
Two corrections to the framing that lower severity: (a) the finding says the script "silently breaks" the build, but the actual failure mode is a **loud link-time symbol mismatch**, not silent runtime corruption; (b) triggering it requires **deliberate manual operator invocation** — it is a latent footgun, not an active defect in any shipped or automated code path. The clobber is "silent" only in the sense that nothing records it must be undone. This is toolchain hygiene rather than a live bug, so medium overstates it; low is what the evidence supports.
Fable
⚙ StructuredOutput {"verdict": "CONFIRMED", "reason": "All factual claims verified. fix-freetype-sjlj.sh:14-15 non-reversibly overwrites the shared sysroot libfreetype.a with the wasm-longjmp (legacysjlj) variant; header lines 5-6 confirm it is for the abando…