Skip to content

fix(m17): 17.3 multi-target SEA build — un-pin the triple, verify it independently (INC-2026-08/09) - #85

Merged
seanrobertwright merged 4 commits into
mainfrom
m17-slice3-multi-target-sea
Aug 9, 2026
Merged

seanrobertwright merged 4 commits into
mainfrom
m17-slice3-multi-target-sea

Conversation

@seanrobertwright

Copy link
Copy Markdown
Owner

What

build-sea.mjs was written for one platform and hardcoded it: TARGET_TRIPLE = "x86_64-pc-windows-msvc" plus a literal .exe. On Linux it produced a working 118 MB ELF under a Windows name, printed PASS, and exited 0 — while Tauri's externalBin looked for collector-x86_64-unknown-linux-gnu and found nothing (INC-2026-09). The darwin recipe was absent entirely. This slice makes the sidecar build emit a correctly-named, working artifact on every target the M17 matrix covers, and adds the verification that makes those claims mean something.

Producer. The name comes from an exported pure rustTargetTriple(platform, arch) table — the cursorStorePathFor(home, platform) shape 17.1 established — fed through the existing sidecarFileName(), which stays the single definition of the .exe-iff-win32 rule. Unsupported pairs throw rather than guessing. The darwin Mach-O steps are Node's documented recipe verbatim: codesign --remove-signature → postject … --macho-segment-name NODE_SEA → ad-hoc codesign --sign - --force.

Verifier. A separate verify-sea.mjs, because INC-2026-09 showed the obvious self-check basename === collector-${rustTargetTriple()} cannot fail — it compares the code to itself, so every wrong triple inside the helper satisfies both sides. Its expectation comes from rustc -vV, the authority Tauri itself resolves by, and it never imports rustTargetTriple. It also enforces a 10 MB floor (a 0-byte stub is not a build) and boot-smokes the artifact.

INC-2026-08, same file: --check and the printed hint booted a second collector against the operator's live ~/.420ai/queue.sqlite — the double-writer bug CLAUDE.md names. serve parses no flags (serve.ts:572), so a --home argument would be silently ignored; the fix is environmental. seaChildEnv sets both HOME and USERPROFILE at a throwaway inside the tmpdir.

CI. All five lanes now build and boot the real SEA instead of cargo checking a 0-byte stub — skipped ≠ passed, one level out. The stub step stays after as a no-op fallback.

Precondition both incidents named: build-sea.mjs had zero exports and ended in main().catch(...), so importing it from a test ran a full build. It now carries the setup-env.mjs entrypoint guard.

Found while planning, fixed here: apps/desktop/.gitignore covered only *.exe, so every non-Windows artifact (~118 MB) would have appeared untracked the moment those targets became buildable.

Negative controls

Every regression test was proven falsifiable, not merely observed green:

  • stripping the env: line reproduces INC-2026-08's queue.sqlite at exactly 40,960 B — byte-for-byte the incident's Linux observation, now on Windows
  • pinning the linux:x64 row back to the Windows triple reddens that row alone
  • renaming the artifact to INC-2026-09's own collector-x86_64-unknown-linux-gnu makes the verifier exit 1 naming both names, where the old script exited 0 printing PASS
  • the 0-byte stub is rejected by the size floor
  • finally does not run on process.exit() (measured) — a deliberately failed verify left an orphan tmpdir before the fix, and creates none after

Verification tier — please read this as written

Windows x64 is built locally and in CI. linux-x86_64 is additionally VM-verified (17.2a). linux-arm64, darwin-x86_64 and darwin-aarch64 are CI-verified, NOT hardware-verified (D-M17-4). The darwin path is the one part of this slice written from documentation rather than measurement — the five green lanes on this PR are its evidence, and 17.2b still owns hardware truth. If 17.2b later finds an ad-hoc-signed Mach-O SEA is killed on real hardware, that is a 17.2b finding, not a 17.3 regression.

Non-goals — named deliberately

  • No CA/Authenticode signing, no notarization — parked by D-M17-2. Ad-hoc codesign --sign - carries no certificate and no identity; it repairs a signature the injection itself invalidated, and does not un-park anything.
  • No lipo universal macOS binary — D-M17-4 promises one; a SEA copies process.execPath, which is single-arch, so fusing the two macOS lanes is 17.6. This slice emits per-arch Mach-O SEAs.
  • No installers, targets, or updater feed — 17.6.
  • No launchd / systemd service definitions — 17.4.
  • No Gatekeeper / quarantine measurement — 17.2b, procurement-blocked.

Review

  • Code review: .agents/code-reviews/m17-slice3-multi-target-sea.md — 6 findings, all fixed. Two were found on the re-review pass, and one is a documented withdrawal of my own incorrect first analysis (codesign --remove-signature is load-bearing, not defensive — a Mach-O signature sits in LC_CODE_SIGNATURE at the end of __LINKEDIT and postject appends).
  • Execution report: .agents/execution-reports/m17-slice3-multi-target-sea.md

Validation

  • npm run repo-health — PASS, 7/7; 1756 tests, 0 skipped (the 1725 baseline + exactly 31 new)
  • npm run typecheck -- --force / lint / format:check — exit 0
  • --require-db not applicable and not claimed: no @420ai/db, no apps/ingest change. The DB layer executed 0-skipped locally anyway.
  • Local Windows: build 89 MB (93,092,352 B) in 12.6 s, verify:collector-sea exit 0, --check PASS
  • The five-lane matrix on this PR is the acceptance criterion for the darwin claim — not a formality.

🤖 Generated with Claude Code

seanrobertwright and others added 3 commits August 9, 2026 16:55
…e smoke (INC-2026-08/09)

`build-sea.mjs` was written for one platform and hardcoded it: `TARGET_TRIPLE =
"x86_64-pc-windows-msvc"` plus a literal `.exe`. On Linux it produced a working 118 MB
ELF under a Windows name, printed `PASS`, and exited 0 — while Tauri's `externalBin`
looked for `collector-x86_64-unknown-linux-gnu` and found nothing (INC-2026-09). The
darwin recipe was absent entirely.

Producer: the name now comes from an exported pure `rustTargetTriple(platform, arch)`
table — the `cursorStorePathFor(home, platform)` shape 17.1 established — fed through
the existing `sidecarFileName()`, which stays the single definition of the
`.exe`-iff-win32 rule. Unsupported pairs throw rather than guessing. The darwin Mach-O
steps are Node's documented recipe verbatim: `codesign --remove-signature` →
`postject … --macho-segment-name NODE_SEA` → ad-hoc `codesign --sign - --force`. Ad-hoc
signing carries no certificate and no identity, so D-M17-2 stays parked; it repairs a
signature the injection itself invalidated. Windows is unchanged (no `signtool`).

Verifier: a SEPARATE `verify-sea.mjs`, because INC-2026-09 showed the obvious self-check
`basename === collector-${rustTargetTriple()}` cannot fail — it compares the code to
itself, so every wrong triple inside the helper satisfies both sides. Its expectation
comes from `rustc -vV`, the authority Tauri itself resolves by, and it never imports
`rustTargetTriple`. It also enforces a 10 MB floor (a 0-byte stub is not a build) and
boot-smokes the artifact.

INC-2026-08, same file: `--check` and the printed hint booted a SECOND collector against
the operator's live `~/.420ai/queue.sqlite` — the double-writer bug CLAUDE.md names.
`serve` parses no flags (`serve.ts:572`), so a `--home` argument would be silently
ignored; the fix is environmental. `seaChildEnv` sets both `HOME` and `USERPROFILE` at a
throwaway inside the tmpdir the existing `finally` already removes.

CI: all five lanes now build AND boot the real SEA instead of `cargo check`ing a 0-byte
stub — `skipped != passed`, one level out. The stub step stays after as a no-op fallback
(it refuses to clobber a non-empty file).

Precondition both incidents named: `build-sea.mjs` had zero exports and ended in
`main().catch(...)`, so importing it from a test ran a full build. It now carries the
`setup-env.mjs` entrypoint guard.

New finding, fixed here: `apps/desktop/.gitignore` covered only `*.exe`, so every
non-Windows artifact (~118 MB) would have appeared untracked the moment those targets
became buildable. `git check-ignore` exited 1 for `collector-x86_64-unknown-linux-gnu`.

Both regression tests were negative-controlled, not just observed green:
- stripping the `env:` line recreates INC-2026-08's exact `queue.sqlite` (40,960 B)
- pinning the `linux:x64` row back to the Windows triple reddens that row alone
- renaming the artifact makes the verifier exit 1 where the old script exited 0 `PASS`

Non-goals held: no `lipo` universal binary (17.6), no installers or updater feed (17.6),
no service definitions (17.4), no signing/notarization (D-M17-2). The darwin path is
`CI-verified`, NOT hardware-verified — 17.2b still owns hardware truth.

Validation: repo-health PASS (7/7), 1756 tests 0 skipped (1725 baseline + 31 new),
tsc -b --force / lint / format:check exit 0, local Windows build 89 MB + verify PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V46NiRDApVRTFVFwTGNEPa
… swallowing it

Five findings, all accepted by the maintainer at the triage gate.

The one with real value before the first darwin CI run: both boot smokes caught the
spawn error only to discard it, keeping `err.stdout`. That is correct for the benign
case (the child exits 0 on stdin EOF and its stdout is still wanted) but it also
swallowed EACCES, ENOEXEC and — the case that matters — a macOS `Killed: 9` from a
Mach-O whose ad-hoc signature does not match its contents. All three produce empty
stdout, so the message read "no status JSON line in output:" followed by nothing, on
the two lanes with the least prior evidence. Both scripts now retain the error and name
it. Demonstrated, not asserted: pointed at an 11 MB non-executable file of the right
name, the verifier now reports `the artifact failed to run: spawnSync … UNKNOWN`.

The other four:
- codesign's two `die()` messages asserted a missing Xcode CLT as THE cause; an unsigned
  input or a read-only artifact land there too, and `stdio: "inherit"` already puts
  codesign's own stderr in the log above. Phrased as a possibility now, no control-flow
  change. (An earlier draft of this finding argued the `--remove-signature` call should
  become non-fatal because the re-sign passes `--force`. That was wrong and is withdrawn
  in the review file: a Mach-O signature lives in LC_CODE_SIGNATURE at the end of
  __LINKEDIT and postject appends, so removing first is load-bearing, not defensive.)
- `it.each` interpolated the input rather than the label, rendering the empty case as
  `throws on malformed input ()` and spilling two multi-line titles. Switched to the
  object form with `$label`.
- `rmSync` gained `maxRetries`/`retryDelay` in both `finally` blocks. New this slice:
  the tmpdirs now hold a `.420ai/queue.sqlite` a child only just closed, `force`
  suppresses ENOENT and not EBUSY, and an escaping cleanup error would report
  "build-sea crashed" for a build that already succeeded. Speculative — never observed.
- The `.exe`-iff-win32 structural test compares the code to itself and stayed green
  under the table negative control. Code unchanged (it mirrors sidecar-stub.test.ts and
  does check the suffix rule); a comment now says it is not a sixth independent check.

Also adds the code review and execution report for the slice.

Validation: repo-health PASS (7/7), 1756 tests 0 skipped, lint + format:check exit 0,
local Windows build 89 MB + verify PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V46NiRDApVRTFVFwTGNEPa
…ips the finally

Found on the code-review's second pass, and measured rather than assumed:
`node -e "try { process.exit(3) } finally { console.log('FINALLY RAN') }"` prints
nothing. `die()` calls process.exit(), so the `finally` cleanup in both scripts covered
the SUCCESS path only, and all six die() sites — esbuild, sea-config, postject, both
codesign calls, and the two smoke assertions — orphaned a tmpdir. Confirmed in the wild:
a deliberately failed `verify:collector-sea` left `…\Temp\verify-sea-556EeE` behind.

Four of the six sites predate this slice. What 17.3 changed is the contents: the
`--check` and boot-smoke tmpdirs now hold a throwaway `.420ai/queue.sqlite`, so a
failure after the child has booted orphans a small SQLite file rather than an empty
directory. This does NOT reopen INC-2026-08 — the leak is under the OS temp root, never
the operator's live collector home, so the single-owner invariant holds either way. But
it did make the plan's Task 5 claim ("the tmp is already removed by the finally, so the
throwaway .420ai disappears with it") true only on success.

Fix: register `process.on("exit", cleanup)` immediately after mkdtempSync in both
scripts and keep the `finally` for the success path. rmSync is synchronous so it is
valid in an exit handler and idempotent under `force`; one registration covers all six
sites. This is CLAUDE.md's "arm the teardown BEFORE the first await" rule applied to a
script rather than a daemon.

Proven, not asserted: after the fix a deliberately failed verify creates no new tmpdir
where the pre-fix run left one, and both the success path and `--check` still pass.

Validation: repo-health PASS (7/7), 1756 tests 0 skipped, lint + format:check exit 0,
build 89 MB + verify PASS + --check PASS.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V46NiRDApVRTFVFwTGNEPa
Copilot AI lite review requested due to automatic review settings August 9, 2026 21:48

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the collector SEA sidecar build pipeline so it produces (and verifies) the correctly named, runnable artifact across the full cross-platform matrix (Windows/Linux/macOS), aligning the produced filename with Tauri’s externalBin target-triple resolution and preventing silent “PASS but unusable artifact” failures.

Changes:

  • Refactors build-sea.mjs into an import-safe module, derives the host Rust target triple from a (platform, arch) table, and implements the macOS Mach-O SEA injection flow (codesign remove → postject --macho-segment-name NODE_SEA → ad-hoc re-sign).
  • Adds an independent verifier (verify-sea.mjs) that derives the expected triple from rustc -vV, enforces a minimum size floor, and boot-smokes the produced sidecar in a confined disposable home.
  • Wires “build + verify + boot” into CI and the desktop build script chain; updates docs, incident log, and .gitignore to match the new multi-target artifact behavior.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
SUMMARY.md Marks M17 17.3 as done and records the delivered behavior and verification tier.
package.json Adds verify:collector-sea and chains verification into build:desktop.
docs/guide/troubleshooting.md Expands troubleshooting entries to include Linux/macOS SEA/postject/codesign specifics and verification failures.
docs/guide/install.md Documents host-derived sidecar naming and the new verification step in the build flow.
apps/desktop/README.md Updates the desktop build recipe, sidecar naming table, verification instructions, and rationale.
apps/desktop/.gitignore Ignores all platform sidecar artifacts (collector-*) while preserving .gitkeep.
apps/collector/scripts/verify-sea.test.ts Adds unit tests for verifier parsing, naming, and size-floor behavior.
apps/collector/scripts/verify-sea.mjs Adds independent sidecar verification: rustc-derived naming, size floor, boot smoke, and hermetic home confinement.
apps/collector/scripts/build-sea.test.ts Adds regression tests for triple derivation, env confinement, hint text, and hermetic --check.
apps/collector/scripts/build-sea.mjs Unpins Windows-only assumptions; adds multi-target naming, macOS recipe, hermetic child env, and import-safe exports.
.github/workflows/cross-platform.yml Builds and verifies the real SEA sidecar on all matrix lanes before Tauri checks.
.agents/research/incidents.md Updates INC-2026-08/09 dispositions to reflect the implemented fixes and test coverage.
.agents/plans/m17-slice3-multi-target-sea.md Adds the detailed slice plan and acceptance criteria for 17.3.
.agents/execution-reports/m17-slice3-multi-target-sea.md Adds execution report, validations run, and remaining verification notes.
.agents/code-reviews/m17-slice3-multi-target-sea.md Adds the slice’s internal code review record and resolved findings.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/desktop/README.md
Comment on lines +82 to +84
`postject` prints an expected warning whose text differs per platform (`The signature seems
corrupted!` on Windows, `Can't find string offset for section name '.note.100'` on Linux);
neither fails the build. On macOS the signature is removed before injection and re-applied
…acle for the split, and six false comments

24 findings from a seven-agent fan-out (errors, tests, types, code, docs, comments,
simplify); all accepted at the triage gate except one reasoned won't-fix. The three
that matter:

**A failure after the copy left a poisoned artifact.** `copyFileSync(process.execPath,
outBin)` wrote ~90-118 MB straight to the FINAL path, so any later failure — and this
slice adds two new ones, both codesign calls, on the least-proven platform — exited 1
leaving a plain `node` binary under the exact name Tauri resolves. Every static guard
accepts it: tauri_build is existence-only, sidecar-stub REFUSES to overwrite a non-empty
file (so the CI stub step would have PRESERVED it), and the 10 MB floor is two orders of
magnitude below. Now staged to `<name>.partial` and published by an atomic `renameSync`
only after every step succeeds, with the staged path registered for cleanup. Measured: a
simulated post-copy failure now leaves the binaries dir empty.

**The verifier could report PASS over a hang.** `execFileSync` throws ONLY on non-zero
exit, signal, or timeout — a clean exit returns normally — so the catch was never the
benign path, and `spawnErr` was silently dropped whenever a status line was present. But
`serve.ts:521` emits a status line unconditionally at BOOT, before reading any command.
So a SEA that boots, prints, then hangs to the 15 s timeout printed
"verify-sea: PASS — and it boots." That is the exit-0-over-a-bad-artifact shape this
slice exists to remove, inside the script that exists to remove it. Both smokes now fail
on `spawnErr` regardless, and the success message no longer overclaims what was measured.

**Nothing enforced the producer/verifier split.** That `verify-sea.mjs` never imports
`rustTargetTriple` — the PR's central architectural guarantee — rested on three prose
comments and one manual grep; a future dedupe would collapse the two oracles and leave
all 31 tests green. Now asserted on the source text, which is a true oracle here because
the fact under test IS an import specifier. Negative-controlled: adding the import
reddens it. Also extracted `resolveSidecarTarget(dir, expected)` so the loud-failure path
— the actual INC-2026-09 fix, previously unreachable from a test and proven only by one
manual rename recorded in prose — now has three hermetic tests.

Six comments were FALSE, which this repo treats as defects in their own right:
- "a musl host must fail loudly here" — it does not and CANNOT: Alpine reports
  linux/x64 exactly as glibc does, so the table returns the gnu triple and only the
  rustc oracle catches it. A second reason the verifier is separate. The slice plan
  carried the same error and now carries an erratum.
- the workflow header still said cargo check runs against a 0-byte stub — contradicting
  its own body 80 lines down.
- the stub step's "safety net"/"fallback" framing: unreachable, since neither step above
  has continue-on-error. Three agents flagged it independently. Reworded, not deleted,
  with an explicit warning against "fixing" it with `if: always()`.
- "Measured cost: ~17 s on windows-x64" attributed a local number to a lane that had
  never run. Replaced with the real first-run figures: ~3 s Linux, ~14-15 s Win/macOS.
- `seaChildEnv`'s "THREE import-time places" — one (capture-engine) resolves at call time.
- `sidecar-stub.mjs` cited the deleted `TARGET_TRIPLE` and described the old CI ordering;
  `sidecar.rs` and `docs/CONTEXT.md` still described a Windows-only `.exe`.

Also: `cleanup()` ran from both the `finally` and the exit handler unguarded, so on the
EBUSY path it double-faulted inside an exit listener — a regression from this slice's own
earlier fix; both closures are self-swallowing now. Four build spawns were unbounded
(codesign can block on a keychain); all now timeout-bounded. The rustc parse is
deduplicated into `sidecar-stub.mjs` (same authority, so this does not couple the two
independent derivations). `verifyHintLine`'s test now keys on the hazard (`\bserve\b`)
rather than on the pipe character of the message it replaced. Size floor pinned at the
boundary. The hermetic spawn timeout dropped below its vitest timeout so a hang keeps its
diagnostic. `@returns {never}` on both `die()`s.

Scope accounting: the milestone plan routed three substrate-independent 17.2a leftovers
to "17.3 (or 17.7's UAT lanes)" and 17.3 never picked them up — marking it DONE would
have absorbed them by omission. Routed to 17.7 explicitly (maintainer's call at the
triage gate), recorded in both the milestone plan and this slice's Skipped Items, and
NOT re-parked behind 17.2b's procurement. The milestone plan's 17.3 row also still said
darwin was "neither measured nor implemented", contradicting SUMMARY in the table SUMMARY
calls the confidence ledger; it now records the CI-verified tier.

Won't fix (reasoned): moving the triple derivation after the `--check` branch. `--check`
is a preflight for a real build and should fail on a host that cannot be built for.

Validation: repo-health PASS (7/7), 1761 tests 0 skipped (+5), lint + format:check +
tsc -b --force exit 0, local build 89 MB + verify PASS, and both new negative controls
(post-copy failure leaves nothing; the import guard reddens) measured.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V46NiRDApVRTFVFwTGNEPa
@seanrobertwright

Copy link
Copy Markdown
Owner Author

prp-review (--agents all) — resolution

Seven specialist agents (errors, tests, types, code, docs, comments, simplify) over the PR diff. 24 findings after dedup; 23 fixed, 1 declined with a reason. Dispositions were chosen by the maintainer at the triage gate.

The three that mattered

# Severity Finding File Disposition What was done Status
1 Important Artifact written straight to its FINAL path, so a failure after the copy leaves a plain node binary under the exact name Tauri resolves — and every static guard accepts it (tauri_build is existence-only, sidecar-stub preserves non-empty files, the 10 MB floor is 2 orders of magnitude below) apps/collector/scripts/build-sea.mjs:230 Fix Staged to <name>.partial, published by atomic renameSync only after every step succeeds; staged path registered for cleanup Fixed — simulated post-copy failure now leaves the dir empty
2 Important Verifier reports PASS over a hang: execFileSync throws only on non-zero/signal/timeout so the catch was never benign, spawnErr was dropped whenever a status line existed, and serve.ts:521 emits one at boot — so boot→print→hang printed PASS … and it boots apps/collector/scripts/verify-sea.mjs:191 Fix Both smokes now fail on spawnErr regardless; success message no longer overclaims Fixed
3 Important Nothing enforced the PR's central guarantee that verify-sea.mjs never imports rustTargetTriple — three prose comments and one manual grep; a dedupe would collapse both oracles with all 31 tests green apps/collector/scripts/verify-sea.test.ts Fix Source-text assertion (a true oracle here — the fact IS an import specifier) + resolveSidecarTarget(dir, expected) extracted so the loud-failure path has 3 hermetic tests Fixed — negative-controlled

Six comments were FALSE — this repo treats that as a defect in itself

# Finding File Status
4 "a musl host must fail loudly here" — it cannot: Alpine reports linux/x64 exactly as glibc, so the table returns the gnu triple and only the rustc oracle catches it build-sea.mjs:61 Fixed (+ erratum in the slice plan, which carried the same error)
5 Workflow header still said cargo check runs against a 0-byte stub — contradicting its own body 80 lines down cross-platform.yml:9 Fixed
6 Stub step's "safety net"/"fallback" framing is unreachable (no continue-on-error above it) — flagged independently by 3 agents cross-platform.yml:101 Fixed — reworded, with a warning against "fixing" it via if: always()
7 "Measured cost: ~17 s on windows-x64" attributed a local number to a lane that had never run cross-platform.yml:88 Fixed — real figures: ~3 s Linux, ~14-15 s Win/macOS
8 seaChildEnv said "THREE import-time places"; one (capture-engine) resolves at call time build-sea.mjs:86 Fixed
9 sidecar-stub.mjs cited the deleted TARGET_TRIPLE + old CI ordering; sidecar.rs and CONTEXT.md still described a Windows-only .exe 3 files outside the diff Fixed

Remaining

# Finding Disposition Status
10 cleanup() ran unguarded from both finally and the exit handler → double-fault inside an exit listener on the EBUSY path (a regression from this slice's own earlier fix) Fix Fixed — both self-swallowing
11 Four build spawns unbounded; codesign can block on a keychain Fix Fixed — all timeout-bounded
12 rustc -vV parse duplicated from sidecar-stub.mjs (2 agents) — same authority, so sharing does not couple the two independent derivations Fix Fixed — one copy, in sidecar-stub.mjs
13 rustc failure asserted "not found" as the cause Fix Fixed
14 verifyHintLine test keyed on | rather than the hazard Fix Fixed — now \bserve\b
15 Size floor pinned below but not at MIN_SEA_BYTES Fix Fixed
16 Hermetic spawn timeout == its vitest timeout, so a hang loses the diagnostic Fix Fixed — 45 s vs 120 s
17 @returns {never} missing on both die()s Fix Fixed
18 expectedSidecarName test comment overclaimed independence Fix (comment only) Fixed — wrapper kept
19-22 install.md:30, CONTEXT.md:296, sidecar.rs:12, README.md:95 (unconditional NSIS) Fix Fixed
23 Milestone plan's 17.3 row still said darwin "neither measured nor implemented" — contradicting SUMMARY in the table SUMMARY calls the confidence ledger Fix Fixed
24 Move triple derivation after the --check branch Won't fix Declined: --check is a preflight for a real build and should fail on a host that cannot be built for

Scope accounting

The milestone plan routed three substrate-independent 17.2a leftovers to "17.3 (or 17.7's UAT lanes)" — the colliding-case dedup-key test, §4b raw-record accounting, and the 2-lines-to-8-events fan-out. 17.3 never picked them up, so marking it DONE would have absorbed them by omission. Routed to 17.7 explicitly (maintainer's decision), recorded in the milestone plan and in this slice's Skipped Items, and deliberately not re-parked behind 17.2b's procurement.

Validation after the fixes

repo-health PASS (7/7) · 1761 tests, 0 skipped (+5) · lint / format:check / tsc -b --force exit 0 · local build 89 MB + verify PASS · both new negative controls measured (a post-copy failure leaves nothing; the import guard reddens when the import is added).

Summary: 24 findings — 23 fixed, 1 declined with a reason, 0 deferred. Three specialists converged independently on the unreachable CI fallback, and two on the duplicated rustc parse.

@seanrobertwright
seanrobertwright merged commit ce5a397 into main Aug 9, 2026
7 checks passed
@seanrobertwright
seanrobertwright deleted the m17-slice3-multi-target-sea branch August 9, 2026 23:30
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.

2 participants