mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-24 02:17:57 +00:00
init
This commit is contained in:
1029
filament_id_plan.html
Normal file
1029
filament_id_plan.html
Normal file
File diff suppressed because it is too large
Load Diff
397
filament_id_plan.md
Normal file
397
filament_id_plan.md
Normal file
@@ -0,0 +1,397 @@
|
||||
# filament_id: generation rule + system-profile fix plan
|
||||
|
||||
Follow-up to PR #14459 (commit `c2e91cb8`, validator `-f` / `check_duplicate_filament_subtypes`).
|
||||
Goal 1: a filament_id generation rule for all vendors. Goal 2: an error-pattern taxonomy and a
|
||||
migration plan that removes every ambiguous filament_id, without touching Bambu (BBL) profiles.
|
||||
|
||||
All numbers below are reproducible: a loader-faithful audit script re-derives the validator's
|
||||
output **exactly** (1256/1256 printer-level errors, 356 logical collision groups, 30 vendors).
|
||||
Every code claim was verified against source with `file:line` references.
|
||||
|
||||
---
|
||||
|
||||
## 0. Executive summary
|
||||
|
||||
- `filament_id` is a **material-family id**: one id per commercial product line, shared by all
|
||||
of that material's per-printer/per-nozzle variants. Matching is always `(filament_id +
|
||||
printer compatibility)`; the invariant from PR #14459 is *per printer preset, at most one
|
||||
compatible instantiated filament preset per id*.
|
||||
- Every modern device ecosystem funnels through this id — not just Bambu AMS: Qidi box,
|
||||
Creality CFS, Klipper AFC/Happy Hare, Snapmaker all emit/consume `tray_info_idx`
|
||||
(see §1). Several consumers match **globally, without printer scoping**, so two *different
|
||||
materials* sharing one id is unsafe even across vendors.
|
||||
- **Proposed rule (§3):** deterministic, script-minted ids — `OF` + 6 base62 chars from
|
||||
`uuid5(vendor + family)`, declared **only on family-root (`@base`) presets**; variants inherit.
|
||||
Nobody ever invents an id by hand; CI prints the expected id when one is missing. Existing
|
||||
unambiguous ids are grandfathered and frozen; `GF*` (Bambu), `QD_*` (Qidi device protocol),
|
||||
and `P<7-hex>` (user custom presets) are reserved namespaces that must never be minted into.
|
||||
This was selected by an adversarial design/judge process over a registry-grammar alternative
|
||||
and a structure-only alternative, then stress-tested; amendments from that stress test are
|
||||
folded in below.
|
||||
- **Migration (§5):** fresh-never-reused ids only, family-atomic, names never changed. This is
|
||||
provably safe: user presets re-derive `filament_id` from their parent on every load
|
||||
(`Preset.cpp:1658-1682`), 3mf resolves presets by name+config (`Preset.cpp:2490-2576`), and
|
||||
Klipper/Creality/Snapmaker derive tray ids at runtime. One PR per vendor; CI's `-f` scope
|
||||
ratchets per vendor until tree-wide.
|
||||
|
||||
---
|
||||
|
||||
## 1. How filament_id actually works (verified)
|
||||
|
||||
### Consumers and scoping
|
||||
|
||||
All device integrations converge on one pipeline: device/agent sets `tray_info_idx` →
|
||||
`DevAmsTray.setting_id` → `Sidebar::build_filament_ams_list` (`Plater.cpp:3423-3493`) →
|
||||
`PresetBundle::sync_ams_list` / `get_ams_cobox_infos` (`PresetBundle.cpp:3112-3308`) match it
|
||||
against filament presets.
|
||||
|
||||
| Ecosystem | Where the id comes from | Effect of changing a system id |
|
||||
|---|---|---|
|
||||
| BBL AMS | device-side (RFID / user tray setting), `DeviceManager.cpp:3823+` | breaks matching — **frozen by mandate** |
|
||||
| Qidi box | built from device enums: `"QD_" + series + "_" + vendor + "_" + type_idx`, `QidiPrinterAgent.cpp:146-152`; needs an exactly-matching visible preset | breaks matching — **`QD_*` ids are a frozen device contract** |
|
||||
| Creality CFS | runtime brand/type scoring returns current preset's id (`CrealityPrintAgent.cpp:46-118`) | invisible |
|
||||
| Klipper (AFC / Happy Hare) | runtime `filament_id_by_type` (`MoonrakerPrinterAgent.cpp:808,936`) | invisible |
|
||||
| Snapmaker | runtime color/vendor/type match (`SnapmakerPrinterAgent.cpp:22-64`) | invisible |
|
||||
|
||||
Matching is printer-scoped (`is_compatible`) in the AMS sync paths and all printer agents — this
|
||||
is what makes the per-printer invariant sufficient there. But several consumers match
|
||||
**globally by id alone**, first match wins:
|
||||
|
||||
- `get_filament_by_filament_id("")` — tray display name, `filament_is_support`,
|
||||
`temperature_vitrification` warnings (`PresetBundle.cpp:690-733`; callers
|
||||
`DevFilaBlackList.cpp:70`, `Plater.cpp:3453`, `SelectMachine.cpp:3560,4623`). The code
|
||||
comment at `:695` states the assumption outright: an id maps to ONE material globally.
|
||||
- `MachineObject::setting_id_to_type` (`DeviceManager.cpp:2538`), calibration-history name
|
||||
lookup (`CaliHistoryDialog.cpp:62`), custom-filament cloud grouping (`Preset.cpp:2839`).
|
||||
- The slicing pipeline itself: multi-nozzle filament grouping merges project filaments whose
|
||||
`(filament_id, color)` match (`FilamentGroup.cpp:513-528` via `ToolOrdering.cpp:1164`).
|
||||
|
||||
**Consequence:** within one printer, duplicate ids break AMS matching (silent first-wins,
|
||||
`find_if` at `PresetBundle.cpp:3132/3233`; the AMS tray-edit dialog even *hides* the second
|
||||
preset, `AMSMaterialsSetting.cpp:894-897`). Across vendors, the same id on *different
|
||||
materials* feeds wrong name/type/vitrification data to the global consumers and can merge
|
||||
different materials into one nozzle group. Same id on the *same* material (e.g. `GFL99` =
|
||||
Generic PLA in 29 vendors) is comparatively benign — those attributes agree.
|
||||
|
||||
### Identity machinery
|
||||
|
||||
- **Effective id resolution** (`PresetBundle.cpp:4842-5080`): own `filament_id` key → vendor
|
||||
`filament_id_maps[inherits]` (file order in the vendor index is load-bearing) →
|
||||
OrcaFilamentLibrary base-bundle map. An instantiated system filament that resolves *no* id is
|
||||
a hard load error that discards the whole vendor bundle (`:5072`, throw at `:5141-5147`) —
|
||||
so "missing id" cannot ship; what looked like 26 id-less Flashforge presets actually resolve
|
||||
to OFL's `OGFL99`/`OGFG99` through the base-bundle fallback.
|
||||
- **Two family-identity systems exist**: `filament_id` (device matching) and `alias` (name
|
||||
before `" @"`). OFL shadowing is keyed on **alias**: `update_library_profile_excluded_from`
|
||||
(`Preset.cpp:3684-3714`) hides an OFL preset (empty `compatible_printers` = compatible with
|
||||
everything, `Preset.cpp:837`) on printers claimed by a same-alias vendor preset. There is
|
||||
**no id-based shadowing**. A vendor preset that tunes an OFL generic but renames it
|
||||
re-exposes the OFL preset and creates a live duplicate. The rule below aligns the two
|
||||
systems: one family = one alias = one id.
|
||||
- **User-custom id space**: user-created filaments get `"P" + md5(name)[0:7]` (8 chars,
|
||||
`CreatePresetsDialog.cpp:533`), or *reuse a system id* when the base name matches an existing
|
||||
preset (`:510-528`). `"null"` is used as a sentinel. Root user presets persist their id
|
||||
forever; inheriting user presets re-derive it on every load.
|
||||
|
||||
## 2. The id landscape today
|
||||
|
||||
**Bambu's grammar** (derived from all 1970 BBL instantiated presets; BBL is internally clean —
|
||||
181 id definitions, 0 duplicates):
|
||||
|
||||
- Classic `GF<LETTER><NN>`: letter = family (A Bambu-PLA, B ABS/ASA, C PC, G PETG/PCTG,
|
||||
L third-party+generic PLA, N PA/PPA, P PP/PE, R misc, S support, T PET/PPS, U TPU).
|
||||
Numbers: 00-49 branded ascending, 50-59 fiber-filled, 60-70 partner block, **95-99 generic
|
||||
tier descending** (99 = the family's plain generic).
|
||||
- Brand partners `GF<BRANDCODE><NNN>`: GFPM Polymaker, GFOT Overture, GFSNL SUNLU, GFNMK
|
||||
Numakers. One id per product line; never per color, never per printer/nozzle/diameter.
|
||||
- Structural rule: the id lives on the material's `@base`; every variant inherits it.
|
||||
- Hardcoded in C++: `GFS00/GFS01` support check (`DeviceManager.cpp:4739`), per-family PA
|
||||
defaults `GFU01/03/04` (`CalibUtils.cpp:54-75`) — `GF*` is Bambu's space, byte-frozen.
|
||||
|
||||
**Everything else is ad-hoc, invented by individual contributors and imitated** (full history
|
||||
in §7): OFL's `O`-prefix mirrors (`OGFA00`; introduced 2025-03-31, commit `8c4a65e3e1`),
|
||||
Tiertime/Afinia `GFx##_##` per-printer-line suffixes, SeeMeCNC per-nozzle ids, LH `LHF_pla`,
|
||||
LONGER 11-char pseudo-GF ids, Anycubic ids **with spaces** (`"GFPLA Silk"`), Prusa ids that are
|
||||
entire preset names (36 chars), and mass copy-paste of `GFL99/GFB99/GFG99` onto everything
|
||||
(Qidi alone stamped `GFB99` into **317 files** across all materials). The only guidance that
|
||||
ever existed was "≤ 8 chars" — enforced for BBL only (`orca_extra_profile_check.py:292,320`),
|
||||
and the (now removed) profile wiki's own examples *taught* id copy-pasting.
|
||||
|
||||
**The damage, quantified** (audit reproduces validator 1256/1256):
|
||||
|
||||
| Ledger | Count |
|
||||
|---|---|
|
||||
| Within-vendor logical collision groups (validator `-f`) | **356** across 30 vendors (1256 printer-level errors) |
|
||||
| OFL×vendor same-id groups (validator blind spot) | 42 — of which **10 are live** (alias mismatch defeats shadowing); 32 already neutralized by alias shadowing |
|
||||
| OFL-internal: one id, several materials, visible on every printer | **16 ids** (e.g. `OEPLAB00` = 14 distinct Elegoo PLA products; `OGFL06` = eSUN PLA-Marble *and* Fiberon PETG-ESD) |
|
||||
| Cross-vendor semantic collisions (same id, different materials) | **67 ids** (e.g. `GFU99` also covers a PEBA; Anycubic minted `GFL95` "Matte" ≠ Bambu `GFL95` "High Speed") |
|
||||
|
||||
Worst vendors by groups: Qidi 97, Flashforge 69, Elegoo 37, Prusa 31, Cubicon 17,
|
||||
Anycubic 14, InfiMech 14, Snapmaker 11, Artillery 8, Creality 8, FlyingBear 8.
|
||||
|
||||
---
|
||||
|
||||
## 3. The rule (proposal)
|
||||
|
||||
Selected by a 3-design / 2-judge adversarial process (deterministic-mint won over
|
||||
registry-grammar and structure-only on ambiguity-prevention, contributor simplicity, and
|
||||
enforceability), then hardened by three adversarial review passes. This section is written as
|
||||
the future authoring doc.
|
||||
|
||||
### 3.1 The one-question test
|
||||
|
||||
> **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`, no id key). Tuning a
|
||||
> generic material → **join the OFL family** (inherit the `Generic X @System` preset, keep the
|
||||
> `Generic X` base name, add no id).
|
||||
|
||||
Same id / new id at a glance:
|
||||
|
||||
| Situation | id |
|
||||
|---|---|
|
||||
| Per-printer / per-nozzle variant of an existing material | same id (inherit, never write the key) |
|
||||
| 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 selectable on the same printer (1.75 + 2.85) | sibling family, new id |
|
||||
| "High-speed" tuned for a *different printer model* | same id (it's a printer variant) |
|
||||
| "High-speed" selectable *alongside* the normal preset on one printer | new id (it's a product line) |
|
||||
|
||||
### 3.2 Structure
|
||||
|
||||
1. **One family = one root.** Each material family has root preset(s) (`instantiation:false`,
|
||||
typically `<Family> @base`) and only roots carry the `filament_id` key. Instantiated
|
||||
variants inherit a root and never write `filament_id`. (A family MAY have several roots —
|
||||
e.g. Qidi's per-series bases — but they must all declare the *identical* id.)
|
||||
2. **Family identity is declared, not name-derived.** Default: the family name is the
|
||||
instantiated presets' base name (name with `/\s?@.*$/` stripped — note *optional* space,
|
||||
because `Afinia PLA@HS`-style names exist). When vendor naming makes that ambiguous, the
|
||||
root declares an explicit `"filament_family"` key that overrides derivation; tooling errors
|
||||
loudly when a root's derived family differs from its children's.
|
||||
3. **Within a family, variants' `compatible_printers` are pairwise disjoint** — that *is* the
|
||||
PR #14459 invariant, enforced by the validator.
|
||||
4. **Generics belong to OFL.** A vendor tuning `Generic PLA` inherits
|
||||
`Generic PLA @System`, keeps the `Generic PLA` base name/alias (so alias shadowing excludes
|
||||
the OFL preset on those printers, `Preset.cpp:3684`), sets non-empty `compatible_printers`,
|
||||
and writes no id. A vendor-*branded* filament never rides a generic family id.
|
||||
5. **Ids are immutable once shipped.** Renaming a family does not change its id (use
|
||||
`renamed_from`). No id is ever recycled for a different material — stale ids live on in
|
||||
user root presets and old 3mfs, and a recycled id would silently match the wrong material.
|
||||
|
||||
### 3.3 Minting — nobody invents ids
|
||||
|
||||
New family ids are computed, exactly like the `setting_id` precedent
|
||||
(`scripts/assign_vendor_setting_ids.py` / `Slic3r::generate_preset_setting_id`):
|
||||
|
||||
```
|
||||
filament_id = "OF" + base62_6( uuid5( NAMESPACE, "filament_family/<vendor>/<family>" ) )
|
||||
```
|
||||
|
||||
8 chars total (satisfies the AMS length limit), same base62 derivation and a dedicated
|
||||
namespace constant. On the astronomically rare collision with an existing id, the minter salts
|
||||
the input (`.../1`, `/2`, …) until free; the result is simply frozen in the file.
|
||||
|
||||
- **Script path:** author commits the family with *no id anywhere*;
|
||||
`python scripts/assign_filament_ids.py` inserts the minted id into the root(s). Idempotent;
|
||||
never rewrites a valid existing id. A `--mint "<Vendor>/<Family>"` one-shot prints the id
|
||||
without touching the tree.
|
||||
- **No-script path:** CI fails with the exact line to paste:
|
||||
`family "MyBrand PLA" (vendor X) needs filament_id "OFq3xT9k" in "MyBrand PLA @base.json"`.
|
||||
|
||||
**Reserved namespaces — never mint or hand-write into:**
|
||||
|
||||
| Space | Owner | Status |
|
||||
|---|---|---|
|
||||
| `GF*` | Bambu AMS/RFID catalog | byte-copies of authentic Bambu ids only, and only where a checked-in `shared_catalog` list sanctions the family (BBL bundle; OFL mirrors; byte-matching families in other vendors, e.g. Snapmaker's Fiberon) |
|
||||
| `QD_*` | Qidi device protocol | frozen; Qidi-only; exempt from family-shape checks |
|
||||
| `P[0-9A-Fa-f]{7}`, `"null"` | user-created custom filaments (`CreatePresetsDialog.cpp:533`) | never emitted for system presets (reserve case-insensitively) |
|
||||
| everything already shipped | grandfather snapshot | frozen as-is (§5) |
|
||||
|
||||
Trade-off accepted: minted ids are opaque (`OFq3xT9k` carries no "PLA" mnemonic — the family
|
||||
name in the same file provides that). The judges preferred this over a Bambu-style extended
|
||||
grammar because it removes the "who allocates the next number" ceremony, cannot race between
|
||||
concurrent PRs, and needs no registry maintenance. If mnemonic ids are strongly preferred, the
|
||||
runner-up design (`<NSCODE><FAMLETTER><SEQ>` + registry file) is documented in the workflow
|
||||
records; everything else in this plan is unchanged under either format.
|
||||
|
||||
### 3.4 What CI enforces (all vendors, ratcheted)
|
||||
|
||||
Extend `scripts/orca_extra_profile_check.py` (it imports the same mint function; setting_id
|
||||
precedent) and the C++ validator:
|
||||
|
||||
1. **Format**: an id is valid iff `OF[0-9A-Za-z]{6}` **or** in the grandfather snapshot **or**
|
||||
vendor==BBL **or** `QD_*` in Qidi. No whitespace/ASCII/length checks needed outside the
|
||||
grandfather set — new ids are minted, and the grandfather set is closed.
|
||||
2. **Uniqueness ratchet**: id→families multimap computed tree-wide; no id may acquire a family
|
||||
claim not recorded in the snapshot (snapshot legalizes today's benign `GFL99`-style sharing;
|
||||
new multi-claims are errors; `shared_catalog` entries are the sanctioned exception).
|
||||
3. **Structure ratchet**: `filament_id` key only on roots; every instantiated filament must
|
||||
resolve an effective id via the simulated loader walk; all members of one family resolve the
|
||||
same id; **a preset may not declare an id different from its inherited effective id** (the
|
||||
`Generic SBS` drift bug class). Pre-existing violations are snapshot-frozen; new ones error.
|
||||
4. **Mint conformance**: an id new relative to the snapshot must equal the mint (or a salt
|
||||
iteration); the error message prints the expected value.
|
||||
5. **Stability**: an `(id, family)` pair on main may not change or vanish, *following
|
||||
`renamed_from` chains* (so an honest rename passes), unless listed in a maintainer-gated
|
||||
migrations file. Retired ids go to an append-only `retired_ids` ledger; a retired id may
|
||||
never be defined again for any family.
|
||||
6. **Alias hygiene for tuned generics**: a preset inheriting an OFL `Generic * @System` (with
|
||||
no own id anywhere in its vendor chain) must keep the OFL base name and have non-empty
|
||||
`compatible_printers` — error message names the rename as the cause.
|
||||
7. **C++ validator**: extend `check_duplicate_filament_subtypes` (`PresetBundle.cpp:5654`) to
|
||||
include OFL presets in every vendor's per-printer check, *minus* alias-excluded ones —
|
||||
`m_excluded_from` is already populated in the validator context (`update_system_maps` at
|
||||
`PresetBundle.cpp:2302`), so the 32 shadowed pairs won't false-positive and the 10 live ones
|
||||
will be caught. Run `-f` per vendor in CI, widening as vendors are cleaned (§5).
|
||||
8. **Runtime backstop** (one-line change): log a warning when the AMS-sync `find_if`
|
||||
(`PresetBundle.cpp:3132/3233`) finds 2+ compatible presets for one id — the only layer that
|
||||
can see side-loaded/forked bundles.
|
||||
|
||||
---
|
||||
|
||||
## 4. Error-pattern taxonomy (goal 2) — with counts and fixes
|
||||
|
||||
356 groups were classified by 37 agents reading the actual profiles, spot-checked
|
||||
independently (1 substantive disagreement in 14 samples). Counts below fold the spot-check
|
||||
corrections in. **Fix rule for all patterns: replacement id values are always freshly minted
|
||||
`OF*`; the "which preset keeps the id" decision uses the precedence _Bambu-catalog material >
|
||||
OFL generic family > family that historically introduced the id_.**
|
||||
|
||||
| # | Pattern | Groups | Fix |
|
||||
|---|---|---|---|
|
||||
| P1 | `copy_paste_id` — different materials share an id verbatim (task's error 1). Qidi's `GFB99`×317-files epidemic; Anycubic's three id "eras"; Peopoly `GFSL99` on ABS | ~167 | impostor families get minted ids on their roots; owner keeps the id |
|
||||
| P2 | `wrong_inherits` / id-less product lines — a variant inherits another family's root (PR #14459's Panchroma case) or a product line never got its own root (Prusa HF; Flashforge's ~140-preset `FFG01` umbrella) | ~87 | create per-family roots with minted ids; re-point `inherits`; **never** delete the id-less shadow/base files — convert them (they carry real config: Flashforge `fdm_filament_pla` differs materially from OFL's) |
|
||||
| P3 | `generic_family_overlap` — vendor-*branded* preset rides a generic family id via inheritance (task's error 2, generalized). Includes the 10 live OFL duplicates | ~68 | branded presets get minted family ids; true generic tunings instead adopt the OFL family *with matching alias* (rule 3.2.4); Sovol is the elegant case — just **delete** its wrong own-id lines and let OFL ids flow through inheritance |
|
||||
| P4 | `overclaim_compat` — same material, broader variant claims a printer that a dedicated variant covers (the BBL H2DP pattern fixed in #14459) | ~24 | trim `compatible_printers` of the broader preset (Dremel, Cubicon `@base`s that are also instantiated, Wanhao France Bowden/Direct) |
|
||||
| P5 | template-carried id — id declared on a shared settings template (`fdm_filament_*`, `fdm_filament_common`) so every family inheriting it collapses (Prusa, Ginger Additive, Snapmaker TPU base) | inside P1/P2 counts | move ids off templates onto family roots |
|
||||
| P6 | OFL-internal collisions — 16 ids spanning several materials, visible on every printer (Elegoo blocks, Elas `OGFA00`×3, `OGFL06` polymer mismatch, `Generic PETG HF/PETG-CF @System` missing own ids) | 16 ids | fix inside OFL first (it's the base bundle every vendor resolves against) |
|
||||
| P7 | alias-mismatch re-exposure — vendor tunes a generic under a different name, OFL preset resurfaces (Snapmaker `PolyTerra J1 PLA` vs OFL `PolyTerra PLA`) | 10 live | rename-to-alias where it's genuinely the same family, else mint |
|
||||
| P8 | per-variant ids — no ambiguity, but family semantics broken: every variant has its own id (Prusa name-ids, SeeMeCNC nozzle suffixes, Afinia/Tiertime `_##`, iQ) so device matching can't identify the material across nozzles | ~210 presets | grandfather (they're unambiguous); converge opportunistically; document as anti-pattern |
|
||||
| P9 | format violations — spaces (`"GFPLA Silk"`), >8 chars (LONGER, SeeMeCNC, LH), GF-shaped inventions (Anycubic `GFL93-97`, CoLiDo `GFA99`) | in the above | fixed as a byproduct of re-minting; snapshot freezes the unambiguous rest |
|
||||
| P10 | cross-vendor semantic collisions — 67 ids meaning different materials in different vendors (dangerous via the global unscoped consumers, §1) | 67 ids | mostly eliminated by P1-P3 re-minting; the remaining same-material generic sharing is legalized by the snapshot |
|
||||
| P11 | deliberate coexistence & data hygiene — Snapmaker "Benchy" demo presets (gated by `compatible_prints`, which the id check can't see) and a self-collision from duplicate `compatible_printers` entries | 4 | give demo presets own minted ids; dedupe list entries; add a lint for duplicate array entries |
|
||||
|
||||
New patterns beyond the two in the task (goal 2.3): P5-P11.
|
||||
|
||||
---
|
||||
|
||||
## 5. Migration plan
|
||||
|
||||
### Safety foundation (verified, §1/§7)
|
||||
|
||||
Safe: fresh never-used ids, family-consistent; trims of `compatible_printers`; inherits
|
||||
re-pointing; OFL id changes (children re-derive). Unsafe: touching `BBL`/`QD_*`; recycling or
|
||||
swapping ids; splitting a family's id; **deleting or renaming preset names** (user presets
|
||||
whose `inherits` no longer resolves are dropped at load, `Preset.cpp:1687-1691`) — if a name
|
||||
must go, `renamed_from` coverage is mandatory.
|
||||
|
||||
### Phases
|
||||
|
||||
0. **Land the rule + tooling first** (no profile changes): `scripts/assign_filament_ids.py`
|
||||
(mint + insert + `--mint`), the extended `orca_extra_profile_check.py` checks in
|
||||
snapshot-ratchet mode, the C++ validator OFL cross-check, the runtime warning, the rule doc.
|
||||
Generate `filament_id_snapshot.json` (id→families multimap over main) and empty
|
||||
`retired_ids.json` — both checked in.
|
||||
1. **OFL first** (it's the base bundle every vendor resolves against): fix the 16 internal
|
||||
collisions (Elas/eSUN/DREMC copy-pastes get mints; `Generic PETG HF/PETG-CF/PP-CF/PP-GF/
|
||||
PE-CF/PLA Matte @System` get their own family roots+ids instead of collapsing into their
|
||||
parent generic), keeping every current effective id that is unambiguous.
|
||||
2. **Per-vendor PRs, worst-first**: Qidi → Flashforge → Elegoo → Prusa → Cubicon → Anycubic →
|
||||
InfiMech → Snapmaker → the long tail (22 vendors, mostly 1-8 one-line fixes). Each PR flips
|
||||
that vendor into CI's `-f` scope (`check_profiles.yml` currently `-v BBL -f`; append
|
||||
vendors as they reach zero; when all are in, drop `-v` and run tree-wide).
|
||||
3. **Delete the ratchet allowlists** once tree-wide zero holds; checks become hard rules for
|
||||
everything born after the snapshot.
|
||||
|
||||
### Migration-script contract (from the adversarial pass — important)
|
||||
|
||||
- Consumes from the classification only: group membership, fix category, keep-id precedence,
|
||||
inherits-repoint targets. **All replacement id values are recomputed via the mint** — id
|
||||
literals in analysis notes (e.g. `GFA00_02`, `GFS98`, `GFG96`) are legacy-culture artifacts
|
||||
and are ignored with a warning; assert no emitted id matches `^(GF|QD_|P[0-9A-Fa-f]{7}$)`.
|
||||
- **Family-atomic**: re-idding any preset re-ids every same-family sibling in the same commit,
|
||||
even siblings outside the collision group (FlyingBear `GFB99 @S1` vs `@Ghost7`); Prusa is
|
||||
family-atomic per material (its HF/CF families span frozen `_N`-suffix ids — freeze what's
|
||||
unambiguous, mint once per family for the colliding members).
|
||||
- **Diff bound**: a vendor migration PR may only touch collision-group files + same-family
|
||||
siblings of re-idded presets; every id that is per-printer-unambiguous today stays
|
||||
byte-identical.
|
||||
- **Config-equivalence gate**: dump every instantiated preset's flattened effective config on
|
||||
main and on the PR head; the diff must be empty except `filament_id`/`inherits`/
|
||||
`compatible_printers` edits the plan prescribes (this is what makes the Flashforge
|
||||
shadow-file conversions safe: each id-less `fdm_filament_*` shadow becomes a named vendor
|
||||
family root carrying its config byte-for-byte, children re-pointed, then the shadow name
|
||||
retired).
|
||||
- **No deletions**: redundant presets (Flashforge's byte-identical `Generic X`/`Flashforge X`
|
||||
twins) are re-minted, not dropped; consolidation with `renamed_from` is a separate,
|
||||
human-reviewed cleanup.
|
||||
- Expected user impact: none for inheriting user presets, 3mfs, Klipper/Creality/Snapmaker
|
||||
sync. Residue: user *root* presets that copied an old system id keep it forever
|
||||
(AMS auto-match falls back to generic-by-type — low severity, unavoidable from the repo).
|
||||
|
||||
### Vendor-specific notes (from classification)
|
||||
|
||||
- **Qidi (97)**: three profile generations. `QD_*` generics are correct and frozen; the fix is
|
||||
the brand families (Bambu/HATCHBOX/Overture/PolyLite/Tinmorry/QIDI-brand) that all carry
|
||||
`GFB99/GFG99/GFL99`. Multi-root families are the norm (`...@Q2-Series` / `@Q2C-Series` /
|
||||
`@X-Max 4-Series` bases) — same mint lands in every series root of one family.
|
||||
- **Flashforge (69)**: two umbrellas (`FFG01` ~140 presets; `GFB99/GFG99/GFL99` G3U-era) +
|
||||
OFL-riding branded presets + shadow-file conversion (above).
|
||||
- **Elegoo (37)**: single mistake — every commercial variant inherits the material-class
|
||||
`@base` (`E<MAT>B00`); mint one id per product line (Silk/Matte/PRO/Rapid/…), roots exist.
|
||||
- **Prusa (31)**: HF product lines need their own roots; ids move off `fdm_filament_*`
|
||||
templates; frozen name-shaped and `_N` ids stay.
|
||||
- **Sovol (6)**: delete the wrong own-id lines; correct ids flow from OFL by inheritance.
|
||||
- **Cubicon (17)**: `@base` presets are themselves instantiated + over-claiming; 9 file edits.
|
||||
|
||||
---
|
||||
|
||||
## 6. Concrete work items (PR-sized)
|
||||
|
||||
1. `scripts/assign_filament_ids.py` + mint function + tests (incl. the 14-group regression set
|
||||
from the adversarial pass). *(new)*
|
||||
2. `orca_extra_profile_check.py`: checks §3.4-1..6 in ratchet mode + snapshot/ledger files;
|
||||
drop the BBL/OFL-only gate at `:292` and the OFL skip at `:601`. *(extend)*
|
||||
3. C++ validator: OFL-aware `check_duplicate_filament_subtypes`; runtime ambiguity warning at
|
||||
the two `find_if` sites. *(small)*
|
||||
4. Rule documentation: `doc/developer-reference/filament_id.md` (recreate the path; wiki
|
||||
cross-link) + profile-PR template checkbox ("new materials: no filament_id key anywhere; CI
|
||||
prints the minted id"). *(new)*
|
||||
5. OFL migration PR (phase 1).
|
||||
6. Per-vendor migration PRs (phase 2), each widening CI `-f` scope.
|
||||
|
||||
The audit tooling from this analysis (loader-faithful resolver; reproduces the validator
|
||||
1256/1256) is in this session's scratchpad (`audit_filament_ids.py`) and is the natural seed
|
||||
for items 1-2.
|
||||
|
||||
## 7. Evidence & methodology
|
||||
|
||||
- Validator ground truth: `OrcaSlicer_profile_validator -f` tree-wide → 1256 errors; audit
|
||||
script reproduces exactly (356 logical groups after dedup by (vendor, id, preset-set)).
|
||||
- Code analysis: 5 parallel agents over runtime consumers, persistence/migration surface,
|
||||
loader semantics, Bambu grammar, and convention history — all claims carry `file:line`.
|
||||
- Classification: 37 agents (one per vendor chunk) reading actual profile JSONs; 14-sample
|
||||
independent re-derivation found 1 substantive error (a Flashforge group mislabeled
|
||||
`missing_id`; corrected — the loader resolves those ids from OFL).
|
||||
- Design: 3 independent designs → 2 judges (both chose the deterministic mint; scores 58/50/56
|
||||
and 60/54/56) → 3 adversarial attackers (35 scenarios; every `breaks` finding is folded into
|
||||
§3.2-3.4/§5 as an amendment: declared families, multi-root support, ratchet-not-absolute
|
||||
checks, no-deletion rule, shadow-file conversion, classification-id-literal quarantine,
|
||||
diameter siblings, case-insensitive P-hex reservation, fork guidance).
|
||||
- Key history: `OGF*` born 2025-03-31 (`8c4a65e3e1`, no PR); `_##` suffix born PR #9739;
|
||||
8-char check born PR #9574; wiki (with the id-copy-paste example) removed 2025-11-24
|
||||
(`f0d79b99eb`).
|
||||
|
||||
## 8. Open decisions for maintainers
|
||||
|
||||
1. **Id format**: opaque deterministic `OF*` mint (recommended, judges 2/2) vs mnemonic
|
||||
registry grammar (runner-up). Everything else in the plan is format-agnostic.
|
||||
2. **Multi-vendor brands** (Snapmaker ships Fiberon with authentic `GF*` ids): sanction via
|
||||
`shared_catalog` (recommended, low churn) vs hoisting those families into OFL.
|
||||
3. **Benchy-style demo presets**: mint ids per demo preset (recommended) vs teaching the
|
||||
validator `compatible_prints` gating.
|
||||
4. **Alias alignment**: fix the 10 live alias-mismatch OFL duplicates by rename-to-alias
|
||||
(better long-term, needs `renamed_from`) vs minting vendor ids (safer, more ids).
|
||||
5. **Where the rule doc lives**: in-repo `doc/` (recommended — CI messages need a stable link)
|
||||
vs wiki-only.
|
||||
13
task.md
Normal file
13
task.md
Normal file
@@ -0,0 +1,13 @@
|
||||
check commit c2e91cb86ce013dc0486419f21620975c220c3be and it's related PR.
|
||||
currently most of the system profiles didn't follow the Bambu's profiles rule of filemant id.
|
||||
we want to come up a rule for filament id generation for all vendors and a fixing plan for existing system profiles so that there is no ambiguous filament ids for any given printer.
|
||||
|
||||
We have two major goals:
|
||||
### goal 1
|
||||
figure out a strategy or filament id generation rule. we want to follow bambu's rule but they only care about their own profiles while we need to consider generic. and the filament id generation rule should be easy to understand and maintain for not just us but other profiles creators too. either a determistic rule by using script like setting_id rule. or a documented rule so developers can refer when manually creating profiles. and figure out a way to fix migrate/fix existing filament ids in current profiles. note: bambu profiles shouldn't be touch to maintain interoperbitly with their AMS.
|
||||
|
||||
### goal 2
|
||||
in existing system profiles, the ambiguous can caused by different error patterns:
|
||||
1. legit sub type don't have unique filament id due to copy-paste when creating profiles. in this case, we should assign filament unique filament id to it.
|
||||
2. generic and specific filament with legit same filament id adds same printer into it's compatible_printers. in this case we should remove the printer from the generic filament's compatible_printers.
|
||||
3. we need to figure out more error patterns and figure out the fix strategy
|
||||
Reference in New Issue
Block a user