Integration: restructuring campaign, do not merge without explicit approval - #4
Draft
santhreal wants to merge 2232 commits into
Draft
Integration: restructuring campaign, do not merge without explicit approval#4santhreal wants to merge 2232 commits into
santhreal wants to merge 2232 commits into
Conversation
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Macroscope has since reviewed this pull request. An earlier review was skipped by a cost limit; a review has now completed, so that notice no longer applies. |
Owner
Author
|
/devin review |
Pass 1 read one element per thread, so the block count was the input divided by the tile: 1024 blocks for a 1M element sum. The fused program carries a whole-grid fence and therefore launches cooperatively, which requires every block co-resident, and no device holds 1024 blocks of 1024 threads. The launch was refused, correctly, and the composition had no way to ask for a grid that fits. The builder now takes the workgroup count and pass 1 strides the whole grid to cover the input, with the trip count fixed at build time. Cooperative residency is a device fact, so it stays out of the composition: vyre-bench reads compute units from the probed device and passes one workgroup per unit, and both the builder and the caller take the clamp from grid_stride_tree_sum_u32_blocks so a program cannot disagree with its own dispatch. Measured on the local device at 1,048,576 elements: 27552 ns against an 83828 ns rayon baseline, 3.0x, against a 1.1x contract. The same case measured 7.15 GB/s before the dispatch grid was bound and now measures 163.6 GB/s. pass_one_strides_far_enough_to_cover_every_element asserts the emitted trip count times the grid stride spans the input at five shapes, which is the invariant a narrower grid breaks.
…one owner Three defects in one neighbourhood. `graph::alias_registry` calls `crate::telemetry::bump` from production code while `graph = [...]` did not name `telemetry`, so selecting the feature could not resolve the module and the crate did not build. The feature now declares what its code uses. `primitive_default_alias_registry` and `build_default_registry` were public names that did nothing but call `default_alias_registry`, and `matches_primitive_directly` asserted that two of them returned equal registries: a differential test whose two sides are the same function cannot fail on anything. The aliases are deleted, every caller names the one function, and the test that could not fail is gone rather than rewritten to compare a function with itself more carefully. The do-calculus tests each wrapped the same infallible reference witness in the same two length checks, three copies in one file and a fourth in its sibling. `graph::do_calculus_oracle` owns the check and the four wrappers. 549 tests pass under `-p vyre-libs --features graph --lib graph::`, which is the selection that previously did not compile.
`cargo fmt --all` was left unrun across the lane merges, so the fmt step of every stable and nightly host job rejected the tree before it compiled anything. No semantic change.
The single-step and batch resident CSR queue suites each carried their own recording `ProgramDispatcher`. The two implemented the same five arms over the same resident ABI and differed only in field spelling and in what they threw away: the batch recorder ignored allocation lengths and upload bytes, so a contract proved against one recorder proved nothing about the other, and a change to the resident dispatch ABI had two places to land. Both suites now include one `recording_resident_dispatcher.rs`. The field names are the short ones, the recorded set is the union, and the refusal message names the path rather than the suite, because the failing test name already names the suite.
`prepare_size` gained a block-count parameter when the grid stopped being inferred from the input size, and its unit test kept the one-argument call, so every non-GPU bench target failed to compile. The test now passes a device-shaped block count and asserts the grid each size resolves to, including the saturating case where more blocks are offered than there are tiles to reduce.
The guide is rendered from the manifest and the test metadata, and the merged lanes moved both. `xtask testing-guides --write`.
Six passes decided whether they had rewritten anything by fingerprinting the program before and after their engine ran. The after-fingerprint is always a miss: an engine returns a freshly built Program, so its OnceLock memo is empty and the call canonicalizes the whole program, encodes it to wire bytes and BLAKE3-hashes the result. A callgrind run over the optimizer pipeline attributed 51% of the pipeline's instructions to that one call, reached only through the fingerprint memo's initializer, and the cost is paid once per pass per fixpoint iteration, which is why every pass added to the pipeline slowed the whole pipeline down. Program's structural equality answers the same question. It ignores buffer declaration order for the same reason the canonical fingerprint did, so a reordering pass still cannot spin the fixpoint loop, it short-circuits on shared Arc identity when an engine handed its input straight back, and it stops at the first difference instead of walking the whole program twice. PassResult::from_programs already owned that rule and is now the only place it lives. It takes `before` by value so an unchanged pass returns the program it was given, keeping that program's fingerprint, statistics and shape memos warm for the next pass. canonicalize, cse and dce leave the borrow-preservation allowlist as a result.
The blocker a failed benchmark records is bounded to 4096 bytes and then had its host root stripped. A child echoes its own absolute command line, so the cut lands inside that path, the remaining text no longer matches the root's own spelling, and nothing is stripped. release/evidence/benchmarks/cuda-release-suite.json shipped a fragment of the operator's directory tree that way. The strip now runs on the joined streams before the cut, so the root is matched where it is whole. The regression case is longer than the bound with the root ahead of the cut point, which the existing short-text case could not fail on.
Every C dependency in the tree failed on windows-latest with `failed to find tool "cl"`: pcre2-sys, libsqlite3-sys and openssl-src all invoke cl by bare name on the MSVC target, and cl is only on PATH inside a Visual Studio developer environment. The job set CC=cl for openssl-src without ever entering one, so both Windows toolchains have been failing at cargo_full test.
try_for_each_expr returns a ControlFlow the closure can never break out of, so the call warned as an unused result.
The release train, every manifest, every lockfile and the documents that quote a version were still on 0.7.2. cargo-semver-checks resolves its baseline from the newest non-rc tag, so the breaking changes this cycle carried were being measured against a version the workspace claimed to still be.
Both are generated artifacts and both were behind their generators: the operation matrix by the registry entries added this cycle, the metadata matrix by the workspace version.
The floor was a flat 16384 MiB restated at five call sites, and nothing in the catalog came near it: the largest registered case declares 1024 MiB of resident bytes. The number was a claim about what class of device the published figures came from, and it rejected hardware that runs every registered workload correctly and at full occupancy, which made release evidence impossible to record on most of the fleet. It is now the largest declared working set plus a fixed CUDA context reserve, read from the registry at run time, so a workload that grows moves the floor without anyone editing a constant. The comparison itself has one owner that both the live nvidia-smi probe and the recorded-JSON release checks route through, and the sub-floor test fixtures derive their memory from that owner instead of naming a number that stops being sub-floor the day the floor moves. The compute-capability floor of 8.0 stays. That one is a feature floor: the CUDA backend targets cuda-12000 and emits asynchronous copies and cooperative launches a pre-Ampere device cannot execute.
The manifests moved to 0.8.0 but the lockfile still resolved every workspace member at 0.7.2, so a build from this tree disagreed with the release train about what it was building.
The grid-stride reduction contract shipped two hand-written descents that enumerated the nesting variants they knew about and treated every other variant as a leaf, so a nesting variant added to Node would have stopped them silently. Both now take children from vyre_foundation::visit::child_bodies, which is an exhaustive match that fails to compile on a new variant. The gate that reports that class could not check its own owner. It read child_bodies out of a hardcoded vyre-foundation/src/visit/node_parts.rs, and the definition had moved to node_bodies.rs beside it, leaving only a re-export at the path the test opened; the test then panicked on a file that has no child_bodies body rather than judging the vocabulary. It now finds the definition by reading the traversal module, and requires exactly one file to define it.
Every source file under vyre-libs/src carried its contract in the reader's head. All 107 files that lacked a module header now state what the module owns. An empty module left behind by a split is deleted with its declaration. The persistent-BFS volume oracle sweep named required-features = ["graph"] while its source addresses graph::dispatch, which lives behind graph-dispatch. The target compiled in no configuration the sweep runs, so the oracle matrix was red on a resolution error rather than a parity verdict.
The changelog fragment for that fix is inside the benchmark source fingerprint, so every measurement recorded against the previous head describes a source tree that no longer exists. Both backend suites were re-recorded on the 24564 MiB release-floor device with the device lane idle, cross-backend comparison and the release axes were regenerated from those runs, and the artifacts name the head that carries the measured code at dirty=false.
The coupling gate resolved its base branch out of the process environment from inside the diff reader, so a caller asking for the worktree diff got the pull-request diff on any runner whose event set that variable. The gate then compared against `origin/main`, which a depth-1 pull-request checkout does not carry, and reported an unreachable base on every pull request. Resolution is one pure function at the entry and the reader answers from its arguments alone. Every combination of flag and event is stated, so a second reader of the event cannot appear unnoticed.
Eleven inline tests in the wgpu driver acquired the singleton device without naming `device-tests`, so a default `cargo test -p vyre-driver-wgpu` demanded an adapter and every GPU-less leg of the hosted matrix went red on a probe report rather than on a contract. The tests are unchanged and still run, on the lane that builds the package with the feature and has the device. The pipeline harness moves behind the same admission, so a module that wants a device cannot be added without stating it.
Three lazily initialized statics in the wgpu driver used a cell whose initializer sat in a separate function, so the declaration did not state what the cell holds and a second initialization path could be added against it. Each is now a lazy cell with the initializer at the declaration. The cached device runtime loses a non-forcing read; every caller of that read is a device test that has already acquired, and the site states that.
A per-backend benchmark artifact identity was rebuilt with the host path joiner, so a recording made on a host that separates with a backslash named an artifact no declaration lists. Two registry tests compared an error that carries a host path against a slash literal. Both make a generated artifact a function of the filesystem it was generated on. The identity is now a repository-relative string split at the last slash, and the tests build the expected path component-wise. The tree also declares its line endings, because the provenance head of a recorded artifact is a literal byte sequence that a translated checkout breaks.
The cost model read its launch floor from the cheapest recorded case and its traffic rate from whichever recording the directory walk returned first. The two numbers could therefore describe different devices, and every fusion decision was priced against a machine nothing measured. The reader returns the file alongside the case, sorts the files, and takes both numbers from the one recording that fixes the floor.
The disk-cache adversarial suite proved that nothing is served from a full cache root by mounting a small tmpfs, which only exists on one platform, so two legs of the hosted matrix failed on the mount rather than on the contract. The tmpfs case stays, restricted to the platform that has tmpfs and still loud there when the mount is refused. A portable sibling proves the same contract through a cache root that is a regular file, which no privilege bypasses.
Two driver test targets named their backend through a constant, which inlines and links nothing, so a linker that drops unreferenced object files dropped the registration object and the test reported the backend as absent from the binary. Each test now sources the identifier from the call that forces the registration, which is the documented mechanism for keeping it.
Two gates read history against a base ref and each carried its own resolver. They had already diverged: one looked for a name locally before reaching for `origin`, the other prefixed unconditionally and so told a caller who named a revision this checkout holds to fetch a ref in front of it. Both also read the pull-request variable from inside the reader, which answers a pull-request question to a caller who asked about the worktree. The checkout module owns both rules and carries their tests. Each gate resolves the name once at its entry and its reader answers from its arguments.
The dashboard picked its input by modification time alone. A checkout writes every file at the same time, so the tie was broken by the order the directory happened to list, and two machines could report a different snapshot as the latest one. The file name breaks the tie.
The release memory floor is the largest resident working set any registered case declares plus a context reserve, so it is a fact about the benchmark catalog. It lived in the release tooling, which the crate holding the catalog cannot depend on, so the recorded-artifact contracts kept a private copy: a flat 16384 MiB, left behind when production stopped asserting a device class, with a comment claiming it matched the producer. It rejected every recording from a device under 16 GiB that the release gate admits, and it made the closure the fragment claimed incomplete. The floor moves to the crate that derives it. The release tooling and the artifact contracts both read it there, and no file restates a number.
The benchmark, backend and release artifacts still named the source before the hosted-matrix, base-ref, directory-order and release-floor corrections. A recorded result cannot describe a tree other than the one it was measured against. CUDA and wgpu release benchmarks were recorded with thirty measured samples on the release device, then the device-bound backend matrix and cross-backend comparison were written. The release-evidence aggregate was generated last, so every cited artifact and fingerprint is the one this commit contains.
The criterion job switched the pull-request checkout to `origin/main` to record its baseline and then switched back. The checkout now declares CRLF for command scripts; `main` does not, so changing branches makes `cargo_full.cmd` dirty under the branch being entered and Git rejects the switch before the benchmark starts. The job extracts `main` into the runner scratch directory, overlays the current benchmark harness there, records the baseline without mutating the tested checkout, and copies the Criterion baseline into the current target before comparing the pull request.
The compile route mixed semantic domains, launch constraints, selected topology and physical descriptors. Define validated logical and neutral schedule stages, authenticate their identities and provenance, derive operation constraints through the registry, and lower the selected phase before target emission. This also closes the conformance and artifact defects found while migrating every caller.
The gate proved staging legitimate by requiring the producer to perform the device upload itself. That seam is gone: a payload is bound to a graph value through a map the request constructor consumes, so no producer could satisfy the old proof and every staged carrier read as unreachable host data processing. Parameter dataflow now follows a value inserted into a local collection, and a staging helper is proven by either binding a tainted payload into a canonical request itself or returning the exact type a submitting function is proven to dispatch. Both arms carry a mutation-proved case.
The operation-facing dispatch API took a physical launch and a device handle list, so an operation chose the geometry its own program would run under and a missing grid silently meant one invocation. The seam now takes a validated graph plus facts, submission takes an admitted artifact with a frozen schedule, and every wrapper-owned grid helper and route choice is gone. Launch coverage is derived where the program states it: `guarded_logical_span` reads the domain a guard admits, `launch_covers_full_input_span` proves a plan covers it, and geometry omitted from a request is rejected instead of defaulted. The host oracle elimination gate, the launch-geometry closure gate and the registration roster now derive their variant space from source rather than from hardcoded lists that had drifted behind the enums they claimed to cover.
Re-including the forward-or-changed internal tests as `#[cfg(test)] #[path]` modules put them back under a parent whose namespace no longer carries the items they were written against, so a glob import resolved nothing. Each file now names the module it takes `validate_csr_inputs`, the parallel workgroup shape, the dynamic-slot builder and the reference adapter from, and the split schedule module drops the imports it left behind.
The schedule IR, its legality proofs, and transform application shared one file that the file-size gate measured at its cap, so any further proof rule had nowhere to land. Application and the normalization it ends in now live in schedule/normalize.rs, legality.rs keeps only the proof machinery, and the IR types keep mod.rs.
Seven fixtures were copied text: the executor double's admitted output, the unknown-device validated request, a graph output binding, launch-geometry limits, the logical-marker census after lowering, the panic-payload renderer, and the packed witness buffers a suffix3 region program reads. Every copy compiled independently, so two suites asserting one contract could drift apart while both stayed green, and ten crates measured above their duplication pin. Each fixture now has a single definition, placed where the contract it states is owned: shared IR and semantic-seam fixtures in `vyre-test-support`, launch limits beside the driver's launch validation, the panic-payload renderer in the conform library its binary and its contract cases both link. Two V055 suites build their nested-loop programs through the `Node` constructors instead of struct literals. `vyre-megakernel` keeps its inline policy, because linking the shared semantic fixtures from the crate under test compiles that crate twice. `dup-scan` pins move down to the measured counts: vyre-driver-cuda 1594 to 1270, vyre-libs 5472 to 5455, vyre-foundation 2334 to 2328, vyre-driver 461 to 438, vyre-runtime 189 to 170, vyre-driver-metal 18 to 8, vyre-megakernel 8 to 0, conform 62 to 59, vyre-pass-engine 170 to 165, vyre-bench 932 to 928.
The operation inventory, operation schema, optimization corpus manifest, and publish-readiness record were rendered before the reference target facet, the new dependency edges, and the row-38 IR shape landed, so five committed artifacts described a tree that no longer exists. Every one is regenerated by the gate that owns it.
Emission reported a workgroup, a grid and a shared-byte requirement beside the artifact, so a target payload could state a shape the search never selected, and target compilation could rewrite a node program's workgroup after selection. A consumer that read either one launched a kernel nothing compiled. The selected schedule phase is now projected into one geometry record per entry point, carrying the entry dependency order, logical coverage, grid, workgroup, vector width, pipeline roles, ring slots, barrier phases, dynamic shared bytes, launch resource intent and persistence, alongside the workspace plan a runtime allocates for the values the artifact produces for itself. EmittedTargetModule and EmittedDialectModule lost their geometry fields, so an emitter reports bytes and cannot disagree; payload admission compares an entry to the record; node programs are frozen at the selected workgroup during assembly and a mismatch is refused at decode. Schema 10 and a matching frame domain refuse an artifact framed under an earlier schema before its body is read. schema.rs reached 1576 lines, over the production file cap, and is now a directory module of four files: the payload and decode boundary, launch geometry and the workspace plan, the record types, and the selected plan. Field-level validation tests sit beside the records they validate.
A dispatch config carried a workgroup and a grid in two independent options, and the loop that ran a resident sequence forwarded only the grid. A step whose grid was sized for a 64-lane workgroup then ran under the program's declared shape and covered a fraction of its work, with no diagnostic anywhere. Admitted modules had the same shape of problem from the other side: the geometry a payload entry stated was copied into the override fields a tuner also writes, so two authorities described one launch and whichever a backend read, the other was a kernel nothing compiled for. A launch is now one value. `LaunchDirective` carries the workgroup, the grid, the logical coverage and the shared byte requirement together, so a partial launch cannot be expressed; admission builds it from the artifact record for the entry point's own node; a caller that dispatches a program the compiler never saw states one itself. Stating a frozen launch beside `workgroup_override`, `grid_override`, `dispatch_elements` or `dispatch_grid` is rejected rather than resolved, and the check destructures the config field by field so a new dispatch-shape field cannot be added without a decision. The recorded order is the submission order. An artifact whose geometry set or fusion plan lists an entry point before one it depends on is refused at decode, and admission walks the selected plan rather than the bundle's own module list, so no consumer sorts the DAG itself. The runtime's own launch-geometry planner no longer produces an override config; nothing called it, and it was a second authority reachable from anywhere.
A resident launch was refused outright when the artifact carried more than one entry point, so a two-stage plan whose intermediate value never leaves the device could only run by routing that value through host memory. The refusal was the only obstacle: the plan already records the submission order, each entry's ABI already names its own resources, and the workspace plan already assigns storage for every value the artifact produces for itself. Resident execution is now an ordered loop over the recorded modules, each resolving its handles through its own module index, and the artifact session allocates and binds the recorded workspace. Binding over a workspace refuses a caller resource for a workspace-owned value, because a caller buffer in that place is a wrong bind rather than a substitution.
Candidate search held a catalog: the unfused baseline, one single-edge fusion pass, one greedy grouping, a fixed width set and a small topology set. Nothing in it could reach a plan the catalog did not already name, so the same semantic graph produced the same kernel organization on every device, differing only in numbers. Candidate generation is now a grammar with one production per schedule transform, so an exhaustive match closes the family space at compile time: a transform added to the schedule IR fails to build until a production derives it. Derivation is a bounded worklist over the baseline, and the search keeps the unfused, unspecialized baseline in the candidate set. Every step is recorded, so the plan carries a derivation that replays against the schedule it selected, and a search certificate states what each family derived, what constraint propagation admitted, and which stable reason eliminated the rest. Device facts speak in one place. A production proposes every structure the schedule IR expresses and constraint propagation eliminates what the authenticated facts do not grant, so the target-fact and progress checks are reachable and the certificate reports a family as considered and eliminated instead of reporting a smaller search. The concurrent-queue arrangement is selected inside derivation against the dependence analysis, so one candidate bound covers the schedule and its submission arrangement, and a graph with cross-arm hazards keeps its sequential plan. Elimination against the objective is real branch-and-bound: fusion removes at most one launch per production and concurrent or resident arrangements co-issue launches, so the bound divides by the widest arrangement the device grants and omits the non-negative traffic and occupancy terms. A candidate no descendant can bring under the incumbent is eliminated before it is expanded. Tiling and axis splitting are realized in the foundation IR rather than recorded as factors nothing performs: both rewrite the axis nest, which moves SCHEDULE_IR_VERSION to 2 and adds the honest overflow failure for an axis index that cannot be assigned. The artifact schema advances to 11 to carry the derivation and the certificate, and a stale artifact is rejected. The partition arm of the target-fact constraint is removed. Topology legality already proves the partition count and the masking capability for every candidate that carries the transform, so the second copy could only certify what it never checked.
The measured path handed one ranked plan to the target compiler, so a plan the target could not build failed the whole compilation even when a plan ranked behind it was buildable. Emission is now a level of the evaluation ladder: the top ranked plans are emitted, a refused plan is eliminated with MKC014_EMISSION charged to the production that derived it, and measurement runs only on what emitted. A compilation where nothing emitted fails with the refusal instead of returning a plan the target cannot build. The certificate is canonicalized after the ladder records its eliminations, so a compile records one certificate whichever level removed a family. The search fixtures the grammar contracts used are now shared, and the ladder has its own contracts: continuation past a refusal, failure when nothing emits, measurement overturning the analytic ranking, and a selection no device timed recorded as unmeasured.
Candidate search admitted a spatial partition, a persistent queue, a pipeline, an asymmetric join, an axis remap, an axis reorder and a recomputation over any phase, including phases whose invocations combine into one location. Over integer addition the resulting order is unobservable. Over floating-point addition it is a different number, and the difference is data-dependent, so a selected plan reached a caller as an accuracy result rather than as a failure. Nothing in constraint propagation asked. Legality now comes from two statements that already have owners. `ScheduleTransform::combine_order` states per transform whether the order it produces differs from the order the program states, in the crate that owns the transform vocabulary; `SetWorkgroup` answers conditionally, so freezing a phase at a shape its own regions declared still reshapes nothing and the baseline survives. `algebraic_reordering::reordering_class` answers the program half from operator laws in the algebraic law registry and the element types the program declares, so an extension operator that registers its own laws is answered without being named and an unregistered one is ordered. `CombineKind` in vyre-spec maps atomics, subgroup reductions and collectives onto one law table, and `visit::expr_combine` and `visit::node_combine` record which IR variants combine at all: three exhaustive matches with no catch-all arm, so a new operator or variant fails to compile instead of defaulting to reorderable. The constraint reuses `MKC001_NUMERICAL`, so no prune vocabulary or artifact schema moves. An exact reduction keeps every reordering production; a rounding one keeps fusion, fission, dispatch cuts, synchronization, memory placement and prefetch, and still compiles.
The selection cost ranked launches, materialized traffic and a coarse occupancy cliff. Instruction mix, matrix-engine work, rendezvous and idle lanes carried no term at all, so a candidate that traded a launch for a whole-grid rendezvous was ranked as pure launch savings, and a fusion whose replayed working set fits the device cache was charged full memory time for it. The occupancy budget was also the architectural register ceiling, which is the count above which no launch exists, not the count above which occupancy falls. Program statistics now state barriers, grid rendezvous and tile statements. Backends report registers and invocations per compute unit, the device-wide cache capacity, and the ceiling separately from the occupancy budget. CostBreakdown carries a count for each of the new terms and prices it only where the device reports the matching rate, so a rate nothing measured charges nothing rather than an invented weight. Topology legality now rejects a register allocation only above the architectural ceiling; between the occupancy budget and that ceiling the allocation spills, which is legal and priced. Every field states its unit and where its weight came from, and the field set is derived from the serialized shape at run time, so a field with no provenance row fails rather than entering the total unexplained.
Candidate resource verification pushed every estimated spill onto the violation list and cleared `is_within_limits`, so a candidate one register over the occupancy budget was reported as illegal as a candidate over the architectural ceiling. Those are different facts. Above the occupancy budget the target compiler spills to local memory and the launch runs, which costs traffic and occupancy and can still win; above the ceiling the device refuses the launch and there is nothing to weigh. Treating the first as illegal eliminated the unrolled and tiled candidates a register-poor target most needs. The limits now name both thresholds and the report states each alongside the spill bytes it implies. Only the ceiling rejects, and a target reporting no ceiling rejects nothing for register pressure rather than falling back to the budget and reintroducing the defect. The fabricated limit set is gone with it. A default of 48 KB, 128 registers and 1024 threads decided legality on numbers no device produced, so limits are now stated from what a target reports.
Registers and local-memory spill are assigned by the target compiler, so no estimate derived from the IR states them and only the loaded module holds them. Compile-time ranking spent its measurements in the analytic order, which put the first launch on whichever plan the estimate liked rather than the one the device would run well, and an allocation above the architectural register limit was priced as occupancy loss instead of rejected as unrunnable. `FinalistEvaluator::resources` and `ArtifactInstance::emitted_resources` are the two seams that answer for an emitted entry point. Each returns one record per payload entry with registers and spill per invocation and statically declared shared bytes. `compile_measured` projects those records onto the fusion groups the cost model prices, multiplies spill by the invocations the authenticated geometry launches, re-prices every emitted finalist through the reported figures, eliminates one above the register ceiling with the emission reason, and measures what survives in the re-ranked order. CUDA answers from `cuFuncGetAttribute` on the loaded function, which is the only place a physical register count exists for a virtual-register PTX module; a backend whose API reports none of it returns default records and keeps the estimate in force. `vyre-lower`'s `rank_measured_candidates` was a second ranking model with no production caller, fabricated defaults, hardcoded float weights and device names as strings, tested only against itself. Its concern is register spill in ranking, which is now priced from device-reported facts with units and provenance, so the model and its contract test are deleted rather than left to disagree with the one that runs.
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.
IMPORTANT: do not merge without explicit approval from me.
This branch is where a large restructuring campaign lands. It is not a single change and it is not ready to be squashed into
mainon a green checkmark. Read the sections below, then decide.mainis untouched at90991bb2e8. This branch is at51032f97d2, 2215 commits ahead: 7556 files changed, 692153 insertions(+), 653191 deletions(-). It is the only open pull request on this repository.What this branch changes
Crates carry one concern each. The C frontend and the Rust frontend are removed from the tree. Eighteen composition domains, 991 files, moved out of
vyre-primitivesintovyre-libs, which leavesvyre-primitivesat 20 files and 3035 lines:hardware/with its nine intrinsics, the catalog, the markers, the organization, and four items still scheduled to leave (wire.rs,ir_safe.rs,dispatch_grid.rs,vfs/). The rule the tree is converging on is thatvyre-primitivesholds only operations that cannot be composed, and every composition lives invyre-libs.File shape.
vyre-megakernel/src/lib.rswent from 2026 lines to 75 across nine modules named for what they own. 98 residue directories left over from removed crates and moved domains are gone from the working tree.Gate truth. A gate that cannot fail was treated as a defect, not as a passing gate. Concrete cases closed here: a required command whose filter matched nothing passed forever; a placement predicate used
is_dir(), so an emptiedvyre-primitives/src/matchingstill named itself the owner of eleven operations, and the predicate now reads for Rust source recursively instead of for directory existence; the op matrix took its owner from the checkout rather than from the id prefix.Duplication closed rather than pinned. Workspace duplicated lines went from 20372 to 19479,
dup-scanfrom 4 findings to 1, andxtask,xtask-registryandstructure-gatereached 0 against a pin of 0 without moving the pin. Every pin that moved, moved down with a measured count. The largest single closure was one owner for the fixed-point parity helpers that 53 integration suites had each restated: 50 xorshift copies, 15 encoder copies, 7 multiply copies, 8 sample generators and 13 unit constants deleted.Documentation is checked against the tree. New
docs-registergate, backed bydocs/REGISTER.toml: banned register phrasing on authored pages, documentation as its own subject, host-local build configuration on a contributor-facing page with the name set unioned at run time from the register pluscargo_fullexport lines plus.cargo/config.toml[env]keys, and every repository-root Markdown page declared indocs/DOCS.tomlwith its audience set derived from the audiences the page rows use. Sixteen unit tests, every clause proved red by injection.One device-visible correctness fix worth calling out. The workgroup Blelloch sweep ended on an unguarded store with no barrier behind it, and
frontier_word_block_offsets_single_workgroupreadsscratch_a[lane - 1]on the statement after the sweep returns, so a lane could read its predecessor's slot one round early and take a block offset short by the previous block's own count. The reference interpreter steps lanes in order, so no value assertion could see it. Publication is now the sweep's contract and two tests assert the emitted shape.Benchmark evidence stopped overstating itself.
synthetic_cpu_countregenerated every record from its index inside the timed region, twelve to twenty-four rotate-multiply rounds per column, while the device side received pre-materialized, pre-uploaded buffers. Reported speedups were 5508x to 6729x for the count patterns against 928x for the one case that already read materialized bitmaps, and the difference was the generator. The baseline now counts over the same host buffers the device reads. Ten baseline labels named software this checkout does not link, including tree-sitter, libclang, Hyperscan, ripgrep, egg,rugwith a GMP backend and a hand-tuned C threaded interpreter; every one of those cases timed an in-tree scalar Rust routine. Labels now come from one owner and a test resolves every named crate against the workspace members and thevyre-benchdependency tables read at run time. A second test compares each release row's primitive, baseline and threshold against the manifest the harness enforces, which immediately found a 100x case with no target row at all.Gate state on this branch
Measured by one
xtask gatessweep at this head, plus the gates that can only answer onthe host that recorded the evidence, run there at the same tree.
xtask gatessweepbackend-matrixbench-releasevyre-release-gaterelease-benchmarksbench-crossbackrelease-evidenceevidence-pathsrelease-docshygiene-matrixpackage-readinessdup-scanwhats-similarworkspace-check,workspace-clippy,workspace-docsThe single nonzero reading is
backend-matrixon a host that is not the recording device:the artifact records 24564 MiB and
sm_89, the probing host reports 12288 MiB andsm_86,and the gate is doing its job by refusing to accept one device's facts as another's. On the
device that recorded the evidence it reads 0, which is why its CI job runs there.
Recorded conformance on this checkout: 349 of 349 operations prove on CUDA, on WGPU and
against the reference interpreter, 1047 pairs across three backends, 0 failed pairs in each
certificate. The proof completes in 74 s; see the teardown fix below for why it used to
take hours.
The release benchmark baseline is recorded, not deferred. Both suites were measured under
the release profile with 30 measured samples per case, on a device holding 139 MiB of 24564
with no other job on the host, and all 34 workload artifacts plus the two suite indexes,
the cross-backend comparison and the release axes cite one source-tree fingerprint. The
axes read warm 4.766 us per file, cold pipeline build 1.214744 ms, 620.153 GiB/s scan
throughput, 0 ulp drift, 24564 MiB of device memory.
One gate reading that changed
whats-similar: 0 findingsused to be reached by skipping 504 pairs. It now scans 268registered ops and skips none: all three skip categories sit at a measured ceiling of 0 and
no pair crosses the duplicate or similarity floor, so the zero is the scan's own answer.
The hand-typed table is still there and still read, one layer over:
IMPLEMENTATION_FAMILY_ROWSin
xtask/src/gates/implementation_family.rsrecords (operation id, shared builder), andlego-no-reinventionnow skips a pair recorded there or inREVIEWED_DISTINCT_OPERATIONS,because two operations reached through one shared builder share that builder's emitted
shape and reporting them demands an extraction already done. Deriving those rows instead of
typing them is blocked on attribution: a shared builder such as
binary_word_program(op_id, ...)wraps the region with the calling op's id, so the treecannot tell which builder emitted a body.
What is still open
Verified against this checkout, not carried over from an earlier reading.
The benchmark target registry states every baseline as a CPU one. Each
[[target]]indocs/optimization/BENCH_TARGETS.tomlcarriescpu_baselineandmin_speedup_over_cpu_sota, and the optimizer-impact row fills them with a self-comparisonthe source declares as
SelfUnoptimized. The vocabulary the file publishes is inert: notarget declares a class. Renaming the keys and making a target's class checkable against
the case it names is a 40-row schema change with its own checker, so it is a backlog row,
not a late edit to this branch.
The IR has buffers and no tiles (#37) and an operation declares its own launch
geometry (#38). Both are specified, neither is built, and both are described below.
Items previously listed here and now closed on this branch: the sweep at this head, above;
the recorded evidence, re-measured from this head after the harness changed shape; the
fresh release benchmark baseline; the
whats-similarreading, now measured with nothingskipped; the two families without a recorded performance contract, both of which now record
a passing one (
foundation.reduce.sum.crossoverat 1.89x against a 1.1x floor,foundation.optimizer.impactat 428.6x against a 1.0x floor); thevyre-libsdefault-feature build; the CUDA
MKC026_FINALIST_EVALUATIONfamily (339 of 339 pairs passon CUDA); the debug-built benchmark numbers; the feature-isolation sweep that could not
fail; the
release-docsanddup-scanfindings;vyre-libs::test_parity_oraclesin apublished surface (it is
#[cfg(test)]); and theverified_loweringerror strings on thehot path (every
format!there is inside amap_err).Two architectural limits, specified and not yet built
Both are prerequisites for compiling a fused model forward pass into one kernel, and both change what an operation's interface is, so they are not deferrable optimization work.
The IR has buffers and no tiles (#37).
Exprproduces scalars andNode::Storewrites one element at an index, so the only medium two operations can use to exchange data is a buffer, including two operations fused into one region. Every surviving operation boundary is a global-memory round trip, no instruction that reads a register fragment can be named, and an algorithm whose speed is residency rather than arithmetic cannot be written. The measured floor: a predicate count over threeu32columns reads 12.58 MB in 26.7 us, which is 471 GB/s against roughly 1.8 TB/s of device bandwidth, on the simplest program in the tree.An operation declares its own launch geometry (#38).
multi_block_prefix_scandeclared a 1024-invocation workgroup as a constant in library code; on a target admitting 256 the program was refused, and the only repair at that layer was to declare 256 everywhere, narrowing the cooperative block on targets that admit 1024. Invocations per workgroup, tile size, elements per invocation, register budget, occupancy, shared footprint and pipeline depth are all decided before the target is known, and the plan search consequently ranks one candidate.Lane state
Every lane is merged and no lane is still running.
lane/contract-architecture,lane/finish-reconcile,fix-cuda-adaptive-axiom,fix-libs-csr-contracts,fix-libs-rms-parityandfix-libs-sinkhorn-contractsare all contained in this branch;their worktrees are deleted. Work since then is on this branch directly.
How to read the diff
The insertion and deletion counts are dominated by moves, not by new code: the 991-file composition move, the frontend removals, and the residue directory cleanup. The commits are individually scoped and each merge commit states what was checked, so
git log --first-parent main..integrationis the shortest path through it.Two rulings that changed the shape of the remaining work
One canonical space.
xtask/ci-registry.tomlat 694 lines andxtask/src/gates/ci_registry.rsat 1631 lines are the wrong shape twice over:one file per hundred declarations instead of one file per declaration, and
hand-written checks where a loader over data belongs. They also cover CI only,
while tests, scripts, crate pages and evidence stay scattered across 38 crates.
They are deleted, not extended.
registry/at the workspace root declares everyrunnable and every placement fact, one TOML file per declared gate, CI lane,
script, crate and evidence artifact, with a single loader crate as the only
parser and every consumer deriving from it at run time. Adding a member with no
file turns the suite red, which is the property the tree lacks today: a stray
script is invisible because nothing enumerates the directory, and a hand-typed
list goes stale in silence, which is the same failure as having no test.
No lane patches, and nothing merges without a spoken guarantee. A change
that is architectural gets escalated and fixed at its own level; a local
workaround in place of that coordination deletes the PR that contains it. Before
any branch merges, the owner states in words that its entire subsystem needs no
refactor, with named exceptions, and each exception becomes a row with its
long-term fix. A guarantee with an honest exception is worth something; a blanket
yes that is later disproved costs the PR.
Landed since the last body revision
A benchmark baseline does not switch the tested checkout. The Criterion job switched the
pull-request checkout to
origin/mainand back. The checkout now declares CRLF for commandscripts while
maindoes not, so changing branches madecargo_full.cmddirty under the branchbeing entered and Git rejected the switch before a benchmark ran. The job extracts
mainintothe runner scratch directory, overlays the current harness, records there, and copies the
Criterion baseline into the current target without mutating the tested checkout.
A test that opens a device is admitted by the device feature. The hosted matrix builds
every package with default features and has no device on two of its three platforms, and it had
never passed on this branch. Eleven inline tests in the wgpu driver acquired the singleton
device without naming
device-tests, so the default test surface demanded an adapter and theleg failed on
Probed adapters: []rather than on a contract. The tests are unchanged and stillrun, on the lane that has the device. The gate that owns this rule reads constructor stems and
cannot see a free function that hides one; the GPU-less legs already turn red on exactly this
mistake, which is the check that closed the class, so the gate keeps its stated blind spot
instead of gaining a weaker second owner.
A registry test links the registration it asserts. Two driver test targets named their
backend through a
const, which inlines and references nothing, so a linker that dropsunreferenced object files dropped the
inventoryregistration and the test reported the backendas absent from the binary. This is invisible on ELF and fatal on Mach-O. Each test now sources
the identifier from the call that forces the registration, which is the documented mechanism for
keeping it.
A weight is read from the recording that fixes the floor. The megakernel cost model took
its launch floor from the cheapest recorded case and its traffic rate from whichever recording
the directory walk returned first, so the two numbers could describe different devices and every
fusion decision was priced against a machine nothing measured. The reader returns the file with
the case, sorts the files, and takes both numbers from the one recording that fixes the floor.
A full filesystem is one platform fact and a refused write is not. The disk-cache
adversarial suite proved that nothing is served from a full cache root by mounting a small
tmpfs, which two platforms of the matrix do not have. The tmpfs case stays, restricted to the
platform that has tmpfs and still loud there when the mount is refused, and a portable sibling
proves the same contract through a cache root that is a regular file, which no privilege
bypasses.
A recorded artifact reads the same on every host. A per-backend benchmark artifact identity
was rebuilt with the host path joiner, so a recording made on a host that separates with a
backslash names an artifact no declaration lists, and two registry tests compared an error that
carries a host path against a slash literal. The identity is now a repository-relative string
split at the last slash and the tests build the expected path component-wise. The tree also
declares LF line endings, because the provenance head of a recorded artifact is a literal byte
sequence that a translated checkout breaks.
One owner answers which ref a run compares against. Two gates read history against a base
ref and each carried its own resolver, already diverged on whether a bare name is looked for
locally before
originis tried, and both read the pull-request variable from inside thereader, which answers a pull-request question to a caller who asked about the worktree. The
checkout module owns both rules and carries their proving tests; each gate resolves the name once
at its entry and its reader answers from its arguments.
docs-couplingwas the gate that failedon every leg for this reason.
A cell holds its own initializer. Three lazily initialized statics in the wgpu driver kept
their initializer in a separate function, so the declaration did not state what the cell holds.
Each is now a lazy cell initialized at its declaration.
The dashboard names one latest snapshot. The bench dashboard picked its input by
modification time alone, and a checkout writes every file at the same time, so the tie was
broken by the order the directory happened to list. The file name breaks it.
A past baseline file is read through the fields it wrote. The required
gatesjob hadnever reached a verdict on the sweep, and this is why:
gate-canonproves a pinned count onlymoves down, it reads the before from the baseline file at the merge base, and it parsed that
revision with the working-tree row type, which denies unknown fields.
mainstill pinsoutput_lines, so the gate could not run at all and the job reportedcannot parse 90991bb2e8:xtask/gate-baselines.tomlinstead of whether a pin had risen. Everylocal run hid it, because a run with no base compares the worktree against
HEAD. A pastrevision is a record this gate does not own, so it is read through the fields that revision
wrote: a row with a count is compared, a row that pinned none offers no direction to judge, and
a file that is not a baseline file at all is still a failure. The working-tree copy stays
strict, so the leniency cannot leak into what this branch pins. Against
mainthe gate nowreads 131 pinned rows, 298 gate sources, 56 ratchet constants and 0 findings.
The sweep host installs the cross targets the tree declares.
cross-targetcompiles theproduct crates for one triple per
target_osthe source branches on and fails closed on atriple that is not installed, because a gate that judges fewer platforms than the tree declares
is the defect it exists for. Nothing installed those triples on the runner, so the sweep failed
on
x86_64-apple-darwin. The install runs inside the checkout, becauserust-toolchain.tomlpins the toolchain every cargo run here uses and a target added to whatever the toolchain action
installed last lands on a toolchain cargo never selects. A triple that stops being named in the
workflow fails the gate by name, which is why the list needs no second owner.
A resident dispatch is judged on what it amortizes. The required GPU lane had never
passed, and one assertion is why: the resident CUDA scaling fixture claimed the tree shape
holds
gpu/cpuunder 0.50 at 50k nodes. No device satisfies that. The lane's own runmeasured 0.75x on the 128-SM part that records the release evidence, and an 80-SM part
measures 1.15x; both clear the release floors, so gating the claim on the floor would not
have saved it, and fitting the number to either measurement asserts the device rather than
the pipeline. A resident dispatch pays a fixed cost before the first element, so what the
pipeline owns is how that cost amortizes: every measured shape must improve its ratio
against the CPU pipeline by at least a factor of two between the smallest and the largest
node count it runs at. On the recording device that reads 20x for tree, 16x for wide and two
orders of magnitude for chain, and with the factor raised to 100 the fixture fails naming
the shape and both ratios, so the comparison is live. The node counts, the shape list and
the rule that skips the chain shape at scale each have one owner now, so a shape added to
the list is judged instead of ignored. A speedup over the CPU pipeline is a release-path
claim, it has no benchmark case behind it, and it is recorded as unproven rather than
asserted from a driver test.
One vocabulary decides what hidden fallback language is. The production backend scan
that the release gate blocks on carried five phrases of its own. The hygiene family that
owns that vocabulary declares ten, so
skip: no gpu,skipped: no gpu,cfg(not(feature = "gpu")),synthetic gpu timingand the fake timing formula werereported by the tree-wide scan and never read on the driver surface. A gate that reads half
a vocabulary certifies the half it never looked for. The family now publishes its phrases
and the scan reads them through that accessor, so there is one list; the test derives the
expected set from the owner and scans a fixture holding every phrase, and with the old
five-phrase list in place it fails naming the four it never read. The four production scan
roots hold none of the widened phrases, so the gate stays at 0 findings.
One walk decides what reading this tree means.
hygiene-matrix.jsonrenders one row perfinding in the order the walk produced them, and the shared walk passed readdir order
through, so the committed artifact was a property of the filesystem rather than of the
source. The required
gatesjob is what proved it: the same 329 findings, regenerated onthe runner's own checkout of this commit, came out in a different sequence, and the artifact
comparison reported a stale artifact for a tree nobody had changed. Order now belongs to the
one walk every gate reads the tree through, so no renderer has to rediscover it; the backend
matrix drops its own recursive
read_dirfor that walk and prunes build output like everyother gate. A contract test asserts name order over a fixture built in descending order and
asserts the prune still applies at every depth: with the sort removed it fails with readdir
order,
dir14first.The recorded evidence names the tree it was measured on. The benchmark harness changed
shape in the two commits before it, and the harness is inside the source-tree fingerprint,
so 113 recorded verdicts over 55 artifacts named a tree that no longer existed. Both suites
are re-recorded on the release device at 30 measured samples from a clean tree, and the
cross-backend table and the aggregate evidence are regenerated from them. A fingerprint is
what makes a measurement describe a source, so this is not bookkeeping: the alternative is
evidence that cites code nobody ran.
One builder turns a contract description into a contract. Both benchmark case shapes
held their own copy of the same construction, so the baseline class had to be threaded
through two identical bodies and a third case shape would have copied it again. The copies
were also measured: they pushed
vyre-benchfour lines past its duplication pin, which ishow a repeated field literal shows up as a gate finding. A description is now built by
naming the comparison it makes,
cpu_sotaorself_unoptimized, so no site can inherit aclass by leaving a field out, and the pin moves down from 948 to the 932 the tree measures.
The target registry lists the classes the source defines.
docs/optimization/BENCH_TARGETS.tomloffered areference_correctnessbaseline classthat no
BaselineClassvariant declares, and omittedSelfUnoptimized, which one does.The test that read the list asserted the stale triple back, so the registry certified a
taxonomy the source had never had.
BaselineClassnow owns the registry keys behind anexhaustive match and publishes the set, and the test compares the registry against that
set: a class added later does not compile until it names its key, and the registry does not
pass until it lists it.
A compute driver does not open a graphics context. Instance construction and every
adapter probe asked wgpu for
Backends::all(), which includes GL. The GL adapterduplicates the Vulkan device on this hardware, lowers nothing this driver emits, and
carries an EGL context whose thread-exit TSD destructor is registered per thread. A stack
capture of a stuck conformance proof showed that destructor blocked on an EGL mutex while
vkDestroyDevicejoined the same thread and four other threads held the Vulkan loaderlock: a cycle no step deadline can break, because the thread it would interrupt is already
inside thread exit. The required
Conformancecheck had never passed on this repository;its last run spent 3 h 32 m at 100 percent CPU and 0 percent GPU utilization before being
cancelled.
COMPUTE_BACKENDSnow names the set this driver can lower to and every probeuses it. The same full proof reports
backends=3 selected_ops=349 prepared_ops=349 pairs=1047 workers=16 total_ms=74198, exit 0, certificate signed. ABackends::all()member that is neither dispatched nor excluded with a stated reason turns the driver's
tests red, and the concurrency contract now drops each acquired backend and reports
through a channel under a deadline, so a teardown regression fails as an expired wait
instead of an unjoinable hang.
An out-of-range store is discarded, never redirected. Both emitters folded an
out-of-range element index to zero and then wrote through it. That is sound for a load,
whose value is discarded, and corruption for a store: element 0 receives whatever the
out-of-range lane carried. A conformance case read 47 from a one-element output buffer
where the reference reads 15, because lane 32 of a 64-lane dispatch stored into the
shorter of two buffers. The kernel-wide exit does not cover this: it compares the global
id against the dispatch element count, which comes from the longest buffer in the program.
Every global store now carries its own buffer's bounds test, on both backends and on all
four routes: scalar, byte read-modify-write, vector op and fused vector chain. The PTX
atomic predicate is unconditional and no longer optional in its own type. The reference
interpreter drops such a store and records it, so this is what makes a device result agree
with the oracle for any program whose buffers have different lengths. Two new contracts
close the class structurally rather than by value: the naga side walks the emitted module
and refuses a storage store that is not inside an
index < lengthtest, the PTX siderefuses an unpredicated
st.globalline, and both read their population from the sharedadversarial corpus at run time.
A reported device limit is what the backend can run. The adapter-limits contract
compared
max_compute_invocations_per_workgroup()against the raw wgpu device limit. Thatreported value is deliberately the dialect ceiling, 256 for WGSL, which every recorded
wgpu workload artifact carries where the CUDA artifacts carry 1024. The contract now pins
the reported value to the capability record the rest of the driver reads and requires it to
stay within the device limit, which is what a caller sizing a dispatch depends on.
A device-acquiring test compiles only where a device is. The conform lens parity suite
acquired hardware from a target that built under default features, so a CPU-only checkout
compiled a test it could never run. The device-acquiring halves are now separate targets
behind
required-features = ["device-tests"], and the live backend accessor exists onlyunder that feature, so the compiler answers a question a source scan was being asked to
answer.
One registry-net driver, many populations. The out-of-bounds registry net existed once
per crate, each copy walking its own catalog beside the driver rather than inside it.
RegistrySweep::from_catalogowns the walk, refuses an empty catalog, and reports fixturedcoverage: 9 of 9 primitive entries and 340 of 340 library entries, 0 entries out of reach.
A baseline class names where the baseline ran. A benchmark baseline class is a
provenance claim, and a reader multiplies the recorded number by what it names.
foundation.optimizer.impactdispatches the same program twice, with and without thesemantic optimizer, and filed the pair as
CpuSota, so a 378.9x self-comparison read as aspeedup over a host implementation of the primitive. The timing was already in the
artifact:
baseline_dispatch_nsexists only when the baseline arm ran on the device, and 46recorded CPU baselines carry no such metric while that one carried 5152 ns.
BaselineClassgains
SelfUnoptimized, every case declares its own class instead of inheriting one fromthe shorthand constructor, and release evidence is refused when a host class records a
dispatched baseline, when a device class records none, or when the recorded class is not one
the enum declares. The placement is an exhaustive match, so a class added later does not
compile until it says which side it is on.
A gate job runs where its evidence was recorded. Three checks queued indefinitely
against a runner that is offline, two of them required, so no cycle could go green. The gates sweep and the coverage job now target the host that holds the
recording device, which is also what makes
backend-matrixconsistent: that gateregenerates device facts and compares them line by line, so a sweep on a second adapter
reports every device fact as divergent.
A fixture arity is the arity the host supplies. The generated hardware-registry matrix
compared each fixture's buffer count against inputs plus outputs, while a packed-u32 entry
deliberately supplies host buffers only, because a backend-allocated output takes no host
slot. Nine entries failed a sum that demanded a placeholder the artifact ABI rejects. The
contract now reads the input count it is about. The
--all-featurestest surface isexecuted by the coverage job alone, which is why this never reported: that job was pinned to
the offline runner.
A package loop reports every failure it found. The per-package CI step ran under
bash -e, so the first failing package ended the step and hid every package after it. Theloop now records each failure and exits at the end with the list.
Merge state
integrationis at51032f97d2on origin and this branch is that ref. Every lane is merged andcontained:
finish-vyre,lane/gpu-evidence-ci,fix-cuda-adaptive-axiom,fix-libs-csr-contracts,fix-libs-rms-parityandfix-libs-sinkhorn-contractsare allancestors of this ref, and no worktree remains beside
mainandintegration. No pin hasbeen raised, no prose exemption has been added, and nothing red has been merged. The only
pin that moved went down, from 948 to the 932 the tree measures, in the commit that removed
the copies it counted.
An earlier revision recorded the work of that day: the tree is rustfmt-clean; every step of
the Windows matrix is written for bash and the
ci-shellgate holds that class, becausethe one PowerShell step this tree ever had was a parse error that failed every Windows job
while saying nothing about its subject; a backend feature marker citing a module root is
scored against the module rather than the root file, and excludes that module's test
material; both generated error catalogs are written by the gate that owns the inventory;
every published multi-block scan spelling is executed against a reference witness; the
semver check compares the members its baseline release declared instead of aborting on the
first member that release never carried; and recording a release benchmark baseline refuses
a device another process holds for compute.