Skip to content

HOST-1: program-derived assimilation completion gate (obligations as a derived list, not a fixed product) - #7877

Merged
briansrls merged 18 commits into
mainfrom
session/cool-ant-587
Aug 6, 2026
Merged

briansrls merged 18 commits into
mainfrom
session/cool-ant-587

Conversation

@briansrls

@briansrls briansrls commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

Stacks on HOST-0 (#7876, merged via session/host-0-program-scoped-assimilation at c560361).

Summary

Replace the fixed four-field AssimilationCompleteGate product with a participation-derived obligation list. CI runner enrollment requires all four AssimilationCompleteInput arms; inference serving requires only NodeRegistered and ResourcesPresent. Roster validation refuses when a required obligation is missing or an unrequired one is present (first-failure-wins in declared order). Green-place projection preserves exact refusal reasons including the #5948 path for the fail-closed P3 scaffold.

Test plan

Executed on head 024fdced0 after merging updated HOST-0 base (post-#7851):

./target/debug/claim_batch --source-root dag --source-root src/v2 \
  --entry dag/test/claim/host_standup_spine_witness_test.dag \
  --functions <all 19 test fns>   # 19/19 PASS

./target/debug/claim_batch --source-root dag --source-root src/v2 \
  --entry dag/test/claim/host_phase_status_witness_test.dag \
  --functions <all 16 test fns>   # 16/16 PASS

Identity conjunct: existing spine assimilation witnesses pass unchanged; p3_green_place_contributes_via_gunbc_gate_after_pinned_tree_lands and fail-closed gap/refusal controls green.

Out of scope (separate PR): gap ledger PhaseDisposition product change.

gunbc-ci-auto-heal and others added 13 commits August 5, 2026 14:52
…rived

First slice of the local-inference economics lane. Lands the receipt carrier
that makes the hardware question measurable, in the observing product layer
(DESIGN external-upstream-decomposition: extdeps.llm.* owns provider wire
contracts, this owns what WE observed when we ran something).

Mechanism:
- TokenCount instantiates the std.measure Count axis (HardwareThreadCount /
  CharacterCount precedent), declared here not in std.measure because an LLM
  token is domain vocabulary and std/measure.dag is seed-emitted.
- No throughput, rate, or cost field exists in the record. Tokens-per-second
  and accepted goodput are DERIVED as exact FieldOfFractions<Nat> over the
  same authority gunbc.econ.acquisition ConversionRate consumes; the floor
  projection is a declared lossy view, total by typed refusal.
- Usage is three-valued: an attempt whose provider reported no usage is not
  an attempt that consumed nothing. Missing usage refuses the economic
  derivation without refusing the attempt or its disposition.
- Goodput counts ACCEPTED dispositions only, so a host that doubles token
  rate while halving acceptance shows no gain.
- Admitted sessions and active sequences are separate observations; a server
  sustaining four sequences can admit considerably more sessions.
- SubstrateIdentity binds the compiler revision, because escalation rate is
  endogenous to both the model improving and gunbc needing less judgment.

Evidence: 13 witnesses green by execution, incl. RED controls for zero and
absent decode duration (no fabricated throughput), unobserved usage, empty
roster, and zero observation window.

Honest limits recorded in-carrier, both measured rather than assumed:
- TokenCount is structurally identical to HardwareThreadCount, so it buys
  reading clarity, not a construction wall.
- Requested/resolved model brands do NOT wall substitution. A scratch probe
  passing RequestedModelIdentity into a ResolvedModelIdentity parameter
  resolved and ran green. An earlier draft of the note claimed a typecheck
  refusal and cited a witness that was never written; both were false and
  are retracted in the carrier with the next-rung trigger named.

No cost derivation lands here: the token-rate rows are not yet cited, and
fabricating a rate to make the arithmetic run is what the follow-on prevents.
This slice declares its frontier rather than claiming a production consumer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…y, don't fork it

review 48816 found the merge-blocking defect and was right. TokenCount was
declared locally in gunbc.econ.llm_attempt_receipt as Measure<Count, One, Nat>,
citing extdeps.pricing.billing_units as precedent for downstream placement.

Verified against the tree, the citation does not cover it. The billing_units
aliases introduce their own phantom markers (PerStoredUnitMonth et al), so
MoneyRate<PerStoredUnitMonth> is a genuinely new point in the type space that
cannot be written in std without importing vendor vocabulary. Measure<Count,
One, Nat> takes only arguments std.measure already owns, and that module
already names the shape three times: HardwareThreadCount, CharacterCount,
AmortizationMonths. A local fourth name was therefore a DESIGN section 3 fork,
not a downstream instantiation.

The review offered a tracked deferral as an alternative. Not taken: the only
argument for deferring was the seed-regeneration cost, which is the cost of
doing this correctly rather than a reason to avoid it, and deferring for the
author's convenience is the unmarked-workaround shape DESIGN section 5 names
as a line-stop signal.

- TokenCount, token_count, token_count_value now live in dag/std/measure.dag
  beside their three siblings, under token_count_note, which records the
  billing_units distinction so the reasoning is not rediscovered, and repeats
  the siblings' honest limit: all four are structurally identical, so the
  family buys reading clarity and one construction site each, never a wall.
- llm_attempt_receipt consumes them and retracts the bad citation in
  llm_token_count_authority_note.
- src/v1/stage0/src/std_measure.rs regenerated (seed-emitted module).

Evidence: regen_stage0 wrote 132 generated files with exactly one changed;
the regenerated seed compiles; regen_stage0 --verify reports
regen_divergence_count=0 with a binary rebuilt FROM the new seed, so the
self-host fixed point holds rather than being self-confirmed by a stale seed.
All 13 witnesses re-run green against the std-homed carrier.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
llm_model_identity_brand_note cited llm_token_count_placement_note, which the
tree no longer contains: the previous commit renamed that note to
llm_token_count_authority_note while re-homing TokenCount, and the honest-limit
claim the sentence points at moved to std.measure token_count_note. Verified as
dangling — the citation was the only occurrence of the name anywhere in dag/.

Now cites std.measure token_count_note, where the Count-axis family's
mitigatable-rung limit actually lives.

This is the DESIGN section 3 stale-citation class in a note whose own subject is
a false citation, and it is the failure mode that rule predicts: a rename
invalidated a name-level reference with nobody touching the referring line. A
symbol citation is at least decidable by grep, which is how review 48829 caught
it; the positional form would not have been reachable at all.

Swept the rest of both files for the same defect rather than fixing only the
reported instance: dispatch_execution_receipt_bar_note, token_count_note,
llm_token_count_authority_note, llm_attempt_receipt_frontier_note,
ConversionRate, FieldOfFractions, character_count_note, HardwareThreadCount,
CharacterCount, AmortizationMonths, dispatch_usage_unobserved,
DispatchUsageObserved, MoneyRate and PerStoredUnitMonth all resolve.

Witnesses re-run green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… spine cross-product

Two DGX Spark inference appliances (srv5, srv6) are on order. Enrolling them
against the current model would manufacture obligations they can never satisfy:
host_standup_spine is ONE universal list -- BMC credential convergence,
virtual-media OS install, Actions runner slots, build cache, green-place pinning
-- and host_phase_status crossed every enrolled host with all of it. An appliance
has no BMC and no runner user, so those cells could never be converged and could
never honestly be marked so. A completeness number computed over invented
obligations is worse than no number.

The correction is program scoping, NOT an Applicable | NotApplicable verdict.
A verdict arm would keep the false cells and label them -- the parallel
representation shape (DESIGN section 3) -- and leave every consumer to remember
to filter. Participation now SELECTS which obligations exist, so an obligation
that does not apply is not a labelled cell, it is not a cell.

- New gunbc.host_assimilation_program: FleetParticipation (CiRunner |
  InferenceServing), HostEnrollmentIntent, HostAssimilationProgram,
  assimilation_program_for. Participation is a LIST because the axes are
  independent, and it is a role rather than a hardware kind, so a future Altra
  dedicated to serving does not inherit BMC obligations from what it is made of.
- Phase-to-participation classification is an EXHAUSTIVE match over both closed
  phase enums, so a newly added phase cannot silently default into or out of a
  program -- it does not compile until classified. Construction, not validation.
- It lives in the new module rather than as a field on HostStandupStep: that
  would reshape fourteen rows in load-bearing host_standup.dag, and that module's
  own gap-ledger note already ruled its row-reshaping change stays separable.
- The program is DERIVED by filtering the spine, never a second hand-authored
  step list that could drift.
- host_phase_status is enrollment-driven; the global-spine path is DELETED, not
  retained beside the new one. fleet_subsumption_hosts is now a projection of
  fleet_subsumption_enrollments, so consumers that only care which hosts exist
  are untouched and the two lists cannot disagree.

Evidence, green by execution (12 witnesses on the refactored module):
- IDENTITY: a CI enrollment selects the whole spine, and the runner-fleet matrix
  is still hosts x spine. Every pre-existing regression witness passes unchanged
  -- no-producer-is-UnknownRefused, the absorbing-fallback RED control, the
  reconcile upsert/teardown/noop diff, observation coverage, remaining work.
- SCOPING: an inference enrollment carries zero BMC/runner/build-cache/
  green-place/session-placement cells and exactly the four shared obligations.
- TOTALITY: no spine step is unclaimed by any participation.
- Downstream consumers re-run green: host_swap_backing, host_network_diagnosis,
  host_toolchain_components.

Prefix phases are CI-runner only, deliberately. A Spark has real arrival
obligations, but they are its own and get authored where that arrival is
modeled; inheriting a differently-shaped host's provisioning steps because they
sound generic is the exact false-obligation defect this removes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Replace the fixed four-field AssimilationCompleteGate product with a
participation-derived obligation roster, roster validation (missing/unrequired
refusal), and first-failure-wins evaluation. Fixes parse error from invalid
++ list concat in the WIP commit that broke regen and heal_generated_artifacts.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 5, 2026 22:40
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Brian Searls and others added 4 commits August 6, 2026 00:24
Route assimilation completion obligations through assimilation_completion_inputs_for_one
with match on FleetParticipation; document empty-participation enrollment invariant.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fold enrolled participations into a deduplicated obligation set by input
identity so multi-role hosts derive all required inputs regardless of list
order. Witness: inference-first both-participation enrollment must still
require CI-only obligations.

Co-authored-by: Cursor <cursoragent@cursor.com>
@briansrls
briansrls merged commit 310bc65 into main Aug 6, 2026
5 checks passed
@briansrls
briansrls deleted the session/cool-ant-587 branch August 6, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant