Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
314afbc
PRINT-0..4: the printed node chassis program, model-first and refusing
Sep 2, 2026
0637eee
PRINT-0..4 repairs: transposed board axes, sidecar contract check, wi…
Sep 2, 2026
a492561
Standoffs are a correspondence to the micro-ATX grid, not read coordi…
Sep 2, 2026
c20c4eb
Contract mints from one declaration: unbound pairing and orphaned sid…
Sep 2, 2026
a5a7ef3
Review 58452: prose that should have been typed, a quadratic scan tha…
Sep 2, 2026
8de9974
Review 58474 and the stale-head reviews: structural equality, a 300um…
Sep 2, 2026
dde7bea
microATX gets its own authority, the A1 mini gets a product row, and …
Sep 2, 2026
db7aeb6
Coupon V0 drops the operation that underdetermined its own output, an…
Sep 2, 2026
e4a3e49
Merge remote-tracking branch 'origin/main' into session/crisp-ibex-710
Sep 2, 2026
9c3c534
The pinned plan stops listing an operation the code deleted, and reco…
Sep 2, 2026
4ba4b44
The transport wall was admitting an operation V0 deleted, and its own…
Sep 2, 2026
15ac307
Semantic admission: the wall compares the whole specimen, and two fau…
Sep 2, 2026
ae4462c
Coupon identity becomes a closed coproduct and the generic mint is de…
Sep 2, 2026
a52dab2
Operation order was already refused; what was missing was the witness…
Sep 2, 2026
fea4fdd
The admitted value was forgeable and I had claimed it was not; a prob…
Sep 2, 2026
968dd91
The pinned plan records what the transport wall actually compares, an…
Sep 2, 2026
236e352
The V1 obligation was a bare String, which is the §4c violation this …
Sep 2, 2026
d7aaff1
The expect-compile-refusal harness already existed, and the refusal a…
Sep 2, 2026
cf277ff
Rename the overclaiming carriers, and go get the document instead of …
Sep 2, 2026
9a5c59e
The actuator pairing is unbound, declared as a typed obligation rathe…
Sep 2, 2026
22f1da8
The coupon cannot be identified from its own geometry, so the canonic…
Sep 2, 2026
07b2288
The datum controls did not cover the coupon being turned OVER, which …
Sep 2, 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
330 changes: 328 additions & 2 deletions dag/extdeps/boards/asrock_rack.dag

Large diffs are not rendered by default.

130 changes: 130 additions & 0 deletions dag/extdeps/printing/bambu_lab_a1_mini.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
module extdeps.printing.bambu_lab_a1_mini

import std.types { List, NonEmptyStr }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import std.measure {
Micrometer, micrometer,
Millimeter, millimeter,
Celsius, celsius,
Watt, watt,
Volt, volt,
Hertz, hertz,
}
import extdeps.printing.fdm {
BuildEnvelope, build_envelope,
NozzleDiameter, nozzle_diameter,
FilamentDiameter, filament_diameter,
MaterialSuitabilityRow, material_suitability_row,
SuitabilityIdeal, SuitabilityNotRecommended,
FilamentMaterial,
Pla, Petg, Tpu, Pva, Abs, Asa, Polycarbonate, Polyamide, Pet, FiberReinforcedPolymer,
}
import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef }
import extdeps.uri { Uri, Https }

// THE A1 MINI AS A CONCRETE PRODUCT, which is the thing extdeps.printing.fdm deliberately is not.
//
// fdm owns the agnostic shapes — an envelope, a nozzle diameter, a material and a suitability
// grading. It enumerates no machine and grades no material, because a generic hub that named
// products would be the external-decomposition violation DESIGN section 3 describes. This module is
// the other half: one independently versioned product, owning its own facts.
//
// WHY IT EXISTS AT ALL, stated because its absence was a real defect rather than a gap. The coupon
// fit witness previously authored `build_envelope(180, 180, 180)` inline. That witness therefore
// tested a number it had written itself: it would have stayed green if this machine's envelope were
// different, and green if no printer authority existed anywhere in the corpus. A witness whose
// subject is its own literal establishes nothing about the world. It now reads the row below, so
// changing this row is what moves that witness.

data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "bambulab.com/en/a1-mini/specs"
}
}

data extdeps_model_scope: ExternalModelScope = ExternalModelScope {
subject: ExternalSubjectRef {
declaration: DeclarationRef {
module_path: "extdeps.printing.bambu_lab_a1_mini",
decl_name: "a1_mini_build_envelope",
field: WholeDeclaration
}
},
first_citation: extdeps_external_authority_anchor,
further_citations: []
}

// PROVENANCE, AND IT IS RELAYED RATHER THAN FETCHED. The vendor's "Technical Specifications A1 mini"
// table, supplied verbatim by the operator 2026-09-01. Outbound requests to bambulab.com are
// refused by this environment's egress policy (403) and the Wayback availability API returns no
// snapshot for that host, so no first-party read is available here and none is claimed. Every value
// below appears in that table; nothing is inferred from the machine's class, and where the table is
// silent this module is silent too rather than supplying the usual answer for a printer like this.

data a1_mini_build_envelope: BuildEnvelope = build_envelope(
x: millimeter(count: 180),
y: millimeter(count: 180),
z: millimeter(count: 180)
)

// The INCLUDED nozzle, distinguished from the optional ones because they are different facts: one
// describes the machine as delivered, the others describe what may be fitted. A process qualified on
// one nozzle is not qualified on another, so collapsing these into a set would let a 0.4 mm
// qualification be spent on a 0.2 mm job.
data a1_mini_nozzle_included: NozzleDiameter = nozzle_diameter(value: micrometer(count: 400))

data a1_mini_nozzle_optional: List<NozzleDiameter> = [
nozzle_diameter(value: micrometer(count: 200)),
nozzle_diameter(value: micrometer(count: 600)),
nozzle_diameter(value: micrometer(count: 800)),
]

data a1_mini_filament_diameter: FilamentDiameter = filament_diameter(value: micrometer(count: 1750))

data a1_mini_max_hot_end_temperature: Celsius = celsius(count: 300)
data a1_mini_max_build_plate_temperature: Celsius = celsius(count: 80)

// Electrical, carried because the rack this program builds shares a supply with these machines and
// because a printer is a node with a power envelope like any other.
//
// THE RATING IS RMS, AND SAYING SO IS NOT PEDANTRY. "100-240 VAC" is a root-mean-square rating; the
// peak is about 1.41x it, so a 240 V rating implies roughly 340 V of insulation stress. Nothing in
// this program consumes that distinction today, so no separate RMS carrier is minted -- a type with
// no consumer is the experimental residue DESIGN section 6 names. It is recorded here so that the
// first consumer which cares about peak stress reads a stated assumption rather than inferring one
// from a bare number.
//
// Volt is the right carrier and its quantity is already ElectricPotentialDifference, so this is a
// potential DIFFERENCE and not an absolute potential. Review 58505 read it as "a flat Volt scalar"
// and asked for an affine split; the response is recorded on the pull request rather than here,
// because it is a fact about the substrate rather than about this machine.
data a1_mini_input_voltage_minimum: Volt = volt(count: 100)
data a1_mini_input_voltage_maximum: Volt = volt(count: 240)
data a1_mini_input_frequency_minimum: Hertz = hertz(count: 50)
data a1_mini_input_frequency_maximum: Hertz = hertz(count: 60)
data a1_mini_max_power: Watt = watt(count: 150)

// Physical footprint of the MACHINE, not of anything it prints. Named to keep that distinction
// visible: 347 x 315 x 365 is the desk space it occupies, and confusing it with the build envelope
// is a mistake that would silently admit parts nearly twice the printable size.
data a1_mini_machine_width: Millimeter = millimeter(count: 347)
data a1_mini_machine_depth: Millimeter = millimeter(count: 315)
data a1_mini_machine_height: Millimeter = millimeter(count: 365)

// THE SUITABILITY ROSTER IS COMPLETE OVER FilamentMaterial, and that is a property worth stating.
// The vendor table grades ten materials and fdm models exactly ten, so every arm has a row and no
// consumer can ask about a material this roster does not answer for. SuitabilityUnstated therefore
// does not appear here — it exists for machines whose vendor is silent, which this one is not.
data a1_mini_material_suitability: List<MaterialSuitabilityRow> = [
material_suitability_row(material: Pla, suitability: SuitabilityIdeal),
material_suitability_row(material: Petg, suitability: SuitabilityIdeal),
material_suitability_row(material: Tpu, suitability: SuitabilityIdeal),
material_suitability_row(material: Pva, suitability: SuitabilityIdeal),
material_suitability_row(material: Abs, suitability: SuitabilityNotRecommended),
material_suitability_row(material: Asa, suitability: SuitabilityNotRecommended),
material_suitability_row(material: Polycarbonate, suitability: SuitabilityNotRecommended),
material_suitability_row(material: Polyamide, suitability: SuitabilityNotRecommended),
material_suitability_row(material: Pet, suitability: SuitabilityNotRecommended),
material_suitability_row(material: FiberReinforcedPolymer, suitability: SuitabilityNotRecommended),
]
127 changes: 127 additions & 0 deletions dag/extdeps/printing/bambu_studio.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
module extdeps.printing.bambu_studio

import std.types { List, NonEmptyStr }
import std.decl_ref { DeclarationRef, WholeDeclaration }
import std.os.types { OperatingSystemProduct, UbuntuOs, WindowsOs, MacosOs, NobleNumbat2404Lts, Windows1124H2Build26100, Sequoia15 }
import extdeps.external_authority { ExternalAuthority, ExternalModelScope, ExternalSubjectRef }
import extdeps.uri { Uri, Https }

// Bambu Studio, the vendor's own slicer, as its OWN subject — not a field on the printer. DESIGN §3
// external decomposition: the slicer is independently versioned from the machine it slices for, and
// OrcaSlicer, its fork, is a third subject again. A printer module that enumerated its slicers would
// be the generic-hub violation that rule names.
data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "github.com/bambulab/BambuStudio"
}
}

data bambu_studio_product_page_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "bambulab.com/en/download/studio"
}
}

data bambu_studio_release_api_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "api.github.com/repos/bambulab/BambuStudio/releases/latest"
}
}

data bambu_studio_flathub_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "flathub.org/apps/com.bambulab.BambuStudio"
}
}

data extdeps_model_scope: ExternalModelScope = ExternalModelScope {
subject: ExternalSubjectRef {
declaration: DeclarationRef {
module_path: "extdeps.printing.bambu_studio",
decl_name: "bambu_studio_platform_support",
field: WholeDeclaration
}
},
first_citation: extdeps_external_authority_anchor,
further_citations: [bambu_studio_release_api_authority, bambu_studio_flathub_authority],
}

// TWO AUTHORITIES FROM ONE VENDOR DISAGREE, AND THE MODEL CARRIES BOTH RATHER THAN PICKING.
//
// The A1 mini specification table, relayed by the operator from the product page, states the slicer's
// supported operating systems as "MacOS, Windows". The vendor's own release feed, fetched
// first-party from this environment, publishes BambuStudio_ubuntu22.04-*.AppImage and
// BambuStudio_ubuntu24.04-*.AppImage as release assets, and Flathub serves the application. Both are
// the vendor speaking. They do not agree.
//
// WHY NOT JUST RECORD "LINUX IS SUPPORTED". Because that resolves a disagreement this repository
// has no authority to resolve, and it discards the fact that is actually load-bearing for an
// operator: the SPEC SHEET does not promise Linux, so a Linux regression is not a warranty claim,
// while the RELEASE FEED demonstrably ships Linux binaries, so the toolchain can be Linux-native
// today. A consumer planning a Linux workstation needs the second; a consumer deciding what the
// vendor is contractually committed to needs the first. Collapsing to one erases the other, and the
// collapse would be invisible — the surviving row looks equally authoritative either way.
//
// This is the shape DESIGN §3 calls a MEANING FORK if it were left implicit: one spelling
// ("supported OS") carrying two materially different obligations. Naming the two claims separately,
// each with its own authority, is what keeps it from being one.
type PlatformSupportClaimKind
= SpecificationSheetClaim
| PublishedReleaseArtifact

type PlatformSupportClaim sole_constructor {
kind: PlatformSupportClaimKind
platform: OperatingSystemProduct
authority: ExternalAuthority
note: NonEmptyStr
}

data bambu_studio_spec_sheet_platforms: List<PlatformSupportClaim> = [
PlatformSupportClaim {
kind: SpecificationSheetClaim,
platform: MacosOs { distro: Sequoia15 },
authority: bambu_studio_product_page_authority,
note: "A1 mini specification table, 'Slicer Supported OS: MacOS, Windows', relayed by the operator 2026-09-01. The table names the OS family without an edition; Sequoia15 is this corpus's macOS surface row and is NOT part of the vendor's claim.",
},
PlatformSupportClaim {
kind: SpecificationSheetClaim,
platform: WindowsOs { distro: Windows1124H2Build26100 },
authority: bambu_studio_product_page_authority,
note: "Same table, same relay. Edition is this corpus's Windows surface row and is not stated by the vendor table.",
},
]

// Fetched first-party: api.github.com answers 200 from this environment, so these asset names were
// READ, not relayed. The release carrying them is v02.08.02.61. Ubuntu 22.04 is also published; only
// the 24.04 asset is modelled here because NobleNumbat2404Lts is the surface row this corpus carries,
// and inventing a 22.04 row to be complete would mint an OS product for a claim nothing consumes.
data bambu_studio_release_artifact_platforms: List<PlatformSupportClaim> = [
PlatformSupportClaim {
kind: PublishedReleaseArtifact,
platform: UbuntuOs { distro: NobleNumbat2404Lts },
authority: bambu_studio_release_api_authority,
note: "Release asset BambuStudio_ubuntu24.04-v02.08.02.61-*.AppImage, read first-party from the release API 2026-09-01. Flathub additionally serves com.bambulab.BambuStudio.",
},
]

// THE JOIN IS A CONCATENATION, NOT AN ADJUDICATION, and reading it requires knowing that.
//
// The two rosters disagree about Linux: the specification table lists macOS and Windows only, while
// the release feed publishes Ubuntu AppImages. Every claim below therefore carries its own kind and
// its own authority, and nothing in this module says which wins — a Linux toolchain is demonstrably
// available and is not promised by the spec sheet, and those are both true at once.
//
// The disagreement is not restated as a datum here. An earlier revision carried it as a standalone
// NonEmptyStr, which is the unclassified prose DESIGN section 4c forbids: every fact in that
// sentence is already in a typed row above (the kinds, the platforms, the authorities, the asset
// names), so the row duplicated modelled data in a form no program can read. What is left is the
// rationale for the shape, which is what an annotation is for.
data bambu_studio_platform_support: List<PlatformSupportClaim> = concat(
bambu_studio_spec_sheet_platforms,
bambu_studio_release_artifact_platforms
)

Loading
Loading