Skip to content

A runtime row carries the architectures it registers, not one model's Bool -- and four GB10 images say what they hold for DeepSeek V4.1 - #11016

Merged
gunbai-bot[bot] merged 31 commits into
mainfrom
session/loyal-ram-346
Sep 11, 2026
Merged

gunbai-bot[bot] merged 31 commits into
mainfrom
session/loyal-ram-346

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

What this changes

1. A runtime row carries the architectures it registers, not one model's Bool

ServingRuntimeRow.registers_glm5_next: Bool is replaced by registry_reading: ArchitectureRegistryReading, and serving_arm_admits asks whether the checkpoint's own architecture is a member of what that reading recorded.

The Bool answered one model's question. It could say nothing about DeepSeek V4.1 — DeepseekV41ForCausalLM did not exist when either runtime row was written — while both rows looked complete. Membership answers every such question, and a miss is a measured negative with a date on it rather than an absence of modelling.

  • ServingCheckpointRow gains architecture, settled from architectures[0] of config.json at each row's pinned revision.
  • The readings live in gunbc.spark.runtime_architecture_registry_reading, one per digest, each carrying image reference, host, observed_at, instrument and answer. A registry list is not something a publisher declares — it is what a call returned on a named host on a named day — so it is a receipt in the observing layer, and extdeps.docker.images.* keeps only publisher-declared identity.
  • The observed digest is frozen into the reading. Desired identity (the image module's pin) is joined to it by reading_applies_to, and serving_arm_admits refuses — naming both digests — when they diverge. A repin therefore costs one probe instead of silently re-addressing an old observation to an image nobody looked inside.

2. What four GB10 images actually hold for V4.1 on sm_121

gunbc.spark.serving_runtime_capability_probe records five capabilities per image, each asked by its own symbol, none derived from another. Probed inside exact digests with docker run --gpus all on spark-a3ee (NVIDIA GB10, torch.cuda.get_device_capability(0) = (12, 1)), 2026-09-11:

image framework archs V4.1
aidendle94/sparkrun-vllm-ds4-gb10 (production) vLLM 0.21.1rc1.dev339 361 architecture absent; 3 of 4 kernel families absent, KV unprobed
ghcr.io/gitcommit90/glm-5.3-one-spark vLLM 0.1.dev20051+g487ecf187 377 same
timothystewart6/vllm-gb10 (newest published GB10 vLLM, 2026-08-28) vLLM 0.28.1.dev0 378 same
xomoxcc/dgx-spark-sglang:0.5.18-sm121 SGLang 247 architecture absent; other four refuse

No published image registers DeepseekV41ForCausalLM on sm_121. The candidate roster is declared beside the result — including candidates that were not probed and why — so that finding has a readable denominator.

The lookup is keyed on (image, capability, device) and returns OutcomeFound / OutcomeUnrecorded / OutcomeConflicted: readings from one compute capability cannot answer for another (the vendor is part of the key — AMD's (12, 1) is gfx121, not sm_121), and disagreeing rows are a lost single-valuedness rather than a value to pick between.

One capability is withdrawn rather than reported. Three FP4-KV readings were taken with operator names that do not exist at the pinned upstream revision — a name that cannot be present answers absent for every image, so they measured the instrument. They are re-typed KernelProbeSymbolUngrounded (counted as unprobed, never missing), and reading the real roster showed the question was wrong too: the nvfp4 DS-MLA layout is not selectable at device major 12 at all, so the capability is renamed MlaKvCacheLayoutAdmitted and carries a frontier naming extdeps.vllm.deepseek_v4_1_sm12 instead of a corrected spelling of ours. The class is filed as gunbc.recurring_failure_mode.a_probe_symbol_that_cannot_exist_records_a_false_absence.

3. Prerequisites are not feasibility

Every probe here asks whether a symbol is registered or a module imports: that rules an image out decisively and cannot rule one in. The positive arm is V41RuntimePrerequisitesPresent, carrying the profile it holds for and what remains; executable feasibility stays a RuntimeFeasibility launch receipt in serving_deployment_selection. Requirements are profile-bound (V41SpeculativeDecode / V41BaselineDecode) so DSpark is required only where speculation is selected — mandatory-for-everyone converted a deployment choice into a hardware verdict.

v41_sm121_build_obligation states what the image that would work must satisfy: subject, source revision (vLLM 07b7553), the profile's own capability list, and a discharge that is another executed probe plus a serving receipt — not a green build log.

Consumers

v41_runtime_verdict, v41_images_with_prerequisites, the reading lookups and the repin join are executed by test.claim.spark.serving_runtime_capability_probe_witness (20 witnesses), which asserts the sweep's standing, the per-image verdict, that an ungrounded symbol reads unprobed and never missing, that a repinned digest finds no rows, that a same-numbered other-vendor device finds nothing, and that every capability row's subject is a digest some reading was taken in. The declared frontier is DSV41-2, which consumes the verdict as RuntimeFeasibility evidence.

Stacking

Stacked on dsv41-0-deepseek-v4-1-flash-authority (#11007) so the architecture name is imported from its authority rather than duplicated. Land #11007 first.

Evidence

  • Probe witnesses 20/20 PASS; external_model_scope_witness 28/28; citation_cit1_witness 22/22.
  • Mutation control in an isolated worktree reds 4 of 7 of the original set, with the 3 mutation-independent ones staying green.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP

Brian Searls and others added 11 commits September 11, 2026 02:22
…ub revision.

V4.1 is a separately versioned upstream, so its config, KV/parameter footprint, and encoder live here rather than as a fork of the V4 family module.

Co-authored-by: Cursor <cursoragent@cursor.com>
…card.

The card contradicts itself on parameter totals; component byte sizes now come from shard headers at dba1be0a40aa45a94ad051997016db3960a90277, and the new module is enrolled as an ExternalModelScope carrier.

Co-authored-by: Cursor <cursoragent@cursor.com>
The tree API's 510296708312-byte shard total is object-store file size, not serving memory and not index metadata.total_size; deepseek-recipe stays a different product.

Co-authored-by: Cursor <cursoragent@cursor.com>
…iterals.

Safetensors payload bytes stay the authority, card parameter counts are labelled as card, hosted API id is dropped, and witnesses now check yarn/budget/prefill/DSML relations rather than echoing declarations.

Co-authored-by: Cursor <cursoragent@cursor.com>
… Bool -- and four GB10 images say what they hold for DeepSeek V4.1

ServingRuntimeRow.registers_glm5_next answered exactly one model's question, so it was silent about DeepseekV41ForCausalLM while looking complete. It is replaced by the image's complete architecture registry, read by executing ModelRegistry.get_supported_archs() inside each exact digest on a GB10, and serving_arm_admits now asks membership against the checkpoint's own architecture (taken from config.json at each pinned revision). Each registry lives in that image's own extdeps.docker.images module rather than in the arm.

Beside it, gunbc.spark.serving_runtime_capability_probe records what four images actually hold for V4.1 on sm_121 -- architecture registration, FP4 weight kernels, FP4 KV-cache kernels, CSA2 compressor kernels, DSpark speculator -- each asked by its own symbol inside the digest, with the candidate roster and its unprobed entries declared beside the result so "no image admits V4.1" has a readable denominator. The SGLang candidate refuses four of the five rather than answering them, because they are asked in vLLM's vocabulary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
The .dag parser treats a newline after `count:` as the end of the argument, so the payload-total fold was not a module.

Co-authored-by: Cursor <cursoragent@cursor.com>
The rework kept the function that multiplies by deepseek_v4_1_flash_yarn_factor after deleting the binding (review 63389).

Co-authored-by: Cursor <cursoragent@cursor.com>
…receipt behind it

Review found two second-authorities and both are cut at the root.

The serving arm rows carried a literal digest and a literal vLLM version beside the extdeps modules that own them, so a re-pin in extdeps would have left the row launching the old image with nothing refusing. They now read the pinned reference and the declared version from the image's own module. hub_cli_path keeps its single home on the arm row, and the copy this branch had added to the gitcommit90 module is deleted rather than duplicated one layer down.

The probe module had minted its own ComputeCapability carrier and an sm_ label nothing called, beside extdeps.gpu.types GpuComputeCapability which already models the vendor-qualified major/minor and already derives that label. The reading is now that type. It stays a gunbc observation: extdeps.systems.nvidia's GB10 row still declares no compute capability, because the cited NVIDIA pages do not state one.

Sweeping the same class found two declarations of this branch's own with no consumer -- the reading lookup and the reading roster. They are consumed now rather than deleted, by a witness asserting that every candidate the roster calls PROBED has a reading carrying a host, a date and an instrument. That closes the gap where "probed" could be a label with no receipt behind it, which would have counted an unread image into the sweep's denominator.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 2 commits September 11, 2026 03:21
…w arithmetic in std.

Bare Nat for sliding_window, index_topk, and vision_max_image_tokens forked the TokenCount already used in this module. The output-budget copies in V4, V4.1 Flash, and GLM were the same saturating subtract, not an upstream fact. Scope-describing Bool flags with no consumer are gone; the annotations remain.

Co-authored-by: Cursor <cursoragent@cursor.com>
…e question behind them was wrong too

DSV41-4 read the operator roster from vLLM at the pinned revision and found that two of the three names this probe asked for were never operators and the third names a C++ header, which Python cannot ask for. Verified here against csrc/libtorch_stable/torch_bindings.cpp at 07b75534651a0dd584c6f3be75d8c62fb8426397 rather than taken on report. A name that cannot be present answers `absent` for every image on earth, so those three rows measured this probe and not the runtimes -- and they measured it confidently, agreeing with each other exactly as a blind instrument guarantees.

Reading the real roster then showed the question was wrong as well as the spelling. The four KV operators that DO exist are present in any image shipping the compiled extension, while the nvfp4 DS-MLA layout they stood for is reached only through a build defining ENABLE_NVFP4_SM100 -- and DeepseekV4FlashInferMLASparseBackend.supports_combination admits, at device capability major 12, exactly fp8, fp8_e4m3 and fp8_ds_mla. On sm_12x that layout is never selected, kernels or no kernels, so a capability named for its kernels would have gone green everywhere while implying a KV path this hardware cannot take.

So the outcome type grows a third way to learn nothing -- KernelProbeSymbolUngrounded, the state where the run succeeded and the question was malformed -- the folds count it as unprobed rather than missing, and the capability is renamed to what it can actually decide here: the MLA KV layout the backend admits, gated on FlashInfer's sparse MLA SM120 decode API. No corrected symbol is spelled in this module. The upstream roster extdeps.vllm.deepseek_v4_1_sm12 is its one home, and the capability carries a frontier naming it, which is why v41_capability_probe_symbol is now a type rather than a string: a string field would have forced either an invented name or an empty value that reads as "no symbol needed".

Two witnesses hold the line: an ungrounded symbol must read unprobed and never missing, and the capability without a landed roster must carry a frontier rather than a spelling. A third was CORRECTED -- it asserted the production image was missing all five capabilities and passed over the vacuous reading, which is what a blind instrument buys you. It now asserts the four that were actually asked, and that the fifth is unprobed.

The class is filed at gunbc.recurring_failure_mode.a_probe_symbol_that_cannot_exist_records_a_false_absence: ceiling 4, because a probe symbol that is membership in a modelled upstream roster has no constructor for a name that cannot exist, and its next-rung trigger is that roster landing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

…get wrappers.

config.json returns integer arrays; fixed-arity layer_a records re-invented that shape. Remaining-window arithmetic already lives in std.measure; product nicknames were a layer inversion.

Co-authored-by: Cursor <cursoragent@cursor.com>
…and a carrier the cover check could not see gets its name

A new file under dag/extdeps has exactly two landing states, carrier or machinery, and the frozen manifest is neither. These three image modules arrived as neither: they copied a sibling's shape, and that sibling is pre-freeze debt rather than a pattern to follow. They now declare extdeps_model_scope naming the subject each of them speaks for -- the published repository, which is the one thing in those files the publisher owns -- and they are enrolled in scope_carrier_paths.

Two declarations in the gitcommit90 module are deleted rather than kept. One was an interpreter path nothing read. The other was a TORCH_CUDA_ARCH_LIST receipt from `docker image inspect`: an observation of ours, authored into the publisher's module, directly beneath an annotation saying that readings belong in gunbc.spark.runtime_architecture_registry_reading. Writing the rule and breaking it in the same file is worse than not writing it.

Running the frontier's own witnesses to check this turned up a red that predates this branch: extdeps.standards.rfc_8118 has been on scope_carrier_paths since #10439 while declaring its scope as rfc_8118_model_scope, and carrier_content_declares_scope reads bytes for the literal `data extdeps_model_scope:`. A carrier whose scope the cover check cannot see is exactly the state that check exists to refuse, so carriers_declare_scope_on_disk has been failing on main for a week. It is fixed here with the same alias that module already uses for its authority anchor -- one scope under two names, the module-scoped one still the authority -- because a branch that only fixes its own half of a red wall stays red.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 2 commits September 11, 2026 04:07
…scribed rows on declared frontiers.

The product module was minting huggingface.co/blob URLs beside HubRepoId, and most config/encoder rows sat in neither a consumer nor a frontier. Blob/tree construction now lives once in the Hub module; V4's encoder citation uses the same fold.

Co-authored-by: Cursor <cursoragent@cursor.com>
… the tautological list witness.

DeepseekV41DeclaredFrontier was a second carrier for subject+reason+dissolution. The layer-id test compared the module to its own literals.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 5 commits September 11, 2026 05:41
…ame a subject.

required-witnesses-floor refused five // lines at EOF after the Bool they used to sit on was deleted.

Co-authored-by: Cursor <cursoragent@cursor.com>
…coverage facts, pin the MIT license source.

hub_blob_url and peers now prefix datasets/spaces (and api collections) from HubRepoId.kind; same-path controls are in the witness. Fleet unread-on-fleet was a gunbc observation, not a DeepSeek fact. Parser names live under recipes.vllm.ai. LICENSE at the pin is MIT, consumed by DSV41-1.

Co-authored-by: Cursor <cursoragent@cursor.com>
… the machine, and prerequisites stop calling themselves service

Three findings from the side-chat review, each verified against the code before it was touched, each true.

A READING'S SUBJECT CANNOT MOVE. The four registry readings took their image_reference from the image module's pinned_reference(), which looks like one-digest-one-home and is the wrong shape for a receipt: repinning would have silently re-addressed every past reading to a digest nobody ran anything inside. The observed digest is frozen into the reading now, and desired identity is joined to it at the point of use by reading_applies_to. extdeps still owns what the fleet intends to run; this module owns what was read and when. The repin control is the arm itself -- serving_arm_admits refuses, naming both digests, when the reading was not taken inside the image the arm would launch. Inheriting the old list instead is the exact shape of every silent-wrongness row this repository files: the provenance still reads convincingly while the fact underneath it has moved.

A KERNEL QUESTION HAS NO ANSWER APART FROM THE MACHINE IT WAS ASKED ON. The lookup matched image and capability only, and took the LAST matching row. Two defects in one shape: readings from different compute capabilities could combine into a single positive verdict, and two disagreeing readings resolved by list order. It is keyed on the device now and returns a typed lookup whose third arm is OutcomeConflicted -- disagreement is not a value to pick between, it is a receipt set that has lost its single-valuedness, so it counts as unprobed and the remedy is to re-probe.

AND A SYMBOL INVENTORY IS NOT A SERVING ENGINE. Every probe here asks whether a symbol is registered or a module imports; that can rule an image OUT decisively and cannot rule one IN. The positive arm is V41RuntimePrerequisitesPresent rather than Admissible, carrying the profile it holds for and the sentence that says what remains. The build obligation's subject is the prerequisites rather than "able to serve", with executable feasibility named as a separate launch receipt. Requirements are bound to a profile in the same move: DSpark is the speculative-decode path, and making it mandatory for everyone converted a deployment choice into a hardware verdict, ruling out images that would have served the thing actually wanted.

Six new witnesses, including both directions of the repin wall, cross-device isolation, and the agreeing/disagreeing pair -- a conflict test alone is satisfied by a function that never finds anything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
…ority' into session/loyal-ram-346

# Conflicts:
#	dag/gunbc/extdeps_scope_frontier.dag
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 2 commits September 11, 2026 07:13
…ommentary-only rows.

engram, effort_preamble, and system_token now execute in the witness (layer overlap, budget-named preamble, token distinct from think markers). The three frontier lists are folded for partition and expiry, so they are no longer a roster nobody reads. named_effort_values duplicated the closed effort type; declares_no_output_ceiling was a commentary Bool.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ty without its vendor is not a device

Two blockers from the side-chat re-review, both true, and both the same root as the last round applied in one place and not the other.

THE CAPABILITY RECEIPTS COULD STILL MOVE. The readings were frozen to the digest they were taken in; the ProbedRuntimeImage subjects that cite them were left reading the image module's current pin, so a repin would have carried every capability row onto a digest nobody probed. That is worse than the reading case rather than the same size: a kernel ABSENCE is what rules an image out, so an inherited absence rules out an image nobody looked inside, and the sweep's headline finding is made of exactly those absences. Each probe subject now takes the observed digest from that image's frozen reading, so the observed digest has one home and the receipts cite it rather than re-deriving it.

The candidate roster still names the DESIRED pin, deliberately. That is what makes a repin find nothing instead of finding stale answers: desired identity moves, the receipts do not, and the join between them fails loudly.

A COMPUTE CAPABILITY WITHOUT ITS VENDOR IS NOT A DEVICE. The device key compared major and minor only, so AMD's (12, 1) -- gfx121 -- matched NVIDIA's sm_121, two unrelated pieces of hardware. GpuComputeCapability carries the vendor precisely so that a capability number cannot be asked as a universal coordinate, and the key now includes it. No AMD row exists in this module, which is exactly why the omission was invisible and exactly why the control asks the question anyway.

Three controls, not two: a repinned digest must find no capability rows and read IncompletelyProbed; a same-numbered device from another vendor must find nothing; and every capability row's subject must be a digest some reading was taken in -- which breaks loudly if anyone re-derives a probe subject from a live pin again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
Brian Searls and others added 2 commits September 11, 2026 07:38
review 63626 was right: tool-call and reasoning parser rows were only self-equal literals, while the frontier named tokenizer_mode alone and claimed the parsers. Each flag is now its own frontier row; the witness checks identity, unique keys, and that all three decls are listed.

Co-authored-by: Cursor <cursoragent@cursor.com>
…by the rename it was avoiding

The previous commit gave extdeps.standards.rfc_8118 a second name for its model scope so that a byte-reading carrier check could find it, and the annotation said "one scope, two names" in as many words. That is nicknaming, and writing it down did not make it something else: the check reads file bytes for `data extdeps_model_scope:`, so the alias existed to satisfy a grep rather than to model anything. DESIGN section 5 names the moment precisely -- noticing you are implementing a workaround IS the line-stop signal -- and this one was noticed and shipped anyway.

The declaration is renamed instead. `rfc_8118_model_scope` becomes `extdeps_model_scope`, its three references move with it, and the module carries one name for one fact. The rename is exactly as cheap as the alias was; nothing was traded away for it.

What this change still does not fix, and says so at the declaration: the carrier check reads bytes for a declaration the namespace tree already carries, which is the positional citation section 3 rules out, and it is why a correctly scoped module could sit red for a week with nobody noticing. That root belongs to the frontier's own lane rather than to a DeepSeek runtime PR, and the difference between fixing it and paying a nickname to keep it green is the difference this commit exists to undo.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 2 commits September 11, 2026 08:06
…recipes.vllm.ai.

The live site is a mutable view. The selector strings are cited from models/deepseek-ai/DeepSeek-V4.1-Flash.yaml at that commit, which is the last change to that file and still spells tokenizer-mode / tool-call-parser / reasoning-parser as deepseek_v41.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ecture spelling beside its authority

Both are the same law I have been applying to everything else in this branch, missed on my own declarations.

registry_reading_names and reading_applies_to were one predicate -- exact digest string equality -- under two names. The first was written to route around a parse trap, the second for the repin join, and the first was never revisited once the second existed. registry_reading_for calls reading_applies_to now and the duplicate is gone.

The membership witness spelled "DeepseekV41ForCausalLM" inline while the production path imports deepseek_v4_1_flash_architecture_class from its authority. That is worse than untidy in this particular spot, because both uses are NEGATIVE assertions: rename the authority and the witness keeps asserting that two runtimes do not register a string nothing uses any more -- green, and about nothing. It reads the symbol now.

The neighbouring "DeepseekV4ForCausalLM" literal was checked for the same defect and left: V4's architecture class has no declaration anywhere in extdeps, only prose mentions in deepspec, so there is no authority to import. A literal with no home is a modelling gap rather than a second name, and inventing a home for it inside a witness would be the fork this commit is removing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Y9csRyPFVoCayJTEZTKpP
@gunbai-bot

gunbai-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Brian Searls and others added 3 commits September 11, 2026 08:20
…_window.

The .dag function landed without its derived std_measure.rs, so stacked heads failed required-regen / generated-artifact stage0-mirrors. The bytes are the required-regen candidate emit, not a hand translation.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ion of both sides' additions

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D2AF1pri3WJkug5AtCYLGF
@gunbai-bot
gunbai-bot Bot merged commit efdf031 into main Sep 11, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/loyal-ram-346 branch September 11, 2026 11:05
briansrls pushed a commit that referenced this pull request Sep 11, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Sep 11, 2026
#11016 merged, so the capability vocabulary, the receipt rows and the compute-capability
shape this lane spelled while it was in flight are a second authority for facts that now
have a home. Uprooted rather than bridged (DESIGN §3), and each deleted piece fixed
forward into the landed model rather than restored to its old binding:

- gunbc.spark.serving_runtime_capability_probe gains the two questions this lane found
  that its five did not ask: Fp4WeightSupportedHere (the predicate CALLED, not the symbol
  looked up) and FlashInferSparseMlaSm120Symbols (the second arm of the major-12 KV
  branch). Both are required by both profiles, which tightens the obligation -- images
  probed before the questions existed now read UNPROBED for them, which is the right
  answer to a question nobody put.
- MlaKvCacheLayoutAdmitted's ProbeSymbolAwaitingRoster frontier has fired:
  extdeps.vllm.deepseek_v4_1_sm12 lands in this PR, so the symbol is grounded IN that
  roster's value. Its witness flips from "carries a frontier" to "is grounded in the
  roster's own declaration" -- a join an author cannot satisfy by editing that file.
- this lane's seven executed readings move into that module's ONE roster, keyed by the
  digest they were taken in and the vendor-qualified device they were taken on, beside
  every other probed image's. The six presences and the one refusal are unchanged; the
  architecture row now DERIVES from a reading, because the run's full 383-name registry
  output was recovered and is recorded in gunbc.spark.runtime_architecture_registry_reading
  with its host, date and instrument -- so it satisfies the same wall every other row does.
- deleted: the seven capability labels, V41RecordedReading/v41_recorded,
  v41_image_capability_readings, v41_reading_is_present, the local compute-capability
  pair, the probed digest/version rows, this lane's spelling of the architecture class
  (now extdeps.deepseek.deepseek_v4_1_flash's), and the two dangling wrappers
  v41_image_absent_capabilities / v41_image_unread_capabilities, whose annotation
  deferred to a trigger that had already fired.
- kept, retargeted, and now CONSUMED: the absent-vs-unread partition folds read a live
  run's parsed readings and their answer is printed in the probe receipt, so the
  distinction is exercised by execution rather than asserted about rows.

What stays in this module is what the capability vocabulary does not ask: the sibling
architecture the same registry did answer for (the discriminator that rules out an empty
registry), and the layout sets the backend returned, both joined in witnesses against
extdeps.vllm.deepseek_v4_1_sm12's independent reading of the same rule.

22/22 witnesses green on this lane's file; 20/20 on #11016's, over the merged tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE
gunbai-bot Bot pushed a commit that referenced this pull request Sep 11, 2026
…capability

review 63843 is right and the trigger had already fired inside this branch. The 🟡 above
neither_upstream_recipe_targets_gb10_and_upstream_still_accepts_it said the compute
capability would be joined to gunbc.spark.serving_runtime_capability_probe
gb10_observed_compute_capability "when #11016 lands" -- it landed, this same file already
imports that symbol and consumes it two witnesses down, and the hand-spelled "12.1" was
still standing beside the authority in two witnesses. A trigger that has fired tells a
reader nothing about which of §4b(2)'s three states the class is in.

So the join is taken rather than the trigger restated:

- extdeps.vllm.source_build gains vllm_torch_cuda_arch_entry, which renders a
  GpuComputeCapability as a TORCH_CUDA_ARCH_LIST entry -- upstream's spelling of the same
  fact extdeps.gpu.types already renders as sm_major_minor, so it reuses that module's
  label OUTCOME rather than minting a second one, and refuses for a vendor whose toolchain
  has no such list instead of rendering a number the compiler would not understand.
- both arch witnesses now ask about the RENDERED observation. v41_gb10_torch_cuda_arch_list
  stays a literal on purpose -- what a build is told to target is policy, and a recipe that
  derived its target from the last device seen would silently re-target -- but the literal
  is now checked against an independently sourced measurement instead of against itself,
  and cannot be made green by editing one string in two places.

22/22 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE
gunbai-bot Bot pushed a commit that referenced this pull request Sep 11, 2026
…e two obligation symbols that do not exist (#11022)

* Model the GB10 sm_121 vLLM build as a content-keyed materialization, and read its capabilities from upstream rather than from prose

The runtime sweep (#11016) found no published GB10 image that registers
DeepseekV41ForCausalLM on sm_121 and left a build obligation. This is that
build, modeled: upstream's own aarch64 release recipe at
07b75534651a0dd584c6f3be75d8c62fb8426397 with one field overridden, an image
tag derived from a content hash over the build inputs, and every leg executed
through the portable-word-sealed fleet ssh route rather than a hand-run script.

- extdeps.vllm.source_build carries upstream's container build recipe at that
  revision, the aarch64 release invocation, and CUDA_SUPPORTED_ARCHS.
- extdeps.vllm.deepseek_v4_1_sm12 carries what the V4.1 SM12 path demands,
  read out of the tree: the FlashInfer SM120 symbols, the registered torch
  operators with their library namespaces, the two arch-gated CMake source
  blocks, and which KV layouts the backend admits per device major.
- gunbc.spark.v41_runtime_image_build converges the source at the revision and
  the image at its key-derived tag.
- gunbc.spark.v41_runtime_image_probe generates its probe from the roster and
  runs it inside the built image; a capability with no VERDICT line reads
  UNREAD, never absent.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Restore the CSA2 and DSpark surfaces and assert the FP4-KV roster correction

Nine witnesses, all executed: the fleet recipe's single divergence from
upstream, that neither upstream recipe targets 12.1 while upstream still
accepts it, that the build key moves with the arch list and not with
parallelism, the rendered build argv, that the probe script is folded out of
the roster, that the layout block calls the admission rule and asks about the
rejected layout, that a capability with no VERDICT line reads UNREAD, that the
DS-MLA nvfp4 kernels are listed only in the SM100 block, and that the FP4-KV
roster carries the registered operators rather than the three names that do
not exist at this revision.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Pin the subject architecture in the witness, with its grounding beside it

The mutation control showed the arch-list witness could not see its own
subject: with v41_gb10_torch_cuda_arch_list mutated to 12.0, two of nine
witnesses went red and the one whose whole point is "the build targets the
architecture the fleet has" stayed green, because it only asserted that the
fleet list differed from upstream's. It now pins 12.1, grounded in the compute
capability GB10 reports and which the probe re-derives on every run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* A contradictory pair of VERDICT lines reads UNREAD, not present

Rendering the generated probe before running it caught the strongest possible
false positive: the architecture capability was emitted through the generic
reporter with empty symbol lists, which prints a vacuous `=present` line (a
conjunction over nothing is true) ahead of the real verdict, so a reader taking
the first match would have reported an unregistered architecture as registered
-- in the one capability this whole lane exists to establish.

The generator no longer emits the vacuous line, and the reader now reads both
lines and calls disagreement UNREAD. The wall stays after the producer is
fixed, because it is the producer that can regress.

Ten witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Record the in-image readings, and the published image's registry entry that explains the one absence

The build converged through the modeled route and the probe ran inside its
digest on a GB10 at compute capability 12.1. Five of six capabilities are
present -- the FP4 weight kernels, the admitted KV layouts, CSA2, DSpark, and
all four FlashInfer SM120 demands. The sixth is absent: the image built from
public main at 07b75534 registers 383 architectures and DeepseekV41ForCausalLM
is not among them, although the class is in the tree.

Two transport defects were found by execution and fixed at their seam rather
than worked around: `docker image inspect --format {{.Id}}` cannot cross the
portable-word allowlist (braces), so the digest is read with `docker images
--no-trunc --quiet`, whose empty answer distinguishes "no such image" from "the
query did not run"; and a serving image's entrypoint swallows a probe's argv, so
the ephemeral run names its interpreter.

extdeps.vllm.deepseek_v4_1_flash_recipe carries what the publisher says, as
publisher figures with their derivations: the 511 GB checkpoint breakdown, the
schema-derived 614 GB minimum, the verified-hardware roster that contains no
GB10, the resolved digests of deepseekv41-flash-0909 (the documented tag 404s),
and the two registry entries its arm64 image carries -- read out of its own
registry.py -- from a distribution stamped g179dd0fa9, a commit the public
repository does not have.

Thirteen witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Take the review: the build host is an argument, the key is std.artifact_store's, and our readings leave extdeps

Four findings, all of them shape rather than fact.

1. No host is named in the build module. An earlier revision carried a literal,
   and the literal was a Spark serving pair member -- policy standing in a
   value. The entries take `--arg host=<identity>` and admit it against a
   DERIVED roster: every Spark with a router binding, minus the members of the
   groups that are actually serving, minus anyone holding an undischarged
   llama.cpp RPC peer reservation. The first cut of that subtraction excluded
   every fabric group rather than the active ones, which left nothing
   admissible -- a FabricGroup is a cage, not a reservation -- and the witness
   caught it.

2. The build key is minted by std.artifact_store artifact_realization_digest
   over named realization inputs, replacing a hand-rolled fold that was a
   second spelling of it. The module is renamed generic
   (gunbc.spark.vllm_runtime_image_build) with the V4.1 recipe as one input
   row. Where it does NOT route through std.materialization_provider or
   std.realization, the module says so and why: ArtifactRequest is a closed
   coproduct over three compiler requests, and widening it for a foreign
   toolchain's container build would be a layer inversion.

3. Statements this repository checked -- the 404 on the documented tag, the
   commit the public repository does not have, the config-blob readings, the
   registry.py entries -- move to gunbc.spark.v41_published_image_observation,
   each carrying its instrument and date. extdeps.vllm.deepseek_v4_1_flash_recipe
   keeps what the page publishes.

4. Numbers are typed: ByteSize for the KV figures, Nat for counts and job
   widths, and torch_cuda_arch_list is a List whose membership is membership
   rather than a substring search. The prose formula row is now an annotation.

Fourteen witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* The receipt carries typed readings, and the witness joins two independent sources

Review 63487, both findings, and they were the same defect seen twice.

The readings were sentences in an `evidence: NonEmptyStr` field -- instrument
output transcribed into prose beside the instrument that produced it (DESIGN
§6) -- and the witness asserted `string_contains` over those same sentences,
which is `measure() == measure()` and cannot go red for any reason that
matters (DESIGN §5). The registry count was the purest case: a number
summarising a list the row did not hold, checkable only against itself.

The rows now carry the outcome in the coproduct the reader already uses and
the measured values in their own typed fields. The count is gone, replaced by
the membership fact that actually decides the lane, with the sibling
architecture recorded beside it so the absence is discriminating rather than
merely negative. The rationale moved to annotations, where §4c puts prose.

The witness joins the in-image reading against an INDEPENDENT source: what
upstream's own files say at the pinned revision, now declared in
extdeps.vllm.source_build -- that no registry entry maps any name to
vllm.models.deepseek_v4_1 while DeepseekV4ForCausalLM maps to
vllm.models.deepseek_v4 -- and what extdeps.vllm.deepseek_v4_1_sm12 reads of
the admission rule. Source and execution are required to agree, in both
directions, at set grain.

Mutation control: flipping either side of the join (adding nvfp4_ds_mla to the
observed admitted set; flipping the source's registry fact) turns exactly the
two join witnesses red and leaves the other fourteen green. 16 of 16 green
unmutated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* State the consumer frontier for the publisher figures, rather than leaving them dangling

Several rows in the recipe and observation modules have no reader in this
change. DSV41-2 (#11013) states that it will import these modules rather than
fork vram_minimum_gb or the admitted-layout set, and it cannot import a module
that is not on the tree -- so the trigger is this change landing. Said in the
modules, because an unstated absence of consumers is the §3c red and a named
later consumer with its trigger is not.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Ask, over the modeled route, whether an admissible build host answers at all

Admissibility says a host is one this lane MAY use. It says nothing about
whether the fleet key is installed on it or whether anything answers at its
endpoint, and those are different failures with different remedies --
discovering the second in the middle of a build is how an hour gets spent
before the first leg refuses.

spark_build_host_reachability_wet asks the whole admissible roster one
question, the remote host's own short hostname, over the same sealed transport
every other leg uses. Its answer is a join a caller needs rather than a ping:
an endpoint resolved from a fleet identity ought to answer with that identity's
machine, so a reachable box reporting a different name is a fleet-data defect
rather than a reachable host.

Executed: all four admissible Sparks -- srv9 through srv12, at .236 through
.239 -- refuse the fleet key with `Permission denied (publickey,password)`.
The host keys verified (strict checking against the materialized anchor got as
far as authentication), so the boxes are up and enrolled and the key is simply
not authorized for this principal on any of them. That is a provisioning fact
about four hosts, taken with one command each and nothing installed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* wip: review 63553 fixes

* Side-chat review: cold acquisition, provenance, probe integrity, scope, and narrowed claims

Five blocking findings, each verified against the code before acting.

COLD ACQUISITION WAS BROKEN AND HAD NEVER RUN. `VllmSourceRevision.repository`
is `github.com/vllm-project/vllm` -- an identity, not a locator -- and git
reads it as a relative path. Reproduced: `git clone --depth 1
github.com/vllm-project/vllm x` in an empty directory answers `fatal:
repository ... does not exist`. The modeled run never reached it because the
tree was already present, which is specification-without-execution exactly.
`vllm_clone_url` derives the https locator from the identity.

PROVENANCE WAS ASSERTED FROM THE REQUEST. `converge_vllm_source` checked HEAD
and not the working tree, so a modified context would be stamped with an
unmodified revision; it now reads `git status --porcelain` back and refuses on
any output. `VllmImageIdentity` filled `built_from` from the requested recipe
for an image merely FOUND under the expected tag; the field is now
`requested_from` beside a `provenance` arm that says BuiltByThisRun or
AdoptedUnderExpectedTag with source equality unestablished. And the key is over
the REQUEST: two of its inputs are mutable registry tags, said in the module
with the trigger that would make it a content identity end to end.

PROBE INTEGRITY. The helpers caught every exception and returned False, so a
broken interpreter manufactured evidence against the image; they now return
found/missing/errored, the absence arm is narrowed to ModuleNotFoundError and
AttributeError, and an errored check suppresses the capability's VERDICT line
so the reader reads UNREAD. The reader parses lines and looks a capability up
by key instead of searching the output -- the reviewer's own counterexample,
`NOT_VERDICT fp4-weight-kernels=present_garbage`, is a witness.

SCOPE. `cutlass_scaled_mm_supports_fp4` is a PREDICATE about this device and
was only being found in the operator table; it is now called with the
capability the interpreter reports, as its own row. The FlashInfer capability
is renamed to `-symbols` because that is what it measures; the scoped question
needs this checkpoint's head count and top-k and is a declared frontier. The
recorded reading for FP4 support is UNREAD -- the run that produced these rows
never asked it -- and absent-versus-unread are now separate rosters.

NARROWED CLAIMS. A setuptools-scm version is a self-report and a failed commit
lookup is a fact about an identifier; together they do not establish which
source produced the bytes. The readings say what was read, source equality
stays unestablished, and "the entire difference" is gone.

23 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Exercise cold acquisition, and fix three annotation placements the floor caught

The clone leg has now RUN. vllm_source_acquire_wet on srv9, over the modeled
route as gunbc-automation: root /home/gunbc-automation/gunbc-vllm-build,
clone_url https://github.com/vllm-project/vllm, already_present=false,
revision 07b75534651a0dd584c6f3be75d8c62fb8426397, clean=true, exit 0. That is
the first execution of the path the side-chat review found broken, and it
exercises the clone, the shallow fetch, the checkout, the HEAD readback and the
new dirty-tree check in one run.

It also needed the build root to stop being a literal under the OPERATOR's
home, since every leg authenticates as the managed executor: a path belonging
to one account written into work performed by another is a permission error at
the far side that reads as a broken build. The root is derived from
spark_managed_principal_home, and the probe's script path with it.

Three annotation placements refused at the floor and not in the local witness
run: two blocks appended at end-of-file with no declaration following them, and
one sitting inside a declaration body. §4c models annotations at module-item
grain only; all three now precede the declaration they describe.

23 witnesses green, including the build argv asserting the DERIVED Dockerfile
path and that no operator home appears in it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Ignored files are part of a build context, a nested import failure is not an absence, and three claims come back in line

Three findings, verified before acting.

THE DIRTY CHECK COULD NOT SEE HALF THE CONTEXT. `git status --porcelain` omits
ignored files; a docker build context contains everything .dockerignore does
not exclude, and those are different sets. Measured at the pin: .gitignore
carries `**/generated/**` and .dockerignore does not. Executed control on srv9,
green-red-green -- a planted vllm/generated/__init__.py is INVISIBLE to the
plain status, shows as `!! vllm/generated/` under --ignored, and the modeled
entry now refuses at source-clean naming it; removing it returns exit 0 and
clean=true. (The reviewer's example file does not exist at this revision; the
mechanism they described does, which is what the control establishes.)

A NESTED IMPORT FAILURE WAS READING AS AN ABSENCE. A module that EXISTS raises
ModuleNotFoundError when its own import of an unrelated dependency fails, so
catching the type and reporting MISSING turned "this image lacks a dependency
of the thing I asked about" into "this image lacks the thing I asked about" --
an absence manufactured by the instrument, at a finer grain than the arm that
was already corrected once. `ModuleNotFoundError.name` says which module was
not found: MISSING only when that name is the target or an ancestor of it,
ERRORED otherwise, which suppresses the verdict and reads UNREAD.

THREE CLAIMS OUTRAN THEIR READINGS. A witness named for source provenance now
says what it checks -- the image registers the architecture and its stamped
identifier is not a public commit. The readings annotation said the class "is
unreachable"; it now separates the registry LOOKUP from the two SOURCE rows the
witness joins it to, and says none of the five presences is a statement that a
kernel is correct or exercised. And the verified-hardware note claimed the
published image "compiles for sm_121" from its TORCH_CUDA_ARCH_LIST -- which is
what a build was TOLD to target, recorded in a config, while upstream's build
prints `Not building ...` and exits zero when a block finds no compatible arch.
Requested and compiled are different facts; only a probe inside the image
settles the second, and this lane has not run one there.

Also in this push: the two GB figures are std.measure Gigabyte rather than bare
Nats named `_gb`, with the published minimum rendered from the Measure instead
of forked as a second literal; and the published-image witness joins typed
lookup outcomes instead of grepping prose this change authored.

24 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Route A becomes a dispatch mode; and the staged-file probe, the manufactured build key and two stale claims go

FIVE FINDINGS ACROSS TWO ROUNDS, one push.

`--untracked-files=all`, because `--ignored` was only half. `status` honours
`status.showUntrackedFiles`, so a repository configured to `no` hides an
ordinary untracked file that docker ships anyway -- reproduced in an isolated
repository, where `--porcelain --ignored` returned EMPTY for exactly such a
file. Naming the mode makes the answer a property of the command rather than of
whatever configuration a host carries.

THE STAGED-FILE PROBE ROUTE IS DELETED, not annotated as gone while surviving.
An earlier note claimed "everything that existed only to get it there" was
gone; the script path, its mode, the bind mount, the ephemeral-run builder, the
file convergence and the key-route entry were all still declared and still
reached, so two mechanisms answered "run this probe inside this image". §3
calls a surviving X an attractor and the remedy delete-first. What remains is
the privileged route, which is the only one that can reach docker on a Spark.

ADOPTION NO LONGER MANUFACTURES A BUILD REQUEST. A pull-only operation was
arriving with a recipe and a build key attached, and the receipt printed that
fallback key beside a published digest. AdoptedUnderExpectedTag made the claim
weak, which was true and beside the point -- the defect was inventing a build
request where there was none. The probe outcome carries a reference and the
digest the daemon reported; vllm_adopted_image_identity is gone.

THE PYTHON PROGRAM CARRIES A DISSOLVE-ON naming what would retire it:
extdeps.languages.python is a TARGET MODEL the emitter consumes to translate
declarations this repository owns, and this content is reflection over symbols
we deliberately do not own, so there is nothing in .dag to emit from. It
dissolves when a modeled foreign-reflection surface exists.

TWO CLAIMS CORRECTED. The witness comment no longer concludes the published
image is built from a revision the public repository lacks -- a version stamp
and a failed lookup cannot establish that. The PR body no longer says no sudo
appears anywhere, which the privileged route makes false.

ROUTE A IS A DISPATCH MODE. spark_runtime_image_probe is a step inside the
existing dispatch-only fleet job, emitted through gunbc.fleet_converge_workflow
and gunbc.ci_spec and regenerated -- never hand-edited. Job count is unchanged
at six, so it adds no standing claim on a runner. The emitted step materializes
the Spark administrator credential from Secret Manager inside itself and all
eight hosts have a case arm, srv9 included.

AND THE DISPATCH MENU STOPS LYING ABOUT THE ROSTER. Its host description read
"srv5..srv11" while the roster it describes carries srv5 through srv12, so a
dispatcher would have believed srv12 illegal while resolution accepted it. The
description is now joined from the roster.

24 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* The fallback build's docker legs take the one modeled docker route, and the header stops claiming they do not need it

TWO FINDINGS, AND THEY WERE THE SAME CONTRADICTION SEEN FROM TWO SIDES.

This PR carried two incompatible answers to one question about the same fleet.
The probe module recorded, as its measured finding, that docker's socket on a
Spark is root-owned and that gunbc-automation is in no docker group on any of
them. The build module's header asserted, as a measured fact, that no sudo
appears in it because the build reaches docker through the operator's docker
group membership. Both halves of that were wrong together: the legs
authenticate as the MANAGED EXECUTOR rather than the operator, and that account
cannot reach the daemon -- so converge_vllm_image's `docker images` and `docker
build` legs could not have run at all.

They did run, once, and that is the part worth recording rather than smoothing
over: srv5 carries a hand-installed key for the human briansrls AND that account
in the docker group, which no modeled route produces. The fallback image exists
because of provisioning drift standing in for a mechanism nobody had.

So the docker legs now bind to gunbc.spark.model_snapshot_materialize
spark_remote_run -- one route to that daemon, the same one the probe uses --
while the git legs keep the key session, which needs no root. The header says
that, and says what it used to say and why it was wrong.

THE BUILD ENTRY MOVES WITH ITS LEGS. Needing the administrator credential means
needing the fleet-converge boundary, so `--arg host=` is gone and the entry
reads SPARK_CONVERGE_TARGET like the probe. It carries a dissolve-on for what is
NOT settled: a cold build took about 75 minutes and the spark step timeout is
60, so whether a build fits in that boundary is a job-level decision this lane
does not get to make.

AND EVERY ENTRY NOW NAMES ITS INVOCATION. Three wet entries have no in-tree
caller, which is the shape of an actuator only if the invocation is stated:
the source acquisition and the reachability probe are operator-invoked through
the CLI and have both been executed that way against srv9; the build entry's
dispatch is owed and is recorded as owed.

24 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Restore the acquisition entry its own note advertised, filter the probe's target the way the build's is, and stop calling a version stamp provenance

THE ACQUISITION ENTRY WAS DELETED BY A REGION REPLACEMENT AND ITS NOTE KEPT
ADVERTISING IT. vllm_source_acquire_wet and its receipt helpers went out with
the build-entry rewrite while the §3c invocation block still named the CLI
command, so the one invocation a reader was told to use did not resolve. That
is the same defect this lane criticised twice in other people's text -- an
annotation describing a mechanism that is not there -- and history executing it
once establishes nothing about its availability now. Restored.

ENROLMENT IS NOT ADMISSIBILITY, and the probe entry had stopped at the first.
The administrator roster answers "does this Spark have a credential", which
srv5 and srv6 do -- and they are the serving pair. A dispatch naming one would
have pulled 9.6 GB and started a container on a serving host, which is the thing
that was explicitly ruled out. The probe now applies the same subtraction the
build does, so a rostered host that is serving or reserved refuses there too.

A VERSION STAMP IS A SELF-REPORT. The readings annotation said the version
string means "the image identifies its own source"; it means the packager
stamped that identifier, which is evidence about the artifact and not proof of
what was compiled -- the same distinction extdeps.vllm.server already draws for
a server's version prefix. The paragraph describing the deleted --arg host=
probe route is gone, and the PR body's "reports its own provenance" with it.

AND THE FIT STATEMENT IS AN ANNOTATION RATHER THAN A ROW. v41_flash_fit_statement
was a String declaration nothing read, and its decidable content is already
carried decidably next door -- verified hardware in one row, the minimum as a
Measure in another. What remained was the publisher's caveat, which §4c puts in
an annotation, placed beside the number a reader is most likely to mistake for
a measurement.

24 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* An annotation reattached, a transcribed measurement removed, a policy thread count typed, and the last prose row folded

Four local fixes, all correct as found.

THE ANNOTATION WAS DESCRIBING THE WRONG DECLARATION. Inserting the probe step
function between the pair-serving block and its function left that block leading
MINE, so it read as if the probe applies serving units workers-before-heads.
Attachment is the whole semantics of the channel (§4c). The function moved below
the one the block describes; the emitted YAML is unchanged, because step ORDER
lives in the steps list and that did not move.

A TRANSCRIBED MEASUREMENT IS GONE. The parallelism annotation carried the build
host's core count, its free memory, and upstream's figure for a different
machine -- three numbers copied into prose with no producer named, which rot the
moment any of the three changes with nobody touching this file. What is citeable
is upstream's own aarch64 release row, which is already a declaration; the fleet
rows are a DEPARTURE from it, chosen low because a Spark is not a dedicated
builder. Where a reader wants the host facts, the annotation names the
instrument that would take them rather than quoting an old one.

nvcc_threads COUNTS HARDWARE THREADS and now carries std.measure's
HardwareThreadCount, the unit extdeps.ci_runner already carries for published
runner vcpus. The bare Nat stays on VllmContainerBuildRecipe, where the field IS
upstream's ARG at the cited-spec boundary; the conversion happens once, at the
call. max_jobs is left a Nat: it is a concurrency degree, not a thread count.

AND THE LAST PROSE ROW FOLLOWS THE FIRST. v41_flash_documented_install_note was
a String nothing read -- the identical defect this module deleted one
declaration earlier for the fit statement, which is how a class gets fixed at
one instance and left standing at the next. Its decidable content is that the
image is not one install option among several but the only one the publisher
offers, which is why a reference that does not resolve is a hard stop.

24 witnesses green; generated artifacts regenerated with no drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Unwrap the thread count at the witness call site, where the previous commit left it wrapped

review 63774: the witness passed v41_build_nvcc_threads -- a HardwareThreadCount,
which is Measure { count } -- into vllm_recipe_targeting's `nvcc_threads: Nat`.
The production call site already unwrapped it; the witness did not, so typing
the policy row in the previous commit was carried through in one place and not
the other. Fixed the way production does it, through hardware_thread_count_value.

WHAT THE REVIEW GOT WRONG, AND IT MATTERS MORE THAN THE FIX. It says the witness
"cannot execute at all in this state". It executed and passed: 24 of 24 green on
the wrapped tree, the arm in question included. So the mismatch was not caught.

A discriminating control says the tolerance is not specific to Measure: with
`max_jobs: "one" as NonEmptyStr` planted in the sibling arm -- a String where a
Nat is declared, which no reading of the types admits -- the same runner returned
24 of 24 green again. Whether the full compiler refuses what the witness runner
admits is a separate question and is being asked; either way, a green witness is
weaker evidence about ARGUMENT TYPES than this lane has been treating it as, and
that is worth more than the one-line fix that prompted it.

24 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* The partition witness exercises the fold over readings it builds, instead of counting the rows it ships with

review 63793: the_built_image_has_one_measured_absence_and_one_unasked_question
compared this change's recorded readings to this change's expectations about
them. Both sides were the same diff's rows, so the only way it went red was an
author editing one -- the change detector §5 names, and moving it from prose to
typed rows changed the grain, not the self-reference. The reviewer offered two
arms, join it or drop it; neither quite fits, because there IS no second source
for "the recorded run never asked this question".

What is worth checking is the code rather than the data: that absent and unread
stay disjoint at all, since folding them would let a question nobody put read as
a capability nobody has. So the folds now take a roster, and the witness builds
three readings -- one of each outcome -- and asserts the two buckets separate
them. The recorded roster is no longer asserted about; its content is already
joined against an independent source by the two agreement witnesses, which can
go red on either side.

Mutation control: making the unread fold also collect Absent -- exactly the
conflation the arm exists to prevent -- turns that witness red and leaves the
other twenty-one green. 22 of 22 green unmutated.

v41_reading_for went with the deleted witness; it had no other consumer. The
thin wrappers over the recorded roster stay, with the consumer already named for
the receipt itself, and no witness asserts their values.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Delete the orphaned probe-convergence annotation; it described a deleted entry

The eight-line block after `v41_probe_body` described `v41_runtime_image_probe_wet(host)`:
tag-based convergence and a `--arg host=` roster admission. That entry is gone; the
surviving `v41_published_image_probe_ci_wet` pulls a digest under SPARK_CONVERGE_TARGET
and carries its own accurate annotation. So the block was both stale in content and,
with nothing between it and the readings section header, misattached under §4c.

22 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Cut the probe over to #11016's capability authority, delete-first

#11016 merged, so the capability vocabulary, the receipt rows and the compute-capability
shape this lane spelled while it was in flight are a second authority for facts that now
have a home. Uprooted rather than bridged (DESIGN §3), and each deleted piece fixed
forward into the landed model rather than restored to its old binding:

- gunbc.spark.serving_runtime_capability_probe gains the two questions this lane found
  that its five did not ask: Fp4WeightSupportedHere (the predicate CALLED, not the symbol
  looked up) and FlashInferSparseMlaSm120Symbols (the second arm of the major-12 KV
  branch). Both are required by both profiles, which tightens the obligation -- images
  probed before the questions existed now read UNPROBED for them, which is the right
  answer to a question nobody put.
- MlaKvCacheLayoutAdmitted's ProbeSymbolAwaitingRoster frontier has fired:
  extdeps.vllm.deepseek_v4_1_sm12 lands in this PR, so the symbol is grounded IN that
  roster's value. Its witness flips from "carries a frontier" to "is grounded in the
  roster's own declaration" -- a join an author cannot satisfy by editing that file.
- this lane's seven executed readings move into that module's ONE roster, keyed by the
  digest they were taken in and the vendor-qualified device they were taken on, beside
  every other probed image's. The six presences and the one refusal are unchanged; the
  architecture row now DERIVES from a reading, because the run's full 383-name registry
  output was recovered and is recorded in gunbc.spark.runtime_architecture_registry_reading
  with its host, date and instrument -- so it satisfies the same wall every other row does.
- deleted: the seven capability labels, V41RecordedReading/v41_recorded,
  v41_image_capability_readings, v41_reading_is_present, the local compute-capability
  pair, the probed digest/version rows, this lane's spelling of the architecture class
  (now extdeps.deepseek.deepseek_v4_1_flash's), and the two dangling wrappers
  v41_image_absent_capabilities / v41_image_unread_capabilities, whose annotation
  deferred to a trigger that had already fired.
- kept, retargeted, and now CONSUMED: the absent-vs-unread partition folds read a live
  run's parsed readings and their answer is printed in the probe receipt, so the
  distinction is exercised by execution rather than asserted about rows.

What stays in this module is what the capability vocabulary does not ask: the sibling
architecture the same registry did answer for (the discriminator that rules out an empty
registry), and the layout sets the backend returned, both joined in witnesses against
extdeps.vllm.deepseek_v4_1_sm12's independent reading of the same rule.

22/22 witnesses green on this lane's file; 20/20 on #11016's, over the merged tree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* The sweep's denominator was still split one layer up: the built image is a probed candidate

The capability rows and a full registry reading for the source-built digest landed in the
last commit, but v41_sm121_runtime_candidates still described that image as a BUILD
obligation nobody had taken. v41_images_with_prerequisites walks CANDIDATES, skipping
CandidateNotProbed, so the one image this lane actually probed sat outside the sweep it
was built to enter -- a roster unified at the row layer and still forked at the candidate
layer, which is the same defect one level up.

- the row is CandidateProbed at the frozen reference the registry reading carries, and its
  discovered_via says what it was (an obligation), what happened (the obligation was taken
  and the image probed), and where the obligation's own discharge is read.
- the reciprocal wall lands with it: every image subject with capability rows must resolve
  to a CandidateProbed candidate. The existing wall stops a candidate claiming a reading it
  does not have; this one stops a reading being invisible to the sweep, which is the
  direction that just failed. An identity join from the rows to the candidates, so a new
  probed subject with no candidate row goes red rather than going unnoticed.

21/21 witnesses green on the capability authority's file.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Say the sweep's shape instead of its size, and name BOTH unmet prerequisites

Prose only; no declaration changed. Every sentence that carried a count of capabilities or
candidates was stale the moment this PR added two questions and a probed image, and a
sentence stating a size goes stale again on the next expansion -- so each one is reworded
from the shape it is describing: "the candidates this roster carries", "the capabilities
this profile requires", "the kernel questions", "the questions that were put to it".

- the sweep's denominator sentence, the SGLang candidate's header and its four recorded
  refusal reasons, the profile note, and the CapabilityProbeSymbol header. That last one
  also said one capability was awaiting its roster; none is today, so it now says what the
  frontier arm is FOR -- a capability that arrives ahead of the upstream roster that names
  its symbols -- and why deleting it would make the next one land as a spelling of ours.
- the SGLang header gains the distinction the two new capabilities create: a question the
  vocabulary gained after a run was never asked of that image, so it is UNRECORDED rather
  than refused. A run cannot have refused a question that did not exist when it happened.
- the witness file's matching framing, and one test renamed off the count it carried.

And one correction rather than a rewording: the build obligation said the built image
answered present to every kernel question and absent to the registry one, which reads as a
single unmet prerequisite. There are two. The FP4 runtime predicate stands at
KernelProbeRefused -- the run FOUND cutlass_scaled_mm_supports_fp4 and never CALLED it -- so
its answer for this device is unknown rather than negative, and discharge needs the re-probe
as well as an image whose registry answers for the architecture. Naming only the absence
would leave a required capability unasked behind a discharge that cited a different defect.

21/21 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Take the join the 🟡 deferred: the arch witnesses render the observed capability

review 63843 is right and the trigger had already fired inside this branch. The 🟡 above
neither_upstream_recipe_targets_gb10_and_upstream_still_accepts_it said the compute
capability would be joined to gunbc.spark.serving_runtime_capability_probe
gb10_observed_compute_capability "when #11016 lands" -- it landed, this same file already
imports that symbol and consumes it two witnesses down, and the hand-spelled "12.1" was
still standing beside the authority in two witnesses. A trigger that has fired tells a
reader nothing about which of §4b(2)'s three states the class is in.

So the join is taken rather than the trigger restated:

- extdeps.vllm.source_build gains vllm_torch_cuda_arch_entry, which renders a
  GpuComputeCapability as a TORCH_CUDA_ARCH_LIST entry -- upstream's spelling of the same
  fact extdeps.gpu.types already renders as sm_major_minor, so it reuses that module's
  label OUTCOME rather than minting a second one, and refuses for a vendor whose toolchain
  has no such list instead of rendering a number the compiler would not understand.
- both arch witnesses now ask about the RENDERED observation. v41_gb10_torch_cuda_arch_list
  stays a literal on purpose -- what a build is told to target is policy, and a recipe that
  derived its target from the last device seen would silently re-target -- but the literal
  is now checked against an independently sourced measurement instead of against itself,
  and cannot be made green by editing one string in two places.

22/22 witnesses green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* Declare what this witness entry reads, so silence stops asserting the wrong thing

Every witness in v41_runtime_image_build_witness_test.dag is a pure fold over declarations
-- generated script text, argv construction, hostname classification, the capability
partition, recorded readings joined against upstream's source rows. None opens a file, asks
a host, or reaches outside its resolved closure; the one thing in this lane that touches a
live tree is the probe, which is a wet entry in gunbc.spark.v41_runtime_image_probe and not
a witness. The file said none of that, and v2.std.live_tree records that the selection
consumer reads an undeclared entry as ReadsLiveTree -- so silence here asserted something
false about this file.

The row is author-vouched and says so: v2.std.live_tree is explicit that nothing checks a
stamp today (the falsifier cadence that would have died with the 2026-08-15 floor cut), so
the annotation states that rather than implying the declaration is verified. No gate is
widened by it; the required floor's home-prefix decline is unchanged and is an operator
ruling, gunbc.rung_drop required_gate_bankruptcy.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

* The headroom factor goes on the Percent carrier std.measure already owns

review 63881 is right, and the sharpest part of it is that this file condemns the defect
four lines above the place it commits it: the annotation on v41_flash_checkpoint says "a
scalar named `_gb` is a unit living in an identifier, which is the place a conversion goes
wrong silently", and the row below it was `v41_flash_headroom_factor_tenths: Nat = 12` --
the unit in the identifier, the scale open-coded beside it as `* factor + 9) / 10`.

std.measure owns this concept: Percent = Measure<Dimensionless, One, Nat>, already imported
by this module for Gigabyte. So the publisher's 1.2 is percent(count: 120), and the scale the
ceiling division undoes is percent_unity_hundred_count() -- extdeps.units.dimensionless'
authority for what "per cent" means -- rather than a literal 10 chosen to match a name. The
ceiling term is written against that scale too, so it stays correct if the factor is ever
restated at a different precision.

The oracle over it is unchanged and is what makes this checkable rather than plausible:
the_published_image_observation witness asserts that the page's stated 614 EQUALS
v41_flash_headroom(total: v41_flash_checkpoint), two independently sourced figures from the
publisher's own page. A wrong conversion (12 rather than 120) cannot satisfy it.

22/22 witnesses green on claim_batch sha256 7c7359ccaf9d62d7c92990bc3501940784377abf38e88926e4106cff597828c2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4MBC3Vb8do5fAXAysiXLE

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants