Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
20 changes: 20 additions & 0 deletions dag/extdeps/ci_runner/blacksmith.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import std.nat { Nat }
import std.measure { hardware_thread_count }
import std.decl_ref { DeclarationRef, decl_ref, WholeDeclaration }
import extdeps.toolchain.types { Aarch64, Architecture, X86_64 }
import extdeps.github.actions { github_actions_runs_on_surface }
import extdeps.ci_runner.types {
CatalogSnapshot,
label_catalog_of_shapes,
RunnerLabelCatalog,
EntitlementUnstated,
RunnerCatalogAvailability,
QuotedWithoutBasis,
Expand Down Expand Up @@ -82,3 +86,19 @@ data blacksmith_runner_catalog: RunnerCatalogAvailability = RunnerShapesCited {
blacksmith_shape(label: "blacksmith-32vcpu-ubuntu-2404", architecture: X86_64, vcpus: 32, quoted_numeral: 128),
],
}

// The label roster and its snapshot. See extdeps.ci_runner.types CatalogSnapshot for why the
// fetch time and the declared scope both have to be carried: a consumer that meets a label this
// catalog lacks must be able to tell a finding about the observed repository from a gap in ours.
data blacksmith_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-08-18T00:00:00Z",
declared_scope: "Linux Ubuntu 22.04/24.04 instance types only, both architectures, from the instance-types page cited above. Any other family that page publishes is absent from this catalog because this repository has not read it.",
}

data blacksmith_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.ci_runner.blacksmith", decl_name: "blacksmith_label_catalog"),
provider: blacksmith_provider_identity,
selection_surface: github_actions_runs_on_surface,
snapshot: blacksmith_catalog_snapshot,
availability: blacksmith_runner_catalog,
)
40 changes: 40 additions & 0 deletions dag/extdeps/ci_runner/circleci.dag
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import std.measure { hardware_thread_count }
import std.decl_ref { DeclarationRef, decl_ref, WholeDeclaration }
import extdeps.toolchain.types { Aarch64, Architecture, X86_64 }
import extdeps.ci_runner.types {
CatalogSnapshot,
label_catalog_of_shapes,
RunnerLabelCatalog,
EntitlementUnstated,
RunnerCatalogAvailability,
QuotedWithoutBasis,
Expand Down Expand Up @@ -77,3 +80,40 @@ data circleci_runner_catalog: RunnerCatalogAvailability = RunnerShapesCited {
circleci_shape(label: "2xlarge+", architecture: X86_64, vcpus: 20, quoted_numeral: 40),
],
}

// The label roster and its snapshot. See extdeps.ci_runner.types CatalogSnapshot for why the
// fetch time and the declared scope both have to be carried: a consumer that meets a label this
// catalog lacks must be able to tell a finding about the observed repository from a gap in ours.
data circleci_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-08-18T00:00:00Z",
declared_scope: "Docker executor resource classes only, from the configuration reference cited above. CircleCI's machine, macOS, GPU and Arm executor classes are absent from this catalog because this repository has not read them.",
}

// THESE LABELS ARE NOT GitHub Actions runs-on VALUES AND THE SURFACE SAYS SO. A CircleCI resource
// class is written in `resource_class` in .circleci/config.yml. The spellings overlap ordinary
// words - small, medium, large, arm.medium - which are exactly what a self-hosted GitHub runner
// gets labelled, so a resolver that searched this catalog for a runs-on label would answer
// confidently from the wrong ecosystem. Naming the surface is what keeps that unwritable.
// THE SURFACE IS ITS OWN DECLARATION AND NOT THE PROVIDER'S. An earlier revision pointed this at
// circleci_catalog_authority, which is byte-for-byte the ref circleci_provider_identity already
// uses - so "which key are these labels written in" and "who publishes them" were the same fact,
// and a provider identity passed where a surface was expected would have compared equal. That is
// the interface/realization/policy conflation DESIGN section 3 names, one level up from the defect
// this axis was added to fix.
//
// GitHub's side names the declaration that IS the key: extdeps.github.actions RunnerSpec. There is
// no CircleCI analogue in this repository - `resource_class` is not modelled here at all - so this
// row names ITSELF rather than borrowing a neighbour, and says so instead of implying a modelled
// key exists. When resource_class is modelled, this ref moves to it.
data circleci_resource_class_surface: DeclarationRef = decl_ref(
module_path: "extdeps.ci_runner.circleci",
decl_name: "circleci_resource_class_surface",
)

data circleci_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.ci_runner.circleci", decl_name: "circleci_label_catalog"),
provider: circleci_provider_identity,
selection_surface: circleci_resource_class_surface,
snapshot: circleci_catalog_snapshot,
availability: circleci_runner_catalog,
)
29 changes: 29 additions & 0 deletions dag/extdeps/ci_runner/depot.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import std.nat { Nat }
import std.measure { hardware_thread_count }
import std.decl_ref { DeclarationRef, decl_ref, WholeDeclaration }
import extdeps.toolchain.types { Aarch64, Architecture, X86_64 }
import extdeps.github.actions { github_actions_runs_on_surface }
import extdeps.ci_runner.types {
CatalogSnapshot,
EntitlementUnstated,
label_catalog_of_shapes,
RunnerCatalogAvailability,
QuotedWithoutBasis,
RunnerLabelCatalog,
RunnerShapeRow,
RunnerShapesCited,
}
Expand Down Expand Up @@ -80,3 +84,28 @@ data depot_runner_catalog: RunnerCatalogAvailability = RunnerShapesCited {
depot_shape(label: "depot-ubuntu-24.04-64", architecture: X86_64, vcpus: 64, quoted_numeral: 256),
],
}

// THE LABEL ROSTER, AND THE SNAPSHOT THAT SAYS WHEN WE LOOKED AND AT WHAT.
//
// Re-fetched 2026-09-10 from the runner-types page cited above and compared row by row against
// the twelve sizes below: the Intel and Arm Ubuntu 24.04 tables still publish 2/8, 4/16, 8/32,
// 16/64, 32/128 and 64/256, unchanged from the 2026-08-18 read. The date moves because the
// comparison was made, not because the rows did.
//
// THE SCOPE IS DECLARED BECAUSE THE PAGE IS WIDER THAN THIS MODULE. The same page publishes
// Ubuntu 22.04 Linux, Windows Server 2022/2025 and macOS families, and a depot-ubuntu-latest
// alias, none of which are modelled here. A consumer that meets depot-windows-2022 therefore
// gets a MISS, and the scope sentence is what tells it the miss is this repository's coverage
// gap rather than a label Depot does not publish. Nothing infers that from the label text.
data depot_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-09-10T00:00:00Z",
declared_scope: "Ubuntu 24.04 Linux runner families only, both architectures, from depot.dev/docs/github-actions/runner-types. The Ubuntu 22.04, Windows Server 2022, Windows Server 2025 and macOS families on the same page, and the depot-ubuntu-latest alias, are NOT modelled here: a label from any of them is absent from this catalog because this repository has not read it, not because Depot does not publish it.",
}

data depot_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.ci_runner.depot", decl_name: "depot_label_catalog"),
provider: depot_provider_identity,
selection_surface: github_actions_runs_on_surface,
snapshot: depot_catalog_snapshot,
availability: depot_runner_catalog,
)
26 changes: 26 additions & 0 deletions dag/extdeps/ci_runner/github_actions.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ import std.nat { Nat }
import std.measure { hardware_thread_count }
import std.decl_ref { DeclarationRef, decl_ref, WholeDeclaration }
import extdeps.toolchain.types { Aarch64, Architecture, X86_64 }
import extdeps.github.actions { github_actions_runs_on_surface }
import extdeps.ci_runner.types {
CatalogSnapshot,
EntitlementUnstated,
label_catalog_of_shapes,
RunnerLabelCatalog,
RunnerCatalogAvailability,
QuotedWithoutBasis,
RunnerShapeRow,
Expand Down Expand Up @@ -86,3 +90,25 @@ data github_actions_runner_catalog: RunnerCatalogAvailability = RunnerShapesCite
github_actions_shape(label: "ubuntu-latest-96core", architecture: X86_64, vcpus: 96, quoted_numeral: 384),
],
}

// THE LABEL ROSTER FOR THIS MODULE'S OWN PAGE, AND NOTHING BEYOND IT.
//
// This module's authority is the larger-runners reference, so its label catalog is exactly the
// projection of the sized rows above. THE STANDARD GitHub-hosted LABELS ARE NOT RE-AUTHORED HERE:
// extdeps.github.hosted_runners already owns them, keyed by extdeps.github.actions RunnerLabel
// with the visibility axis this module's RunnerShapeRow lacks, and it says in its own words that
// the label vocabulary is spelled once and "never a free string beside it". Enrolling that
// catalog is gunbc.runner_provider_survey's job, because joining two upstream authorities is
// consumer-layer work and not something either upstream module may do to the other.
data github_actions_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-08-18T00:00:00Z",
declared_scope: "The sized ubuntu-latest-Ncore larger-runner families only, from the larger-runners reference cited above. The STANDARD GitHub-hosted labels are not in this catalog and are not missing from it: they are owned by extdeps.github.hosted_runners and enrolled separately. Self-hosted labels are in no vendor catalog and never will be - a self-hosted label is named by the repository that registered it, so a miss on one is not a coverage gap.",
}

data github_actions_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.ci_runner.github_actions", decl_name: "github_actions_label_catalog"),
provider: github_actions_provider_identity,
selection_surface: github_actions_runs_on_surface,
snapshot: github_actions_catalog_snapshot,
availability: github_actions_runner_catalog,
)
98 changes: 97 additions & 1 deletion dag/extdeps/ci_runner/types.dag
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ module extdeps.ci_runner.types

import std.types { Bool, List, NonEmptyStr }
import std.nat { Nat }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import std.decl_ref { DeclarationRef, WholeDeclaration, declaration_ref_eq }
import extdeps.toolchain.types { Architecture }
import extdeps.time.rfc3339 { Rfc3339Timestamp }
import std.measure {
ByteSize,
Gibibyte,
Expand Down Expand Up @@ -167,3 +168,98 @@ fn runner_shape_rows(availability: RunnerCatalogAvailability) -> List<RunnerShap
fn shape_is_architecture(row: RunnerShapeRow, architecture: Architecture) -> Bool {
row.architecture == architecture
}

// -------------------------------------------------------------------------------------
// THE LABEL SIDE OF A CATALOG, AND WHY IT IS A NARROWER ROW THAN A SHAPE.
//
// A `runs-on` label answers two questions of very different difficulty. WHICH VENDOR AND
// WHICH ARCHITECTURE is a fact every vendor's own page states unambiguously and which does
// not vary with anything else. HOW MANY vCPU AND HOW MUCH MEMORY is not: GitHub publishes
// ubuntu-24.04-arm at 4 vCPU / 16 GB for a PUBLIC repository and 2 vCPU / 8 GB for a private
// one, on the same page, under the same label. A RunnerShapeRow has nowhere to put that, so a
// standard-runner row could only be added to a shape catalog by picking one of the two
// numbers, which is a fabricated fact rather than a modelled one.
//
// So the label roster is its own carrier. Every sized shape yields a label row by projection -
// the sizes are additional, never contradictory - and a vendor may additionally publish labels
// whose size this repository cannot state visibility-free. Nothing is duplicated: a label
// appears here once, either projected from its shape or authored because no shape exists.
type RunnerLabelRow {
provider: DeclarationRef
label: NonEmptyStr
architecture: Architecture
}

fn label_row_of_shape(row: RunnerShapeRow) -> RunnerLabelRow {
RunnerLabelRow { provider: row.provider, label: row.label, architecture: row.architecture }
}

// WHEN THIS REPOSITORY LOOKED, AND WHAT IT CLAIMED TO BE LOOKING AT. Both fields exist because
// a catalog MISS is otherwise two different facts wearing one shape: the vendor does not
// publish that label, or OUR SNAPSHOT is too old or too narrow to know. Those point at
// opposite remedies - report the finding, versus go and re-fetch - and a consumer that cannot
// tell them apart reads a deficit in our own data as a property of somebody else's repository.
// fetched_at decides the first split by construction; declared_scope carries the second, which
// is a claim about our own coverage and can only be authored.
type CatalogSnapshot {
fetched_at: Rfc3339Timestamp
declared_scope: NonEmptyStr
}

// WHICH SELECTION SURFACE THESE LABELS ARE WRITTEN IN, AND WHY THE ABSENCE OF THIS FIELD WAS A
// SOUNDNESS DEFECT RATHER THAN AN OMISSION.
//
// A runner label is not a free-floating name: it is a value written in one specific key of one
// specific CI system's configuration. GitHub Actions labels are written in `runs-on`; CircleCI
// resource classes are written in `resource_class` in .circleci/config.yml. Those are different
// ecosystems, and their namespaces OVERLAP on ordinary words - CircleCI publishes small, medium,
// large, xlarge and arm.medium, all of which are perfectly ordinary things to label a self-hosted
// GitHub runner.
//
// Without this axis a resolver asked what a GitHub Actions `runs-on` label means searched every
// enrolled catalog and answered from whichever one happened to carry the spelling. Measured before
// the fix: resolve_runner_label("arm.medium") returned ArmConfirmed, sourced from CircleCI, for a
// label a GitHub workflow could legitimately carry. That is a CONFIDENT WRONG ANSWER with full
// provenance attached, and no unresolved arm can catch it, because every unresolved arm in that
// resolver is a response to a MISS and this is a HIT from the wrong ecosystem.
//
// IT IS A DeclarationRef AND NOT A VARIANT, for exactly the reason RunnerShapeRow.provider is: a
// central enum of surfaces would have to be widened by every CI system anyone ever enrolls, which
// is the concrete-product enumeration DESIGN section 3 forbids a generic hub. A surface names the
// declaration that defines it and a consumer compares refs.
// WHICH CATALOG THIS IS, WHICH IS NOT THE SAME FACT AS WHO PUBLISHED ITS ROWS. One provider can
// have SEVERAL catalogs in a survey - GitHub's sized larger-runner families and its standard
// runners are two readings of two different published references, and both carry GitHub as the
// provider. A consumer that identified a catalog by its provider could not tell "this catalog
// lists a label twice" from "two catalogs both claim it", which are defects with different owners
// and different repairs: the first belongs to the module that projected the rows, the second to
// the roster that enrolled them.
type RunnerLabelCatalog {
catalog: DeclarationRef
provider: DeclarationRef
selection_surface: DeclarationRef
snapshot: CatalogSnapshot
rows: List<RunnerLabelRow>
}

fn catalog_is_on_surface(catalog: RunnerLabelCatalog, surface: DeclarationRef) -> Bool {
declaration_ref_eq(a: catalog.selection_surface, b: surface)
}

// The projection every provider whose published sizes are visibility-free uses, so that
// enrolling a provider's labels is one line in that provider's own module and no second list.
fn label_catalog_of_shapes(
catalog: DeclarationRef,
provider: DeclarationRef,
selection_surface: DeclarationRef,
snapshot: CatalogSnapshot,
availability: RunnerCatalogAvailability,
) -> RunnerLabelCatalog {
RunnerLabelCatalog {
catalog: catalog,
provider: provider,
selection_surface: selection_surface,
snapshot: snapshot,
rows: map(runner_shape_rows(availability: availability), r => label_row_of_shape(row: r)),
}
}
20 changes: 20 additions & 0 deletions dag/extdeps/ci_runner/warpbuild.dag
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import std.nat { Nat }
import std.measure { hardware_thread_count }
import std.decl_ref { DeclarationRef, decl_ref, WholeDeclaration }
import extdeps.toolchain.types { Aarch64, Architecture, X86_64 }
import extdeps.github.actions { github_actions_runs_on_surface }
import extdeps.ci_runner.types {
CatalogSnapshot,
label_catalog_of_shapes,
RunnerLabelCatalog,
EntitlementUnstated,
RunnerCatalogAvailability,
QuotedWithoutBasis,
Expand Down Expand Up @@ -76,3 +80,19 @@ data warpbuild_runner_catalog: RunnerCatalogAvailability = RunnerShapesCited {
warpbuild_shape(label: "warp-ubuntu-latest-x64-32x", architecture: X86_64, vcpus: 32, quoted_numeral: 128),
],
}

// The label roster and its snapshot. See extdeps.ci_runner.types CatalogSnapshot for why the
// fetch time and the declared scope both have to be carried: a consumer that meets a label this
// catalog lacks must be able to tell a finding about the observed repository from a gap in ours.
data warpbuild_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-08-18T00:00:00Z",
declared_scope: "Linux ubuntu-latest cloud-runner families only, both architectures, from the cloud-runners documentation cited above. Any other family that documentation publishes is absent from this catalog because this repository has not read it.",
}

data warpbuild_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.ci_runner.warpbuild", decl_name: "warpbuild_label_catalog"),
provider: warpbuild_provider_identity,
selection_surface: github_actions_runs_on_surface,
snapshot: warpbuild_catalog_snapshot,
availability: warpbuild_runner_catalog,
)
25 changes: 25 additions & 0 deletions dag/extdeps/cloud/ubicloud.dag
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import std.measure {
hardware_thread_count,
}
import std.decl_ref { DeclarationRef, decl_ref }
import extdeps.github.actions { github_actions_runs_on_surface }
import extdeps.ci_runner.types {
CatalogSnapshot,
label_catalog_of_shapes,
RunnerLabelCatalog,
CpuEntitlement,
DedicatedPhysicalCore,
EntitlementUnstated,
Expand Down Expand Up @@ -264,3 +268,24 @@ fn ubicloud_runner_shape(row: UbicloudRunnerCatalogRow) -> RunnerShapeRow {
data ubicloud_runner_catalog_shapes: RunnerCatalogAvailability = RunnerShapesCited {
rows: map(ubicloud_runner_catalog(), r => ubicloud_runner_shape(row: r)),
}

// The label roster and its snapshot. See extdeps.ci_runner.types CatalogSnapshot for why the
// fetch time and the declared scope both have to be carried: a consumer that meets a label this
// catalog lacks must be able to tell a finding about the observed repository from a gap in ours.
//
// THIS SCOPE NOTE EARNED ITSELF ON A REAL LABEL. PowerDNS/pdns runs jobs on
// ubicloud-standard-8-ubuntu-2404, and the ten rows above carry the bare ubicloud-standard-N and
// ubicloud-standard-N-arm spellings only. The OS-suffixed spelling is therefore a MISS, and it is
// a miss of this repository's coverage rather than a label Ubicloud does not publish.
data ubicloud_catalog_snapshot: CatalogSnapshot = CatalogSnapshot {
fetched_at: "2026-07-11T00:00:00Z",
declared_scope: "The bare ubicloud-standard-N and ubicloud-standard-N-arm runner-type spellings only, from the runner-types page cited above. The OS-suffixed spellings Ubicloud also accepts (ubicloud-standard-8-ubuntu-2404 and its siblings) are NOT modelled here: such a label is absent from this catalog because this repository has not read that surface, not because Ubicloud does not publish it.",
}

data ubicloud_label_catalog: RunnerLabelCatalog = label_catalog_of_shapes(
catalog: decl_ref(module_path: "extdeps.cloud.ubicloud", decl_name: "ubicloud_label_catalog"),
provider: ubicloud_provider_identity,
selection_surface: github_actions_runs_on_surface,
snapshot: ubicloud_catalog_snapshot,
availability: ubicloud_runner_catalog_shapes,
)
Loading
Loading