Description
Diagnosed by SKT-0010.01 lane L12, 2026-08-27, and it is the blocker standing between the gate and CI teeth.
kubernetes_build_info produces five contradictions — build_date, git_commit, git_version, go_version, minor — because the k3d lab records the single observed value for each and thereby asserts it knows the whole value space. It does not: those are one cluster point-in-time identity, and any two clusters differ on them regardless of substrate.
The corpus already has the right encoding for this, and the sibling producer already uses it. values_elided: true means “this label value space is not enumerable from one capture”. The gcx read-back sets it on exactly these labels of exactly this metric. Only the k3d lab does not.
Why this matters more than five rows: it is the last thing that would make the gate fail CI on a version string. Once SKT-0010.05 gives the gate teeth, a k3s patch release or a Go toolchain bump breaks the build for a reason no maintainer can act on — and a gate that fails for unactionable reasons is a gate people learn to ignore.
The alternative that was measured and rejected: declaring provenance.substrate = "eks" on the synth export would also suppress these five, but it was measured to remove 38 contradictions of which 31 are REAL — 24 invented-dimension rows on coredns plus the 7 le-rendering rows — because the substrate filter is document-level and drops both k3d documents whole, taking the entire signals/k8s-addons.md area dark along with the two OTLP-logs coverage-gap findings. Net-negative, so the synth substrate stays undeclared. That decision is recorded and pinned by a test; do not reopen it by declaring a substrate to make these five go away.
Fix in the producer, matching what the gcx producer already does for the same metric.
Acceptance Criteria
- #1 The k3d lab producer elides capture-instance identity values, matching the gcx producer for the same metric
- #2 The five kubernetes_build_info contradictions are gone without a substrate being declared on the synth export
- #3 No real value-space evidence is elided along with the identity values
- #4 The rule for what counts as capture-instance identity is stated, so a future producer applies it consistently
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/
Final Summary
The k3d producer now elides capture-instance identity values on Prometheus build-identity families, and the gate no longer fails on a version string.
THE RULE, stated in the producer so a future one can follow it: on a *_build_info family, the version tuple and build provenance labels carry capture-instance identity — record the key, elide the values. Scoped by the _build_info suffix rather than a metric allow-list, so a newly captured addon build_info family is covered the first time it appears rather than needing someone to remember.
DELIBERATELY RETAINED as real value-space evidence, which is the half that makes this a rule rather than a blunt strip: compiler (gc for every Kubernetes build ever) and git_tree_state (clean for every release build) are fixed by the RELEASE PROCESS, not by the instance; platform, job, namespace, service and source are dimensions of the deployment, not its build. Eliding those would have destroyed genuine evidence to fix a version skew.
Applied in the producer AND to the two committed k3d documents, decoded through the typed corpus envelope so the diff shows the elision rather than a whole-file key reshuffle. Six labels elided in k8s, three in k8s-addons.
Measured: total findings 649 to 644, label_value_contradiction 9 to 4, kubernetes_build_info value contradictions 5 to 0. The delta is EXACTLY those five rows and nothing else, verified by diffing the two reports line by line. The four survivors are all genuine and actionable — created_by_kind and host_network on kube_pod_info, and operation_type on two kubelet families.
The rejected alternative stays rejected and is now pinned by a test: no substrate is declared on the synth export, because that was measured to remove 38 contradictions of which 31 are real.