Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
e759b44
Shape git-update-ref's compare-and-swap form, so the unconditional wr…
Aug 20, 2026
0930d5c
Merge remote-tracking branch 'origin/main' into fleet/converge-deploy…
Aug 20, 2026
cb433ed
Give git.PublicationTransport a compare-and-swap ref advance
Aug 20, 2026
016c86d
Stop claiming PushRefUpdateWithLease separates a refused lease from a…
Aug 20, 2026
fecf00f
Hoist the PushRefUpdateWithLease annotation to module grain
Aug 21, 2026
cd53704
Remove the observer-split increment that git add -A swept into this PR
Aug 21, 2026
183cb77
Split FleetDesiredRevision so an absent ref is a claim, not a failure…
Aug 21, 2026
3d5cdee
Name the refusal that cannot license a write, instead of collapsing it
Aug 21, 2026
caf4da3
The admission gate consumes the observation's decision, not an Option…
Aug 21, 2026
e33fc50
Merge remote-tracking branch 'origin/main' into fleet/converge-observ…
Aug 21, 2026
f9be532
Merge branch 'fleet/converge-observe-absent' into fleet/admission-con…
Aug 21, 2026
0ee97e7
One accepted fleet revision from two exact positive facts
Aug 21, 2026
5703f2c
Forward-only desired-ref admission: a lease is atomic, not monotone
Aug 21, 2026
5863789
Merge remote-tracking branch 'origin/main' into fleet/admission-consu…
Aug 21, 2026
a437d89
Merge remote-tracking branch 'origin/main' into fleet/admission-consu…
Aug 21, 2026
36530ac
Merge branch 'fleet/admission-consumes-expectation' into fleet/accept…
Aug 21, 2026
06c5544
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
c5b3e7f
Fix broken main: answer the two observation arms fleet_desired_admiss…
Aug 21, 2026
af5cfd2
Merge branch 'fix/main-fleet-desired-admission-exhaustive' into fleet…
Aug 21, 2026
7bd2796
Port the live admission consumer to the typed expectation seam
Aug 21, 2026
d9bead4
Deduplicate the fleet_desired_ref_name import (review 54265)
Aug 21, 2026
29bb71b
Merge branch 'fix/main-fleet-desired-admission-exhaustive' into fleet…
Aug 21, 2026
b455a8e
Merge branch 'fleet/admission-consumes-expectation' into fleet/accept…
Aug 21, 2026
eb9abd6
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
52c4398
Say what the module cannot EXECUTE, not what policy forbids (module o…
Aug 21, 2026
84e4a5c
Merge branch 'fix/main-fleet-desired-admission-exhaustive' into fleet…
Aug 21, 2026
07efdb8
Merge branch 'fleet/admission-consumes-expectation' into fleet/accept…
Aug 21, 2026
b8acbc2
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
ef4bbb7
Surface MergeBase's exit code and fold it into a subject-bound ancest…
Aug 21, 2026
4b9d025
Hoist the arm rationale to module grain (§4c): the floor refused duri…
Aug 21, 2026
c6ec69e
Merge branch 'fix/main-fleet-desired-admission-exhaustive' into fleet…
Aug 21, 2026
3f849ab
Merge branch 'fleet/admission-consumes-expectation' into fleet/accept…
Aug 21, 2026
acfb39f
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
42f83e9
Three structural corrections: input sum, one unverifiable, and creati…
Aug 21, 2026
bb56350
Merge remote-tracking branch 'origin/main' into fleet/admission-consu…
Aug 21, 2026
d66f6eb
Take main's arm wording and drop this PR's stale copy of its witnesses
Aug 21, 2026
7877843
Merge branch 'fleet/admission-consumes-expectation' into fleet/accept…
Aug 21, 2026
1224ff5
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
6e088d6
Reuse the relation DECISION, not only its five variant names
Aug 21, 2026
645eb5a
The effectful half of the ancestry observation, and the sole construc…
Aug 21, 2026
d326030
Read the repository and branch authorities instead of spelling them a…
Aug 21, 2026
5246f59
Merge branch 'fleet/accepted-revision-two-facts' into fleet/forward-o…
Aug 21, 2026
da6de46
Port the live fleet-desired admission onto the accepted-revision auth…
Aug 21, 2026
86ed90a
Repair the fixture the previous commit captured mid-mutation, and cor…
Aug 21, 2026
6193747
Queue every admissible main completion instead of replacing it: forwa…
Aug 21, 2026
7d9f0ba
Merge remote-tracking branch 'origin/main' into fleet/forward-only-ad…
Aug 21, 2026
600f3e3
git.Inspect.MergeBase names the repository it inspects instead of inh…
Aug 21, 2026
44328ea
Restore the creation capability this branch silently reverted, and bo…
Aug 21, 2026
fa2290e
Revert the creation "restoration": it reversed a deliberate policy wh…
Aug 21, 2026
fcbda10
Give git's merge-base exit table an owner, and pin the absent-arm cla…
Aug 21, 2026
0f2269d
Stop the unrelated-advance receipt claiming a topology it never observed
Aug 21, 2026
66f662b
Inject the observed repository, and ground `queue: max` by measuremen…
Aug 21, 2026
4b938cd
State what MergeBaseOutcome did NOT dissolve, before the annotation i…
Aug 21, 2026
5cd007e
Prove the effectful ancestry observer end to end, and declare where i…
Aug 21, 2026
939bed4
Merge origin/main: resolve the creation divergence, and PORT the one …
Aug 21, 2026
903cbfd
Rename the merge-base field to what it holds, and refuse to claim a r…
Aug 21, 2026
accc0a5
Fold the duplicated import blocks this branch's own merge created
Aug 21, 2026
1a6b6c9
Merge remote-tracking branch 'origin/main' into fleet/forward-only-ad…
Aug 21, 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
9 changes: 6 additions & 3 deletions .github/workflows/fleet-desired.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ name: fleet-desired
on:
workflow_run:
workflows: [witnesses]
branches: [main]
types: [completed]
concurrency:
queue: max
group: gunbc-fleet-desired-admission
cancel-in-progress: false
jobs:
admit:
runs-on: [self-hosted, linux, arm64, srv1]
Expand All @@ -29,7 +32,7 @@ jobs:
set -eu
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
mkdir -p "$ROOT/target"
rm -f "$ROOT/target/fleet-desired-authorized-push.sh"
rm -f "$ROOT/target/fleet-desired-authorized-action.sh"
cp "$GITHUB_EVENT_PATH" "$ROOT/target/fleet-desired-admission-event.json"
- name: Decide whether the floor admits this revision
run: |
Expand All @@ -39,5 +42,5 @@ jobs:
run: |
set -eu
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
test -s "$ROOT/target/fleet-desired-authorized-push.sh"
sh "$ROOT/target/fleet-desired-authorized-push.sh"
test -s "$ROOT/target/fleet-desired-authorized-action.sh"
sh "$ROOT/target/fleet-desired-authorized-action.sh"
104 changes: 101 additions & 3 deletions dag/extdeps/git/inspect.dag
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module extdeps.git.inspect

import std.types { Bool, CommitSha, FilePath, GitRef, String }
import std.types { Bool, CommitSha, FilePath, GitRef, Int, String }
import std.algebra { trim }
import extdeps.external_authority { ExternalAuthority }
import extdeps.uri { Uri, Https }

Expand Down Expand Up @@ -64,6 +65,43 @@ data git_inspect_service_note: String = "Read-only repository-root, revision, an
// `--exclude-standard` is pinned because without it the command applies no ignore rules at all and would
// return every untracked path — the opposite of the question. The output is a bare NUL-separated path list,
// so unlike porcelain v1 it carries no status codes and no rename-source continuation to track.
// MergeBase NAMES THE REPOSITORY IT INSPECTS, AND THE OPERAND IS REQUIRED.
// An ambient operation answers about whichever checkout the process happens to occupy, so the
// same call means different things depending on where it was invoked from -- and a wrong answer
// is INDISTINGUISHABLE from a right one, because two repositories can hold refs that look
// identical. An OPTIONAL operand would keep the ambient form writable, so it is required: the
// state this replaces has no spelling.
//
// THIS IS THE REPOSITORY'S OWN ESTABLISHED ANSWER, NOT A NEW CONVENTION. extdeps.git RemoteUrlIn
// already takes `repository_path` and renders `git -C {repository_path}`, for exactly this reason
// -- it could otherwise confirm the remote of the wrong checkout. This operation is brought into
// line with that authority rather than inventing a second way to say the same thing.
//
// WHY THE OPERAND SITS ON THE OPERATION AND NOT ON THE INVOCATION. "Which repository does this
// inspect" is a fact about the git operation's SUBJECT; "what directory did the OS start this
// process in" is a transport fact. Modeling the first as the second would push repository
// selection into every handler that runs a command -- the N x M adapter shape. One
// repository-addressed operation with one shell realization is not that.
//
// THE SIBLING POPULATION IS DECLARED RATHER THAN SILENTLY LEFT. Five operations in this service
// are still repository-ambient by the same mechanism: HeadCommit, WorkingTreeStatus,
// IgnoredFiles, ListTreePathsAtRevision and ShowTree. They are NOT ported here because each
// carries its own consumer census and this cut is scoped to the operation whose ambient
// repository blocked a wet observation. Toplevel is deliberately NOT in that list: its purpose IS
// to discover the ambient repository, so naming one would be circular. RUNG for the five:
// mitigatable, and the mitigation is only that production happens to run from the repository
// root. NEXT TRIGGER: the first consumer that must inspect a repository other than its own
// process position -- which is what forced this one.

// MergeBase CARRIES ITS EXIT CODE BECAUSE THE Bool COLLAPSES AN ANSWER WITH AN ABSENCE OF ONE.
// `git merge-base` exits 1 when the two commits genuinely share NO merge base -- unrelated
// histories, which is a FACT about the pair -- and 128 when the ref is invalid or this is not a
// repository, which is a failure to look. Both render `exit_success = false`, so a consumer
// holding only the Bool must either refuse both (losing a real answer) or admit both (treating an
// unreadable repository as proof that two revisions are unrelated). That operation's `exit` block
// has always DECLARED the distinction; its output simply never surfaced it, so the declaration was
// unreachable by any caller.

// ResolveRefCommit is a SEPARATE operation from ShowTree rather than a format flag on it, and the
// separation is the point: `%T` and `%H` answer different questions about the same ref. The tree is
// the CONTENT at that ref; the commit is its identity INCLUDING ancestry, which the tree does not
Expand Down Expand Up @@ -137,14 +175,15 @@ service git.Inspect {
}

operation MergeBase {
input { left: GitRef, right: GitRef }
input { repository_path: String, left: GitRef, right: GitRef }
output {
sha: CommitSha from "stdout"
success: Bool from "exit_success"
exit_code: Int from "exit_code"
stderr: String from "stderr"
}
readonly
transport shell { argv: ["git", "merge-base", "{left}", "{right}"] }
transport shell { argv: ["git", "-C", "{repository_path}", "merge-base", "{left}", "{right}"] }
exit {
0 => Unit
1 => String "No merge base"
Expand Down Expand Up @@ -197,3 +236,62 @@ service git.Inspect {
}
}
}

// MERGE-BASE EXIT SEMANTICS ARE A FACT OF GIT, SO THEY ARE MODELED HERE BESIDE THE EXIT TABLE THAT
// DECLARES THEM, and not re-derived by each consumer as bare integers compared with `==`. The
// operation above already states the contract -- 0, 1, 128 with distinct meanings -- and a consumer
// that mints its own `merge_base_exit_ok: Int = 0` beside it is holding a second representation of
// this module's fact: the §2/§3 undeclared sum, free to drift from the exit table the day a fourth
// code is declared, and free to be compared against the wrong operation's codes with no complaint
// from anything.
//
// THE THREE OUTCOMES ARE NOT A RANKING AND THE MIDDLE ONE IS NOT AN ERROR. Exit 1 is a legitimate
// ANSWER -- git looked and there is no common ancestor -- which is precisely what lets a consumer
// distinguish "these histories never met" from "I could not find out", the distinction §5 forbids
// collapsing. Exit 128 is the refusal: a bad object or a path that is not a repository, where
// nothing about the two revisions has been established. Rendering 128 as NoCommonAncestor would
// read an unreadable repository as proof that two revisions are unrelated.
//
// THE FIELD IS `base_hex`, NOT `stdout`, AND THAT RENAME IS THE ACTUAL FIX. It never held raw
// stdout: the operation's output binding delivers `sha` already stripped of git's line terminator,
// so a field named for the transport was describing something the transport does not hand over.
//
// THE NEWLINE CLAIM THIS PARAGRAPH ORIGINALLY MADE WAS FALSE AND IS CORRECTED BY MEASUREMENT.
// Review 54424 reported that a future caller passing raw stdout would get an "undecodable" refusal
// on a trailing newline, and I wrote a paragraph here asserting exactly that mechanism -- citing
// `git merge-base` emitting a newline after the fortieth hex digit, which it does. What I had not
// checked was whether that byte survives to this fold. It does not. Receipt: a recorded fixture's
// stored `sha` is 40 characters with no terminator, and REMOVING the trim below leaves the whole
// wet matrix green -- a mutation that changes nothing is the proof the guard was inert. The
// caller's trim, which this change deleted, was equally inert for the same reason.
//
// So the trim stays as idempotent normalization at the boundary that owns the wire format, and it
// is described as what it is: a total function over any string a caller hands this fold, NOT a
// live defect being closed. Calling it the latter would have been a fabricated mechanism sitting
// in a paragraph justifying its own code -- the same class as an inflated rung, and the reason the
// measurement is recorded here rather than the conclusion alone.
//
// Decoding that hex into an object id still belongs to the consumer that owns the id type; this
// module owns what git SAID and what its exit code MEANS, not how the caller names commits.
type MergeBaseOutcome
= MergeBaseReported { base_hex: String }
| NoCommonAncestor
| MergeBaseRefused { exit_code: Int, stderr: String }

data merge_base_exit_reported: Int = 0

data merge_base_exit_no_common_ancestor: Int = 1

// Total over every integer, deliberately: an undeclared exit code is a REFUSAL carrying the code
// that produced it, never a fourth silent arm and never a default that resolves to an answer.
fn merge_base_outcome(exit_code: Int, stdout: String, stderr: String) -> MergeBaseOutcome {
if exit_code == merge_base_exit_reported {
MergeBaseReported { base_hex: trim(s: stdout) }
} else {
if exit_code == merge_base_exit_no_common_ancestor {
NoCommonAncestor
} else {
MergeBaseRefused { exit_code: exit_code, stderr: stderr }
}
}
}
21 changes: 20 additions & 1 deletion dag/extdeps/github/actions.dag
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ type WorkflowTrigger
| Schedule { cron: CronSchedule }
| WorkflowDispatch { inputs: List<DispatchInput> }
| WorkflowCall { inputs: List<DispatchInput> }
| WorkflowRunCompleted { workflows: List<String> }
| WorkflowRunCompleted { workflows: List<String>, branches: List<String> }
| MergeGroup

type PullRequestActivity
Expand Down Expand Up @@ -144,6 +144,25 @@ type CancelInProgressWhenQueueMax
= QueueMaxCancelInProgressFalse
| QueueMaxCancelInProgressExpression { expression: String }

// THE `queue` KEY IS NOT IN GITHUB'S PUBLISHED WORKFLOW SYNTAX, AND ITS BEHAVIOUR HERE IS
// GROUNDED BY OBSERVATION RATHER THAN BY CITATION. That is the honest position and it is stated on
// the type rather than left for a reader to assume a doc link exists: raised in review 54384, which
// asked whether GitHub silently ignores the key -- in which case the queueing guarantee reduces to
// `cancel-in-progress: false` and the emitted yaml promises something the platform never consumes.
//
// Established by execution, not by reading: two workflows differing ONLY in this key, three rapid
// pushes each, same repository and runner pool. With `queue: max` all four runs completed and none
// was cancelled; without it, two of four were CANCELLED while pending. So the key is consumed and
// it changes behaviour in exactly the direction the variant names. The measured receipt lives in
// the observing layer, per the external-upstream rule that an observation this repository produces
// is a receipt of ours and not a fact authored inside the upstream module: gunbc.fleet_desired_admission_workflow
// `fleet_desired_queue_max_measured_receipt`.
//
// WHAT IS STILL UNGROUNDED, named so it is not mistaken for settled: an undocumented key can change
// or be withdrawn without a deprecation, and the 100-pending ceiling is read from GitHub's prose
// about full queues rather than from a specification of this key. Next-rung trigger: GitHub
// publishing `queue` in the workflow-syntax authority, at which point this note becomes an ordinary
// citation row and the receipt becomes a regression control rather than the grounding itself.
type ConcurrencySpec
= ConcurrencyScalar { group: String }
| ConcurrencyMappingQueueMax {
Expand Down
5 changes: 4 additions & 1 deletion dag/extdeps/languages/yaml/gha_workflow.dag
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,10 @@ fn workflow_trigger_entry(trigger: WorkflowTrigger) -> YamlKeyValue {
]))
WorkflowCall { inputs: _ } =>
kv(key: "workflow_call", value: YamlNull)
WorkflowRunCompleted { workflows: ws } =>
WorkflowRunCompleted { workflows: ws, branches: bs } =>
kv(key: "workflow_run", value: yaml_mapping(entries: [
kv(key: "workflows", value: string_list_flow(items: ws)),
kv(key: "branches", value: string_list_flow(items: bs)),
kv(key: "types", value: string_list_flow(items: [workflow_run_activity_completed]))
]))
MergeGroup =>
Expand All @@ -195,6 +196,8 @@ fn cancel_in_progress_when_queue_max_yaml(spec: CancelInProgressWhenQueueMax) ->
}
}

data workflow_run_branches_emission_note: String = "GitHub filters workflow_run by the branch of the TRIGGERING run, documented as `You can use the branches or branches-ignore filter to specify what branches the triggering workflow must run on in order to trigger your workflow` (docs.github.com Events that trigger workflows, workflow_run, read 2026-08-21). That is the same fact a job-level `head_branch ==` condition tests, one grain earlier: the condition skips the job AFTER the run has been created and has entered its concurrency group, while the filter stops the event creating a run at all. The distinction is load-bearing rather than cosmetic -- a created-then-skipped run still occupies a concurrency slot, and in the default group an arriving entry evicts the pending one, so an irrelevant branch could cancel a real pending admission and then do nothing. The member is REQUIRED and emitted unconditionally, matching the Push and PullRequest siblings: a caller declaring this trigger must decide which branches it answers to, and an omitted filter meaning `every branch` is exactly the state that produced the eviction."

data concurrency_queue_max_emission_note: String = "ConcurrencyMappingQueueMax exists to express GitHub's `queue: max`, and until this row it emitted NO queue key — so it serialized byte-identically to ConcurrencyMappingQueueNotMax and the modeled distinction had no realization difference at all (srv1-deploy-serialization-and-false-greens.md §4, second drop). That matters because the two variants mean DIFFERENT THINGS on the platform: the default (QueueNotMax) holds at most one running and one pending entry, and a newly-arriving entry CANCELS the existing pending one, whereas `queue: max` permits multiple pending up to a documented cap of 100 with cancel-in-progress forced false. A caller reaching for QueueMax is asking for the no-cancel queue and was silently getting pending-replacement. `queue` is emitted FIRST so the mapping reads queue-then-group-then-cancel; CancelInProgressWhenQueueMax already models the platform's constraint that cancel-in-progress cannot be true here, so that arm needs no extra guard. Witness: gha_job_projection_witness_test asserts the emitted mapping CONTAINS the queue key and that the two variants no longer serialize identically."

fn concurrency_mapping_queue_max(group: String, cip: CancelInProgressWhenQueueMax?) -> YamlValue {
Expand Down
6 changes: 6 additions & 0 deletions dag/gunbc/ci_layer_roots.dag
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,12 @@ data witness_exclusion_frontier: List<WitnessExclusionRow> = [
reason: "wet-integration class (wet_integration_offline_note posture), substantiated per-row: direct_rust_door_emit_write_compile_holds runs tools.direct_rust_door_transport.run_direct_rust_door_emit_write_compile_smoke, which performs live shell.Mktemp.Dir, Filesystem.Write, and cargo.Build.BuildManifest effects with no hermetic mock_response coverage. Hermetic discovery REFUSES rather than fabricating Unit, so per-PR discovery cannot exercise the write-to-disk + compile receipt. Ingest-path provenance and closing-contract witnesses live in src/v2/test/claim/long/ (5s budget rule); fast closure witnesses stay per-PR in src/v2/test/claim/self_host/.",
dissolution: unbound_dissolution(description: "the wet lane un-darkens and admits live cargo compile smokes under its own budget; this witness enrolls there as a declared execution row and this exclusion deletes. Local recipe until then: claim_batch --wet --source-root dag --source-root src/v2 --entry dag/test/claim/direct_rust_door_write_compile_witness_test.dag --function direct_rust_door_emit_write_compile_holds")
},
WitnessExclusionRow {
pattern: "fleet_revision_relation_wet_matrix_test.dag",
classification: OfflineLocalRecipe,
reason: "wet/replay class (wet_integration_offline_note posture), substantiated by reading the carrier rather than by a floor red: every dispatching row reaches git.Inspect.MergeBase, which publishes no mock_response, so hermetic discovery REFUSES by construction rather than skipping. WHAT MAKES THIS ROW DIFFERENT FROM ITS SIBLINGS ABOVE, and the reason it is not merely 'another live-effects file': the recorded observations that WOULD make it hermetic already exist and are committed — the seven cases were recorded wet against a deterministic fixture repository and replay green from dag/test/fixtures/fleet-revision-relation. The blocker is that there is no way to hand them to a floor run. v2.std.witness_evaluation WitnessEvaluationFrame carries `rest_fixtures: List<RestExchangeFixture>` and nothing else; its own note states that filesystem and environment replay bindings are intended to extend that carrier later, and no shell/service arm exists yet. The external store this file's recipe uses is a claim_batch flag (--fixture-store) and claim_executor has no equivalent, so neither route reaches the required floor. So the honest state is: the composition is PROVEN, and its proof executes nowhere the floor can see. THE PURE HALF IS NOT EXCLUDED — the merge-base fold's exit-code and relation controls stay discovery-enrolled in fleet_main_revision_witness_test.dag per-PR (exit_one_is_an_answer_and_exit_one_two_eight_is_an_absence_of_one, one_merge_base_decides_both_directions, a_successful_probe_with_undecodable_output_refuses); only the effectful composition runs here.",
dissolution: unbound_dissolution(description: "A SHELL/SERVICE FIXTURE ARM ON v2.std.witness_evaluation WitnessEvaluationFrame, beside rest_fixtures, so a recorded shell-transport observation can be installed for the dynamic extent of a witness the way a REST one already is. That is the carrier the frame's own note anticipates. When it lands these nine rows enroll unchanged — they are already written against a replay store — and this exclusion deletes; no second trigger is needed and the wet lane un-darkening is NOT one, because these rows do not need live git, they need their recorded answers to reach a hermetic run. Local recipe until then, and it carries its own discriminating controls: RECORD claim_batch --wet --record --fixture-store dag/test/fixtures/fleet-revision-relation --source-root dag --source-root src/v2 --entry dag/test/claim/fleet_revision_relation_wet_matrix_test.dag --functions identical_revisions_are_converged_without_dispatching_a_probe,identical_revisions_converge_even_when_the_path_is_not_a_repository,an_ancestor_current_is_a_forward_advance,an_ancestor_accepted_is_superseded,siblings_sharing_an_ancestor_are_neither_ancestor_of_the_other,an_orphan_root_has_no_common_ancestor,an_absent_object_is_unverifiable_not_unrelated,a_non_repository_path_is_unverifiable_rather_than_answering,no_merge_base_and_could_not_look_stay_distinguishable ; REPLAY the same command with --hermetic in place of --wet --record ; CONTROL replay again with --fixture-store pointing at an EMPTY directory — the two short-circuit rows must still PASS and the other seven must FAIL with `missing recorded fixture`, which is what proves the passing replay consumed recorded observations rather than reaching live git. The fixture repository is rebuilt by docs/plans/fleet-revision-relation-fixture.md")
},
WitnessExclusionRow {
pattern: "external_model_scope_live_cover_witness_test.dag",
classification: OfflineLocalRecipe,
Expand Down
Loading