Skip to content

A composition-only layer installs, and its includes land beside it - #191

Merged
avrabe merged 1 commit into
mainfrom
fix/install-composition-only
Sep 24, 2026
Merged

avrabe merged 1 commit into
mainfrom
fix/install-composition-only

Conversation

@avrabe

@avrabe avrabe commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Two defects, both found building the covalent realm — the worked multi-realm
example: one pin over the PulseEngine toolchain and the bytecodealliance
component tools.
It deposited and signed, and then neither command that had
to read it worked.

1. Install refused a layer made only of includes

layer 2026.09.0 carries no entry for platform x86_64-unknown-linux-gnu —
refusing to install a wrong-architecture toolchain

The fail-closed platform rule is right and stays. It asked the wrong
question: matched == 0 && !manifest.entries.is_empty(). A composition edge is
not a payload — it names another layer's manifest and the fetch loop
deliberately skips it — so a pure composition has zero entries that could
ever match a platform, and "none matched" is not evidence of a wrong
architecture. The check now counts payload entries.

a_layer_with_nothing_for_the_host_platform_fails_closed still passes. That is
the point: the rule is unchanged, only its question.

This is the deposit-side defect one stage down — deposit learned that a
composition-only layer is not an empty layer (#171); install had not.

2. The included realms nested inside the composing one — mine, from #177

fetch_included_layer used realm.effective_root(ctx.store.root()). That maps
a base root to <base>/realms/<fingerprint>, and ctx.store.root() is
already a partition, so a transitive install wrote:

realms/<covalent>/realms/<pulseengine>/…      <- nested
realms/<covalent>/realms/<pulseengine-wasm>/… <- nested

Install printed "fetched composed layer 2026.09.12 from realm 'pulseengine'"
and succeeded; the very next command said the layer was not installed, because
the composition walk looks at siblings.

ProjectCtx now carries base_root, named for what it is, so a caller cannot
reach for the wrong root without noticing which field they typed.

The result

composition: 3 layers —
  2026.09.0  (verified against realm 'covalent')  [pinned]
  2026.09.12 (verified against realm 'pulseengine')
  2026.09.0  (verified against realm 'pulseengine-wasm')

66 payload(s): 59 DISPATCHED, 7 HELD
  wac · wasm-tools · wit-bindgen-wrpc · wkg  →  pulseengine-wasm
  rivet · spar · synth · …                    →  pulseengine

Neither defect was reachable by unit test: one needs a layer with no payloads,
the other needs two realms in one store. Both are one command in the product.

Control: reverting the emptiness test to count every entry fails the new test.

Gate: fmt · clippy -D warnings · 1038 tests, 0 failed · trace-gate OK.

(trace-gate also caught me inventing REQ-COMPOSEONLY-001 from a PR title —
the marker now names REQ-COMPOSE-001, which exists.)

🤖 Generated with Claude Code

https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu

@avrabe
avrabe enabled auto-merge (squash) September 24, 2026 17:39
Both found building the `covalent` realm — the worked multi-realm example: one
pin over the PulseEngine toolchain and the bytecodealliance component tools.
It deposited and signed, and then neither command that had to read it worked.

FIRST: install refused it outright.

  layer 2026.09.0 carries no entry for platform x86_64-unknown-linux-gnu —
  refusing to install a wrong-architecture toolchain

The fail-closed platform rule is right and stays: a fully-stamped layer with
nothing for this host must never install looking complete. It asked the wrong
question. A composition edge is not a payload — it names another layer's
manifest and the fetch loop deliberately skips it — so a pure composition has
ZERO entries that could ever match a platform, and "none matched" is not
evidence of a wrong architecture. The check now counts payload entries rather
than all entries. `a_layer_with_nothing_for_the_host_platform_fails_closed`
still passes, which is the point: the rule is unchanged, its question is not.

This is the deposit-side defect one stage down. `deposit` learned that a
composition-only layer is not an empty layer; `install` had not.

SECOND, and mine: the included realms were nested inside the composing one.

`fetch_included_layer` computed the included realm's partition with
`realm.effective_root(ctx.store.root())`. That function maps a BASE root to
`<base>/realms/<fingerprint>`, and `ctx.store.root()` is already a partition —
so a transitive install wrote `realms/<covalent>/realms/<pulseengine>/…`.
Install reported "fetched composed layer 2026.09.12 from realm 'pulseengine'"
and succeeded; the very next command said the layer was not installed, because
the composition walk looks at siblings.

`ProjectCtx` now carries `base_root` explicitly, named for what it is, so a
caller cannot reach for the wrong root without noticing which field it typed.
The partitions are siblings again, and the composition installs, inspects and
verifies:

  composition: 3 layers —
    2026.09.0  (verified against realm 'covalent')  [pinned]
    2026.09.12 (verified against realm 'pulseengine')
    2026.09.0  (verified against realm 'pulseengine-wasm')
  66 payload(s): 59 DISPATCHED, 7 HELD

Neither was reachable by unit test: one needs a layer with no payloads, the
other needs two realms in one store. Both are one command in the product.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019TNtfRjLNhEz82G2ggeeNu
@avrabe
avrabe force-pushed the fix/install-composition-only branch from 280857f to c3c9af7 Compare September 24, 2026 17:39
@avrabe
avrabe merged commit 859d33e into main Sep 24, 2026
26 checks passed
@avrabe
avrabe deleted the fix/install-composition-only branch September 24, 2026 18:27
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