Task · SKT-0013.09

Correct and exercise the k8s_cluster classic Loki pod-log lane

Description

SKT-0013.08 reconciled the six platform-addon Loki pod-log emitters to the captured wire shape through one shared builder, k8saddon.NewLokiPodLogStream. It did not touch the k8s_cluster construct’s own classic Loki lane, buildPodLogStreamsClassic in internal/construct/k8scluster/podlogs.go, which was outside its file ownership.

That lane still diverges from the capture in four ways. Measured against reality-corpus/k8s/k3d-lab.json, the entry with source: k8s_pod_logs and transport: loki:

  1. pod is a STREAM LABEL. On the wire it is structured metadata. This is the defect SKT-0013.08 was filed to fix – every pod restart currently creates a new Loki stream.
  2. service_instance_id is a STREAM LABEL, same mistake, same reason.
  3. detected_level is emitted as a stream label. It is not in the captured set at all.
  4. flags is missing. The captured stream carries it.

It also puts k8s_pod_name in structured metadata, which the capture does not.

The reason this is invisible today, and why the fix has two halves. podLogsMethod returns opentelemetry when a cluster declares pod_logs: true without a method, because that is the k8s-monitoring 4.x chart default. No blueprint in the repository declares pod_logs_method: kubernetes_api or loki. So buildPodLogStreamsClassic never runs, its output never reaches the synth inventory, and make signal-fidelity reports nothing about it – neither a contradiction nor a coverage gap. Verified 2026-08-28: the only loki k8s_pod_logs entry in the synth inventory comes from the addon builder and matches the capture exactly.

So correcting the code alone leaves the same hole open: nothing proves it stays correct. The lane must also be exercised by a blueprint, so the gate compares it on every run.

Decision taken 2026-08-28 (Rob): wire it up and exercise it. Do not delete the lane – podLogsViaLoki is a real documented deployment permutation and SKT-0013.05 recorded that both shapes are real and the difference is the transport.

Route it through the shared builder rather than repairing it in place. Two implementations of one captured contract is how the addon lanes drifted in the first place.

Acceptance Criteria

Definition of Done

Implementation Plan

Lane C: first pin the current classic Loki divergence with a failing test, route the classic lane through the shared k8saddon builder, and return the exact root-owned blueprint wiring needed to exercise it. Root will verify inventory reachability and before/after fidelity findings.

Implementation Notes

Lane C dispatch preflight: EXECUTION route requested as gpt-5.6-luna/max with fork_turns=none; Delegation forbidden. Lane A code base 25e8c040 is exact-SHA green including e2e and ci-success.

Final verification: the classic Loki builder test pins exactly 10 stream-label keys and 2 structured-metadata keys from the captured contract; k8s-logs-events declares pod_logs_method: loki and the complete synth inventory contains the classic k8s_pod_logs lane. The fidelity comparison reports no contradiction for that lane. The OTLP pod-log finding set was identical before and after. Focused pod-log tests, complete 28-blueprint dry-run inventory, make e2e at 650/650 and make gate passed.

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

Routed classic Kubernetes pod logs through the captured shared Loki builder and exercised the lane in a blueprint; exact shape, non-vacuous comparison, unchanged OTLP findings and full gates were verified.

View the source file on GitHub