The post-processor stored the LLM's confidence as `_llm_confidence`, but
that value could never be read back: `BaseModelMetadata.from_dict()`
deliberately excludes underscore-prefixed keys from `_unknown_fields` and
`to_dict()` strips private fields, so it was erased by the next metadata
write and was invisible to `read_metadata()`. The enrichment evaluation
harness reads this field to score runs, so confidence was always scored
as blank.
Store it as `llm_confidence`, which round-trips as an ordinary unknown
field — the same mechanism `llm_enriched_at` already relies on. Nothing
else consumed the old name, and the harness still accepts it so sidecars
written by earlier versions keep evaluating.
Covered by a metadata load/save round-trip regression test plus
assertions that the post-processor writes the persisted key and no longer
writes the private one.
Refresh after manual .metadata.json deletion rebuilds the payload without
file_name/size/modified, which are required by BaseModelMetadata.from_dict.
The recreated sidecar then fails to parse and the scanner skips the model.
- load_metadata_payload fills missing file facts from os.stat
- hydrate_model_data restores every missing key from the cache snapshot
only when the sidecar is missing entirely (disk stays authoritative
otherwise), preferring the cached import timestamp for modified
- save_metadata fills file facts on write so no write path can produce
an unparseable sidecar