Skip to content

fix(maintainer): verify final E2E coordinator evidence - #8241

Closed
cv wants to merge 1 commit into
mainfrom
codex/e2e-gate-observation-evidence
Closed

fix(maintainer): verify final E2E coordinator evidence#8241
cv wants to merge 1 commit into
mainfrom
codex/e2e-gate-observation-evidence

Conversation

@cv

@cv cv commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Make the maintainer merge check verify the complete E2E coordinator history and the final pull request state. This prevents a passing result when coordinator evidence is ambiguous or another repository check changes before the merge decision.

Changes

  • Accept a fork approval only when one automatic coordinator is followed by the sole enclosing manual approval coordinator.
  • Reject missing, duplicate, malformed, queued, or ambiguous coordinator evidence across the bounded paginated history.
  • Re-evaluate the complete check rollup from the final pull request snapshot and require the required checks to remain unchanged.
  • Add regression fixtures for fork approval timing, duplicate predecessors, pagination limits, queued runs, and late pending or failing checks.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: This changes an internal maintainer merge check and does not change a supported user surface.
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: Independent Codex Desktop security review passed all nine categories for f3b9686b3.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: The changed maintainer script and test fixtures do not alter user-facing behavior or documentation.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run validate:pr passed after refreshing origin/main when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: GitHub CI pending.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: GitHub CI pending.
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Carlos Villela cvillela@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved CI gate validation to detect stale, incomplete, duplicated, or conflicting workflow evidence.
    • Added stronger validation for required checks, E2E results, pull request revisions, and final CI status.
    • Improved handling of paginated workflow results and repeated observations for more reliable merge decisions.
  • Tests

    • Expanded automated coverage for valid and invalid CI evidence, timestamp edge cases, retries, pagination, and changing check results.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The gate evaluator now validates E2E coordinator histories, caches CI evidence, captures status-check rollups, and performs staged consistency checks across PR revisions and final CI observations. Tests add paginated coordinator fixtures and broad acceptance and rejection coverage.

Changes

CI and E2E evidence validation

Layer / File(s) Summary
Coordinator evidence discovery and validation
.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
The evaluator discovers paginated coordinator runs, validates run and job metadata, partitions timestamps, checks run identity, and classifies authorization predecessors.
Cached and staged CI evaluation
.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
CI evaluation caches action evidence and compares required-check, E2E, selected-check, and coordinator snapshots across staged reads.
Revision and final-flow consistency
.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
PR revision snapshots include validated status-check rollups. The main flow performs revision and CI consistency checks before and after final evaluation.
Coordinator and staged-response fixtures
test/skills/check-gates-test-fixtures.ts
Fixtures model coordinator runs, paginated workflow responses, timestamps, job metadata, injected clocks, staged responses, and final PR reads.
Coordinator evidence and consistency tests
test/skills/check-gates-coordinator-evidence.test.ts
Tests cover valid coordinator histories and rejection of malformed, stale, duplicated, incomplete, conflicting, and changed evidence.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: area: ci, area: e2e, area: security, bug-fix

Suggested reviewers: prekshivyas, apurvvkumaria

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: verifying final E2E coordinator evidence before merge.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ 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 codex/e2e-gate-observation-evidence

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

@github-code-quality

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit f3b9686 in the codex/e2e-gate-obser... branch remains at 96%, unchanged from commit 8683777 in the main branch.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (11)
test/skills/check-gates-coordinator-evidence.test.ts (3)

207-207: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the local coordinatorJobs to remove the shadow.

Line 207 declares a local const coordinatorJobs. It shadows the module-level coordinatorJobs helper from line 31. The two names mean different things: one builds a job list, the other holds a resolved job list. The behavior is correct today because the helper is not called inside this function, but the reuse makes the fixture harder to follow.

♻️ Proposed rename
-  const coordinatorJobs = configuredJobs ?? coordinator.jobs ?? defaultCoordinator.jobs;
+  const resolvedCoordinatorJobs = configuredJobs ?? coordinator.jobs ?? defaultCoordinator.jobs;

Update the three references inside runGate({ ... }) (lines 222, 248) to resolvedCoordinatorJobs.

As per coding guidelines: "Use existing repository vocabulary and one name per concept".
🤖 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/skills/check-gates-coordinator-evidence.test.ts` at line 207, Rename the
local constant `coordinatorJobs` to `resolvedCoordinatorJobs` and update all of
its references within the surrounding `runGate({ ... })` setup, while leaving
the module-level `coordinatorJobs` helper unchanged.

Source: Coding guidelines


1151-1166: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add rejection rows for null run-level created_at and updated_at.

The table covers run timestamps that are absent (omitCreatedAt, omitUpdatedAt), malformed, and out of order. It does not cover a run timestamp that is present and null.

This PR widens ActionRunFixture.createdAt and ActionRunFixture.updatedAt to string | null in test/skills/check-gates-test-fixtures.ts (lines 69-70), and actionRunData preserves an explicit null rather than substituting the default. The job-level equivalents already have rows at lines 1117-1122. The run-level null shape therefore has a supported fixture type and no protecting test. A GitHub workflow-run payload can carry "updated_at": null, so the shape is realistic.

Add the two rows, or narrow the two fixture fields back to string if the null shape is not required.

♻️ Proposed rows
     {
       condition: "the coordinator run has no updated_at timestamp",
       coordinator: { omitUpdatedAt: true },
     },
+    {
+      condition: "the coordinator run created_at timestamp is null",
+      coordinator: { createdAt: null },
+    },
+    {
+      condition: "the coordinator run updated_at timestamp is null",
+      coordinator: { updatedAt: null },
+    },
As per coding guidelines: "Do not add configuration, fallback, migration, compatibility, or extension layers without a current requirement; identify the current consumer and protecting test."
🤖 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/skills/check-gates-coordinator-evidence.test.ts` around lines 1151 -
1166, Extend the rejection-case table in the coordinator evidence tests with
cases for run-level created_at and updated_at explicitly set to null, using the
existing fixture properties and matching the job-level null cases. Preserve the
current absent, malformed, and ordering cases.

Source: Coding guidelines


273-298: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Clarify the manual-only fork case in the test title.

check-gates.ts accepts zero automatic predecessors. Rename the test to state this boundary explicitly.

🤖 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/skills/check-gates-coordinator-evidence.test.ts` around lines 273 - 298,
Rename the test describing the repository-owned manual coordinator in
runGateWithCoordinator to explicitly state that the authorized fork revision has
zero automatic predecessors, while leaving its setup and assertions unchanged.
test/skills/check-gates-test-fixtures.ts (3)

352-357: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Share the default observation timestamp with the default partition window.

Line 356 defaults observationTime to "2026-01-01T00:03:00Z". Line 584 independently ends the default coordinator partition at the same instant. The two literals must stay equal, otherwise the injected clock and the discovery window disagree and coordinator tests drift without an obvious cause. Extract one constant.

Note on the static analysis hint at line 356: clockPath derives from fs.mkdtempSync, so no external input reaches the path. Treat the path-traversal warning as a false positive.

♻️ Proposed refactor
+const DEFAULT_OBSERVATION_TIME = "2026-01-01T00:03:00Z";
+
 function runGate(fixture: ComplianceFixture) {
   const observationTime =
     fixture.observationTime ??
     fixture.coordinatorRunPartitions?.at(-1)?.createdRange.split("..")[1] ??
-    "2026-01-01T00:03:00Z";
+    DEFAULT_OBSERVATION_TIME;
     {
-      createdRange: "2026-01-01T00:00:00Z..2026-01-01T00:03:00Z",
+      createdRange: `2026-01-01T00:00:00Z..${DEFAULT_OBSERVATION_TIME}`,
       runPages: coordinatorRunPages,
     },
🤖 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/skills/check-gates-test-fixtures.ts` around lines 352 - 357, Extract a
shared constant for the default observation timestamp and reuse it both in the
observationTime fallback near the clock setup and in the default coordinator
partition window. Remove the duplicated timestamp literal while preserving the
existing fallback behavior; ignore the path-traversal warning for clockPath.

Source: Linters/SAST tools


592-604: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Guard against duplicate (event, createdRange) partitions producing a dead case arm.

The pre-fill loop keys partitions on the (event, createdRange) pair. The generated bash case at line 656 uses one label per partition, built from the same pair. If a fixture declares two partitions with the same event and the same createdRange, the second label is unreachable and its runPages, finalRunPages, and runOverrides never reach the script under test. The test then passes or fails for a reason unrelated to its stated claim.

No current fixture hits this. Add a fail-fast check so a future fixture reports the mistake instead of silently losing evidence.

♻️ Proposed guard
   const coordinatorWorkflowRunCases = coordinatorRunPartitions
     .map((partition, partitionIndex) => {
       const fallbackCreatedAt =
         partition.fallbackCreatedAt ?? partition.createdRange.split("..")[0];
       const event = partition.event ?? "workflow_run";
+      const duplicate = coordinatorRunPartitions.findIndex(
+        (other) =>
+          (other.event ?? "workflow_run") === event &&
+          other.createdRange === partition.createdRange,
+      );
+      if (duplicate !== partitionIndex) {
+        throw new Error(
+          `duplicate coordinator partition for event ${event} and range ${partition.createdRange}`,
+        );
+      }
As per path instructions: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."

Also applies to: 655-656

🤖 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/skills/check-gates-test-fixtures.ts` around lines 592 - 604, Add a
fail-fast validation for duplicate (event, createdRange) pairs in the fixture
partition setup before generating the bash case labels. Update the
partition-building logic around coordinatorRunPartitions and the generated case
construction so duplicate declarations throw a clear error instead of producing
unreachable arms and silently dropping partition data.

Source: Path instructions


96-98: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the untested final partition fields.

No test sets finalTotalCount, finalPageTotalCounts, or finalRunOverrides; only finalRunPages has a test consumer. Remove these fields and their fallback handling, or add tests that require them.

🤖 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/skills/check-gates-test-fixtures.ts` around lines 96 - 98, Remove the
unused finalTotalCount, finalPageTotalCounts, and finalRunOverrides fields from
the fixture type and delete their fallback-handling logic. Preserve
finalRunPages and its existing tested behavior; do not add new support unless
tests are introduced to exercise these fields.

Source: Coding guidelines

.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts (5)

751-762: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the workflow path from E2E_COORDINATOR_WORKFLOW_PATH.

Line 757 hardcodes pr-e2e-gate.yaml, but parseE2eCoordinatorRun validates record.path against E2E_COORDINATOR_WORKFLOW_PATH. If the workflow file is renamed, the two sites drift and the inventory returns runs that the parser then rejects.

♻️ Proposed refactor
+const E2E_COORDINATOR_WORKFLOW_FILE = E2E_COORDINATOR_WORKFLOW_PATH.slice(
+  E2E_COORDINATOR_WORKFLOW_PATH.lastIndexOf("/") + 1,
+);
         "repos/" +
           repo +
-          "/actions/workflows/pr-e2e-gate.yaml/runs?event=" +
+          "/actions/workflows/" +
+          E2E_COORDINATOR_WORKFLOW_FILE +
+          "/runs?event=" +
           event +
🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
751 - 762, Update the workflow-runs API path in the pages query to derive the
filename from the existing E2E_COORDINATOR_WORKFLOW_PATH constant instead of
hardcoding pr-e2e-gate.yaml, keeping it consistent with parseE2eCoordinatorRun
validation.

1001-1035: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the external-id and check-name constants.

selectE2eCoordinationCheck (line 1006) and e2eCoordinationHistoryStartedAt (line 1034) build the same nemoclaw-pr-e2e:v2:... string, and fetchE2eCoordinationEvidence repeats checkNames at line 1065. Three copies must change together when the external-id version changes.

♻️ Proposed refactor
+const E2E_COORDINATION_CHECK_NAMES = ["E2E / PR Gate", "E2E / PR Gate Coordination"];
+
+function e2eCoordinationExternalId(exactDiff: ExactDiffIdentity): string {
+  return `nemoclaw-pr-e2e:v2:${exactDiff.number}:${exactDiff.headSha}:${exactDiff.baseSha}`;
+}
🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
1001 - 1035, Extract shared constants or helper symbols for the E2E coordination
external ID format and accepted check names, then update
selectE2eCoordinationCheck, e2eCoordinationHistoryStartedAt, and
fetchE2eCoordinationEvidence to reuse them. Ensure all three paths retain the
current values and filtering behavior while eliminating duplicated definitions.

603-635: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align the malformed-payload disposition inside the job loop.

Line 604 returns { result: null } for a malformed page object, but line 630 returns { result: false } for a malformed job object. Both cases describe an unusable API payload. The current split makes a malformed job record a hard rejection and a malformed page an indeterminate result. The behavior is fail-closed, so this is a consistency concern only. Pick one disposition for malformed payload shape.

🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
603 - 635, Align the malformed-payload handling in the job-page loop by using
the same result disposition for invalid page objects and invalid job records.
Update the return in the record validation branch alongside the existing
page-object check, preserving all validation conditions and fail-closed
behavior.

2770-2783: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Guard prData.statusCheckRollup when building capturedRevision.

Line 2756 already treats the field as possibly absent through statusCheckRollup && statusCheckRollup.length > 0 inside checkCi, and line 2758 guards prData.files with ?? []. Line 2782 assigns the value directly into a field declared as non-optional StatusCheck[]. If gh pr view omits the field, the snapshot holds undefined behind a non-optional type. checkFinalRevision does not read the field today, so no failure occurs now, but a future comparison on it would dereference undefined.

🛡️ Proposed fix
     headRepository,
-    statusCheckRollup: prData.statusCheckRollup,
+    statusCheckRollup: prData.statusCheckRollup ?? [],
   };
🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
2770 - 2783, Update the capturedRevision construction to normalize
prData.statusCheckRollup to an empty StatusCheck[] when the field is absent,
preserving existing values when present. Keep the non-optional statusCheckRollup
contract intact and limit the change to the capturedRevision assignment.

741-841: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Consider the API call volume of the partitioned inventory.

The loop issues one paginated gh api request for each event and partition pair. With the 14-day maximum and 12-hour partitions, that reaches 56 paginated requests before candidate validation adds three more requests per candidate. Each request carries the 120 s run() timeout from shared.ts. For a maintainer-invoked CLI the latency is acceptable, but consider widening E2E_COORDINATOR_PARTITION_MS or narrowing the inventory window when the check start is recent.

🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
741 - 841, Reduce partitioned inventory API volume for recent checks by widening
E2E_COORDINATOR_PARTITION_MS or narrowing the inventory window before
e2eCoordinatorRunPartitions creates partitions. Preserve the existing 14-day and
12-hour behavior for older or non-recent checks, and keep candidate validation
unchanged.
🤖 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 1973-1974: Update captureRequiredCheckSnapshot to sort
JSON-serialized entries using a deterministic code-unit comparison instead of
localeCompare, returning a total ordering for distinct strings. Keep
checkFinalCi and checkLastCi unchanged so their deep snapshot comparisons no
longer depend on GitHub rollup input order.
- Around line 1533-1534: Update isCurrentE2eSeedRun to require the run’s
coordination-cycle identifier to match the selected coordination check, in
addition to the existing e2eControllerHeadBinding and e2eGateRun conditions. Add
a regression test covering a stale seed run from before a newer coordination
check, ensuring it is rejected even when the head binding is “current.”

---

Nitpick comments:
In @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:
- Around line 751-762: Update the workflow-runs API path in the pages query to
derive the filename from the existing E2E_COORDINATOR_WORKFLOW_PATH constant
instead of hardcoding pr-e2e-gate.yaml, keeping it consistent with
parseE2eCoordinatorRun validation.
- Around line 1001-1035: Extract shared constants or helper symbols for the E2E
coordination external ID format and accepted check names, then update
selectE2eCoordinationCheck, e2eCoordinationHistoryStartedAt, and
fetchE2eCoordinationEvidence to reuse them. Ensure all three paths retain the
current values and filtering behavior while eliminating duplicated definitions.
- Around line 603-635: Align the malformed-payload handling in the job-page loop
by using the same result disposition for invalid page objects and invalid job
records. Update the return in the record validation branch alongside the
existing page-object check, preserving all validation conditions and fail-closed
behavior.
- Around line 2770-2783: Update the capturedRevision construction to normalize
prData.statusCheckRollup to an empty StatusCheck[] when the field is absent,
preserving existing values when present. Keep the non-optional statusCheckRollup
contract intact and limit the change to the capturedRevision assignment.
- Around line 741-841: Reduce partitioned inventory API volume for recent checks
by widening E2E_COORDINATOR_PARTITION_MS or narrowing the inventory window
before e2eCoordinatorRunPartitions creates partitions. Preserve the existing
14-day and 12-hour behavior for older or non-recent checks, and keep candidate
validation unchanged.

In `@test/skills/check-gates-coordinator-evidence.test.ts`:
- Line 207: Rename the local constant `coordinatorJobs` to
`resolvedCoordinatorJobs` and update all of its references within the
surrounding `runGate({ ... })` setup, while leaving the module-level
`coordinatorJobs` helper unchanged.
- Around line 1151-1166: Extend the rejection-case table in the coordinator
evidence tests with cases for run-level created_at and updated_at explicitly set
to null, using the existing fixture properties and matching the job-level null
cases. Preserve the current absent, malformed, and ordering cases.
- Around line 273-298: Rename the test describing the repository-owned manual
coordinator in runGateWithCoordinator to explicitly state that the authorized
fork revision has zero automatic predecessors, while leaving its setup and
assertions unchanged.

In `@test/skills/check-gates-test-fixtures.ts`:
- Around line 352-357: Extract a shared constant for the default observation
timestamp and reuse it both in the observationTime fallback near the clock setup
and in the default coordinator partition window. Remove the duplicated timestamp
literal while preserving the existing fallback behavior; ignore the
path-traversal warning for clockPath.
- Around line 592-604: Add a fail-fast validation for duplicate (event,
createdRange) pairs in the fixture partition setup before generating the bash
case labels. Update the partition-building logic around coordinatorRunPartitions
and the generated case construction so duplicate declarations throw a clear
error instead of producing unreachable arms and silently dropping partition
data.
- Around line 96-98: Remove the unused finalTotalCount, finalPageTotalCounts,
and finalRunOverrides fields from the fixture type and delete their
fallback-handling logic. Preserve finalRunPages and its existing tested
behavior; do not add new support unless tests are introduced to exercise these
fields.
🪄 Autofix

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: 63cfc202-6bcc-4310-a891-bae896e7b3a3

📥 Commits

Reviewing files that changed from the base of the PR and between 8683777 and f3b9686.

📒 Files selected for processing (3)
  • .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts
  • test/skills/check-gates-coordinator-evidence.test.ts
  • test/skills/check-gates-test-fixtures.ts

Comment on lines +1533 to +1534
const isCurrentE2eSeedRun = (run: ActionRunMetadata): boolean =>
e2eControllerHeadBinding(run) === "current" && run.e2eGateRun === true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Inspect seed-run recognition, controller head binding, and coordinator enclosure rules.
set -euo pipefail

fd -t f 'check-gates.ts' .agents | while IFS= read -r file; do
  echo "== $file"
  rg -n -C 6 'isCurrentE2eSeedRun|e2eControllerHeadBinding|coordinateStartedAt <= coordinationCompletedAt' "$file"
done

# Surface tests that assert seed-run timing behavior.
fd -t f -e ts . test | while IFS= read -r file; do
  rg -n -C 4 'seed[ -]?run|e2eGateRun|coordination(Started|Completed)At' "$file" || true
done

Repository: NVIDIA/NemoClaw

Length of output: 3510


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts"

echo "== coordinator evidence validation =="
sed -n '650,735p' "$file"
sed -n '1060,1120p' "$file"

echo "== run binding and classification =="
sed -n '1450,1555p' "$file"
sed -n '1650,1745p' "$file"

echo "== test fixtures and timing cases =="
rg -n -C 12 'runGateWithCoordinator|custom check completed|retry check|seedRun|coordinationStartedAt|coordinationCompletedAt|latestAttempt' .agents/skills/nemoclaw-maintainer-day test 2>/dev/null || true

Repository: NVIDIA/NemoClaw

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts"

echo "== rollup selection functions =="
sed -n '1580,1675p' "$file"
sed -n '1740,1905p' "$file"

echo "== all current-run selection references =="
rg -n -C 5 'checksFromLatestAttempt|isMeaningfulExactDiffRun|allActionRunIds|latest.*timestamp|updatedAt|createdAt|detailsUrl|currentCheckRollup' "$file" | sed -n '1,260p'

echo "== focused tests =="
rg -n -C 8 'runGateWithCoordinator|seedRun|e2eGateRun|E2E / PR Gate|coordination' .agents/skills/nemoclaw-maintainer-day --glob '*test*.ts' --glob '*.spec.ts' 2>/dev/null | sed -n '1,300p'

Repository: NVIDIA/NemoClaw

Length of output: 20087


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file=".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts"

echo "== E2E evidence selection and trusted check identity =="
sed -n '840,920p' "$file"
sed -n '1120,1180p' "$file"

echo "== required check definitions and final E2E handling =="
rg -n -C 8 'REQUIRED_CHECK_NAMES|E2E / PR Gate|trustedCustomCheckId|incompleteAttemptEvidence|allPass|currentCheckRollup' "$file" | sed -n '1,360p'

echo "== test files containing E2E fixtures =="
git ls-files | rg '(^|/)(test|tests|__tests__)/|\\.test\\.|\\.spec\\.' | head -100

Repository: NVIDIA/NemoClaw

Length of output: 23396


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -l 'runGateWithCoordinator|custom check completed after its seed run|retry check that starts after its authenticated seed run finishes' . | head -20

rg -n -C 18 'custom check completed after its seed run|retry check that starts after its authenticated seed run finishes|seedRun:' . --glob '*.ts' | sed -n '1,420p'

Repository: NVIDIA/NemoClaw

Length of output: 11836


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="test/skills/check-gates-coordinator-evidence.test.ts"

echo "== fixture construction =="
sed -n '1,265p' "$file"

echo "== retry timing fixture =="
sed -n '397,455p' "$file"

echo "== status-check rollup and mocked action runs =="
rg -n -C 10 'statusCheckRollup|check-runs|E2E / PR Gate|detailsUrl|seedJobs|extraRuns|runId' "$file" | sed -n '1,360p'

Repository: NVIDIA/NemoClaw

Length of output: 21840


🏁 Script executed:

python3 - <<'PY'
from datetime import datetime, timezone

def ts(value):
    return datetime.fromisoformat(value.replace("Z", "+00:00")).timestamp()

# Model the predicates at e2eControllerHeadBinding and isCurrentE2eSeedRun.
seed = {
    "event": "pull_request_target",
    "path": ".github/workflows/pr-e2e-gate.yaml",
    "exactDiff": None,
    "e2eGateDiff": True,
    "e2eGateRun": True,
    "hasPullRequests": False,
    "headShaMatches": True,
    "headRefNameMatches": True,
    "headRepositoryMatches": True,
    "createdAt": ts("2026-08-04T14:07:32Z"),
    "updatedAt": ts("2026-08-04T14:08:01Z"),
}
coordination = {
    "valid": True,
    "startedAt": ts("2026-08-04T14:28:06Z"),
    "completedAt": ts("2026-08-04T14:38:01Z"),
}

binding = (
    coordination["valid"]
    and seed["event"] == "pull_request_target"
    and seed["path"] == ".github/workflows/pr-e2e-gate.yaml"
    and seed["e2eGateDiff"] is True
    and seed["hasPullRequests"] is False
    and seed["headShaMatches"] is True
    and seed["headRefNameMatches"] is True
    and seed["headRepositoryMatches"] is True
)
classified_current = binding and seed["e2eGateRun"] is True

print({
    "seed_finished_before_coordination_started":
        seed["updatedAt"] < coordination["startedAt"],
    "controller_binding": "current" if binding else "unknown",
    "isCurrentE2eSeedRun": classified_current,
    "seed_window_checked": False,
})
assert classified_current is True
assert seed["updatedAt"] < coordination["startedAt"]
PY

Repository: NVIDIA/NemoClaw

Length of output: 297


Bind the E2E seed run to the selected coordination cycle. A seed run that finished before the coordination check started still returns current; exact head identity does not distinguish attempts. Add an explicit cycle binding and a regression test for a stale seed with a newer coordination check.

🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
1533 - 1534, Update isCurrentE2eSeedRun to require the run’s coordination-cycle
identifier to match the selected coordination check, in addition to the existing
e2eControllerHeadBinding and e2eGateRun conditions. Add a regression test
covering a stale seed run from before a newer coordination check, ensuring it is
rejected even when the head binding is “current.”

Comment on lines +1973 to +1974
snapshot.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
return snapshot;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Sort the snapshot with a code-unit comparison instead of localeCompare.

captureRequiredCheckSnapshot sorts by JSON.stringify(...).localeCompare(...), and checkFinalCi and checkLastCi then compare snapshots with isDeepStrictEqual. Default collation can report two distinct strings as equal. For such a tie, Array.prototype.sort keeps the input order, and the input order comes from the GitHub rollup, which can differ between the initial, final, and last reads. That produces a false "Required check rollup changed during gate evaluation" rejection. A plain code-unit comparison gives a total order and removes the tie.

🐛 Proposed fix
-  snapshot.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
+  snapshot.sort((left, right) => {
+    const leftKey = JSON.stringify(left);
+    const rightKey = JSON.stringify(right);
+    return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
+  });
📝 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.

Suggested change
snapshot.sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
return snapshot;
snapshot.sort((left, right) => {
const leftKey = JSON.stringify(left);
const rightKey = JSON.stringify(right);
return leftKey < rightKey ? -1 : leftKey > rightKey ? 1 : 0;
});
return snapshot;
🤖 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 @.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts around lines
1973 - 1974, Update captureRequiredCheckSnapshot to sort JSON-serialized entries
using a deterministic code-unit comparison instead of localeCompare, returning a
total ordering for distinct strings. Keep checkFinalCi and checkLastCi unchanged
so their deep snapshot comparisons no longer depend on GitHub rollup input
order.

@github-actions

github-actions Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 4 warnings · 2 suggestions
  • Model comparison: normalized findings differ; normalized terminology decisions differ; normalized E2E selections match; Nemotron reported the same number of blockers, 4 more warnings, 2 more suggestions.
7 terminology differences from the second opinion

Advisory only. These are normalized differences from the primary terminology receipt.

  • gate evaluation at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:2114: selected only by the second-opinion lane as established.
  • E2E custom-check at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:2149: selected only by the second-opinion lane as established.
  • enclosing coordinator at test/skills/check-gates-coordinator-evidence.test.ts:371: selected only by the second-opinion lane as define.
  • E2E coordinator at test/skills/check-gates-coordinator-evidence.test.ts:263: selected only by the second-opinion lane as justified.
  • authorization predecessor at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:555: selected only by the second-opinion lane as define.
  • final evidence at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:2150: selected only by the second-opinion lane as justified.
  • required check rollup at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:2114: selected only by the second-opinion lane as justified.

Second-opinion terminology and E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

3 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • established — latest-attempt evidence at test/skills/check-gates-coordinator-evidence.test.ts:351: Keep the established term for current-attempt validation.
  • justified — custom-check history at .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts:2149: Keep the modifier because it distinguishes complete historical evidence from one selected check.
  • justified — coordinator evidence at test/skills/check-gates-coordinator-evidence.test.ts:263: Keep the term because it names a distinct evidence source used by the gate.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: None

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@wscurran wscurran added area: ci CI workflows, checks, release automation, or GitHub Actions area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression labels Aug 4, 2026
@cv

cv commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Closed as superseded by #8258. The successor preserves this PR's authored commits and attribution, carries the same effective four-file change plus mechanical merges from main, and avoids force-pushing this published branch.

@cv cv closed this Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ci CI workflows, checks, release automation, or GitHub Actions area: e2e End-to-end tests, nightly failures, or validation infrastructure bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants