Skip to content

feat(recipe): shared coordinate mapping + taxonomy spec (TG6)#1409

Merged
njhensley merged 2 commits into
mainfrom
feat/tg6-recipe-coordinate-mapping
Jun 23, 2026
Merged

feat(recipe): shared coordinate mapping + taxonomy spec (TG6)#1409
njhensley merged 2 commits into
mainfrom
feat/tg6-recipe-coordinate-mapping

Conversation

@mchmarny

Copy link
Copy Markdown
Member

Summary

Adds pkg/recipe.CoordinateFor — the canonical, pure recipe→board-coordinate mapping (group=service, dashboard=accelerator-os, tab=intent[-platform]) — plus its golden test and the docs/design/012 taxonomy spec that pins the mapping, stable URL form, column-metadata key schema, and the ADR-009 / #1224 reconciliation.

Motivation / Context

This is TG6 — the Wave 0 linchpin of the evidence-dashboard tracks. Per the epic plan, one shared mapping function gates four workstreams: GP4 (#1404), GP5 (#1405), RQ1 (#1283), and the entire TestGrid track (#1266#1273) all import CoordinateFor rather than re-deriving the coordinate. Landing it first lets those consumers build against a fixed contract instead of a stub.

Scope is deliberately the function + spec. The user-facing docs/user/ TestGrid page is deferred (soft dependency on TG4a's served URL form, which doesn't exist yet), so #1272 stays open after this merges.

Fixes: N/A
Related: #1272 (partial — docs/user page deferred), epic #1263, unblocks #1404 / #1405 / #1283

Type of Change

  • New feature (non-breaking change that adds functionality)
  • Documentation update

Component(s) Affected

  • Recipe engine / data (pkg/recipe)
  • Docs/examples (docs/, examples/)

Implementation Notes

  • CoordinateFor is pure: no clock, no maps, no registry, no I/O — same Criteria always yields the same Coordinate. It consumes already-resolved Criteria and never parses metadata.name (the recipe name is accelerator-first; the coordinate is service-first — they stay independently correct).
  • Fails closed: service/accelerator/os/intent are required; a nil Criteria, empty value, or the "any" wildcard returns ErrCodeInvalidRequest naming the offending dimension. Platform is the only optional sub-segment — dropped when unset, never unknown-substituted.
  • The golden test enumerates the runtime CriteriaRegistry union (not a closed enum), so a new const or --data-contributed value is covered without editing the table.
  • The spec doc reflects the current repo state: pkg/health + docs/user/recipe-health.md have shipped (structural matrix), with the Evidence column a literal pending placeholder today — the coordinate deep-link is what RQ1 will wire.

Testing

make qualify   # passed (exit 0)
go test -race ./pkg/recipe/...          # PASS
golangci-lint run -c .golangci.yaml ./pkg/recipe/...   # 0 issues

Coverage: pkg/recipe/coordinate.goCoordinateFor / Path / String / requireConcrete all 100%; pkg/recipe package total ~86.8% (well above the 75% floor).

Risk Assessment

  • Low — Additive only (one new file + tests + one design doc); no existing code paths touched; pure function, easy to revert.

Rollout notes: N/A — no consumers wired yet; this PR only publishes the contract.

Checklist

  • Tests pass locally (make test with -race)
  • Linter passes (make lint)
  • I did not skip/disable tests to make CI green
  • I added/updated tests for new functionality
  • I updated docs if user-facing behavior changed
  • Changes follow existing patterns in the codebase
  • Commits are cryptographically signed (git commit -S)

Note for the epic author: #1272's body example h100-eks-ubuntu-training → eks/h100-ubuntu/training-kubeflow contradicts its own empty-platform→bare-intent rule (that overlay has no platform). This PR implements the rule — that recipe maps to eks/h100-ubuntu/training — treating the -kubeflow suffix in the example as a typo. Flag if that was intentional.

@mchmarny mchmarny requested a review from a team as a code owner June 22, 2026 20:33
@mchmarny mchmarny added the theme/supply-chain SLSA, SBOM, Sigstore, and provenance verification label Jun 22, 2026
@mchmarny mchmarny self-assigned this Jun 22, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e36251f1-5736-40b2-a684-ccf1342c8c70

📥 Commits

Reviewing files that changed from the base of the PR and between 54c4447 and 820eef3.

📒 Files selected for processing (3)
  • docs/design/012-recipe-coordinate-mapping.md
  • pkg/recipe/coordinate.go
  • pkg/recipe/coordinate_test.go

📝 Walkthrough

Walkthrough

A new ADR (docs/design/012-recipe-coordinate-mapping.md) defines the canonical recipe-to-board-coordinate mapping contract, specifying group/dashboard/tab taxonomy, fail-closed validation rules, the optional platform suffix behavior, a stable URL format, the started.json column-metadata key schema (7 snake_case keys), reconciliation with ADR-009 via metadata.name, and the cross-link contract for recipe-health Evidence. The Go implementation in pkg/recipe/coordinate.go adds the Coordinate struct, its Path()/String() methods, the CoordinateFor(*Criteria) function, and the requireConcrete and rejectPathSeparator helpers. A new test file covers specific-input formatting, format locking, error naming, and a full registry cross-product.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: introduction of a shared coordinate mapping function and taxonomy specification for the recipe engine.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering motivation, implementation details, testing, and risk assessment.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/tg6-recipe-coordinate-mapping

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/design/012-recipe-coordinate-mapping.md`:
- Around line 125-127: The fenced code block containing the path template
`<group>/<dashboard>/<tab>` is missing a language identifier on the opening
fence marks, which causes markdownlint MD040 to trigger. Add a language
identifier such as `text` to the opening backticks of the code block to resolve
the linting error and keep the documentation lint-clean.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: fc6dd4aa-9a89-4702-9ff1-9f3aac9dcf58

📥 Commits

Reviewing files that changed from the base of the PR and between 7f7ae67 and fc95522.

📒 Files selected for processing (3)
  • docs/design/012-recipe-coordinate-mapping.md
  • pkg/recipe/coordinate.go
  • pkg/recipe/coordinate_test.go

Comment thread docs/design/012-recipe-coordinate-mapping.md Outdated
@mchmarny mchmarny requested a review from njhensley June 22, 2026 20:41
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Coverage Report ✅

Metric Value
Coverage 77.3%
Threshold 75%
Status Pass
Coverage Badge
![Coverage](https://img.shields.io/badge/coverage-77.3%25-green)

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
github.com/NVIDIA/aicr/pkg/recipe 86.84% (+0.66%) 👍

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/NVIDIA/aicr/pkg/recipe/coordinate.go 100.00% (+100.00%) 28 (+28) 28 (+28) 0 🌟

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

@mchmarny mchmarny force-pushed the feat/tg6-recipe-coordinate-mapping branch from fc95522 to 54c4447 Compare June 22, 2026 21:10

@njhensley njhensley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multi-persona review + senior-engineer meta-review

Reviewed by four independent personas (correctness, API-contract, docs, test), then adjudicated by a senior-engineer meta-review that calibrated severity to this PR's additive, contract-publishing scope (no consumers wired yet).

TL;DR — no blockers. Clean, pure, well-tested function. The personas converged on one real defect: the coordinate string is provably not round-trippable (rtx-pro-6000 and --data values collide with the -// delimiters). But since nothing parses Path() yet, that is a High-priority design issue to resolve with the first parsing consumer (RQ1/TG4a) — not a merge blocker. Deep-links and the presence endpoint only need the string stable and equal, not decomposable.

Recommendation: merge-with-changes (minimal) + tracked follow-ups.

  • Fold into this PR (cheap, contract-strengthening): the / charset guard, the dead-filter test cleanup, the ## Status line, and rewording the 7-key schema as "specified here, enforced by TG2."
  • Block on the first consumer issue (cross-linked from ADR-012): the round-trippability fix / ParseCoordinate / delimiter invariant — so no string-splitting consumer can land before parseability is settled.

Inline comments below, tiered High → Nitpick. One persona finding was dismissed: "the Coordinate struct omits the metadata.name join key" — the ADR deliberately keeps name (identity) off Coordinate (placement) since the caller holds both; that's a correct design choice.

Comment thread pkg/recipe/coordinate.go
// host/navigation scheme built around this path is owned by the
// consumer (GP5/TG4a); this package only emits the canonical segments.
func (co Coordinate) Path() string {
return co.Group + "/" + co.Dashboard + "/" + co.Tab

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[High] Path() is not round-trippable, but ADR-012 markets it as the parseable "stable URL form."

Dashboard = accelerator + "-" + os joins two free-form fields with -, and CriteriaAcceleratorRTXPro6000 = "rtx-pro-6000" (criteria.go:121) already contains hyphens. So eks/rtx-pro-6000-ubuntu/training has no positional split point — a consumer cannot recover (rtx-pro-6000, ubuntu) vs (rtx, pro-6000-ubuntu). ADR §"Stable URL form" says RQ1 deep-links to and TG4a's presence endpoint checks this string.

Not a blocker for this PR — nothing parses Path() yet; deep-links/presence checks only need it stable+equal, not decomposable. Recommend: track on the first parsing consumer (RQ1 #1283 / TG4a #1284) — ship an explicit ParseCoordinate, or keep consumers on the struct fields rather than string-splitting. Add an ADR note that Path() is a stable opaque identity, not a decomposable key, until then.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documented (820eef3). Added an ADR note under "Stable URL form": `Path()` is a stable opaque identity, not a decomposable key — `rtx-pro-6000` already carries the join char, so consumers compare/deep-link the string but address dimensions via the `Coordinate` struct fields, never by splitting. An explicit `ParseCoordinate` (with a "values must not contain the active delimiter" invariant) is deferred to the first parsing consumer (RQ1 #1283 / TG4a #1284).

Comment thread pkg/recipe/coordinate.go
// non-wildcard) dimension, or an ErrCodeInvalidRequest naming dim when it
// is empty or the "any" wildcard.
func requireConcrete(dim, value string) (string, error) {
if value == "" || value == CriteriaAnyValue {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[High] No charset guard → a / in a value silently breaks the segment count.

requireConcrete rejects only empty/"any". Registry values admitted via --data are merely lowercased/trimmed (no charset validation), so a service value like acme/ncp yields acme/ncp/h100-ubuntu/training — a 4-segment path that any positional / split mis-parses. That is exactly the "ambiguous placement / silent fusion" the ADR claims to prevent.

This one is cheap and self-contained — reasonable to fold into this PR: reject values containing / (and arguably - in the joined fields), failing closed with ErrCodeInvalidRequest naming the dimension, plus a negative test.

[Low, same spot] value == CriteriaAnyValue compares to the literal "any" without trim/lowercase, so "ANY"/" any " from a hand-built (unnormalized) Criteria would pass as concrete. Only reachable if a caller bypasses the resolve path — either normalize here or document that CoordinateFor assumes resolved input.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folded in (820eef3). `requireConcrete` now routes through a new `rejectPathSeparator`, so service/accelerator/os/intent and platform fail closed with `ErrCodeInvalidRequest` naming the dimension when a value contains `/`. Added negative cases (`service contains slash`, `platform contains slash`). On the [Low]: left as-is — the function documents its input as already-resolved `Criteria`, and normalizing `"any"`/case here would duplicate the resolve path; the resolved-input assumption is stated in the doc comment.

func TestCoordinateForRegistryUnionConcrete(t *testing.T) {
r := NewCriteriaRegistry()

services := concreteValues(r.AllServiceTypes())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[High] The registry-union test never actually exercises the registry-driven fail-closed path.

concreteValues() strips "any", but NewCriteriaRegistry() is empty and the static Get*Types() lists never contain "any" — so the filter removes a token that is never present, and no wildcard ever reaches CoordinateFor through this test. If concreteValues were removed or a --data registry ever surfaced "any", this test would still pass.

Fail-closed is covered by the literal cases in TestCoordinateFor (nil + each dimension any), so this is dead-code/clarity rather than a true coverage hole. Recommend: either feed an explicit "any"/empty into the loop and assert it fails closed, or drop the dead filter with a comment pointing at the literal cases that own that coverage.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed (820eef3). Added an explicit assertion that a wildcard service fails closed through the registry-driven path, plus a comment noting `concreteValues` is defensive against a `--data`-seeded registry surfacing `"any"` and that the literal per-dimension cases in `TestCoordinateFor` own the rest of that coverage.

Comment thread pkg/recipe/coordinate.go
}

tab := intent
if platform := string(c.Platform); platform != "" && platform != CriteriaAnyValue {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Medium] tab = intent-platform round-trips only by the unenforced accident that intents are hyphen-free.

Splitting training-kubeflow back to (training, kubeflow) works only because today's intents (training, inference) contain no -. A future/--data intent like fine-tuning would make fine-tuning-kubeflow un-splittable. Same delimiter family as the Path() issue above — the structural-parsing fix covers it. Recommend: add an explicit ADR invariant: "dimension values must not contain the active delimiter."

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Covered by the same opaque-identity note (820eef3): the ADR now states values may contain `-` (`rtx-pro-6000`, a future `fine-tuning` intent), so the tab is not `-`-decomposable, and the delimiter invariant is deferred to `ParseCoordinate`. Only `/` is enforced now, since it is the one char that changes the segment count.

the recipe.
- `signer_identity` + `signer_issuer` together key the **latest-per-signer**
default scope referenced in the k8s-in-column countermeasure.
- The key strings and their count (7) are the contract: TG2 emits exactly these;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Medium] The 7-key started.json schema is declared as a binding contract but is prose-only — nothing enforces it.

"TG2 emits exactly these; TG3 reads exactly these" reads as a frozen ABI, yet no Go constant/struct/test pins the key names, order, or count. A typo or reorder on either side drifts silently — the same anti-drift failure the ADR's Problem section warns against, now in the half of the contract that isn't code. Deferring the emitter to TG2 (#1267) is fine, but reword to: "specified here, enforced by TG2," rather than implying it is pinned in code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded (820eef3): "specified here and enforced by TG2 (#1267)" — and added that no Go constant pins the names today, so TG2 must lock the key names/order/count in a shared constant + round-trip test when it lands, rather than relying on the prose.

@@ -0,0 +1,232 @@
# ADR-012: Recipe → Board-Coordinate Mapping

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Low] Missing ## Status section. 7 of 8 prior ADRs (002–005, 007–009) open with a ## Status. Add ## Status: Accepted (or Proposed) so consumers importing this contract know whether the mapping is ratified.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added `## Status: Accepted` (820eef3).

name: "eks h100 ubuntu training kubeflow",
c: &Criteria{Service: CriteriaServiceEKS, Accelerator: CriteriaAcceleratorH100,
OS: CriteriaOSUbuntu, Intent: CriteriaIntentTraining, Platform: CriteriaPlatformKubeflow},
want: "eks/h100-ubuntu/training-kubeflow",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Low] No format-lock golden test independent of the fixtures. The canonical string is only asserted via the table's want fields; a refactor that changes the delimiter in both Path() and these want strings stays green while breaking the five downstream consumers that hardcode <group>/<dashboard>/<tab>. Consider one standalone Path() == "eks/h100-ubuntu/training-kubeflow" assertion explicitly framed as "this exact string must never change."

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added `TestCoordinatePathFormatLock` (820eef3) — a standalone assertion that `Path()` equals `eks/h100-ubuntu/training-kubeflow`, framed as a frozen contract string that must fail even if the table want-strings change in lockstep.

t.Fatalf("err = %v, wantErr %v", err, tt.wantErr)
}
if tt.wantErr {
if !stderrors.Is(err, errors.New(errors.ErrCodeInvalidRequest, "")) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Low] Negative cases assert the error code but not that the message names the offending dimension — which both the code comment and ADR explicitly promise ("naming the offending dimension"). A refactor dropping the dim name from the message (e.g. a generic "dimension must be concrete") still passes. Add a substring assertion on the dimension name in one negative case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added `TestCoordinateForErrorNamesDimension` (820eef3) — asserts the failure message contains `accelerator` for an `any`-accelerator input.

- The API and UI that render the board (GP5).
- The live board / hosting / navigation host.
- The user-facing `docs/user/` TestGrid page. It is **deferred**: it has a soft
dependency on TG4a's served URL form, so it is not authored here. **#1272 stays

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Nitpick] Durable ADR embeds transient issue-lifecycle state ("#1272 stays open until that user-facing page lands"). Once #1272 closes, the ADR still asserts it's open. Keep the design record timeless and let the issue tracker own lifecycle — consistent with the repo's "don't reference transient state in durable artifacts" guidance.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reworded (820eef3) to drop the issue-lifecycle state — the deferred page is now described as "authored alongside that work rather than here," leaving #1272 lifecycle to the tracker.

Add pkg/recipe.CoordinateFor — the canonical, pure recipe→board-coordinate mapping (group=service, dashboard=accelerator-os, tab=intent[-platform]) that GP4/GP5/RQ1 and the TestGrid track import instead of re-deriving. Required dimensions fail closed on empty, "any", or a "/" path separator; platform is the only optional segment. Includes golden, format-lock, and CriteriaRegistry-union tests, plus ADR-012 documenting the taxonomy, opaque-identity URL form, pinned column-metadata schema, and ADR-009/#1224 reconciliation.
@mchmarny mchmarny force-pushed the feat/tg6-recipe-coordinate-mapping branch from 54c4447 to 820eef3 Compare June 22, 2026 21:29
@njhensley

Copy link
Copy Markdown
Member

Re-review — feedback addressed ✅

Re-reviewed at 820eef35. All 9 inline findings from the prior review are resolved; I ran go test ./pkg/recipe/... -run Coordinate -v against the updated code — all pass, including the new negative/contract tests.

# Finding Resolution
High 1 Path() not round-trippable, marketed as parseable ADR now has a dedicated "Path() is a stable opaque identity, not a decomposable key" section — spells out the rtx-pro-6000 ambiguity, directs consumers to the struct fields (never string-split), and defers ParseCoordinate + the delimiter invariant to RQ1 #1283 / TG4a #1284
High 2 No / charset guard on --data values Added rejectPathSeparator, applied to all four required dims and platform; fails closed naming the dimension
High 3 Registry-union test never fed a wildcard Added an explicit wildcard-service CoordinateFor assertion that must fail closed, with a comment pointing at the literal cases that own the rest
Med 4 7-key schema declared binding but prose-only Reworded to "specified here and enforced by TG2"; notes no Go constant pins it today and that TG2 must lock names/order/count + round-trip test
Med 5 intent-platform delimiter invariant unenforced Folded into the opaque-identity section + the deferred "values must not contain the active delimiter" invariant
Low 6 Missing ## Status Added ## Status: Accepted
Low 8 No format-lock golden test Added TestCoordinatePathFormatLock (frozen-string assertion independent of fixtures)
Low 9 Negative tests didn't assert dimension name Added TestCoordinateForErrorNamesDimension
Nit 10 ADR embedded issue-lifecycle state "#1272 stays open until…" reworded to "authored alongside that work rather than here"

One optional item intentionally left (Low, from the High-2 comment): requireConcrete still compares to the literal "any" without trim/lowercase. It's only reachable via a hand-built unnormalized Criteria, so defense-in-depth — fine to leave or document as "assumes resolved input."

LGTM — the cheap contract-strengthening fixes landed in this PR and the round-trippability work is correctly deferred and cross-linked to the first parsing consumer. No remaining blockers.

@njhensley njhensley enabled auto-merge (squash) June 23, 2026 01:12
@njhensley njhensley merged commit a1b6e20 into main Jun 23, 2026
33 checks passed
@njhensley njhensley deleted the feat/tg6-recipe-coordinate-mapping branch June 23, 2026 01:21
srao-nv added a commit that referenced this pull request Jun 24, 2026
PR #1409 (feat(recipe): shared coordinate mapping) is now merged.
Replace the local coordinate.go implementation with a thin wrapper that
delegates to recipe.CoordinateFor(*recipe.Criteria).

RecipeCriteria is retained for the testgrid-specific K8sVersion and
K8sConstraint fields which have no equivalent in recipe.Criteria.
toRecipeCriteria() converts between the two for the coordinate call.

The /"-in-dimension rejection guard added by pkg/recipe is now applied
automatically; existing tests are unchanged since all test values are
slash-free.
srao-nv added a commit that referenced this pull request Jun 25, 2026
PR #1409 (feat(recipe): shared coordinate mapping) is now merged.
Replace the local coordinate.go implementation with a thin wrapper that
delegates to recipe.CoordinateFor(*recipe.Criteria).

RecipeCriteria is retained for the testgrid-specific K8sVersion and
K8sConstraint fields which have no equivalent in recipe.Criteria.
toRecipeCriteria() converts between the two for the coordinate call.

The /"-in-dimension rejection guard added by pkg/recipe is now applied
automatically; existing tests are unchanged since all test values are
slash-free.
srao-nv added a commit that referenced this pull request Jun 25, 2026
PR #1409 (feat(recipe): shared coordinate mapping) is now merged.
Replace the local coordinate.go implementation with a thin wrapper that
delegates to recipe.CoordinateFor(*recipe.Criteria).

RecipeCriteria is retained for the testgrid-specific K8sVersion and
K8sConstraint fields which have no equivalent in recipe.Criteria.
toRecipeCriteria() converts between the two for the coordinate call.

The /"-in-dimension rejection guard added by pkg/recipe is now applied
automatically; existing tests are unchanged since all test values are
slash-free.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs size/XL theme/supply-chain SLSA, SBOM, Sigstore, and provenance verification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants