Skip to content

pkg/health: chart_pinned + declared_coverage signals #1226

Description

@njhensley

Parent: #1224 (Epic: Recipe health tracking, ADR-009 V1)

Summary

Add the two structural signals that are pure reads of the resolved RecipeResult — no external integration — on top of the #1225 package core.

Scope

  • chart_pinned (graded): iterate RecipeResult.ComponentRefs; for every Type == ComponentTypeHelm, require a non-empty Version. Empty → fail. Pure in-repo field check — no Helm render.
    • ADR-006 layer 1 only: this checks the chart version pin, not image digests. Layer-2 image overrides / layer-3 chart-default sub-images need a render and are out of scope. Kustomize defaultTag is also out of scope, so a pure-Kustomize recipe scores chart_pinned as a vacuous pass — note this in the signal's Detail and the matrix header so the column isn't misread as "supply-chain pinned".
  • declared_coverage (descriptor, never graded): from RecipeResult.Validation.{Readiness,Deployment,Performance,Conformance}, record per phase Declared bool, sorted Checks []string, len(Constraints). A minimal recipe (e.g. Slurm dropping K8s checks) must not be penalized.

Key files

pkg/recipe/metadata.go (ComponentRef: Type, Version), pkg/recipe/validation.go (ValidationConfig, ValidationPhase: Checks, Constraints), docs/design/006-image-pinning-policy.md (layer model).

Tests

Unpinned Helm component → fail on chart_pinned; pure-Kustomize recipe → vacuous pass with an explanatory Detail; minimal recipe → pass with sparse declared_coverage, never penalized; Checks emitted sorted.

Acceptance

Both signals computed; chart_pinned is layer-1-only and says so; declared_coverage is descriptive and never moves status.

Dependencies

Depends on #1225. Feeds the rollup; consumed by #1228 and #1229.

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions