New CODEMAPS/container-extra-json.md documents the contract every
source plugin must follow when reading or writing containers.extra_json.
Closes the open architectural question that was tracked in
WORKLOAD_REFACTOR_TODO.md.
Covers:
- Schema position (column default, four write-path normalization
sites) and ownership model (per-source row keys, current writers).
- Reader rules: tolerate unknown keys via default json.Unmarshal,
tolerate decode failure where first-class columns suffice.
- Writer patterns: wholesale-overwrite (image source, single-writer
short-lived rows) vs preserve-unknown-keys (static source, RMW with
generic-map round-trip). Preserve-unknown-keys is the recommended
default for new sources.
- Concurrency: SetMaxOpenConns(1) + WAL gives atomic per-row writes
and consistent reader snapshots, but does NOT serialize multi-
goroutine RMW — a per-workload sync.Mutex is required for that
(fenced by TestSaveState_ConcurrentWritesDoNotLoseUpdates).
- What extra_json is NOT for (workload config, cross-source state,
queryable data, secrets) and a checklist for adding a new field.
- Pointers to every example in tree: image's containerExtra writer/
reader, static's saveState round-trip, workload_runtime.go's
decode-and-tolerate consumer.
WORKLOAD_REFACTOR_TODO Container.extra_json question flipped to DONE.
CODEMAPS/INDEX bumped + entry linked.
Reviewer pass (code-reviewer subagent) caught one HIGH factual error
(wrong cross-source consumer claim) and several MEDIUM/LOW drifts;
all addressed inline before commit.