30. The Kernel Requirement Decoder Follows the Schema Owner¶
Date: 2026-10-17
Status¶
Accepted. Supersedes decision 4 of ADR-0021.
Context¶
cordanaLLM/Aegis-OS owns the schema aegis.p01-nucleus.kernel-requirement.v1. Its decoder is KernelRequirement::decode in the crate aegis-fabrica-defs, and it publishes a JSON Schema of the payload as build/kernel-requirement.schema.json. imago writes its own requirement in that shape (kernel/requirement.json) and nucleus reads both.
ADR-0021 decision 4 gave imago its own set of bounds, written before the owner had fixed its rules. Issue #48 records the result: the two decoders disagreed on 30 of the 80 rows that tools/kernel/aegis_conformance.py builds from the owner's payload.
- imago refused what the owner accepts: the states
presentandabsent, the optionalartifactobject, a:in the correlation id, a release such as7or7.3-rc2, arequired-byof up to 128 characters, a repeated architecture, and four architectures. - imago accepted what the owner refuses: a target release older than the minimum or empty,
riscv64or any other architecture outsidex86-64andarm64, a lowercase or digit-firstrequired-byand the bare prefixREQ-, 65 features, a 65-byte symbol, a member named twice or in another case, and a payload above 16384 bytes.
A requirement imago validated could therefore be refused by nucleus, and the reverse.
Aegis-OS decision D103 (2026-09-29) made required-by schema-generic: any identifier of an upper-case letter followed by upper-case letters, digits and -. imago's flavor-tier ids such as FLAVOR-K8S-NODE are valid under it.
Decision¶
- The owner's decoder at Aegis-OS commit
e915c654e6c1e497c976c02ae977067516575552is the reference.pkg/kernelaccepts and refuses exactly what it does. The bounds, character sets and allow-lists inpkg/kernel/requirement.goare the owner's: payload of at most 16384 bytes; correlation id of 1..128 characters of[A-Za-z0-9._:-]; 1..4 architectures fromx86-64andarm64, repeats allowed; releases of 1..64 characters of[0-9A-Za-z._+-]starting with a digit;target-releaseandmodule-abiabsent,null, or a release, never empty; a target release not older than the minimum, compared on the leading dotted numeric components like the owner; 1..64 features with distinct symbols of at most 64 bytes; the statesbuilt-in,module,presentandabsent;required-byof 1..128 characters as D103 defines it, but notREQ-alone; and an optional top-levelartifactwith a 64-character lowercase hexdigestand an optionalsignatureof up to 256 lowercase hex characters of even length. - Strict decoding refuses what the owner's JSON layer refuses.
decodeStrictdecodes withencoding/json/v2, which matches member names case-sensitively and refuses a duplicate member; it also refuses unknown members, a second document and an oversized payload. The kernel artifact manifest of ADR-0021 decision 1 shares this decoder and is decoded the same way. - imago keeps its flavor-tier ids.
kernel/requirement.jsonkeepsrequired-byids of the formFLAVOR-<TIER>.TestRepositoryRequirementDecodesholds them to that prefix. - The owner's files are vendored at the pinned commit.
pkg/kernel/testdata/aegis/holds the owner's payload, its reference payload and its JSON Schema, copied byte for byte frombuild/at the pinned commit, under the owner's EUPL-1.2 notice (REUSE.toml). - Agreement is held by a recorded corpus.
tools/kernel/aegis_conformance.pybuilds 80 rows from the vendored payload: one-field edits, each bound and the value just past it, and raw texts the JSON layer must refuse. Run with--decoder, it records the owner's verdict on every row inpkg/kernel/testdata/aegis/conformance.json, together with the commit.pkg/kernel/conformance_test.goreplays every verdict against the Go decoder.tests/test_kernel_conformance.pyreplays them against the vendored schema, lists the five rows a JSON Schema cannot decide with the rule each needs, and fails when the corpus differs from the rows the tool builds. - A new owner commit is adopted by regenerating the corpus. Moving the pin means copying the three files from the new commit, building the owner's decoder there, running the tool with
--decoderand--aegis-commit, and changing the decoder until both replays pass.
Consequences¶
- Positive: a requirement imago validates is one the owner's decoder accepts, row for row.
imago kernel requirement validate kernel/requirement.jsonand the owner's decoder both accept the repository's requirement. - Positive: a change on either side shows as a failing row with the row's name, not as a refusal at
nucleus. - Negative: the owner's bounds are tighter than imago's were (64 features instead of 512, 4 architectures instead of 8). A requirement that outgrows them needs a change at the owner first.
- Negative: the artifact manifest is now decoded case-sensitively and refuses a duplicate member. No producer writes either, but a hand-edited manifest that relied on case-insensitive matching is refused.
- Neutral: regenerating the verdicts needs a Rust build of the owner's crate. The replays run offline from the committed corpus.
References¶
- ADR-0021: the kernel artifact contract with
cordanaLLM/nucleus. - ADR-0028: the bound on every error text, which the new checks keep.
- Aegis-OS
docs/build/product-input.mdat the pinned commit: decision D103 onrequired-by. - Fleet answer ledger, ids
imago-48-requirement-schemaandimago-48-pin-refresh, 2026-10-17: conform at Aegis-OSe915c65, keep the flavor-tier ids, vendor the fixtures and the schema at that commit (paraphrased).