mirror of
https://github.com/logos-co/logos-logoscore-cli.git
synced 2026-08-30 20:31:09 +00:00
The gate was exposed in `checks` and built by NOTHING. ci.yml names `tests`
specifically, `nix flake check` runs nowhere in this repo, and `ws test` builds
exactly one check per repo -- so the control that mechanically enforces the
one-runtime invariant was dead code here, exactly as it was in logos-basecamp.
The negative control is wired alongside it, always: a gate that has never been
seen to fail is indistinguishable from a broken one.
Three defects in the gate itself, all Windows-only, all inherited from the
logos-basecamp sibling this file was copied from and all found by cross-building
it there:
* the peer sweep globbed lib/*.{dylib,so}. On Windows every liblogos_* shared
image is staged into bin/ as a .dll, because the PE loader searches the
executable's directory -- so it found ZERO owners and the exactly-one
assertion could not pass on a correct tree.
* `nm` and `c++filt` were called by their bare names. The cross bintools
installs ONLY x86_64-w64-mingw32-prefixed ones, so neither was on PATH and
every measurement read nothing; valid() then refused to assert over it.
Fail-closed, but the gate could never run. Fixed with targetPrefix, which is
"" natively and therefore a no-op here.
* `nm --defined-only` counts PE import THUNKS as definitions: ld synthesizes a
.text stub AND an __imp_<mangled> IAT slot per imported function. That
reported images as definers of types they merely import. The paired __imp_
entry is the discriminator, and it is the right one rather than merely a
working one -- a genuine second copy statically linked in has no __imp_ slot
and still counts. (The PE export table also hides the phantom, but it hides
a real private copy too, trading a false positive for a false NEGATIVE.)
NOT covered: x86_64-windows, which is where a duplicate actually bites. `checks`
is native-only in this flake and Windows artifacts are built in release.yml, so
exposing the gate for that target is a follow-up. The gate itself is now correct
for PE -- verified in logos-basecamp, which does cross-build it.
Verified on aarch64-darwin: SYMBOL GATE PASS (TokenManager 1 definer
liblogos_protocol(35), LogosAPI 1 definer liblogos_qt_host(26), LogosAPIClient 1
definer liblogos_protocol(49); consumers 0) and NEGATIVE CONTROL PASS, rejecting
a planted duplicate at 49 symbols.
Also drops two dangling references to cmake/LogosSharedFromDll.cmake, the
single-provider shim deleted once the runtime became real shared libraries, and
the claim that liblogos_core is the provider -- it is not, which is precisely
why the assertion is exactly-one rather than naming an owner.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
63 lines
2.4 KiB
YAML
63 lines
2.4 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [ master ]
|
|
pull_request:
|
|
branches: [ master ]
|
|
|
|
jobs:
|
|
test:
|
|
# ATTIC_TOKEN_PUBLIC only exists in the public-cache environment; master
|
|
# jobs must opt into it to publish to the public cache.
|
|
environment: ${{ github.ref == 'refs/heads/master' && 'public-cache' || '' }}
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- arch: x86_64-linux
|
|
runner: ubuntu-latest
|
|
- arch: aarch64-linux
|
|
runner: ubuntu-24.04-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
|
|
steps:
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Install Nix and set up cache
|
|
uses: logos-co/setup-nix-cache-action@v1
|
|
with:
|
|
attic-token-ci: ${{ secrets.ATTIC_TOKEN_CI }}
|
|
attic-token-public: ${{ secrets.ATTIC_TOKEN_PUBLIC }}
|
|
extra-nix-config: |
|
|
experimental-features = nix-command flakes
|
|
|
|
- name: Build
|
|
run: nix build --print-build-logs
|
|
|
|
- name: Run tests
|
|
run: nix build '.#checks.${{ matrix.arch }}.tests' --print-build-logs
|
|
|
|
# The one control that mechanically enforces the one-runtime invariant.
|
|
# Until this step existed the gate was exposed in `checks` and built by
|
|
# NOTHING: this workflow names `tests` specifically, `nix flake check` runs
|
|
# nowhere, and `ws test` builds exactly one check per repo. An absence
|
|
# assertion nobody runs is not an assertion.
|
|
#
|
|
# The negative control ships with it, always. It plants a REAL duplicate
|
|
# definer where an in-process consumer goes and asserts the gate REJECTS
|
|
# that tree; without it, a gate that has never been seen to fail is
|
|
# indistinguishable from a broken one.
|
|
#
|
|
# NOT covered here: x86_64-windows, which is where a duplicate actually
|
|
# bites -- PE has no symbol interposition, so the duplicate that Linux and
|
|
# macOS collapse to one is fatal only there. `checks` is native-only in this
|
|
# flake (forAllSystems at the top), and Windows artifacts are built in
|
|
# release.yml, so exposing the gate for that target is a follow-up rather
|
|
# than a line here. The gate ITSELF now handles the PE layout correctly --
|
|
# verified in logos-basecamp, which does cross-build it.
|
|
- name: One-runtime symbol gate
|
|
run: |
|
|
nix build '.#checks.${{ matrix.arch }}.symbol-gate' --print-build-logs
|
|
nix build '.#checks.${{ matrix.arch }}.symbol-gate-negative' --print-build-logs
|