Skip to content

Local-remote CI parity: unified venues, artifact/glibc/Defender lanes, dry-run red fixes - #1280

Merged
DeusData merged 7 commits into
mainfrom
feat/local-remote-parity
Jul 26, 2026
Merged

Local-remote CI parity: unified venues, artifact/glibc/Defender lanes, dry-run red fixes#1280
DeusData merged 7 commits into
mainfrom
feat/local-remote-parity

Conversation

@DeusData

Copy link
Copy Markdown
Owner

What

Establishes local = remote minus {arch legs, YAML glue, release plumbing} — every gate-shaped behavior now routes through the same canonical entries on every venue — and fixes the reds from the last two release dry runs.

Venue unification (staged bundle, now landed)

  • `_smoke.yml` onto the shared wrappers with an extracted-artifact input; `soak-legs.sh` as the one canonical soak entry; protected per-user TEMP roots and clean-disk preflights on every venue; `soak.yml` retired; venue-parity contract (whitelist walker).

Parity lanes (new)

  • Artifact-flow smoke locally: canonical `scripts/package-release.sh` (archive layout defined ONCE, `_build.yml`'s eight inline archive blocks now call it) + `scripts/ci/smoke-artifact.sh` (package → extract → same wrapper, artifact mode) wired for mac / linux container / Windows VM.
  • glibc-floor leg: ubuntu-22.04 (glibc 2.35) portable-binary smoke + dynamic-binary refusal assert.
  • Defender-ON everywhere: `scripts/ci/ensure-defender.ps1` (enable + verify, fail-closed) in every Windows CI job and the VM preflight; the `_smoke.yml` AV scan engine-failure soft-skip is now a red gate. Expect slower Windows jobs (real-time scanning during install/build/test I/O).

Contract updates

  • Launcher-bundle contract retargeted onto the canonical wrappers (six pinned security invariants kept, anchors moved; RUNNER_TEMP ban → provision/scan allowlist + no-exe backstop). Five-file Windows bundle layout asserted in `package-release.sh`.
  • Venue-parity contract: requires the new lanes, counts one ensure-defender step per Windows job, `--help` probes for new entries. Fails with 20 violations on the pre-change tree.

Dry-run red fixes

  • launcher: bounded backoff on `ERROR_SHARING_VIOLATION` for the staged-copy secure open (windows-11-arm + windows-2025 smoke reds; image-specific scan window, no local repro — this dry run is the arbiter).
  • mcp: tree-format output is valid UTF-8 by construction (macos-15-intel B3 class: one raw byte makes BSD grep treat the whole output as binary). Unit test RED-on-revert-proven. B3 failure path now dumps `od -c`.
  • tests: leak-free teardown in the daemon_runtime disconnect-cancel test (LSan 200-byte leak on its failure path).
  • ci: executable bits for directly-invoked canonical scripts (fresh checkouts got 644 → `ci-ok`/shard-union/soak/package steps would have failed with permission denied).

Verification

  • Both contracts green here, red on the pre-change architecture (six/twenty violations respectively).
  • macOS: full suite + TSan + smoke + both soak legs green; sanitizer test RED-on-revert ×2, green with fix.
  • Windows VM (Defender ACTIVE, verified by the new preflight): full build green incl. launcher fix; guards/smoke-install/soak green; query-leak soak 1.1x (vs the old 53x, Reapply the #581 thread-heap release (TLS detach callback) #1275 holds).
  • Linux: arm64 test/TSan/smoke/portable green on the base; canonical lint green.
  • Remote arbiter: release dry run on main after merge (launcher-32 jobs, Defender enablement on runners, macos-15-intel B3, YAML glue).

DeusData added 7 commits July 26, 2026 22:23
The staged venue-unification bundle: _smoke.yml onto the shared
wrappers with an extracted-artifact input (CBM_SMOKE_ARTIFACT_DIR),
soak-legs.sh as the one canonical soak entry (quick + query-leak legs
across all venues), protected per-user TEMP roots shared across
venues, clean-disk preflights before every VM/Docker run, win.sh and
run.sh routed through the canonical scripts, soak.yml retired, and
the venue-parity contract (whitelist walker: workflows may provision
or call canonical entries, nothing else).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
… wrappers

The venue unification moved release-smoke staging/execution out of
_smoke.yml into the canonical wrappers (vm-smoke.sh / smoke-local.sh),
so Step 0e's needle checks against inline YAML failed on every venue.

Re-anchor each pinned invariant where the behavior now lives:
- canonical-exe execution + profile-rooted fixtures + update fixture
  identification: asserted in vm-smoke.sh / smoke-local.sh, plus the
  workflow must call the wrapper on the extracted artifact
- version/install-audit preflight needles updated to the artifact-dir
  text shape (still workflow provisioning)
- RUNNER_TEMP: absolute ban replaced by a provision/scan allowlist
  walker + an explicit no-exe-under-RUNNER_TEMP backstop

No pinned security property is dropped; the retargeted contract fails
on the pre-unification architecture (verified against HEAD).

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…r, Defender-ON everywhere

Closes the closable local-vs-remote venue gaps so that, outside arch
legs / YAML glue / release plumbing, every local red is a remote red
and vice versa on shared legs:

- scripts/package-release.sh: THE canonical archive step (names +
  five-file Windows bundle layout defined once); _build.yml's eight
  inline archive blocks become calls to it.
- scripts/ci/smoke-artifact.sh: the artifact-flow smoke lane — build,
  package, extract, then the canonical wrapper in artifact mode; wired
  as run.sh smoke-artifact (compose service), win.sh smoke-artifact,
  and directly runnable on macOS. Archive-layout bugs now surface
  locally instead of in a release dry run.
- glibc-floor leg (Dockerfile.glibc22 + compose + run.sh): portable
  binary smokes on ubuntu-22.04/glibc 2.35; the dynamic binary must
  refuse there (2.38+ floor by design).
- Defender-ON parity (user directive): scripts/ci/ensure-defender.ps1
  enables + VERIFIES real-time protection, fail-closed; runs in every
  Windows CI job (_test x2, _soak x3, _smoke, pr.yml) AND in the VM
  preflight; _smoke.yml's scan engine-failure soft-skip becomes a red
  gate. Expected cost: slower Windows jobs (AV scanning during
  install/build/test I/O); the next dry run proves the runner side.
- Contracts: launcher-bundle five-file check retargeted onto
  package-release.sh + per-archive canonical-call association;
  venue-parity contract requires the new lanes, counts one
  ensure-defender step per Windows job, adds --help probes for the new
  entries. Extended contract fails on the pre-change tree (verified:
  20 violations on HEAD).
- VM README: ephemerality/Defender posture documented — utmctl has no
  snapshot verb, so per-run revert stays a manual qcow2 option; the
  sweep preflight remains the standing mechanism.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
git-apply of the staged unification recorded the new canonical entries
as 100644; workflows execute them directly (run: scripts/ci/...), so a
fresh CI checkout would fail at ci-ok/shard-union/soak/package steps
with permission denied — the same class the parity worktree's own
preflight just tripped over locally.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
…ecure open

Dry run 30206811293: windows-11-arm (both variants) and windows-2025
smoke failed in the update/uninstall E2E phases with 'private staged
copy failed secure open (error 32)' — ERROR_SHARING_VIOLATION. On the
newer hosted images a first-touch scanner transiently holds the
just-staged executable without FILE_SHARE_DELETE, so the launcher's
GENERIC_READ|DELETE retirement open collides on cold images.

Absorb the scan window with the same bounded backoff the staged
RENAME path already uses (<=~2.5s, exponential); every retry re-runs
the full secure-open validation, so no TOCTOU surface changes.

No deterministic local repro exists (the VM passes this phase with
Defender active; the collision is image-specific) — the next dry run
on the same three jobs is the arbiter.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Dry run 30206811293: macos-15-intel release smoke failed B3 with a
visibly correct 'semantic: 50' table — BSD grep returns no-match for
the ENTIRE output when any line carries a NUL, control byte, or
invalid UTF-8 (verified: printf poisoned input -> grep -qE fails), so
one bad byte in one row silently unmatches every anchored check.

Close the class at the emission choke point: control bytes and
invalid UTF-8 force the quoted form; quoting escapes controls as
\u00XX and replaces invalid sequences with U+FFFD (RFC 3629
validation, NUL-safe). Tool output is valid UTF-8 by construction.

Unit test proven RED-on-revert (raw bytes emitted) and green with the
fix. The smoke's B3 failure path now also dumps od -c bytes so a
future red names the exact byte.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
LSan (Linux amd64 leg): 200 bytes — the runtime client (192) plus its
IPC connection (8) — leaked whenever an earlier stage of
daemon_runtime_disconnect_cancels_blocked_non_index_child... failed:
both close blocks were gated on the request thread having completed,
so a failed run skipped the close entirely.

Teardown now closes unconditionally: close_begin interrupts the
transport (forcing the blocked call to complete), the join becomes
safe, and close_finish frees the client on every path.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData
DeusData merged commit 3d046fb into main Jul 26, 2026
10 of 11 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.

1 participant