Skip to content

Commit d675d79

Browse files
committed
feat(release): surface validated Brev image evidence
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
1 parent 06ac446 commit d675d79

14 files changed

Lines changed: 844 additions & 182 deletions

File tree

.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md

Lines changed: 125 additions & 24 deletions
Large diffs are not rendered by default.

.agents/skills/nemoclaw-maintainer-cut-release-tag/scripts/release-e2e-evidence.mts

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ export type ReleaseE2ePreflight = {
2727
candidateSha: string;
2828
dispatches: {
2929
completeRun: {
30-
includeStagingBrevLaunchable: true;
30+
includeStagingBrevLaunchable: false;
3131
jobs: "";
32-
mode: "full";
32+
mode: "ordinary";
3333
targets: "";
3434
};
3535
};
@@ -156,24 +156,18 @@ function validateDispatchIdentity(
156156
): string {
157157
requireEqual(dispatch.candidateSha, candidateSha, `${label}.candidateSha`);
158158
const kind = stringField(dispatch, "kind", label);
159-
if (kind === "nemoclaw-e2e-dispatch-v1") return candidateSha;
160159
if (kind !== "nemoclaw-e2e-dispatch-v2") {
161-
throw new Error(
162-
`${label}.kind must equal "nemoclaw-e2e-dispatch-v1" or "nemoclaw-e2e-dispatch-v2"`,
163-
);
160+
throw new Error(`${label}.kind must equal "nemoclaw-e2e-dispatch-v2"`);
164161
}
165162

166163
requireEqual(dispatch.repository, "NVIDIA/NemoClaw", `${label}.repository`);
167164
const candidateRepository = requireRepository(dispatch, "candidateRepository", label);
168165
const baseSha = requireSha(dispatch, "baseSha", label);
169166
const workflowSha = requireSha(dispatch, "workflowSha", label);
170-
if (dispatch.prNumber === null) {
171-
requireEqual(candidateRepository, "NVIDIA/NemoClaw", `${label}.candidateRepository`);
172-
requireEqual(baseSha, candidateSha, `${label}.baseSha`);
173-
requireEqual(workflowSha, candidateSha, `${label}.workflowSha`);
174-
} else {
175-
numberField(dispatch, "prNumber", label);
176-
}
167+
requireEqual(dispatch.prNumber, null, `${label}.prNumber`);
168+
requireEqual(candidateRepository, "NVIDIA/NemoClaw", `${label}.candidateRepository`);
169+
requireEqual(baseSha, candidateSha, `${label}.baseSha`);
170+
requireEqual(workflowSha, candidateSha, `${label}.workflowSha`);
177171
return workflowSha;
178172
}
179173

@@ -352,9 +346,17 @@ export function buildReleaseE2ePreflight(input: {
352346
const inventory = readFreeStandingJobsInventory(workflowPath);
353347
const plan = input.plan ?? buildE2eWorkflowPlan();
354348
const pathExists = input.candidatePathExists ?? candidatePathExists;
355-
const defaultJobIds = inventory.workflowJobs.filter(
349+
const workflowJobIds = inventory.workflowJobs.filter(
356350
(jobId) => jobId !== "shared-e2e" && !OPT_IN_HARDWARE_JOB_IDS.has(jobId),
357351
);
352+
const launchableE2eJobs = workflowJobIds.filter((jobId) =>
353+
isLaunchableE2eJob(jobId, record(jobs[jobId], `workflow.jobs.${jobId}`)),
354+
);
355+
if (launchableE2eJobs.length !== 1) {
356+
throw new Error(`expected exactly one Launchable E2E job, found ${launchableE2eJobs.length}`);
357+
}
358+
const launchableE2eJobId = launchableE2eJobs[0]!;
359+
const defaultJobIds = workflowJobIds.filter((jobId) => jobId !== launchableE2eJobId);
358360
for (const jobId of defaultJobIds) {
359361
const activationPath = releaseActivationPath(
360362
record(jobs[jobId], `workflow.jobs.${jobId}`),
@@ -366,13 +368,6 @@ export function buildReleaseE2ePreflight(input: {
366368
);
367369
}
368370
}
369-
const launchableE2eJobs = defaultJobIds.filter((jobId) =>
370-
isLaunchableE2eJob(jobId, record(jobs[jobId], `workflow.jobs.${jobId}`)),
371-
);
372-
if (launchableE2eJobs.length !== 1) {
373-
throw new Error(`expected exactly one Launchable E2E job, found ${launchableE2eJobs.length}`);
374-
}
375-
const launchableE2eJobId = launchableE2eJobs[0]!;
376371
const executions = [
377372
...defaultJobIds.flatMap((jobId) =>
378373
jobExecutions(jobId, record(jobs[jobId], `workflow.jobs.${jobId}`), "default", plan),
@@ -398,9 +393,9 @@ export function buildReleaseE2ePreflight(input: {
398393
candidateSha: input.candidateSha,
399394
dispatches: {
400395
completeRun: {
401-
includeStagingBrevLaunchable: true,
396+
includeStagingBrevLaunchable: false,
402397
jobs: "",
403-
mode: "full",
398+
mode: "ordinary",
404399
targets: "",
405400
},
406401
},
@@ -476,7 +471,7 @@ export function buildReleaseE2eLedger(
476471
);
477472
requireEqual(
478473
booleanField(dispatch, "includeStagingBrevLaunchable", `${label}.dispatch`),
479-
true,
474+
false,
480475
`${label}.dispatch.includeStagingBrevLaunchable`,
481476
);
482477
requireEqual(

.agents/skills/nemoclaw-maintainer-e2e/SKILL.md

Lines changed: 72 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ description: Dispatches and verifies trusted GitHub Actions E2E for NemoClaw mai
1111
Use `.github/workflows/e2e.yaml` from trusted `main`.
1212
Every push to `main` selects the default workflow E2E jobs.
1313
Push runs skip `jetson-nvmap-gpu`, `llama-cpp-dgx-spark-plan`, and `llama-cpp-dgx-spark-qualification` because push events cannot set the required workflow dispatch flags.
14-
Pre-tag evidence still requires the full `workflow_dispatch` mode described below.
14+
Pre-tag release-ledger evidence uses ordinary `workflow_dispatch` mode. Release-image evidence uses
15+
the separate fully validated Launchable result described below.
1516
Do not substitute local `npm run test:live-e2e` unless the maintainer explicitly requests local execution.
1617

1718
## Manual PR E2E
@@ -154,7 +155,7 @@ A changed head repository, head SHA, or base SHA invalidates the evidence and re
154155
| “Run the full E2E suite” | Full | empty | `true` |
155156
| “deploy pre-release full E2E” | Full | empty | `true` |
156157
| “run pre-tag full E2E” | Full | empty | `true` |
157-
| “run release-candidate E2E” | Full | empty | `true` |
158+
| “run release-candidate E2E” | Ordinary | empty | `false` |
158159
159160
A generic E2E request must not authorize the Brev Launchable path.
160161
Do not infer full mode from words such as “all” or “complete.”
@@ -294,26 +295,34 @@ Queued, waiting, or accepted dispatch state is not success.
294295
295296
## Verify the Result
296297
297-
Create a private temporary evidence directory:
298+
Create a private evidence directory. A release caller sets `EVIDENCE_DIR` to its durable private
299+
release directory; a standalone invocation removes its temporary directory on exit:
298300
299301
```bash
300-
EVIDENCE_DIR="$(mktemp -d)"
302+
if [ -z "${EVIDENCE_DIR:-}" ]; then
303+
EVIDENCE_DIR="$(mktemp -d)"
304+
trap 'rm -rf "$EVIDENCE_DIR"' EXIT
305+
else
306+
install -d -m 0700 "$EVIDENCE_DIR"
307+
fi
301308
chmod 700 "$EVIDENCE_DIR"
302-
trap 'rm -rf "$EVIDENCE_DIR"' EXIT
303309
gh api "repos/NVIDIA/NemoClaw/actions/runs/$RUN_ID" >"$EVIDENCE_DIR/run-$RUN_ID.json"
304310
gh api "repos/NVIDIA/NemoClaw/actions/runs/$RUN_ID/jobs?filter=latest&per_page=100" \
305311
>"$EVIDENCE_DIR/jobs-latest-$RUN_ID.json"
306312
```
307313
308-
For full-mode or release evidence, collect every attempt for the matrix-preserving ledger:
314+
For release-ledger evidence and every Launchable image-evidence validation, collect every attempt:
309315
310316
```bash
311317
gh api --paginate --slurp \
312318
"repos/NVIDIA/NemoClaw/actions/runs/$RUN_ID/jobs?filter=all&per_page=100" \
313319
>"$EVIDENCE_DIR/jobs-$RUN_ID.json"
314320
```
315321
316-
Reuse `run-$RUN_ID.json` and `jobs-$RUN_ID.json` as the `nemoclaw-maintainer-cut-release-tag` manifest inputs and as the full-mode validator inputs. Do not fetch the same run again. `jobs-latest-$RUN_ID.json` is only for ordinary and Launchable modes.
322+
Reuse `run-$RUN_ID.json` and `jobs-$RUN_ID.json` as the
323+
`nemoclaw-maintainer-cut-release-tag` manifest inputs when building a release ledger and as validator
324+
inputs when validating image evidence. Do not fetch the same run again. Use
325+
`jobs-latest-$RUN_ID.json` only for an ordinary status report that does not validate image evidence.
317326
318327
For ordinary and Launchable modes, require `run-$RUN_ID.json` to report:
319328
@@ -324,7 +333,8 @@ For ordinary and Launchable modes, require `run-$RUN_ID.json` to report:
324333
For Launchable mode, also require `jobs-latest-$RUN_ID.json` to contain one completed, successful
325334
`Exact staging Brev Launchable` job. Return the workflow and job URLs.
326335
327-
For full mode, select and download the Launchable E2E artifact for the latest successful Launchable job attempt:
336+
For full mode, selective Launchable mode, or a trusted `main` push selected for an image handoff,
337+
download the artifact for the latest successful Launchable job attempt:
328338
329339
```bash
330340
EVIDENCE_ATTEMPT="$(jq -er '
@@ -335,57 +345,99 @@ EVIDENCE_ATTEMPT="$(jq -er '
335345
(.run_attempt | type) == "number") |
336346
.run_attempt] | unique | sort | last // error("no successful Launchable attempt")
337347
' "$EVIDENCE_DIR/jobs-$RUN_ID.json")"
338-
FULL_E2E_DIR="$EVIDENCE_DIR/full-$EVIDENCE_ATTEMPT"
348+
FULL_E2E_DIR="$EVIDENCE_DIR/image-$RUN_ID-$EVIDENCE_ATTEMPT"
339349
install -d -m 0700 "$FULL_E2E_DIR"
340350
gh run download "$RUN_ID" --repo NVIDIA/NemoClaw \
341351
--name "staging-brev-launchable-${CANDIDATE_SHA}-${RUN_ID}-${EVIDENCE_ATTEMPT}" \
342352
--dir "$FULL_E2E_DIR"
353+
VALIDATOR_MODE_ARGS=()
354+
if [ -n "${EVIDENCE_MODE:-}" ]; then
355+
VALIDATOR_MODE_ARGS=(--mode "$EVIDENCE_MODE")
356+
fi
343357
node --experimental-strip-types --no-warnings \
344358
.agents/skills/nemoclaw-maintainer-e2e/scripts/validate-full-e2e-evidence.mts \
359+
"${VALIDATOR_MODE_ARGS[@]}" \
345360
--candidate-sha "$CANDIDATE_SHA" \
346361
--run-json "$EVIDENCE_DIR/run-$RUN_ID.json" \
347362
--jobs-json "$EVIDENCE_DIR/jobs-$RUN_ID.json" \
348363
--dispatch-json "$FULL_E2E_DIR/dispatch.json" \
349364
--launchable-e2e-json "$FULL_E2E_DIR/launchable-e2e.json" \
350-
--cleanup-json "$FULL_E2E_DIR/cleanup.json"
365+
--cleanup-json "$FULL_E2E_DIR/cleanup.json" \
366+
>"$FULL_E2E_DIR/validated.json"
351367
```
352368
353-
The validator requires:
369+
Leave `EVIDENCE_MODE` unset for the legacy full-run validator path. For a release-image evidence
370+
candidate, set it to `full`, `launchable`, or `push`. That stricter path rejects PR-shaped evidence.
371+
372+
Every validator mode requires:
354373
355374
- the workflow run to succeed for the selected SHA;
356-
- `dispatch.json` to bind the same run, empty selectors, `include_staging_brev_launchable=true`, `allowJetsonRunnerQueue: false`, `allowDgxSparkRunnerQueue: false`, and the selected successful Launchable job attempt;
375+
- `dispatch.json` to bind the same run and selected successful Launchable job attempt;
357376
- `allowJetsonDispatch: false` in every v2 `dispatch.json` receipt;
358377
- `allowJetsonDispatch` to be absent or `false` in every v1 `dispatch.json` receipt;
378+
- `allowJetsonRunnerQueue: false` and `allowDgxSparkRunnerQueue: false`;
359379
- `Exact staging Brev Launchable` to conclude `success` in the selected current or earlier attempt of the same workflow run;
360380
- `launchable-e2e.json` to identify the selected SHA in the repository and provision records;
381+
- `launchable-e2e.json` to bind the booted GCP image URI to its project, name, numeric ID,
382+
self-link, source family, image origin, creation time, and image-repository SHA;
383+
- the source project to equal trusted project `brevdevprod`;
361384
- the booted repository to be unmodified;
362385
- the in-guest full E2E to pass; and
363386
- `cleanup.json` to report the same workspace as `ABSENT`.
364387
388+
The selector contract is mode-specific: `full` requires empty selectors and
389+
`include_staging_brev_launchable=true`; `launchable` requires
390+
`jobs=staging-brev-launchable`, empty targets, and the opt-in false; `push` requires empty selectors
391+
and the opt-in false.
392+
365393
A skipped, cancelled, queued, or failed Launchable E2E job is not evidence.
366-
A Launchable-mode run is not full-mode or pre-tag release evidence.
394+
A Launchable-mode run is not release-ledger evidence. It is qualified historical image evidence after
395+
the stricter direct `main` validator succeeds.
367396
A missing, mismatched, or failed cleanup receipt is not evidence.
368397
398+
## Select Release Image Evidence
399+
400+
When `nemoclaw-maintainer-cut-release-tag` requests an image choice, list successful E2E workflow
401+
runs on `main` newest first. Inspect each run's `Exact staging Brev Launchable` job and artifact by
402+
using the collection and validator steps above. Derive `EVIDENCE_MODE` from the trusted receipt:
403+
404+
- use `push` for a `push` event with empty selectors and no Launchable opt-in;
405+
- use `launchable` for `workflow_dispatch` with `jobs=staging-brev-launchable`; and
406+
- use `full` for `workflow_dispatch` with empty selectors and
407+
`include_staging_brev_launchable=true`.
408+
409+
Reject an expired or missing artifact, a failed or skipped job, invalid evidence, and PR-shaped
410+
evidence. An itemized release-ledger exception is not image evidence. Return every valid candidate
411+
needed for the caller's ancestry check, sorted by `jobCompletedAt` newest first. The caller chooses
412+
the newest historically validated ancestor of the release SHA and keeps its `validated.json` in the private
413+
release evidence directory.
414+
369415
## Bind Release Evidence
370416
371-
If no release plan exists, label a successful full run against `origin/main` as provisional release evidence.
417+
If no release plan exists, label a successful ordinary run against `origin/main` as provisional
418+
release-ledger evidence. Return validated Launchable evidence separately when available.
372419
Return:
373420
421+
- the exact `validated.json` path;
374422
- candidate SHA;
375423
- workflow run URL and conclusion;
424+
- workflow run ID, creation timestamp, and selected job completion timestamp;
376425
- `Exact staging Brev Launchable` job URL;
377426
- selected successful Launchable job attempt;
378-
- Launchable E2E identity; and
427+
- exact GCP image and Launchable E2E identity; and
379428
- cleanup result.
380429
381-
If the release candidate SHA changes, discard the earlier full run and dispatch full mode for the new SHA.
430+
If the release candidate SHA changes, discard the earlier release ledger and dispatch ordinary mode
431+
for the new SHA. Discard the prior image decision, rediscover the newest qualified ancestor for the
432+
new SHA, present its evidence, and obtain the image choice again.
382433
No release-note-only delta exception is currently defined.
383434
384435
When `nemoclaw-maintainer-cut-release-tag` invokes this skill, return the validated fields for its pre-tag E2E evidence ledger.
385-
The trusted `dispatch.json` receipt proves that full mode used empty selectors and included `Exact staging Brev Launchable`.
386-
For Jetson dispatch, a v2 receipt requires `allowJetsonDispatch: false`.
387-
A v1 receipt may omit `allowJetsonDispatch`, but it must be `false` when present.
388-
Both receipt versions require the optional DGX Spark runner path to be disabled.
436+
The release-ledger `dispatch.json` is a v2 direct `main` receipt. It proves ordinary mode used empty
437+
selectors and excluded `Exact staging Brev Launchable`; `prNumber` is null, both repositories are
438+
`NVIDIA/NemoClaw`, and its base, workflow, and candidate SHAs are identical. It also requires
439+
`allowJetsonDispatch: false` and both optional runner queues disabled. Image qualification validates
440+
its own mode-specific v1 or v2 receipt.
389441
The release evidence ledger proves the result of each workflow E2E.
390442
Do not ask for the release confirmation phrase in this skill.
391443

0 commit comments

Comments
 (0)