---
name: stacked-defects-mask-each-other
description: "Adapter 644-packing masked a spt-core extractor defect (BigscreenVR/spt-bs-releases#62) — fixing the outer one is what made the real cause visible; plus lia's reset-to-genuine-pre-state rule against false passes."
metadata: 
  node_type: memory
  type: project
  originSessionId: 19af1a2f-5196-41e5-8233-8bb5241f8280
  modified: 2026-08-01T01:05:29.856Z
---

**2026-08-01, Linux adapter bricking.** Two defects were stacked and each hid the other:

1. **Adapter side (perri's, real):** claude-spt's `adapter.spt` packed Linux binaries mode 0644 — built on Windows, no POSIX exec bit. Fixed in v0.25.31 by forcing modes at tar time.
2. **Core side (the live root cause, `BigscreenVR/spt-bs-releases#62`):** the **CRC-swap update plan is content-blind** — `crc_swap.rs` `collect_diffs` compares sha256 only, so a **mode-only** difference in a byte-identical binary is invisible to the plan and never heals. Reproducible builds make it permanent: the fixed binary has the same bytes, so the update path skips it forever. **Update path only — fresh installs land healthy.** Mechanism confirmed in source by doyle; every placement primitive *does* preserve modes. Fix shape: a mode-only `set_permissions` arm (`applyhost.rs:445` precedent). Detail in [[crc-swap-metadata-blindness]].

**The isolating control that made it decisive** (lia): plain `tar` on the SAME archive, same box, same user, same minute, preserved 0755 on both Linux binaries; `spt adapter update` on that same archive produced 0644 + `Permission denied (os error 13)`. umask 0002 cannot strip an exec bit.

**I carried a wrong mechanism into this file and doyle's source check replaced it.** I wrote "the extractor loses the mode when it flattens the triple dir" and "fresh install too, not only update" — both false, inherited from the reporter's framing rather than measured. The control above proves the *update path* is broken; it never showed where, and I filled the gap with a plausible story. **A control that isolates a symptom does not locate the cause** — resist naming a mechanism the evidence does not reach.

**The lesson:** a defect can be *masked* by another defect upstream of it. The 0644 archive meant core's update path could never be observed failing on a mode-only diff — every failure was attributable to the packaging. Perri's v0.25.31 was not wasted work even though it did not fix Linux: **it is the only reason the real cause became visible.** When a fix "doesn't work," suspect a second defect underneath before suspecting the fix.

**My own error, worth not repeating:** I accepted "nothing core-side is at fault; nothing filed against core" from the reporter without checking, and downgraded lia's question — should core force exec on an adapter's declared entry binary — to "merit as defense in depth." It was not hardening; it was the live root cause, in my own project's domain. **A "defense in depth" label on someone else's finding is a categorization, and categorizing is a claim.** See [[stale-carried-forward-sentence]].

**False-pass method rule (lia's, fleet-wide):** her earlier `chmod` had left the installed binary at 755, which would have produced a **false PASS**. She reset it to 644 to restore the genuine pre-state before testing. *A test that lies in the direction of good news is the worst kind* — reset to the real pre-state first. Same family as [[instrument-soundness-guards]].

**OWED BY ME (doyle-ruled, 2026-08-01) — F-028 contract section, blocked until todlando's #62 fix GATES.** The published surface states no POSIX-mode contract for an adapter's declared entry binary (perri's finding, `docs/SPT-CORE-FINDINGS.md` @597a6ca). Authorship ruled mine on the [[v0490-published]] PR #141 precedent; doc-stage tag + docs-drift gate ride my leg; the section lands inside the #62 lane, **after** the fix gates, so it documents which guarantee *became true* rather than which was intended. Three possible guarantees, and the fix decides: preserve the archived mode / force exec on the declared entry / loudly refuse a non-executable one. **Do not write it early** — that either constrains the fix by accident or documents a guarantee core does not make.

The class, and the framing doyle is putting in the wave brief verbatim: **an unstated ownership boundary does not fail loudly, it fails as two parties being reasonable.** perri and lia each concluded the other side was faithful from the same silence. Identical shape to PR #141 (published contract never said which component carried ring's perch safety).

**Release consequence I own:** v0.49.0 shipped carrying #62. When it lands, this is patch-cut severity by the same logic applied to perri's 0.25.31 — total platform breakage, no durable workaround (chmod is re-broken by the next extraction) — not something to hold for the next milestone batch.

**Bound honestly:** genuine **musl-host** extraction remains UNTESTED — `spt adapter add` has no triple flag and seeks the host triple strictly, so a glibc box selects gnu. Identical binary bytes across 0.25.30/0.25.31 were verified as reproducibility, not a stale repack (empty `tools/` diff, no version string in either binary).
