Skip to content

ci(deps): validate OpenShell candidate runtime#6738

Open
HOYALIM wants to merge 4 commits into
NVIDIA:mainfrom
HOYALIM:codex/issue-6691-candidate-compat
Open

ci(deps): validate OpenShell candidate runtime#6738
HOYALIM wants to merge 4 commits into
NVIDIA:mainfrom
HOYALIM:codex/issue-6691-candidate-compat

Conversation

@HOYALIM

@HOYALIM HOYALIM commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Summary

  • narrow the first Run speculative compatibility tests against candidate OpenShell, OpenClaw, Hermes, and DCode versions #6691 vertical slice to OpenShell so every accepted artifact has verifiable official provenance and a complete execution path
  • bind the Linux CLI, gateway, and sandbox release assets and SHA-256 digests to one immutable resolution ID for an exact NemoClaw SHA
  • run the installer lane through receipt-bound wrappers and require proof that all three candidate binaries were invoked
  • run the existing openshell-gateway-auth-contract live test against the materialized candidate and require proof that the candidate gateway was started, not merely version-probed
  • publish deterministic and live results in one durable evidence artifact without changing pin authorities or granting write permissions

The earlier Hermes and OpenClaw paths were removed: Hermes included an artifact not controlled by NousResearch, while OpenClaw's top-level tarball did not bind its transitive dependency closure. Those components need separate provenance-complete slices before they can be added safely.

Validation

  • npm run typecheck:cli
  • npx vitest run test/candidate-compat.test.ts test/e2e/support/openshell-gateway-auth-source-contract-helpers.test.ts test/e2e/support/openshell-gateway-auth-contract-workflow-boundary.test.ts (27 passed)
  • npm run source-shape:check (0 unbudgeted cases)
  • npm run check:diff
  • resolved OpenShell v0.0.82 for chore(openshell): upgrade supported version to 0.0.82 #6726 head 81895e0967a17b6d063ecaf4482aab7a4ee2b9a0; bound all three official release digests to resolution 55cffa81b9833cf7adbd0099cc7740f1a42038cdb3b4e3cc51b5b4ab4e45dda3

Local Docker runtime evidence could not be produced because the local Docker daemon was unavailable. The new Ubuntu live job executes that exact gateway-auth contract and fails closed if runtime invocation proof is absent.

Refs #6691

Signed-off-by: Ho Lim subhoya@gmail.com

Copilot AI review requested due to automatic review settings July 13, 2026 02:34
@copy-pr-bot

copy-pr-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds candidate compatibility resolution and verification tooling, deterministic lane planning, artifact materialization, evidence finalization, a GitHub Actions workflow, and tests covering provenance, security boundaries, runtime observations, and complete evidence aggregation.

Changes

Candidate Compatibility

Layer / File(s) Summary
Candidate resolution and provenance
tools/candidate-compat.mts, test/candidate-compat.test.ts
Validates candidate inputs and official sources, resolves component artifacts, verifies provenance and digests, and generates stable receipts.
Lane planning and evidence validation
tools/candidate-compat.mts, test/candidate-compat.test.ts
Builds deterministic and live lanes, verifies observed candidates, and requires complete, consistent lane results before finalizing evidence.
Candidate materialization and CLI commands
tools/candidate-compat.mts, test/candidate-compat.test.ts
Downloads and verifies artifacts, installs component runtimes, captures observed versions, and implements the resolve, plan, materialize, and finalize commands.
Compatibility workflow orchestration
.github/workflows/candidate-compatibility.yaml, test/candidate-compat.test.ts, ci/source-shape-test-budget.json
Dispatches compatibility runs, executes planned lanes against the resolved NemoClaw commit, uploads evidence, and enforces workflow security contracts.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant CandidateCLI
  participant NemoClawCheckout
  participant CandidateRuntime
  GitHubActions->>CandidateCLI: resolve candidate and generate plan
  CandidateCLI-->>GitHubActions: receipt and lane matrix
  GitHubActions->>NemoClawCheckout: checkout resolved NemoClaw SHA
  GitHubActions->>CandidateRuntime: materialize candidate and run lane
  CandidateRuntime-->>GitHubActions: observed output and lane result
  GitHubActions->>CandidateCLI: finalize lane evidence
  CandidateCLI-->>GitHubActions: auditable compatibility evidence
Loading

Suggested labels: integration: hermes, integration: openclaw, area: cli

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is related to the PR, but it only highlights OpenShell runtime validation and omits the broader candidate compatibility workflow and tooling changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@HOYALIM HOYALIM force-pushed the codex/issue-6691-candidate-compat branch from 4fe9f8c to 05fedce Compare July 13, 2026 02:43

@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.

🧹 Nitpick comments (1)
tools/candidate-compat.mts (1)

552-564: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Validate the initial artifact URL host before issuing the request.

download uses redirect: "follow" and only checks the host of the final response.url. The initial request to artifactValue.url is issued before any host check, so a tampered receipt URL would still trigger an outbound fetch to an arbitrary host. The receipt is produced by the trusted resolve job, so this is defense-in-depth rather than an active exploit, but re-asserting the host on the initial URL is cheap and closes the gap.

🛡️ Proposed defense-in-depth check
 async function download(artifactValue: Artifact, directory: string): Promise<string> {
+  const requestUrl = new URL(artifactValue.url);
+  if (requestUrl.protocol !== "https:" || !DOWNLOAD_HOSTS.has(requestUrl.hostname)) {
+    throw new Error(`candidate artifact is not on an approved download host: ${artifactValue.url}`);
+  }
   const response = await fetch(artifactValue.url, { redirect: "follow" });
   if (!response.ok) throw new Error(`candidate download failed (${response.status})`);
🤖 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/candidate-compat.mts` around lines 552 - 564, Update download to parse
and validate artifactValue.url against the approved HTTPS protocol and
DOWNLOAD_HOSTS before calling fetch, rejecting unapproved initial hosts while
preserving the existing final response URL validation.
🤖 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.

Nitpick comments:
In `@tools/candidate-compat.mts`:
- Around line 552-564: Update download to parse and validate artifactValue.url
against the approved HTTPS protocol and DOWNLOAD_HOSTS before calling fetch,
rejecting unapproved initial hosts while preserving the existing final response
URL validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6b2028c0-76d0-4737-9143-32cb81fc4ff1

📥 Commits

Reviewing files that changed from the base of the PR and between deed1aa and 4fe9f8c.

📒 Files selected for processing (4)
  • .github/workflows/candidate-compatibility.yaml
  • ci/source-shape-test-budget.json
  • test/candidate-compat.test.ts
  • tools/candidate-compat.mts

@cv cv added the v0.0.82 Release target label Jul 13, 2026
Comment thread tools/candidate-compat.mts Fixed
Comment thread tools/candidate-compat.mts Fixed
Signed-off-by: Ho Lim <subhoya@gmail.com>
@HOYALIM HOYALIM force-pushed the codex/issue-6691-candidate-compat branch from 05fedce to ae774d4 Compare July 13, 2026 06:22

@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.

🧹 Nitpick comments (2)
tools/candidate-compat.mts (1)

111-121: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Use code-point ordering in stableJson resolutionId and the equality checks built from this helper should not depend on locale/ICU collation.

♻️ Use deterministic code-point ordering
-      .sort(([left], [right]) => left.localeCompare(right))
+      .sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0))
🤖 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/candidate-compat.mts` around lines 111 - 121, Update stableJson’s
object-key sort to use deterministic code-point ordering rather than
localeCompare. Preserve the existing filtering, serialization, and recursive
traversal behavior while ensuring generated strings are independent of locale or
ICU collation.
.github/workflows/candidate-compatibility.yaml (1)

162-175: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pass resolution_id via env: instead of interpolating into the shell body.

Line 172 expands ${{ needs.resolve.outputs.resolution_id }} directly into the run script, unlike every other step here which passes values through env: (e.g. LANE). The value is validated to ^[a-f0-9]{64}$ at line 85 so actual injection risk is nil, but keeping it as an env reference silences the scanner and honors the untrusted-as-data convention.

🔒 Proposed change to pass the value as data
         env:
           LANE: ${{ matrix.lane }}
+          RESOLUTION_ID: ${{ needs.resolve.outputs.resolution_id }}
         shell: bash
         run: |
           set -euo pipefail
           node --experimental-strip-types controller/tools/candidate-compat.mts materialize \
             --receipt candidate-input/candidate-receipt.json \
-            --resolution-id "${{ needs.resolve.outputs.resolution_id }}" \
+            --resolution-id "$RESOLUTION_ID" \
             --directory "${RUNNER_TEMP}/candidate-runtime" \
             --output "candidate-observed-${LANE}.json" \
             --github-env "$GITHUB_ENV" 2>&1 | tee "candidate-materialize-${LANE}.log"

As per path instructions: "pass untrusted values as data rather than interpolating them into shell programs."

🤖 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/candidate-compatibility.yaml around lines 162 - 175,
Update the “Materialize and verify candidate runtime” step to add
needs.resolve.outputs.resolution_id to its env mapping, then reference that
environment variable in the candidate-compat materialize command instead of
interpolating the GitHub expression directly in the shell script. Preserve the
existing resolution ID value and command 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.

Nitpick comments:
In @.github/workflows/candidate-compatibility.yaml:
- Around line 162-175: Update the “Materialize and verify candidate runtime”
step to add needs.resolve.outputs.resolution_id to its env mapping, then
reference that environment variable in the candidate-compat materialize command
instead of interpolating the GitHub expression directly in the shell script.
Preserve the existing resolution ID value and command behavior.

In `@tools/candidate-compat.mts`:
- Around line 111-121: Update stableJson’s object-key sort to use deterministic
code-point ordering rather than localeCompare. Preserve the existing filtering,
serialization, and recursive traversal behavior while ensuring generated strings
are independent of locale or ICU collation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d87636d0-b189-4b6a-8730-8c380b6a5681

📥 Commits

Reviewing files that changed from the base of the PR and between 05fedce and ae774d4.

📒 Files selected for processing (4)
  • .github/workflows/candidate-compatibility.yaml
  • ci/source-shape-test-budget.json
  • test/candidate-compat.test.ts
  • tools/candidate-compat.mts
🚧 Files skipped from review as they are similar to previous changes (2)
  • ci/source-shape-test-budget.json
  • test/candidate-compat.test.ts

@wscurran wscurran added area: ci CI workflows, checks, release automation, or GitHub Actions chore Build, CI, dependency, or tooling maintenance integration: dcode LangChain Deep Code integration behavior labels Jul 13, 2026
@wscurran

Copy link
Copy Markdown
Contributor

✨ Thanks for the CI infrastructure work, @HOYALIM. Adding a maintainer-dispatched compatibility controller for candidate versions will improve our validation coverage. Ready for maintainer review.


Related open issues:

@cjagwani cjagwani 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.

Reviewed exact head ae774d4. Both manually dispatched Advisors analyzed this head and recommend merge_as_is, but the direct supply-chain review found three blockers their broad checks miss:

  1. High — .github/workflows/candidate-compatibility.yaml:162-248 and tools/candidate-compat.mts:744-812,857-877 can mark a lane successful after standalone materialization plus ordinary tests without proving the lane consumed the candidate. NEMOCLAW_CANDIDATE_* has no repository consumer; the recorded version is a pre-lane probe. Require trusted, receipt-bound evidence that each selected install/build/runtime path actually invoked the candidate, and fail if that proof is absent.

  2. Medium — tools/candidate-compat.mts:347-356,530-536,748-787 admits npm hermes-agent as an official Hermes artifact using only version equality. The package's own registry metadata identifies it as an unofficial bridge from wyrtensi/hermes-agent-npm, while the receipt labels NousResearch. A digest authenticates those bytes, not official provenance. Remove it or replace it with an artifact verifiably controlled by the official upstream.

  3. Medium — tools/candidate-compat.mts:249-269,432-440,789-798 materializes OpenClaw with npm install from only a verified top-level tarball. The transitive closure is neither policy-checked nor bound into resolutionId/evidence; current caret dependencies make identical resolution IDs capable of executing different bytes. Resolve and bind a complete lock/integrity closure in the trusted resolve job, install from it, and preserve it in evidence.

Terra's process-boundary test warning is therefore blocking, not cosmetic. Add a fixture-based materialize CLI regression that validates observed JSON, PATH/candidate env output, actual candidate invocation, and fail-closed version mismatch.

@cjagwani cjagwani self-assigned this Jul 13, 2026
@cjagwani cjagwani added v0.0.83 Release target and removed v0.0.82 Release target labels Jul 13, 2026
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / low confidence
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions
Status: Partial review preserved 1 canonical finding(s) before the advisor stopped.

Model lanes

  • GPT-5.6 Terra (primary): Failed after a partial review · low confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

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

Recommended E2E: cloud-onboard, credential-sanitization, security-posture, openshell-gateway-auth-contract

1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Cover artifact parsing in the finalize CLI path

  • Location: tools/candidate-compat.mts:905
  • Category: tests
  • Problem: The `finalize` command parses downloaded receipt and plan JSON with type assertions and passes them directly to `finalizeEvidence`; existing tests exercise `finalizeEvidence` only with constructed valid objects. A malformed plan whose selected lane lists are empty can therefore allow an empty result directory to produce successful aggregate evidence without exercising the complete-evidence check.
  • Impact: Malformed or incompatible downloaded control-plane artifacts could be classified as a successful compatibility result without evidence for the intended deterministic or live lanes.
  • Recommendation: Validate the downloaded receipt and plan against their schemas and expected component/selection before finalization, and add a hermetic CLI-level regression test for malformed or empty-selected plan artifacts.
  • Verification: Inspect the `finalize` branch in `tools/candidate-compat.mts` and add a test invoking it with a receipt-bound but malformed plan containing no selected lanes and an empty results directory; verify it exits nonzero.
  • Test coverage: A hermetic CLI/integration test that writes a valid receipt plus a malformed plan with zero selected lanes and no result files, invokes `candidate-compat.mts finalize`, and asserts rejection rather than `overall: success`.
  • Evidence: `main` parses `candidate-receipt.json` and `candidate-plan.json` with `JSON.parse(...) as CandidateReceipt` / `as CandidatePlan` in the `finalize` branch. `finalizeEvidence` derives its required lane set solely from `input.plan`; when both selected lists are empty, its exact-result-set check accepts an empty `results` array and `every(...)` reports success. `test/candidate-compat.test.ts` tests `finalizeEvidence` with constructed plans/results, but no test covers CLI parsing of downloaded plan or receipt artifacts.

Workflow run details

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

@cv cv added v0.0.84 Release target and removed v0.0.83 Release target labels Jul 14, 2026
@cv cv assigned cv and unassigned jyaunches and cjagwani Jul 14, 2026
Signed-off-by: Ho Lim <subhoya@gmail.com>
@HOYALIM HOYALIM changed the title ci(deps): add candidate compatibility workflow ci(deps): validate OpenShell candidate runtime Jul 14, 2026
@HOYALIM

HOYALIM commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the requested supply-chain redesign in verified commit 375e45941. The PR is now an OpenShell-only vertical slice: it removes the unofficial Hermes npm path and unbound OpenClaw install, binds the official CLI/gateway/sandbox release digests to one receipt, requires per-lane wrapper invocation evidence, and runs the existing gateway-auth live test against the candidate. Validation: npm run typecheck:cli; 27 focused tests passed; npm run source-shape:check; npm run check:diff. The PR title/body now describe the narrowed scope and the local Docker limitation; GitHub CI owns the Ubuntu live proof.

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] .github/workflows/candidate-compatibility.yaml:177-216 and tools/candidate-compat.mts:655-689 — the deterministic installer lane still does not prove the tests exercised the candidate. The workflow invokes each wrapper with --version before running Vitest, and verifyCandidateInvocations accepts exactly those three probes as sufficient for an installer success. Nothing requires an installer test to invoke a candidate binary during the tested install/build path, so a suite that uses only fixtures or the committed stable pin can still emit successful candidate evidence. This leaves the original process-boundary blocker unresolved and does not meet #6691, which requires normal deterministic coverage to run against the candidate environment and every candidate-aware job to report the runtime it actually exercised. Require receipt-bound invocation from the installer behavior under test (not a pre-lane probe), or select a deterministic test that performs and verifies a real candidate install/runtime path; add a negative regression where only the three preflight --version calls occur and the lane is rejected.

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 chore Build, CI, dependency, or tooling maintenance integration: dcode LangChain Deep Code integration behavior v0.0.84 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants