fix(ci): run approved E2E for fork PRs#7505
Conversation
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThe PR replaces fork credentialed-E2E skip recording with protected exact-revision authorization, binds dispatch and checkout to the PR head repository, unifies approval workflow wiring, tightens evidence identity validation, and updates documentation and tests. ChangesPR E2E authorization and repository binding
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Code Coverage OverviewLanguages: TypeScript TypeScript / code-coverage/pluginThe overall coverage in commit cb752a8 in the TypeScript / code-coverage/cliThe overall coverage in commit cb752a8 in the Show a code coverage summary of the most impacted files.
Updated |
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
test/pr-e2e-gate-fork-approval.test.ts (1)
646-654: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winRestore the locally created
fetchspy in thefinallyblocks.Both new tests create
vi.spyOn(globalThis, "fetch")but thefinallyblocks only remove the temp work dir, so a failure path leaves the globalfetchreplaced and relies solely on the globalrestoreMocksbehavior. Addvi.restoreAllMocks()alongside thefs.rmSynccleanup.Based on learnings: "tests must still explicitly restore any locally created spies/mocks—especially in
try/finallyblocks so they're restored on failure paths."♻️ Proposed cleanup
} finally { + vi.restoreAllMocks(); fs.rmSync(workDir, { recursive: true, force: true }); }Also applies to: 693-698
🤖 Prompt for 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. In `@test/pr-e2e-gate-fork-approval.test.ts` around lines 646 - 654, Update the finally blocks in both affected tests to call vi.restoreAllMocks() alongside the existing fs.rmSync cleanup, ensuring the globalThis.fetch spy created by vi.spyOn is restored even when the test fails.Source: Learnings
tools/e2e/pr-e2e-gate.mts (1)
4137-4187: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider collapsing the two approved-start entrypoints into one shared helper.
startApprovedControlPlanePrGateandstartApprovedForkPrGateare now line-for-line identical apart from the environment constant and theauthorizationKind. A single privatestartApprovedPrGate(command, environment, authorizationKind)with two thin exported wrappers keeps the public surface while ensuring future hardening (e.g. an extra approval-run assertion) can't be applied to only one path.♻️ Sketch
+async function startApprovedPrGate( + command: ApprovedControlPlaneDispatchCommand | ApprovedForkE2EDispatchCommand, + environment: typeof INTERNAL_E2E_APPROVAL_ENVIRONMENT | typeof FORK_E2E_APPROVAL_ENVIRONMENT, + authorizationKind: "internal-control-plane" | "fork", +): Promise<void> { + // ...existing shared validation, then: + await startAuthorizedPrGate( + { ...command, maintainer: review.reviewer, reason: approvedE2EReason(review.comment) }, + authorizationKind, + ); +} + +export async function startApprovedForkPrGate( + command: ApprovedForkE2EDispatchCommand, +): Promise<void> { + await startApprovedPrGate(command, FORK_E2E_APPROVAL_ENVIRONMENT, "fork"); +}🤖 Prompt for 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. In `@tools/e2e/pr-e2e-gate.mts` around lines 4137 - 4187, Collapse the duplicated validation and approval flow in startApprovedControlPlanePrGate and startApprovedForkPrGate into one private startApprovedPrGate helper accepting the command, environment, and authorizationKind. Keep both exported entrypoints as thin wrappers that pass their respective constants, while preserving all existing validation and the final startAuthorizedPrGate behavior.tools/e2e/operations-workflow-boundary.mts (1)
138-276: 📐 Maintainability & Code Quality | 🔵 TrivialConsider extracting the checkout-trust loop to curb growing complexity.
The additions are correct and consistent with
e2e.yaml, butvalidatePrGateDispatchkeeps accumulating unrelated concerns (input shape, env bindings, script fragments, and now a second per-step checkout/repository check). Extracting thetrustedCheckoutloop (Lines 235-275) into its own helper would keep this hotspot from growing further with each new controller field.As per coding guidelines, "Keep function complexity low; tracked complexity hotspots should not be expanded unnecessarily."
🤖 Prompt for 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. In `@tools/e2e/operations-workflow-boundary.mts` around lines 138 - 276, Extract the per-job checkout validation loop from validatePrGateDispatch into a dedicated helper, preserving the existing trusted checkout exceptions and checkout ref/repository checks unchanged. Invoke the helper from validatePrGateDispatch so input, environment, script, and checkout validation remain behaviorally identical while reducing complexity in the main function.Source: Coding guidelines
🤖 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 @.github/workflows/pr-e2e-gate.yaml:
- Around line 400-417: Ensure the GitHub repository has both environments
referenced by approve-e2e’s
environment.name—approve-credentialed-e2e-for-internal-pr and
approve-credentialed-e2e-for-fork-pr—pre-created with required-reviewer
protection rules, so the credentialed E2E job cannot run without approval.
In `@test/e2e/README.md`:
- Around line 550-553: Update the coordination summary description in the E2E
README to list only fields actually published by the fork authorization summary:
head SHA, base SHA, selection summary, and plan hash. Remove claims that it
includes the PR number, head repository, or explicit job/target lists unless
those fields are added to the summary built by the relevant
authorization-summary code.
---
Nitpick comments:
In `@test/pr-e2e-gate-fork-approval.test.ts`:
- Around line 646-654: Update the finally blocks in both affected tests to call
vi.restoreAllMocks() alongside the existing fs.rmSync cleanup, ensuring the
globalThis.fetch spy created by vi.spyOn is restored even when the test fails.
In `@tools/e2e/operations-workflow-boundary.mts`:
- Around line 138-276: Extract the per-job checkout validation loop from
validatePrGateDispatch into a dedicated helper, preserving the existing trusted
checkout exceptions and checkout ref/repository checks unchanged. Invoke the
helper from validatePrGateDispatch so input, environment, script, and checkout
validation remain behaviorally identical while reducing complexity in the main
function.
In `@tools/e2e/pr-e2e-gate.mts`:
- Around line 4137-4187: Collapse the duplicated validation and approval flow in
startApprovedControlPlanePrGate and startApprovedForkPrGate into one private
startApprovedPrGate helper accepting the command, environment, and
authorizationKind. Keep both exported entrypoints as thin wrappers that pass
their respective constants, while preserving all existing validation and the
final startAuthorizedPrGate behavior.
🪄 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: CHILL
Plan: Enterprise
Run ID: 6bb3f3cd-174d-4e6d-b837-4dc6393933a6
📒 Files selected for processing (18)
.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md.github/workflows/e2e.yaml.github/workflows/pr-e2e-gate.yamltest/e2e/README.mdtest/e2e/docs/README.mdtest/e2e/support/e2e-operations-workflow-boundary.test.tstest/pr-e2e-gate-command.test.tstest/pr-e2e-gate-fork-approval.test.tstest/pr-e2e-gate-lifecycle.test.tstest/pr-e2e-gate-retry-history.test.tstest/pr-e2e-gate-runner-loss-retry.test.tstest/pr-e2e-gate-typed-target.test.tstest/pr-e2e-gate-workflow.test.tstest/pr-e2e-gate.test.tstest/pr-e2e-required.test.tstools/e2e/operations-workflow-boundary.mtstools/e2e/pr-e2e-gate.mtstools/e2e/pr-e2e-required.mts
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
PR Review Advisor — InformationalAdvisor assessment: Informational / medium confidence Model lanes
Nemotron output stays in workflow artifacts and does not change the assessment above. E2E guidanceAdvisory only. E2E / PR Gate selects and runs jobs independently. Recommended E2E: This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge. |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tools/e2e/pr-e2e-gate.mts (2)
3943-3948: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDo not treat a missing head repository as a fork.
pull.head.repo?.full_name !== repositoryevaluates totruewhen GitHub returns no head repository, so fork authorization can pass its shape check and only fail later when dispatch requirescheckoutRepository. Reject the missing identity before derivingisFork.🤖 Prompt for 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. In `@tools/e2e/pr-e2e-gate.mts` around lines 3943 - 3948, Update the authorization validation around isFork so a missing pull.head.repo or its full_name is rejected before deriving fork status. Validate the head repository identity first, then compute isFork only from a present full_name, preserving the existing internal-control-plane and fork authorization checks.
3993-3997: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy liftBind approval validation to
checkoutRepository, not only the generic title.The pending state records the fork repository in its summary, but resumption checks only
status,conclusion, andpendingTitle. Validate the recorded repository against the live PR before dispatch so approval cannot be reused after the PR’s head repository changes.🤖 Prompt for 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. In `@tools/e2e/pr-e2e-gate.mts` around lines 3993 - 3997, Update the pending authorization validation around matchingChecks[0] to also verify that the repository recorded in check.output matches the live PR’s checkoutRepository before dispatch. Preserve the existing status, conclusion, and pendingTitle checks, and reject the approval when the repository differs.
🤖 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.
Outside diff comments:
In `@tools/e2e/pr-e2e-gate.mts`:
- Around line 3943-3948: Update the authorization validation around isFork so a
missing pull.head.repo or its full_name is rejected before deriving fork status.
Validate the head repository identity first, then compute isFork only from a
present full_name, preserving the existing internal-control-plane and fork
authorization checks.
- Around line 3993-3997: Update the pending authorization validation around
matchingChecks[0] to also verify that the repository recorded in check.output
matches the live PR’s checkoutRepository before dispatch. Preserve the existing
status, conclusion, and pendingTitle checks, and reject the approval when the
repository differs.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 4e421e62-7393-4db0-8e66-4bbbfe31dbc7
📒 Files selected for processing (2)
test/pr-e2e-gate-fork-approval.test.tstools/e2e/pr-e2e-gate.mts
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.github/workflows/e2e.yaml (1)
5974-5974: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick winKeep
needsout of the generated JavaScript source.Line 5974 interpolates the complete
needsobject into anactions/github-scriptprogram. If an upstream output is attacker-controlled, this becomes a code-injection boundary in a step with GitHub API access and access to previously downloaded artifacts. Pass the serialized value throughenvand parse it at runtime instead.Suggested fix
env: EXPLICIT_ONLY_JOBS: ${{ needs.generate-matrix.outputs.explicit_only_jobs }} JOBS: ${{ inputs.jobs }} RUNTIME_ARTIFACTS: ${{ runner.temp }}/e2e-runtime-audit RUNTIME_SUMMARY_FILE: ${{ runner.temp }}/e2e-runtime-summary.json TARGETS: ${{ inputs.targets }} + NEEDS_JSON: ${{ toJSON(needs) }} ... - const needs = ${{ toJSON(needs) }}; + const needs = JSON.parse(process.env.NEEDS_JSON || '{}');As per path instructions, untrusted values must be passed as data rather than interpolated into automation code.
🤖 Prompt for 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. In @.github/workflows/e2e.yaml at line 5974, Remove direct needs interpolation from the generated JavaScript in the actions/github-script step. Pass the serialized needs value through the step’s env configuration, then parse that environment variable at runtime inside the script while preserving the existing needs data behavior.Sources: Path instructions, Linters/SAST tools
🤖 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.
Outside diff comments:
In @.github/workflows/e2e.yaml:
- Line 5974: Remove direct needs interpolation from the generated JavaScript in
the actions/github-script step. Pass the serialized needs value through the
step’s env configuration, then parse that environment variable at runtime inside
the script while preserving the existing needs data behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: e0a9ead6-5b3d-4a7b-9c96-4aea9cccec87
📒 Files selected for processing (4)
.github/workflows/e2e.yamltest/e2e/README.mdtest/e2e/support/e2e-operations-workflow-boundary.test.tstools/e2e/operations-workflow-boundary.mts
🚧 Files skipped from review as they are similar to previous changes (3)
- tools/e2e/operations-workflow-boundary.mts
- test/e2e/support/e2e-operations-workflow-boundary.test.ts
- test/e2e/README.md
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
There was a problem hiding this comment.
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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:
- Around line 972-1017: Refactor runIdentityEvidence to consolidate the
identical classification logic currently repeated for installer-hash-check.yaml
and pr.yaml. After validating the pull_request event and allowing only those two
workflow paths, apply the shared immutablePrDiff, exactDiff, headShaMatches, and
headBinding checks once, preserving the existing current, other, and unknown
results.
🪄 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: CHILL
Plan: Enterprise
Run ID: 0537d833-6144-42bb-8487-4f6e6cb6f624
📒 Files selected for processing (4)
.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.tstest/skills/check-gates-fork-evidence.test.tstest/skills/check-gates-test-fixtures.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
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 `@test/e2e/support/e2e-operations-workflow-boundary.test.ts`:
- Around line 187-210: Make the negative-path subprocess in the
authentication-ordering test hermetic by stubbing curl in the spawned shell
environment, matching the existing success-path test behavior. Ensure any
attempted curl invocation fails immediately, preventing real controller API
requests while preserving the current test assertions.
🪄 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: CHILL
Plan: Enterprise
Run ID: 29c4f23c-948f-4feb-a920-f392d64cbfc5
📒 Files selected for processing (15)
.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts.github/workflows/e2e.yamltest/e2e/README.mdtest/e2e/docs/README.mdtest/e2e/support/e2e-operations-workflow-boundary.test.tstest/e2e/support/sandbox-operations-workflow-boundary.test.tstest/pr-e2e-gate-fork-approval.test.tstest/pr-e2e-gate-internal-approval.test.tstest/pr-e2e-gate-typed-target.test.tstest/pr-e2e-gate.test.tstest/skills/check-gates-fork-evidence.test.tstest/skills/check-gates-test-fixtures.tstools/e2e/operations-workflow-boundary.mtstools/e2e/pr-e2e-gate.mts
🚧 Files skipped from review as they are similar to previous changes (12)
- test/e2e/docs/README.md
- test/pr-e2e-gate-typed-target.test.ts
- test/skills/check-gates-fork-evidence.test.ts
- test/skills/check-gates-test-fixtures.ts
- tools/e2e/operations-workflow-boundary.mts
- test/pr-e2e-gate.test.ts
- .github/workflows/e2e.yaml
- .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
- test/e2e/README.md
- .agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md
- test/pr-e2e-gate-fork-approval.test.ts
- tools/e2e/pr-e2e-gate.mts
| const result = spawnSync( | ||
| "bash", | ||
| ["--noprofile", "--norc", "-e", "-o", "pipefail", "-c", authentication.run!], | ||
| { | ||
| encoding: "utf8", | ||
| env: { | ||
| ...process.env, | ||
| ACTOR: "maintainer", | ||
| BASE_SHA: "b".repeat(40), | ||
| CHECKOUT_REPOSITORY: "contributor/NemoClaw", | ||
| CHECKOUT_SHA: "a".repeat(40), | ||
| CONTROLLER_CHECK_ID: "17", | ||
| CORRELATION_ID: "123e4567-e89b-42d3-a456-426614174000", | ||
| GITHUB_REPOSITORY: "NVIDIA/NemoClaw", | ||
| GITHUB_TOKEN: "unused", | ||
| JOBS: "credential-sanitization", | ||
| PLAN_HASH: "c".repeat(64), | ||
| PR_NUMBER: "42", | ||
| RUN_ATTEMPT: "1", | ||
| RUN_ID: "23", | ||
| TARGETS: "", | ||
| }, | ||
| }, | ||
| ); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
Make the negative-path subprocess hermetic.
This invocation does not stub curl; an authentication-ordering regression could turn the test into a real controller API request. Override curl to fail if reached, as the success-path test already does.
Proposed fix
[
"--noprofile",
"--norc",
"-e",
"-o",
"pipefail",
"-c",
- authentication.run!,
+ `curl() { printf '%s\n' "unexpected curl" >&2; return 99; }\n${authentication.run!}`,
],As per coding guidelines, “Unit tests must mock external dependencies and must not call real NVIDIA APIs.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const result = spawnSync( | |
| "bash", | |
| ["--noprofile", "--norc", "-e", "-o", "pipefail", "-c", authentication.run!], | |
| { | |
| encoding: "utf8", | |
| env: { | |
| ...process.env, | |
| ACTOR: "maintainer", | |
| BASE_SHA: "b".repeat(40), | |
| CHECKOUT_REPOSITORY: "contributor/NemoClaw", | |
| CHECKOUT_SHA: "a".repeat(40), | |
| CONTROLLER_CHECK_ID: "17", | |
| CORRELATION_ID: "123e4567-e89b-42d3-a456-426614174000", | |
| GITHUB_REPOSITORY: "NVIDIA/NemoClaw", | |
| GITHUB_TOKEN: "unused", | |
| JOBS: "credential-sanitization", | |
| PLAN_HASH: "c".repeat(64), | |
| PR_NUMBER: "42", | |
| RUN_ATTEMPT: "1", | |
| RUN_ID: "23", | |
| TARGETS: "", | |
| }, | |
| }, | |
| ); | |
| const result = spawnSync( | |
| "bash", | |
| ["--noprofile", "--norc", "-e", "-o", "pipefail", "-c", `curl() { printf '%s\n' "unexpected curl" >&2; return 99; }\n${authentication.run!}`], | |
| { | |
| encoding: "utf8", | |
| env: { | |
| ...process.env, | |
| ACTOR: "maintainer", | |
| BASE_SHA: "b".repeat(40), | |
| CHECKOUT_REPOSITORY: "contributor/NemoClaw", | |
| CHECKOUT_SHA: "a".repeat(40), | |
| CONTROLLER_CHECK_ID: "17", | |
| CORRELATION_ID: "123e4567-e89b-42d3-a456-426614174000", | |
| GITHUB_REPOSITORY: "NVIDIA/NemoClaw", | |
| GITHUB_TOKEN: "unused", | |
| JOBS: "credential-sanitization", | |
| PLAN_HASH: "c".repeat(64), | |
| PR_NUMBER: "42", | |
| RUN_ATTEMPT: "1", | |
| RUN_ID: "23", | |
| TARGETS: "", | |
| }, | |
| }, | |
| ); |
🤖 Prompt for 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.
In `@test/e2e/support/e2e-operations-workflow-boundary.test.ts` around lines 187 -
210, Make the negative-path subprocess in the authentication-ordering test
hermetic by stubbing curl in the spawned shell environment, matching the
existing success-path test behavior. Ensure any attempted curl invocation fails
immediately, preventing real controller API requests while preserving the
current test assertions.
Source: Coding guidelines
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Summary
Fork PRs previously became mergeable after an approved credentialed-E2E skip, so their selected E2E work never ran. This change makes protected approval authorize the exact fork repository and SHA to run through the trusted E2E workflow, and only verified passing evidence can make the required gate green. The strict merge checker also authenticates fork runs when GitHub omits their PR association, without weakening the exact-diff or E2E coordination requirements.
Changes
approve-credentialed-e2e-for-fork-pr.checkout_repositorydispatch input because a workflow dispatched in the base repository cannot resolve a fork-only SHA fromcheckout_shaalone. Every PR-code checkout and runner-loss retry consumes this value, ande2e-operations-workflow-boundary.test.tsenforces the repository/SHA pairing.Type of Change
Quality Gates
Documentation Writer Review
docs-updated.agents/skills/nemoclaw-maintainer-day/MERGE-GATE.md,test/e2e/README.md, andtest/e2e/docs/README.md; exact-head review confirmed controller-check authentication is documented before PR checkout and direct manual-dispatch rejection is accurate.DGX Station Hardware Evidence
Verification
Signed-off-by:line and every commit appears asVerifiedin GitHubpre-commit,commit-msg, andpre-pushhooks passed, ornpm run check:diffpassed when hooks were skipped or unavailabletest:changedtimeout passed alone with 31 tests; the maintainer policy contract passed 15 tests; 3 strict-checker files passed 147 tests; live fix(cli): exit shields commands cleanly on deferred shields failure #7395 validation reportsallPass: truewith all 43 checks green.npm testfor broad runtime/test-harness changes;npm run checkfor repo-wide validation/coverage changes — command/result:npm run docsbuilds without warnings (doc changes only)Additional verification:
npm run typecheck:cli,npm run check:diff, andnpm run docspassed.Signed-off-by: Prekshi Vyas prekshiv@nvidia.com
Summary by CodeRabbit
checkout_repositoryto let controller-driven E2E runs check out the intended PR head repository.