chore(deps): Bump clap from 4.6.1 to 4.6.6 - #267
Closed
dependabot[bot] wants to merge 1787 commits into
Closed
Conversation
… and two fixtures A generated component crate that does not compile is the failure mode this whole face exists to prevent, and every other gate is blind to it: a WIT package can resolve, encode and validate perfectly while the glue implementing it names a trait method that does not exist. So `component_crate_builds_for_wasm32_wasip2` generates to scratch and really builds for the target, asserting the artifact carries the component-model preamble (layer 1) so a core-module build cannot pass vacuously. Nested cargo, memoized per generated-crate content hash by the gate cache; a missing target is reported as a provisioning problem naming the `rustup target add`, never as a broken emitter. The smoke narrows the RUST crate's `crate-type` to `rlib` in its scratch copy. That crate's `cdylib` output exists for wasm-bindgen's `wasm32-unknown-unknown` target; asking the wasip2 linker for it is not something the component face needs (the guest consumes the rlib) and `wasm-component-ld` crashes on it for some specs. Narrowing it keeps the gate's verdict about the crate under test. The two emission invariants get structural pins rather than prose: no `borrow_mut` may share a statement with an argument's `.get::<Wit…>()`, plus a positive assertion that the recursive fixture DOES materialize its `list<borrow<node>>` argument — without which the first assertion could pass on glue that had stopped emitting the shape at all. Getters are pinned to clone the field into a fresh handle, in both the scalar and the per-element form. `tests/component-multifile` is the multi-interface shape with NO externs, which is what lets the build smoke compile it: `tests/multifile`'s own rust crate needs a hand-written extern re-export before it builds at all, so it can gate the projection but never the link. It is where two `Guest` impls under one `export!`, a cross-interface `borrow` parameter and an `own` handle minted for another interface's resource are checked at link time. `tests/component-cycle` is the end-to-end half of the cross-scope cycle detector: two scopes referencing each other with no type-level recursion anywhere — the case a type-level detector would miss — asserted to generate fine on the rust face and to hard-error under `--component`. Neither fixture dir carries a top-level `input.cddl`, so neither is visible to the corpus axis gate, which keys on exactly that file. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Each is a spec a user can legitimately write whose emitted guest crate fails to build, and none was reachable from the fixtures. A NonEmpty TABLE parameter crosses as `list<tuple<K, V>>` like every other despecialized collection, and the guest re-enters the invariant through a `try_into` on the vec it collected — but `NonEmptyMap` had only the map door, so the vec never converted. It gains the vec-of-pairs door its `NonEmptyPairMap` twin already had, delegating to the single map door so the empty-map refusal error stays identical on every path. A RECORD's `new` is fallible when a mandatory field carries a value bound, and that verdict is reached by a different rule from the `@newtype` wrapper's: the wrapper's rides the IR, the record's is derived per emission. The glue consulted only the first and bound a `Result` where the rep expects the value, so it now reads the rust face's own rule through the mirror `emit_tests` already shares with `records.rs`. A type the rust face declines to give a `Deserialize` impl — an array struct whose optional field is CBOR-ambiguous with what follows it — still got a `from-cbor-bytes` on both sides of the macro, naming a trait impl that does not exist. The projection now takes the no-deserialize set as an input and drops the member, mirroring the wasm face's own fork. That set is a GENERATION-time verdict, so it arrives from the caller: the finalization-time collision detector projects with an empty set, which is the safe direction (dropping a member can only remove a collision), and `api::wit_strings` filters the full producer rather than shortcutting to the projection, so what the gates pin is what the tool ships. The first two are pinned by compilation: `tests/component-core` gains a NonEmpty table and a value-bounded field, so the wasip2 build smoke is the oracle. The third is pinned per-type, both halves, on a scratch spec. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…t asks what the boundary dropped Every other component gate judges what was emitted against itself: the four-stage validity gate resolves, encodes and validates the `.wit`, and the wasip2 smoke compiles whatever glue implements whatever that `.wit` declared. A member missing from BOTH halves therefore yields a package that resolves, validates and builds, and nothing can see it. This is the sibling of `wasm_api_parity` for that boundary, with the same one-directional question and the same ledger-with-a-two-way-guard. Two deltas from the wasm sibling. It parses EVERY per-scope rust file rather than one `mod.rs`, because one WIT interface per input file is what the component face is for. And its WIT half goes through the pinned `wit-parser`, so what is compared is the surface the toolchain sees, against a rust->WIT name map that is a pure function of the rust name plus the single `new` -> `constructor` mapping. The projection does carry the pairing, but reading it would make this an intent check where the whole point is an output check. The ledger opens with the `Int` value-type class — a `variant` has no member namespace for `new_uint`/`new_nint` to land in — and `IntError`, the rust-only error enum minted beside `Int`, which is not an IR type at all and has nothing to be on a face that carries every failure as a string. Both are live findings, so the resurfaced guard has something to reconcile from the first run. Non-vacuity is guarded three ways: a floor on the obligations compared, a stray-key guard over both generated trees, and an axis assertion that every fixture `component_tests` compiles or validates is differentialled here too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ated artifact that is not rust Two profile-limited `WHOLE_PROGRAM_CASES` rows under `--component=true`: the single-scope type corpus and the multi-INTERFACE directory input. They capture the whole fourth crate — its manifest, its seed-once root and its glue — and the emitted WIT package, which is the only generated artifact that is not rust and so had no byte-level pin anywhere. They also extend `generated_files_start_with_header` at no cost: its sweep is `WHOLE_PROGRAM_CASES` filtered by `is_header_stamped_path`, which already knows about `.wit`. Thirty new snapshot files, no existing snapshot changed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pelled as unwrap The tier's clippy gate runs --all-targets with -D assertions_on_result_states, so assert!(x.is_ok()) in a test is a compile failure, not a style nit. timings.json carries the registry's new component gate rows, per the tier's own commit-it notice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… might have The WIT face carries two `--component` refusals, and each was judging a surface the emitted package does not have. The cycle detector recorded a NAMED COLLECTION's own ident where the projection resolves through it to the element. Both directions of that disagreement invent edges: a holder of an `a::names` whose element lives in `c` got `b -> a` instead of the `b -> c` the emitted `use` carries, and the collection RULE — which surfaces no WIT type at all, so it owns no interface — contributed `a -> c` on top. Either one closes a cycle in a spec whose WIT resolves perfectly, and the resulting refusal names scopes the package never links, which a user cannot act on. Measured on this worktree before the fix: `a::names = [* text]` held by `b::rec` beside `a::holder -> b::rec` was refused as "the scopes `a`, `b` reference each other", and so was the collection-rule-only variant. The walk now resolves through exactly as `map_named` does (with the same re-entry guard, so a self-referential collection terminates rather than overflowing the stack) and skips collection rules exactly as `project` does. A real cycle closed through a collection is still refused and now names only the two scopes the `use` graph links, which is a strictly better message. The name-collision detector projected with an EMPTY no-deserialize set, because at IR finalization the rust face has not yet decided which types get a `Deserialize` impl. That superset over-reports for real: a type with no `Deserialize` impl AND a field named `from_cbor_bytes` was rejected for a collision between a getter and a `from-cbor-bytes` static the tool never emits. It moves to generation time, where the verdict exists, and surfaces through the graceful error channel `generated_files`/`export` already carry — checked before any write, so a refusal never scatters half a tree. The cycle detector STAYS at finalization: it needs no verdict, and a spec with both reports the cycle first, which is correct — a cyclic package has no resolvable WIT to hold collisions. The three pinned collision messages are byte-identical. Both fixes carry a negative control, because "agree with the projection" and "consult the verdict" are each satisfiable by a detector that sees nothing: the real cycle through a collection is still refused, and the same `from_cbor_bytes` field on a DESERIALIZABLE type is still refused with the pinned message. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Type and group choices were the largest excluded class on the WIT face. They now project to a `resource` with NO constructor — there is nothing to build without picking an arm — plus one `new-<variant>` STATIC per arm, a `kind` discriminant returning a new `<name>-kind` enum, and one `as-<variant>` per arm that carries data. A fixed-value arm gets a nullary static and no getter: it has no payload for one to return, and `kind` is already the whole answer for it. All three families spell `<variant>` from ONE conversion of `EnumVariant::name_as_var()`, which is also the source of the rust `new_<variant>` the guest calls, so a drift between the WIT name and the rust one is not expressible. The parameters mirror the rust constructor per arm shape rather than per enum — a group-choice arm naming a record takes that record's mandatory fields, an inlined arm takes its non-fixed field, everything else takes the variant's own type — because the guest calls that constructor positionally. Fallibility is carried the same way: the rust constructor's own is projected beside the member's, which is strictly wider (a despecialized `[+ T]` arm makes the STATIC fallible over an INFALLIBLE rust constructor, so the glue must not `?` it). The `kind` / `as-` arms are spelled by `enums::EnumVariantInRust`, widened to `pub(super)` rather than re-derived. That fork is per VARIANT, not per enum — under `--preserve-encodings` a primitive arm becomes braced while a `Rust`-typed arm in the same enum stays a tuple — and a second derivation would be a `match` that compiles in one posture and not the other, in generated code the user cannot edit. The guest never names the rust `<Name>Kind`, which exists only under `--wasm`. The `<name>-kind` enum lives in the interface's one flat type namespace, so it is collision-checked like any other name; that makes it the shape the `@name` remedy can be PROVEN against. Every collision message names `@name` as the fix and nothing proved it worked, so `tests/component-rename` now generates only because of two `@name`s — one moving a field off its resource's own name, one moving a group-choice arm struct off a choice's `-kind` enum — with both un-renamed twins asserted still refused, since a fixture that generates proves nothing about a remedy unless what it remedies still fails. `component_wit_excludes_a_type_choice_and_everything_that_reaches_it` is re-pointed at the EXTERN class and renamed: choices are projected now, and the exclude-and-record path must keep a live test rather than lose one when its last subject ships. Item F (extern bridging) will have to point it somewhere else again. Verified on this worktree: `cargo test --bin cddl-codegen component` 35 passed / 0 failed, including the wasip2 build smoke over the new choices fixture (re-run with GATE_CACHE=0 so the cell actually built); snapshot tests 46/0 with only the new `component_choices` rows added and no existing snapshot byte changed; `wasm_api_parity` 13/0; clippy `--all-targets` clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s on the fact that owns it The component face routed every boundary parameter off one bit, `validates`, which is the UNION of three unrelated facts: a despecialized collection, a value window, and CDDL `any`. Two defects fell out of the conflation, both invisible to every WIT gate because a bounded setter's `result<_, string>` reads identically either way. A bounded setter checked NOTHING while declaring itself fallible, leaving this face strictly weaker than the wasm one, which emits the range check at the same site. And `materialize`'s `validates && is a list` sent a merely-BOUNDED collection through the despecialization door: for `[2*5 uint]` that resolves to `Vec<T>`'s identity `TryFrom` (`Error = Infallible`), which compiles while checking nothing, and for an inline bounded map it named a `TryFrom<Vec<(K, V)>> for BTreeMap` that does not exist at all — glue that did not compile. So `WitParam` now carries `rust_type: Option<RustType>` (R3: the projection carries the rust fact rather than the emitter re-deriving it) and the two doors read the type directly. `wit_param_despecialized` is the narrow predicate for the `TryFrom` door; `bounds.rs` gains `component_bounds_check_line`, which walks the SAME decision tree as `value_bounds_check_line` through the same condition owners (`reject_cond`, `bounds_check_expr_rust_type`, `bounds_check_expr_non_negative`, `nint_bounds_to_u64`, `float_accept_cond`, `float_literal`) and forks only the `Err(..)` construction — a second condition spelling is the drift the bounds machinery was consolidated to prevent. Two spellings there were probed rather than assumed. `DeserializeFailure` implements no `Display` (only `DeserializeError` does), so the failure is lifted through `DeserializeError::from` before it reaches the guest's `Display`-bounded `err` helper. And the check is emitted against the BOUNDARY value, ahead of the conversion, because a `.len()` read off a `collect()`-bound local is E0282 — confirmed by compiling the shape — the container type being pinned only by the assignment that follows. That is also exactly where the wasm face puts its own check (`records.rs`, ahead of `from_wasm_boundary_clone`), so the two stay parallel. The window is a SETTER's job alone: every other door hands its parameter to a rust constructor that range-checks and whose `Result` the guest already unwraps. Externs and raw-bytes types get bridging resources, so one hand-written type no longer takes every record that reaches it out of the WIT. An extern carries the cbor seam over the `Serialize`/`Deserialize` its contract already requires. A raw-bytes type does NOT: its contract is `RawBytesEncoding` and nothing requires `Serialize` of it — the emitted extern-interface self-check asserts `_assert_raw_bytes` and no `_assert_serialize`, and the generated serializer reads it through `to_raw_bytes()`/`from_raw_bytes()` — so it carries a `to-raw-bytes`/`from-raw-bytes` seam instead. This deviates from PLAN §4's last row, which says every such type bridges "via the rust Serialize/Deserialize the extern contract requires"; that is true of `Extern` and false of `RawBytesType`, and a cbor bridge there would name a trait impl that need not exist. Both halves of the raw seam are unconditional, since `RawBytesEncoding` is one trait declaring both methods. A generic extern BASE is skipped from the projection the way a named collection is — it names no concrete type, so a resource over it would be a resource over nothing — keyed on `generic_extern_base_idents()` rather than the narrower `generic_instance_bases()` the wasm glue uses. Its INSTANCES are bridged under the instance ident and reached through the `pub type <Instance> = <Base><Args>;` alias the rust crate emits. A bare reference to a base is excluded WITH a reason naming the shape, and the same set is filtered out of the cycle detector's edges so a skipped ident can close no cycle. Non-extern generic instances are monomorphized before generation and need nothing at all — asserted by fixture, not prose. `component_wit_excludes_an_extern_and_everything_that_reaches_it` is re-pointed at the generic extern base, which is the class still unprojectable now: the exclude-and-record path must keep a live test rather than lose one when its last subject is implemented. Verification (targeted; `check.ts` was not run at any tier). `cargo test --bin cddl-codegen component`: 39 passed, 22.4 s, including the wasip2 build smoke over the new bounds fixture and `component_api_parity`, which reported no new asymmetry — a user-owned extern emits no rust `pub struct`, so it owes the differential nothing. `snapshot_tests`: 46 passed, 21.5 s, and the only snapshots written were the new `component_extern` row — no existing pin moved. `wasm_api_parity_axes_and_pins_are_live`: pass. `cargo clippy --all-targets`: clean. `tests/component-extern` cannot enter the build smoke (its rust crate names user-owned types, the same reason `tests/multifile` is absent), so its glue was compiled once by hand against written `Ext`/`Raw`/`ExternGeneric<T>` definitions: `cargo build --target wasm32-wasip2` finished in 11.3 s with no errors, and the bounds fixture independently in 11.7 s. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…es whose contract carries it Three things land together because the third is what the second makes reachable. **`to-canonical-cbor-bytes`.** Under `--preserve-encodings --canonical-form` every resource carrying the cbor seam also carries the canonical re-encoding door, bridged through `Serialize::to_canonical_cbor_bytes`. The gate is that flag pair and not a choice: the method is declared on the `Serialize` trait, and the runtime composes `Serialize` from exactly `serialization_preserve_force_canonical.rs` — every other posture composes a `ToCBORBytes` that declares `to_cbor_bytes` alone, so a row emitted there would name a method the user's crate does not have. `bytes_members` owns the row, so records, `@newtype` wrappers, choices and extern bridges all get it from one place, and the raw-bytes bridge (which has no cbor seam at all) still gets nothing. The glue names `Serialize` literally rather than reusing the emitter's `to_bytes_trait()` fork: the two agree by construction here, and naming the trait that OWNS the method is what keeps the glue honest if either moves. **The JSON seam.** Under `--json-serde-derives`, per-resource `to-json` / `from-json` plus the free `cbor-to-json` / `cbor-from-json` on the `any-cbor` alias, emitted as `serde_json` calls over the serde impls the rust crate derives under the same flag. Two decisions worth the words: - It has its OWN owner (`json_members`) rather than joining `bytes_members`, so it reaches only the types the tool DEFINES. Sharing the cbor owner with the extern bridge is legitimate — the extern contract already imposes `Serialize`/`Deserialize` and the emitted `extern_interface_check.rs` asserts them — but nothing imposes serde on a user-owned type, so a `to-json` on a bridging resource would name a trait impl that need not exist. That is the compile-error-in-generated-code class the `no_deserialize` fork and the raw-bytes seam split both exist to prevent, reached a third time. Probed rather than assumed: the emitted self-check for `tests/component-extern` asserts `cbor_event::se::Serialize` / `Deserialize` / `RawBytesEncoding` and no serde bound, and the wasm face emits no wrapper for an extern at all, so there is no precedent to copy. - `to-json` is `result<string, string>`, DEVIATING from the plan's infallible `string`. The wasm face's own `to_json` is `Result<String, JsError>` and rendering genuinely can fail — the runtime's `AnyCbor` serde fragment documents a "key must be a string" failure for a non-string-keyed map, which reaches any type holding one. Parallel-with-documented-deltas means fallible here. The component manifest gains `serde_json` under the same flag, set-or-REMOVE, at `ops_for_wasm`'s version and features verbatim (`float_roundtrip` included, because `from-json` parses through `serde_json::from_str` and has to round-trip `f64` bit-for-bit). It does NOT gain `serde` or `serde-wasm-bindgen`: the emitted guest names neither crate, and `to_json_value` has no WIT counterpart. The dep is a flag-conditional in-code op, so the drift-gated `static/Cargo_component.toml` — which renders from the append-only log alone — is unchanged; `manifest_template_drift` passes without a re-bless. **The collision detector now walks an interface's free FUNCTIONS too.** A WIT interface's types and its free functions share ONE flat namespace: `wit-parser` refuses `name X is defined more than once` at RESOLVE, probed against the pinned 0.247 resolver. The interface-level check walked only `iface.types`, so a rule converging on a synthesized door reached the user as a parse failure against a file they did not write — the sighting this detector exists to replace. Latent for `cbor-kind` and widened by the two doors above, so it is fixed here rather than ledgered. The three pinned messages are unchanged; the only new text is the `the free function \`x\`` owner string. Coverage, since a seam that names a serialization trait is a two-crate fact no WIT gate can see: `COMPONENT_FIXTURES` gains force-canonical rows for core / choices / bounds / extern and JSON rows for core / choices / extern, which extends the wasm-posture purity invariant and the WIT-validity sweep to both postures by registration alone (both iterate that list). `PARITY_CASES` mirrors them; the differential reported only the pre-existing `Int` value-type class on the two new core labels, so serde derives and a trait method genuinely add no rust inherent surface. The wasip2 build smoke gains one row in the posture that carries BOTH seams, and a `component_json` whole-program row pins the emitted bytes including the manifest. No existing snapshot moved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ction rather than a rumour The generated rust crate declares crate-type = ["cdylib", "rlib"] for the wasm face, and on wasm32-wasip2 that cdylib can take wasm-component-ld's LLD down with a SIGSEGV. Documented on the --component row, where a user turning the face on will meet it. Every claim in the row was measured on this worktree under the pinned rustc 1.96.1: tests/component-multifile/inputs reproduces the crash with the exact signature quoted, while component-core, component-choices and component-bounds all link cleanly at exit 0 — so the row says spec-dependent instead of implying every spec crashes. Building only the component crate was probed and does NOT avoid it (cargo builds every crate-type a path dependency declares), which is why the row rules that out explicitly rather than leaving it as the obvious guess. Narrowing to ["rlib"] was then verified to build the same spec at exit 0. The fix is documented as a consuming-workspace edit and NOT emitted: the cdylib is load-bearing for --wasm, so a crate generated with both faces on needs it, and changing what the tool writes is a maintainer ruling this does not take. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lly do The message told a user to @name a top-level rule, which the comment DSL cannot rename — a remedy that cannot be followed is worse than none. The remedy is now renaming the rule in the spec, with the fact that makes it safe (rule names never reach the wire) stated inline. The test pins anchor on the message prefix, which is unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The reworded remedy landed one commit ago with this pin still on the @name tail — message and pin move together, and the previous commit shipped them apart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ere it differs
`ALL_PROFILES` grows a fourth row, `component` = `--component=true`, so every
`tests/corpus/*.cddl` fixture is exercised through the WIT projection and the
guest glue rather than only the five hand fixtures the face's own gates sweep.
`--wasm` stays at its default. The repo has already chosen that posture for this
face's whole-program snapshots; the emitted `component/wit/**` is byte-identical
between the two wasm postures for every corpus fixture, so turning wasm off buys
no coverage; and every consumer of this const hardcodes `--wasm=true` before
appending a profile's flags, where a second `--wasm` is not a last-wins override
but a clap error ("cannot be used multiple times").
The face is purely ADDITIVE — `--component=true` mints `component/**` and changes
no other emitted byte — so the corpus snapshots only `component/**` under this
profile and ASSERTS the rest byte-identical to the `default` profile's. That is
strictly stronger than a fourth copy of the rust and wasm trees: those bytes are
duplicates by construction, whereas the assertion states the invariant they would
only implicitly encode and fails the day the component face starts leaking into
the other two.
Seven consumers filter the row out BY NAME through the shared `COMPONENT_PROFILE`
constant, each with its own reason, and a liveness test fails loudly if the row is
renamed rather than letting the filters become silent no-ops. `feature_corpus_compiles`
cannot pick the row up in any case: it compiles for the HOST with hardcoded
rust/wasm `crate_subs` and no `--target`, while the component crate is a wasip2
target. Corpus-breadth component coverage therefore lands here as
`component_wit_validates_the_corpus` — the same four stages the fixture sweep uses
(resolve, encode, validate), over all 89 fixtures. It deliberately makes no
"world is non-empty" assertion: three fixtures resolve every rule through as an
alias or named collection and project an empty world, which is correct output.
Zero pins: all 89 fixtures generate, resolve, encode and validate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…, not which exist `verify.ts` writes this header, and its text now records that the `component` row of `ALL_PROFILES` is deliberately not probed on this axis. Applying the same two lines to the committed file keeps a `verify` run from surfacing a header-only diff that reads as drift; nothing below the header moves, and `build_matrix.ts --check` confirms matrix.json is unaffected (TOML comments carry no values). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sweep proved The row explains why `--wasm` stays on, and its second reason described clap as last-wins with a missing-crate failure downstream. `ArgAction::Set` is set-once: a repeated `--wasm` is refused at argument parsing, which is both earlier and louder than the failure the comment predicted. `component_profile_flags` already carried the correct rule; the two comments now agree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gate Every component gate so far judges emitted bytes. A `.wit` that resolves, encodes and validates over glue that compiles is still silent about what the boundary DOES, so this adds the gate that runs it: a real `wasm32-wasip2` component loaded into wasmtime and driven through one `#[test]` per assertion class — construction/read-back, byte-equality against the rust crate's own serialization, fallible doors returning `Err` without trapping (and the instance surviving), the three states of `option<option<T>>`, snapshot semantics in both the return and the parameter direction, the same-handle-as-receiver-and-argument case, and the `any-cbor` canonical re-encode and one-item rules. The trap TEXT is deliberately never pinned. What matters is that a trap POISONS the instance, so "still usable afterwards" is the assertion a wording pin would only approximate. The host crate is nested and gate-cache memoized rather than a dev-dep: wasmtime in the bin crate's dev-graph would tax every `local`-tier compile. It is copied INSIDE the hashed output root before the key is taken, because every input a cached cell reads from scratch must live there — a host crate parked beside the tree would serve a stale PASS forever after any edit to its assertions, and the closure audit cannot flag it. Its `bindgen!` reaches the WIT by a relative path and the artifact by an env var, so the hashed bytes stay run-independent, and the cached closure's extra verdict logic is versioned into the key as an argv marker. Measured: 81 s cold (fresh scratch root, wasmtime builds), 3 s warm (gate-cache hit), 9 s on a cache miss with the scratch root warm — which is why that root is checkout-hash keyed and kept rather than deleted. Those numbers put it at `local` tier with the test not `#[ignore]`d. The fixture is a DIRECTORY input: `tests/<dir>/input.cddl` carries a corpus-parity registration obligation and this fixture has no wasm-parity question to answer. Its `children` field is optional so the resource gets a `set-children` at all, which is what makes `x.set-children([x])` expressible. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s a consumer supplies `tests/component-extern/inputs` was validity- and snapshot-gated only, so its bridge glue was compiled by no gate at all. That is the worst place for the gap: every OTHER build-smoke row compiles a crate the tool wrote alone, while a bridge names a TRAIT on a type the tool does not define — so naming the wrong one is a compile error in the CONSUMER's crate, and nothing that reads our own output can see it. The fixture now enters the wasip2 build smoke in two rows, each paired with hand-written definitions of its extern types. They are appended into the generated crate's THIN ROOT, which is where a real consumer puts them and the only place they can go: the generator re-exports every in-crate extern with `pub use crate::<Name>;` into `generated/**`, so a definition there collides E0255 and that subtree is clobbered every regen. Written before the cell is keyed, so they sit inside the hashed root rather than beside it. Two flavors, because the CONTRACT differs by posture and that difference is the reason the second row exists: the default posture asks an extern for `cbor_event`'s `Serialize`, while `--preserve-encodings --canonical-form` makes the runtime compose its own — the trait on which `to_canonical_cbor_bytes` is declared — and the emitted `extern_interface_check.rs` asserts that one instead. The canonical row is therefore the one that compiles the `to-canonical-cbor-bytes` half of the extern's seam and proves the raw-bytes bridge, whose contract is `RawBytesEncoding` and nothing more, was left alone beside it. Verified live rather than assumed: removing the `Deserialize` impl from the defs reds the gate with E0277 on the extern and on the generic instance that reaches it. Three comments asserting the fixture could not be compiled are updated rather than left to rot, and each now says what its own half asks that the other cannot — the snapshot pins the trait a bridge NAMES and what the projection EXCLUDED, neither of which a build outcome can judge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ys what that found
`feature_corpus_compiles` structurally cannot compile this face: it hardcodes
its crate list to the rust and wasm trees and runs a HOST `cargo check` with no
`--target`, which is why the `ALL_PROFILES` component row filters OUT of it
rather than flowing into it. So corpus-breadth component compilation needed its
own gate, and this is it — `cargo check --target wasm32-wasip2` per fixture.
`check` rather than `build`, probed rather than assumed: the link is already
asserted on five representative fixtures by the build smoke, and the class that
only breadth reaches — glue naming a trait, method or macro the bindings never
minted — is a type-check failure. `cargo check` expands
`wit_bindgen::generate!` and reports every one of them.
No sharding, sized from this gate's own measurement rather than
`feature_corpus_compiles`' curve: ~10 s for the first cell, which builds the
shared dependency graph, then ~0.4 s each. 140 s cold, 97 s warm — a warm run
still pays generation and the lockfile preflight per cell, which is most of what
remains. The scratch root is flocked and kept so that graph survives; per-cell
trees are freed.
The gate immediately earned itself. Nine corpus fixtures do not compile, in four
emitter classes, all in the emitted `component/src/generated/mod.rs` and all
reproducing under either `--wasm` posture: a world exporting no interface still
emits `export!(Component);`; an interface whose only types are VALUE types still
emits `impl wit_types::Guest for Component {}`; a despecialized `[+ T]` /
`{+ K => V}` in a position no component fixture reaches `.collect()`s straight
into `NonEmptyVec`/`NonEmptyMap` instead of re-entering its `TryFrom` door; and a
`@default`ed scalar's glue treats the value as a handle. They are recorded in
`EXPECTED_COMPILE_FAIL` — guarded both ways, so a fix cannot land unnoticed and a
regression cannot hide behind a neighbour's pin — rather than left in prose,
which is what makes them a worklist instead of an anecdote.
The per-cell EXPECTATION is part of the gate-cache key, so removing a pin
re-runs the cell rather than serving a PASS recorded under the old expectation.
Fixtures whose rust crate references user-supplied code are excluded through
`integration_tests::COMPILE_SKIP`, shared rather than restated so the two corpus
compile gates can never disagree about which those are.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e, not always `wit_bindgen::generate!` mints an `export!` macro only for a world that HAS exports, and a `Guest` trait only for an interface that has something to implement. The glue emitted `export!(Component);` and one `impl <iface>::Guest for Component` per interface unconditionally, so two ordinary CDDL shapes emitted glue that could not compile for `wasm32-wasip2`: a spec whose every rule resolves through — a plain alias, a named collection — exports no interface at all (`cannot find macro export in this scope`), and a spec whose only projected type is a value type — a c-style enum — exports an interface of pure type declarations (E0405 on the `Guest` trait). The condition is asked per interface for the impl and per package for the block. Both halves were probed against wit-bindgen 0.57 rather than reasoned about: an interface with a FREE FUNCTION and no resource does mint the trait, so "has a resource" alone would have suppressed the impl this face's `any-cbor` free functions need — one compile error traded for another. What is left once the impls are gone has no possible caller: the guest type, its `export!`, the `err` funnel every fallible door reports through, the enum/`int`/`any-cbor-kind` bridges and the interface `use` aliases they are spelled against all exist to serve a `Guest` impl. So the whole block goes with them and the emitted file is the `generate!` invocation alone — dead code in a file the user cannot edit is the same thing the emitter already avoids for an unreachable match arm. The WIT surface is untouched: a world's exports live in the component type section `generate!` emits whether or not `export!` is invoked, and a value-only world built to a valid component either way (probed by building one). Pinned by three tests in the same commit, since `component_corpus_compiles` is `full`-tier and `#[ignore]`d and nothing in `fast`/`local` would catch a regression: the two spec shapes and their control, the per-interface granularity of the impl half beside an interface that does get one, and the free-function rule at the one position no CDDL spec currently reaches. Six `EXPECTED_COMPILE_FAIL` rows removed; the gate re-ran exactly those six cells (6 run, 80 cached, 93.9 s) and its resurfaced guard stayed silent. The six corpus snapshots that moved are pure deletions — 120 lines, no additions, no other fixture touched. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ts loop All 89 emitted component crates are `cddl-lib-component v0.1.0`, and cargo does not tell two of them apart across the shared target dir the gate keeps for speed: a batch that generated every fixture first and checked afterwards was measured serving one fixture's `Finished` — replayed warnings and all — for the next fixture's check, which would turn a real compile failure into a silent pass. The gate is already safe, because it generates each fixture immediately before checking it and every cell's sources are therefore newer than the fingerprint the previous cell wrote. Nothing said so, so a later refactor hoisting generation out of the loop would make the sweep vacuous without failing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e emitter and measured sizes The sibling of wasm_differences.mdx for the component face: why the boundary is resources with borrow-parameters and own-returns, why collections lost their wrapper classes and gained a validate-on-consume door, and what a consumer has to know before composing against a generated package. Every row was taken from the emitter or from a measurement rather than from the plan, and two rows differ from what the plan sketched: only OPTIONAL fields mint a set- setter (a mandatory field's value is established at the constructor and nowhere else), and there is no indexed setter at all. The size section is measured on this worktree under the pinned rustc 1.96.1, release with opt-level = "s" and the rust crate narrowed to rlib: 275,768 B for a small single-scope spec, 338,772 B for the json fixture, and 145,020 B for a one-rule spec — so the floor is the linked CBOR runtime, not the glue. wasm-opt is documented as refusing components outright at Binaryen 125, with the embedded core module's -38.2%/-42.9% quoted as an upper bound and strip = true (-23.1% / -25.8%) named as the lever that actually applies today. The 14 wasi:* import floor the phase-0 spike measured is confirmed exactly, identical across all three artifacts. The wasip2 cdylib link crash is referenced rather than restated: it is already documented on the --component flag row, and a second account of it would be a second thing to keep true. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…that would have caught them Both were found while building the component face and both reproduce with --component nowhere in sight, at master 781e6b8. The wasm face drops to_canonical_cbor_bytes: create_base_wasm_struct builds the function and never pushes it, so under --preserve-encodings --canonical-form the rust crate has the method and the wasm boundary has zero occurrences of it against four of to_cbor_bytes. The entry names the testing gap rather than the one-line fix, because the gap is the larger half: wasm_api_parity's rust-side walk reads inherent impls only, and every member of this family exists ONLY as a trait method on the rust side and ONLY as an inherent fn on the wasm side — so all six of them are invisible to it by the same structural exemption, and the component face already ships the posture-conditioned assertion the wasm face wants. A self-referential named collection aborts the tool: foos = [* foos] plus a holder overflows the stack at exit 134, after printing the recursion diagnostic. The owning family is the input panic-robustness catalog, whose neighbours bracket the shape without covering it — but that catalog runs generation in-process under catch_unwind, and an abort is not an unwind, so the fixture would take the test binary down rather than record a row. The missing system is therefore an out-of-process outcome lane with a fourth verdict, not a fixture. Each entry's reopening signal is scoped to the generalization the entry deliberately does not propose, and is checked against its own body: one silently-missing member and one hand-found abort shape are recorded, so "a second, found by another route" can still fire. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… when the consumer supplies its wit A dependency reached through `--extern-import` has no WIT projection today: its types are skipped and every consumer signature naming one is recorded as `// unexported:`. `--component-extern-wit <dep>=<path to the dep's component/wit>` opts that dependency into IMPORT MODE instead, so one dependency component instance can serve every consumer and handles interchange between them. Opt-in per dependency, because the payoff is: a dependency with no component face has no `component/wit` to point at (a hand-written crate, a stub tree), and a mandatory flag would make those ungeneratable under `--component`. Without the flag nothing changes at all, which is asserted rather than assumed. The dependency's WIT is COPIED, never re-derived — only its own run knows its `--wit-package` id and the reasons behind its `// unexported:` rows — into `component/wit/deps/<dep>/`, whose `deps/` level is required (a flat sibling `.wit` is read as part of this package and fails on package identity). It is an explicit cross-crate INPUT, the same class as `--extern-import` reading `extern-interface/<dep>/**`, and the copy's file-class comment says so in those terms; it keeps the dependency's own provenance banner rather than being stamped with this run's, which is why the `deps/` subtree is exempt from the header stamper. The copy is also where every name comes from. The consumer's `use` targets, and the `with:` rows the guest crate's `wit_bindgen::generate!` needs, are read out of the dependency's WIT rather than reconstructed from its cddl: `wit_bindgen` matches those keys against the file, and a `wit/deps` tree without the co-required `with:` map panics the macro at the consumer's build naming a key nobody wrote. Dependency values cross the guest boundary through a CBOR bytes seam — serialize on one side, `from_cbor_bytes` on the other — which is fallible, so every door touching a dependency type carries `result<…, string>`. That is the honest signature: the far side can fail on a value this crate's own serializer produced when the dependency component and the linked dependency crate disagree about a shape, a failure class that is compile-time within one crate. An imported resource's `borrow<t>` lowers to a plain `&T` rather than the `TBorrow<'_>` newtype an exported one gets, so the two glue templates are separate. A dependency type in a REPEATED parameter position is refused at generation, naming the cause: `list<borrow<t>>` over an imported resource is legal WIT that wit-bindgen's Rust backend cannot lower (E0506), so emitting it would hand the user a crate that fails to compile inside a macro expansion. A signature naming a type the dependency's WIT recorded as `// unexported:` is refused too, quoting the dependency's own reason verbatim — it parses (the name is in the extern-interface export) and only the WIT seam knows there is nothing to `use`. The config key lands with the flag so every flag stays settable from a config file; the `deps`-edge derivation is separate work. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two facts the cross-crate seam rests on are macro-expansion failures, invisible to anything that reads the emitted bytes: `wit_bindgen::generate!` PANICS on a materialized `wit/deps` tree with no `with:` map, and an IMPORTED resource's `borrow<t>` lowers to a plain `&T` rather than the borrow newtype an exported one gets. A WIT that resolves, encodes and validates says nothing about either. So the emitted consumer crate is built for `wasm32-wasip2` against a real generated dependency — three crates sharing one serialization runtime, which is the shape every other cross-crate consumer here uses and the precondition the bytes seam inherits. Nested cargo, memoized by the gate cache; 28 s for the whole suite on a cold scratch root. That build is also why the fixture dependency now splits in two. The only shape whose WIT projection FAILS — a bare reference to a generic extern base — is also not a rust type a crate can hold, so a single dependency cannot both be compiled and carry an `// unexported:` row. `dep/` is compiled and excludes nothing; `dep-unexported/` is projected and never built. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s to decide `--component-extern-wit` needs its own `:::info` block for the same reason every flag does (the docs-contract gate asserts one), but the block leads with the two decisions a reader actually faces rather than with the mechanics: which of the two dependency trees the path names — `component/wit`, not `extern-interface/<dep>` — and why the flag is opt-in at all, which is that a dependency with no component face has nothing to point at and must stay generatable. The rest is what a consumer cannot discover from its own build log: the `with:` map is co-required and its absence panics the macro in the CONSUMER's build; dependency-typed doors are fallible because the far side's decode genuinely can fail; and the two shapes refused at generation each name their cause, so a future toolchain fix has something to search for. The config-file document gains the key in its two lists — the `<k>=<v>` sub-tables and the path-valued keys that resolve against the config file — which is where its right-hand side belongs: the tool reads that path itself, unlike the four manifest sub-tables cargo resolves. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…o the map closure must not wrap it A list whose element conversion can fail lowers to a `map(..).collect::<Result<Vec<_>, String>>()`, and the closure body differs by element shape: a map ROW is rebuilt from parts each already unwrapped with `?`, so the tuple literal owes the closure its `Ok(..)`, while every other element's conversion already evaluates to the `Result`. Wrapping the second in `Ok(..)` collects a `Vec<Result<..>>` inside a `Result` — E0308 at the consuming call, in a crate the user cannot edit. The two are told apart by the ELEMENT TYPE, because the tuple branch is the only producer of the rebuilt form. Both directions carried it, so both are fixed together: a parameter of `[* any]` and a getter over one are the same conversion mirrored. The reason it survived is that no COMPILED fixture carried the shape. `component-core`'s `meta: any` is the same fallible conversion in a NON-REPEATED position, where the question never arises, and every repeated fallible element the corpus reached was a map row. So the fixture grows a `[* any]` row rather than the suite growing an assertion about emitted text: this is a type error, and the wasip2 build gates are what see one. Confirmed by reverting the fix under the new row — both build gates fail. The corpus snapshots move with the fixture: a twelfth field, its `AnyList` collection wrapper and the serialization of both. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ugh an accumulator, not a borrow in a list `borrow<imported-resource>` is usable ONLY in a non-repeated parameter position. `list<borrow<t>>`, `list<option<borrow<t>>>` and `list<tuple<k, borrow<t>>>` are all legal WIT whose Rust lowering is E0506: wit-bindgen hoists one handle binding out of the lowering loop and reassigns it on every iteration while a reference to it is retained. Measured unfixed from the pinned 0.57.1 through 0.60.0, the newest release, which is why the pin stays where it is. So the borrow moves one level UP, out of the repeated position. Every parameter the ownership rule would spell `list<borrow<t>>` is spelled `borrow<t-list>`, where `t-list` is a consumer-exported accumulator the caller fills one element at a time; a map-shaped one takes `insert(k, v)` instead of `push(v)`. Both fillers are where the CBOR seam runs — once per element — so the consuming constructor or setter clones a SETTLED collection and is infallible, which is the honest signature rather than a fallibility spread over a door that can no longer fail. The alternatives lost on merit: `list<own t>` would consume the caller's handles at the ABI boundary, the exact bug class the borrow rule exists to prevent, and `list<list<u8>>` would trade a typed surface for nested bytes. The cause is named at every place the shape is emitted — the `.wit` resource, the guest rep's doc comment and the projection's own docs — because a future toolchain fix needs a stated trigger to revisit this. RETURNS are untouched. Minting fresh handles is what a return does, so a collection getter keeps `list<own t>`, which lowers cleanly; own-crate collection parameters keep `list<borrow<t>>` for the same reason, since an exported resource's borrow was never the problem. The rewrite is total rather than case-by-case: a `list` carrying a dependency handle at ANY depth is replaced, and the replacement hoists its own element first, so a nested collection of dependency types becomes an accumulator of accumulators rather than reintroducing the repeated borrow one level down. One accumulator per distinct element SHAPE per interface — named after that shape, so two maps sharing a dependency-typed key and differing in their value get two carriers rather than one name with two incompatible `insert` signatures. That name is derived, so it appears nowhere in the spec, and a rule converging on it is a collision the user cannot see coming. It goes through the existing three-level detector — already one walk over the projection — with the one thing the shared text cannot supply: what minted the name. The re-entrancy invariant is unweakened. A filler materializes its element to an owned rust value in its own statement before borrowing the accumulator mutably, and the consuming door does the same with the settled collection, so no two guards are ever live. Compiled, not only read: the shape's whole reason for existing is invisible to every WIT-level oracle — a package spelling the collection directly resolves, encodes and validates just as happily — so the cross-crate gate now builds BOTH consumers for `wasm32-wasip2`, the scalar one and the collection one, off one dependency in one workspace. The dependency gains `@used_as_key` on `token` because a consumer uses it as a map key: key-demand is a property only the dependency's own run can satisfy, and the inference that would have derived it cannot see across the crate boundary. This replaces the generation-time refusal that stood in for the shape, and deletes its pin. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…efused before anything is written A dependency-typed value crossing the component boundary is serialized by one crate and deserialized by the other, so the crossing preserves the value only while the two agree about what CBOR they write and accept. A mismatch fails nothing — not generation, not the build, not composition — it silently re-encodes on every crossing, which is the failure class that costs the most to find. Config mode sees both ends of a `deps` edge, so it refuses; a hand-written invocation sees one crate at a time and can only document the obligation. Scoped to edges that CARRY the seam: this crate emits a component and the dependency is in import mode. On every other `deps` edge the dependency's types are reached by ordinary rust linkage, so no bytes are produced at a boundary and none are parsed there — there is no crossing to re-encode, and a message that explains itself in terms of crossings would be attached to an edge that has none. Widening it would also newly reject configs that generate correctly today. If posture skew across a plain `--extern-import` edge is a problem too, it is a different one with a different mechanism and a different remedy, and folding it under a component-flavored message would hide it rather than report it. The axes are `RuntimeFlavor::equality_axes`, not a list of the seam's own, because it is the same question at a second level: `[runtime]` asks which flags make two crates' serialization contracts non-interchangeable in SOURCE, the seam asks it of BYTES. Each of the three has a stake in both — the two encoding axes change what comes out, the depth limit changes what is accepted, so a crossing the producer considers well-formed is one the consumer rejects. A sibling list would be a second copy of a fact that changes, and a fourth axis minted for the runtime would silently not reach it. The seam predicate is shared with the graph derivation rather than restated, so the check and the flags that create the seam cannot disagree about which edges have one — including the case a derivation cannot produce, a hand-written `component-extern-wit` entry naming a dependency whose own `component` is off. Run over every crate rather than the selection, so a subset run rejects what a full run rejects: whether an edge can mean anything is a property of the config. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ves its own two flags The cross-crate values the component face needs are ones the config already holds, which is the rule every other `deps` derivation follows: hand-maintaining them means two invocations that must agree about a third crate's `output` and `lib-name`, and nothing checks that they do. `--component-extern-wit` takes the `--extern-wrapper-index` PATH FRAME, not the `--extern-import` one, and the difference is invisible until somebody turns `--package-json` on: the dependency's WIT lives INSIDE its component crate, so it moves one level down with the nesting, while the extern-interface export it sits beside is emitted in every mode and does not move. Both frames spell the same string in the unnested layout, so the wrong one is right until it is catastrophically not — which is why the nesting test pins this value. `--component-dep` names the dependency's RUST package. The guest glue holds a dependency-typed value natively and converts it across the bytes seam, so that is the crate the component manifest has to reach; the dependency's own component crate is wired by the composer at the component level and never by cargo. That is the whole asymmetry with the wasm manifest, which derives two packages per edge because its pass also emits `use <dep>_wasm::…`. Both are gated on the SEAM rather than on either crate's `component` alone, through the same predicate the posture check uses, so the flags that CREATE a seam and the rule that refuses an unsound one cannot disagree about which edges have one. A dependency with no component face has no `component/wit` to point at and its types stay excluded from the projection, so neither flag would name anything; where both sides do have one there is nothing to decide, since import mode is the only shape in which such an edge means anything on this face. The acceptance gate covers them by carrying the face rather than by asserting about it: the fixture's `deps` edge now has `component` on both ends, and its consumer spec names a dependency type in a collection, so the byte-identical comparison runs over an emitted component crate whose WIT imports the dependency and whose glue routes both the scalar and the accumulator shapes. `COMPONENT_PACKAGE_SUFFIX` keeps its `#[allow(dead_code)]`, and the comment that promised this derivation would read it is replaced by the reason nothing does: no derivation predicts a dependency's component package, because nothing depends on one. It gains the reader it should have had instead — the drift gate that holds a suffix constant against the manifest template that emits it — so the one suffix with no derivation behind it is no longer the one suffix nothing asserts against. Also corrects the flag reference, which still described a dependency-typed collection parameter as refused at generation; the accumulator replaced that refusal. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…sidual The entry was the layer's own spec — both variant families, the cheaper static floor, the `@used_as_key` shaping note — and the layer is built (`regen_over_prior_output_corpus` + its compile sibling, `7b21547d`), so the spec text goes and what is genuinely future-facing stays. That residual is the sweep's ONE emission profile. It generates `--wasm=true` and nothing else, which is the profile both known trap instances lived in; `--preserve-encodings` emits a whole file the sweep never sees (`cbor_encodings.rs`) and json adds a tree of its own. The signal is written on the dimension the deferred cost actually grows: not "someone wants more profiles" but a SECOND trap instance in a file the default profile does not emit — at which point the profile that produced it is the one to add, rather than all of them. The recur-first FIRED-triggers list drops the entry with it, since its trigger is no longer an unbuilt work item. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
A cache-hit run of `regen_over_prior_output_corpus_compiles` still pays the per-cell generation, the replace-block injection and the lockfile preflight, so "159 s" alone reads as the price of a re-run when it is the price of a cold scratch root. Measured ~90 s fully cache-hit (88 of 88 cells), on the same terms its `component_corpus_compiles` neighbour states both numbers. The `fast`-tier wall in tests/timings.json moved on its own sliding-window rule during these runs; the digest and the spans derived from it are one commit, per tests/README.md § "Measured gate durations". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
The sweep's first cut generated one profile, and the profile it did not generate emits a FILE it does not: `cbor_encodings.rs`, one struct per rule that carries encodings. A per-rule surface is precisely where a comment on a deletable row would live, and nothing else looks for one there — so the cheapest legs (one extra generation per fixture each) now sweep the default and preserve profiles both. The edit leg stays on the default: a replace block costs three generations, and its compile gate nested cargo per fixture. Measured 55 s, up from 40 s, which keeps the gate at `local` with room. Counts roughly double where they should: 1320 files scanned (was 577), 177 deletion cells (was 89), 12 of them deleting a `@used_as_key` rule (was 6); the floors follow. Green on the new surface — no trap in `cbor_encodings.rs`. A secondary profile's GENERATION verdict is deliberately not this gate's to own. `feature_corpus_compiles` gates that both ways through `EXPECTED_GENERATION_FAIL`, where a listed pair that starts generating fails as a stale pin; here a fixture that will not generate under preserve is a recorded SKIP (today, `dsl_ignore`), so the ownership stays single. The roadmap residual narrows with it: two profiles of four, and the edit leg's one, with the trigger re-aimed at a sentinel in a file NEITHER swept profile emits. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…ll tier's wall follows The cycle's new full-tier gate `regen_over_prior_output_corpus` records a warm median of 55.0s (n=3) — its first, so the span that reported it as unmeasured now names a number. The tier's own wall moves 33m4s -> 40m43s (n=16): the gate is new work in the tier rather than a slowdown of existing work, and the per-gate medians either held or moved within noise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…e rest row's key domain become cells Twelve `[[contain]]` cells, no new fixtures: each sub-batch's regression defense already lives generator-side, and a cell's `example` IS its probe input. - The `any`-arm POSITION axis (role.choice-member): a non-last bare `any` (unsupported, PERMANENT by decision — a green flip is a regression, per README § "Gotchas"), the last-position bare arm, and a tagged `#6.n(any)` in a non-last position. Position and tagging are the two axes that flip the verdict, and now each is a cell rather than a sentence. - The fixed-value KINDs the enumeration still owed: a nint constant and a tag-wrapped fixed form as ARRAY-rep group-choice arms, a type choice whose fixed arms share a CBOR major type, and the nint MEMBER cell. Every one spells its DISPATCH PATH from the emitted deserialize — type-match for the two arm kinds, brute-force try-each-arm for `true / null / tstr` and for a last-position bare `any` — because the two sites emit independently and a kind proven on one certifies nothing about the other. - The rest row's KEY-DOMAIN axis (role.occurrence-target): named-rule, `bytes` and `nint` domains supported, the float-containing and null-admitting domains rejected. The generator's boundary moved along this axis in 2026-08; until now no cell could state where it sits, so a consumer had no way to ask. Probed at HEAD before authoring: the seven supported shapes generate, compile and round-trip under the default and `--preserve-encodings` profiles, generate under the json flags, and their `--wasm` crates check clean; the three rejected shapes exit 1 with the messages their generator-side pins assert. Both oracles accept all twelve examples. No panic, no silent-wrong. The source entries prune with the delivery: the `any`-arm entry and the rest-row key-domain entry retire whole; the fixed-value KINDs entry narrows to its one residual, the FLOAT kind in both positions. The arm-classification entry stays — enumerating arm positions is not the same act as getting their rejection evidence, and its signal is still an arm-position reject vector. Verdicts land on the next evidence mint; the new cells render `?` in the grid until then. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
… a new oracle gap The cycle-13 registration chain over 0fb4fd1's cells, everything downstream of the two full verify.ts passes: - Evidence: all 12 verdicts minted exactly as the pre-probes predicted — 9 supported (round-trips, wasm round-trips, json+preserve emission green), 3 graceful refusals, both oracles corroborating every example. Eight supported rows carry fresh decode-foreign vectors; the nint member cell adds the hand constraint pair (accept 8120 / reject 8121, "Expected fixed value -1 found -2" verbatim from the decoder), taking the fixed-value MEMBER family to 16 cells and the enforcement spans to 69 vectors over 49 rows. - The projections follow: reject-catalog snap (+3 rows, all error (graceful)), matrix_supported (+9) / matrix_reject (+3) fixtures, COVERAGE.md (the occurrence-target memberkey.type1 and prelude.any grid cells resolve ? -> half-supported), the generated Limitations block, and the status-header spans (286 annotations). - The arm-classification entry's reopening signal did NOT fire, now verified rather than reasoned: 21 arm-role catalog rows post-mint, zero reject vectors, zero class= — the mint writes accepts and re-certifies pre-existing hand pins only, and the one hand vector added here sits on a MEMBER role. The floor-scope pins for the three new choice rows record their own limits, including the same-major blind spot ({3,7} satisfiable by one major-7 accept when true and null share the major); ruled comment-sufficient — the decode-foreign floor is corroboration-side by the catalog's contract, and per-arm evidence is execution-gated in the emitted round-trip (the row carries f5 AND f6 regardless). - The tagged-any cell's note stops claiming a pin that never executed the shape: the two robustness fixtures spell the BARE arm only, and the pins that DO execute #6.n(any) non-last are named instead (tagged_any_arm_allowed_in_any_position; choice_tagged_any in tests/any-positions). - The named_key row minted pinned_reason-vectorless: gap #11 exactly (named-rule key domain, every candidate ruby=0 rust=1), now recorded as that gap's first MATRIX resident with its inline-key siblings as the controlled pair. Separating the pair surfaced a NEW oracle gap — #13, string-typed rest-row keys in a MIXED map demand an entry (* read as +): {1: 692} fails "map requires entry key of type bytes" against { 1: uint, * bytes => any } while uint/nint domains pass, the rest-entry-bearing instance passes, and the pure table keeps its empty-map pass; ruby accepts throughout. Differential grid and upstream-report sketch in draft/rust-cddl-string-key-mixed-map-rest-occurrence-gap.md; catalog cost is bytes_key's two zero-rest-entry accept candidates, dropped by the two-oracle gate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
query_q4_directional's EXPECTED_ENFORCE_YES is the deliberate-addition fence for the enforce=yes green set; the nint member cell joined that set when its hand constraint vector landed, so the pin gains the id. Caught by the fast tier on the evidence commit — the README's 15 -> 16 prose count moved with the vector, but this pin is the mechanical half of the same fact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
… compiled `fuzz_compile_rot` proves the byte-fuzzer's targets still COMPILE; nothing ever ran them, so a panic that only a live libFuzzer input triggers sat outside every tier. `fuzz_bounded_run` (full tier, registered after the compile-rot gate) runs both targets sequentially over the local corpus for `FUZZ_BUDGET_S` seconds each (default 120) at `-rss_limit_mb=2048`, and fails naming the libFuzzer artifact to replay. One process at a time: the peak the tier must bound is one libFuzzer RSS plus the cargo build that precedes it, and no factor scales with core count. Three deliberate properties, each recorded at the gate: - NOT gate-cached. A randomized exploration is not a pure function of the tree's bytes, so a content-hash hit would skip the only thing the gate does. Nothing else records the exemption: the closure audit traces ONE cached cell (`CLOSURE_AUDIT_GATE`) and enumerates no gate set. - Missing nightly / cargo-fuzz is a FAIL naming the install commands, never a skip — the gate is full-only, and a silent skip in the tier that ships the guarantee voids it (`runNoStdCheck`'s posture); there is no softer tier for it to be in, hence no softening arm. - No `requires:` edge on `fuzz_compile_rot`. `ensureFuzzGenerated` is shared, so either gate provisions `fuzz/generated` itself and `--only fuzz_bounded_run` asserts exactly what a whole tier run does rather than passing vacuously. The first real run is RED, and the gate is right to say so. 480 s over `from_cbor_bytes` (1929-file seed corpus, ~7 080 exec/s, peak RSS 653 MiB) found a preserve-encodings FIDELITY violation in `NonOverlapBasicNotBasic`: `bytes .cbor basic_arr` accepts a byte string whose embedded CBOR does not consume the whole payload, then re-encodes only the consumed prefix. Hand-derived 6-byte reproducer: `81 44 82 09 60 00` re-encodes as `81 43 82 09 60` — the trailing `0x00` is dropped. Disposition is a maintainer call (a fidelity violation is tier-1 class), so nothing is ledgered, pruned or retired here; on a corpus that has seen it, the default 120 s budget re-finds it in ~5 s, so the full tier fails this gate until the bug is fixed. `from_cbor_bytes_recursive` ran clean over the same 480 s: 54 768 212 execs, peak RSS 601 MiB, no crash, no artifact. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…re-encodes to itself `bytes .cbor T` says the byte string IS T's encoding. The embed read the payload and stopped — bytes left over inside the byte string were accepted, and since nothing held them, the value re-encoded to the consumed prefix ALONE. Over-acceptance on every profile, and under `--preserve-encodings` a fidelity violation on top: an ACCEPTED input round-tripped to different bytes, in a crate that compiled and passed every round-trip test, because round-trip tests only ever feed encodings the serializer itself produced. Found by the byte fuzzer's second oracle on the first bounded run of `fuzz_bounded_run` (adb165a) — the fidelity assert, not the crash boundary. Minimal reproducer, hand-derived from the libFuzzer artifact: `81 44 82 09 60 00` re-encoded as `81 43 82 09 60`. The payload is now required to be exhausted, raising the SAME `DeserializeFailure::CBOR(cbor_event::Error::TrailingData)` the top-level `from_cbor_bytes` raises for the same fact — one spelling, so a consumer matching on trailing data at the top level matches it here too, and the enclosing annotation still names the member. One emission site serves every `.cbor` spelling (`generate_deserialize`'s `CBORBytes` arm), so the rule body and the member expression were wrong together and are fixed together — both pinned by `structural_rejects` in `tests/core/tests.rs`, red-first on the pre-fix emitter. Completeness established over the OUTPUT rather than by grepping the emitter: all 154 embed sites across the blessed snapshots and the exported crates reach the check at their own block level, none with an early `return` that could bypass it. The check follows the payload's code, which is only expressible where that code is a complete STATEMENT; at a terminal position (a block's tail, a tuple element) the payload value is bound first and the binding yielded. Both spellings are emitted rather than always binding, so consumers do not get a `let x = x_payload;` rebinding that says nothing. The binding also RESTORES the check for the c-style-enum payload sweep, whose `return Ok(variant)` would otherwise have jumped past it. Snapshot churn is 30 files, audited by diff class: the new check, the payload binding, and rustfmt re-indentation around them — no other emitted token moved. `docs/docs/output_format.mdx`'s trailing-bytes paragraph said nested decoding was deliberately unaffected; that sentence was the documented form of the bug and is now the documented form of the rule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…gistration cost The first full-tier run over cycle 13's cells failed decode_conformance_replay on contain.choice-member.prelude.any.last: all ten wrong_major header mutants DECODED Ok. For this row that is the spec's own semantics, verified before ledgering rather than assumed: - The acceptances reach the arm the spec says accepts them: probed on the generated crate, all seven non-text major shapes decode to the A::Any(AnyCbor) variant — the last-position bare `any` catch-all under forced-backtracking dispatch — never A::Text, which would have been the tstr arm mis-dispatching mutated bytes and a real over-acceptance finding. The major-3 control still lands on A::Text (first match wins). - No trunc_head mutant is in the failing set (all ten trunc_head tests ok in the gate's own output) — a trunc_head acceptance is ill-formed by construction and would be a finding always. So (row, wrong_major) joins HEADER_MUTANT_ACCEPT_SKIP beside its feature-row precedent (prelude.any, same class at the rule position), with the reason naming the accepting arm and the probe. The entry is (row, label)-wide because every committed accept samples the tstr arm (the mint's shape), so every flip lands on an any-only major — exact, not a suppression. The ledger's stale guard retires it if the row's shape ever changes. Every future any-typed catalog row owes this same entry on its first tier appearance; the cycle record says so. Rides along: the backwards-compatibility note for cff8516's `.cbor` exhaustion change in docs/docs/output_format.mdx — the acceptance change is exactly the class the docs convention carves out for historical notes (pre-2026-08 generators accepted-and-dropped trailing payload bytes; re-generated crates newly reject them; serializer-produced data is unaffected). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…ischarged in one sweep
Two consecutive full-tier runs each died on a DIFFERENT missed registration obligation of cycle
13's twelve cells — fail-fast surfaces one per run, so this stops discovering them serially: a
complete sweep of every leg obligation for every new cell, enumerated from the gate's own ledger
registry (every `const` decode_conformance_replay declares — PRESERVE_SKIP, EXPECTED_MISMATCH,
ENCODING_VARIANT_SKIP, DOUBLED_LOCATION_SKIP, HEADER_MUTANT_{ACCEPT,LOCATION}_SKIP,
JSON_SURFACE_SKIP, WASM_SURFACE_SKIP, the four floors), not from a keyword grep. Full table:
draft/burndown2-cycle13-registration-sweep.md.
Discharged here (run 2's failure): contain.occurrence-target.memberkey.type1.open_struct_bytes_key
joins JSON_SURFACE_SKIP. Verified to be the decided boundary, not a new shape: the error is the
strict-fail the delivered posture documents ("open struct-map rest key has no JSON member-name
image", docs/docs/output_format.mdx § "Typed key domains in JSON"), the cell's own note already
marked the row as where the flattened-rest JSON convention stops, and the § findings non-string-
map-key entry carries the decided precedent verbatim — it now also names this cell among its
surfaced-by sites. The nint sibling is deliberately NOT listed (nint has a member-name image, per
the error's own admitted list); a json failure there next run is a finding, not a registration.
Every other (cell x leg) obligation is answered concretely in the sweep table: four rows have
nothing to replay (three reject fixtures, the gap-#11-pinned named_key), and every remaining cell
x leg is either LEDGERED (any.last wrong_major, d1997e1; bytes_key json, here) or explicitly
"should work" with the reason — notably tag.any_non_last owes NO header entry because its accepts
evidence majors 3 AND 6, so every derived flip lands on a major both arms reject with a located
error.
Verified by the gate in isolation at this tree: cargo test decode_conformance_replay --ignored ->
ok, 674 s, zero failures beyond the two pre-existing derived pair-map suppressions. A third
full-tier failure in this gate on these cells would now be a real finding.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…decode replay's grows with its catalog `fuzz_bounded_run` records 4m3s (n=3), its first — the span that reported it as unmeasured now names a number. `corpus_decode_replay` moves 15m36s -> 18m45s (n=20): the cycle added twelve catalog rows with real vectors, so the gate is replaying more per run rather than replaying the same work more slowly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…t session finds them The TDD pass over everything this cycle caught by reading, probing or burning tier runs — each lesson filed in the system that owns its class: - The serial-registration cost becomes a FIRED work item (TESTING_ROADMAP § Next work items, now item 1): decode_conformance_replay aggregates failures within a row but panics at the first failing ROW, so twelve new cells cost two ~40-min full-tier runs for two independent ledger obligations. Fix shape recorded (route per-row failures into the end-of-gate failures collection the stale guards already use); the cycle's sweep table stays the authoring half. List renumbered (positional citations are banned tree-wide, so nothing dangles). - The `.cbor` doc sentence joins the docs-conformance decline as its FOURTH recorded instance — and the sharpest, because doc and behavior AGREED: "(Nested/embedded decoding — e.g. bytes .cbor T — is unaffected)" was a TRUE sentence about a DEFECT, which any docs-vs-behavior harness passes by construction. The decline is not reopened: the layer that caught it is a SPEC-side oracle (the fuzz fidelity leg, now standing), and the instance adds the zero-cost authoring rule instead — a limitation/boundary sentence in docs names its provenance (decided- posture record or findings entry), so an anchorless boundary reads as an undecision wearing decided clothes. Reopening signal for the rule: a second anchorless boundary sentence found to have documented a defect as intended, after the rule was in force. - The kill-by-PID rule in AGENTS.md learns the case where its own precondition is unsatisfiable: when agents share one harness, ancestry attributes nothing (proven 2026-08-04 — a tier run nearly killed on a wrong ancestry read; the sub-agent refused on better evidence). Attribution is by INVOCATION RECORD (disjoint self-log name classes, the log's own banner, who issued the command), and shared ancestry means identify-then-coordinate, never kill. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…unt inventory
The roadmap's fired work item asked for aggregation that already exists. Probed at HEAD by
reading both gates: every per-row, per-leg failure in `decode_conformance_replay` and
`corpus_decode_replay` is pushed into one `failures: Vec<String>` and panicked ONCE at the end —
no `panic!` or `assert!` sits inside either row loop (the asserts around them are the pre-loop
catalog/stale-pin registration guards and the post-loop vacuity floors, all outside the walk).
Cycle 13's two-run cost is explained by CONSUMPTION, not gate shape: run 1 failed with
26 problem(s) — 10 `any.last` header `wrong_major` + 8 `bytes_key` json + 8 the same row's wasm —
and run 2 with 16, a strict SUBSET of what run 1 had already printed. Each problem embeds its full
captured cargo-test output, so the 10 same-row header problems occupied ~1600 lines before the
second family's first line appeared, and the session discharged only the family it read.
So the residual is legibility, and that is what lands: `replay_failure_summary` groups failures by
the leading `"{row.id}: "` prefix (prefix-less stale-guard messages group under their own truncated
first line), and both final panics now head their details with the inventory —
decode-conformance replay found 26 problem(s) across 2 source(s):
contain.choice-member.prelude.any.last — 10
contain.occurrence-target.memberkey.type1.open_struct_bytes_key — 16
in first-appearance (row-walk) order, so related legs stay adjacent. Display-only: no leg, no
collection and no pass/fail semantics change, and the block is reachable only on an already-failing
run. The leading texts "decode-conformance replay found" / "corpus decode-conformance replay found"
are unchanged verbatim — only the count line is extended.
`replay_failure_summary_groups_by_row` (a plain `#[test]`, no crate build) pins the helper on cycle
13's exact shape: 26 synthetic multi-line failures over two rows plus one stale-guard message → 3
groups, counts 10/16/1, first-appearance order, every summary line short and free of captured
output. Its name deliberately carries neither gate's name — check.ts runs both by SUBSTRING filter.
TESTING_ROADMAP's item is removed rather than checked off (list renumbered; positional citations are
banned tree-wide, so nothing dangles). No committed doc stated the per-row-panic claim — the
decode-direction conformance sections of tests/README.md were read end to end and describe the legs
and ledgers without asserting a failure-reporting shape, so nothing was corrected there; the
rationale now lives durably in the helper's doc comment.
Verified: `cargo test --bin cddl-codegen replay_failure_summary` green (1 passed, 1193 filtered —
the name matches exactly one test), and `bun run check.ts fast` PASS, all in-tier gates green,
wall 38.2s. The local and full tiers remain unrun and are the orchestrator's to run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…lent again
Two arms of `try_defer_wrapper` decline BEFORE any index is consulted — the
ident≠structural screen and the R3c constituent screen — so the class they mint
can carry a name a dependency's `--extern-wrapper-index` also lists, and the
defer seam has no way to see it. That is the same duplicate-`#[wasm_bindgen]`
configuration `warn_rule_declared_table_shadows_index` announces, reached by
paths that announced nothing.
The honesty check therefore lives at the one seam every LOCAL mint passes:
`warn_local_mint_shadows_index`, called from `record_collection_wrapper` and
keyed on the EMITTED ident rather than on the reason a particular arm declined.
That closes the family at once instead of chasing `return false` sites, and it
covers any future arm that declines before consulting the index. It shares
`deferred_warned` with the existing warnings, so a rule-declared table still
warns exactly once with its more specific text; it skips the
`requested_scope_override` mint by intent (a hosted wrapper's name is the
REQUESTING consumer's choice, arbitrated by the request sidecar, not this
crate's); and it is unreachable with no index flag, so flag-off byte AND stderr
identity hold — verified by generating the fixture both ways against a stashed
build.
Probed at HEAD before coding, and the recorded shape was half wrong: the
roadmap's spelling `arr_idx_foo_list = [* idx_foo_list]` never reaches R3c at
all — its structural name is `IdxFooListList`, so the ident≠structural screen
declines first — while `idx_hash_list = [* idx_hash]` over a consumer-owned
element does take R3c. Both mint a dep-indexed name silently, which is why the
fix is seam-level rather than branch-level, and both are now pinned by
`extern_wrapper_index_local_mint_under_indexed_name_warns` over the new
`inputs_nested` fixture: warning texts verbatim, the classes and their own-index
rows asserted unchanged (warn-only), the deferring sibling's unification warning
asserted to still fire beside them, and the consumer wasm `cargo check` floor.
The fixture is a new sibling dir rather than an addition to `inputs_named`,
whose `!index.contains("IdxFooList")` assertion the substring `ArrIdxFooList`
would falsify.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
… and becomes an enumeration Every collection wrapper a spec implies has an emission MODE, and the ~20 committed pins over that space are incident-shaped: each records the exact configuration of one past escape. What none of them gives is the grid, and the escapes on record were never in the primary wrapper — they were in a COMPANION (a table's synthesized keys-list, a restricted wrapper's loose `try_from` source) or a POSITION (a named-rule reference, a non-root declaring scope) that one mode happened not to walk. `src/tests/wrapper_participation_tests.rs` is that enumeration. `PARTICIPATION_TABLE` is the grid AS DATA over MODE × SHAPE × POSITION; each row states its expected outcome (Defer / Borrow / Host / LocalWarned(<which warning>) / LocalSilent(<why silence is correct>)) and, where an existing test already pins it, that test — those rows are REFERENCED, never rebuilt, so the four always-on per-mode sweeps generate exactly the rows nothing else covered. Each row's CDDL is derived from its own axes and each owns a distinct element ident, so one generated crate carries a whole mode and a new shape or mode is one table row rather than a new function. `..._table_is_complete_and_live` is the grid's own guard: rows unique, every mode covering every shape that participates in it (the one documented gap — a table RULE cannot be requested — spelled rather than silently absent), and every `pinned_by` resolving to a test that still exists, so a referenced row cannot keep reading as coverage after its pin is renamed away. Two participation facts are ENCODED rather than assumed, and one of them earned its keep immediately: a reject set can be HOSTED but never DEFER, so under `--extern-wrapper-index` an indexed name is a collision only the mint-seam backstop can announce — the row is green solely because of the previous commit. The other is that the name-only index is flavor-SAFE by construction, which makes a preserve table an ordinary shape row instead of a hazard cell. Floors are `#[ignore]`d and batched per (mode, floor), gate-cached per generated-crate content hash: `wrapper_participation_floors` runs a `cargo check` of the standalone Local column plus a real wasm32-unknown-unknown link of the index and workspace columns against the committed wasm-clean dep pair, GREEN only (the RED leg is already demonstrated once by `extern_wrapper_index_defers_to_dep`; verified non-vacuous here by regenerating the same spec flagless, which fails that link with 20 duplicate-symbol errors). What the link legs add is the POSITION crossing — a named-rule declaration, a by-name reference and a non-root scope had never reached a wasm32 link. `wrapper_participation_host_floor` checks the HOST crate a `--wrapper-requests` run emits. That host floor found a live defect on its first run, so it ships NARROWED and says so: a requested NonEmpty wrapper whose loose `try_from` source is itself co-hosted makes `requested_collections.rs` import that source from `crate::generated`, where it is not — it is in that same file. E0432, at exit 0. It is the co-hosted self-import class `workspace_requests_cohosted_keys_list_no_self_import` closed for the keys-list and left open for this second companion, and the committed request cells cannot see it because their dep spec produces the loose source itself, which makes the same import path correct. The roadmap entry is retired into its two honest successors: that finding as a DUE item carrying its reproduction, and a single-PROFILE residual whose reopening signal is a placement decision differing between two profiles for one row — something a consumer regenerating one spec twice can measure, which the entry does not already record evidence for. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…rofile sweep grows with the corpus `regen_over_prior_output_corpus` records its first warm median at 1m40s (n=3). `feature_corpus_roundtrips_nondefault_profiles` moves 7m45s -> 9m58s (n=20): the corpus gained fixtures across the last cycles, so the sweep covers more per run. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…findings ledger into the gotchas
The end-of-burndown holistic docs pass, executing the maintainer-ruled deferral recorded at cycle 11
close-out: the @custom_json can't-compile-standalone entry and its non-string-map-key sibling are
DECIDED postures — a contract boundary and a kept boundary — so § findings' own intro ("a defect or
a missing capability") mismatched them. Both are now current state in cddl-matrix/README.md
§ Gotchas, phrased as what the generator does today rather than as candidates, with the observable
that would make each a finding again stated as the boundary's own bound.
Every pointer that reached the findings entries retargets in the same change: the
JSON_SURFACE_SKIP / WASM_SURFACE_SKIP ledger citations in both replay gates (matrix and corpus),
their header comments' resident-citation contract (owning record: a decided-posture gotcha or a
findings entry), tests/README.md's json/wasm-surface-legs resident description, and the
containment-cell registration recipe's step-7 wording. The ledger instructions that route REAL
decoder gaps to § findings (ENCODING_VARIANT_SKIP and the variant-failure message) are unchanged —
that is still where defects go.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…in two stale homes The .default / range-bound / .cbor-head control-arm aborts were converted to graceful refusals in 12c9abc, which updated current_capacities.mdx and TESTING_ROADMAP but left two other homes describing the aborts as live — the classic finding-ledgered-in-two-homes staleness the holistic pass exists to catch (probed at HEAD: all three robustness rows record `error (graceful)` and KNOWN_CLOSURE_BREACH is an empty slice): - cddl-matrix/ROADMAP.md § findings still carried the "Three control-operator arms ABORT (exit 101)" entry as a candidate fix. Pruned outright: the refusals are the delivered remedy, pinned by the robustness catalog and documented in current_capacities.mdx, so nothing future-facing remains. - tests/README.md's refused-name-closure sibling paragraph still read "The pin list is NOT empty" over the same ten .default cells. It now records the empty-at-HEAD state and how it got there. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
…r entry that owns it The one transparent-alias wire-facts carve-out is documented in current_capacities.mdx as a limitation with a workaround but named no tracking artifact — the anchorless-boundary-sentence class the docs-conformance decline's fourth instance added an authoring rule for (a docs sentence stating a limitation names its provenance). It now cites the owning findings entry by exact title, the same citation shape the byte-string-literal limitation already uses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JYLwxUHShu3rXopnyHjnRd
Bumps [clap](https://github.com/clap-rs/clap) from 4.6.1 to 4.6.6. - [Release notes](https://github.com/clap-rs/clap/releases) - [Changelog](https://github.com/clap-rs/clap/blob/master/CHANGELOG.md) - [Commits](clap-rs/clap@clap_complete-v4.6.1...clap_complete-v4.6.6) --- updated-dependencies: - dependency-name: clap dependency-version: 4.6.6 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com>
Contributor
Author
|
OK, I won't notify you again about this release, but will get in touch when a new version is available. If you'd rather skip all updates until the next major or minor version, let me know by commenting If you change your mind, just re-open this PR and I'll resolve any conflicts on it. |
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.
Bumps clap from 4.6.1 to 4.6.6.
Release notes
Sourced from clap's releases.
Changelog
Sourced from clap's changelog.
Commits
348cff3chore: Released478377docs: Update changelog04b9fbbMerge pull request #6414 from koopatroopa787/fix-bash-completion-bracket-glob7075239Merge pull request #6422 from BaumiCoder/fix-fish-indentationsf90a966fix(complete): Use spaces for indentation in fishdd4997bfix(complete): Don't glob-expand bash positionals8387c81Merge pull request #6399 from clap-rs/renovate/crate-ci-typos-1.x8141e11chore(deps): Update compatible (dev) (#6398)8a6bd4echore(deps): Update pre-commit hook crate-ci/typos to v1.47.071a7213chore(deps): Update Rust Stable to v1.96 (#6396)You can trigger a rebase of this PR by commenting
@dependabot rebase.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebasewill rebase this PR@dependabot recreatewill recreate this PR, overwriting any edits that have been made to it@dependabot show <dependency name> ignore conditionswill show all of the ignore conditions of the specified dependency@dependabot ignore this major versionwill close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor versionwill close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependencywill close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)