mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-09 10:16:50 +00:00
Make a filament's id depend only on the filament itself
A filament_id is now exactly what the preset's own filament_vendor, filament_type and filament name mint, wherever it inherits from. Inheriting settings no longer limits what a preset may claim, so the checks that policed inheritance are gone, and so are the four grandfather lists that held thousands of presets as permanent exceptions. The snapshot records sanctioned state rather than excuses: one entry per id, carrying the product it names beside the presets claiming it. Profiles that disagreed are corrected instead of excused. The Elegoo TPU and PAHT roots were named for a different product than all of their variants and become TPU 95A and PAHT-CF; Elegoo PET-CF gains the filament_type its variants already set; the Snapmaker breakaway support presets get an id of their own rather than riding the PVA chain; and a BBL preset name carrying a doubled space is fixed behind renamed_from. Their ids re-mint from the corrected identities. The tooling and the design note also drop the word "family", which invited reading a brand's Lite and Pro spools as one id. No change to slicing output — only filament_id values, three preset names, the inherits lines following those renames and the vendor indexes move.
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
# Filament IDs (`filament_id`)
|
||||
|
||||
`filament_id` identifies a **material family**: one commercial product line = one id, shared by
|
||||
all of that material's per-printer / per-nozzle variants, in every profile bundle that ships it.
|
||||
`filament_id` identifies one **filament product**: one named spool product = one id, shared by
|
||||
all of that product's per-printer / per-nozzle variants, in every profile bundle that ships it.
|
||||
Devices use it to match a physical spool or tray to a filament preset. It is never per-color,
|
||||
per-printer, per-nozzle, or per-preset (per-preset identity is `setting_id`), and it is never
|
||||
per-bundle either — PolyLite PLA carries the same id whether the preset lives in the
|
||||
OrcaFilamentLibrary (OFL), Qidi, or Snapmaker bundle.
|
||||
OrcaFilamentLibrary (OFL), Qidi, or Snapmaker bundle. The granularity is the name on the spool,
|
||||
not the brand behind it: `AAA PLA Lite` and `AAA PLA Pro` are two filaments with two ids, not
|
||||
variants of one.
|
||||
|
||||
**How it is generated:** an id is computed, never invented. `scripts/assign_filament_ids.py`
|
||||
mints it as a deterministic hash of the product's identity — the triple
|
||||
`(filament_vendor, filament_type, family name)`, where the family name is the preset name
|
||||
`(filament_vendor, filament_type, filament name)`, where the filament name is the preset name
|
||||
with its `@...` variant suffix stripped — producing an 8-character `OF*` code that is the
|
||||
same for that product in every bundle, in every PR, on every machine. For example, Polymaker's
|
||||
PolyLite PLA presets (`PolyLite PLA @base`, `PolyLite PLA@Q2-Series`, …) resolve
|
||||
`filament_vendor` `Polymaker`, `filament_type` `PLA`, and family name `PolyLite PLA`; hashing
|
||||
`filament_vendor` `Polymaker`, `filament_type` `PLA`, and filament name `PolyLite PLA`; hashing
|
||||
`filament_product/Polymaker/PLA/PolyLite PLA` yields `OF5CgdDq`, and that is the id the
|
||||
OrcaFilamentLibrary, OrcaArena, Qidi, and Snapmaker bundles all arrive at independently
|
||||
(derivation details in the Minting section).
|
||||
@@ -31,8 +33,8 @@ This page is the rule for authoring `filament_id` in system profiles
|
||||
(`resources/profiles/**`). CI enforces everything below; the short version is:
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **Never write a `filament_id` value by hand.** New families get their id from
|
||||
> `python scripts/assign_filament_ids.py`; existing families already have one — inherit it.
|
||||
> **Never write a `filament_id` value by hand.** A new filament gets its id from
|
||||
> `python scripts/assign_filament_ids.py`; one already in the tree has one — inherit it.
|
||||
|
||||
## The design, in two pieces
|
||||
|
||||
@@ -47,7 +49,7 @@ the system is built to make them impossible:
|
||||
number, and no way to get it wrong by hand, because you never write it by hand.
|
||||
2. **A sanctioned snapshot.** The complete id landscape derived from the tree must equal
|
||||
`scripts/filament_id_snapshot.json` exactly, so every change to ids, claims (which bundles
|
||||
ship which id, and for which family), or product identity surfaces as a reviewable diff to
|
||||
ship which id, and for which filament), or product identity surfaces as a reviewable diff to
|
||||
one file — the maintainer gate.
|
||||
|
||||
## Who consumes the id
|
||||
@@ -55,7 +57,7 @@ the system is built to make them impossible:
|
||||
The canonical consumer is tray-to-preset matching: a device reports a tray material id
|
||||
(`tray_info_idx`), and the shared matching pipeline (`PresetBundle::sync_ams_list` and
|
||||
friends) resolves it to a preset. The matcher is printer-scoped and first-match-wins:
|
||||
scanning only compatible family roots — system roots plus user-made custom filaments, which
|
||||
scanning only compatible root presets — system roots plus user-made custom filaments, which
|
||||
are user roots carrying their own `P*` ids; a preset derived from another resolves through
|
||||
its root and never matches directly — it picks the first one whose `filament_id` equals the
|
||||
tray's. On a miss it falls back by filament type: a system `Generic <type>` preset
|
||||
@@ -73,7 +75,7 @@ device-reported tray material id flowing through the shared matcher.
|
||||
| Ecosystem | Where the tray id comes from today |
|
||||
| --- | --- |
|
||||
| Bambu AMS | the device itself (RFID / user tray setting), in Bambu's own `GF*` catalog; `BBLPrinterAgent` rewrites it into our id before the matcher sees it (see [The Bambu catalog map](#the-bambu-catalog-map)) |
|
||||
| Qidi box | composed at runtime as `QD_<series>_<vendor>_<typeidx>` — vendor and type indices from the device's per-slot saved variables, the series digit inferred client-side from the printer model/name. No preset carries a `QD_*` value, so the slot currently resolves by filament type; mapping the composed id onto the family's minted id belongs in the agent |
|
||||
| Qidi box | composed at runtime as `QD_<series>_<vendor>_<typeidx>` — vendor and type indices from the device's per-slot saved variables, the series digit inferred client-side from the printer model/name. No preset carries a `QD_*` value, so the slot currently resolves by filament type; mapping the composed id onto the filament's minted id belongs in the agent |
|
||||
| Creality CFS | runtime brand/type scoring returns the winning preset's id |
|
||||
| Klipper (AFC / Happy Hare) | runtime lookup by filament type |
|
||||
| Snapmaker | runtime color/vendor/type match |
|
||||
@@ -115,45 +117,47 @@ Two more consumer-side facts worth knowing:
|
||||
> **Would a user consider this a different spool product than anything already in the tree?**
|
||||
|
||||
Different polymer, different sub-brand (Basic / Matte / Silk / HF), fiber-filled sibling, or a
|
||||
second selectable diameter → **new family, new id**. The same spool tuned for another printer
|
||||
or nozzle → **join the existing family** (inherit its `@base`, write no id key). Tuning a
|
||||
generic material → **join the OrcaFilamentLibrary family** (inherit `Generic X @System`, keep
|
||||
the `Generic X` base name, write no id key).
|
||||
second selectable diameter → **new filament, new id**. The same spool tuned for another printer
|
||||
or nozzle → **join the existing filament** (keep its base name and inherit it; no id
|
||||
key needed). Tuning a generic material → **join the OrcaFilamentLibrary filament** (inherit
|
||||
`Generic X @System` and keep the `Generic X` base name; no id key needed).
|
||||
|
||||
| Situation | id |
|
||||
| --- | --- |
|
||||
| Per-printer / per-nozzle variant of an existing material | same id (inherit, never write the key) |
|
||||
| Per-printer / per-nozzle variant of an existing material | same id (inherit it) |
|
||||
| Sub-brand or product line (PLA vs PLA Matte vs PLA Silk vs PLA HF) | new id each |
|
||||
| Color | never a new id |
|
||||
| Second diameter of the same product (1.75 + 2.85) | sibling family, new id |
|
||||
| Second diameter of the same product (1.75 + 2.85) | sibling filament, new id |
|
||||
| "High-speed" tuned for a *different printer model* | same id (it is a printer variant) |
|
||||
| "High-speed" selectable *alongside* the normal preset on one printer | new id (it is a product line) |
|
||||
|
||||
## Structure rules
|
||||
|
||||
1. **Only family roots carry the key.** Root presets (any preset *not* marked
|
||||
`"instantiation": "true"`, typically `<Family> @base` with `"instantiation": "false"`)
|
||||
declare `filament_id`; instantiated variants inherit a root and never write the key.
|
||||
A family may have several roots — Qidi's PolyLite PLA has four per-series roots
|
||||
(`PolyLite PLA@Q2-Series`, `@Q2C-Series`, `@X-Max 4-Series`, `@X-Plus 5-Series`) — and all
|
||||
of them must declare the *identical* id. This is the authoring rule for new work; a large
|
||||
grandfathered tail of older presets breaks it in two ways — keys written on instantiated
|
||||
presets (frozen in the snapshot's `instantiated_with_id` list) and keys that override the
|
||||
id the preset would inherit from its family (frozen in `id_overrides`) — and CI ratchets
|
||||
so no new preset joins either tail.
|
||||
2. **The family name is the base name**: the preset name with everything from the first
|
||||
1. **Every preset carries the id of its own product, wherever it gets it from.** The id is a
|
||||
function of the preset's own triple (rule 5), and `inherits` carries settings, never
|
||||
identity. So a preset may declare the key itself or inherit it from any ancestor — a
|
||||
`<Filament> @base` root, a real (instantiated) preset of the same filament, an
|
||||
OrcaFilamentLibrary preset — and CI checks one thing: the id it ends up with equals the
|
||||
mint of *its* triple. The usual shape is one `@base` root (`"instantiation": "false"`)
|
||||
declaring the key and the per-printer variants inheriting it; a filament may have several
|
||||
roots — Qidi's PolyLite PLA has four per-series roots (`PolyLite PLA@Q2-Series`,
|
||||
`@Q2C-Series`, `@X-Max 4-Series`, `@X-Plus 5-Series`) — which then all declare the identical
|
||||
id. A branded filament that borrows a generic's settings (`Flashforge ABS Basic @FF C5`
|
||||
inherits `Generic ABS @System`) declares its own id, because its triple is its own.
|
||||
2. **The filament name is the base name**: the preset name with everything from the first
|
||||
(optionally space-preceded) `@` stripped. `MyBrand PLA @Orca 3D Fuse1` and `MyBrand PLA@HS`
|
||||
both belong to family `MyBrand PLA`.
|
||||
3. **Within a family, variants' `compatible_printers` are pairwise disjoint** — per printer,
|
||||
are both the filament `MyBrand PLA`.
|
||||
3. **Within one filament, variants' `compatible_printers` are pairwise disjoint** — per printer,
|
||||
at most one compatible instantiated preset per id, or AMS matching turns ambiguous. The
|
||||
C++ validator's `-f` check enforces this.
|
||||
4. **Generics belong to OrcaFilamentLibrary.** A vendor tuning a generic material inherits
|
||||
`Generic X @System`, keeps the `Generic X` base name (that alias is what hides the library
|
||||
preset on your printers), sets a non-empty `compatible_printers`, and writes no id key —
|
||||
e.g. `Generic PLA @Sovol SV08 MAX` inherits `Generic PLA @System` and lists three Sovol
|
||||
nozzles. A vendor-*branded* filament never rides a generic family id.
|
||||
preset on your printers, and it is what makes its triple — and so its id — the library's)
|
||||
and sets a non-empty `compatible_printers` — e.g. `Generic PLA @Sovol SV08 MAX` inherits
|
||||
`Generic PLA @System` and lists three Sovol nozzles. Renaming such a preset makes it a
|
||||
different product by rule 5, so it then needs its own id.
|
||||
5. **Ids follow the product identity.** The id is a pure function of the product triple
|
||||
`(filament_vendor, filament_type, family name)`, so correcting any of them re-mints the id
|
||||
`(filament_vendor, filament_type, filament name)`, so correcting any of them re-mints the id
|
||||
**by design** (via `--remint <Vendor>`; the exact sequence is in the FAQ). Nothing forwards
|
||||
the old value, so anything outside the tree that stored it — a device tray, a calibration
|
||||
record, a saved project — falls back to matching by filament type until the user re-selects
|
||||
@@ -169,48 +173,48 @@ New ids are deterministic, computed exactly like the `setting_id` precedent
|
||||
FILAMENT_ID_NAMESPACE = uuid5(setting-id NAMESPACE, "filament_id")
|
||||
= c4d3ff49-4c32-5534-a3e3-00894157ab97
|
||||
filament_id = "OF" + base62_6( uuid5(FILAMENT_ID_NAMESPACE,
|
||||
"filament_product/<filament_vendor>/<filament_type>/<family_name>") )
|
||||
"filament_product/<filament_vendor>/<filament_type>/<filament_name>") )
|
||||
```
|
||||
|
||||
`base62_6` is the low 6 base62 digits (alphabet `0-9A-Za-z`) of the UUID taken as a big-endian
|
||||
integer, most-significant digit first; with the `OF` prefix the full id is 8 chars, within the
|
||||
AMS length limit. The triple comes from the family root's *flattened* config:
|
||||
AMS length limit. The triple comes from the root preset's *flattened* config:
|
||||
`<filament_vendor>` is the filament
|
||||
**manufacturer** (`"Polymaker"`, or `"Generic"` for generics — never the printer brand),
|
||||
`<filament_type>` the material type, `<family_name>` the root's base name; the two config
|
||||
`<filament_type>` the material type, `<filament_name>` the root's base name; the two config
|
||||
values are inheritable list options and the first element counts.
|
||||
|
||||
Content-addressing on that triple is what makes the whole system converge. The key contains no
|
||||
bundle name, so the same product mints the same id in every bundle — hoisting a family into
|
||||
bundle name, so the same product mints the same id in every bundle — moving a filament into
|
||||
OrcaFilamentLibrary never changes its id, and two vendors independently shipping the same
|
||||
product arrive at the same id without coordinating. `Polymaker/PLA/PolyLite PLA` mints
|
||||
`OF5CgdDq`, and that one id is declared by the OrcaFilamentLibrary, OrcaArena, Qidi, and
|
||||
Snapmaker bundles alike; the OFL generic `Generic/PLA/Generic PLA` mints `OFDSrzZ8`, claimed
|
||||
by ten bundles — most by independent declarations converging on the same mint, the rest
|
||||
purely through inheritance from the OFL family.
|
||||
by 35 bundles — most by independent declarations converging on the same mint, the rest
|
||||
purely through inheritance from the OFL preset.
|
||||
|
||||
On the rare collision with an existing id, the minter salts the input (`…/1`,
|
||||
`…/2`, …) until free, and the result is frozen in the profile file. Salting is also used
|
||||
deliberately: a *salt split* keeps two presets of one product on distinct ids where a single
|
||||
id would be AMS-ambiguous on the same printer — the "selectable alongside" situation from the
|
||||
table above, resolved without inventing a second family name. The tooling recognizes salt
|
||||
table above, resolved without inventing a second filament name. The tooling recognizes salt
|
||||
iterations of a triple as conformant and preserves such splits across re-mints.
|
||||
|
||||
Workflow for a new family:
|
||||
Workflow for a new filament:
|
||||
|
||||
```bash
|
||||
# 1. Author the family with NO filament_id key anywhere.
|
||||
python scripts/assign_filament_ids.py # 2. mint + insert ids into the family root(s)
|
||||
# 1. Author the filament with NO filament_id key anywhere.
|
||||
python scripts/assign_filament_ids.py # 2. mint + insert ids into the root preset(s)
|
||||
python scripts/assign_filament_ids.py --update-snapshot # 3. record the new claims in the snapshot
|
||||
python scripts/assign_filament_ids.py --check # 4. verify — the same checks CI runs
|
||||
# 5. Commit the profile edits together with scripts/filament_id_snapshot.json.
|
||||
```
|
||||
|
||||
The default run mints ids for id-less families and replaces any declaration that is not in
|
||||
The default run mints ids for id-less filaments and replaces any declaration that is not in
|
||||
`OF` format; it never rewrites a valid `OF` id, so it is idempotent and a no-op once every
|
||||
family has one. It edits profile files byte-preservingly (indentation, BOM, and line endings
|
||||
filament has one. It edits profile files byte-preservingly (indentation, BOM, and line endings
|
||||
intact) and re-parses them to fail loudly.
|
||||
`--mint "filament_vendor/filament_type/family_name"` prints the id a **new** mint of that
|
||||
`--mint "filament_vendor/filament_type/filament_name"` prints the id a **new** mint of that
|
||||
triple would get, without touching anything — note that for a triple whose id already exists
|
||||
it prints the next *free* salt iteration, not the live id (asking for
|
||||
`Polymaker/PLA/PolyLite PLA` today prints the salt-1 id, because `OF5CgdDq` is taken).
|
||||
@@ -228,7 +232,7 @@ normally only used by id migrations):
|
||||
- `--profiles DIR` points the tooling at a different profile tree (default
|
||||
`resources/profiles`).
|
||||
|
||||
If you skip the tooling, CI fails and prints the remedy: the expected id for your family and
|
||||
If you skip the tooling, CI fails and prints the remedy: the expected id for your filament and
|
||||
the instruction to run `python scripts/assign_filament_ids.py`; once the id is minted, the
|
||||
snapshot checks likewise point at `--update-snapshot` and tell you to commit the resulting
|
||||
diff.
|
||||
@@ -244,23 +248,21 @@ bundle — not even the one whose printers use the catalog — that may write on
|
||||
| `GF*` | Bambu AMS/RFID catalog | declarable by **nobody**, BBL included: Bambu's own ids live in the generated catalog map, never in a profile |
|
||||
| `QD_*` | Qidi device protocol | declarable by **nobody**, Qidi included: the box composes these ids at runtime and they are not preset ids |
|
||||
| `P` + 7 hex chars (case-insensitive), `"null"` | user-created custom filaments (`CreatePresetsDialog.cpp`) | never appears in system profiles |
|
||||
| every already-shipped id | frozen in the snapshot (grandfathered) | frozen as-is; new claims need maintainer sign-off |
|
||||
|
||||
The two device namespaces, in detail:
|
||||
|
||||
- **Bambu (`GF*`).** Bambu's device/RFID/cloud catalog is external and opaque, which is a
|
||||
reason to keep it out of the profiles rather than to let one bundle own it. Every BBL family
|
||||
reason to keep it out of the profiles rather than to let one bundle own it. Every BBL filament
|
||||
mints an `OF` id from its triple like every other vendor's, and the correspondence to Bambu's
|
||||
catalog ids lives in one generated file the app applies at the printer boundary — the next
|
||||
section. Nothing under `resources/profiles/**` carries a `GF*` id today and the snapshot
|
||||
grandfathers none, so a `GF*` id appearing anywhere in the tree is a mistake, whoever wrote
|
||||
it.
|
||||
section. Nothing under `resources/profiles/**` carries a `GF*` id today and nothing can be
|
||||
exempted, so a `GF*` id appearing anywhere in the tree is a mistake, whoever wrote it.
|
||||
- **Qidi (`QD_*`).** `QD_*` is a device-*protocol* namespace, not a preset id space: the
|
||||
Qidi box path composes `QD_<series>_<vendor>_<typeidx>` ids at runtime (slot vendor and
|
||||
type indices reported by the device, the series digit inferred client-side from the printer
|
||||
model/name). Qidi presets carry ordinary minted `OF*` ids (generics share the OFL ids), so
|
||||
a composed id matches no preset and the slot falls back to filament type; translating it to
|
||||
the family's id belongs in `QidiPrinterAgent`. The alternative — treating per-series
|
||||
the filament's id belongs in `QidiPrinterAgent`. The alternative — treating per-series
|
||||
protocol ids as preset ids — would put one product under five ids (`QIDI PLA Rapido` would
|
||||
be `QD_0_1_1` through `QD_4_1_1`), exactly the fragmentation the mint rule removes.
|
||||
|
||||
@@ -294,7 +296,7 @@ it from **BambuStudio's own shipped BBL bundle** — a sparse shallow clone of u
|
||||
or `--bambustudio-dir <a BambuStudio resources/profiles checkout>`. Our BBL bundle is a fork of
|
||||
Bambu's, tuned and extended independently, so it is not the source of truth for Bambu's ids.
|
||||
A row's key is whatever id our tree already mints for that same
|
||||
`(filament_vendor, filament_type, family)` triple; a product we do not ship gets a freshly
|
||||
`(filament_vendor, filament_type, filament name)` triple; a product we do not ship gets a freshly
|
||||
generated key and the row sits inert until some bundle claims that triple — `OFdyfQvU` /
|
||||
`GFG03`, "Bambu PETG Matte", is such a row today.
|
||||
|
||||
@@ -303,18 +305,18 @@ prints. Two lines, both informational, neither blocking the write:
|
||||
|
||||
```text
|
||||
upstream ships 'Bambu PETG Matte' (Bambu Lab/PETG), we ship nothing with that identity
|
||||
Orca BBL families with no row: 135 Orca-only product(s)
|
||||
Orca BBL filaments with no row: 135 Orca-only product(s)
|
||||
```
|
||||
|
||||
The first names each upstream product our BBL bundle has no same-identity family for —
|
||||
The first names each upstream product our BBL bundle has no same-identity filament for —
|
||||
sometimes a genuinely missing product, sometimes a name drift a follow-up rename would
|
||||
converge. The second counts our own BBL families that matched no row: 135 of 234 today, of
|
||||
converge. The second counts our own BBL filaments that matched no row: 135 of 234 today, of
|
||||
which 109 send an `OF` id on the wire and 26 already rode `OF` ids inherited from the
|
||||
OrcaFilamentLibrary. **135 is the number to expect at every regeneration** — 109 was the
|
||||
one-off size of the transition and stopped being computable from the tree once the BBL bundle
|
||||
was re-minted, so do not "fix" the report to print it.
|
||||
|
||||
**Check 8** lives in `check_filament_ids`, so profile CI runs it alongside the other seven. It
|
||||
**Check 6** lives in `check_filament_ids`, so profile CI runs it alongside the other five. It
|
||||
holds the file to its contract: it parses, carries `source` / `bambustudio_commit` /
|
||||
`generated`, keys only `OF`-format ids, maps each Bambu id at most once, and — for every row
|
||||
whose key the tree actually claims — agrees with the tree on that id's `(vendor, type, name)`
|
||||
@@ -408,49 +410,41 @@ Profile CI (`check_profiles.yml`) runs `check_filament_ids()` tree-wide via
|
||||
tree must equal the snapshot exactly, in both directions. Any change to the id landscape
|
||||
therefore surfaces as a diff to that file, and **that snapshot diff is what maintainers review
|
||||
and gate in a PR**. Never edit the snapshot by hand — `--update-snapshot` regenerates it
|
||||
deterministically (running it twice changes nothing). Besides the live `ids` and `triples`
|
||||
maps, the snapshot carries grandfather lists (`instantiated_with_id`, `id_overrides`,
|
||||
`alias_exceptions`, `triple_exceptions`) that freeze pre-existing structure debt while the
|
||||
checks ratchet all new profiles to the clean rules.
|
||||
deterministically (running it twice changes nothing). The snapshot holds one map, `ids`: each
|
||||
entry is the product the id is minted from (`filament_vendor`, `filament_type`, `name`) and the
|
||||
`filaments` claiming it (`Vendor/Filament`), and it sanctions *state*, never exceptions: no check
|
||||
consults it to excuse a preset from a rule, and there is no grandfather list of any kind.
|
||||
|
||||
The checks, in brief:
|
||||
|
||||
- **Format** — every id occurring in the tree is `OF` + 6 base62 chars. No exceptions: not a
|
||||
grandfathered snapshot entry, not BBL.
|
||||
- **Snapshot equality** — tree claims == snapshot claims **and** tree triples == snapshot
|
||||
triples, both directions: any `filament_vendor`/`filament_type`/family-name change surfaces
|
||||
as a snapshot diff.
|
||||
- **Mint conformance** — a non-grandfathered `OF*` id must equal the mint (or a low salt
|
||||
iteration) of its declarer's product triple; the error prints the expected id to paste into
|
||||
the family root.
|
||||
- **Alias hygiene** — a vendor preset riding an OFL family id must keep the library preset's
|
||||
base name (a rename re-exposes the library preset, since alias shadowing is name-based),
|
||||
a non-empty `compatible_printers` (an empty one shadows nothing), and no own id key
|
||||
(structure rule 4).
|
||||
- **Triple integrity** — every declarer must resolve a non-empty `filament_vendor` and
|
||||
`filament_type` (generics use `"Generic"`), and all declarers of one family within a
|
||||
bundle must agree on the triple.
|
||||
snapshot entry, not BBL.
|
||||
- **Snapshot equality** — tree claims == snapshot claims **and** each id's declared triple ==
|
||||
its snapshot entry, both directions: any `filament_vendor`/`filament_type`/name change
|
||||
surfaces as a snapshot diff.
|
||||
- **Identity** — the id is a function of the triple alone. A declared `OF*` id must equal the
|
||||
mint (or a low salt iteration) of its declarer's own triple; the id an instantiated preset
|
||||
*inherits* must equal the mint of *its* own triple, however it inherits it (a root, a real
|
||||
filament, a library preset — structure rule 1); and every instantiated system filament must
|
||||
resolve an effective id at all (recall: an id-less one is a hard load error in C++ that
|
||||
discards the whole vendor bundle). The errors print the expected id.
|
||||
- **Reserved namespaces** — `GF*`, `QD_*`, `P<7-hex>` or `"null"` claimed by any vendor,
|
||||
BBL and Qidi included, unless that exact claim is grandfathered in the snapshot (none is
|
||||
today).
|
||||
- **Structure** — no `filament_id` key on newly instantiated presets; no new
|
||||
declared-vs-inherited id drift; every instantiated system filament must resolve an
|
||||
effective id through its `inherits` chain (recall: an id-less one is a hard load error in
|
||||
C++ that discards the whole vendor bundle).
|
||||
BBL and Qidi included.
|
||||
- **Triple integrity** — every declarer must resolve a non-empty `filament_vendor` and
|
||||
`filament_type` (generics use `"Generic"`), and all declarers of one filament within a
|
||||
bundle must agree on the triple.
|
||||
- **Bambu catalog map** — `resources/printers/bambu_filament_ids.json` parses, carries its
|
||||
`source` / `bambustudio_commit` / `generated` header, keys only `OF`-format ids, maps each
|
||||
Bambu id at most once, and agrees with the tree on the triple of every row whose key the
|
||||
tree claims. See [The Bambu catalog map](#the-bambu-catalog-map); the remedy is always to
|
||||
regenerate, never to hand-edit.
|
||||
|
||||
Any new claim on a **reserved namespace** — a profile that declares a `GF*`, `QD_*` or
|
||||
`P<7-hex>` id, whatever its vendor — is refused by `--update-snapshot` unless you pass
|
||||
`--allow-shared-catalog`, and even then it lands in the snapshot diff for maintainer review.
|
||||
There is no such claim in the tree today and adding one should be a last resort: for a
|
||||
Bambu-cataloged product, the catalog map is where the correspondence belongs. Any other new
|
||||
sharing via a *declared* id is caught by the mint-conformance check; sharing through
|
||||
inheritance carries no declaration to check and surfaces only as a new claim in the snapshot
|
||||
diff — which is exactly why that diff is the gate.
|
||||
A profile that declares a **reserved-namespace** id — `GF*`, `QD_*` or `P<7-hex>`, whatever
|
||||
its vendor — cannot pass the format check, so `--update-snapshot` refuses to sanction it
|
||||
rather than hide the mistake until CI. For a Bambu-cataloged product, the catalog map is where
|
||||
the correspondence belongs. Any other new sharing via a *declared* id is caught by the identity
|
||||
check; sharing through inheritance carries no declaration to check and surfaces only as a new
|
||||
claim in the snapshot diff — which is exactly why that diff is the gate.
|
||||
|
||||
`orca_extra_profile_check.py` separately holds every declared id to the AMS 8-character limit,
|
||||
tree-wide and for every vendor alike, scoped to the presets a vendor's index actually
|
||||
@@ -463,24 +457,27 @@ ambiguity check behind structure rule 3.
|
||||
|
||||
## FAQ
|
||||
|
||||
- **A new color of an existing product?** Never a new id — colors are not families.
|
||||
- **A second diameter (1.75 mm and 2.85 mm) of the same product?** A sibling family with its
|
||||
- **A new color of an existing product?** Never a new id — colors are not filaments.
|
||||
- **A second diameter (1.75 mm and 2.85 mm) of the same product?** A sibling filament with its
|
||||
own id: two diameters are separately selectable spool products.
|
||||
- **A high-speed tune of an existing material for another printer model?** Same family:
|
||||
inherit the family's root, write no id key.
|
||||
- **A high-speed tune of an existing material for another printer model?** Same filament:
|
||||
keep the base name and inherit its root; no id key needed.
|
||||
- **A tuned generic ("our profile for Generic PLA")?** Inherit `Generic PLA @System`, keep the
|
||||
`Generic PLA` base name, set `compatible_printers`, write no id key.
|
||||
- **I need to fix a family's `filament_vendor` or `filament_type`.** Fix the config, run
|
||||
`Generic PLA` base name, set `compatible_printers`; no id key needed.
|
||||
- **A branded filament that borrows a generic's settings?** Fine — inherit `Generic X @System`
|
||||
(or any real filament) for the settings and declare the id of your own filament; run
|
||||
`python scripts/assign_filament_ids.py` to mint it. Inheritance never changes the id.
|
||||
- **I need to fix a filament's `filament_vendor` or `filament_type`.** Fix the config, run
|
||||
`--remint <Vendor>` then `--update-snapshot`, and commit the profile and snapshot diffs
|
||||
together. The id re-derives from the corrected identity, and nothing forwards the old
|
||||
value, so a tray or record still holding it falls back to matching by filament type.
|
||||
- **I need to rename a family.** Rename the presets (adding `renamed_from`, which keeps the
|
||||
- **I need to rename a filament.** Rename the presets (adding `renamed_from`, which keeps the
|
||||
preset *name* resolving), then `--remint <Vendor>`, then `--update-snapshot`. The id follows
|
||||
the new family name; as with any identity fix, the old id is not forwarded.
|
||||
the new filament name; as with any identity fix, the old id is not forwarded.
|
||||
- **Can I reuse a `QD_*` id for a Qidi profile?** No — nobody can. It is the device protocol's
|
||||
own id space: the box composes those values at runtime and no preset carries one. Author
|
||||
Qidi filaments like any other vendor's.
|
||||
- **CI says my family needs an id.** Run `python scripts/assign_filament_ids.py`, then
|
||||
- **CI says my filament needs an id.** Run `python scripts/assign_filament_ids.py`, then
|
||||
`--update-snapshot`, and commit both diffs. Do not type an id by hand.
|
||||
|
||||
For general profile authoring, see the profile development guide on the
|
||||
|
||||
Reference in New Issue
Block a user