Skip to content

fix(cli): prepare Hermes light terminal skin - #6578

Merged
jyaunches merged 16 commits into
mainfrom
fix/6380_hermes_light_skin
Jul 10, 2026
Merged

fix(cli): prepare Hermes light terminal skin#6578
jyaunches merged 16 commits into
mainfrom
fix/6380_hermes_light_skin

Conversation

@chengjiew

@chengjiew chengjiew commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • write a NemoClaw-managed nemoclaw-light Hermes skin inside the sandbox Hermes home for light terminal sessions
  • activate it only when COLORFGBG reports a light background and the user has not set HERMES_TUI_THEME, HERMES_TUI_LIGHT, or display.skin
  • keep the theme chrome unchanged while using the darker Hermes body/list text color from the upstream Hermes fix proposal

Fixes #6380.

Related upstream Hermes PR: NousResearch/hermes-agent#60972.

Validation

  • npm test -- --run src/lib/domain/sandbox/connect-env.test.ts src/lib/actions/sandbox/connect-hermes-light-theme.test.ts
  • git diff --check
  • Linux smoke on aits-log-worker-6: real Hermes TUI output used #7A5A0F (38;2;122;90;15) for body/list text after writing /sandbox/.hermes/skins/nemoclaw-light.yaml and display.skin: nemoclaw-light

Summary by CodeRabbit

  • New Features
    • Hermes sandbox connections now automatically prepare/apply a light-compatible terminal skin when the host terminal appears light.
    • The connect flow now uses a computed connection environment and avoids unnecessary sandbox reconfiguration when a managed display.skin is already present.
  • Bug Fixes
    • Improved reconnect and failure handling: connection still proceeds while emitting safe, redacted warnings.
    • Skin/config operations are correctly scoped to the selected Hermes sandbox and skipped when user theme overrides are set.
  • Tests
    • Expanded Hermes connect-environment/skin behavior coverage and updated the connect-flow test harness (plus timing determinism for gateway recovery).

Signed-off-by: Chengjie Wang chengjiew@nvidia.com

@coderabbitai

coderabbitai Bot commented Jul 9, 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

This PR adds Hermes light-terminal detection and managed skin configuration for sandbox connects, applies it before launching openshell sandbox connect, and adds helper, integration, and failure-path coverage. It also updates gateway recovery tests to use virtual clocks.

Changes

Hermes light-theme skin preparation

Layer / File(s) Summary
Light-theme detection and config helpers
src/lib/domain/sandbox/connect-env.ts
Defines the managed skin, detects light terminals, gates inspection on agent and override state, mutates compatible Hermes configs, and clones the connect environment.
Sandbox skin preparation and connect wiring
src/lib/actions/sandbox/connect-hermes-light-skin.ts, src/lib/actions/sandbox/connect.ts
Writes nemoclaw-light.yaml, updates Hermes sandbox configuration when required, emits redacted warnings on failures, and prepares the skin before connecting.
Light-theme helper validation
src/lib/domain/sandbox/connect-env.test.ts
Tests terminal detection, override handling, managed skin content, config application, and environment passthrough.
Sandbox connect integration coverage
test/support/connect-flow-test-harness.ts, src/lib/actions/sandbox/connect-hermes-light-theme.test.ts
Adds Hermes configuration spies and covers scoped operations, existing configurations, overrides, successful continuation, and failure warnings.

Gateway recovery test timing

Layer / File(s) Summary
Deterministic gateway recovery tests
src/lib/onboard/gateway-recovery.test.ts
Injects virtual clock sleep and time functions into two recovery scenarios.

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

Sequence Diagram(s)

sequenceDiagram
  participant connectSandbox
  participant prepareHermesLightTerminalSkin
  participant Sandbox
  participant openshell

  connectSandbox->>prepareHermesLightTerminalSkin: prepare Hermes skin before connect
  prepareHermesLightTerminalSkin->>Sandbox: read Hermes config
  prepareHermesLightTerminalSkin->>Sandbox: write skin YAML and updated config
  connectSandbox->>openshell: spawn sandbox connect with constructed environment
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#5478: Covers connectSandbox OpenShell handoff and process.exit behavior related to this connect-flow change.

Suggested labels: bug-fix, area: sandbox, area: cli

Suggested reviewers: cv, ericksoa

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The gateway recovery virtual-clock test wiring is unrelated to Hermes light-skin prep and appears outside the issue scope. Move the gateway recovery clock-test changes to a separate PR unless they are required by this issue.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly names the main change: preparing the Hermes light terminal skin for CLI connects.
Linked Issues check ✅ Passed The PR implements light-terminal detection and managed Hermes skin preparation to restore readable reply text on light profiles.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/6380_hermes_light_skin

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

@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 (4)
src/lib/domain/sandbox/connect-env.test.ts (1)

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

Consider exact equality instead of objectContaining.

Since buildSandboxConnectEnv currently just spreads env, asserting toEqual(env) directly would give a stronger guarantee than objectContaining, which only checks the given keys are present and wouldn't catch unexpected additions/omissions.

🤖 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 `@src/lib/domain/sandbox/connect-env.test.ts` around lines 14 - 26, The test in
buildSandboxConnectEnv is using a weak partial match, so update the assertion to
compare the full returned environment exactly rather than using
objectContaining. Keep the existing setup around buildSandboxConnectEnv, but
change the expectation to verify the result matches the input env object
precisely so unexpected keys or missing keys are caught.
src/lib/domain/sandbox/connect-env.ts (1)

34-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate YAML parse/validate logic between the two helpers.

hermesConfigHasDisplaySkin (Lines 34-44) and buildHermesLightSkinConfig (Lines 46-64) both repeat the same parse-and-validate sequence: YAML.parseDocument, doc.errors.length > 0 check, and the root-type guard. Consider extracting a shared helper (e.g. parseHermesConfigDocument(configText): YAML.Document | null) that both functions call, to keep the validation rule in one place.

♻️ Suggested extraction
+function parseHermesConfigDocument(configText: string): YAML.Document | null {
+  const doc = YAML.parseDocument(configText.trim() ? configText : "{}");
+  if (doc.errors.length > 0) return null;
+  const root = doc.toJSON();
+  if (root !== null && (typeof root !== "object" || Array.isArray(root))) return null;
+  return doc;
+}
+
 export function hermesConfigHasDisplaySkin(configText: string): boolean | null {
   try {
-    const doc = YAML.parseDocument(configText.trim() ? configText : "{}");
-    if (doc.errors.length > 0) return null;
-    const root = doc.toJSON();
-    if (root !== null && (typeof root !== "object" || Array.isArray(root))) return null;
+    const doc = parseHermesConfigDocument(configText);
+    if (!doc) return null;
     return doc.hasIn(["display", "skin"]);
   } catch {
     return null;
   }
 }

 export function buildHermesLightSkinConfig(configText: string): string | null {
   try {
-    const doc = YAML.parseDocument(configText.trim() ? configText : "{}");
-    if (doc.errors.length > 0) return null;
-
-    const root = doc.toJSON();
-    if (root !== null && (typeof root !== "object" || Array.isArray(root))) return null;
+    const doc = parseHermesConfigDocument(configText);
+    if (!doc) return null;
     if (doc.hasIn(["display", "skin"])) return null;
🤖 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 `@src/lib/domain/sandbox/connect-env.ts` around lines 34 - 64, Both
hermesConfigHasDisplaySkin and buildHermesLightSkinConfig repeat the same
YAML.parseDocument, doc.errors.length check, and root-type validation, so
extract that shared parse/validate flow into a helper such as
parseHermesConfigDocument(configText) in connect-env.ts and have both functions
call it; then keep hermesConfigHasDisplaySkin focused on the display/skin lookup
and buildHermesLightSkinConfig focused on the mutation path using the parsed
document.
src/lib/actions/sandbox/connect.ts (1)

118-133: 📐 Maintainability & Code Quality | 🔵 Trivial

Duplicate gating logic ahead of shouldPrepareHermesLightSkin.

Lines 123-130 hand-roll the same agent?.name === "hermes", hostTerminalLooksLight(env), HERMES_TUI_LIGHT/HERMES_TUI_THEME checks that shouldPrepareHermesLightSkin (from connect-env.ts) already encodes, then line 133 calls shouldPrepareHermesLightSkin again with the same inputs plus the config check. This is understandable as an optimization to avoid the sandbox round-trip in readSandboxHermesConfig when the cheap checks already fail, but the duplicated boolean logic can silently drift from the domain source of truth (e.g. if hasEnvValue's trimming/semantics change in connect-env.ts, this inline copy won't follow). Consider exposing a cheap pre-check (e.g. a hasEnvValue-style helper or a shouldPrepareHermesLightSkin variant that accepts a lazy config getter) from the domain module instead of re-implementing the guard here.

As per path instructions, src/lib/{actions,domain,adapters,state}/** should avoid "duplicate sources of truth" between layers.

🤖 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 `@src/lib/actions/sandbox/connect.ts` around lines 118 - 133, The guard logic
in prepareHermesLightTerminalSkin duplicates the same Hermes/light-theme checks
already owned by shouldPrepareHermesLightSkin, creating a second source of
truth. Refactor this flow to reuse the domain logic from connect-env.ts instead
of re-implementing the agent name, hostTerminalLooksLight, and env-value checks
inline. Keep the early exit optimization, but move it behind a shared helper or
a lazy-config variant of shouldPrepareHermesLightSkin so the sandbox config read
only happens after the canonical pre-check passes.

Source: Path instructions

src/lib/actions/sandbox/connect-hermes-light-theme.test.ts (1)

49-69: 📐 Maintainability & Code Quality | 🔵 Trivial

Assertions are entirely mock-call/implementation-detail based.

Both tests verify behavior exclusively by inspecting captureOpenshellSpy/runOpenshellSpy call arguments (exact CLI argv shape, substring checks on the generated shell script) rather than any observable outcome through connectSandbox's public surface. This locks the test to the exact shape of the generated sh -c script and argv positions (e.g. args.slice(0, 6).join(" "), args[7]), so refactoring the script construction (even without changing behavior) will break these tests without a real regression.

Given the harness mocks the openshell adapter entirely, there's no alternative filesystem/output artifact to assert on directly, so this is a reasonable practical compromise — but it's worth being aware this is exactly the "mock-call assertion" pattern flagged for **/*.test.{ts,js,mts,mjs,cts,cjs}.

As per path instructions, tests should "Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions."

Also applies to: 119-125

🤖 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 `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts` around lines 49 -
69, The test is asserting against mock-call implementation details instead of an
observable outcome from connectSandbox. Update the connectHermes light-theme
tests to verify the public behavior of the connectSandbox flow through the
harness’s externally visible result/state, and avoid depending on exact argv
positions, shell-script substrings, or captureOpenshellSpy/runOpenshellSpy call
shapes. Use the connectSandbox and harness APIs as the stable entry points, and
keep only assertions that reflect the intended outcome rather than the generated
command text.

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 `@src/lib/domain/sandbox/connect-env.ts`:
- Around line 80-86: The buildSandboxConnectEnv function is intentionally not
using the agent parameter, but it currently silences that with a void statement
instead of following the unused-variable convention. Rename the parameter in
buildSandboxConnectEnv to use an underscore prefix (for example, `_agent`) and
remove the void agent line so the intent is clear and consistent with the coding
guidelines.

---

Nitpick comments:
In `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts`:
- Around line 49-69: The test is asserting against mock-call implementation
details instead of an observable outcome from connectSandbox. Update the
connectHermes light-theme tests to verify the public behavior of the
connectSandbox flow through the harness’s externally visible result/state, and
avoid depending on exact argv positions, shell-script substrings, or
captureOpenshellSpy/runOpenshellSpy call shapes. Use the connectSandbox and
harness APIs as the stable entry points, and keep only assertions that reflect
the intended outcome rather than the generated command text.

In `@src/lib/actions/sandbox/connect.ts`:
- Around line 118-133: The guard logic in prepareHermesLightTerminalSkin
duplicates the same Hermes/light-theme checks already owned by
shouldPrepareHermesLightSkin, creating a second source of truth. Refactor this
flow to reuse the domain logic from connect-env.ts instead of re-implementing
the agent name, hostTerminalLooksLight, and env-value checks inline. Keep the
early exit optimization, but move it behind a shared helper or a lazy-config
variant of shouldPrepareHermesLightSkin so the sandbox config read only happens
after the canonical pre-check passes.

In `@src/lib/domain/sandbox/connect-env.test.ts`:
- Around line 14-26: The test in buildSandboxConnectEnv is using a weak partial
match, so update the assertion to compare the full returned environment exactly
rather than using objectContaining. Keep the existing setup around
buildSandboxConnectEnv, but change the expectation to verify the result matches
the input env object precisely so unexpected keys or missing keys are caught.

In `@src/lib/domain/sandbox/connect-env.ts`:
- Around line 34-64: Both hermesConfigHasDisplaySkin and
buildHermesLightSkinConfig repeat the same YAML.parseDocument, doc.errors.length
check, and root-type validation, so extract that shared parse/validate flow into
a helper such as parseHermesConfigDocument(configText) in connect-env.ts and
have both functions call it; then keep hermesConfigHasDisplaySkin focused on the
display/skin lookup and buildHermesLightSkinConfig focused on the mutation path
using the parsed document.
🪄 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: 8a19716f-c550-4a8f-85d9-20bb751ff888

📥 Commits

Reviewing files that changed from the base of the PR and between 9cfce7a and 9a5995b.

📒 Files selected for processing (4)
  • src/lib/actions/sandbox/connect-hermes-light-theme.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/domain/sandbox/connect-env.test.ts
  • src/lib/domain/sandbox/connect-env.ts

Comment thread src/lib/domain/sandbox/connect-env.ts Outdated
@apurvvkumaria apurvvkumaria self-assigned this Jul 9, 2026
cv added 2 commits July 9, 2026 09:54
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
@github-code-quality

github-code-quality Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the fix/6380_hermes_ligh... branch remains at 77%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main 2b84a04 fix/6380_hermes_ligh... ca83661 +/-
src/lib/messagi...etup-applier.ts 90% 59% -31%
src/lib/sandbox-base-image.ts 99% 92% -7%
src/lib/state/registry.ts 78% 85% +7%
src/lib/inferen...apter-server.ts 0% 67% +67%
src/lib/actions...s-light-skin.ts 0% 67% +67%
src/lib/onboard...uter-runtime.ts 0% 70% +70%
src/lib/domain/.../connect-env.ts 0% 82% +82%
src/lib/actions...pter-cleanup.ts 0% 85% +85%
src/lib/inferen...pter-forward.ts 0% 88% +88%
src/lib/inferen...apter-common.ts 0% 88% +88%

Updated July 10, 2026 18:20 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

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

I resolved the merge conflict by merging current main (4df9fc2c7) into this branch and preserved both the inference-route hardening from main and this PR's Hermes hook. I also applied CodeRabbit's valid unused-parameter cleanup. The exact head is 0581b7ab0; the focused 11 tests, CLI type-check, npm run check:diff, and normal pre-push hooks pass.

I am requesting changes for three remaining hard gates:

  1. The PR description is missing the contributor DCO declaration. All commits currently appear as GitHub Verified, but the body has no Signed-off-by: line. .github/PULL_REQUEST_TEMPLATE.md:31 and :42-43 require the contributor's declaration in the PR description. Please add your own valid sign-off (for example, Signed-off-by: Chengjie Wang <chengjiew@nvidia.com> if that identity is correct); a maintainer cannot declare it on your behalf.

  2. The managed light skin is sticky across later dark-terminal connections. src/lib/domain/sandbox/connect-env.ts:59 persists display.skin: nemoclaw-light. On a later dark connection, src/lib/actions/sandbox/connect.ts:136-143 exits before reading or reconciling that managed setting, and src/lib/domain/sandbox/connect-env.ts:53,76 treats every existing skin—including NemoClaw's own—as an override. This conflicts with the stated “activate it only when COLORFGBG reports a light background” behavior and can recreate unreadable colors after the user switches to a dark terminal. Please define the managed-skin lifecycle without ever removing a user-owned skin, and add a light-to-dark transition regression test.

  3. The config write bypasses the supported Hermes mutation boundary and suppresses failure. src/lib/actions/sandbox/connect.ts:153-165 overwrites /sandbox/.hermes/config.yaml through ordinary openshell sandbox exec, with ignoreError: true and ignored stdio. The existing contract says direct in-sandbox edits are not adopted (docs/reference/commands.mdx:1081-1084), host config writes must share the root-only mutation lock and atomically refresh strict/compatibility hashes (:1086-1088), and config changes are refused while shields are up (:1090). The runtime enforces the same trust model in agents/hermes/start.sh:1850-1857. As written, this can silently fail under the normal locked posture or create config bytes that later fail strict-hash validation. Please route the change through the supported host mutation/lock/hash path (or choose a session-scoped design), surface failures, and cover shields-up plus hash-refresh behavior.

The documentation pass confirmed this changes user-visible connect behavior, but docs should follow after these lifecycle and mutation semantics are settled. I did not dispatch live E2E because the source/design gates above must be resolved first.

@cv

cv commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Exact-head CI follow-up for 0581b7ab0: Codebase Growth Guardrails run 29035420706 fails because src/lib/actions/sandbox/connect-hermes-light-theme.test.ts adds 3 if statements (0 at the base).

Please keep the changed test linear when addressing the requested source/design changes: split conditional behavior into separate cases, use declarative/mapped mock outputs, or move non-asserting conditional setup into a non-test helper. This is an additional required CI fix; no live E2E was dispatched while the source gates remain open.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: onboard-repair, onboard-resume, cloud-onboard
Optional E2E: hermes-e2e, sandbox-operations

Dispatch hint: onboard-repair,onboard-resume

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • onboard-repair (live E2E, ~75 minute timeout): Required by the deterministic risk plan for lifecycle-state changes in sandbox connect code. Validates repair convergence across persisted state, gateway/sandbox state, and live runtime after partial failure.
  • onboard-resume (live E2E, ~45 minute timeout): Required by the deterministic risk plan for lifecycle-state changes in sandbox connect code. Validates interrupted onboarding resume behavior and cached state convergence rather than relying only on unit tests.
  • cloud-onboard (high): Changed onboard, trace timing, scorecard, or E2E workflow code can affect cloud onboard wall-clock behavior and should refresh the trusted cloud-onboard trace timing signal.

Optional E2E

  • hermes-e2e (live E2E, ~75 minute timeout): Adjacent confidence for Hermes onboarding/runtime after adding Hermes-specific connect-time config and in-sandbox file writes. This does not fully cover the new light-terminal connect skin behavior, but it is the closest existing Hermes live user-flow validation.
  • sandbox-operations (live E2E): Broader adjacent coverage for sandbox lifecycle/status/cleanup contracts around connect-related code paths, including preserving owned state and recovering live sandbox/gateway state.

New E2E recommendations

  • hermes-connect-user-flow (high): No existing live E2E appears to specifically run a Hermes nemoclaw <sandbox> connect session with light-terminal environment detection and then verify the managed skin file/config are applied, cleaned up, and do not overwrite user-owned Hermes skins.
    • Suggested test: Add a live Hermes light-terminal connect E2E that onboards Hermes, sets TERM_PROGRAM/COLORFGBG to simulate a light terminal, runs nemoclaw <sandbox> connect through a PTY or minimal connect harness, asserts /sandbox/.hermes/skins/nemoclaw-light.yaml and display.skin: nemoclaw-light, reconnects with a dark terminal to assert managed cleanup, and separately verifies an existing user skin is preserved.

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: onboard-repair,onboard-resume

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: onboard-repair, onboard-resume
Optional E2E targets: None

Dispatch required E2E targets:

  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • onboard-repair: Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair
  • onboard-resume: Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume

Optional E2E targets

  • None.

Relevant changed files

  • src/lib/actions/sandbox/connect-hermes-light-skin.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/domain/sandbox/connect-env.ts

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 2 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Run the `onboard-repair` E2E job for Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime. Matched files: `src/lib/actions/sandbox/connect-hermes-light-skin.ts`, `src/lib/actions/sandbox/connect.ts`.. Deterministic regression risks require live validation: lifecycle-state. All deterministic behavior has checked-in coverage: 10 unit tests for pure helpers, 11 integration tests for all state transitions + failure modes + sibling isolation + redaction. Risk plan invariants (partial failure convergence, cleanup isolation) verified by integration tests. Required E2E jobs (onboard-repair, onboard-resume) are validation floor per risk plan for lifecycle-state family.
  • PRA-T2 Runtime validation — Run the `onboard-resume` E2E job for Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime. Matched files: `src/lib/actions/sandbox/connect-hermes-light-skin.ts`, `src/lib/actions/sandbox/connect.ts`.. Deterministic regression risks require live validation: lifecycle-state. All deterministic behavior has checked-in coverage: 10 unit tests for pure helpers, 11 integration tests for all state transitions + failure modes + sibling isolation + redaction. Risk plan invariants (partial failure convergence, cleanup isolation) verified by integration tests. Required E2E jobs (onboard-repair, onboard-resume) are validation floor per risk plan for lifecycle-state family.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings

Merge posture: No blocking advisor findings
Primary next action: Add or justify PRA-T1 and any related test follow-ups.
Open items: 0 required · 0 warnings · 0 suggestions · 4 test follow-ups
Since last review: 0 prior items resolved · 0 still apply · 0 new items found

Action checklist

  • PRA-T1 Add or justify test follow-up: Runtime validation
  • PRA-T2 Add or justify test follow-up: Runtime validation
  • PRA-T3 Add or justify test follow-up: Runtime validation
  • PRA-T4 Add or justify test follow-up: Runtime validation
Test follow-ups to resolve or justify

If these cover changed behavior, prefer adding them in this PR; otherwise state why existing coverage is enough or link the follow-up.

  • PRA-T1 Runtime validation — Run the `onboard-repair` E2E job for Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime. Matched files: `src/lib/actions/sandbox/connect-hermes-light-skin.ts`, `src/lib/actions/sandbox/connect.ts`.. Deterministic regression risks require live validation: lifecycle-state. Checked-in unit and mocked connect-flow tests cover each changed lifecycle-state invariant: partial failure/retry convergence, preparation before final connect, and cleanup scoping. The risk plan is tier 2 for lifecycle-state, so real OpenShell/Hermes validation remains useful but no live job execution is claimed.
  • PRA-T2 Runtime validation — Run/observe the `onboard-repair` E2E job for Hermes connect after light-skin preparation to validate persisted metadata, reported status, live runtime, and cleanup convergence across real OpenShell/Hermes boundaries.. Deterministic regression risks require live validation: lifecycle-state. Checked-in unit and mocked connect-flow tests cover each changed lifecycle-state invariant: partial failure/retry convergence, preparation before final connect, and cleanup scoping. The risk plan is tier 2 for lifecycle-state, so real OpenShell/Hermes validation remains useful but no live job execution is claimed.
  • PRA-T3 Runtime validation — Run the `onboard-resume` E2E job for Onboarding and sandbox state must converge across persisted metadata, reported status, and the live runtime. Matched files: `src/lib/actions/sandbox/connect-hermes-light-skin.ts`, `src/lib/actions/sandbox/connect.ts`.. Deterministic regression risks require live validation: lifecycle-state. Checked-in unit and mocked connect-flow tests cover each changed lifecycle-state invariant: partial failure/retry convergence, preparation before final connect, and cleanup scoping. The risk plan is tier 2 for lifecycle-state, so real OpenShell/Hermes validation remains useful but no live job execution is claimed.
  • PRA-T4 Runtime validation — Run/observe the `onboard-resume` E2E job for Hermes connect after light-skin preparation to validate persisted metadata, reported status, live runtime, and cleanup convergence across real OpenShell/Hermes boundaries.. Deterministic regression risks require live validation: lifecycle-state. Checked-in unit and mocked connect-flow tests cover each changed lifecycle-state invariant: partial failure/retry convergence, preparation before final connect, and cleanup scoping. The risk plan is tier 2 for lifecycle-state, so real OpenShell/Hermes validation remains useful but no live job execution is claimed.

Workflow run details

This is an automated, non-binding review; it still expects maintainers and agents to respond to each required or warning item. Treat suggestions as current-PR improvements when they touch changed code; defer only with maintainer rationale or a linked follow-up. A human maintainer must make the final merge decision.

@jyaunches jyaunches added v0.0.80 and removed v0.0.79 labels Jul 9, 2026
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
…_skin

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>

# Conflicts:
#	test/support/connect-flow-test-harness.ts

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/lib/actions/sandbox/connect-hermes-light-theme.test.ts (1)

37-39: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make all Hermes override gates explicit in these tests.

The first case does not stub HERMES_TUI_THEME; the other two cases stub neither HERMES_TUI_THEME nor HERMES_TUI_LIGHT. A runner-level override could therefore skip the new path while the tests still pass for the wrong reason. Set both variables to the intended empty/unset state in each case, with separate tests for non-empty overrides.

Also applies to: 86-89, 113-115

🤖 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 `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts` around lines 37 -
39, The Hermes theme tests do not explicitly control all override gates,
allowing runner environment values to affect results. In each test case around
the existing environment stubs, explicitly set both HERMES_TUI_THEME and
HERMES_TUI_LIGHT to empty/unset as intended, and add separate coverage for
non-empty overrides; update all referenced cases consistently.

Source: Path instructions

🧹 Nitpick comments (1)
src/lib/domain/sandbox/connect-env.test.ts (1)

19-30: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert that the environment is actually cloned.

This test only checks copied values, so it would pass if buildSandboxConnectEnv returned the original object. Capture the input, assert result is not the same reference, and verify the input remains unchanged.

As per path instructions, tests should verify observable behavior rather than only incidental implementation details.

🤖 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 `@src/lib/domain/sandbox/connect-env.test.ts` around lines 19 - 30, The test
should verify that buildSandboxConnectEnv returns a cloned environment without
mutating the input. Store the input environment in a variable, capture the
result, assert the result is not the same reference as the input, and confirm
the original input remains unchanged while retaining the existing value
assertions.

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 `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts`:
- Around line 137-138: Update the test assertion after the write operation to
inspect the actual payload passed to writeSandboxConfig via
writeSandboxConfigSpy.mock.calls[0][2], asserting it equals { model: "test" } or
otherwise contains no display.skin; do not rely on hermesConfig, since it is the
same object returned by the read mock and may only demonstrate in-place
mutation.

In `@src/lib/domain/sandbox/connect-env.ts`:
- Around line 39-62: Refactor applyHermesLightSkinConfig and
removeHermesLightSkinConfig to avoid mutating the caller’s ConfigObject: return
an immutable result containing the transformed config and a changed boolean,
preserving existing no-op and invalid-input behavior. Update action-layer
callers to use the returned config and persist changes there, while keeping
domain logic limited to pure transformations and decisions.
- Around line 120-132: Update shouldApplyHermesLightSkin to distinguish a
missing display.skin key from an explicitly present non-string value; use the
relevant config structure/key-presence check alongside hermesConfigDisplaySkin
so only missing skin or managed light skin qualifies. Keep
applyHermesLightSkinConfig behavior consistent, and add a regression test
covering non-string display.skin values such as null to ensure light-skin
preparation is not incorrectly selected.

---

Outside diff comments:
In `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts`:
- Around line 37-39: The Hermes theme tests do not explicitly control all
override gates, allowing runner environment values to affect results. In each
test case around the existing environment stubs, explicitly set both
HERMES_TUI_THEME and HERMES_TUI_LIGHT to empty/unset as intended, and add
separate coverage for non-empty overrides; update all referenced cases
consistently.

---

Nitpick comments:
In `@src/lib/domain/sandbox/connect-env.test.ts`:
- Around line 19-30: The test should verify that buildSandboxConnectEnv returns
a cloned environment without mutating the input. Store the input environment in
a variable, capture the result, assert the result is not the same reference as
the input, and confirm the original input remains unchanged while retaining the
existing value assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 51466300-474d-49e0-910e-319909700b61

📥 Commits

Reviewing files that changed from the base of the PR and between 0581b7a and 09fcdf5.

📒 Files selected for processing (6)
  • src/lib/actions/sandbox/connect-hermes-light-theme.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/domain/sandbox/connect-env.test.ts
  • src/lib/domain/sandbox/connect-env.ts
  • src/lib/onboard/gateway-recovery.test.ts
  • test/support/connect-flow-test-harness.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/actions/sandbox/connect.ts

Comment on lines +137 to +138
expect(harness.writeSandboxConfigSpy).toHaveBeenCalledOnce();
expect(hermesConfig).toEqual({ model: "test" });

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

Assert the configuration sent to the write boundary.

hermesConfig is the same object returned by the harness read mock, while writeSandboxConfig is a no-op. Checking the fixture afterward only proves in-place mutation; it can miss a regression where the write payload still contains display.skin. Assert writeSandboxConfigSpy.mock.calls[0][2] has no display.skin instead.

Suggested assertion
-    expect(hermesConfig).toEqual({ model: "test" });
+    const writtenConfig = harness.writeSandboxConfigSpy.mock.calls[0][2];
+    expect(writtenConfig).toEqual(expect.objectContaining({ model: "test" }));
+    expect(writtenConfig).not.toHaveProperty("display.skin");
📝 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(harness.writeSandboxConfigSpy).toHaveBeenCalledOnce();
expect(hermesConfig).toEqual({ model: "test" });
const writtenConfig = harness.writeSandboxConfigSpy.mock.calls[0][2];
expect(writtenConfig).toEqual(expect.objectContaining({ model: "test" }));
expect(writtenConfig).not.toHaveProperty("display.skin");
🤖 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 `@src/lib/actions/sandbox/connect-hermes-light-theme.test.ts` around lines 137
- 138, Update the test assertion after the write operation to inspect the actual
payload passed to writeSandboxConfig via writeSandboxConfigSpy.mock.calls[0][2],
asserting it equals { model: "test" } or otherwise contains no display.skin; do
not rely on hermesConfig, since it is the same object returned by the read mock
and may only demonstrate in-place mutation.

Source: Path instructions

Comment on lines +39 to +62
export function applyHermesLightSkinConfig(config: ConfigObject): boolean {
const display = config.display;
if (isConfigRecord(display)) {
if (display.skin !== undefined && display.skin !== NEMOCLAW_HERMES_LIGHT_SKIN_NAME) {
return false;
}
if (display.skin === NEMOCLAW_HERMES_LIGHT_SKIN_NAME) return false;
display.skin = NEMOCLAW_HERMES_LIGHT_SKIN_NAME;
return true;
}
if (display !== undefined) return false;
config.display = { skin: NEMOCLAW_HERMES_LIGHT_SKIN_NAME };
return true;
}

export function removeHermesLightSkinConfig(config: ConfigObject): boolean {
const display = config.display;
if (!isConfigRecord(display) || display.skin !== NEMOCLAW_HERMES_LIGHT_SKIN_NAME) {
return false;
}
delete display.skin;
if (Object.keys(display).length === 0) delete config.display;
return 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.

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Keep config transforms pure in the domain layer.

applyHermesLightSkinConfig and removeHermesLightSkinConfig mutate caller-owned objects. Move this transformation to an immutable result ({ config, changed }) and let the action layer persist it, preventing shared-state surprises and aligning ownership boundaries.

As per path instructions, domain modules should make pure decisions while actions orchestrate and state modules own persisted state.

🤖 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 `@src/lib/domain/sandbox/connect-env.ts` around lines 39 - 62, Refactor
applyHermesLightSkinConfig and removeHermesLightSkinConfig to avoid mutating the
caller’s ConfigObject: return an immutable result containing the transformed
config and a changed boolean, preserving existing no-op and invalid-input
behavior. Update action-layer callers to use the returned config and persist
changes there, while keeping domain logic limited to pure transformations and
decisions.

Source: Path instructions

Comment thread src/lib/domain/sandbox/connect-env.ts
@prekshivyas prekshivyas self-assigned this Jul 10, 2026
Signed-off-by: Prekshi Vyas <prekshiv@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)
src/lib/actions/sandbox/connect-hermes-light-skin.ts (1)

57-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Simplify the apply/remove control flow to reduce branching.

The mixed if/else-if chain with embedded early returns (Lines 75-84) is hard to trace at a glance and pushes cyclomatic complexity higher than needed for this function.

♻️ Suggested simplification
-  if (shouldApplyHermesLightSkin(agent, env, config)) {
-    const changed = applyHermesLightSkinConfig(config);
-    if (!changed && !hermesConfigUsesManagedLightSkin(config)) return;
-    if (!writeHermesLightSkinFile(sandboxName)) return;
-    if (!changed) return;
-  } else if (!shouldRemoveHermesLightSkin(agent, env, config)) {
-    return;
-  } else if (!removeHermesLightSkinConfig(config)) {
-    return;
-  }
+  let needsConfigWrite = false;
+  if (shouldApplyHermesLightSkin(agent, env, config)) {
+    const changed = applyHermesLightSkinConfig(config);
+    const alreadyManaged = hermesConfigUsesManagedLightSkin(config);
+    if (changed || alreadyManaged) {
+      if (!writeHermesLightSkinFile(sandboxName, target.configDir)) return;
+      needsConfigWrite = changed;
+    }
+  } else if (shouldRemoveHermesLightSkin(agent, env, config)) {
+    needsConfigWrite = removeHermesLightSkinConfig(config);
+  }
+  if (!needsConfigWrite) return;

As per coding guidelines, "Keep function complexity low."

🤖 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 `@src/lib/actions/sandbox/connect-hermes-light-skin.ts` around lines 57 - 91,
Refactor the apply/remove decision logic in prepareHermesLightTerminalSkin into
a simpler, flatter flow with clearly separated apply and removal paths. Preserve
the existing guards, file-write behavior, and early-return semantics while
reducing nested branching; consider extracting the apply/remove operations into
focused helper functions.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/lib/actions/sandbox/connect-hermes-light-skin.ts`:
- Around line 57-91: Refactor the apply/remove decision logic in
prepareHermesLightTerminalSkin into a simpler, flatter flow with clearly
separated apply and removal paths. Preserve the existing guards, file-write
behavior, and early-return semantics while reducing nested branching; consider
extracting the apply/remove operations into focused helper functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5ccc9bdf-06ea-4297-9794-6a6519138e40

📥 Commits

Reviewing files that changed from the base of the PR and between 09fcdf5 and 0ab9ad9.

📒 Files selected for processing (5)
  • src/lib/actions/sandbox/connect-hermes-light-skin.ts
  • src/lib/actions/sandbox/connect-hermes-light-theme.test.ts
  • src/lib/actions/sandbox/connect.ts
  • src/lib/domain/sandbox/connect-env.test.ts
  • src/lib/domain/sandbox/connect-env.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/lib/domain/sandbox/connect-env.test.ts
  • src/lib/domain/sandbox/connect-env.ts

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Comment thread src/lib/domain/sandbox/connect-env.test.ts Fixed
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Comment thread src/lib/domain/sandbox/connect-env.test.ts Fixed
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 29111677227
Workflow ref: fix/6380_hermes_light_skin
Requested targets: (default — all supported)
Requested jobs: onboard-repair,onboard-resume,hermes-e2e,cloud-onboard
Summary: 4 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
hermes-e2e ✅ success
onboard-repair ✅ success
onboard-resume ✅ success

@github-actions

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 29112526596
Workflow ref: fix/6380_hermes_light_skin
Requested targets: (default — all supported)
Requested jobs: onboard-repair,onboard-resume,hermes-e2e,cloud-onboard
Summary: 4 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
hermes-e2e ✅ success
onboard-repair ✅ success
onboard-resume ✅ success

@jyaunches
jyaunches merged commit 640e64b into main Jul 10, 2026
57 of 60 checks passed
@jyaunches
jyaunches deleted the fix/6380_hermes_light_skin branch July 10, 2026 18:45
cv pushed a commit that referenced this pull request Jul 11, 2026
## Summary

Release-prep documentation for **v0.0.80**. Adds the `## v0.0.80`
section to `docs/about/release-notes.mdx` summarizing user-facing
changes since v0.0.79, each bullet linking to the relevant deeper page.

Produced via `nemoclaw-contributor-update-docs` (pre-tag path): scanned
`v0.0.79..HEAD`, applied the docs skip list (no violations), and
confirmed the 8 commits that already shipped in-PR docs are complete. No
new pages needed.

## Source summary

- #6507 -> `docs/about/release-notes.mdx`: Hermes v0.18 + Slack Block
Kit (rich rendering, digest-pinned base image).
- #6584 / #6616 -> `docs/about/release-notes.mdx`: host-local OpenRouter
runtime attribution adapter (port `11437`,
`NEMOCLAW_OPENROUTER_RUNTIME_ADAPTER_PORT`) and native Deep Agents
`openrouter` provider.
- #6210 / #6292 -> `docs/about/release-notes.mdx`: host corporate proxy
CA import into sandbox trust (`NEMOCLAW_CORPORATE_CA_BUNDLE`,
`NEMOCLAW_CORPORATE_CA_IMPORT`).
- #6624 / #6623 / #6656 -> `docs/about/release-notes.mdx`:
release-matched base-image selection, surfaced cluster-image build
diagnostics, preserved Nemotron profile registration.
- #6629 / #6637 -> `docs/about/release-notes.mdx`: bare `connect`
default-sandbox behavior and route-probe hardening.
- #6634 / #6626 / #6596 / #5569 / #6610 / #6655 ->
`docs/about/release-notes.mdx`: onboarding/recovery preservation,
stale-gateway-PID fix, installer backup message, vLLM label on managed
platforms.
- #6578 / #5670 -> `docs/about/release-notes.mdx`: automatic Hermes
light terminal skin and non-interactive `npx` MCP server startup.

## Verification

`npm run docs`: 0 errors, all internal links resolve (2 pre-existing
hidden-page warnings). `_build/` variants for OpenClaw, Hermes, and Deep
Agents all regenerate with the v0.0.80 section.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>

🤖 Generated with [Claude Code](https://claude.com/claude-code)


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

* **Documentation**
  * Added release notes for v0.0.80.
  * Documented Hermes upgrades, including Slack Block Kit rendering.
  * Added details on OpenRouter traffic routing and attribution headers.
* Documented improved proxy certificate handling and sandbox
reliability.
* Highlighted enhanced connection defaults, route-probing safeguards,
onboarding recovery, and terminal/MCP startup behavior.
  * Added references to relevant user-guide documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: ui Web UI, terminal display, visual layout, or UX behavior bug-fix PR fixes a bug or regression integration: hermes Hermes integration behavior labels Jul 12, 2026
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
## Summary
- write a NemoClaw-managed `nemoclaw-light` Hermes skin inside the
sandbox Hermes home for light terminal sessions
- activate it only when `COLORFGBG` reports a light background and the
user has not set `HERMES_TUI_THEME`, `HERMES_TUI_LIGHT`, or
`display.skin`
- keep the theme chrome unchanged while using the darker Hermes
body/list text color from the upstream Hermes fix proposal

Fixes NVIDIA#6380.

Related upstream Hermes PR: NousResearch/hermes-agent#60972.

## Validation
- `npm test -- --run src/lib/domain/sandbox/connect-env.test.ts
src/lib/actions/sandbox/connect-hermes-light-theme.test.ts`
- `git diff --check`
- Linux smoke on `aits-log-worker-6`: real Hermes TUI output used
`#7A5A0F` (`38;2;122;90;15`) for body/list text after writing
`/sandbox/.hermes/skins/nemoclaw-light.yaml` and `display.skin:
nemoclaw-light`


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

* **New Features**
* Hermes sandbox connections now automatically prepare/apply a
light-compatible terminal skin when the host terminal appears light.
* The connect flow now uses a computed connection environment and avoids
unnecessary sandbox reconfiguration when a managed `display.skin` is
already present.
* **Bug Fixes**
* Improved reconnect and failure handling: connection still proceeds
while emitting safe, redacted warnings.
* Skin/config operations are correctly scoped to the selected Hermes
sandbox and skipped when user theme overrides are set.
* **Tests**
* Expanded Hermes connect-environment/skin behavior coverage and updated
the connect-flow test harness (plus timing determinism for gateway
recovery).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Chengjie Wang <chengjiew@nvidia.com>

---------

Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
## Summary

Release-prep documentation for **v0.0.80**. Adds the `## v0.0.80`
section to `docs/about/release-notes.mdx` summarizing user-facing
changes since v0.0.79, each bullet linking to the relevant deeper page.

Produced via `nemoclaw-contributor-update-docs` (pre-tag path): scanned
`v0.0.79..HEAD`, applied the docs skip list (no violations), and
confirmed the 8 commits that already shipped in-PR docs are complete. No
new pages needed.

## Source summary

- NVIDIA#6507 -> `docs/about/release-notes.mdx`: Hermes v0.18 + Slack Block
Kit (rich rendering, digest-pinned base image).
- NVIDIA#6584 / NVIDIA#6616 -> `docs/about/release-notes.mdx`: host-local OpenRouter
runtime attribution adapter (port `11437`,
`NEMOCLAW_OPENROUTER_RUNTIME_ADAPTER_PORT`) and native Deep Agents
`openrouter` provider.
- NVIDIA#6210 / NVIDIA#6292 -> `docs/about/release-notes.mdx`: host corporate proxy
CA import into sandbox trust (`NEMOCLAW_CORPORATE_CA_BUNDLE`,
`NEMOCLAW_CORPORATE_CA_IMPORT`).
- NVIDIA#6624 / NVIDIA#6623 / NVIDIA#6656 -> `docs/about/release-notes.mdx`:
release-matched base-image selection, surfaced cluster-image build
diagnostics, preserved Nemotron profile registration.
- NVIDIA#6629 / NVIDIA#6637 -> `docs/about/release-notes.mdx`: bare `connect`
default-sandbox behavior and route-probe hardening.
- NVIDIA#6634 / NVIDIA#6626 / NVIDIA#6596 / NVIDIA#5569 / NVIDIA#6610 / NVIDIA#6655 ->
`docs/about/release-notes.mdx`: onboarding/recovery preservation,
stale-gateway-PID fix, installer backup message, vLLM label on managed
platforms.
- NVIDIA#6578 / NVIDIA#5670 -> `docs/about/release-notes.mdx`: automatic Hermes
light terminal skin and non-interactive `npx` MCP server startup.

## Verification

`npm run docs`: 0 errors, all internal links resolve (2 pre-existing
hidden-page warnings). `_build/` variants for OpenClaw, Hermes, and Deep
Agents all regenerate with the v0.0.80 section.

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>

🤖 Generated with [Claude Code](https://claude.com/claude-code)


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

* **Documentation**
  * Added release notes for v0.0.80.
  * Documented Hermes upgrades, including Slack Block Kit rendering.
  * Added details on OpenRouter traffic routing and attribution headers.
* Documented improved proxy certificate handling and sandbox
reliability.
* Highlighted enhanced connection defaults, route-probing safeguards,
onboarding recovery, and terminal/MCP startup behavior.
  * Added references to relevant user-guide documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: cli Command line interface, flags, terminal UX, or output area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery area: ui Web UI, terminal display, visual layout, or UX behavior bug-fix PR fixes a bug or regression integration: hermes Hermes integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[macOS][Agent&Skills] Hermes CLI TUI reply text unreadable on light-theme Terminal.app

7 participants