Skip to content

ci(wsl): bootstrap trusted workflow helper - #7719

Merged
cv merged 13 commits into
mainfrom
codex/issue-6958-trusted-helper
Jul 28, 2026
Merged

ci(wsl): bootstrap trusted workflow helper#7719
cv merged 13 commits into
mainfrom
codex/issue-6958-trusted-helper

Conversation

@cv

@cv cv commented Jul 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add the tested WSL provisioning helper to a trusted main revision before consumer workflows adopt it. This helper-only PR is the first stage of #6958 so root-capable WSL execution can fail closed until the helper is present on main.

Related Issue

Part of #6958
Parent: #6952
Previous staged extraction: #7709 (merged into this branch and reverted)
Previous replacement extraction: #7737 (merged into this branch and reverted)
Next step: recreate the extraction directly from main after this PR lands

Changes

  • Add tools/wsl/ci-helper.ps1 for WSL path conversion, LF-safe script transfer, command construction, distro provisioning, Node.js installation, and ext4 checkout synchronization.
  • Add direct PowerShell batch tests for quoting, spaces, drive-letter conversion, LF encoding, optional-argument binding, deletion-path restrictions, install retry behavior, exit propagation, and temporary-script cleanup on success and failure.
  • Bootstrap the helper separately because Move WSL provisioning programs out of workflow YAML #6958 requires the helper to be trusted before root-capable WSL execution. A combined first change cannot satisfy that requirement because its pull-request base does not yet contain the helper.
  • Preserve the audit trail with signed, non-force reverts after ci: finish executable workflow extraction #7709 and ci: finish executable workflow extraction #7737 were merged into this staging branch. The resulting PR diff is helper-only again.

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 adds an internal CI helper and direct tests. Consumer workflow adoption will be recreated in a separate PR after this helper lands, so no user-facing or contributor-facing contract changes here.
  • 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: Codex security review at 3a5ebeb2f passed all nine categories, and the helper files at 92507d621 are byte-for-byte unchanged. The helper keeps WSL arguments separate and quotes shell values. Sync deletion is limited to one positive run-ID/attempt child under the two workflow-owned roots and fails closed for symlinked roots, bidirectional checkout overlap, traversal, and unrelated paths. Package and owner inputs are validated, pinned Node.js archives are verified, transferred scripts are deleted in finally, and direct tests protect these boundaries.
  • 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; writing review passed with no findings
  • Evidence: At exact head 92507d621762bb77ac7e76baf50d9a7c6ee87f28 and base bbdd85008c34503ea47d4a80d57e90074ff3c79e, the exact-base diff adds only tools/wsl/ci-helper.ps1 and test/wsl-ci-helper.test.ts. Both match the previously reviewed helper tree. No documentation sources or user-facing contracts changed. Twelve PowerShell cases were discovered and skipped because PowerShell is unavailable locally; source architecture checks, CLI type-check, normal hooks, and diff check passed.
  • 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
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification: The focused integration command collected all twelve direct PowerShell cases and skipped them because PowerShell is unavailable locally; PR CI runs them on a PowerShell-capable shard. npm run checks, npm run typecheck:cli, normal hooks, and the diff check passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • 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

  • New Features
    • Added a Windows-to-WSL CI helper that generates Ubuntu provisioning and checkout-sync scripts, provisions apt dependencies, and installs a pinned Node.js version in the target distro.
    • Added strict Windows path conversion to /mnt/..., safe bash literal escaping, and LF-only UTF-8 script writing without a byte-order mark.
    • Improved WSL distro install robustness with bounded retries and safe checkout workdir validation.
  • Tests
    • Added Vitest coverage for conversions, WSL argument construction, generated scripts, distro retry recovery, workdir rejection, exit propagation, and temporary-script cleanup.

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-code-quality

github-code-quality Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 92507d6 in the codex/issue-6958-tru... branch remains at 96%, unchanged from commit f90c792 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 92507d6 in the codex/issue-6958-tru... branch remains at 81%, unchanged from commit bbdd850 in the main branch.


Updated July 28, 2026 16:06 UTC

@cv cv added area: ci CI workflows, checks, release automation, or GitHub Actions platform: wsl Affects Windows Subsystem for Linux labels Jul 28, 2026
@cv cv self-assigned this Jul 28, 2026
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a trusted PowerShell WSL helper for execution, distro initialization, provisioning, workflow path setup, and ext4 checkout synchronization. Migrates WSL workflows to the helper and adds tests for helper behavior, trusted loading, workflow boundaries, and environment-based needs handling.

Changes

Trusted WSL CI orchestration

Layer / File(s) Summary
Script execution and safety
tools/wsl/ci-helper.ps1, test/wsl-ci-helper.test.ts
Adds path conversion, Bash escaping, LF-only UTF-8 script writing, WSL invocation, temporary-file cleanup, and success/failure coverage.
Workflow paths and distro initialization
tools/wsl/ci-helper.ps1, test/wsl-ci-helper.test.ts
Computes workflow paths and initializes Ubuntu with bounded retries, partial-registration cleanup, initialization, and default-distro setup.
Ubuntu and Node provisioning
tools/wsl/ci-helper.ps1, test/wsl-ci-helper.test.ts
Generates validated Ubuntu dependency scripts and installs a pinned, checksum-verified, architecture-aware Node.js archive.
Ext4 checkout synchronization
tools/wsl/ci-helper.ps1, test/wsl-ci-helper.test.ts
Validates dedicated workdirs, rejects overlap, synchronizes checkout contents, configures Git safety, resets and cleans to HEAD, and optionally applies ownership.
Trusted workflow integration
.github/workflows/platform-vitest-main.yaml, .github/workflows/wsl-e2e.yaml, test/platform-vitest-main-workflow.test.ts, test/helpers/*, test/vitest-watch-triggers.test.ts, ci/source-shape-test-budget.json
Migrates WSL jobs to trusted helper execution, separates trusted and candidate checkouts, and updates workflow security and trigger contracts.

Environment-based needs handling

Layer / File(s) Summary
Workflow needs transport
.github/workflows/e2e.yaml
Passes needs through NEEDS_JSON and parses it at runtime in reporting and scorecard scripts.
Needs transport validation
tools/e2e/operations-workflow-boundary.mts, test/e2e/support/e2e-operations-workflow-boundary.test.ts
Requires environment-based needs transport and rejects direct or obscured script interpolation patterns.

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

Sequence Diagram(s)

sequenceDiagram
  participant Workflow
  participant TrustedHelper
  participant RunnerTemp
  participant WSL
  participant BashScript
  Workflow->>TrustedHelper: Load trusted helper
  TrustedHelper->>WSL: Ensure distro and provision environment
  TrustedHelper->>RunnerTemp: Write temporary Bash script
  TrustedHelper->>WSL: Sync checkout and invoke script
  WSL->>BashScript: Execute workflow commands
  BashScript-->>WSL: Return output and exit code
  TrustedHelper->>RunnerTemp: Delete temporary script
Loading

Possibly related PRs

Suggested labels: area: security

Suggested reviewers: prekshivyas, brandonpelfrey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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 concise and accurately summarizes the main change: bootstrapping a trusted WSL workflow helper for CI.
✨ 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/issue-6958-trusted-helper

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

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocking findings reported

Advisor assessment: Blockers require maintainer review
Next action: Review the blockers below.
Findings: 1 blocker · 0 warnings · 0 suggestions
Status: Same-session synthesis validation failed; the advisor result is incomplete.

Model lanes

  • GPT-5.6 Terra (primary): Completed · low confidence · 1 blocker · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported 1 fewer blocker, the same number of warnings, the same number of 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: None

Blockers

PRA-1 Blocker — Wire the trusted WSL helper into both workflows

  • Location: .github/workflows/wsl-e2e.yaml:54
  • Category: acceptance
  • Problem: The PR adds the helper, but both WSL workflows retain their inline provisioning programs and do not load it. The new path restrictions and helper behavior therefore do not affect CI.
  • Impact: The workflows continue to execute duplicated inline root-capable WSL provisioning. The new helper and its checkout deletion guard are unconsumed, so the requested trusted-helper extraction is not delivered.
  • Fix: Update both WSL workflows to load a helper verified from the trusted revision before root-capable execution, and replace the duplicated provisioning blocks with its functions while retaining workflow-specific commands.
  • Verification: Read both workflow YAML files and confirm they verify and load `tools/wsl/ci-helper.ps1` before calling its provisioning functions; confirm the duplicate inline provisioning blocks are removed.
  • Test coverage: Add workflow-boundary tests that verify both workflows load the helper from a trusted revision and invoke the extracted helper path rather than inline provisioning.
  • Evidence: Issue Move WSL provisioning programs out of workflow YAML #6958 acceptance criteria require extraction from both workflow YAML files and a trusted-revision helper boundary. `.github/workflows/wsl-e2e.yaml:54-263` retains inline WSL setup and execution. `.github/workflows/platform-vitest-main.yaml:186-363` retains inline WSL setup and execution. `tools/wsl/ci-helper.ps1:352-451` contains the new guarded checkout-sync implementation, but no checked-in workflow calls it.

Workflow run details

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

@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: 1

🧹 Nitpick comments (1)
tools/wsl/ci-helper.ps1 (1)

91-102: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Captured output always merges stderr, unlike Invoke-WslNative's opt-in switch.

Invoke-WslNativeOutput unconditionally does 2>&1, so any stderr text (or the caller's own error records) gets interleaved into Output and later joined into the returned string in Invoke-WslScript (Line 139). Invoke-WslNative instead makes this opt-in via -MergeError. If a future caller uses -CaptureOutput to parse structured output (e.g. git status --short for the ext4 sync layer), stray stderr lines could corrupt the parsed result.

♻️ Proposed fix: make error-stream merging opt-in for consistency
 function Invoke-WslNativeOutput {
     param(
         [Parameter(Mandatory = $true)]
-        [string[]]$ArgumentList
+        [string[]]$ArgumentList,
+
+        [switch]$MergeError
     )
 
-    $output = @(& wsl `@ArgumentList` 2>&1)
+    $output = if ($MergeError) { @(& wsl `@ArgumentList` 2>&1) } else { @(& wsl `@ArgumentList`) }
     return [pscustomobject]@{
         ExitCode = $LASTEXITCODE
         Output = $output
     }
 }
🤖 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/wsl/ci-helper.ps1` around lines 91 - 102, Update Invoke-WslNativeOutput
to make stderr merging opt-in, matching Invoke-WslNative’s MergeError behavior,
while preserving normal stdout capture and the returned ExitCode/Output
structure. Ensure callers only receive stderr entries in Output when the new or
existing merge switch is explicitly enabled.
🤖 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 `@tools/wsl/ci-helper.ps1`:
- Around line 350-399: Validate $Workdir before deriving $workdirParent or
generating the destructive command: reject empty/root paths, and reject paths
equal to or containing $Checkout such that $Workdir is the checkout or an
ancestor of it. Normalize both paths consistently for comparison, throw a clear
error on invalid overlap, and preserve the existing sync behavior only for safe,
non-overlapping workspaces in Get-WslCheckoutSyncScript.

---

Nitpick comments:
In `@tools/wsl/ci-helper.ps1`:
- Around line 91-102: Update Invoke-WslNativeOutput to make stderr merging
opt-in, matching Invoke-WslNative’s MergeError behavior, while preserving normal
stdout capture and the returned ExitCode/Output structure. Ensure callers only
receive stderr entries in Output when the new or existing merge switch is
explicitly enabled.
🪄 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: 838d510c-c4ee-4879-a228-f597bc742c9c

📥 Commits

Reviewing files that changed from the base of the PR and between 45da24e and ff0fcec.

📒 Files selected for processing (2)
  • test/wsl-ci-helper.test.ts
  • tools/wsl/ci-helper.ps1

Comment thread tools/wsl/ci-helper.ps1
Signed-off-by: Carlos Villela <cvillela@nvidia.com>

@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)
test/wsl-ci-helper.test.ts (1)

117-128: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Restore the PowerShell stub after this test.

Invoke-WslScript is replaced but never restored or removed. If runPowerShellBatch reuses a PowerShell session, later cases become order-dependent and may silently call this no-op stub. Wrap the calls in try/finally and restore the original function (or remove the stub); also confirm the batch runner’s isolation behavior.

As per coding guidelines, deterministic tests must undo global stubs. Based on learnings, locally created mocks should be explicitly restored in a finally block.

Suggested cleanup
+$originalInvokeWslScript =
+  (Get-Command Invoke-WslScript -CommandType Function).ScriptBlock
+try {
 function Invoke-WslScript {
   param(
     [string]$Distro,
@@
 Install-WslUbuntuDependencies -Distro Ubuntu -Packages @('curl')
 Install-WslUbuntuDependencies -Distro Ubuntu -Packages @('curl') -TestUser nemoclaw-ci
+} finally {
+  Set-Item Function:\Invoke-WslScript -Value $originalInvokeWslScript
+}
🤖 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/wsl-ci-helper.test.ts` around lines 117 - 128, Update the test setup
around the Invoke-WslScript stub to scope its use with try/finally, and in the
finally block restore the original function or remove the locally created stub.
Ensure runPowerShellBatch completes before cleanup and verify the cleanup
preserves isolation for subsequent test cases.

Sources: Coding guidelines, Learnings

🤖 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 `@test/wsl-ci-helper.test.ts`:
- Around line 117-128: Update the test setup around the Invoke-WslScript stub to
scope its use with try/finally, and in the finally block restore the original
function or remove the locally created stub. Ensure runPowerShellBatch completes
before cleanup and verify the cleanup preserves isolation for subsequent test
cases.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 4b6b611d-0bad-4acd-a3a1-2a362442358e

📥 Commits

Reviewing files that changed from the base of the PR and between ff0fcec and 6585841.

📒 Files selected for processing (2)
  • test/wsl-ci-helper.test.ts
  • tools/wsl/ci-helper.ps1
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/wsl/ci-helper.ps1

cv added 7 commits July 28, 2026 02:24
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
<!-- markdownlint-disable MD041 -->
## Summary

This stacked PR completes #6952 by extracting the remaining repeated
Windows/WSL setup and command construction. It uses the trusted
PowerShell helper bootstrapped by #7719, switches both workflow
consumers to that trusted boundary, and fails closed if the helper is
absent. It also passes the `needs` context through environment data
instead of interpolating it into GitHub Script source.

## Related Issue

Fixes #6952
Fixes #6958

## Changes

- Use `tools/wsl/ci-helper.ps1`, bootstrapped by #7719, for the WSL E2E
and platform Vitest workflows. Both consumers require the same distro
setup, script transfer, Node.js installation, and ext4 checkout
synchronization. Keeping this logic inline duplicated the
security-sensitive command boundary; the helper and workflow regression
tests protect the shared behavior and connection.
- Load the helper through mandatory sparse checkouts at the PR base SHA
or workflow SHA before the candidate checkout. Both workflows fail
closed if the trusted helper is missing; the workflow boundary tests
protect the trusted-source requirement.
- Pass `needs` JSON through `NEEDS_JSON` and parse it inside GitHub
Script. The E2E operations boundary rejects direct expression
interpolation.
- Reduce nonblank executable lines from 191 to 80 in `wsl-e2e.yaml` and
from 228 to 129 in `platform-vitest-main.yaml`. Keep the root-only test
selection inline with an adjacent rationale.

## Type of Change

- [x] 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

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: This changes internal CI
workflows and their tests. It does not change a CLI, configuration,
supported integration, or end-user contract.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: At stacked PR SHA
`d6662d367`, targeted boundary review and tests verify trusted helper
provenance, fail-closed loading, bidirectional checkout/workdir overlap
rejection, command quoting, script encoding, credential-data
interpolation, and root/non-root separation.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `no-docs-needed`
- Evidence: At exact head `d6662d367`, the exact-base diff against
helper head `3a5ebeb2f` contains the expected nine internal workflow,
validator, trigger, and regression-test files. The reviewed overlap
guard is present in both head and base, so helper files do not appear in
this PR diff. No documentation sources changed; focused tests, CLI
type-checking, and the exact-base diff check passed.
- Agent: Codex Desktop
<!-- docs-review-head-sha: d6662d3 -->
<!-- docs-review-agents-blob-sha:
be20a09 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: The
combined focused run passed 50 tests across the platform workflow,
watch-trigger, and E2E boundary suites. It also discovered twelve
PowerShell helper tests and skipped them locally because PowerShell is
unavailable. `npm run typecheck:cli`, the exact-base diff check, normal
commit hooks, and the pre-push TypeScript check passed.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

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


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved reliability and orchestration of WSL-based test runs with
clearer conditional execution and safer setup/sync.
* **Security**
* Strengthened workflow-boundary enforcement so `needs` is provided via
`env` and parsed as JSON (no inline interpolation).
  * Routed WSL provisioning/execution through a trusted helper path.
* **Tests**
* Expanded CI, boundary, and trusted-helper suite coverage for script
generation, path handling, and failure propagation.
  * Updated workflow trigger mappings to include the trusted helper.
* **Chores**
  * Consolidated WSL workflow logic into the shared trusted helper flow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv cv mentioned this pull request Jul 28, 2026
19 tasks
@cv cv added the v0.0.97 label Jul 28, 2026
cv added 2 commits July 28, 2026 08:38
<!-- markdownlint-disable MD041 -->
## Summary

This replacement stacked PR completes #6952 by extracting the remaining
repeated Windows and WSL setup and command construction. It uses the
trusted helper from #7719 and restores the reviewed #7709 diff after
#7709 merged into its staging branch.

## Related Issue

Fixes #6952
Fixes #6958
Replaces staged PR #7709
Depends on #7719

## Changes

- Use `tools/wsl/ci-helper.ps1`, bootstrapped by #7719, for WSL E2E and
platform Vitest workflows.
- Load the helper through mandatory sparse checkouts at the PR base SHA
or workflow SHA before candidate checkout, and fail closed.
- Pass `needs` through `NEEDS_JSON` and parse it instead of
interpolating expressions into executable code.
- Reduce inline executable workflow logic while retaining root-only
selection and its reason.
- Reapply the exact reviewed #7709 patch after recovering #7719's
helper-only scope. The binary patch is identical to `df3bcdcdd`.

## Type of Change

- [x] Code
- [ ] Documentation
- [ ] Tests only
- [ ] Other

## Quality Gates

- [x] Tests added or updated for changed behavior
- [x] Documentation is not applicable because this changes internal CI
only
- [x] Sensitive paths changed
- [x] Sensitive-path review completed: the exact
`c1f34675d1025b7f189938977cf6158efdc66b4c` patch is byte-for-byte
identical to reviewed #7709 commit `df3bcdcdd`; targeted boundary review
covers trusted provenance, fail-closed loading, bidirectional overlap,
quoting, encoding, `needs` interpolation, and root/non-root separation
- [ ] Non-success behavior changed

## Documentation Writer Review

- [x] Documentation writer review completed

Result: no-docs-needed

Evidence: Reviewed exact head `c1f34675d1025b7f189938977cf6158efdc66b4c`
against base `e69d9c3d94623a0cd499fb2c84f33f88c863c631`. The expected
nine files match the binary patch SHA-256 for reviewed #7709 commit
`df3bcdcdd`; no user-facing documentation changes are required. Focused
tests passed 50 cases with 12 PowerShell cases skipped because
PowerShell is unavailable locally. CLI type-check and exact-base diff
checks passed.

Agent surface: Codex Desktop

<!-- docs-review-head-sha: c1f3467 -->
<!-- docs-review-agents-blob-sha:
be20a09 -->

## DGX Station Test Evidence

Not applicable.

## Verification

- [x] DCO declaration is included and every commit is GitHub Verified
- [x] Normal commit and pre-push hooks passed
- [x] Targeted tests passed: 50 passed; 12 PowerShell cases skipped
locally because PowerShell is unavailable
- [x] CLI type-check and exact-base diff checks passed
- [ ] Broad test suite passed
- [x] Quality gates above are complete
- [x] No secrets, API keys, or credentials are committed
- [ ] User-facing documentation was updated
- [ ] Documentation build passed

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

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

@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: 3

🧹 Nitpick comments (1)
test/e2e/support/e2e-operations-workflow-boundary.test.ts (1)

68-117: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Make the negative tests isolate the interpolation predicate.

The first case deletes NEEDS_JSON at Line [76]-[77], so it would fail even if NEEDS_INTERPOLATION were removed. The second case tests only the toJSON(needs) form. Keep the environment binding intact while injecting interpolation, and add a direct ${{ needs.* }} regression case.

Proposed test adjustment
-    delete report.env?.NEEDS_JSON;
-    delete scorecard.env?.NEEDS_JSON;
     report.with!.script = String(report.with!.script).replace(
       "JSON.parse(process.env.NEEDS_JSON || '{}')",
       "${{ toJSON(needs) }}",
     );
@@
     scorecard.with!.script = `${String(scorecard.with!.script)}
 const interpolatedNeeds = \${{   toJSON ( needs )   }};
+const directNeeds = \${{ needs.live.result }};
 `;

As per path instructions, tests should prove the boundary behavior rather than only one implementation spelling.

🤖 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 68 -
117, Update the negative tests in the interpolation validation cases so they
preserve the existing NEEDS_JSON environment bindings and isolate only the
interpolation predicate. Replace the first test’s deletion of
report.env.NEEDS_JSON and scorecard.env.NEEDS_JSON with injected interpolation,
and extend the second test to cover direct `${{ needs.* }}` interpolation in
addition to whitespace-obscured `toJSON(needs)`.

Source: Path instructions

🤖 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/wsl-e2e.yaml:
- Around line 153-170: Update the WSL invocation around Invoke-WslScript so
NVIDIA_INFERENCE_API_KEY and GITHUB_TOKEN are passed through the WSL environment
via WSLENV rather than embedded in the $exports script content. Remove those
secrets from the generated script and export/read them directly inside WSL,
while preserving the existing non-secret environment exports and test command.

In `@test/platform-vitest-main-workflow.test.ts`:
- Around line 130-133: Extend the forbidden-pattern assertions in the main and
WSL E2E workflow checks to also reject direct `wsl -d` invocations, including
the PowerShell environment-variable form used by the migrated command tail. Keep
the existing `WriteAllText`, `wslpath`, and `wsl --install` protections
unchanged, ensuring both `readRepoText` checks enforce that only the trusted
helper constructs WSL commands.

In `@tools/e2e/operations-workflow-boundary.mts`:
- Around line 51-53: Broaden NEEDS_INTERPOLATION and the
passesNeedsAsEnvironmentData check in tools/e2e/operations-workflow-boundary.mts
(lines 51-53 and 141-149) to reject direct needs.* interpolations as well as
toJSON(needs), while preserving the NEEDS_JSON environment binding. Add a
regression case in test/e2e/support/e2e-operations-workflow-boundary.test.ts
(lines 68-117) covering a direct needs.job.outputs.foo reference.

---

Nitpick comments:
In `@test/e2e/support/e2e-operations-workflow-boundary.test.ts`:
- Around line 68-117: Update the negative tests in the interpolation validation
cases so they preserve the existing NEEDS_JSON environment bindings and isolate
only the interpolation predicate. Replace the first test’s deletion of
report.env.NEEDS_JSON and scorecard.env.NEEDS_JSON with injected interpolation,
and extend the second test to cover direct `${{ needs.* }}` interpolation in
addition to whitespace-obscured `toJSON(needs)`.
🪄 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: 589a00cd-6664-45fd-9559-b860cb7a5dc4

📥 Commits

Reviewing files that changed from the base of the PR and between e69d9c3 and 7db0b2b.

📒 Files selected for processing (9)
  • .github/workflows/e2e.yaml
  • .github/workflows/platform-vitest-main.yaml
  • .github/workflows/wsl-e2e.yaml
  • ci/source-shape-test-budget.json
  • test/e2e/support/e2e-operations-workflow-boundary.test.ts
  • test/helpers/vitest-watch-triggers.ts
  • test/platform-vitest-main-workflow.test.ts
  • test/vitest-watch-triggers.test.ts
  • tools/e2e/operations-workflow-boundary.mts

Comment thread .github/workflows/wsl-e2e.yaml Outdated
Comment on lines +153 to +170
. "$env:TRUSTED_WSL_HELPER"
$workdir = ConvertTo-BashLiteral -Value $env:WSL_WORKDIR
$exports = @(
'export NVIDIA_INFERENCE_API_KEY=' + (ConvertTo-BashLiteral -Value ([string]$env:NVIDIA_INFERENCE_API_KEY))
'export GITHUB_TOKEN=' + (ConvertTo-BashLiteral -Value ([string]$env:GITHUB_TOKEN))
'export NEMOCLAW_NON_INTERACTIVE=' + (ConvertTo-BashLiteral -Value $env:NEMOCLAW_NON_INTERACTIVE)
'export NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE=' + (ConvertTo-BashLiteral -Value $env:NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE)
'export NEMOCLAW_RECREATE_SANDBOX=' + (ConvertTo-BashLiteral -Value $env:NEMOCLAW_RECREATE_SANDBOX)
'export NEMOCLAW_SANDBOX_NAME=' + (ConvertTo-BashLiteral -Value $env:NEMOCLAW_SANDBOX_NAME)
) -join "`n"
$script = @"
set -euo pipefail
cd '$env:WSL_WORKDIR'
export NVIDIA_INFERENCE_API_KEY='$env:NVIDIA_INFERENCE_API_KEY'
export GITHUB_TOKEN='$env:GITHUB_TOKEN'
export NEMOCLAW_NON_INTERACTIVE='$env:NEMOCLAW_NON_INTERACTIVE'
export NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE='$env:NEMOCLAW_ACCEPT_THIRD_PARTY_SOFTWARE'
export NEMOCLAW_RECREATE_SANDBOX='$env:NEMOCLAW_RECREATE_SANDBOX'
export NEMOCLAW_SANDBOX_NAME='$env:NEMOCLAW_SANDBOX_NAME'
cd $workdir
$exports
export NEMOCLAW_RUN_LIVE_E2E=1
npx vitest run --project e2e-live test/e2e/live/full-e2e.test.ts --silent=false --reporter=default
"@
$tmp = "$env:RUNNER_TEMP\wsl-step.sh"
[IO.File]::WriteAllText($tmp, ($script -replace "`r",""), (New-Object System.Text.UTF8Encoding $false))
$wslTmp = wsl -d $env:WSL_DISTRO -- wslpath -u ($tmp -replace '\\','/')
wsl -d $env:WSL_DISTRO -- bash -l $wslTmp
Invoke-WslScript -Distro $env:WSL_DISTRO -Script $script

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect how the helper transfers scripts and whether it supports env passthrough.
fd -t f 'ci-helper.ps1' tools
rg -nP -C3 'WSLENV|Write-WslScriptFile|New-WslScriptArguments|nemoclaw-wsl-step' tools/wsl/ci-helper.ps1
# Any existing precedent for env passthrough into WSL in workflows?
rg -nP -C2 'WSLENV' .github tools

Repository: NVIDIA/NemoClaw

Length of output: 1015


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the relevant helper functions and workflow lines.
sed -n '1,220p' tools/wsl/ci-helper.ps1
printf '\n--- WORKFLOW ---\n'
sed -n '130,190p' .github/workflows/wsl-e2e.yaml
printf '\n--- SEARCH ---\n'
rg -n 'WSLENV|ENV|environment|pass.*env|ScriptArguments|Invoke-WslScript|Write-WslScriptFile|New-WslScriptArguments' tools/wsl/ci-helper.ps1 .github/workflows/wsl-e2e.yaml

Repository: NVIDIA/NemoClaw

Length of output: 10665


Pass the secrets through WSL env instead of inlining them into the script

NVIDIA_INFERENCE_API_KEY and GITHUB_TOKEN end up in the temporary nemoclaw-wsl-step.sh file. Use WSLENV/env passthrough and read them directly inside WSL so the transferred script stays secret-free.

🤖 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/wsl-e2e.yaml around lines 153 - 170, Update the WSL
invocation around Invoke-WslScript so NVIDIA_INFERENCE_API_KEY and GITHUB_TOKEN
are passed through the WSL environment via WSLENV rather than embedded in the
$exports script content. Remove those secrets from the generated script and
export/read them directly inside WSL, while preserving the existing non-secret
environment exports and test command.

Comment on lines +130 to +133
expect(readRepoText(WORKFLOW_PATH)).not.toMatch(/WriteAllText|wslpath|wsl\s+--install/u);
expect(readRepoText(WSL_E2E_WORKFLOW_PATH)).not.toMatch(
/WriteAllText|wslpath|wsl\s+--install/u,
);

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Forbidden-pattern guard misses direct wsl -d invocation, the main path being migrated away from.

/WriteAllText|wslpath|wsl\s+--install/u catches temp-file writes, path conversion, and distro install, but a reintroduced wsl -d $env:WSL_DISTRO bash -l ... tail in either workflow would still pass. Since only the trusted helper is supposed to construct WSL commands, include the direct-invocation shape too.

As per path instructions, "Migration tests must prove the superseded path is unreachable or removed, not merely prove that the new path also works."

🔒 Proposed tightening
-    expect(readRepoText(WORKFLOW_PATH)).not.toMatch(/WriteAllText|wslpath|wsl\s+--install/u);
-    expect(readRepoText(WSL_E2E_WORKFLOW_PATH)).not.toMatch(
-      /WriteAllText|wslpath|wsl\s+--install/u,
-    );
+    const forbidden = /WriteAllText|wslpath|\bwsl(?:\.exe)?\s+(?:--install|-d\b|--distribution\b)/u;
+    expect(readRepoText(WORKFLOW_PATH)).not.toMatch(forbidden);
+    expect(readRepoText(WSL_E2E_WORKFLOW_PATH)).not.toMatch(forbidden);
📝 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
expect(readRepoText(WORKFLOW_PATH)).not.toMatch(/WriteAllText|wslpath|wsl\s+--install/u);
expect(readRepoText(WSL_E2E_WORKFLOW_PATH)).not.toMatch(
/WriteAllText|wslpath|wsl\s+--install/u,
);
const forbidden = /WriteAllText|wslpath|\bwsl(?:\.exe)?\s+(?:--install|-d\b|--distribution\b)/u;
expect(readRepoText(WORKFLOW_PATH)).not.toMatch(forbidden);
expect(readRepoText(WSL_E2E_WORKFLOW_PATH)).not.toMatch(forbidden);
🤖 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/platform-vitest-main-workflow.test.ts` around lines 130 - 133, Extend
the forbidden-pattern assertions in the main and WSL E2E workflow checks to also
reject direct `wsl -d` invocations, including the PowerShell
environment-variable form used by the migrated command tail. Keep the existing
`WriteAllText`, `wslpath`, and `wsl --install` protections unchanged, ensuring
both `readRepoText` checks enforce that only the trusted helper constructs WSL
commands.

Source: Path instructions

Comment on lines +51 to +53
const NEEDS_INTERPOLATION = /\$\{\{\s*toJSON\s*\(\s*needs\s*\)\s*\}\}/iu;
const NEEDS_ENV_PARSE =
/\bJSON\.parse\(\s*process\.env\.NEEDS_JSON\s*\|\|\s*["']\{\}["']\s*\)/u;

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf '\n== tools/e2e/operations-workflow-boundary.mts ==\n'
sed -n '1,240p' tools/e2e/operations-workflow-boundary.mts

printf '\n== test/e2e/support/e2e-operations-workflow-boundary.test.ts ==\n'
sed -n '1,220p' test/e2e/support/e2e-operations-workflow-boundary.test.ts

Repository: NVIDIA/NemoClaw

Length of output: 19450


🏁 Script executed:

set -euo pipefail
sed -n '1,240p' tools/e2e/operations-workflow-boundary.mts
printf '\n---\n'
sed -n '1,220p' test/e2e/support/e2e-operations-workflow-boundary.test.ts

Repository: NVIDIA/NemoClaw

Length of output: 19340


🏁 Script executed:

set -euo pipefail
echo 'hi'

Repository: NVIDIA/NemoClaw

Length of output: 156


🏁 Script executed:

set -euo pipefail
printf '\n== workflow refs ==\n'
rg -n "NEEDS_JSON|toJSON\\(needs\\)|process\\.env\\.NEEDS_JSON|needs\\." .github/workflows/e2e.yaml test/e2e/support/e2e-operations-workflow-boundary.test.ts tools/e2e/operations-workflow-boundary.mts

Repository: NVIDIA/NemoClaw

Length of output: 4409


Broaden the needs guard in the workflow-boundary check.
passesNeedsAsEnvironmentData only rejects ${{ toJSON(needs) }}, so a direct ${{ needs.job.outputs.foo }} interpolation can still satisfy the current checks. Tighten that predicate and add a regression test for a direct needs.* reference while keeping the NEEDS_JSON env binding intact.

📍 Affects 2 files
  • tools/e2e/operations-workflow-boundary.mts#L51-L53 (this comment)
  • tools/e2e/operations-workflow-boundary.mts#L141-L149
  • test/e2e/support/e2e-operations-workflow-boundary.test.ts#L68-L117
🤖 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 51 - 53, Broaden
NEEDS_INTERPOLATION and the passesNeedsAsEnvironmentData check in
tools/e2e/operations-workflow-boundary.mts (lines 51-53 and 141-149) to reject
direct needs.* interpolations as well as toJSON(needs), while preserving the
NEEDS_JSON environment binding. Add a regression case in
test/e2e/support/e2e-operations-workflow-boundary.test.ts (lines 68-117)
covering a direct needs.job.outputs.foo reference.

Source: Path instructions

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cv
cv merged commit c3ab052 into main Jul 28, 2026
75 of 76 checks passed
@cv
cv deleted the codex/issue-6958-trusted-helper branch July 28, 2026 16:23
@cv cv mentioned this pull request Jul 28, 2026
23 tasks
cv added a commit that referenced this pull request Jul 28, 2026
<!-- markdownlint-disable MD041 -->
## Summary

This PR completes #6952 and #6958 by moving repeated Windows and WSL
executable logic into the trusted helper from #7719. It recreates the
#7737 extraction directly on `main` after the helper landed.

## Related Issue

Fixes #6952
Fixes #6958

## Changes

- Use `tools/wsl/ci-helper.ps1` for WSL E2E and platform Vitest setup,
script transfer, Node.js installation, and ext4 checkout
synchronization. The workflow regression tests protect both consumers.
- Load the helper from the PR base SHA or workflow SHA before candidate
checkout. Both workflows fail if the trusted helper is missing.
- Pass `needs` through `NEEDS_JSON` instead of interpolating GitHub
expressions into executable source. The E2E operations boundary test
rejects direct interpolation.
- Validate through the TypeScript AST that `needs` receives the parsed
environment value. Isolated tests reject comments, unrelated
assignments, and malformed wiring.
- Update watch triggers and the source-shape budget for the extracted
logic.

## Type of Change

- [x] 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

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: This PR changes internal CI
workflows and tests. It does not change a CLI, configuration, supported
integration, or user-facing contract.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: The trusted helper is
loaded from the base or workflow SHA before candidate checkout. Focused
tests verify trusted provenance, failure when the helper is missing,
path overlap rejection, quoting, encoding, `needs` assignment and
interpolation, and root separation.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `no-docs-needed`
- Evidence: Reviewed head `b56897529e166385464c7e8ec051174f3af4f2aa`
against base `c3ab0526eba41d1c681e92bbad3d174925aeaa6a`. The AST
validator and its regressions change internal CI security enforcement
only. No documentation source or user-facing contract changed. The
review-fix suite passed 45 tests. Biome, repository checks, CLI
type-checking, the diff check, source-shape budget, title check,
gitleaks, and commitlint passed.
- Agent: Codex Desktop
<!-- docs-review-head-sha: b568975 -->
<!-- docs-review-agents-blob-sha:
be20a09 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: The
original focused suite passed 50 tests and skipped 12 PowerShell-only
tests. After the review fix, the E2E operations boundary suite passed 45
tests. `npx biome check` for the changed files, `npm run checks`, `npm
run typecheck:cli`, and `git diff --check` passed.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

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

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@cjagwani cjagwani removed the v0.0.97 label Jul 28, 2026
@cjagwani cjagwani mentioned this pull request Jul 28, 2026
23 tasks
cv pushed a commit that referenced this pull request Jul 28, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Add the canonical dated changelog entry for NemoClaw v0.0.97 before the
release plan captures `origin/main`.
The entry groups the user-visible and maintainer-facing changes since
v0.0.96 while preserving the Deferred dual-Station status, experimental
runtime-identity boundary, and pending physical IGX validation.

## Changes

- Add `docs/changelog/2026-07-28.mdx` with the parser-safe MDX SPDX
comment and exact `## v0.0.97` heading.
- Summarize the 43 merged PRs in the release range, omitting
internal-only changes from the public entry and linking each grouped
change to its most specific published documentation.
- Keep the experimental Okta reference explicitly opt-in and outside
normal onboarding, keep the two-Station path Deferred, and state that
physical IGX Orin validation remains pending.

### Source summary

- [#7440](#7440),
[#7443](#7443), and
[#7445](#7445) ->
`docs/changelog/2026-07-28.mdx`: Document read-only host readiness
reports and fail-closed platform qualification.
- [#7030](#7030) ->
`docs/changelog/2026-07-28.mdx`: Document the Deferred trusted
two-Station vLLM evaluation.
- [#7265](#7265) ->
`docs/changelog/2026-07-28.mdx`: Document the bounded experimental
direct-runner Okta runtime-identity reference.
- [#7711](#7711) and
[#7648](#7648) ->
`docs/changelog/2026-07-28.mdx`: Document compatible-endpoint reasoning
effort and retired NVIDIA Build model paths.
- [#7746](#7746),
[#7763](#7763), and
[#7681](#7681) ->
`docs/changelog/2026-07-28.mdx`: Document safe compatible-provider
creation, replacement refusal, and narrow OpenShell bridge URL handling.
- [#7641](#7641),
[#7690](#7690),
[#7631](#7631), and
[#7710](#7710) ->
`docs/changelog/2026-07-28.mdx`: Document paused-container recovery,
recreation journaling, pre-mutation uninstall checks, and
source-checkout OpenShell selection.
- [#7624](#7624) and
[#7762](#7762) ->
`docs/changelog/2026-07-28.mdx`: Document Jetson release diagnostics and
bounded render-device group propagation.
- [#7639](#7639),
[#7760](#7760),
[#7721](#7721), and
[#7761](#7761) ->
`docs/changelog/2026-07-28.mdx`: Document Telegram, MCP media-type,
Hermes image-mode, and locked-restart fixes.
- [#7653](#7653) and
[#7680](#7680) ->
`docs/changelog/2026-07-28.mdx`: Document Deep Agents policy tasks and
the bounded Claude Code OAuth path.
- [#7679](#7679) ->
`docs/changelog/2026-07-28.mdx`: Document the checksum-bound libssh2 and
Python HTMLParser backports.
- [#7655](#7655),
[#7651](#7651),
[#7664](#7664),
[#7666](#7666),
[#7670](#7670),
[#7719](#7719), and
[#7741](#7741) ->
`docs/changelog/2026-07-28.mdx`: Document exact candidate E2E evidence,
Launchable selection, diagnostic consolidation, and trusted WSL
validation.

## Type of Change

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

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [x] Existing tests cover changed behavior — justification:
`test/changelog-docs.test.ts` validates the dated changelog contract,
MDX header, heading uniqueness, and release-entry structure.
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] 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:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: The committed `docs/changelog/2026-07-28.mdx` blob exactly
matches the reviewed file. Completeness, factual accuracy, link shape,
parser-safe MDX header, one-sentence-per-line style, `.docs-skip`
compliance, and bounded product claims passed.
- Agent: Codex Desktop documentation writer subagent
<!-- docs-review-head-sha: da6aa27 -->
<!-- docs-review-agents-blob-sha: be20a09 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit: Not applicable; this PR changes only the dated
changelog.
- Station profile/scenario: Not applicable.
- Result: Not applicable.
- Supporting evidence: Not applicable.

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run
test/changelog-docs.test.ts` passed 6/6.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — not applicable to this doc-only release
entry.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) —
completed with 0 errors and 2 pre-existing Fern warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)
— native changelog entries use the required parser-safe MDX SPDX comment
and intentionally have no frontmatter.

---
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added improved host readiness reporting and Jetson onboarding
guidance.
* Added controls for reasoning effort with compatible endpoints and
enhanced managed MCP discovery.
  * Improved Deep Agents task publication and preset support.
* **Bug Fixes**
* Hardened provider switching, sandbox recovery, uninstall behavior, and
Telegram connectivity.
* Improved container image integrity checks, media-type handling, and
checksum validation.
  * Enhanced vLLM evaluation behavior and release diagnostics.
* **Documentation**
  * Added the NemoClaw v0.0.97 changelog.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
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 platform: wsl Affects Windows Subsystem for Linux

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants