Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ The script handles the deterministic checks. You handle judgment calls:

- **Product scope not established:** Stop before approval when the PR would create a new supported product surface and no accepted issue or design decision establishes ownership and lifecycle expectations. Technical correctness, successful tests, green CI, and positive advisor output do not substitute for product approval. Ask a maintainer for the product decision or route an independent solution through [Community Solutions](../../../docs/resources/community-contributions.mdx).
- **Missing required checks:** The checked-in script requires `checks`, `check-hash`, `changes`, `commit-lint`, `dco-check`, and `E2E / PR Gate` in the status rollup, including while the repository ruleset rollout is staged. First-time fork contributors may need "Approve and run" before the ordinary `pull_request` checks appear. The trusted E2E controller reserves its exact head/base context for both internal and fork PRs without executing PR code. Never waive a missing, neutral, or skipped E2E gate, and never run untrusted fork code with privileged credentials to manufacture a result.
- **No-secret exception approval:** The primary path uses the same failed `E2E / PR Gate` run. Open the failed check's **Details** link, choose **Review deployments**, select `e2e-no-secret-exception`, add an optional comment, and approve. The waiting job has `deployment: false`, no secrets, and no PR-controlled execution. The controller reads GitHub's approval history, requires exactly one approval for only that environment, verifies that the recorded reviewer still has `maintain` or `admin`, and then applies the existing exact PR/head/base, deterministic-plan, matching-failed-check, compatible-`main`, and final stale-revision checks. The environment must be configured before rollout with required reviewers whose approving members have `maintain` or `admin`; add no secrets, variables, or custom protection app, and preferably disable administrator bypass. An absent or unprotected environment fails closed. Do not rerun the waiting workflow: environment approvals are not attempt-bound, so the controller accepts only the first attempt. Trigger fresh upstream PR CI for a new gate run, or use the typed manual fallback below. Per-PR concurrency cancels an older waiting approval when a newer exact revision reaches the gate.
- **Fork no-secret exception:** Use this only when an exact-diff gate has failed with `Maintainer fork exception required`. Independently review the fork change and non-secret PR CI, then use the protected-environment approval above. The controller rejects a closed PR, a changed head or base, an internal PR, an empty E2E plan, a non-failed gate, a controller commit that is neither current `main` nor a safely validated ancestor of it, or a recorded reviewer below maintainer role. A safe `main` advance must preserve the controller commit as its merge base, contain fewer than 300 fully enumerated changed files, and avoid `e2e-control-plane` changes; other advances fail closed. It re-reads the open PR's exact head and base immediately before writing success. The result records the reviewer, optional bounded comment, validated approval-run URL, plan, and waived jobs. Credential-bearing E2E was not run; this is an audited no-secret exception, not passing E2E evidence. If the button path is unavailable, choose **Run workflow** on `main`, select `resolve-fork`, and provide the fork PR number, its current 40-character head SHA as `expected_head_sha`, its current 40-character base SHA as `expected_base_sha`, a specific 10–500-character reason, and optionally an `NVIDIA/NemoClaw` Actions run URL. Re-read both PR SHAs immediately before dispatch. The controller validates the optional URL's repository and run-ID shape but does not inspect that run's head, jobs, or conclusion; review the run yourself before citing it.
- **E2E control-plane no-secret exception:** Use this only when an internal exact-diff gate has failed with `Maintainer control-plane exception required`. The deterministic `e2e-control-plane` family is a conservative path boundary: it covers E2E and PR-CI workflows, risk policy, dependency and test configuration, preparation and upload actions, and non-documentation files under `tools/e2e/` and `test/e2e/`, including shell and Python support files. Because a matching revision may influence job selection, credential-bearing execution, or the evidence used by the gate, the controller withholds the selected live jobs instead of trying to classify individual diffs as harmless. Independently review the change and its non-secret CI, then use the protected-environment approval above. The controller rejects closed PRs, forks, stale heads or bases, plans without that family, a mismatched failed gate, a controller commit that is neither current `main` nor a safely validated ancestor of it, or a recorded reviewer below maintainer role. A safe `main` advance must preserve the controller commit as its merge base, contain fewer than 300 fully enumerated changed files, and avoid `e2e-control-plane` changes; other advances fail closed. It re-reads the open PR's exact head and base immediately before writing success. The recorded result identifies the reviewer and validated approval run and states that the credential-bearing jobs were waived; it never claims they passed. If the button path is unavailable, choose **Run workflow** on `main`, select `resolve-control-plane`, and provide the PR number, current `expected_head_sha`, current `expected_base_sha`, a specific 10–500-character reason, and optionally a same-repository Actions run URL. The typed fallback is the maintainer's auditable assertion; it does not query a separate approval record or inspect optional run evidence.
- **Controller workflow versus PR verdict:** `E2E / PR Gate Controller` reports whether the trusted controller safely published an outcome. It can be green while the custom `E2E / PR Gate` check is failed or cancelled. Merge authority comes from the custom check for the current exact head and base, not from the controller workflow. `Superseded by PR update` and `PR closed — gate no longer applies` are cancelled outcomes for an obsolete revision and require no action on that old check; the current revision still needs its own successful gate. The closed-PR outcome also covers a deleted fork repository whose GitHub head-repository field is empty.
- **CI or selected E2E did not pass:** A handled prerequisite-CI or selected-E2E failure leaves `E2E / PR Gate` red while `E2E / PR Gate Controller` completes successfully. Follow the CI run, E2E run, non-passing job, and failed-step links in the custom check, fix or rerun the failing work, and require a successful gate for the resulting exact revision. A green controller run does not override the red verdict.
- **Evidence could not be verified:** If a selected child succeeds but `Download evidence` fails, is cancelled, or is skipped, the custom check fails closed with `Evidence could not be verified` and `E2E / PR Gate Controller` is red. Inspect the `Download evidence` step and rerun the gate; the green child alone is not accepted evidence. A successful download with missing, duplicate, skipped, pending, or reported-failing signals is a handled red PR verdict with a green controller. Malformed or unsafe evidence, schema or exact-identity mismatches, and traversal-limit violations remain controller verification errors: both the check and controller fail closed.
- **No-secret exception approval:** The primary path uses the same failed `E2E / PR Gate` check. Follow the explicit `E2E / PR Gate Controller run <id>` link embedded in the check summary rather than relying on the custom check's **Details** destination, choose **Review deployments**, select `e2e-no-secret-exception`, add an optional comment, and approve. The waiting job has `deployment: false`, no secrets, and no PR-controlled execution. The controller reads GitHub's approval history, requires exactly one approval for only that environment, verifies that the recorded reviewer still has `maintain` or `admin`, and then applies the existing exact PR/head/base, deterministic-plan, matching-failed-check, compatible-`main`, and final stale-revision checks. A recorded exception completes the custom check successfully with `No E2E run — exception approved by @<maintainer>` and leads with `Outcome: EXCEPTION — credentialed E2E did not run.` Treat this as an audited exception, not passing E2E evidence. The environment must be configured before rollout with required reviewers whose approving members have `maintain` or `admin`; add no secrets, variables, or custom protection app, and preferably disable administrator bypass. An absent or unprotected environment fails closed. Do not rerun the waiting workflow: environment approvals are not attempt-bound, so the controller accepts only the first attempt. Trigger fresh upstream PR CI for a new gate run, or use the typed manual fallback below. Per-PR concurrency cancels an older waiting approval when a newer exact revision reaches the gate.
- **Fork no-secret exception:** Use this only when an exact-diff gate has failed with `Maintainer fork exception required`. Independently review the fork change and non-secret PR CI, then use the protected-environment approval above. The controller rejects a closed PR, a changed head or base, an internal PR, an empty E2E plan, a non-failed gate, a controller commit that is neither current `main` nor a safely validated ancestor of it, or a recorded reviewer below maintainer role. A safe `main` advance must preserve the controller commit as its merge base, contain fewer than 300 fully enumerated changed files, and avoid `e2e-control-plane` changes; other advances fail closed. It re-reads the open PR's exact head and base immediately before writing success. The result records the reviewer, optional bounded comment, validated approval-run URL, plan, and jobs that did not run. If the button path is unavailable, choose **Run workflow** on `main`, select `resolve-fork`, and provide the fork PR number, its current 40-character head SHA as `expected_head_sha`, its current 40-character base SHA as `expected_base_sha`, and a specific 10–500-character reason. Re-read both PR SHAs immediately before dispatch. Optionally set `evidence_url` to an exact `https://github.com/NVIDIA/NemoClaw/actions/runs/<run-id>` URL that you reviewed, or leave it blank when no supporting run exists. PR, issue, comment, job, and external URLs are rejected. The controller validates the optional URL's repository and run-ID shape but does not inspect that run's head, jobs, or conclusion.
- **E2E control-plane no-secret exception:** Use this only when an internal exact-diff gate has failed with `Maintainer control-plane exception required`. The deterministic `e2e-control-plane` family is a conservative path boundary: it covers E2E and PR-CI workflows, risk policy, dependency and test configuration, preparation and upload actions, and non-documentation files under `tools/e2e/` and `test/e2e/`, including shell and Python support files. Because a matching revision may influence job selection, credential-bearing execution, or the evidence used by the gate, the controller withholds the selected live jobs instead of trying to classify individual diffs as harmless. Independently review the change and its non-secret CI, then use the protected-environment approval above. The controller rejects closed PRs, forks, stale heads or bases, plans without that family, a mismatched failed gate, a controller commit that is neither current `main` nor a safely validated ancestor of it, or a recorded reviewer below maintainer role. A safe `main` advance must preserve the controller commit as its merge base, contain fewer than 300 fully enumerated changed files, and avoid `e2e-control-plane` changes; other advances fail closed. It re-reads the open PR's exact head and base immediately before writing success. The recorded result identifies the reviewer and validated approval run and states which jobs did not run; it never claims they passed. If the button path is unavailable, choose **Run workflow** on `main`, select `resolve-control-plane`, and provide the PR number, current `expected_head_sha`, current `expected_base_sha`, and a specific 10–500-character reason. Optionally set `evidence_url` to an exact `https://github.com/NVIDIA/NemoClaw/actions/runs/<run-id>` URL that you reviewed, or leave it blank. PR, issue, comment, job, and external URLs are rejected. The typed fallback is the maintainer's auditable assertion; it does not query a separate approval record or inspect optional run evidence.
- **Two-phase ruleset rollout and backfill:** First deploy the E2E check producer and its trusted fork handling. Re-run `CI / Pull Request` for every already-open exact PR head/base pair (approving a first-time fork run when necessary), then verify that `E2E / PR Gate` is attached to that same head SHA for the current base. The fail-closed maintainer checker identifies any head still needing backfill. Adding the workflow does not retroactively report the context, and enabling the ruleset first leaves existing PRs at "Waiting for status to be reported." Do not activate the context as a security boundary while it is scoped only to the shared GitHub Actions app: that app identity cannot distinguish this workflow from another workflow. First give the gate distinct provenance through a dedicated GitHub App or an organization required-workflow rule. When the context is finally activated, also enable strict/up-to-date required status checks; otherwise a successful head can remain mergeable after `main` advances and changes the effective merge diff. Preserve the control-plane review and deterministic floor even after those external protections are in place.
- **Contributor compliance failed:** Reject the PR and ask the contributor to provide the PR-body DCO declaration or replace unverified commits with a clean verified history. Do not approve, merge, amend, sign, or force-push on the contributor's behalf.
- **Contributor/approver overlap:** Surface `advisories.contributorApprovalOverlap` when the same account not recognized as automated by the supported login conventions appears as the current PR opener, commit author, or co-author and its latest opinionated review is approved. The invalid state detected here is contributor and approver identity overlap in the current GitHub PR metadata; the source boundary is the current opener plus all commit-author and review pages fetched through GitHub's GraphQL API. The advisory includes contributors whose commits remain in the current PR head at check time; it does not retain original push actors or authors removed when history is rebased, squashed, or fixed up. A clear result is not proof of independent approval. Missing, invalid, or conflicting review timestamps, or failure to retrieve complete paginated history, produce a warning because the latest opinion cannot be selected reliably.
Expand Down
24 changes: 13 additions & 11 deletions .github/workflows/pr-e2e-gate.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: E2E / PR Gate
name: E2E / PR Gate Controller

on:
workflow_run:
Expand Down Expand Up @@ -36,7 +36,7 @@ on:
required: true
type: string
evidence_url:
description: Optional maintainer-supplied NVIDIA/NemoClaw Actions reference.
description: Optional Actions run URL, for example https://github.com/NVIDIA/NemoClaw/actions/runs/123. Leave blank if none.
required: false
default: ""
type: string
Expand Down Expand Up @@ -68,7 +68,7 @@ jobs:
node-version: "22"

- name: Install controller dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Reserve exact-diff gate
env:
Expand Down Expand Up @@ -103,7 +103,7 @@ jobs:
node-version: "22"

- name: Install controller dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Cancel superseded E2E runs
env:
Expand Down Expand Up @@ -145,7 +145,7 @@ jobs:
node-version: "22"

- name: Install controller dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- id: workspace
name: Create private workspace
Expand Down Expand Up @@ -236,8 +236,8 @@ jobs:
"$RUN_ID" "$run_url"
;;
completed:failure | completed:cancelled | completed:timed_out | completed:action_required | completed:neutral | completed:skipped | completed:stale | completed:startup_failure)
printf '::error title=E2E run failed::Run %s completed with conclusion %s. %s\n' \
"$RUN_ID" "${state#*:}" "$run_url" >&2
printf 'Run %s status=completed conclusion=%s url=%s\n' \
"$RUN_ID" "${state#*:}" "$run_url"
;;
*)
printf '::error title=Unexpected run state::Run %s returned an unsupported status/conclusion pair. %s\n' \
Expand All @@ -251,7 +251,7 @@ jobs:
queued:none | in_progress:none | requested:none | waiting:none | pending:none)
sleep 10
;;
completed:success)
completed:success | completed:failure | completed:cancelled | completed:timed_out | completed:action_required | completed:neutral | completed:skipped | completed:stale | completed:startup_failure)
exit 0
;;
*)
Expand All @@ -262,7 +262,8 @@ jobs:
WAIT

if [ "$wait_status" -eq 124 ]; then
printf '::error title=E2E run timed out::The run did not complete within 105 minutes.\n' >&2
printf 'Run %s did not complete within 105 minutes; finalization will cancel it and report the PR gate outcome.\n' "$RUN_ID"
wait_status=0
fi
exit "$wait_status"

Expand Down Expand Up @@ -296,6 +297,7 @@ jobs:
--state-hash "${{ steps.start.outputs.state_hash }}"
--check-id "${{ steps.start.outputs.check_id }}"
--run-id "${{ steps.start.outputs.run_id }}"
--evidence-outcome "${{ steps.evidence.outcome }}"

- name: Close incomplete check
if: ${{ always() && steps.start.outputs.check_id != '' && steps.start.outputs.finalized != 'true' && steps.finish.outputs.finalized != 'true' }}
Expand Down Expand Up @@ -341,7 +343,7 @@ jobs:
node-version: "22"

- name: Install controller dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Record approved E2E exception
env:
Expand Down Expand Up @@ -388,7 +390,7 @@ jobs:
node-version: "22"

- name: Install controller dependencies
run: npm ci --ignore-scripts
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Record E2E exception
env:
Expand Down
Loading
Loading