Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
d4257b6
Spark row production leaves artifact assembly, and members bind to th…
Aug 30, 2026
7ca57a6
wip axis disposition
Aug 30, 2026
c31cc43
wip axis controls
Aug 30, 2026
5942842
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 30, 2026
ee2b645
P0-C3: the axis names its own host and an unprobed Spark is not a non…
Aug 30, 2026
1d9a590
hoist annotation to module grain
Aug 30, 2026
9491b3c
witness call sites: the axis is tagged for the host being planned
Aug 30, 2026
4c24c5b
cli axis arm: witnesses
Aug 30, 2026
af91e62
apply refuses an enrolled Spark it did not observe: the plan-side gua…
Aug 30, 2026
a7f035f
apply-path refusal extracted to a witnessable decision, with its control
Aug 30, 2026
cdc4f1c
close the apply spark-admission match
Aug 30, 2026
bbd24bf
the empty spark population is not constructible for an enrolled Spark
Aug 30, 2026
255d309
exact-consumer control for the apply interlock
Aug 30, 2026
53ae6c8
typed artifact refusal, one exhaustive axis match, projections deleted
Aug 30, 2026
a69115e
Merge main into P0-C3
Aug 30, 2026
99eec02
enrollment is one classification read by both CLIs
Aug 30, 2026
423a620
probe transaction carrier: one host, one attempt, one locus, one capt…
Aug 30, 2026
5cef216
the mint is the admission
Aug 30, 2026
32187f6
one acquisition per host: the sub-observers become pure reads of capt…
Aug 30, 2026
73cb22d
close the observed-facts match at the slice site
Aug 30, 2026
0cfcd24
rename the carrier capture: SparkServingProbeCapture was already take…
Aug 30, 2026
062f26d
restore the terminal-health import name
Aug 30, 2026
cab0b0c
argv derived from the leg, provenance survives projection, linger rea…
Aug 30, 2026
da69f92
bind the extracted parameter names
Aug 30, 2026
d33e2d9
the planned axis carries an opaque transaction-bound payload
Aug 30, 2026
d3200f9
thread provenance through the projection; provenance minted through o…
Aug 30, 2026
025391f
correction A and B: total assembler, honest claim subjects
Aug 30, 2026
9c0c100
retire the endpoint consumer row for the deleted direct probe leg
Aug 30, 2026
6fbc777
mint provenance through its single constructor inside observe too
Aug 30, 2026
288a6cc
Merge main into P0-C3: the apply interlock moves inside main's reques…
Aug 30, 2026
5dece71
balance the apply body after the merge
Aug 30, 2026
371ba0a
the scope predicates gained the arm #9746 added
Aug 30, 2026
ae64f62
the capture carries a request and a typed outcome; coverage is requir…
Aug 30, 2026
da36784
rejoin the split annotation block
Aug 30, 2026
bf4f1c1
guard the empty digest population instead of pattern-matching an empt…
Aug 30, 2026
1066f47
carrier witnesses: coverage, typed outcomes, and the mislabel counter…
Aug 30, 2026
4210409
the missing-leg claim reads the refusal, not a forged transaction
Aug 30, 2026
36bb0fb
string_contains is a builtin
Aug 30, 2026
428f16d
the observation attempt is derived from the sealed context, the host …
Aug 30, 2026
9167a9e
phase identity controls
Aug 30, 2026
1f5fb62
seal the host-observation mint to the transaction projectors and one …
Aug 30, 2026
0690642
the fixture's real module path
Aug 30, 2026
a8ca711
sealed mints, provenance as a sum, and an exhaustive prerequisite que…
Aug 30, 2026
eab7d91
restore the phase declarations swallowed by the provenance rewrite
Aug 30, 2026
81f6789
bind the facts provenance from the context
Aug 30, 2026
506e47c
the axis production route consumes one sealed observation
Aug 30, 2026
80ae195
the bound plan carries the provenance value and its mint is sealed
Aug 30, 2026
6947410
the witness reads the provenance value
Aug 30, 2026
3310fe8
the annotation states the construction that is now present, and names…
Aug 30, 2026
90031b2
the witness reaches the sealed mints through its two admitted fixtures
Aug 30, 2026
f542d1b
the post-apply replan is its own transaction under its own phase
Aug 30, 2026
c80219b
drop the brace left by the extracted replan body
Aug 30, 2026
0bea17c
post-apply phase and provenance-arm controls
Aug 30, 2026
e73ef87
the per-host receipt carries the acquisition it came from
Aug 30, 2026
67594c4
receipt controls
Aug 30, 2026
71a3cc6
adjudicate the linger-argv consolidation as two exact wave-admission …
Aug 30, 2026
74110b3
typed identity lives in the transaction; every provenance projector t…
Aug 31, 2026
68e3090
wip: transaction carries full acquisition identity
Aug 31, 2026
12b7d81
wip: one hermetic acquisition fixture authority
Aug 31, 2026
8ace20b
wip: single planning route, one fixture authority
Aug 31, 2026
23a5eb5
wip: acquisition receipt sum carried and rendered by the production line
Aug 31, 2026
6e96e40
wip: prove the acquisition receipt by consumption through spark_servi…
Aug 31, 2026
e0b36ec
wip: typed observation request names one identity for attempt and ref…
Aug 31, 2026
1b2d0b4
fix: field value must follow its name on one line; restore displaced …
Aug 31, 2026
2078fec
fix: witness consumes computed rows; generic-artifact claim takes its…
Aug 31, 2026
8612587
fix: axis route reads the typed refusal request
Aug 31, 2026
370869c
fix: the fixture imports the calls actually needed; bare references w…
Aug 31, 2026
a8e15b3
wip: hermetic-only fixture mint, typed transaction refusal, coverage …
Aug 31, 2026
1d468c8
wip: delete the bare-projection artifact route; slice takes the obser…
Aug 31, 2026
6f7a9c9
wip: capture shapers drive the production projectors to chosen states
Aug 31, 2026
73e575c
file resolved_reference_outside_execution_closure as a recurring fail…
Aug 31, 2026
4933ebd
wip: fixture owns the one admitted request mint route
Aug 31, 2026
933737b
wip: report claims build observations through the production transact…
Aug 31, 2026
0e93d05
restore the axis route the artifact cut over-removed; slice witness p…
Aug 31, 2026
d0e7d95
witness claims enter the row producer and the observation route; ling…
Aug 31, 2026
1eef079
fix module paths and the two remaining splice call sites
Aug 31, 2026
6b25a49
arity fix on the refusal renderer
Aug 31, 2026
3d1c451
the converged host is assembled from probe output the projectors read
Aug 31, 2026
2e24187
slice and role claims observe a converged host through the captures
Aug 31, 2026
d2bc7c6
c3 claims observe the converged host
Aug 31, 2026
04d9da7
name the positional binders in the content-hash match
Aug 31, 2026
d258a01
the runtime receipt echoes the identity digest the projector compares
Aug 31, 2026
0721889
the unit read echoes the desired unit wire, so the content member con…
Aug 31, 2026
6d0670a
split the conjoined slice claim so a red names which fact broke
Aug 31, 2026
fab7753
one artifact assembler: the generic body writes the typed-actions lin…
Aug 31, 2026
39e8495
the schedule-carrying claims observe a drifting host, so the equality…
Aug 31, 2026
98f732d
the deleted assembler's imports go with it
Aug 31, 2026
5668baf
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
0731d82
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
5fdb7a8
seal the fixture chain transitively and execute its admission wall
Aug 31, 2026
dbab6a5
the control pair varies exactly one fact: whether the roster names th…
Aug 31, 2026
6cef566
regenerate the design projections from the merged roster
Aug 31, 2026
689a3c3
the control pair calls the same function; only the roster differs
Aug 31, 2026
b60ea37
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
05c0ddd
regenerate the projections after the main merge
Aug 31, 2026
2578ec1
fourth shrink: the XL-0N row dissolved when its own PR merged
Aug 31, 2026
755e287
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
34de783
close the import block the conflict boundary split
Aug 31, 2026
654b065
the assembler stays total: the merge reintroduced the absorbing Optio…
Aug 31, 2026
bb99a04
the rebuilt artifact literal carries the field main added
Aug 31, 2026
a44a6a1
Integrate main for composed-tree canary verification
Aug 31, 2026
ce01e18
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
32e2dcc
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
c34717d
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
0599a8a
the relocated spelling names where it went, and the matched variant i…
Aug 31, 2026
744d69e
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
3add770
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
c36658a
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 2026
6a17153
the outcome census is one traversal, and the linger question short-ci…
Aug 31, 2026
68bf48d
Merge remote-tracking branch 'origin/main' into session/eager-pike-54…
Aug 31, 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
1 change: 1 addition & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ One row per class, each carrying its recognition rule and its receipts, in [docs
- `remediation_mutated_view`
- `diagnostic_name_mechanism_silent`
- `identity_absent_graph_traversal`
- `resolved_reference_outside_execution_closure`
- `surface_shorthand_preempts_resolved_identity`
- `meaning_fork`
- `externalized_degradation`
Expand Down
5 changes: 0 additions & 5 deletions dag/gunbc/endpoint_authority_replacement_cut.dag
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,6 @@ fn external_consumers() -> List<BoundaryConsumer> {
decl_name: "spark_serving_converge_slice_wet_host_report",
justification: "wet slice host report addressing",
),
endpoint_consumer(
module_path: "gunbc.spark.serving_observe",
decl_name: "spark_serving_probe_leg",
justification: "serving observation probe endpoint",
),
]
}

Expand Down
215 changes: 197 additions & 18 deletions dag/gunbc/fleet/fleet_converge_plan.dag
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import std.dissolution { DissolutionCondition, dissolution_description, unbound_
import std.disposition { Disposition, Scaffold, SingleAuthority }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import std.content_hash {
content_hash_atom,
content_hash_of_value,
serialize_content_hash,
Fnv1a64StructuralDigestHex,
Expand Down Expand Up @@ -122,7 +123,17 @@ import gunbc.fleet_posix_accounts {
fleet_posix_ci_runner_principal, grounded_posix_principal_name,
ci_runner_sudo_binary_path, SudoInstall, SudoSystemctl,
}
import gunbc.spark.serving_execution_schedule { ScheduledRows, scheduled_rows_empty, scheduled_rows_list }
import gunbc.spark.serving_execution_schedule {
ScheduledRows,
scheduled_rows_empty,
scheduled_rows_list,
SparkServingAxisDisposition,
SparkServingAxisNotApplicable,
SparkServingAxisUnobserved,
SparkServingAxisRefused,
SparkServingAxisPlanned,
}

import gunbc.fleet_converge_timer {
fleet_converge_service_unit_name,
fleet_converge_timer_unit_name,
Expand Down Expand Up @@ -162,7 +173,7 @@ import extdeps.github.actions_runner {
actions_runner_binary_artifact_for_arch,
}
import extdeps.cpu.ampere { altra_max_m12830_catalog }
import product.placement_supply { HostIdentity }
import product.placement_supply { HostIdentity, host_identity_eq }
import gunbc.runner_host_deploy {
RunnerHostDeployFound,
RunnerHostDeployUnmodeled,
Expand Down Expand Up @@ -2322,16 +2333,184 @@ fn fabric_cell_apply_executable_lines(
}
}

// THE ARTIFACT'S OPTIONAL CARRIED A FACT THAT CANNOT HAPPEN, so it is dissolved rather than reused.
//
// It answered `Absent` when `content_hash_of_value` did not return the Fnv1a64 arm -- an absorbing
// arm in the narrowing direction, since a hash the match did not recognize became "there is no plan
// artifact", which every caller reads as nothing to converge rather than as could-not-classify. The
// Spark plan builder repaired exactly this in its own copy and this one was left behind.
// `content_hash_atom` returns Fnv1a64Structural directly -- the same digest, since
// `content_hash_of_value` is that function wrapped in the union -- so there is no union to match and
// no arm to get wrong.
//
// The outcome stays a sum because assembling a plan IS refusable, and the Refused arm now has a real
// producer: a SparkServingAxisRefused disposition propagates here instead of being laundered into an
// empty schedule. An earlier revision made the artifact total and left this arm with nothing
// constructing it -- a permanently-green arm carrying no information, which DESIGN §4b calls worse
// than absent because it gets cited as coverage.
type FleetConvergePlanArtifactOutcome
= FleetConvergePlanArtifactReady { artifact: FleetConvergePlanArtifact }
| FleetConvergePlanArtifactRefused { refusal: FleetConvergePlanArtifactRefusal }

// THE REFUSAL IS A COPRODUCT BECAUSE A DOWNSTREAM CONSUMER CANNOT ASK PROSE WHICH THING WENT WRONG.
//
// Rendering all four non-success situations into one `cause: String` repeated the C2
// producer-versus-renderer mistake one layer later: "the axis does not apply", "the axis applies but
// nobody observed it", "planning ran and refused", and "this axis belongs to another host" are four
// different facts with four different operator responses, and a string is a second, lossy naming
// scheme for a distinction the disposition already carries. The CLI renders this to prose at its
// receipt boundary, which is where rendering belongs.
type FleetConvergePlanArtifactRefusal
= SparkAxisSubjectHostMismatch { axis_host: HostIdentity, subject_host: HostIdentity }
| SparkAxisUnobservedRefusal { host: HostIdentity }
| SparkAxisPlanningRefused { host: HostIdentity, cause: String }

fn fleet_converge_plan_artifact_refusal_text(r: FleetConvergePlanArtifactRefusal) -> String {
match r {
SparkAxisSubjectHostMismatch { axis_host: ah, subject_host: sh } =>
join([
"SparkAxisSubjectHostMismatch — the spark axis is tagged for host ",
ah as String,
" but the plan subject is ",
sh as String,
"; the plan would carry one host's serving rows under another host's baseline and lease",
], "")
SparkAxisUnobservedRefusal { host: h } =>
join([
"SparkAxisUnobserved — ",
h as String,
" is an enrolled Spark and its serving axis was never observed, so a plan built here would",
" claim a completeness that was never measured",
], "")
SparkAxisPlanningRefused { host: h, cause: why } =>
join(["SparkAxisPlanningRefused — on host ", h as String, ": ", why], "")
}
}

// P0-C3: THE SPARK AXIS ARRIVES AS ONE ALREADY-PLANNED PRODUCT.
//
// THE MEMBERS AND THE ROWS ARE ONE PARAMETER BECAUSE THEY ARE ONE FACT. A first cut took
// `observed_spark` and the schedule separately, so a caller could hand members from one observation
// and rows planned from another. `observed_spark` feeds the observed BASELINE, and the baseline is
// what apply re-checks to decide the plan still applies -- so that disagreement would have been
// invisible at exactly the moment it mattered. SparkServingAxisProduct is sole_constructor and only
// the row producer mints it, so the members that fingerprinted the baseline are the members the
// schedule was planned from.
//
// `spark_serving_typed_actions: scheduled_rows_empty()` stood here unconditionally, so the
// production full-host plan could not emit a Spark row even when handed a real observation. That is
// one of two independent breaks that made P0-WET unreachable -- the other being that the CLI passed
// `observed_spark: []` -- which is why repairing either alone changed nothing.
//
// THE ROWS ARE A PARAMETER AND NOT SOMETHING THIS FUNCTION PLANS. A first attempt had the artifact
// call the Spark row producer directly, and the substrate refused it with a circular dependency:
// gunbc.fleet_converge_plan -> gunbc.spark.serving_converge_apply -> gunbc.spark.serving_converge_plan
// already runs the other way. That refusal was correct and load-bearing. Artifact assembly consumes
// already-planned axis products -- timer plan, cap plan, slot plan, fabric plan, activation plan --
// and the Spark schedule is one more of them, not an exception this module reaches down to compute.
// THE AXIS CARRIES A HOST AND SO DOES THIS ARTIFACT, AND NOTHING JOINED THEM.
//
// Putting the host inside the disposition stopped it disagreeing with the OBSERVATION that produced
// it. It did not stop it disagreeing with the SUBJECT being planned: an axis tagged srv6 could be
// handed to an artifact whose subject is srv5, and the resulting plan would carry srv6's retirement
// rows under srv5's baseline and lease. Third instance of the class #9754 opened -- a host carried
// twice, joined by convention -- and this function refuses on the disagreement rather than making it
// unrepresentable, because the two hosts are genuinely two facts until the comparison is made.
// ONE EXHAUSTIVE MATCH ON THE AXIS, NOT THREE PROJECTIONS THAT AGREE BY CALLER ARRANGEMENT.
//
// The first cut asked the disposition three separate questions -- members, rows, refusal -- and was
// safe only because the caller happened to consult the refusal before using the other two. Both
// Unobserved and Refused projected to an empty member list and an empty schedule, so a caller that
// forgot the third question would assemble a perfectly well-formed plan that actuates nothing on a
// host nobody looked at. A refusal has no rows projection now: the arms that cannot be planned are
// eliminated here and never reach the assembler, which takes members and rows as ordinary values.
//
// The subject-host join is part of the same match rather than a guard beside it: each arm binds the
// host the axis is tagged for, so there is no second reading of it to disagree with.
fn fleet_converge_plan_artifact(
host: NonEmptyStr,
prior_generation: Int,
observed_timers: List<TimerRetirementMember>,
observed_caps: List<CapMember>,
spark_axis: SparkServingAxisDisposition<FleetConvergeSparkServingTypedAction>,
observed_slots: List<RunnerSlotMember>,
observed_fabric_cells: FabricCellObservationDecision,
observed_activation_readiness: RunnerActivationReadiness,
) -> FleetConvergePlanArtifactOutcome {
match spark_axis {
SparkServingAxisUnobserved { host: ah } =>
if !host_identity_eq(a: ah, b: host as HostIdentity) {
FleetConvergePlanArtifactRefused {
refusal: SparkAxisSubjectHostMismatch { axis_host: ah, subject_host: host as HostIdentity },
}
} else {
FleetConvergePlanArtifactRefused { refusal: SparkAxisUnobservedRefusal { host: ah } }
}
SparkServingAxisRefused { host: ah, cause: why } =>
if !host_identity_eq(a: ah, b: host as HostIdentity) {
FleetConvergePlanArtifactRefused {
refusal: SparkAxisSubjectHostMismatch { axis_host: ah, subject_host: host as HostIdentity },
}
} else {
FleetConvergePlanArtifactRefused { refusal: SparkAxisPlanningRefused { host: ah, cause: why } }
}
SparkServingAxisNotApplicable { host: ah } =>
if !host_identity_eq(a: ah, b: host as HostIdentity) {
FleetConvergePlanArtifactRefused {
refusal: SparkAxisSubjectHostMismatch { axis_host: ah, subject_host: host as HostIdentity },
}
} else {
FleetConvergePlanArtifactReady {
artifact: fleet_converge_plan_artifact_assembled(
host: host,
prior_generation: prior_generation,
observed_timers: observed_timers,
observed_caps: observed_caps,
observed_spark: [],
spark_rows: scheduled_rows_empty(),
observed_slots: observed_slots,
observed_fabric_cells: observed_fabric_cells,
observed_activation_readiness: observed_activation_readiness,
),
}
}
SparkServingAxisPlanned { plan: bound } =>
if !host_identity_eq(a: bound.host, b: host as HostIdentity) {
FleetConvergePlanArtifactRefused {
refusal: SparkAxisSubjectHostMismatch {
axis_host: bound.host,
subject_host: host as HostIdentity,
},
}
} else {
FleetConvergePlanArtifactReady {
artifact: fleet_converge_plan_artifact_assembled(
host: host,
prior_generation: prior_generation,
observed_timers: observed_timers,
observed_caps: observed_caps,
observed_spark: bound.observed_members,
spark_rows: bound.rows,
observed_slots: observed_slots,
observed_fabric_cells: observed_fabric_cells,
observed_activation_readiness: observed_activation_readiness,
),
}
}
}
}

fn fleet_converge_plan_artifact_assembled(
host: NonEmptyStr,
prior_generation: Int,
observed_timers: List<TimerRetirementMember>,
observed_caps: List<CapMember>,
observed_spark: List<SparkServingMember>,
spark_rows: ScheduledRows<FleetConvergeSparkServingTypedAction>,
observed_slots: List<RunnerSlotMember>,
observed_fabric_cells: FabricCellObservationDecision,
observed_activation_readiness: RunnerActivationReadiness,
) -> FleetConvergePlanArtifact? {
) -> FleetConvergePlanArtifact {
let request = FullHostConverge {
host: host,
observed_timers: observed_timers,
Expand Down Expand Up @@ -2373,6 +2552,12 @@ fn fleet_converge_plan_artifact(
["# fabric-cell"],
fleet_converge_fabric_cell_lines(host: host, observed_fabric_cells: observed_fabric_cells),
[
concat(
"# spark-serving-typed-actions:",
fleet_converge_spark_serving_typed_actions_wire(
rows: scheduled_rows_list(scheduled: spark_rows),
),
),
concat("# slot-refusals=", to_string(fleet_converge_slot_refusal_count(host: host, observed_slots: observed_slots))),
concat("# activation-refusals=", to_string(fleet_converge_activation_refusal_count(host: host, readiness: observed_activation_readiness))),
concat("# cap-refusals=", to_string(membership_refusal_count(plan: cap_plan))),
Expand Down Expand Up @@ -2416,21 +2601,15 @@ fn fleet_converge_plan_artifact(
observed_activation_readiness: observed_activation_readiness,
terminal: planned_terminal,
)
match content_hash_of_value(value: baseline as NonEmptyStr) {
Fnv1a64(structural) =>
Present {
value: FleetConvergePlanArtifact {
subject: subject,
prior_generation: prior_generation,
plan_lease: lease,
apply_terminal: planned_terminal,
observed_baseline_hex: structural.digest,
plan_body: body,
apply_shell: apply_shell,
spark_serving_typed_actions: scheduled_rows_empty(),
},
}
_ => Absent
FleetConvergePlanArtifact {
subject: subject,
prior_generation: prior_generation,
plan_lease: lease,
apply_terminal: planned_terminal,
observed_baseline_hex: content_hash_atom(value: baseline as NonEmptyStr).digest,
plan_body: body,
apply_shell: apply_shell,
spark_serving_typed_actions: spark_rows,
}
}

Expand Down
Loading
Loading