Skip to content

Commit d10c5fb

Browse files
committed
docs(recipe): document joint sufficiency, replacing the OS-guard section
Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
1 parent e5cb762 commit d10c5fb

1 file changed

Lines changed: 38 additions & 8 deletions

File tree

docs/contributor/recipe.md

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,44 @@ on any overlay are rejected at load time (`ErrCodeInvalidRequest`) to
476476
prevent silent match-all behaviour; operators must remove or zero that
477477
field before upgrading.
478478

479-
**Composition with the OS guard.** `requireOSIfNeeded` (the joint
480-
service+accelerator OS gate) is a separate, pre-existing check and runs
481-
*first*, before the merge. It is **not subsumed** by the coverage
482-
post-condition: coverage is satisfied when service and accelerator are each
483-
honored by *some* overlay independently, while the OS guard demands *one*
484-
overlay carry both service and accelerator together before it will consider
485-
the OS-agnostic tier served. Both checks apply; a request can trip either
486-
one independently.
479+
**Joint sufficiency.** Per-dimension coverage is necessary but not
480+
sufficient. It is satisfied when `service` and `accelerator` are each honored
481+
by *some* overlay independently, even when no single overlay carries the
482+
combination and the combination's content lives only on an OS-gated leaf. The
483+
caller then receives a recipe that silently never applied it.
484+
`verifyCriteriaCoverage` therefore also enforces a second condition
485+
(issue #1782): resolution fails when **no applied overlay jointly carries
486+
every stated dimension** *and* stating a strict dimension would reach an
487+
overlay currently being skipped.
488+
489+
Both halves matter. The first is the escape hatch that keeps the generic tier
490+
valid: `--service eks` resolves through `eks.yaml`, which carries the whole
491+
stated combination, and is never asked for an OS. The second is what detects
492+
the loss.
493+
494+
`os` is the only **strict** dimension, and `coverage.go` records why. Every
495+
other dimension degrades to a smaller but coherent recipe when omitted: no
496+
`--platform` yields no Slurm or Kubeflow layer, no `--intent` yields untuned
497+
GPU Operator values. `os` decides whether the driver can be installed at all.
498+
On Ubuntu the GPU Operator installs it, so an OS-agnostic recipe is a real
499+
answer and `eks.yaml` carries no `os`; on COS the operator installs no driver
500+
and the device-plugin owner differs, which is why every `gke` overlay is
501+
OS-gated and no OS-agnostic GKE recipe exists to return. That is a property of
502+
installing NVIDIA drivers on Linux rather than of this catalog's shape, so it
503+
holds for external `--data` catalogs too.
504+
505+
This condition replaced the `requireOSIfNeeded` guard, which ran before the
506+
merge and hardcoded three separate scopes: it only fired when `service` was
507+
stated, only compared `service`+`accelerator` regardless of what the caller
508+
asked for, and only ever demanded `os`. Only the last survives.
509+
`coverage_subsumption_test.go` keeps the retired guard as a test-only oracle
510+
and asserts over generated catalogs that every query it would have rejected is
511+
still rejected.
512+
513+
A joint-sufficiency failure carries `details.strictDimensions`, **not**
514+
`details.uncovered`. The distinction is load-bearing: `pkg/client/v1`
515+
relaxation clears uncovered dimensions and retries, which here would discard
516+
the check and return the partial recipe that #1542 fixed.
487517

488518
**Evaluator error classification is fail-closed.** During constraint
489519
evaluation on the snapshot-driven path, `ErrCodeNotFound` (the evaluator's

0 commit comments

Comments
 (0)