Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5ac1863
Plan: replace GitHub Actions with the fabric, as one atomic cutover
Aug 19, 2026
424fe99
Register two defects in the CI replacement plan before the sign-off r…
Aug 19, 2026
564c5a8
Bind the CI replacement plan into the doc graph: it was an orphan
Aug 19, 2026
278a437
Two blocking corrections: the plan tests the wrong commit, and LeaseE…
Aug 19, 2026
0e208d7
Sign-off received: approved in direction, amended with 8 blocking cor…
Aug 19, 2026
6de3cfe
Operator ruling on wet proof: a second job in the same PR, not a hand…
Aug 19, 2026
cf1423e
The cutover PR cannot merge itself, and my rollback claim was wrong
Aug 19, 2026
7936884
The fabric authorizes the witness run: the floor's argv is produced u…
Aug 19, 2026
1287990
Review 53848: the derivation claim was false, and the argv was a stri…
Aug 19, 2026
d316f5e
Fix two floor-scope resolution errors, and stop forking the source-ro…
Aug 19, 2026
8abd305
Product direction reframes the PR: first production CI binding, not w…
Aug 19, 2026
61aea6b
Fungibility moves to the fabric, the floor becomes priced demand, and…
Aug 19, 2026
c9fefeb
The floor's demand: priced terms and reuse-as-policy, both executable
Aug 20, 2026
3686f01
Remove the inert floor_architecture carrier the lens caught
Aug 20, 2026
5540bab
The hourly minimum breaks the affordability fold I just landed
Aug 20, 2026
ee67c87
Record the dimensional defect, acquisition as a third concept, and th…
Aug 20, 2026
a2dec60
Refuse rate quotes against a per-grant ceiling instead of comparing a…
Aug 20, 2026
4719885
Record the dimensional fix and its two-way evidence in section 20
Aug 20, 2026
ea69cf3
Price the owned fleet at opportunity cost; record the two-cost ruling
Aug 20, 2026
1bf1742
Correct supply.dag's note in place: opportunity cost is a supply-side…
Aug 20, 2026
7ee1e3c
Record the erased-test review tell and the class underneath it
Aug 20, 2026
36fb449
Scope the lens to a decidable sub-class before signing up for it
Aug 20, 2026
ff68121
Ground the unfireable-vs-untested distinction in the empty-observatio…
Aug 20, 2026
d34b7ed
Repair a witness whose premise moved, and strip the economic pretension
Aug 20, 2026
598e6e3
Delete the stale Offer inert-carrier row: this PR is the live consumer
Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dag/gunbc/doc_graph_roots.dag
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ data body_lowering_production_consumer_ref: DeclarationRef = DeclarationRef { mo
data mock_corpus_prefilter_control_note: String = "LIVE CONTROL FOR THE MOCK-CORPUS DECLARER OBSERVATION, and the reason this sentence names the type it does. This module imports v2 modules and sits under dag/, so it is exactly the shape that broke the floor when whole-tree published-mock declarer selection was decided by a substring scan: a documentary row naming PublishedMockCase made this file read as a corpus declarer, its closure could not resolve under the dag-only roots that precompute uses, and the run refused before any witness executed. The declarer decision is now the exact type-annotation check. This sentence therefore MENTIONS PublishedMockCase without declaring one, so if the substring shortcut is ever restored the floor reds here first."

data hand_authored_doc_bind_incomings: List<HandAuthoredDocBind> = [
HandAuthoredDocBind {
home: PlanDoc,
slug: "fabric-ci-replacement",
primary_work: DeclarationRef { module_path: "gunbc.witness_floor_workflow", decl_name: "witness_floor_job", field: WholeDeclaration },
additional_works: [
DeclarationRef { module_path: "extdeps.github.checks", decl_name: "CheckRun", field: WholeDeclaration },
DeclarationRef { module_path: "product.fabric.execution", decl_name: "ExecutionGrant", field: WholeDeclaration },
DeclarationRef { module_path: "gunbc.ci_runner_target", decl_name: "CiRunnerTarget", field: WholeDeclaration },
],
dissolution: PlanRetiresWhen { condition: unbound_dissolution(description: "the cutover lands: the fabric issues the grant that runs the required floor, the check verdict is reported through the modeled Checks surface, and .github/workflows/witnesses.yml is deleted along with the emitter that produced it -- at which point this document describes a shipped system rather than a planned one and the row deletes with it. Registered at subject grain: the four systems bound here are the ones whose movement would make this document's purpose false. witness_floor_job is the thing being replaced and is bound deliberately, so that if it is renamed or restructured before the cutover this document reds rather than silently describing a job that no longer exists.") },
},
HandAuthoredDocBind {
home: PlanDoc,
slug: "fabric-recut-program",
Expand Down
222 changes: 222 additions & 0 deletions dag/gunbc/fabric_witness_run.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
module gunbc.fabric_witness_run

import std.types { NonEmptyStr }
import std.currency { CurrencyCode, Usd }
import std.nat { Nat }
import std.measure { HardwareThreadCount, hardware_thread_count, MoneyAmountMicro }
import product.fabric.identity {
FabricIdentity, WorkKey, ExecutionAttemptKey, OfferKey, GrantKey,
fabric_identity_eq,
}
import product.fabric.work {
Work, WorkContract, WorkStep, ResumabilityTier, ReceiptSatisfiable,
ExecutionRequirements, Shape, HardRequirements,
CapabilityManifestRef, TrustDomainRef,
ProgramRef, SourceManifestRef, ArtifactManifestRef, EffectContractRef, OutputContractRef,
}
import product.fabric.supply { Offer, OfferEligibility, offer_eligibility_for }
import product.fabric.demand {
Demand, AdmissionTerms, BuyTerms, SatisfactionRequirement, BudgetAccountId, ObservationReceiptRef,
}
import std.types { Timestamp }
import extdeps.exec.command { ArgvCommand }
import gunbc.ci_layer_roots { witness_layer_roots }
import std.types { String, List }

// THE FLOOR'S PROGRAM AND CONTRACTS. NOTHING ELSE.
//
// This module used to own authorize_floor_run and a FloorRunRefusal coproduct.
// Both moved to product.fabric.supply, because comparing a Work's requirements
// against an Offer's capabilities is provider-neutral fungibility and nothing in
// ShapeNotCovered / TrustDomainMismatch / CapabilitiesNotOffered was ever about
// the floor. A gunbc module answering a fabric question is a gunbc module that
// will answer it differently from the next consumer.
//
// THE FABRIC RUNS THE WITNESSES.
//
// This is the execution half of the CI replacement: the argv that runs the
// required floor is PRODUCED BY THE FABRIC UNDER A GRANT, rather than written
// into a workflow step. No grant, no command -- so the authorization is not a
// label beside the run, it is the only thing that can yield a run.
//
// What is deliberately NOT here, because GitHub Actions still supplies it while
// it still triggers: polling, durable state, the compare-and-swap authority
// transition, supersession, and check publication. Those are the CONTROL plane
// and they are only needed once the fabric owns triggering. Attempting them now
// would build a second scheduler beside a live one.

// The floor's contract. Every field is a fact about WHAT is promised, never
// about where or when it runs -- scheduling facts live in ExecutionRequirements
// beside it, so revising a thread estimate cannot mint a new semantic Work.
//
// Two steps, not one, because the workflow gates them separately and the v1
// parse gate is a blocking step in its own right: collapsing them into one step
// would make a parse failure and a floor failure indistinguishable in the
// receipt, which is the distinction gunbc#8466 -> #8519 was paid to learn.

fn floor_work_contract(source: SourceManifestRef) -> WorkContract {
WorkContract {
program: "gunbc.claim_executor",
steps: [
WorkStep { step_id: "v1-dag-parse", resumability: ReceiptSatisfiable },
WorkStep { step_id: "required-floor", resumability: ReceiptSatisfiable },
],
source: source,
inputs: floor_inputs_manifest_ref(),
runtime_closure: "gunbc.toolchain.rust-1.93.0+clippy+rustfmt",
effect_contract: "gunbc.floor.effects.read-only-corpus",
output_contract: "gunbc.floor.outputs.required-floor-summary",
}
}

// OUR FLOOR IS arm64. THE CLASS IS NOT.
//
// This function previously spelled the architecture INSIDE a capability tag --
// "gunbc.capabilities.linux-aarch64-rust-toolchain" -- which made an accident of
// our own supply look like a property of the execution class. Ampere is what we
// happen to stock; the product must serve x86 and arm at the lowest cost, and
// rented x86 is a supplier we now anticipate. A class that names its
// architecture cannot admit one it did not, which is the GitHub-vocabulary
// argument one layer over.
//
// The capability tag below therefore names the toolchain and NOT the machine.
// That our floor happens to be arm64 is a fact about our fleet's supply, not a
// property of the class -- see the note below for why it is not yet a value.
//
// WHY NO Architecture VALUE IS DECLARED HERE YET, and the receipt for it.
// Matching a declared architecture against an offer's requires the OFFER to
// carry one, and Offer has 25 constructors in tree, so the field and the arm
// that reads it land together. An earlier revision of this module declared
// `floor_architecture() -> Architecture = Aarch64` anyway, with a comment
// explaining that the consuming arm would come later. It had ZERO consumers,
// and v2.lens.inert_carrier caught it on CI as an unrostered inert carrier --
// in the same commit whose message refused to add an unread field to Offer by
// citing review 53848's declared-but-nothing-derives-it defect. Refusing the
// defect on one side of a module boundary and authoring it on the other is the
// same defect, and the lens was a better reader of that than I was.
//
// So the architecture decision lives in prose and in the recut plan until it has
// a consumer. That is the honest state: a decision recorded is not a carrier
// modeled, and minting the carrier early buys nothing except a row that lies
// about being load-bearing.

fn floor_execution_requirements() -> ExecutionRequirements {
ExecutionRequirements {
shape: Shape { hard: HardRequirements { threads: hardware_thread_count(count: 8) } },
capabilities: "gunbc.capabilities.linux-rust-toolchain",
trust_domain: "gunbc.trust.internal-fleet",
}
}

// THE SOURCE ROOTS ARE NOT THIS MODULE'S FACT. gunbc.ci_layer_roots
// witness_layer_roots is the existing authority -- the live workflow already
// folds it into its --source-root flags -- so declaring a list here was a fork
// of it, which is the violation one level above the one review 53848 caught.
// Consumed, not redeclared.
//
// The argv is a TOTAL fold over that authority, so adding a root changes the
// command with nothing to remember. An earlier revision of this module hand-
// expanded the pairs and declared a substrate gap with a dissolution trigger,
// on the grounds that expanding one element into two needs a flat-map and the
// substrate has neither flatten nor list destructuring. Both observations were
// true and the conclusion was wrong: `fold` exists and is exactly the primitive
// required -- the workflow module two files away was already using it for this
// same job. I declared a language-layer gap without enumerating the language,
// which is the failure my own notes name as searching by remembered name rather
// than reading the authority surface.

fn floor_inputs_manifest_ref() -> ArtifactManifestRef {
concat("gunbc.floor.inputs.source-roots:", join(witness_layer_roots, "+"))
}

// A modeled command, not a string blob. extdeps.exec.command already owns the
// argv carrier, so authoring a shell line here would have been a second
// representation of "how a process is invoked" -- the medium-as-string tell.

fn floor_run_command() -> ArgvCommand {
ArgvCommand {
argv: fold(
witness_layer_roots,
init: ["target/release/claim_executor", "--required-floor"],
f: fn(acc, root) { append(acc, items: ["--source-root", root]) },
),
}
}

// THE FLOOR IS AN ORDINARY PRICED DEMAND, NOT A PRIVILEGED PATH.
//
// gunbc's own CI enters the market on the same terms as any other demand, and
// this fold takes the budget ceiling as an argument precisely so that there is
// no arm here that admits a floor run without clearing a price. If self-CI
// bypassed the market, the opportunity cost of running our own work would not
// be a computable quantity and the arbitrage -- run our CI on our hardware, or
// sell that capacity and rent -- would degrade into a hand-maintained
// spreadsheet.
//
// Control-plane work is a separately privileged class. That exclusion must not
// leak here: a floor run is customer work that happens to be ours.

fn floor_offer_eligibility<P>(
offer: Offer<P>,
maximum_buy_order: MoneyAmountMicro,
budget_currency: CurrencyCode,
) -> OfferEligibility {
offer_eligibility_for(
requirements: floor_execution_requirements(),
offer: offer,
maximum_buy_order: maximum_buy_order,
budget_currency: budget_currency,
)
}

// THE FLOOR'S DEMAND. This is where "ordinary priced demand" stops being a
// property of a fold's signature and becomes a row someone can read.
//
// REUSE IS A POLICY ON THE DEMAND, NOT A PROPERTY OF THE WORK. The cutover runs
// with terminal_receipt_may_satisfy = false and new_attempt_required = true, so
// an identical Work that already has an accepted receipt still executes. That
// is deliberately conservative -- it preserves today's Actions behaviour while
// the purity of the floor as a function of the tree is unproven -- and it is
// expressed HERE rather than in the Work key, because turning reuse on later
// must edit a policy row and not edit what a Work IS. The two were conflated in
// the plan's own section 13 and in the sign-off that answered it; the carriers
// never conflated them, which is why this needed no new modeling.
//
// step_reuse_permitted stays TRUE: a materialization provider may still
// accelerate a rerun. That is not the same claim as "the step completed" -- a
// build cache making the second attempt faster is not a receipt.

fn floor_satisfaction_requirement() -> SatisfactionRequirement {
SatisfactionRequirement {
terminal_receipt_may_satisfy: false,
new_attempt_required: true,
step_reuse_permitted: true,
}
}

fn floor_buy_terms(
account: BudgetAccountId,
reservation_price: MoneyAmountMicro,
maximum_buy_order: MoneyAmountMicro,
) -> BuyTerms {
BuyTerms {
budget_account: account,
currency: Usd,
reservation_price: reservation_price,
maximum_buy_order: maximum_buy_order,
}
}

// priority_class is NOT a privilege escape. The floor competes on price like any
// other demand; a priority class orders demands that can all be afforded, it
// does not admit one that cannot. If this ever becomes the field that lets gunbc
// jump the queue, the arbitrage has been lost and the opportunity cost of our
// own work has stopped being computable.

fn floor_admission_terms(buy: BuyTerms, deadline: Timestamp?) -> AdmissionTerms {
AdmissionTerms {
priority_class: "gunbc.ci.floor",
deadline: deadline,
buy: buy,
}
}
102 changes: 100 additions & 2 deletions dag/product/fabric/supply.dag
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
module product.fabric.supply

import std.types { Timestamp, Int }
import std.measure { MoneyAmountMicro, MoneyPerSecond, MoneyPerHour, MoneyOnce }
import std.measure {
MoneyAmountMicro, MoneyPerSecond, MoneyPerHour, MoneyOnce,
HardwareThreadCount, hardware_thread_count_value, money_amount_micro_count,
}
import std.currency { CurrencyCode }
import product.fabric.identity { FabricIdentity, OfferKey }
import product.fabric.demand { ObservationReceiptRef }
import product.fabric.work { Shape, CapabilityManifestRef, TrustDomainRef }
import product.fabric.work { Shape, CapabilityManifestRef, TrustDomainRef, ExecutionRequirements }

// An Offer is a supplier's statement of capacity it is willing to sell. Owned
// capacity and rented capacity are ONE type: what differs is the evidence behind
Expand Down Expand Up @@ -132,3 +135,98 @@ type Offer<P> {

type SelectionPolicy =
| CheapestFungibleWithDelayValuation

// FUNGIBILITY IS THE FABRIC'S QUESTION, NOT A CONSUMER'S.
//
// This fold arrived here from gunbc.fabric_witness_run, where it had been
// written as authorize_floor_run with a FloorRunRefusal coproduct. Nothing in
// it was ever about the floor: comparing a Work's requirements against an
// Offer's capabilities is provider-neutral, and work.dag's own header already
// calls fungibility "selection's first and load-bearing step". A consumer that
// owns this fold is a consumer that will answer it differently from the next
// consumer, which is the fork the fabric exists to prevent.
//
// AFFORDABILITY IS DELIBERATELY A SEPARATE ARM FROM CAPABILITY. A demand that
// cannot afford an offer and a demand an offer cannot serve are different
// facts with different remedies -- raise the buy order, or find another
// supplier -- and collapsing them into one "not eligible" loses which.

type OfferEligibility
= OfferEligible
| ShapeNotCovered { required_threads: HardwareThreadCount, offered_threads: HardwareThreadCount }
| TrustDomainMismatch { required: TrustDomainRef, offered: TrustDomainRef }
| CapabilitiesNotOffered { required: CapabilityManifestRef, offered: CapabilityManifestRef }
| QuoteExceedsMaximumBuyOrder { quoted: MoneyAmountMicro, maximum: MoneyAmountMicro }
| QuoteCurrencyMismatch { quoted: CurrencyCode, budgeted: CurrencyCode }
| RateQuoteNotPriceableAgainstGrantCeiling { quoted: MoneyAmountMicro }

fn offer_covers_shape(offered: Shape, needed: Shape) -> Bool {
hardware_thread_count_value(t: offered.hard.threads) >= hardware_thread_count_value(t: needed.hard.threads)
}

// THIS FOLD SCREENS AFFORDABILITY. IT DOES NOT SELECT.
//
// It answers: can this demand pay this offer's asking price, in this currency,
// for a shape and trust domain that fit. Nothing here chooses among several
// eligible offers, and choosing is where the economics actually live.
//
// WHAT AN OFFER CARRIES, AND WHAT IT DOES NOT. The quote is a supplier-side
// ASKING PRICE for one grant. It is NOT an opportunity cost: what an hour could
// otherwise have earned depends on which OTHER demands could use it, so it is a
// property of the assignment evaluation and of the decision receipt, never a
// field on the supply row. Two earlier revisions of this note got this wrong in
// opposite directions -- first calling opportunity cost a demand-side question,
// then carrying it on the offer as a second cost -- and both are recorded here
// rather than reworded, because the sentence was cited downstream each time.
//
// Nor is marginal cash cost zero for an owned host: power and cooling are
// incurred by the act of running, so they are a real dispatch input. Only the
// HISTORICAL PURCHASE is sunk, and sunk cost is excluded from dispatch while
// being retained for accounting.
//
// WHAT SELECTION WOULD NEED, none of which exists here: the offer's availability
// interval, the supplier tariff with its billing quantum, rounding and minimum
// charge, the paid-through commitment state that makes an already-bought hour's
// marginal cash zero until it expires, transition and start costs, and the
// alternative uses that give an opportunity cost its value -- including the arm
// where there is NO feasible alternative use, so an hour about to expire idle is
// not priced as though a customer had been displaced, and the arm where the
// alternative is simply UNREAD, so unknown does not silently become zero.
//
// Until those land, this fold is honest as a screen and would be a lie as a
// selector.

// The budget ceiling arrives as SCALARS rather than as demand.BuyTerms, because
// supply must not import demand -- a backward edge this module already carries
// once for ObservationReceiptRef and must not deepen. The demand side supplies
// them at the call site, which is also where they are known.

fn offer_eligibility_for<P>(
requirements: ExecutionRequirements,
offer: Offer<P>,
maximum_buy_order: MoneyAmountMicro,
budget_currency: CurrencyCode,
) -> OfferEligibility {
if requirements.trust_domain != offer.trust_domain {
TrustDomainMismatch { required: requirements.trust_domain, offered: offer.trust_domain }
} else if requirements.capabilities != offer.capabilities {
CapabilitiesNotOffered { required: requirements.capabilities, offered: offer.capabilities }
} else if !offer_covers_shape(offered: offer.shape, needed: requirements.shape) {
ShapeNotCovered {
required_threads: requirements.shape.hard.threads,
offered_threads: offer.shape.hard.threads,
}
} else if offer_quote_currency(q: offer.quote) != budget_currency {
QuoteCurrencyMismatch { quoted: offer_quote_currency(q: offer.quote), budgeted: budget_currency }
} else {
match offer.quote {
QuotedPerSecond(r) => RateQuoteNotPriceableAgainstGrantCeiling { quoted: r.amount }
QuotedPerHour(r) => RateQuoteNotPriceableAgainstGrantCeiling { quoted: r.amount }
QuotedFlatPerGrant(r) => if money_amount_micro_count(m: r.amount) > money_amount_micro_count(m: maximum_buy_order) {
QuoteExceedsMaximumBuyOrder { quoted: r.amount, maximum: maximum_buy_order }
} else {
OfferEligible
}
}
}
}
Loading