Building the prototype
The prototype exercises portable C++20 code on development hosts. It implements
aslice --help, aslice --version, and aslice db schema [--role ROLE].
Schema defaults to client-state; the other roles are client-cache,
system-state, coordinator, publisher, and release-signer.
aslice dev fixture runs an unsigned fixture package lifecycle in a disposable
prefix. It exercises package selection, dependency resolution, the store, profile
links, generation activation, upgrade, rollback, and removal together.
Bare invocation and command groups print help without opening a prefix. For a
command's arguments, options, examples, and platform limits, use
aslice help artifact verify or aslice artifact verify --help. Missing required
leaf arguments and unknown options return exit 2. The former unreleased
prototype command group has been removed; stored .prototype.json markers,
aslice-prototype-1 data, and fixture artifact identities remain unchanged.
Portable package and container commands
These commands run with CLion's bundled MinGW as well as on POSIX hosts:
aslice version normalize v7.1
aslice version compare 1.1.1.11 1.1.1
aslice version matches 1.6.43 ">=1.6, <1.7"
aslice dev fixture resolve --catalog tests/fixtures/prototype/catalog-v1.json hello
aslice artifact inspect tests/fixtures/artifact-manifest.json
resolve requires no prefix and writes no files. It accepts simulated
--target-os, --flavor, and --prerelease options. Version ordering implements
epoch, three or four numeric components, and SemVer prereleases. Normalization
accepts the upstream forms in PACKAGE-FORMAT, including lettered patches.
Constraints support equality, comparisons, caret, tilde, comma intersections, and
|| unions. Prereleases require explicit admission; a prerelease bound admits
prereleases of that same numeric version. Numeric core components are bounded by
unsigned 64-bit integers. Fixture candidates may carry an unsigned 64-bit
revision and a variants object whose values are booleans. Missing fields retain
revision zero and an empty assignment without changing existing fixture identities.
Version ordering, including epoch, precedes revision; revision precedes flavor.
Install retains an eligible installed artifact, while upgrade prefers newer candidates.
A dependency such as "dep": "^1.0 +metal" requires a candidate with metal
enabled. Variant tokens may precede or follow the version constraint, and multiple
requirements must hold on the same selected artifact. "dep": "+metal" accepts
any normally admitted version with that variant. Missing or disabled variants
do not match. Candidate assignments describe existing fixture builds; the resolver
does not infer defaults, generate assignments, or plan source builds. Formula-level
variant prerequisites/conflicts, virtual providers, root variant requests, and
conditional dependencies remain pending.
Manifest inspection validates the artifact-manifest fields and semantic checks: OS ranges, unique dependencies, file inventory, case collisions, transitive symlinks, and relocation bounds and bindings. It computes the artifact identity from canonical JSON, including UTF-16 object-key ordering. ABI records are checked structurally; this does not inspect Mach-O binaries or prove ABI compatibility. The illustrative repository fixture can be inspected but does not match a real payload. For a manifest with actual file hashes:
aslice artifact verify manifest.json --payload payload
aslice slice pack manifest.json payload example.slice
aslice slice inspect example.slice
Payload verification checks kinds, file sizes and SHA-256, link targets, unlisted
entries, and relocation expected bytes. POSIX also checks file/directory modes;
Windows reports posix_modes_verified: false. Paths currently use a conservative
ASCII subset. Unicode normalization remains pending. Local manifest input is
capped at 4 MiB, nesting at 64 levels, inventory at 100,000 entries, and regular
payload bytes at 1 GiB. These are lower prototype limits than the release contract.
slice pack creates a new output file exclusively, after validating the payload. It
emits canonical metadata, sorted inventory members, normalized POSIX tar headers,
and one zstd frame at level 3. Its JSON output records the packer and zstd version;
this is not signed provenance. Existing output is never overwritten. A write or
flush failure may leave a partial new output file; it is not registered or installed.
slice inspect verifies the container, canonical descriptor/manifest bindings, member
order, checksums, payload hashes and relocation bytes, and archive termination.
It rejects extra members, hardlinks, special files, special mode bits, concatenated
frames, and trailing compressed bytes. The current tar subset uses short ASCII
names (at most 100 bytes including payload/); pax extension and prefix headers
are refused. Packing and inspection cap compressed input/output at 16 MiB and
expanded tar at 64 MiB. Decoding uses an 8 MiB window ceiling and a cooperative
five-second check. The archive is buffered in memory; these are not total process
memory or hard execution deadlines.
All artifact/container results report authenticated: false. These are local
inspection tools and do not extract into a prefix or authorize installation.
TUF, package signatures, index/recipe agreement, descriptor-based extraction,
relocation application, and installed receipts remain pending. Same-user filesystem
races and hostile-prefix access are outside this adapter's guarantees.
Run a complete portable packing demonstration from the checkout:
python tools/demo-slice.py build/windows-clion/aslice.exe
Run the package lifecycle
After building the development image, run the complete demonstration:
docker run --rm --network none --entrypoint sh aslice-prototype /src/tools/demo-prototype.sh
The demonstration creates a temporary prefix, installs hello and its greeting
dependency, executes the installed program, upgrades both, rolls back, verifies
the store, uninstalls hello, and removes its orphaned dependency. It prints
hello 1.0.0: dependency 1.0.0, then version 2.0.0, then version 1.0.0 again.
Its temporary prefix is removed on exit.
To explore manually inside the container:
docker run --rm -it --network none --entrypoint sh aslice-prototype
/build/aslice dev fixture init --prefix /tmp/aslice-play
/build/aslice dev fixture install hello --prefix /tmp/aslice-play --catalog /src/tests/fixtures/prototype/catalog-v1.json
/tmp/aslice-play/profiles/default/bin/hello
/build/aslice dev fixture list --prefix /tmp/aslice-play
Commands also include search, info, plan, why, leaves, history, and
verify. Mutations accept --dry-run except initialization. plan is always
read-only. Prefixes must be new, private, and explicitly selected. A marker
distinguishes these disposable prefixes from future production installations.
The fixture catalog has its own aslice-prototype-1 format, with inline text
payloads. It is neither an authenticated index nor a .slice archive. It uses
the portable version and constraint implementation described above. Namespaces,
OS floors, and v1/v2/v3 selection are exercised. Initialize
with --target-os and --flavor to simulate a target; these options do not detect
host capabilities or establish package executability on that target.
The bounded backtracking solver is an experiment, not the specified PubGrub implementation. Fixture identities hash normalized fixture JSON, not production RFC 8785 artifact manifests. Files are imported into separate read-only store trees and generations link to exact fixture identities. Case-insensitive ASCII path collisions exclude that candidate combination and allow backtracking; a solve refuses if no collision-free combination exists. Install prefers existing selections; upgrade selects the newest compatible requested closure. Uninstall retains orphaned dependencies until autoremove. All complete generations are retained; garbage collection is absent.
Generation activation uses a flushed symlink rename under a prefix lock.
ASLICE_PROTOTYPE_FAILPOINT=before-switch and after-switch exercise the two
activation boundaries. Prepared generations may remain after a failed activation;
history lists available generations, not a proven committed operation log.
These checks do not establish power-loss recovery. Signed repositories, archive
extraction, TOML/Starlark builds, full variant planning, relocation, ABI checks, privilege
separation, production journals, services, machine setup, and self-update remain
unimplemented. The fixture lifecycle currently uses generation JSON rather than
the production state database. Same-user filesystem races and hostile-prefix
recovery are not supported by this adapter.
CLion on Windows
For CLion's bundled MinGW, install matching development headers and libraries:
powershell -NoProfile -ExecutionPolicy Bypass -File tools/bootstrap-windows.ps1
The script pins vcpkg to the revision in vcpkg.json, disables its telemetry, and
installs JSON, OpenSSL, zstd, and tl-expected 1.3.1 into build/windows-deps/x64-mingw-static. CMake detects
that location for MinGW builds, including the ordinary CLion Debug profile.
Reload the CMake project after installation. The windows-clion CMake preset
also names the bundled compiler and Ninja at the default per-user CLion location.
For another installation location, pass -ClionRoot to the bootstrap and use
CLion's configured toolchain instead of that preset.
CMake copies the bundled MinGW runtime DLLs beside the executables, so the
development build also runs from an ordinary terminal without CLion's compiler
directory on PATH. Keep those DLLs with the executable when moving this build.
OpenSSL stays a real required dependency in Windows builds; its declarations and portable callers are compiled and linked. The same holds for zstd. Native Windows builds support CLI, version/resolver, manifest, container, and query tests. The POSIX filesystem lifecycle runs in Docker/WSL; a native Windows invocation reports that limitation. A CLion WSL or Docker toolchain can compile and debug the POSIX implementation as well.
An installed JSON package is preferred; if absent, CMake downloads the checksum-pinned 3.12.0 release. Linux local builds require OpenSSL development headers and libraries, plus the zstd development package. These host development dependencies do not establish the release linkage or macOS toolchain contract.
CMake embeds the SQL from docs/sqlite into the executable at configure
time and reconfigures when those files change. The executable needs no checkout,
prefix, database, or network to print a schema. It rejects unsupported arguments
before printing SQL, with exit 2. Output failures return 1; successful output
returns 0. Examples put role selection after schema; the existing
aslice db --role ROLE schema ordering is also accepted.
Docker Desktop
Use Linux containers and run from the repository root:
docker build -t aslice-prototype .
docker run --rm aslice-prototype --version
docker run --rm aslice-prototype db schema --role publisher
docker run --rm --entrypoint ctest aslice-prototype --test-dir /build --output-on-failure
The build downloads Ubuntu packages for LLVM 22 (compiler, formatter, and analyzer), libc++, CMake, Ninja, and Python. CMake downloads SQLite 3.51.3 and checks both the pinned archive SHA-256 and the published source SHA3-256 before compiling it as a static library. Extension loading is compiled out. Compiler, VFS, and macOS release qualification remain pending; the source pin alone does not establish a release build. The Dockerfile is a development environment with distribution-managed versions; it is not a pinned release toolchain. Rebuild the image after source changes.
Local build
On a Linux development host with Clang, libc++, CMake 3.20 or newer, Ninja, and Python 3 installed (network access is required for the initial SQLite download):
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_CXX_FLAGS=-stdlib=libc++
cmake --build build
cmake --build build --target format-check tidy
ctest --test-dir build --output-on-failure
./build/aslice db schema
For an offline build, extract the same SQLite amalgamation archive into a local
directory and add -DFETCHCONTENT_SOURCE_DIR_SQLITE=/path/to/sqlite-amalgamation-3510300
to the configure command. The source checksum remains mandatory. Initial downloads require network access. The expected library is pinned to 1.3.1
with its reviewed archive checksum; an installed matching package is preferred.
CTest runs the compiled executable from temporary directories, compares all six schemas to the specification, executes each in SQLite, and tests argument refusals. Python's SQLite library creates test fixtures only; query-engine tests execute against the pinned C library.
Query engine
The internal aslice_db library reads a supplied standalone snapshot in memory.
It checks the application ID, role/schema version, and identity against an
independently supplied instance and owner. It uses defensive mode, query-only
connections, disabled trusted schema, an SQL authorizer with a function allowlist,
and a read-only deserialized database. Virtual tables, writes, PRAGMAs, transaction
control, unbound parameters, EXPLAIN, and non-whitespace statement tails refuse.
SELECT, read-only CTEs, and ordinary views are tested.
Queries have ceilings of 5 seconds, 10,000 rows, and 16 MiB of serialized data. The engine buffers output and returns an explicit error on failure, discarding partial rows. Its JSON data object preserves duplicate column names, nulls, base64 BLOBs, and large integers as decimal strings. Invalid UTF-8 and non-finite floating-point values refuse instead of silently changing data. Limits may be lowered for tests.
Prototype resource limits also cap snapshot input at 32 MiB, SQLite heap at 64 MiB, SQL at 64 KiB, columns at 128, expression depth at 100, compound SELECTs at 10, and compiled VM instructions at 25,000. Output buffering uses separate C++ memory. The SQLite heap ceiling is process-wide, so this component belongs in a dedicated inspection process. A progress handler bounds SQLite execution; it is not a hard real-time deadline for every allocation or built-in function.
tests/query_driver.cpp supplies a test-only adapter for synthetic snapshots.
It does not authorize access to an installation. The public aslice db query
command remains unavailable until owner-approved snapshot export, provisioning,
filesystem ownership checks, process isolation, and the command envelope exist.
The engine is not a database health check or a recovery authority.
macOS validation
Linux execution does not establish the macOS 10.11–12 contract. The release build still needs the self-hosted toolchain, static libc++, the v1 CPU floor, and execution on each claimed OS. Installation, recovery, trust, and self-update remain unimplemented.
The supplied WSL walkthrough
now reports that its procedure no longer works. Use
OSX-KVM as a separate VM investigation:
first verify KVM access and guest creation, then QEMU/OpenCore and the intended
guest OS. A visible /dev/kvm alone does not prove a usable macOS guest. No VM,
installer, SDK, or Windows/WSL configuration change is part of this prototype.