mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-01 06:16:58 +00:00
Phase v3.1 of filament_id_plan_v3.md: every OFL-declared filament_id
re-derives from its product triple; the succession ledger absorbs the old
ids. Config-equivalence verified: flattened effective configs differ ONLY
in filament_id (284 consistent old->new changes tree-wide, including every
vendor preset that rides an OFL family), zero config/compatible_printers/
setting_id drift.
Structural pre-step (id-value-neutral, verified): OFL generic family ids
move from the shared fdm_filament_* template bases onto the product-named
"Generic X @System" presets, so the v3 triple's family component is the
product name, not an internal file name (12 relocations; 2 dead duplicate
declarations on fdm_filament_pa/pet pruned; every consumer chain itemized
first - the +12 instantiated_with_id entries are this deliberate pattern,
matching the 11 generics that already declared on @System).
fdm_filament_pc keeps its declaration this phase: 7 Prusa presets (Prusa
Generic PC, Prusament PC Blend) inherit it directly and re-home in the
v3.2 Prusa worksheet; its transitional id is documented in the plan.
Re-mint: 301 declarations re-derived (e.g. Generic PLA OGFL99 ->
OFDSrzZ8 = mint("filament_product/Generic/PLA/Generic PLA")). Snapshot:
1477 ids (+300/-292). Ledger:
- 230 shipped ids retired with mode-rule successors (OGF* library ids,
OFLSBS99, DREMC/FILAR/AliZ/eSUN/... legacy strings). DREMC010 had been
shared by a PPA-CF and a TPU family - a data bug this split resolves;
its successor follows its only shipped claim (DREMC PPA-CF).
- 25 GF-shaped ids OFL had copied from the Bambu catalog (GFOT00x
Overture, GFSEP0xx) are RELEASED to the BBL island space with hints at
the re-minted families - never retired, so a future legitimate BBL
catalog addition is never blocked; plus an explicit GFOT001 ->
OFxA1p01 hint (Overture PLA Pro, still live in BBL).
- 37 never-shipped v1 branch mints dropped from lineage
(--forget-never-shipped; they exist in no release, no forwarding
needed).
- OGFC99/OGFG99/OGFL96/OGFN99/OGFSNL08 stay live (still declared by
vendor bundles); they retire in v3.2 when those declarers re-mint.
Gates: 106 unit tests OK; --check exit 0; orca_extra_profile_check exit 0;
validator -l 2 / -f tree-wide / -r BBL+Qidi exit 0; Moonraker OFL map
check resolves all 29 aliases against the re-minted presets; flatten
equivalence pre/post as above; snapshot regen idempotent.
214 lines
14 KiB
Markdown
214 lines
14 KiB
Markdown
# filament_id plan v3: OFL as the catalog, content-addressed product ids
|
||
|
||
Supersedes §5 of `filament_id_plan_v2.md` (whose P+md5 verdict stands unchanged) and
|
||
revises the mint rule of `filament_id_plan.md` (v1, implemented on `feature/filament_id`).
|
||
Decision driver: v1's mint key scoped families to the *profile bundle* (printer brand), so
|
||
one commercial product tuned in N bundles carries N ids — e.g. PolyLite PLA ships in five
|
||
bundles (`BBL`, `OrcaFilamentLibrary`, `OrcaArena`, `Qidi`, `Snapmaker`), all with
|
||
`filament_vendor: "Polymaker"`, under up to five different ids (`GFL00`, `OFceJcLf`, …).
|
||
That contradicts what `filament_id` means: one id per commercial product line.
|
||
|
||
## 0. The architecture
|
||
|
||
Three tiers, two frozen islands:
|
||
|
||
1. **BBL island — untouched.** Bambu profiles keep their `GF*` catalog ids byte-for-byte
|
||
(device/RFID/cloud contract). No convergence between GF and OFL ids is attempted: the
|
||
same product may permanently carry `GFL00` on the BBL side and an `OF*` id everywhere
|
||
else. This is a deliberate trade for simplicity; v2's curated-GF-adoption (old W4) is
|
||
dropped.
|
||
2. **`QD_*` island — untouched.** Qidi's box builds `QD_<series>_<vendor>_<type>` from
|
||
device enums and requires exactly-matching presets (`QidiPrinterAgent.cpp:146-152`).
|
||
Qidi presets carrying `QD_*` are exempt from re-minting, forever.
|
||
3. **Everything else converges on OrcaFilamentLibrary.** OFL is the product catalog: a
|
||
material family's id is declared once, on its OFL family root. Vendor bundles carry
|
||
only per-printer *specializations* of OFL families — same base name, non-empty
|
||
`compatible_printers`, **no `filament_id` key** — which (a) alias-shadow the OFL preset
|
||
on the printers they claim (`Preset.cpp:3684-3714`: "Generic PLA @Qidi Q2 0.4mm nozzle"
|
||
hides "Generic PLA @System" on that machine) and (b) resolve the OFL family's id
|
||
through the loader's inherits/base-bundle walk (`PresetBundle.cpp:4842-5080`). Products
|
||
OFL does not (yet) carry mint their id in the vendor bundle **with the same rule**;
|
||
because the key is bundle-independent (§1), later hoisting the family into OFL never
|
||
changes its id.
|
||
|
||
Convergence therefore happens by *single declaration point*, not by copying ids across
|
||
bundles — no adoption registry, no cross-bundle id claims to curate.
|
||
|
||
## 1. The mint rule
|
||
|
||
```
|
||
triple = (filament_vendor, filament_type, family_name) # from the family ROOT's flattened config
|
||
key = "filament_product/<filament_vendor>/<filament_type>/<family_name>"
|
||
id = "OF" + base62_6( uuid5( FILAMENT_ID_NAMESPACE, key ) ) # namespace unchanged:
|
||
# c4d3ff49-4c32-5534-a3e3-00894157ab97
|
||
```
|
||
|
||
- **Triple resolution.** All three values come from the family root preset's *flattened
|
||
effective config* (`filament_vendor` and `filament_type` are inheritable list options —
|
||
take the first element; family_name = the root's base name, `\s?@.*` stripped once).
|
||
For own-key-layout families (no root), each declaring preset's flattened config is used
|
||
and CI requires all declarers of one family to agree on the triple. A root that resolves
|
||
an empty `filament_vendor` or `filament_type` is a CI error (generics use `"Generic"`).
|
||
Values enter the key verbatim (UTF-8, no case folding).
|
||
- **Bundle-independent by design.** The key contains no bundle name, so the same product
|
||
yields the same id whether minted in OFL or in a vendor bundle; migrating a family into
|
||
OFL (§0.3) is id-stable. Two bundles independently adding the same triple converge
|
||
automatically — and that is correct, because equal (vendor, type, name) *is* the
|
||
definition of "same product" here. The known look-alike hazards stay separated by the
|
||
type component: the 4 same-name-different-type groups (Flashforge `Generic PLA Silk` as
|
||
SILK, OFL `Generic PETG-CF` as PETG, `Generic PA6-CF`, `Generic PE-CF`) hash apart until
|
||
their type bugs are fixed (§5, W3) and converge automatically after — self-healing that
|
||
pure name-keying (rejected in v2) could not provide.
|
||
- **Format and salt unchanged from v1**: 8 chars, `OF` + 6 base62; deterministic `/1`,
|
||
`/2`… salt past any taken or retired id (the O+7 widening was evaluated and rejected:
|
||
62⁶ expects 1.9×10⁻⁵ collisions at today's 1,455 families, and `^O.{7}$` would sweep 35
|
||
legacy ids into the conformance gate vs. one today).
|
||
- **Content-addressed, deliberately.** If any triple component changes — a family rename,
|
||
a `filament_vendor` correction, a `filament_type` fix — the id changes with it. This
|
||
*replaces* v1's "ids are immutable once shipped" with "ids are derivable from the
|
||
product identity, and identity changes are migrations" — made safe by the succession
|
||
ledger (§2). `renamed_from` still gates preset-name compatibility as before.
|
||
- CLI: `--mint "Polymaker/PLA/PolyLite PLA"` prints without touching the tree; running
|
||
the script plain inserts missing ids; CI errors print the expected id.
|
||
|
||
## 2. The succession ledger (the amendment that makes this safe)
|
||
|
||
Shipped ids are referenced outside the tree: AFC/Klipper lane data, Bambu AMS trays
|
||
holding OFL-only materials, on-device PA-calibration records, user-root preset copies,
|
||
3mf `slice_info`. Retiring an id without a forwarding pointer downgrades all of those to
|
||
`Generic <type>` fallbacks. Therefore:
|
||
|
||
- **Schema.** `scripts/retired_filament_ids.json` entries become objects:
|
||
`{"retired": {"OGFL99": {"claims": [...], "successor": "OFxxxxxx"}}}`. Append-only as
|
||
before; a successor may itself be retired later (chains allowed, cycle-checked, and
|
||
followed to the live end). A retired id may never be minted again (check 4 unchanged).
|
||
Cross-island *hint* entries are permitted for ids Orca cannot retire because another
|
||
island owns them (e.g. `GFL99 → <OFL Generic PLA id>`): consulted only when no live
|
||
preset matches, so BBL installs still resolve `GFL99` natively first. By the same
|
||
principle, an id in a foreign island's space (`GF*`/`QD_*`) that vanishes from the tree
|
||
is **released with a hint, never retired** — the island's catalog owns it and may
|
||
legitimately (re)ship it later, which check 4 must never block. (Implementation
|
||
amendment, v3.0: `--update-snapshot` routes such ids to `hints` automatically; hint
|
||
keys may be absent from the tree.)
|
||
- **Shipped and consulted at runtime.** The ledger ships in `resources/`; a small helper
|
||
(`resolve_filament_id_succession(id)`) follows the chain and is consulted **only on
|
||
resolution miss**, before the `Generic <type>` name fallback, in:
|
||
`PresetBundle::get_filament_by_filament_id` (covers `DevFilaBlackList`, `SelectMachine`
|
||
warnings, `Plater` tray configs in one place), the AMS sync match predicates
|
||
(`PresetBundle.cpp:3151`, `:3252-3254` miss paths at `:3157-3169`/`:3260-3305`),
|
||
`PresetComboBoxes::add_ams_filaments`, `MachineObject::setting_id_to_type`
|
||
(`DeviceManager.cpp:2545` miss branch), calibration-history name lookup
|
||
(`CaliHistoryDialog.cpp:62`), and the #14423 Moonraker lane matching when it lands.
|
||
With this in place the OFL re-mint is near-residue-free and every future
|
||
content-addressed rename stays safe.
|
||
- **Kill the hardcoded generic map.** `MoonrakerPrinterAgent::map_filament_type_to_generic_id`
|
||
(`MoonrakerPrinterAgent.cpp:608-658`) hardcodes 23 OFL ids (`OGFL99`… `OFLSBS99`).
|
||
Replace it with a runtime lookup of the OFL generic preset by name ("Generic PLA
|
||
@System" → its current id), removing the code↔profile lockstep permanently. (This also
|
||
releases `OFLSBS99`, v2's one frozen OF-shaped legacy id, for normal re-minting.)
|
||
|
||
## 3. Validation rule changes
|
||
|
||
- **Check 3 (mint conformance)** becomes a pure function of the root's triple: a non-BBL,
|
||
non-`QD_*` id must equal `mint(triple)` ± salt, or be snapshot-grandfathered (the
|
||
grandfather set shrinks to ≈ nothing for non-BBL once migration completes).
|
||
- **Check 5 (alias hygiene) generalizes and becomes load-bearing.** For *every*
|
||
OFL-carried family (not just `Generic * @System`): a vendor specialization must keep the
|
||
OFL base name (else the OFL preset un-shadows and creates a live per-printer duplicate —
|
||
v1's P7 pattern) and non-empty `compatible_printers`, and must not declare an id. The
|
||
C++ validator's OFL-aware `-f` (`PresetBundle.cpp:5674-5753`) already enforces the
|
||
runtime consequence; the script check names the rename as the cause.
|
||
- **New check 8 (triple integrity):** every id-declaring family resolves a complete,
|
||
family-consistent triple; roots missing `filament_vendor`/`filament_type` error.
|
||
- **New check 9 (succession integrity):** every retired entry's successor chain ends at a
|
||
live tree id (or a documented cross-island hint target); no cycles; retired ids absent
|
||
from the tree.
|
||
- Snapshot mechanism, reserved spaces (`GF*`→BBL, `QD_*`→Qidi, `P`-hex/`null`→user-custom;
|
||
v2's do-not-reserve-`OF*` note stands), and check 1/2/4/7 are unchanged.
|
||
|
||
## 4. Migration phases
|
||
|
||
**v3.0 — tooling + prerequisites (no profile changes).** New mint + triple resolver
|
||
(reuse the flatten machinery), succession schema migration + C++ lookup helper wired into
|
||
the §2 miss paths, Moonraker map → runtime lookup, checks 3/5/8/9, tests. Carry v2's W1
|
||
client hardening (skip tray-wipe/temp-rewrite when a system preset holds the id; relax
|
||
the `DeviceManager.cpp:5252` assert; guard the `PresetBundle.cpp:3717` deref) — it ships
|
||
first regardless. **W3 type fixes land here**, *before* any re-mint: type is now a key
|
||
component, so minting before fixing OFL `Generic PETG-CF`/`Generic PE-CF` would re-id
|
||
those families twice.
|
||
|
||
**v3.1 — OFL re-mint.** Every OFL-declared id re-derives from its triple (mirrors like
|
||
`OGFA00`, generics like `OGFL99`, blocks like `OEPLAB00` — all of it); each old shipped id
|
||
gains a succession entry pointing at its replacement; the 26 GF-shaped ids OFL declares
|
||
(measured at v3.0: only one of them, `GFOT001`, is also declared by BBL) are released to
|
||
the BBL island space with hints at the re-minted families — two-island purity. Snapshot
|
||
regenerated; full gate battery + fixture overlays (this phase touches preset-visibility
|
||
machinery only via ids, but the fixtures are cheap insurance). Implementation notes
|
||
(v3.1, executed): OFL generic ids relocate from the fdm_filament_* template bases onto
|
||
the product-named "Generic X @System" presets first, so their triples carry the product
|
||
name; `fdm_filament_pc` keeps a (transitional) declaration because 7 Prusa presets
|
||
inherit it directly — the v3.2 Prusa worksheet re-homes them and deletes it.
|
||
|
||
**v3.2 — vendor bundles, worksheet-per-vendor (v1 machinery).** Three sub-cases:
|
||
(a) the **391 unshipped v1 `OF*` mints** re-derive under the triple key — no succession
|
||
entries (they never shipped; a documented one-time `--forget-never-shipped <list>` drops
|
||
them from the ledger lineage instead of retiring them, since the ledger's rationale —
|
||
ids live on in user presets and 3mfs — cannot apply to unreleased ids);
|
||
(b) **true generic tunings** riding copied legacy ids (`GFL99`-class) drop their own id
|
||
and re-point to the OFL generic family (the v1 Sovol pattern) — their old ids get
|
||
cross-island hints where BBL owns them, succession entries otherwise;
|
||
(c) remaining **shipped legacy ids** (numeric, name-shaped, pseudo-GF, the 57
|
||
multi-vendor GF residue, the 10 P-hex — everything non-BBL/non-`QD_*`, ~800 ids)
|
||
re-mint with succession entries. Retiring the 10 P-hex system ids also removes the last
|
||
system ids from `check_ams_filament_valid`'s destructive P-gate.
|
||
|
||
**v3.3 — ongoing consolidation (optional, per-vendor, id-stable).** Hoist vendor-unique
|
||
products into OFL where a family is genuinely multi-vendor material; thanks to the
|
||
bundle-independent key this never changes ids, so it can proceed opportunistically.
|
||
|
||
## 5. Gates (every phase)
|
||
|
||
`python scripts/orca_extra_profile_check.py` exit 0; `assign_filament_ids.py --check`
|
||
exit 0; unit tests green (existing 46 + new triple/succession/adoption tests); validator
|
||
`-l 2` exit 0, `-f` tree-wide exit 0, `-r` BBL+Qidi exit 0; custom-preset fixture
|
||
archives; config-equivalence — flattened effective configs differ only in `filament_id`
|
||
(re-mints), `inherits`/`compatible_printers` (re-points, as prescribed per worksheet), and
|
||
the W3 `filament_type` corrections. New for v3: a C++ test that a retired id resolves
|
||
through the succession chain in the sync miss path, and a Moonraker test that the generic
|
||
map lookup matches the shipped OFL presets. Manual AMS smoke test (tray set → old-id
|
||
resolve → clear) stays a release-checklist item.
|
||
|
||
## 6. Accepted costs (explicit)
|
||
|
||
- **GF ↔ OFL divergence is permanent** for products in both catalogs (PolyLite PLA ≠
|
||
`GFL00` outside BBL). The forward-looking fix is PR #12724-style filament-database
|
||
upload, where Orca ids become first-class device artifacts.
|
||
- **Renames/type-fixes re-id families** (by design); the succession ledger absorbs the
|
||
device/user residue, but each one is still a ledger entry and a snapshot diff to review.
|
||
- **User roots** keep whatever id they copied at creation; with succession lookup in
|
||
`get_filament_by_filament_id` they now *resolve* instead of dangling — strictly better
|
||
than v1's accepted residue.
|
||
- **One-time field transition**: devices holding pre-v3 ids (AFC lanes, AMS trays, cali
|
||
records) resolve via succession on updated clients; *older* Orca versions and
|
||
BambuStudio never resolved OFL-only ids anyway (`?`/generic fallback — unchanged for
|
||
them).
|
||
|
||
## 7. Open decisions
|
||
|
||
1. Whether v3.2(b)'s cross-island hints (`GFL99` → OFL generic) are wanted at launch or
|
||
deferred (pure-miss-path feature; zero risk to BBL installs, small review surface).
|
||
2. v3.3 pacing: per-vendor PRs opportunistically vs. a dedicated consolidation train.
|
||
3. Whether to fold v2's W5 (P+md5 ids for inherited *user* presets, PR #13315) into v3.0's
|
||
C++ work or keep it a separate PR (recommended: separate; W1 is its only prerequisite).
|
||
|
||
## 8. Evidence
|
||
|
||
Carried from v2 §8 (all re-verified this session), plus: `filament_vendor` audit — 49
|
||
distinct strings tree-wide, `"Polymaker"` byte-consistent across all five PolyLite-PLA
|
||
bundles; multi-vendor different-family GF residue = 57 ids; `MoonrakerPrinterAgent.cpp:
|
||
608-658` = 23 hardcoded OFL ids; mint examples verified live (`Qidi/PolyLite PLA` →
|
||
`OFceJcLf` under the v1 key — the fragmentation this plan removes; salt determinism
|
||
`OF8afiMO`). Alias shadowing and the OFL id fallback verified at `Preset.cpp:3684-3714`
|
||
and `PresetBundle.cpp:4842-5080` during the v1 audit; per-printer `-f` semantics at
|
||
`PresetBundle.cpp:5674-5753`.
|