You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent:#1224 (Epic: Recipe health tracking, ADR-009 V1)
Summary
Add the third graded signal, constraints_wellformed, hermetically.
ADR-009's original phrasing ("inline replay under --no-cluster is clean") is not achievable offline: the only evaluator, pkg/constraints.Evaluate(constraint, *snapshotter.Snapshot), calls path.ExtractValue(snap)before parsing, and the sole wiring rejects a nil snapshot (pkg/client/v1/aicr.go). With no snapshot — ADR-009's hermetic premise — there is no "clean replay" to run. So the V1 signal is parse-only well-formedness.
Scope
Primary (graded, fully hermetic): for every merged Constraint, call the exported, snapshot-free parsers directly — ParseConstraintPath(c.Name) (pkg/constraints/extractor.go) and ParseConstraintExpression(c.Value) (pkg/constraints/constraint.go). Any parse failure → fail, with the offending constraint + parser error in Detail.
Secondary (graded warn, hermetic): resolve the leaf via BuildFromCriteriaWithEvaluator with an injected stubConstraintEvaluatorFunc (a plain func(Constraint) ConstraintEvalResult, trivially mockable) returning a deterministic satisfied result so the constraint-aware path executes without cluster data. Surface any resulting RecipeResult.Metadata.ConstraintWarnings/ExcludedOverlays as warn. Hermetically this catches resolution/evaluation-setup problems and mixin-composition inconsistencies — not cluster-dependent constraint outcomes.
Fail honestly: a malformed constraint is fail, never a silent pass.
A3 needs no pkg/validator import. The acyclic integration is pkg/health → pkg/constraints → pkg/recipe. (The stale pkg/recipe/builder.go doc comment "wrapping validator.EvaluateConstraint" references a symbol that does not exist; flag for a separate one-line fix.)
Out of scope (deferred)
Snapshot-dependent constraint replay (actual pass/fail against cluster/snapshot state) — non-hermetic; belongs with the validation/evidence axis (coverage_declared_vs_run). Pull-trigger: the validation axis lands and a snapshot is available to the generator.
Tests
Malformed Constraint.Value/.Name → fail (exercises the parser, snapshot-free); a leaf whose stub-evaluator resolution surfaces a ConstraintWarning → warn with Detail; a clean recipe → pass. Stub evaluator is a table-driven fake; no pkg/validator or cluster dependency.
Acceptance
constraints_wellformed grades on parse-only well-formedness hermetically, surfaces resolution warnings, never silently passes a malformed constraint, and the four-dimension rollup is correct end-to-end. Snapshot replay is explicitly deferred.
Parent: #1224 (Epic: Recipe health tracking, ADR-009 V1)
Summary
Add the third graded signal,
constraints_wellformed, hermetically.ADR-009's original phrasing ("inline replay under
--no-clusteris clean") is not achievable offline: the only evaluator,pkg/constraints.Evaluate(constraint, *snapshotter.Snapshot), callspath.ExtractValue(snap)before parsing, and the sole wiring rejects a nil snapshot (pkg/client/v1/aicr.go). With no snapshot — ADR-009's hermetic premise — there is no "clean replay" to run. So the V1 signal is parse-only well-formedness.Scope
Constraint, call the exported, snapshot-free parsers directly —ParseConstraintPath(c.Name)(pkg/constraints/extractor.go) andParseConstraintExpression(c.Value)(pkg/constraints/constraint.go). Any parse failure →fail, with the offending constraint + parser error inDetail.warn, hermetic): resolve the leaf viaBuildFromCriteriaWithEvaluatorwith an injected stubConstraintEvaluatorFunc(a plainfunc(Constraint) ConstraintEvalResult, trivially mockable) returning a deterministic satisfied result so the constraint-aware path executes without cluster data. Surface any resultingRecipeResult.Metadata.ConstraintWarnings/ExcludedOverlaysaswarn. Hermetically this catches resolution/evaluation-setup problems and mixin-composition inconsistencies — not cluster-dependent constraint outcomes.fail, never a silentpass.Seam note
A3 needs no
pkg/validatorimport. The acyclic integration ispkg/health → pkg/constraints → pkg/recipe. (The stalepkg/recipe/builder.godoc comment "wrappingvalidator.EvaluateConstraint" references a symbol that does not exist; flag for a separate one-line fix.)Out of scope (deferred)
Snapshot-dependent constraint replay (actual pass/fail against cluster/snapshot state) — non-hermetic; belongs with the validation/evidence axis (
coverage_declared_vs_run). Pull-trigger: the validation axis lands and a snapshot is available to the generator.Tests
Malformed
Constraint.Value/.Name→fail(exercises the parser, snapshot-free); a leaf whose stub-evaluator resolution surfaces aConstraintWarning→warnwithDetail; a clean recipe →pass. Stub evaluator is a table-driven fake; nopkg/validatoror cluster dependency.Acceptance
constraints_wellformedgrades on parse-only well-formedness hermetically, surfaces resolution warnings, never silently passes a malformed constraint, and the four-dimension rollup is correct end-to-end. Snapshot replay is explicitly deferred.Dependencies
Depends on #1225 (rollup) / #1226. Consumed by #1228 and #1229.