v3.2: vendor-bundle re-mint under the product-triple rule

Every remaining legacy filament_id outside the BBL/QD_* islands re-derives
from its product triple (filament_vendor / filament_type / family name),
completing the content-addressed id model of filament_id_plan_v3.md:

- Relocation pre-step: 14 fdm_filament_* template forks (Cubicon x3,
  Prusa x6, RH3D x6 minus the pc fork already re-homed) stop declaring
  ids; the 16 presets that rode Prusa's forks now declare the id they
  already resolved (verified zero effective-id drift over all 5892
  instantiated presets).
- --drop-redundant-ids: 6 Custom/MyToolChanger generics drop copied GF
  ids and ride their OFL families.
- --remint over all 62 non-island vendors: 2647 declarations re-derived;
  identical products converge cross-bundle (showcase: PolyLite PLA is now
  OF5CgdDq in OrcaFilamentLibrary, Qidi, OrcaArena and Snapmaker).
- Prusament @XL completions surfaced by the relocation: filament_vendor
  ["Prusa Polymers"] on the 8 @XL declarers; Prusament PA-CF typed
  PA11-CF (the product is Prusament PA11CF) and PC-CF typed PC-CF
  (-CF family typed as base polymer); each family converges on one id.
- Succession: 331 ids retired with mode-rule successors, 355 never-shipped
  v1 mints forgotten with chain splicing, 151 GF-shaped ids released to
  the island space with hints, 27 curated BBL-generic -> OFL-generic
  hints (GFL99 -> OFDSrzZ8 class). New --retire "OLD=NEW" maintenance
  mode records lineage for OGFC99/OGFG99/OGFN99 (the shipped ids of OFL's
  Generic PC/PETG/PA in released versions, whose claims migrated in v3.1
  while Cubicon's inert fork declarations kept them alive).
- Retiring the P-hex system ids removes the last system ids from
  check_ams_filament_valid's destructive P-gate.
- AMS-ambiguity fixes surfaced by convergence (validator -f): 4 presets
  riding another family's id through inherits now declare their true
  family id (Elegoo Generic ASA-CF/PETG-CF, Snapmaker PolyLite Dual PLA /
  PolyLite J1 PLA); 9 Cubicon @base presets and Dremel Generic PLA, which
  duplicate their per-printer variants on the same printers, split onto
  the salt-1 iteration of their triple (sanctioned by the mint-conformance
  check; --remint now leaves salt-conformant declarations alone).

Gates: assign_filament_ids --check 0; orca_extra_profile_check 0;
116 python unit tests; config-equivalence over all 5892 instantiated
presets (byte-identical configs except the 14 sanctioned Prusament
vendor/type corrections; setting_id and compatible_printers unchanged;
per-family convergence and ledger conservation verified); profile
validator base/-f/-r(BBL)/-r(Qidi) all green; libslic3r_tests 48610
assertions; Moonraker OFL generic map check; custom-preset fixture
archives v1.9.0-v2.4.1.
This commit is contained in:
SoftFever
2026-07-04 21:09:29 +08:00
parent e3ac835cc3
commit f7c1b290fd
2663 changed files with 12019 additions and 12498 deletions

View File

@@ -153,6 +153,12 @@ class SyntheticTree:
rc = afi.add_hints(pairs, self.profiles, self.retired)
return rc, buf.getvalue()
def retire(self, pairs):
buf = io.StringIO()
with contextlib.redirect_stdout(buf):
rc = afi.retire_ids(pairs, self.profiles, self.retired)
return rc, buf.getvalue()
def make_clean_tree():
"""Baseline tree: OFL base+generic, a vendor family, a clean tuned generic."""
@@ -1049,6 +1055,65 @@ class TestAddHint(SyntheticTreeCase):
self.assertIn('expects "OLD=NEW"', out)
class TestRetire(SyntheticTreeCase):
def test_retires_vanished_id_with_successor(self):
rc, out = self.t.retire(["OFOLD001=AX01"])
self.assertEqual(rc, 0, out)
self.assertEqual(load_json_file(self.t.retired)["retired"]["OFOLD001"],
{"claims": [], "successor": "AX01"})
errors, out = self.t.check()
self.assertEqual(errors, 0, out)
def test_rejects_live_old(self):
rc, out = self.t.retire(["AX01=OGFL99"])
self.assertEqual(rc, 1)
self.assertIn("still lives in the tree", out)
self.assertEqual(afi.load_ledger(self.t.retired)["retired"], {})
def test_rejects_declaration_only_old(self):
# The inert-fork case: an id declared by a claim-less root still lives
# in the tree; the declaration must be deleted before --retire.
self.t.write_preset("VendorA", preset("ZOLD @base", filament_id="ZDECL01",
instantiation=False,
filament_vendor="ZV",
filament_type="PLA"))
rc, out = self.t.retire(["ZDECL01=AX01"])
self.assertEqual(rc, 1)
self.assertIn("still lives in the tree", out)
def test_rejects_island_space_old(self):
rc, out = self.t.retire(["GFXX99=AX01"])
self.assertEqual(rc, 1)
self.assertIn("reserved id space", out)
def test_rejects_user_space_old(self):
rc, out = self.t.retire(["P1234ABC=AX01"])
self.assertEqual(rc, 1)
self.assertIn("reserved id space", out)
def test_rejects_already_retired_old(self):
self.t.write_ledger(retired={"ROLD": {"claims": [], "successor": None}})
rc, out = self.t.retire(["ROLD=AX01"])
self.assertEqual(rc, 1)
self.assertIn("already retired", out)
def test_rejects_hinted_old(self):
self.t.write_ledger(hints={"HOLD": "AX01"})
rc, out = self.t.retire(["HOLD=AX01"])
self.assertEqual(rc, 1)
self.assertIn("hint key", out)
def test_rejects_dead_successor(self):
rc, out = self.t.retire(["OFOLD001=OFnope99"])
self.assertEqual(rc, 1)
self.assertIn("not a live tree id", out)
def test_rejects_malformed_pair(self):
rc, out = self.t.retire(["OFOLD001"])
self.assertEqual(rc, 1)
self.assertIn('expects "OLD=NEW"', out)
# ---------------------------------------------------------------------------
# default run: mint + insert
# ---------------------------------------------------------------------------
@@ -1261,6 +1326,21 @@ class TestRemint(SyntheticTreeCase):
changed, errors, _out = self.t.remint(["VendorA"])
self.assertEqual((changed, errors), (0, 0))
def test_salted_declaration_survives_remint(self):
# A deliberate salt split (a second preset of one product kept on its
# own id for per-printer AMS disambiguation) is mint-conformant and
# must not be converged back onto salt 0.
salt1 = afi.generate_filament_id(*self.TRIPLE, salt=1)
self.t.write_preset("VendorA", preset("APLA @legacy",
filament_id=salt1,
inherits="APLA @base",
compatible_printers=["P2 0.4 nozzle"]))
changed, errors, out = self.t.remint(["VendorA"])
self.assertEqual(errors, 0, out)
self.assertEqual(changed, 1) # only the non-conformant AX01 root
legacy = load_json_file(self.t.preset_path("VendorA", "APLA @legacy"))
self.assertEqual(legacy["filament_id"], salt1)
def test_same_triple_converges_within_run(self):
self.t.add_vendor("VendorB", [
preset("APLA @Bbase", filament_id="BX01", instantiation=False,