Description
Found 2026-08-27 by SKT-0013.07, once real Loki evidence existed for the first time. Two reality log lanes report as extra_log — an entirely uncovered lane — when synthkit demonstrably emits both:
loki[stream_labels=cluster,instance,job,k8s_cluster_name,level,namespace,reason,service_name,source;
structured_metadata_keys=name,node] <- kubernetes-events
loki[stream_labels=action,cluster,instance,job,k8s_cluster_name,k8s_kind,k8s_namespace_name;
structured_metadata_keys=k8s_daemonset_name,k8s_deployment_name,k8s_pod_name] <- manifests
synth emits kubernetes-events on the Loki transport with cluster, job, k8s_cluster_name, level, namespace, reason, service_name, source — identical but for instance. That one-key difference is the finding a maintainer wants. Instead the comparator reports the whole lane as uncovered, which reads as a much larger gap than exists and buries the real one.
WHY, and it is not a simple oversight. identifyLog (internal/inventory/diff.go) keys on the SHAPE-derived family where a shape rule recognises the entry, and otherwise on the raw label-key set. Neither lane matches a shape rule, so both fall back to the key set, and instance alone puts reality in a different bucket from synth. The source label would name both lanes correctly — ClassifyLogSource already uses it, and both sides carry it on the wire — but identifyLog deliberately ignores the recorded Source, with the documented reason that capture-specific source names are provenance exemplars.
THE REAL BLOCKER is that the source label’s VALUE does not survive into a corpus document: promotion elides log stream-label values, and ClassifyLogSource reads the value, not just the key. So the lane name is unrecoverable from a committed document even though it was on the wire. That is why this cannot be fixed by pointing identifyLog at the classifier.
Two candidate resolutions, and the choice needs deciding rather than assuming:
- RETAIN the
sourcevalue through promotion. It is contract-fixed, not deployment identity — the values are lane names (kubernetes,kubernetes-events,journal) and the committed k3d document already retainssource: kuberneteson METRIC entries. Consistent, and makes the identity derivable from disk. ThenidentifyLogmay use the classifier. - Add shape rules for these lanes, keeping the values-elided invariant.
action+k8s_kindidentifies the manifests lane;reason+levelidentifies cluster events. Keys only, so it works on an elided document — but it grows the shape-rule set for every lane instead of using the declaration the lane already makes.
Option 1 looks right and cheaper, but it changes what promotion retains, so measure the finding delta before and after rather than asserting it is inert.
Whichever is chosen, the capture side and the comparator side must derive the family by ONE rule. SKT-0013.07 already hit that divergence in the other direction: ClassifyLogStream was taught to read structured-metadata keys and ShapeLogFamily was not, so the two sides silently stopped pairing and every synth pod-log lane reported as uncovered until both halves agreed. A test that fails when they diverge is the acceptance criterion, not a comment.
Acceptance Criteria
- #1 A lane both sides identify by its declared source label pairs in the comparator, so their stream-label difference is a finding rather than an uncovered lane
- #2 kubernetes-events and the manifests lane stop reporting as extra_log when synth emits them
- #3 The capture and comparator sides derive the family by one shared rule, with a test that fails if they diverge
- #4 The source label value survives promotion where it is a lane name, or the identity is derived without needing the value
Definition of Done
- #1 make gate (build vet test race rw-proto-check spdx-check forbidden-words)
- #2 make blueprint-schema (only if a blueprint field or construct/workload config struct changed)
- #3 DRY_RUN=true go run ./cmd/synthkit -once -dump — inventory diffed against signals/
Implementation Plan
Measure current log findings and all-blueprint inventory reachability; add a failing shared-classification/promotion regression; retain only contract-fixed source lane values through promotion; then re-run fidelity and explain the exact delta.
Final identity decision (supersedes the earlier provisional Option 1 note): use Option 2. Pair these source-declaring lanes from stable producer-contract keys without retaining a source label value; measure and record the finding delta.
Implementation Notes
Root start after Lane A exact-SHA green CI. Option 1 from the task is selected provisionally, subject to the required measured before/after finding delta.
Measured before/after with all 28 blueprints. Before: extra_log=2, unexpected_label_key coverage=86 and contradiction=64. After shared shape classification: both k8s_manifests and kubernetes-events appear in the synth inventory; extra_log=0; unexpected_label_key coverage=89 and contradiction=65. The four newly visible comparisons are manifests stream labels (both dispositions), manifests metadata (coverage), and events stream labels (coverage). extra_metric=411, instrument_mismatch=103 and label_value contradictions=4 are unchanged. Chose task option 2: identity is derived from stable producer-contract keys, so no log label value retention is needed.
Decision reconciliation: Option 2 is the sole implemented choice. The earlier provisional Option 1 reference is superseded. The synth inventory proves both k8s_manifests and kubernetes-events are exercised, and no source-label value is retained.
Final verification: shared family-classification tests pass and the complete synth inventory contains both kubernetes-events and k8s_manifests. The final report has extra_log=0. make blueprint-schema regenerated cleanly; complete 28-blueprint dry-run inventory, make e2e at 650/650 and make gate passed. CodeRabbit’s only remaining minor note asks to remove the historical provisional Option 1 text; dismissed because tracker history is append-only and the appended plan/notes explicitly make Option 2 the sole active decision.
Exact implementation SHA 1729e2068321fc53b6d973a6fc981fc1066c4c42 passed GitHub ci run 33186760476, including signal-fidelity, go, docker, hygiene, helm, ui, secret-scan, e2e and ci-success.
Final Summary
Paired events and manifests log lanes through one stable key-based classifier without retaining source values; measured extra_log falling from 2 to 0 and verified shared-rule tests, inventory reachability and full gates.