feat(opencomputers): native desktop consent and cross-platform host foundations - #275
Merged
Merged
Conversation
…ipeline contract test
`linux-helper` failed on every run with:
libgstreamer1.0-dev : Depends: libunwind-dev
E: Unable to correct problems, you have held broken packages.
Root cause, MEASURED on the real runner (ubuntu-22.04, image
20260907.292.1, diagnostic run 34670653303) — the image PREINSTALLS
`libunwind-14-dev`, LLVM 14's versioned unwinder dev package, which declares:
Replaces: libunwind-dev
Breaks: libunwind-dev
so installing `libunwind-dev` requires REMOVING `libunwind-14-dev` — and the
`libc++-dev` / `libc++-14-dev` that depend on it:
Remv libc++-dev [1:14.0-55~exp2]
Remv libc++-14-dev [1:14.0.0-1ubuntu1.1]
Remv libunwind-14-dev [1:14.0.0-1ubuntu1.1]
Inst libunwind-dev (1.3.2-2build2.1)
apt will not remove an installed package as a side effect of resolving a
dependency inside a COMBINED transaction, so asking for `libgstreamer1.0-dev`
alone dead-ends. Naming `libunwind-dev` as an explicit target authorises the
replacement, and the chain then resolves.
Confirmed end-to-end in the same run: the swap happened, pkg-config reported
gstreamer-1.0 1.20.3 / gstreamer-app-1.0 1.20.1, and the helper built —
`Compiling osa-screen-capture-wayland v0.1.0`, `Finished release profile in
1m 12s`, a 4,182,136-byte ELF x86-64 executable.
This is a RUNNER-IMAGE fact, not a Docker one. A bare `ubuntu:22.04` container
does not ship `libunwind-14-dev`, so the combined install succeeds there — I
reproduced that on both arm64 and amd64 before finding the real cause. That is
why it could only ever be caught in CI.
Why it matters beyond the helper: `release.yml` runs the same install on the
same image, so this does not merely fail a helper build — it fails
`build-linux-x64`, after which the publish gate refuses to publish and the tag
ships with no assets (the v1.0.191 failure mode).
Adds `test/release_pipeline_contract_test.exs`, which reads the workflows as
DATA (following `toolchain_pin_test.exs`) and fails if:
* either workflow installs the GStreamer dev packages without installing
`libunwind-dev` first, or installs them in a different order;
* the two workflows install different GStreamer package sets — they must
agree, because linux-helper exists to fail BEFORE the release does;
* the publish gate requires an asset that nothing in release.yml or the
scripts it invokes produces;
* the gate stops checking the `.sha256` sidecar for each asset;
* `install.sh` / `install.ps1` stop deriving asset names from a platform
variable, or the Windows enrollment bundle loses an input it copies.
Both new assertions were confirmed to FAIL against the regressed state:
removing the `libunwind-dev` line trips the ordering guard, and adding a bogus
asset to the gate trips the producer guard. The producer search deliberately
excludes the gate's own list — the first version of this test passed with a
bogus asset added, because the search matched the gate line and every name
"produced itself".
`release.yml` builds the Windows desktop helper, validates its PE
architecture, hashes it into `priv/helpers`, runs the enrollment suite and
assembles `osa-opencomputers-windows.zip` — and the publish gate now REQUIRES
that zip, so a failure anywhere in that chain blocks the ENTIRE release,
Linux and macOS included.
None of it ran anywhere except `release.yml` itself, i.e. only after a tag
existed. That is precisely the v1.0.191 failure mode this repository has
already paid for once: a lane whose first execution is the release it was
supposed to protect.
Coverage was asymmetric before this commit:
| native target | PR-exercised |
|------------------------|------------------------------------|
| Linux Wayland helper | linux-wayland-helper.yml |
| macOS capture | native-capture.yml |
| Windows helper+bundle | (nothing — tag only) |
`windows-desktop-helper.yml` runs the same steps as the release job on the
same runner label (`windows-latest`), so a break fails on the pull request
instead of on the tag: .NET 8, `build.ps1 -Runtime win-x64 -BundleDirectory
priv/helpers` (which runs the protocol tests and validates the PE header
first), `Enrollment.Tests.ps1`, then `Build-EnrollmentBundle.ps1` with a
SYNTHETIC `v0.0.0-ci` tag so CI never presents itself as a release.
It also asserts the bundle's contents rather than just its existence: the
runtime installer reads `RELEASE_TAG` to pin what it downloads and delegates
to `install-runtime.ps1`, so a bundle missing either is unusable for
enrollment — which is the entire reason the release requires it.
Also strengthens the pipeline contract test with a sidecar-glob guard. The
`.sha256` sidecars are produced by a globbed loop:
for f in *.tar.gz *.zip osagent-tui-*; do ... done
An asset whose extension matches no glob silently gets no sidecar, and the
gate then fails on a missing `.sha256` — for an asset that was built
correctly. The new assertion fails if any asset the gate requires matches no
glob. Confirmed by adding `osa-newformat.tar.zst` to the gate: both this
guard and the producer guard fire, with messages naming the fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose and relationship
Continues the OpenComputers platform work after #274 merged.
This branch is based on current main and does not replay the merged reconnect fix.
Keep subsequent OSA changes in this PR; the companion compute work remains https://github.com/Miosa-osa/miosa-compute/pull/1557.
This is a draft implementation checkpoint, not a claim that the entire cross-platform product is finished or deployed.
Included
Evidence recorded by implementation owners
These are targeted tests, not live capture/input or end-to-end VM acceptance.
The implementation preserves explicit unavailable results instead of inventing readiness or usage measurements.
Remaining acceptance and integration
No merge or deployment is requested by this PR checkpoint.
Release-pipeline fixes (added during review)
Root cause of the failing
linux-helper— fixedEvery run failed with:
MEASURED on the real runner (ubuntu-22.04, image
20260907.292.1, diagnostic runs34670409222/34670564638/34670653303): the image preinstallslibunwind-14-dev(1:14.0.0-1ubuntu1.1), which declaresso installing
libunwind-devrequires REMOVINGlibunwind-14-dev— and thelibc++-dev/libc++-14-devthat depend on it. apt will not remove aninstalled package as a side effect of resolving a dependency inside a combined
transaction, so asking for the dev packages alone dead-ends. Naming
libunwind-devas an explicit target authorises the replacement.This is a runner-image fact, not a Docker one. A bare
ubuntu:22.04container (both arm64 and amd64) does NOT ship
libunwind-14-devand installsthe dev packages in one transaction — which is why it could only ever reproduce
in CI.
Why it mattered beyond the helper:
release.ymlruns the same install on thesame image, so this would have failed
build-linux-x64, after which the publishgate refuses to publish and the tag ships with zero assets — the v1.0.191
failure mode.
Fixed in
linux-wayland-helper.ymlandrelease.yml. Verified end-to-end on thereal runner: the swap happened, pkg-config reported
gstreamer-1.0 1.20.3/gstreamer-app-1.0 1.20.1, and the helper built (Finished release profile in 1m 07s, 4,182,136-byte ELF x86-64). Run34671103633: success.The Windows helper had no PR-time coverage — fixed
Coverage was asymmetric:
linux-wayland-helper.ymlnative-capture.ymlrelease.ymlbuilds the Windows helper, validates its PE architecture, hashes itinto
priv/helpers, runs the enrollment suite and assemblesosa-opencomputers-windows.zip— and the publish gate now REQUIRES that zip, so afailure anywhere in that chain blocks the entire release, Linux and macOS
included. Its first execution was the release it was supposed to protect.
windows-desktop-helper.ymlcloses it: same runner label, same steps, plus abundle-content check (the runtime installer reads
RELEASE_TAGand delegates toinstall-runtime.ps1, so a bundle missing either is unusable for enrollment).Uses a synthetic
v0.0.0-citag so CI never presents itself as a release. Run34671361337: success,Enrollment bundle OK: 26925 bytes.Windows asset contract — kept, not weakened
docs/windows-onboarding.mdstates the release producesosa-opencomputers-windows.zipand its SHA-256 sidecar, so requiring it isconsistent with the gate's "complete release or nothing" design. The gate was
not relaxed; the missing CI coverage was added instead.
Regression coverage —
test/release_pipeline_contract_test.exsReads the workflows as DATA (following
toolchain_pin_test.exs) and fails if:libunwind-devfirst, or in a different order;
because linux-helper exists to fail BEFORE the release does;
release.ymlor the scripts itinvokes produces;
.sha256sidecar glob (it would silently get nosidecar, then fail the gate);
the enrollment bundle loses an input it copies.
Every assertion was confirmed to FAIL against the regressed state. The producer
search deliberately excludes the gate's own list — the first version of the test
passed with a bogus asset added, because the search matched the gate line and
every name "produced itself".
Final asset list — 14 files (was 12)
Both installers derive asset names from a platform variable rather than
hardcoding a list, so the new asset does not break them.
Tag-time pre-checks
lib/optimal_system_agent-<ver>/priv/helpers/…— matchesthe verifier predicate (verified
PurePosixPathnormalization);prune_build_artifacts/1only removespriv/rust/tui/targetand stale libdirs — it does not strip
priv/helpers;stage.shruns beforemix releaseon both Linux and Windows;build.sh/stage.sh/verify-package.shagree onCARGO_TARGET_DIR.Not verified
The publish assembly itself —
release.ymltriggers only on a tag, andrunning it means creating a public release. The contract test statically proves
every required asset has a producer and a sidecar glob, so the gate is
satisfiable.
Release ordering (unchanged)
miosa-compute#1557 remains the companion. ItsSec-WebSocket-Protocolresponse-header fix must be deployed before a client release containing #274's
strict validation is published.