Task · SKT-0015.06

high_dpm is inert: correct the floor rule so a default-cadence construct is sped up

Description

SKT-0015.04 changed instanceMetricInterval to if iv < floor { return floor }; return iv. With high_dpm.metric_interval: 10s and a construct declaring 60s, 60s < 10s is false, so the construct keeps 60s. Every one of the 25 Interval() implementations in the catalogue returns exactly 60 * time.Second, so nothing in the repository can be sped up by high_dpm any more. The feature is inert.

Measured 2026-08-28 on main at 69232b1:

DRY_RUN=true BLUEPRINT_NAMES=high-dpm-churn go run ./cmd/synthkit -once
runner: blueprint "high-dpm-churn" high-DPM projection: metric_instances=1
  metric_interval=10s projected_series=690 projected_dpm=690 dpm_per_series=1

dpm_per_series=1 is the tell: the blueprint declares a 10s interval and the runtime resolves 1 data point per minute.

How the acceptance criteria passed anyway, which is the more important lesson. SKT-0015.04 AC#5 was “the projected DPM for high-dpm-churn is unchanged, proving the refactor is behaviour-preserving today”. 690 did stay 690 – because projected_series rose from 115 to 690 as dpm_per_series fell from 6 to 1. The one number chosen to prove safety was the product of the two that inverted. An invariant that survives the bug it was chosen to catch is worse than no invariant.

The root cause is the specification, not the implementation. SKT-0015.04 was written with the rule effective = max(declared_instance_interval, blueprint_floor). That is a correct reading of “floor” as a minimum interval, and it is a no-op precisely because every construct already sits at the old floor value.

Decision taken 2026-08-28 (Rob): a construct sitting at 60s was never making a choice – 60s IS the MinMetricInterval default – so high_dpm speeds it up. A construct declaring anything longer than 60s is making a real statement about its poll rate and keeps it.

if iv <= r.opts.MinMetricInterval { return floor }
return iv

60s  construct + 10s high_dpm -> 10s   (sped up)
300s construct + 10s high_dpm -> 300s  (kept)

projectHighDPMCost must be corrected with it: it should report dpm_per_series=6 and projected_series=115 for high-dpm-churn, matching what the blueprint metadata and the docs already claim.

Documentation currently contradicts the code and must be reconciled in the same change. docs/blueprints.md:19 and docs/troubleshooting.md:88 both state “115 series at 6 DPM per series, or 690 data points per minute”. The blueprint’s own header comment and metadata.description were rewritten to describe the inert behaviour instead. One of those is right; after this fix it is the docs.

Acceptance Criteria

Definition of Done

Implementation Plan

  1. Change the runner tests first so they directly assert a MinMetricInterval-default instance resolves to the high_dpm interval, an explicit 300s fixture remains unchanged, and the cost projection reports the resulting per-series rate and series count; run them red against the current floor rule. 2. Implement Rob’s frozen resolver rule: metric-bearing instances at or below MinMetricInterval use the high_dpm interval, while longer declarations retain their cadence. 3. Reconcile high-dpm-churn header and metadata with the runtime’s 115-series, 6-DPM projection and validate the exact startup log. 4. Run focused tests, CodeRabbit, make gate, the meaningful dry-run inventory check, then exact-SHA CI before finalization.

Implementation Notes

TDD evidence: the revised tests failed before the resolver change because the default-cadence instance remained at 60s and the projection stayed at 690 series x 1 DPM; the direct default-cadence test returned 60s instead of 10s. After applying the frozen rule, focused runner tests pass, including a fake metric construct declaring 300s that remains at 300s. A real DRY_RUN startup for high-dpm-churn reported metric_instances=1, metric_interval=10s, projected_series=115, projected_dpm=690, dpm_per_series=6. The blueprint header and metadata now match the already-correct docs. CodeRabbit reviewed all four changed files and raised 0 issues. make gate passed, and the blueprint-specific -once -dump emitted 39 documented network-topology metric families plus the declared Loki stream. make blueprint-schema is not applicable because no blueprint field or construct/workload config struct changed.

Exact-SHA CI run 33212665892 at commit 415f0d6f3026835f823f6fd986d429fa77219b1e passed all required jobs on attempt 2, including e2e and ci-success. Attempt 1 had one connection reset in the Lane A OTLP-log Docker readiness test immediately after the port wait and before the control-server startup log; the same exact test passed locally on this tree and in the exact-SHA rerun, with no code change, so it was recorded as a non-reproducing startup race rather than folded into this task. DOD #2 remains unchecked and is not applicable.

Final Summary

Activated high_dpm for default-cadence metric instances while preserving explicitly slower intervals. Direct tests pin 60s -> 10s and 300s -> 300s; the real high-dpm-churn startup projection is 115 series x 6 DPM = 690 data points per minute, matching its header, metadata, and operator docs. Verified with red/green TDD, zero-issue CodeRabbit review, make gate, blueprint-specific inventory dump, targeted Docker e2e, and exact-SHA CI run 33212665892.

View the source file on GitHub