An archive's filament_color was parsed verbatim from the print job's
3MF (filament_colour in project_settings.config) — the slicer's
filament-slot colour, which a user picks independently of the exact
hex they curate on the Bambuddy inventory spool. So a print from a
#000000 inventory spool showed #161616 (the slicer's near-black) in
the archive card and the Color Distribution graph, even though usage
tracking correctly decremented the right spool.
Once usage tracking has resolved the print's filament slots to
inventory spools, the spool colours are authoritative. _track_from_3mf
(built-in inventory) and report_usage (Spoolman mode) now overwrite
the archive's filament_color with the slot-ordered, de-duplicated
colours of the matched spools.
The rewrite is all-or-nothing: it only applies when every used slot
resolved to a spool carrying a colour, so a partially-mapped
multi-colour print keeps the 3MF colour rather than silently dropping
the unmatched slots.
Shipped for both inventory modes: built-in spools read Spool.rgba,
Spoolman spools read the spool's filament.color_hex (fetched via
get_spool for tag-less slot-assignment matches). New helpers
_spool_color_to_hex / _archive_colors_from_spools in usage_tracker.py,
reused by spoolman_tracking.py via _apply_spool_colors_to_archive.
Tests: 12 new in test_usage_tracker.py (hex normalisation, the
all-or-nothing rule across single/multi/partial/no-colour/AMS-fallback
cases, end-to-end rewrite), 4 in test_spoolman_tracking.py (Spoolman
rewrite + empty/partial/missing-archive no-ops). 70 tracking tests
green; backend ruff clean.