Skip to content

Commit 9ed09df

Browse files
committed
docs(adr): fix sketch union totality; reframe the mechanism amendment
Address review: the amended example broke the union-totality rule this PR introduces — operator-selfdriver owned the nested installer.enabled while operator and csp-managed still drew the top-level install. All three drawn values now own installer.enabled, and the ownedPaths example records the nested path. The mechanism amendment no longer carries the GKE marker rationale (settled separately by value replacement) and instead records the two rules that govern readinessConstraints use: the self-falsifying pre-condition trap (a pre-condition the value's success erases must not be a generation constraint, since those are re-evaluated at validate), and that self-rendered readings (deployed ClusterPolicy fields) are drift checks, not qualification — a value's distinguishing constraint must read cluster state independent of the bundle's own output. Signed-off-by: Atif Mahmood <atif1996@users.noreply.github.com>
1 parent 6de8196 commit 9ed09df

1 file changed

Lines changed: 39 additions & 52 deletions

File tree

docs/design/015-recipe-configuration-profiles.md

Lines changed: 39 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -247,18 +247,15 @@ spec:
247247
componentRefs:
248248
- name: gcp-driver-installer
249249
overrides:
250-
install: false # every value assigns every union path
250+
# every value assigns every union path; nested gate — see the
251+
# amendment on operator-selfdriver below.
252+
installer: {enabled: false}
251253
- name: gpu-operator
252254
overrides:
253255
devicePlugin: {enabled: true}
254256
constraints:
255257
- name: NodeTopology.gpu-nodes.label # requires #1755
256258
value: gke-no-default-nvidia-gpu-device-plugin=true
257-
# Amended 2026-08-22: DD5 symmetry — this value asserts the
258-
# ABSENCE of the installer's ownership marker at readiness.
259-
readinessConstraints:
260-
- name: NodeTopology.gpu-nodes.label
261-
value: "!feature.node.kubernetes.io/gcp-driver-installer"
262259
# GKE-installed driver AND GKE's managed device plugin — a
263260
# default-provisioned GKE cluster (no node label required). The
264261
# declared default: the only value satisfied with zero setup.
@@ -267,7 +264,7 @@ spec:
267264
componentRefs:
268265
- name: gcp-driver-installer
269266
overrides:
270-
install: false
267+
installer: {enabled: false}
271268
- name: gpu-operator
272269
overrides:
273270
devicePlugin: {enabled: false}
@@ -296,13 +293,6 @@ spec:
296293
constraints:
297294
- name: NodeTopology.gpu-nodes.label
298295
value: gke-no-default-nvidia-gpu-device-plugin=true
299-
# Amended 2026-08-22: the DD5 distinguishing signal — a property
300-
# the value's own deployment creates, absent from any
301-
# pre-deployment snapshot — is declared under readinessConstraints
302-
# and evaluated by the validate pre-flight only.
303-
readinessConstraints:
304-
- name: NodeTopology.gpu-nodes.label
305-
value: feature.node.kubernetes.io/gcp-driver-installer=true
306296
```
307297
308298
The GKE declaration lives once in `gke-cos`; accelerator/intent leaves
@@ -530,7 +520,7 @@ to the surviving composition:
530520
# digest, so ordering must be byte-stable
531521
# Post-DD5 state shown; the initial recording is
532522
# gpu-operator: [devicePlugin.enabled, enabled] only.
533-
gcp-driver-installer: [enabled, install]
523+
gcp-driver-installer: [enabled, installer.enabled]
534524
gpu-operator: [devicePlugin.enabled, enabled]
535525
```
536526

@@ -1542,40 +1532,37 @@ work that resolves it.
15421532
**Proposed: identify a durable signal during the value's adoption;
15431533
the `operator` and `csp-managed` values do not wait on it.**
15441534

1545-
*Amended 2026-08-22 (issue #1716).* Two parts land with the value's
1546-
adoption:
1547-
1548-
- **Mechanism.** `ProfileValue` gains `readinessConstraints` — same
1549-
catalog-load validation as `constraints` with per-phase name
1550-
deduplication (the same measurement path may carry a generation
1551-
pre-condition and a readiness post-deployment state — this is
1552-
exactly the DD5 shape, since both signals here are
1553-
`NodeTopology.gpu-nodes.label` readings), routed into
1554-
`spec.validation.readiness.constraints` at resolution and **never
1555-
evaluated at generation time**. This is required for any
1556-
post-deployment signal: generation-time evaluation runs against a
1557-
pre-deployment snapshot in which the signal cannot yet exist, and
1558-
the overlay-level readiness block cannot vary per value. The
1559-
`aicr validate` readiness pre-flight evaluates them with the same
1560-
fail-closed exit as every other readiness gate.
1561-
- **Signal.** GCP-native labels cannot distinguish the two unmanaged
1562-
values: both require identical pool shapes
1563-
(`gpu-driver-version=disabled` + the opt-out label; Google's own
1564-
installer DaemonSet schedules only where
1565-
`cloud.google.com/gke-gpu-driver-version` is absent, so a
1566-
version-labeled pool is unreachable for either). The signal is
1567-
therefore AICR-owned: the `gcp-driver-installer` DaemonSet stamps
1568-
a durable node label after a successful install;
1569-
`operator-selfdriver` asserts it under `readinessConstraints` and
1570-
`operator` (shipped name `driver-installer`) asserts its absence —
1571-
both declarations land together with the value's adoption (the
1572-
sketch above shows the declared shape).
1573-
A further hardening — a generation-time
1574-
`!cloud.google.com/gke-gpu-driver-version` constraint on both
1575-
unmanaged values, converting the documented "opt-out label +
1576-
managed install = driverless pool" misconfiguration into a
1577-
fail-closed recipe error — is DEFERRED: a value may carry one
1578-
constraint per measurement path per phase, and
1579-
`NodeTopology.gpu-nodes.label` is already occupied at generation
1580-
by the pool-label constraint. It requires a conjunction grammar
1581-
for the label form, tracked as follow-up work.
1535+
*Amended 2026-08-24: mechanism only.* `ProfileValue` gains
1536+
`readinessConstraints` — same catalog-load validation as `constraints`
1537+
with per-phase name deduplication (the same measurement path may carry
1538+
a generation-time pre-condition and a readiness-time post-deployment
1539+
state), routed into `spec.validation.readiness.constraints` at
1540+
resolution and **never evaluated at generation time**. The
1541+
`aicr validate` readiness pre-flight evaluates them with the same
1542+
fail-closed exit as every other readiness gate.
1543+
1544+
The mechanism exists for values whose distinguishers are
1545+
deployment-created — where no generation-time reading can hold. Two
1546+
rules govern its use:
1547+
1548+
- **The self-falsifying pre-condition trap.** Generation-time
1549+
constraints are re-evaluated by the validate pre-flight, so a
1550+
pre-condition that the value's own success erases (e.g. "no NVIDIA
1551+
driver loaded" on a value whose operator installs the driver) must
1552+
never be declared as a generation constraint — it fails every
1553+
post-deployment validate on a correctly working cluster. Such state
1554+
belongs in `readinessConstraints`, asserted in its post-deployment
1555+
form.
1556+
- **Self-rendered readings do not qualify.** A reading the selected
1557+
bundle itself renders (e.g. deployed ClusterPolicy fields) is
1558+
satisfied by construction under every value — it is a useful
1559+
rendered-policy **drift check**, but it cannot serve as a value's
1560+
distinguishing constraint. Qualification requires cluster state
1561+
independent of the bundle's own output (provider properties, node
1562+
labels set at provisioning, externally-owned objects).
1563+
1564+
This PR resolves no GKE signal: the GKE family's DD5 question was
1565+
settled separately by value replacement (see the adoption-step
1566+
amendment), and its shipped values are generation-time
1567+
distinguishable. The mechanism's consumers are families whose values
1568+
are distinct cluster shapes with deployment-created distinguishers.

0 commit comments

Comments
 (0)