Files
OrcaSlicer/filament_id_plan_v3.md
SoftFever acd5dd0794 v3.1: OrcaFilamentLibrary re-mint under the product-triple rule
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.
2026-07-04 16:41:41 +08:00

214 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`.