Skip to content

fix(onboard): diagnose incomplete custom plugin images#6250

Closed
ericksoa wants to merge 85 commits into
mainfrom
fix/discussion-6108-plugin-image
Closed

fix(onboard): diagnose incomplete custom plugin images#6250
ericksoa wants to merge 85 commits into
mainfrom
fix/discussion-6108-plugin-image

Conversation

@ericksoa

@ericksoa ericksoa commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Extends Aaron Erickson's original custom-plugin diagnosis and lifecycle work so OpenClaw image plugins remain correct across onboarding, restart, recreation, and rebuild. The follow-up hardens provenance/restore boundaries, adds release-matched live coverage, and keeps the historical fixture isolated from Docker credentials.

Aaron remains the original author and PR author; Apurv Kumaria contributed the review-driven follow-up fixes.

Related Issue

Changes

  • Diagnose custom OpenClaw images that contain only the intermediate sandbox-base instead of the complete managed runtime.
  • Record authoritative image-plugin provenance and reconcile removed, renamed, and same-ID upgraded plugins during recreation/rebuild.
  • Preserve user-owned plugin/channel/tool state while removing stale image-owned configuration and fail closed on incomplete provenance.
  • Add deterministic v0.0.71 → current release lifecycle coverage for onboarding, restart, recreation, rebuild, workspace preservation, and EXDEV-safe runtime dependency replacement.
  • Authenticate only for the exact digest-pinned builder pre-pull, then remove Docker credentials before release-pinned fixture code runs.
  • Document the full-image plugin recipe, troubleshooting guidance, dependency risk controls, and the explicit REMOVE-WHEN condition.

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:
  • 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: CodeRabbit is green and there are zero unresolved review threads. Both exact-head Advisor workflows completed, but their sticky recommendations require independent human disposition; exact-head evidence and the requested decisions are in this review comment.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes the DCO sign-off declaration and every commit appears as Verified in GitHub — DCO is green; six historical Aaron commits remain unsigned under the explicit maintainer waiver, while both new contributor merge commits are GitHub Verified.
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — custom-Dockerfile 10/10; workflow/auth boundaries 10/10; runtime diagnosis 16/16; full onboard 65/65; current-main workflow integration 26/26; published-route regression 8/8
  • Applicable broad gate passed — standard CI completed with 34 passed and 2 expected skips; seven-lane exact-head live E2E passed all selected lanes; the Advisor-added sandbox-operations exact-head run also passed
  • Quality Gates section completed with required justifications or waivers — independent maintainer dispositions remain requested in the exact-head evidence comment.
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only) — completed with 0 errors and 2 pre-existing warnings
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Aaron Erickson aerickson@nvidia.com
Signed-off-by: Apurv Kumaria akumaria@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added support for OpenClaw custom-plugin images with clearer onboarding, restore, and recovery behavior.
    • Introduced a new weather plugin fixture and live E2E coverage for plugin discovery and invocation.
    • Added a dedicated EXDEV regression job for custom-plugin lifecycle and runtime dependency validation.
  • Bug Fixes
    • Improved recovery checks to prevent unsafe restores when custom image provenance is missing or incomplete.
    • Tightened restore and cleanup behavior for managed extensions and plugin-linked files.
  • Documentation
    • Expanded install, troubleshooting, and command reference guidance for custom Dockerfile-based sandboxes.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 3, 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 custom OpenClaw runtime diagnosis, threads OpenClaw plugin provenance through restore and rebuild flows, updates managed-extension and config-merge behavior, refreshes OpenClaw docs, and expands the weather fixture plus E2E regression coverage.

Changes

Custom OpenClaw runtime, provenance restore, docs, and lifecycle tests

Layer / File(s) Summary
Custom runtime diagnosis
src/lib/onboard/custom-openclaw-runtime-diagnosis.ts, src/lib/verify-deployment.ts, src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts, src/lib/verify-deployment.test.ts
Adds custom OpenClaw runtime failure classification, gateway/dashboard hint generation, and deployment verification branching for the new diagnostic path.
Recreate and backup provenance
src/lib/onboard/sandbox-recreate-protection.ts, src/lib/onboard/not-ready-recreate.ts, src/lib/onboard/sandbox-backup-on-recreate.ts, src/lib/onboard/created-sandbox-finalization.ts, src/lib/onboard.ts, src/lib/actions/sandbox/rebuild-*.ts, test/helpers/rebuild-flow-*.ts, src/lib/onboard/*test.ts
Adds recreate-protection orchestration, custom-image provenance checks for not-ready selection and recreate backups, and matching sandbox onboarding and backup tests.
Managed extensions and config provenance
src/lib/state/openclaw-managed-extensions.ts, src/lib/state/openclaw-plugin-restore.ts, src/lib/state/openclaw-config-merge.ts, src/lib/state/openclaw-config-restore-input.ts, src/lib/state/sandbox.ts, src/lib/state/registry.ts, src/lib/state/*test.ts, test/snapshot-openclaw-managed-extensions.test.ts
Adds OpenClaw image-plugin provenance discovery, restore planning, state backup and restore handling, registry persistence, managed-extension preservation, and provenance-aware config merge and restore input validation.
Docs and security waiver
docs/deployment/install-openclaw-plugins.mdx, docs/reference/commands*.mdx, docs/reference/troubleshooting.mdx, docs/get-started/quickstart.mdx, docs/manage-sandboxes/lifecycle.mdx, docs/about/release-notes.mdx, docs/security/e2e-weather-plugin-fixture-dependency-review.md
Updates the plugin onboarding, command reference, troubleshooting, lifecycle, release-note link, and fixture security waiver docs for the complete-image contract and provenance rules.
Weather plugin fixture
test/e2e/fixtures/plugins/weather/*, tsconfig.cli.json
Adds a deterministic weather plugin fixture package, manifest, build config, and tool implementation, and excludes the fixture from the CLI build.
Live plugin lifecycle regression
test/e2e/live/openclaw-plugin-runtime-exdev.test.ts, test/e2e/support/*.test.ts, test/e2e-fixture-dependency-review.test.ts, test/helpers/onboard-openshell-fixture.ts, test/onboard-custom-dockerfile.test.ts
Builds the weather-plugin Dockerfile at test time, verifies runtime/plugin integrity across onboarding and lifecycle transitions, and updates the supporting E2E workflow inventory and boundary tests.
CI workflow and contract checks
.github/workflows/e2e.yaml, .github/workflows/regression-e2e.yaml, test/regression-e2e-workflow.test.ts
Renames the OpenClaw EXDEV workflow job and step, extends the workflow gating and reporting, and updates the regression contract test to enforce the secret-free lane.

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

Suggested labels: area: sandbox

Suggested reviewers: jyaunches

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: diagnosing incomplete custom plugin images during onboarding.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/discussion-6108-plugin-image

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

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

@github-code-quality

github-code-quality Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

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

TypeScript / code-coverage/cli

The overall coverage in the branch remains at 76%, unchanged from the branch.

Show a code coverage summary of the most impacted files.
File 5ddf9a1 e4c712e +/-
src/lib/inference/nim.ts 71% 64% -7%
src/lib/state/config-io.ts 95% 88% -7%
src/lib/messagi.../persistence.ts 95% 92% -3%
src/lib/credentials/store.ts 61% 59% -2%
src/lib/state/sandbox.ts 75% 76% +1%
src/lib/adapters/http/probe.ts 89% 91% +2%
src/lib/actions...red-recovery.ts 78% 88% +10%
src/lib/state/o...ugin-restore.ts 0% 94% +94%
src/lib/onboard...me-diagnosis.ts 0% 100% +100%
src/lib/onboard...e-protection.ts 0% 100% +100%

Updated July 08, 2026 19:31 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

E2E Advisor Recommendation

Required E2E: onboard-resume, onboard-repair, cloud-onboard, openclaw-plugin-runtime-exdev, rebuild-openclaw, sandbox-rebuild, state-backup-restore, upgrade-stale-sandbox
Optional E2E: diagnostics, sandbox-survival, snapshot-commands

Dispatch hint: onboard-resume,onboard-repair,cloud-onboard,openclaw-plugin-runtime-exdev,rebuild-openclaw,sandbox-rebuild,state-backup-restore,upgrade-stale-sandbox

Workflow run

Full advisor summary

E2E Recommendation Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E

  • onboard-resume (medium): Required by the onboarding resume rule because onboarding state transitions, sandbox finalization, recreation protection, and session-sensitive paths changed. This must be exercised with the live resume flow, not only unit/runtime-boundary tests.
  • onboard-repair (high): Required by the onboarding resume rule because repair/recreate decisions and not-ready recovery can affect resumed onboarding repair behavior and must be validated at the live OpenShell boundary.
  • cloud-onboard (high): The changes can affect full hosted onboarding, created sandbox finalization, deployment verification, registry publication, and the real installer/onboard path.
  • openclaw-plugin-runtime-exdev (very high): Directly covers the new/modified OpenClaw custom-plugin lifecycle fixture and workflow target, including complete managed runtime construction, plugin runtime dependency replacement, restart persistence, and rebuild persistence across the live sandbox boundary.
  • rebuild-openclaw (high): OpenClaw rebuild behavior, plugin/config restore, and custom-image provenance changes can affect state restoration and post-rebuild OpenClaw repair in real sandboxes.
  • sandbox-rebuild (high): Rebuild preflight, backup, prepared recovery, and restore phase source files changed; this job validates the generic destructive rebuild lifecycle with live Docker/OpenShell boundaries.
  • state-backup-restore (medium): State backup/restore and OpenClaw plugin restore inputs changed, so live backup/restore behavior should be validated beyond unit-level archive and registry tests.
  • upgrade-stale-sandbox (medium): Installer/upgrade recovery semantics around custom-image evidence and validated backups are documented and implemented through sandbox state/recreate protection changes; stale-sandbox upgrade should prove existing recovery behavior remains safe.

Optional E2E

  • diagnostics (medium): Useful adjacent confidence for deployment verification and gateway/dashboard diagnostic output changes, but less targeted than cloud-onboard and the custom-plugin lifecycle test.
  • sandbox-survival (medium): Optional extra coverage for registry/state persistence and gateway restart survival after changes to sandbox registry/state code.
  • snapshot-commands (medium): Optional adjacent coverage for state backup/restore metadata paths and snapshot persistence after registry and sandbox state changes.

New E2E recommendations

  • custom OpenClaw image deployment diagnosis (high): The PR adds diagnosis for custom OpenClaw images that lack the managed runtime paths, but existing live coverage primarily exercises the successful full-runtime plugin path. Add a bounded live negative-path E2E that onboards from a base-only custom Dockerfile and asserts the managed-runtime diagnostic, sandbox retention behavior, and absence of misleading dashboard retry guidance.
    • Suggested test: custom-openclaw-runtime-diagnosis-live
  • custom-image provenance recovery guard (medium): The new provenance rules distinguish image-owned OpenClaw plugins from backup-only plugins and block unsafe custom-image recovery when provenance is missing or invalid. Add a live E2E that creates or simulates an older custom-image sandbox/backup without validated provenance and proves recreate/upgrade recovery fails closed before deleting the existing sandbox.
    • Suggested test: custom-openclaw-provenance-recovery-guard-live

Dispatch hint

  • Workflow: .github/workflows/e2e.yaml
  • jobs input: onboard-resume,onboard-repair,cloud-onboard,openclaw-plugin-runtime-exdev,rebuild-openclaw,sandbox-rebuild,state-backup-restore,upgrade-stale-sandbox

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

E2E Target Recommendation

Required E2E targets: openclaw-plugin-runtime-exdev, onboard-resume, onboard-repair
Optional E2E targets: None

Dispatch required E2E targets:

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

Workflow run

Full E2E target advisor summary

E2E Target Advisor

Base: origin/main
Head: HEAD
Confidence: high

Required E2E targets

  • openclaw-plugin-runtime-exdev: Focused free-standing E2E job wired for changed live test test/e2e/live/openclaw-plugin-runtime-exdev.test.ts.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=openclaw-plugin-runtime-exdev
  • onboard-resume: The onboarding, sandbox recreation, registration, deployment verification, and state restore changes can affect onboarding state transitions and persisted-session resume behavior. The onboarding resume rule requires onboard-resume for these paths.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-resume
  • onboard-repair: The recreate, backup/provenance, not-ready recovery, and restore changes can affect repair/backstop execution from persisted onboarding sessions, so onboard-repair is required alongside onboard-resume.
    • Dispatch: gh workflow run e2e.yaml --ref <pr-head-ref> --field jobs=onboard-repair

Optional E2E targets

  • None.

Relevant changed files

  • .github/workflows/e2e.yaml
  • src/lib/actions/sandbox/rebuild-backup-phase.ts
  • src/lib/actions/sandbox/rebuild-preflight-guards.ts
  • src/lib/actions/sandbox/rebuild-preflight-phase.ts
  • src/lib/actions/sandbox/rebuild-prepared-recovery.ts
  • src/lib/actions/sandbox/rebuild-restore-phase.ts
  • src/lib/onboard.ts
  • src/lib/onboard/created-sandbox-finalization.ts
  • src/lib/onboard/custom-openclaw-runtime-diagnosis.ts
  • src/lib/onboard/not-ready-recreate.ts
  • src/lib/onboard/sandbox-backup-on-recreate.ts
  • src/lib/onboard/sandbox-recreate-protection.ts
  • src/lib/onboard/sandbox-registration.ts
  • src/lib/state/openclaw-config-merge.ts
  • src/lib/state/openclaw-config-restore-input.ts
  • src/lib/state/openclaw-managed-extensions.ts
  • src/lib/state/openclaw-plugin-restore.ts
  • src/lib/state/registry.ts
  • src/lib/state/sandbox.ts
  • src/lib/verify-deployment.ts
  • test/e2e/fixtures/plugins/weather/.gitignore
  • test/e2e/fixtures/plugins/weather/openclaw.plugin.json
  • test/e2e/fixtures/plugins/weather/package-lock.json
  • test/e2e/fixtures/plugins/weather/package.json
  • test/e2e/fixtures/plugins/weather/src/index.ts
  • test/e2e/fixtures/plugins/weather/src/version.ts
  • test/e2e/fixtures/plugins/weather/tsconfig.json
  • test/e2e/live/openclaw-plugin-runtime-exdev.test.ts
  • test/e2e/support/e2e-workflow.test.ts
  • test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts
  • test/e2e/support/platform-parity-cloud-experimental.test.ts
  • test/e2e/support/upload-e2e-artifacts-workflow-boundary.test.ts

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-1: Trusted Discussion #6108 clauses are unavailable; then add or justify PRA-T1.
Open items: 1 required · 1 warning · 0 suggestions · 6 test follow-ups
Since last review: 0 prior items resolved · 2 still apply · 0 new items found

Action checklist

  • PRA-1 Fix: Trusted Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are unavailable
  • PRA-2 Resolve or justify: Weather plugin fixture keeps a known-vulnerable release-pinned OpenClaw dev graph in docs/security/e2e-weather-plugin-fixture-dependency-review.md:44
  • 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
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Acceptance clause

Findings index

ID Severity Category Location Required action
PRA-1 Required acceptance Provide a trusted issue/discussion extract containing the literal Discussion #6108 body and relevant comments, then map every named clause to concrete diff and test evidence. Do not rely on PR prose, branch names, commit messages, comments embedded in the diff, or test names as the acceptance source.
PRA-2 Resolve/justify security docs/security/e2e-weather-plugin-fixture-dependency-review.md:44 Resolve or explicitly justify the residual risk before merge: keep the waiver current with the exact lockfile digest and advisory state, preserve the workflow controls that remove Docker Hub credentials before fixture code runs, and update the fixture only with the reviewed NemoClaw/OpenClaw runtime pin. If the historical release pin is no longer required, move the fixture to a non-vulnerable audited graph.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-1 Required — Trusted Discussion #6108 clauses are unavailable

  • Location: not file-specific
  • Category: acceptance
  • Problem: The deterministic review context still has no trusted linked issue or discussion records for Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108; `linkedIssues` is empty. This PR changes sandbox lifecycle, custom OpenClaw image diagnosis, image-plugin provenance, destructive rebuild/recreate restore behavior, workflow credential boundaries, fixture dependencies, and docs. PR body text, branch names, commit messages, diff comments, and test names reference Unable to install custom plugin with NemoClaw (OpenClaw) #6108 but are PR-provided and cannot be used as the literal acceptance source of truth.
  • Impact: A literal Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body clause or named comment clause could remain unmapped or unimplemented while the PR modifies security-sensitive lifecycle behavior intended to satisfy that discussion.
  • Required action: Provide a trusted issue/discussion extract containing the literal Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body and relevant comments, then map every named clause to concrete diff and test evidence. Do not rely on PR prose, branch names, commit messages, comments embedded in the diff, or test names as the acceptance source.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read-only check: inspect the deterministic validation context for a trusted `linkedIssues` or equivalent record containing Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comments, then verify each literal clause maps to changed tests and code such as `src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts`, `src/lib/actions/sandbox/rebuild-backup-phase.test.ts`, `src/lib/onboard/created-sandbox-finalization.test.ts`, `src/lib/state/openclaw-plugin-restore.test.ts`, `src/lib/state/openclaw-config-merge.test.ts`, `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts`, and `test/e2e/live/openclaw-plugin-runtime-exdev.test.ts`.
  • Missing regression test: After trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 text is available, add or identify a targeted automated regression for any literal clause not already covered. Existing likely coverage to map includes base-only custom image diagnosis, fail-closed provenance before backup/delete, fresh plugin discovery failure leaving replacements unregistered, image-owned plugin config reconciliation, workflow credential cleanup, and live custom-plugin lifecycle persistence/EXDEV behavior.
  • Done when: The required change is committed and verification passes: Read-only check: inspect the deterministic validation context for a trusted `linkedIssues` or equivalent record containing Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comments, then verify each literal clause maps to changed tests and code such as `src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts`, `src/lib/actions/sandbox/rebuild-backup-phase.test.ts`, `src/lib/onboard/created-sandbox-finalization.test.ts`, `src/lib/state/openclaw-plugin-restore.test.ts`, `src/lib/state/openclaw-config-merge.test.ts`, `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts`, and `test/e2e/live/openclaw-plugin-runtime-exdev.test.ts`.
  • Evidence: `pr_review_validation_context.linkedIssues` is `[]`; the previous Advisor review reported the same acceptance limitation and the current deterministic context still lacks a trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comment extract.
Review findings by urgency: 1 required fix, 1 item to resolve/justify, 0 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-2 Resolve/justify — Weather plugin fixture keeps a known-vulnerable release-pinned OpenClaw dev graph

  • Location: docs/security/e2e-weather-plugin-fixture-dependency-review.md:44
  • Category: security
  • Problem: The fixture waiver records that `npm audit` reports 9 vulnerable packages in the release-pinned `openclaw@2026.5.27` development graph used by `test/e2e/fixtures/plugins/weather`. The PR adds meaningful controls: exact fixture versions, committed lockfile integrity, lockfile digest enforcement, `npm ci --ignore-scripts`, pruning development and peer dependencies before staging the runtime plugin, read-only workflow permissions, checkout credential persistence disabled, Docker auth cleanup before fixture execution, and workflow-boundary tests. The vulnerable graph remains an accepted residual risk rather than an eliminated risk.
  • Impact: If a vulnerable or compromised package in the fixture build graph executes during fixture compilation or runtime, it could affect the trusted E2E runner. The workflow limits credential exposure before fixture execution, but the repository is intentionally accepting known vulnerable code in a checked-in test dependency graph.
  • Recommended action: Resolve or explicitly justify the residual risk before merge: keep the waiver current with the exact lockfile digest and advisory state, preserve the workflow controls that remove Docker Hub credentials before fixture code runs, and update the fixture only with the reviewed NemoClaw/OpenClaw runtime pin. If the historical release pin is no longer required, move the fixture to a non-vulnerable audited graph.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read-only check: inspect `docs/security/e2e-weather-plugin-fixture-dependency-review.md` for the 9-vulnerability advisory record and compensating controls; inspect `test/e2e-fixture-dependency-review.test.ts` for exact-version, digest, integrity, and control-marker assertions; inspect `.github/workflows/e2e.yaml` and `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` for Docker auth cleanup and secret-free fixture execution before the Vitest step.
  • Missing regression test: Existing coverage enforces the current repository contract: `test/e2e-fixture-dependency-review.test.ts` binds committed fixture lockfiles to the waiver and exact lockfile digest/integrity, while `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` asserts Docker auth is removed/unset before fixture execution. Add a new test only if the accepted contract changes, for example to require a different credential cleanup step, dependency source, or non-vulnerable OpenClaw fixture pin.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read-only check: inspect `docs/security/e2e-weather-plugin-fixture-dependency-review.md` for the 9-vulnerability advisory record and compensating controls; inspect `test/e2e-fixture-dependency-review.test.ts` for exact-version, digest, integrity, and control-marker assertions; inspect `.github/workflows/e2e.yaml` and `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` for Docker auth cleanup and secret-free fixture execution before the Vitest step.
  • Evidence: `docs/security/e2e-weather-plugin-fixture-dependency-review.md` records 9 vulnerable packages in the release-pinned OpenClaw development graph. `test/e2e/fixtures/plugins/weather/package.json` pins `openclaw` to `2026.5.27`, and `.github/workflows/e2e.yaml` carries the secret-free fixture workflow boundary.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

  • None.
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 — Map the trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause for base-only custom OpenClaw image diagnosis to `src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts` and `src/lib/verify-deployment.test.ts`, or add a behavior test for any missing probe/hint case.. This PR changes runtime/sandbox/infrastructure paths including workflow jobs, Docker/OpenShell custom image creation, destructive rebuild/recreate restore, OpenClaw config/plugin provenance, and docs. The patch includes extensive unit/integration coverage plus a direct live Vitest lane; acceptance-specific runtime coverage still cannot be confirmed until trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are available.
  • PRA-T2 Runtime validation — Map the trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause for missing image-plugin provenance stopping before backup/delete to `src/lib/actions/sandbox/rebuild-backup-phase.test.ts` and `src/lib/onboard/sandbox-backup-on-recreate.test.ts`, or add a behavior test for any uncovered destructive boundary.. This PR changes runtime/sandbox/infrastructure paths including workflow jobs, Docker/OpenShell custom image creation, destructive rebuild/recreate restore, OpenClaw config/plugin provenance, and docs. The patch includes extensive unit/integration coverage plus a direct live Vitest lane; acceptance-specific runtime coverage still cannot be confirmed until trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are available.
  • PRA-T3 Runtime validation — Map the trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause for fresh custom-image plugin discovery failure leaving replacement sandboxes unregistered to `src/lib/onboard/created-sandbox-finalization.test.ts`, or add a behavior test for any uncovered cleanup/retry wording.. This PR changes runtime/sandbox/infrastructure paths including workflow jobs, Docker/OpenShell custom image creation, destructive rebuild/recreate restore, OpenClaw config/plugin provenance, and docs. The patch includes extensive unit/integration coverage plus a direct live Vitest lane; acceptance-specific runtime coverage still cannot be confirmed until trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are available.
  • PRA-T4 Runtime validation — Map the trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause for preserving fresh image-owned plugins while restoring user-owned plugin state to `src/lib/state/openclaw-plugin-restore.test.ts` and `src/lib/state/openclaw-config-merge.test.ts`, or add a behavior test for any uncovered rename/remove/same-ID ownership case.. This PR changes runtime/sandbox/infrastructure paths including workflow jobs, Docker/OpenShell custom image creation, destructive rebuild/recreate restore, OpenClaw config/plugin provenance, and docs. The patch includes extensive unit/integration coverage plus a direct live Vitest lane; acceptance-specific runtime coverage still cannot be confirmed until trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are available.
  • PRA-T5 Runtime validation — Map the trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause for Docker credential removal before release-pinned fixture execution to `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts`, or add a workflow-boundary test for any additional secret-free execution requirement.. This PR changes runtime/sandbox/infrastructure paths including workflow jobs, Docker/OpenShell custom image creation, destructive rebuild/recreate restore, OpenClaw config/plugin provenance, and docs. The patch includes extensive unit/integration coverage plus a direct live Vitest lane; acceptance-specific runtime coverage still cannot be confirmed until trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clauses are available.
  • PRA-T6 Acceptance clause — Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body and relevant comments — add test evidence or identify existing coverage. Trusted literal clauses are unavailable because the deterministic validation context has `linkedIssues: []`. PR-provided references to Unable to install custom plugin with NemoClaw (OpenClaw) #6108 in the body, branch name, commit messages, comments, test names, and diff text were treated as untrusted evidence only.
Since last review details

Current findings, using the urgency labels above:

PRA-1 Required — Trusted Discussion #6108 clauses are unavailable

  • Location: not file-specific
  • Category: acceptance
  • Problem: The deterministic review context still has no trusted linked issue or discussion records for Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108; `linkedIssues` is empty. This PR changes sandbox lifecycle, custom OpenClaw image diagnosis, image-plugin provenance, destructive rebuild/recreate restore behavior, workflow credential boundaries, fixture dependencies, and docs. PR body text, branch names, commit messages, diff comments, and test names reference Unable to install custom plugin with NemoClaw (OpenClaw) #6108 but are PR-provided and cannot be used as the literal acceptance source of truth.
  • Impact: A literal Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body clause or named comment clause could remain unmapped or unimplemented while the PR modifies security-sensitive lifecycle behavior intended to satisfy that discussion.
  • Required action: Provide a trusted issue/discussion extract containing the literal Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body and relevant comments, then map every named clause to concrete diff and test evidence. Do not rely on PR prose, branch names, commit messages, comments embedded in the diff, or test names as the acceptance source.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read-only check: inspect the deterministic validation context for a trusted `linkedIssues` or equivalent record containing Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comments, then verify each literal clause maps to changed tests and code such as `src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts`, `src/lib/actions/sandbox/rebuild-backup-phase.test.ts`, `src/lib/onboard/created-sandbox-finalization.test.ts`, `src/lib/state/openclaw-plugin-restore.test.ts`, `src/lib/state/openclaw-config-merge.test.ts`, `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts`, and `test/e2e/live/openclaw-plugin-runtime-exdev.test.ts`.
  • Missing regression test: After trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 text is available, add or identify a targeted automated regression for any literal clause not already covered. Existing likely coverage to map includes base-only custom image diagnosis, fail-closed provenance before backup/delete, fresh plugin discovery failure leaving replacements unregistered, image-owned plugin config reconciliation, workflow credential cleanup, and live custom-plugin lifecycle persistence/EXDEV behavior.
  • Done when: The required change is committed and verification passes: Read-only check: inspect the deterministic validation context for a trusted `linkedIssues` or equivalent record containing Discussion Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comments, then verify each literal clause maps to changed tests and code such as `src/lib/onboard/custom-openclaw-runtime-diagnosis.test.ts`, `src/lib/actions/sandbox/rebuild-backup-phase.test.ts`, `src/lib/onboard/created-sandbox-finalization.test.ts`, `src/lib/state/openclaw-plugin-restore.test.ts`, `src/lib/state/openclaw-config-merge.test.ts`, `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts`, and `test/e2e/live/openclaw-plugin-runtime-exdev.test.ts`.
  • Evidence: `pr_review_validation_context.linkedIssues` is `[]`; the previous Advisor review reported the same acceptance limitation and the current deterministic context still lacks a trusted Unable to install custom plugin with NemoClaw (OpenClaw) #6108 body/comment extract.

PRA-2 Resolve/justify — Weather plugin fixture keeps a known-vulnerable release-pinned OpenClaw dev graph

  • Location: docs/security/e2e-weather-plugin-fixture-dependency-review.md:44
  • Category: security
  • Problem: The fixture waiver records that `npm audit` reports 9 vulnerable packages in the release-pinned `openclaw@2026.5.27` development graph used by `test/e2e/fixtures/plugins/weather`. The PR adds meaningful controls: exact fixture versions, committed lockfile integrity, lockfile digest enforcement, `npm ci --ignore-scripts`, pruning development and peer dependencies before staging the runtime plugin, read-only workflow permissions, checkout credential persistence disabled, Docker auth cleanup before fixture execution, and workflow-boundary tests. The vulnerable graph remains an accepted residual risk rather than an eliminated risk.
  • Impact: If a vulnerable or compromised package in the fixture build graph executes during fixture compilation or runtime, it could affect the trusted E2E runner. The workflow limits credential exposure before fixture execution, but the repository is intentionally accepting known vulnerable code in a checked-in test dependency graph.
  • Recommended action: Resolve or explicitly justify the residual risk before merge: keep the waiver current with the exact lockfile digest and advisory state, preserve the workflow controls that remove Docker Hub credentials before fixture code runs, and update the fixture only with the reviewed NemoClaw/OpenClaw runtime pin. If the historical release pin is no longer required, move the fixture to a non-vulnerable audited graph.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read-only check: inspect `docs/security/e2e-weather-plugin-fixture-dependency-review.md` for the 9-vulnerability advisory record and compensating controls; inspect `test/e2e-fixture-dependency-review.test.ts` for exact-version, digest, integrity, and control-marker assertions; inspect `.github/workflows/e2e.yaml` and `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` for Docker auth cleanup and secret-free fixture execution before the Vitest step.
  • Missing regression test: Existing coverage enforces the current repository contract: `test/e2e-fixture-dependency-review.test.ts` binds committed fixture lockfiles to the waiver and exact lockfile digest/integrity, while `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` asserts Docker auth is removed/unset before fixture execution. Add a new test only if the accepted contract changes, for example to require a different credential cleanup step, dependency source, or non-vulnerable OpenClaw fixture pin.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read-only check: inspect `docs/security/e2e-weather-plugin-fixture-dependency-review.md` for the 9-vulnerability advisory record and compensating controls; inspect `test/e2e-fixture-dependency-review.test.ts` for exact-version, digest, integrity, and control-marker assertions; inspect `.github/workflows/e2e.yaml` and `test/e2e/support/openclaw-plugin-runtime-exdev-workflow-boundary.test.ts` for Docker auth cleanup and secret-free fixture execution before the Vitest step.
  • Evidence: `docs/security/e2e-weather-plugin-fixture-dependency-review.md` records 9 vulnerable packages in the release-pinned OpenClaw development graph. `test/e2e/fixtures/plugins/weather/package.json` pins `openclaw` to `2026.5.27`, and `.github/workflows/e2e.yaml` carries the secret-free fixture workflow boundary.

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 3, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor (Nemotron Ultra) — Blocked

Merge posture: Do not merge until addressed
Primary next action: Fix PRA-6: Cross-provenance plugin ID collision not validated in planOpenClawPluginRestore; then add or justify PRA-T1.
Open items: 10 required · 12 warnings · 2 suggestions · 8 test follow-ups
Since last review: 1 prior item resolved · 19 still apply · 7 new items found

Action checklist

  • PRA-6 Fix: Cross-provenance plugin ID collision not validated in planOpenClawPluginRestore in src/lib/state/openclaw-plugin-restore.ts:447
  • PRA-7 Fix: Cross-provenance plugin ID collision not validated in revalidatePreparedRecoveryBeforeDelete in src/lib/actions/sandbox/rebuild-prepared-recovery.ts:124
  • PRA-8 Fix: Missing regression test for cross-provenance plugin ID collision in src/lib/state/openclaw-plugin-restore.test.ts:395
  • PRA-9 Fix: 476-line monolith combines index reading, validation, and restore planning in src/lib/state/openclaw-plugin-restore.ts:1
  • PRA-10 Fix: Test file grew by 262 lines (388→650) — needs split by ownership domain in src/lib/state/openclaw-config-merge.test.ts:1
  • PRA-11 Fix: Test file grew by 244 lines (386→630) — needs split by agent type in src/lib/onboard/created-sandbox-finalization.test.ts:1
  • PRA-12 Fix: Provenance helpers belong in openclaw-plugin-restore.ts in src/lib/state/sandbox.ts:234
  • PRA-13 Fix: openclaw-config-merge.ts grew by 164 lines — multiple merge functions in one file in src/lib/state/openclaw-config-merge.ts:1
  • PRA-14 Fix: Test file grew by 85 lines (498→583) — needs split by verification layer in src/lib/verify-deployment.test.ts:1
  • PRA-15 Fix: verify-deployment.ts grew by 27 lines — formatVerificationDiagnostics should be extracted in src/lib/verify-deployment.ts:1
  • PRA-1 Resolve or justify: Source-of-truth review needed: docs/deployment/install-openclaw-plugins.mdx
  • PRA-2 Resolve or justify: Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45
  • PRA-3 Resolve or justify: Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65
  • PRA-4 Resolve or justify: Source-of-truth review needed: src/lib/actions/sandbox/rebuild-preflight-phase.ts / rebuild-preflight-guards.ts
  • PRA-5 Resolve or justify: Source-of-truth review needed: test/e2e/fixtures/plugins/weather/package-lock.json
  • PRA-16 Resolve or justify: Committed fixture lockfile has 9 vulnerable packages without CI revalidation gate in test/e2e/fixtures/plugins/weather/package-lock.json:1
  • PRA-17 Resolve or justify: Source-of-truth comment missing for custom-image plugin install workaround in docs/deployment/install-openclaw-plugins.mdx:1
  • PRA-18 Resolve or justify: shouldDiagnoseCustomOpenClawRuntime missing function-level source-of-truth comment in src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45
  • PRA-19 Resolve or justify: classifyOpenClawRuntimeFailure missing function-level source-of-truth comment in src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65
  • PRA-20 Resolve or justify: Early returns after bail() in preflight phase lack source-of-truth comment in src/lib/actions/sandbox/rebuild-preflight-phase.ts:1
  • 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
  • PRA-T5 Add or justify test follow-up: Runtime validation
  • PRA-T6 Add or justify test follow-up: Missing regression test for cross-provenance plugin ID collision
  • PRA-T7 Add or justify test follow-up: Test file grew by 1 line — verify test coverage intent
  • PRA-T8 Add or justify test follow-up: Acceptance clause
  • PRA-23 In-scope improvement: registry.ts grew by 9 lines (713→722) — review extraction feasibility in src/lib/state/registry.ts:1
  • PRA-24 In-scope improvement: Test file grew by 1 line — verify test coverage intent in src/lib/actions/sandbox/rebuild-dcode-recovery.test.ts:1

Findings index

ID Severity Category Location Required action
PRA-1 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-2 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-3 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-4 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-5 Resolve/justify architecture Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
PRA-6 Required security src/lib/state/openclaw-plugin-restore.ts:447 After both parseOpenClawImagePluginInstalls calls succeed, collect IDs from freshProjection.pluginInstalls and previousProjection.pluginInstalls. Reject with ok:false if any ID intersection exists where installPath or loadPaths differ (indicating different provenance). Only allow same-ID when installPath and loadPaths are identical (true upgrade).
PRA-7 Required security src/lib/actions/sandbox/rebuild-prepared-recovery.ts:124 After authoritativePluginProvenance validation (line 111), add explicit cross-provenance ID collision check: extract IDs from candidate.openclawImagePluginInstalls and latestManifest.openclawImagePluginInstalls, reject with failPreparedRecoveryPreDelete if any intersection exists where installPath or loadPaths differ.
PRA-8 Required tests src/lib/state/openclaw-plugin-restore.test.ts:395 Add test case: planOpenClawPluginRestore with freshImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v2', loadPaths:[]}] and previousImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v1', loadPaths:[]}] should return ok:false. Add equivalent test in rebuild-prepared-recovery.test.ts for pre-delete boundary.
PRA-9 Required architecture src/lib/state/openclaw-plugin-restore.ts:1 Extract into three modules: openclaw-plugin-index-reader.ts (buildFreshOpenClawPluginIndexSqliteReadCommand, readFreshOpenClawPluginInstallIndex, discoverFreshOpenClawPluginExtensionDirs, discoverFreshOpenClawImagePluginInstalls), openclaw-plugin-validator.ts (parseOpenClawImagePluginInstalls, validateDurableOpenClawImagePluginInstall, isSafeOpenClawPluginInstallId, isSafeOpenClawExtensionDirName, hasCompleteOpenClawImagePluginProvenance), openclaw-plugin-restore-planner.ts (planOpenClawPluginRestore). Split test file correspondingly.
PRA-10 Required architecture src/lib/state/openclaw-config-merge.test.ts:1 Split into: openclaw-config-merge-channels.test.ts, openclaw-config-merge-plugins.test.ts, openclaw-config-merge-providers.test.ts, openclaw-config-merge-tools.test.ts. Each with focused test setup.
PRA-11 Required architecture src/lib/onboard/created-sandbox-finalization.test.ts:1 Split into created-openclaw-finalization.test.ts and created-dcode-finalization.test.ts. Each covers its agent's finalization path independently.
PRA-12 Required architecture src/lib/state/sandbox.ts:234 Move hasAuthoritativeOpenClawImagePluginProvenance and hasCompleteOpenClawImagePluginProvenance to openclaw-plugin-restore.ts, export them, and update imports in call sites. Add tests for hasAuthoritativeOpenClawImagePluginProvenance in openclaw-plugin-restore.test.ts (hasCompleteOpenClawImagePluginProvenance already tested).
PRA-13 Required architecture src/lib/state/openclaw-config-merge.ts:1 Extract each merge function into separate modules or add clear /// section comments with module boundaries. Each merge function should have its own test file mirroring the split in PRA-10.
PRA-14 Required architecture src/lib/verify-deployment.test.ts:1 Split into verify-gateway.test.ts, verify-dashboard.test.ts, verify-inference.test.ts, verify-messaging.test.ts, verify-custom-runtime.test.ts.
PRA-15 Required architecture src/lib/verify-deployment.ts:1 Extract formatVerificationDiagnostics to verify-deployment-format.ts. Keep core verification in verify-deployment.ts. Split test file per PRA-14.
PRA-16 Resolve/justify security test/e2e/fixtures/plugins/weather/package-lock.json:1 Add CI step (e.g., in e2e.yaml or new workflow) that runs 'npm audit --package-lock-only --ignore-scripts --json' on fixture lockfiles and fails if new advisories appear beyond documented baseline. Revalidate waiver on every fixture manifest or lockfile change. Document baseline advisory IDs in waiver doc (partially done in e2e-weather-plugin-fixture-dependency-review.md).
PRA-17 Resolve/justify architecture docs/deployment/install-openclaw-plugins.mdx:1 Add source-of-truth comment block in document (or code) linking: validation functions (hasAuthoritativeOpenClawImagePluginProvenance in sandbox.ts, planOpenClawPluginRestore in openclaw-plugin-restore.ts), E2E test (openclaw-plugin-runtime-exdev.test.ts), and removal condition (#5998).
PRA-18 Resolve/justify architecture src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45 Add JSDoc comment block at line 45 (function start) with: @InvalidState 'user Dockerfile selects sandbox-base as final runtime', @sourceBoundary 'onboard --from Dockerfile source boundary', @sourceFixConstraint 'requires static analysis of arbitrary multi-stage Dockerfiles or build-time image contract', @RegressionTest 'classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E', @removalCondition '#5998 managed plugin lifecycle or build-time image contract validator'.
PRA-19 Resolve/justify architecture src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65 Add module-level or function-level source-of-truth comment with all five tags matching PRA-17.
PRA-20 Resolve/justify architecture src/lib/actions/sandbox/rebuild-preflight-phase.ts:1 Identify invalid state handled, source boundary, why source can't be fixed, regression test, and removal condition for each early-return path. Add source-of-truth comment if this is a deliberate workaround. Consider consolidating fail-closed patterns.

🚨 Required before merge

Address these before merging unless a maintainer explicitly overrides the advisor with rationale.

PRA-6 Required — Cross-provenance plugin ID collision not validated in planOpenClawPluginRestore

  • Location: src/lib/state/openclaw-plugin-restore.ts:447
  • Category: security
  • Problem: planOpenClawPluginRestore treats same plugin ID in both fresh and previous projections as an upgrade without verifying installPath and loadPaths are identical. A custom image installing a plugin with the same ID as a user-installed plugin (different provenance) causes the previous directory to be excluded from backup while fresh image code wins — sandbox escape via plugin substitution.
  • Impact: Attacker with custom-image build access can install a malicious plugin sharing an ID with a legitimate user plugin; during rebuild/recovery, the user's plugin directory is excluded from backup and the malicious version persists, enabling arbitrary code execution in the sandbox.
  • Required action: After both parseOpenClawImagePluginInstalls calls succeed, collect IDs from freshProjection.pluginInstalls and previousProjection.pluginInstalls. Reject with ok:false if any ID intersection exists where installPath or loadPaths differ (indicating different provenance). Only allow same-ID when installPath and loadPaths are identical (true upgrade).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/state/openclaw-plugin-restore.ts lines 423-480; search for ID intersection check between freshProjection and previousProjection pluginInstalls — currently absent.
  • Missing regression test: Add test case in openclaw-plugin-restore.test.ts: planOpenClawPluginRestore with fresh and previous having same ID but different installPath/loadPaths should return ok:false.
  • Done when: The required change is committed and verification passes: Read src/lib/state/openclaw-plugin-restore.ts lines 423-480; search for ID intersection check between freshProjection and previousProjection pluginInstalls — currently absent.
  • Evidence: Line 447 comment explicitly states 'The same ID in both projections is an image-owned plugin upgrade, not a provenance collision' without validation. PRA-6 from previous review still applies.

PRA-7 Required — Cross-provenance plugin ID collision not validated in revalidatePreparedRecoveryBeforeDelete

  • Location: src/lib/actions/sandbox/rebuild-prepared-recovery.ts:124
  • Category: security
  • Problem: Pre-delete check validates authoritativePluginProvenance but does not compare candidate.openclawImagePluginInstalls against latestManifest.openclawImagePluginInstalls for cross-provenance collisions. Comment at line 124-127 acknowledges 'fresh-vs-previous ownership is validated later by the restore planner after the replacement image has been created' but restore planner (PRA-6) does not do it.
  • Impact: Pre-delete check passes for custom-image recovery with cross-provenance collision; deletion proceeds, then restore planner silently accepts collision. User's legitimate plugin lost, malicious custom-image plugin persists.
  • Required action: After authoritativePluginProvenance validation (line 111), add explicit cross-provenance ID collision check: extract IDs from candidate.openclawImagePluginInstalls and latestManifest.openclawImagePluginInstalls, reject with failPreparedRecoveryPreDelete if any intersection exists where installPath or loadPaths differ.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/actions/sandbox/rebuild-prepared-recovery.ts lines 110-130; verify no collision check between candidate and latestManifest plugin installs.
  • Missing regression test: Add test in rebuild-prepared-recovery.test.ts: revalidatePreparedRecoveryBeforeDelete with candidate and latestManifest having same plugin ID but different installPath should reject with failPreparedRecoveryPreDelete.
  • Done when: The required change is committed and verification passes: Read src/lib/actions/sandbox/rebuild-prepared-recovery.ts lines 110-130; verify no collision check between candidate and latestManifest plugin installs.
  • Evidence: Comment at line 124-127 admits validation deferred to restore planner; PRA-7 from previous review still applies.

PRA-8 Required — Missing regression test for cross-provenance plugin ID collision

  • Location: src/lib/state/openclaw-plugin-restore.test.ts:395
  • Category: tests
  • Problem: Test suite covers upgrade (same ID + same path), invalid provenance (relative path), empty provenance — but no test for same ID with different installPath/loadPaths which should be rejected as collision.
  • Impact: Without this test, the collision vulnerability (PRA-6, PRA-7) cannot be caught by CI. Future refactors could reintroduce the bug undetected.
  • Required action: Add test case: planOpenClawPluginRestore with freshImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v2', loadPaths:[]}] and previousImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v1', loadPaths:[]}] should return ok:false. Add equivalent test in rebuild-prepared-recovery.test.ts for pre-delete boundary.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search openclaw-plugin-restore.test.ts for 'cross', 'provenance', 'collision', 'same.*id.*different' — no matches found.
  • Missing regression test: This finding IS the missing regression test request. Implement the test described in recommendation.
  • Done when: The required change is committed and verification passes: Search openclaw-plugin-restore.test.ts for 'cross', 'provenance', 'collision', 'same.*id.*different' — no matches found.
  • Evidence: PRA-8 from previous review still applies; test file ends at line 476 with no collision test.

PRA-9 Required — 476-line monolith combines index reading, validation, and restore planning

  • Location: src/lib/state/openclaw-plugin-restore.ts:1
  • Category: architecture
  • Problem: New file openclaw-plugin-restore.ts (476 lines) contains SQLite index reading, legacy JSON fallback, plugin install validation, ID safety checks, path validation, extension directory projection, and restore planning — three distinct responsibilities in one file.
  • Impact: Hard to review, test, and maintain. Security-critical validation logic mixed with I/O and planning. Changes to one domain risk breaking others.
  • Required action: Extract into three modules: openclaw-plugin-index-reader.ts (buildFreshOpenClawPluginIndexSqliteReadCommand, readFreshOpenClawPluginInstallIndex, discoverFreshOpenClawPluginExtensionDirs, discoverFreshOpenClawImagePluginInstalls), openclaw-plugin-validator.ts (parseOpenClawImagePluginInstalls, validateDurableOpenClawImagePluginInstall, isSafeOpenClawPluginInstallId, isSafeOpenClawExtensionDirName, hasCompleteOpenClawImagePluginProvenance), openclaw-plugin-restore-planner.ts (planOpenClawPluginRestore). Split test file correspondingly.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Count lines in openclaw-plugin-restore.ts (476) and identify distinct responsibility boundaries: lines 1-150 (SQLite/legacy reading), 150-350 (validation), 350-476 (planning).
  • Missing regression test: After extraction, each module should have its own focused test file mirroring the current test coverage split by domain.
  • Done when: The required change is committed and verification passes: Count lines in openclaw-plugin-restore.ts (476) and identify distinct responsibility boundaries: lines 1-150 (SQLite/legacy reading), 150-350 (validation), 350-476 (planning).
  • Evidence: Drift tool flagged +476 lines as blocker severity; PRA-9 from previous review still applies.

PRA-10 Required — Test file grew by 262 lines (388→650) — needs split by ownership domain

  • Location: src/lib/state/openclaw-config-merge.test.ts:1
  • Category: architecture
  • Problem: openclaw-config-merge.test.ts grew from 388 to 650 lines (+262), combining channel, plugin, provider, and tool merge tests in one file.
  • Impact: Test maintenance burden; hard to isolate failures; CI runs all tests together slowing feedback.
  • Required action: Split into: openclaw-config-merge-channels.test.ts, openclaw-config-merge-plugins.test.ts, openclaw-config-merge-providers.test.ts, openclaw-config-merge-tools.test.ts. Each with focused test setup.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check openclaw-config-merge.test.ts line count (650) and identify test describe blocks for channels, plugins, providers, tools.
  • Missing regression test: After split, each test file must pass independently with full coverage of its domain.
  • Done when: The required change is committed and verification passes: Check openclaw-config-merge.test.ts line count (650) and identify test describe blocks for channels, plugins, providers, tools.
  • Evidence: Drift tool flagged +262 lines as blocker; PRA-10 from previous review still applies.

PRA-11 Required — Test file grew by 244 lines (386→630) — needs split by agent type

  • Location: src/lib/onboard/created-sandbox-finalization.test.ts:1
  • Category: architecture
  • Problem: created-sandbox-finalization.test.ts grew from 386 to 630 lines (+244), combining OpenClaw and DCode finalization tests.
  • Impact: Agent-specific finalization logic mixed; hard to verify each agent's behavior in isolation.
  • Required action: Split into created-openclaw-finalization.test.ts and created-dcode-finalization.test.ts. Each covers its agent's finalization path independently.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check created-sandbox-finalization.test.ts line count (630) and identify OpenClaw vs DCode test describe blocks.
  • Missing regression test: After split, each test file must pass independently with full coverage of its agent's finalization.
  • Done when: The required change is committed and verification passes: Check created-sandbox-finalization.test.ts line count (630) and identify OpenClaw vs DCode test describe blocks.
  • Evidence: Drift tool flagged +244 lines as blocker; PRA-11 from previous review still applies.

PRA-12 Required — Provenance helpers belong in openclaw-plugin-restore.ts

  • Location: src/lib/state/sandbox.ts:234
  • Category: architecture
  • Problem: hasAuthoritativeOpenClawImagePluginProvenance and hasCompleteOpenClawImagePluginProvenance are defined in sandbox.ts (lines 234-268) but are OpenClaw plugin provenance logic, not general sandbox state. They are imported by rebuild-backup-phase.ts, rebuild-prepared-recovery.ts, sandbox-backup-on-recreate.ts, not-ready-recreate.ts.
  • Impact: Provenance logic scattered across sandbox.ts instead of co-located with plugin restore logic. Violates module cohesion; harder to audit security boundaries.
  • Required action: Move hasAuthoritativeOpenClawImagePluginProvenance and hasCompleteOpenClawImagePluginProvenance to openclaw-plugin-restore.ts, export them, and update imports in call sites. Add tests for hasAuthoritativeOpenClawImagePluginProvenance in openclaw-plugin-restore.test.ts (hasCompleteOpenClawImagePluginProvenance already tested).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search sandbox.ts for 'hasAuthoritativeOpenClawImagePluginProvenance' and 'hasCompleteOpenClawImagePluginProvenance' — found at lines 234, 246, 267, 1764.
  • Missing regression test: Add test for hasAuthoritativeOpenClawImagePluginProvenance in openclaw-plugin-restore.test.ts covering reconcileOpenClawImagePluginProvenance=true with valid/invalid installs.
  • Done when: The required change is committed and verification passes: Search sandbox.ts for 'hasAuthoritativeOpenClawImagePluginProvenance' and 'hasCompleteOpenClawImagePluginProvenance' — found at lines 234, 246, 267, 1764.
  • Evidence: Drift tool flagged +187 lines in sandbox.ts as blocker; PRA-12 from previous review still applies.

PRA-13 Required — openclaw-config-merge.ts grew by 164 lines — multiple merge functions in one file

  • Location: src/lib/state/openclaw-config-merge.ts:1
  • Category: architecture
  • Problem: openclaw-config-merge.ts grew from 304 to 468 lines (+164), containing merge functions for channels, plugins, providers, tools, and subagents in one file without clear module boundaries.
  • Impact: Hard to review merge logic per domain; changes to one merge function risk affecting others.
  • Required action: Extract each merge function into separate modules or add clear /// section comments with module boundaries. Each merge function should have its own test file mirroring the split in PRA-10.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check openclaw-config-merge.ts line count (468) and identify distinct merge function exports.
  • Missing regression test: After extraction, each merge module must have its own test file with full coverage.
  • Done when: The required change is committed and verification passes: Check openclaw-config-merge.ts line count (468) and identify distinct merge function exports.
  • Evidence: Drift tool flagged +164 lines as blocker; PRA-13 from previous review still applies.

PRA-14 Required — Test file grew by 85 lines (498→583) — needs split by verification layer

  • Location: src/lib/verify-deployment.test.ts:1
  • Category: architecture
  • Problem: verify-deployment.test.ts grew from 498 to 583 lines (+85), combining gateway, dashboard, inference, messaging, and custom runtime verification tests.
  • Impact: Test file becoming monolithic; hard to run focused verification layer tests.
  • Required action: Split into verify-gateway.test.ts, verify-dashboard.test.ts, verify-inference.test.ts, verify-messaging.test.ts, verify-custom-runtime.test.ts.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check verify-deployment.test.ts line count (583) and identify test describe blocks per verification layer.
  • Missing regression test: After split, each test file must pass independently with full coverage of its verification layer.
  • Done when: The required change is committed and verification passes: Check verify-deployment.test.ts line count (583) and identify test describe blocks per verification layer.
  • Evidence: Drift tool flagged +85 lines as blocker; PRA-14 from previous review still applies.

PRA-15 Required — verify-deployment.ts grew by 27 lines — formatVerificationDiagnostics should be extracted

  • Location: src/lib/verify-deployment.ts:1
  • Category: architecture
  • Problem: verify-deployment.ts grew from 582 to 609 lines (+27). The formatVerificationDiagnostics function (formatting logic) is mixed with core verification logic.
  • Impact: Formatting concerns mixed with verification logic; harder to test formatting in isolation.
  • Required action: Extract formatVerificationDiagnostics to verify-deployment-format.ts. Keep core verification in verify-deployment.ts. Split test file per PRA-14.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search verify-deployment.ts for 'formatVerificationDiagnostics' function.
  • Missing regression test: Add test file for verify-deployment-format.ts with formatting edge cases.
  • Done when: The required change is committed and verification passes: Search verify-deployment.ts for 'formatVerificationDiagnostics' function.
  • Evidence: Drift tool flagged +27 lines as blocker; PRA-15 from previous review still applies.
Review findings by urgency: 10 required fixes, 12 items to resolve/justify, 2 in-scope improvements

⚠️ Resolve or justify before merge

Investigate these in the current review; either fix them, explain why they are not applicable, or document the accepted risk.

PRA-1 Resolve/justify — Source-of-truth review needed: docs/deployment/install-openclaw-plugins.mdx

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E (openclaw-plugin-runtime-exdev.test.ts)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Document has Warning block referencing VoiceClaw integration via existing messaging and provider contracts #5998 but no structured @invalidState/@sourceBoundary/@sourceFixConstraint/@regressionTest/@removalCondition tags. PRA-16.

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Function shouldDiagnoseCustomOpenClawRuntime at line 45 lacks function-level JSDoc with 5 source-of-truth tags. Module-level REMOVE-WHEN exists. PRA-17.

PRA-3 Resolve/justify — Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Function classifyOpenClawRuntimeFailure at line 65 lacks function-level JSDoc with 5 source-of-truth tags. PRA-18.

PRA-4 Resolve/justify — Source-of-truth review needed: src/lib/actions/sandbox/rebuild-preflight-phase.ts / rebuild-preflight-guards.ts

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: rebuild-preflight-guards.test.ts (not in diff) should cover each fail-closed path
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Multiple bail() calls with early returns in preflight-guards.ts (checkRebuildGatewaySchemaPreflight, getRebuildSandboxEntryOrBail, isSingleAgentRebuildSupported, acquireRebuildOnboardLock) lack source-of-truth comments. PRA-19.

PRA-5 Resolve/justify — Source-of-truth review needed: test/e2e/fixtures/plugins/weather/package-lock.json

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: e2e-fixture-dependency-review.test.ts enforces review doc existence and lockfile digest; npm audit documented in review
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Review doc exists with advisory list and SHA-256 digest; compensating controls documented. But no CI gate to revalidate. PRA-20.

PRA-16 Resolve/justify — Committed fixture lockfile has 9 vulnerable packages without CI revalidation gate

  • Location: test/e2e/fixtures/plugins/weather/package-lock.json:1
  • Category: security
  • Problem: Weather fixture package-lock.json has 9 npm advisories (3 moderate, 6 high: GHSA-22p9-wv53-3rq4, GHSA-2gcr-mfcq-wcc3, etc.). Compensating controls documented (npm ci --ignore-scripts, --no-audit --no-fund, prune dev/peer deps, lockfile integrity) but no automated CI gate to revalidate on lockfile change or advisory update.
  • Impact: If new advisories affect fixture dependencies, the E2E lane could compile/run vulnerable code. Risk is limited to secret-free test lane with read-only contents permission, but should be gated.
  • Recommended action: Add CI step (e.g., in e2e.yaml or new workflow) that runs 'npm audit --package-lock-only --ignore-scripts --json' on fixture lockfiles and fails if new advisories appear beyond documented baseline. Revalidate waiver on every fixture manifest or lockfile change. Document baseline advisory IDs in waiver doc (partially done in e2e-weather-plugin-fixture-dependency-review.md).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run 'npm audit --package-lock-only --ignore-scripts --json' from test/e2e/fixtures/plugins/weather — exits 1 with 9 vulnerable packages. Check .github/workflows for any npm audit step on fixtures.
  • Missing regression test: e2e-fixture-dependency-review.test.ts enforces review doc existence but does not run npm audit. Add audit step to CI or enhance test to fail on new advisories.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run 'npm audit --package-lock-only --ignore-scripts --json' from test/e2e/fixtures/plugins/weather — exits 1 with 9 vulnerable packages. Check .github/workflows for any npm audit step on fixtures.
  • Evidence: e2e-weather-plugin-fixture-dependency-review.md documents 9 advisories and SHA-256 lockfile digest; PRA-20 from previous review still applies.

PRA-17 Resolve/justify — Source-of-truth comment missing for custom-image plugin install workaround

PRA-18 Resolve/justify — shouldDiagnoseCustomOpenClawRuntime missing function-level source-of-truth comment

  • Location: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45
  • Category: architecture
  • Problem: Function at line 45 handles invalid state (user Dockerfile selects sandbox-base as final runtime) but lacks function-level source-of-truth comment with all 5 tags (@InvalidState, @sourceBoundary, @sourceFixConstraint, @RegressionTest, @removalCondition). Module-level comment exists but not at function.
  • Impact: Cannot trace this specific function to its invalid state, source boundary, fix constraint, test, and removal condition without reading full module.
  • Recommended action: Add JSDoc comment block at line 45 (function start) with: @InvalidState 'user Dockerfile selects sandbox-base as final runtime', @sourceBoundary 'onboard --from Dockerfile source boundary', @sourceFixConstraint 'requires static analysis of arbitrary multi-stage Dockerfiles or build-time image contract', @RegressionTest 'classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E', @removalCondition 'VoiceClaw integration via existing messaging and provider contracts #5998 managed plugin lifecycle or build-time image contract validator'.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read custom-openclaw-runtime-diagnosis.ts line 45; verify no JSDoc comment with all 5 tags.
  • Missing regression test: Classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E (openclaw-plugin-runtime-exdev.test.ts) already exist.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read custom-openclaw-runtime-diagnosis.ts line 45; verify no JSDoc comment with all 5 tags.
  • Evidence: PRA-17 from previous review still applies. Module-level REMOVE-WHEN comment exists but not function-level.

PRA-19 Resolve/justify — classifyOpenClawRuntimeFailure missing function-level source-of-truth comment

  • Location: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65
  • Category: architecture
  • Problem: Function at line 65 distinguishes base-only image failure from normal gateway failure but lacks function-level source-of-truth comment with all 5 tags.
  • Impact: Same as PRA-17 — traceability gap for this security-critical classifier.
  • Recommended action: Add module-level or function-level source-of-truth comment with all five tags matching PRA-17.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read custom-openclaw-runtime-diagnosis.ts line 65; verify no JSDoc comment with all 5 tags.
  • Missing regression test: Classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E already exist.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read custom-openclaw-runtime-diagnosis.ts line 65; verify no JSDoc comment with all 5 tags.
  • Evidence: PRA-18 from previous review still applies.

PRA-20 Resolve/justify — Early returns after bail() in preflight phase lack source-of-truth comment

  • Location: src/lib/actions/sandbox/rebuild-preflight-phase.ts:1
  • Category: architecture
  • Problem: rebuild-preflight-phase.ts has multiple early returns after bail() calls (gateway schema mismatch, sandbox not found, multi-agent unsupported, lock contention). These are deliberate fail-closed guards but lack source-of-truth comments identifying invalid state, source boundary, why source can't be fixed, regression test, and removal condition.
  • Impact: Hard to distinguish deliberate fail-closed guards from bugs. Future changes might weaken guards without understanding their purpose.
  • Recommended action: Identify invalid state handled, source boundary, why source can't be fixed, regression test, and removal condition for each early-return path. Add source-of-truth comment if this is a deliberate workaround. Consider consolidating fail-closed patterns.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read rebuild-preflight-phase.ts and rebuild-preflight-guards.ts; find all bail() calls and early returns. Check for source-of-truth comments.
  • Missing regression test: rebuild-preflight-guards.test.ts (not in diff) should cover each fail-closed path.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read rebuild-preflight-phase.ts and rebuild-preflight-guards.ts; find all bail() calls and early returns. Check for source-of-truth comments.
  • Evidence: PRA-19 from previous review still applies. Multiple bail() calls in preflight-guards.ts without source-of-truth comments.

PRA-21 Resolve/justify — Complex curl pipeline for plugin verification — simplify or extract

  • Location: docs/deployment/install-openclaw-plugins.mdx:186
  • Category: scope
  • Problem: Verification step uses complex heredoc curl pipeline with printf config to invoke tool via gateway. This is a user-facing verification command, not a test, but is brittle and hard to maintain.
  • Impact: Users may fail to verify plugin correctly; command spans multiple lines with escaping complexity.
  • Recommended action: Extract to a helper script (scripts/verify-plugin-invocation.sh) or add openclaw CLI subcommand for tool invocation verification. If kept in doc, simplify to single-line curl with @- config file reference.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read install-openclaw-plugins.mdx lines 186-195; verify curl command complexity.
  • Missing regression test: N/A — documentation UX improvement.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read install-openclaw-plugins.mdx lines 186-195; verify curl command complexity.
  • Evidence: PRA-24 from previous review still applies. Simplification signal detected at line 186.

PRA-22 Resolve/justify — Legacy maxLines budget allows very large legacy test files

  • Location: ci/test-file-size-budget.json:1
  • Category: scope
  • Problem: legacyMaxLines budget permits test files up to 4826 lines (nemoclaw-start.test.ts), 4774 (onboard-selection.test.ts), 4039 (onboard.test.ts), 3934 (install-preflight.test.ts). New defaultMaxLines is 1500 but legacy entries not being reduced.
  • Impact: Large test files discourage splitting; monolith growth continues unchecked for legacy files.
  • Recommended action: Gradually reduce legacyMaxLines entries as files are split. Add CI check that fails if any non-legacy test file exceeds defaultMaxLines. Prioritize splitting the largest legacy files.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read ci/test-file-size-budget.json; compare legacyMaxLines values against defaultMaxLines (1500).
  • Missing regression test: N/A — CI budget configuration.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read ci/test-file-size-budget.json; compare legacyMaxLines values against defaultMaxLines (1500).
  • Evidence: PRA-25 from previous review still applies. Budget shows 10 legacy files over 1500 lines.

💡 In-scope improvements

These are lower-risk, not throwaway. Prefer fixing them in this PR when they are local to changed code; defer only with rationale or a linked follow-up.

PRA-23 Improvement — registry.ts grew by 9 lines (713→722) — review extraction feasibility

  • Location: src/lib/state/registry.ts:1
  • Category: architecture
  • Problem: registry.ts grew from 713 to 722 lines (+9). While not a blocker, it's a large-file hotspot that should be reviewed for extraction opportunities.
  • Impact: Incremental growth on already large file; may indicate missing module boundaries.
  • Suggested action: Review whether new additions belong in registry.ts or should be extracted to focused modules (e.g., sandbox entry projections, messaging persistence).
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check registry.ts line count (722) and recent commit history for what was added.
  • Missing regression test: N/A — architectural hygiene.
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Drift tool flagged +9 lines as warning severity.

PRA-24 Improvement — Test file grew by 1 line — verify test coverage intent

  • Location: src/lib/actions/sandbox/rebuild-dcode-recovery.test.ts:1
  • Category: tests
  • Problem: rebuild-dcode-recovery.test.ts grew by 1 line (400→401). Minor but worth confirming the addition is a meaningful test case.
  • Impact: Low — single line growth. Could be a test name or assertion addition.
  • Suggested action: Verify the new line adds meaningful test coverage; if trivial, consider if test file organization needs review.
  • Expected follow-up: Prefer a current-PR fix when local to changed code; defer only with rationale or linked follow-up.
  • Verification: Check rebuild-dcode-recovery.test.ts diff for what changed.
  • Missing regression test: N/A
  • Done when: The local improvement is applied, or the PR notes why it should be deferred.
  • Evidence: Drift tool flagged +1 line as warning.
Simplification opportunities: 16 possible cuts, net -59 lines possible

These are safe simplification checks only. Do not remove validation, security controls, data-loss prevention, or required tests.

  • PRA-9 shrink (src/lib/state/openclaw-plugin-restore.ts:1): openclaw-plugin-restore.ts (476 lines)
    • Replacement: openclaw-plugin-index-reader.ts + openclaw-plugin-validator.ts + openclaw-plugin-restore-planner.ts
    • Net: 0 lines
    • Safety boundary: Validation functions (isSafeOpenClawPluginInstallId, validateDurableOpenClawImagePluginInstall, hasCompleteOpenClawImagePluginProvenance) must retain identical semantics; no weakening of provenance checks.
  • PRA-10 shrink (src/lib/state/openclaw-config-merge.test.ts:1): openclaw-config-merge.test.ts (650 lines)
    • Replacement: 4 focused test files by config domain
    • Net: 0 lines
    • Safety boundary: All existing test cases must be preserved; no behavior changes.
  • PRA-11 shrink (src/lib/onboard/created-sandbox-finalization.test.ts:1): created-sandbox-finalization.test.ts (630 lines)
    • Replacement: created-openclaw-finalization.test.ts + created-dcode-finalization.test.ts
    • Net: 0 lines
    • Safety boundary: All existing test cases must be preserved; no behavior changes.
  • PRA-12 shrink (src/lib/state/sandbox.ts:234): hasAuthoritativeOpenClawImagePluginProvenance, hasCompleteOpenClawImagePluginProvenance from sandbox.ts (~40 lines)
    • Replacement: Import from openclaw-plugin-restore.ts
    • Net: -40 lines
    • Safety boundary: Function signatures and semantics must remain identical; call sites in rebuild-backup-phase.ts, rebuild-prepared-recovery.ts, etc. must not change behavior.
  • PRA-13 shrink (src/lib/state/openclaw-config-merge.ts:1): openclaw-config-merge.ts merge functions
    • Replacement: Separate modules per config domain or clear /// section boundaries
    • Net: 0 lines
    • Safety boundary: Merge function signatures and behavior must remain identical; no changes to config merge semantics.
  • PRA-14 shrink (src/lib/verify-deployment.test.ts:1): verify-deployment.test.ts (583 lines)
    • Replacement: 5 focused test files by verification layer
    • Net: 0 lines
    • Safety boundary: All existing test cases must be preserved; no behavior changes.
  • PRA-15 shrink (src/lib/verify-deployment.ts:1): formatVerificationDiagnostics function from verify-deployment.ts
    • Replacement: verify-deployment-format.ts module
    • Net: 0 lines
    • Safety boundary: Formatting output must remain identical; no changes to diagnostic content.
  • PRA-16 stdlib (test/e2e/fixtures/plugins/weather/package-lock.json:1): Manual revalidation process documented in review doc
    • Replacement: Automated npm audit CI gate on fixture lockfile changes
    • Net: 0 lines
    • Safety boundary: Must not block legitimate OpenClaw version pins; only fail on NEW advisories beyond documented baseline.
  • PRA-17 yagni (docs/deployment/install-openclaw-plugins.mdx:1): N/A — add comment block
    • Replacement: Source-of-truth JSDoc-style comment block at top of document
    • Net: 10 lines
    • Safety boundary: Documentation only; no code behavior change.
  • PRA-18 yagni (src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45): N/A — add comment
    • Replacement: Function-level JSDoc with 5 source-of-truth tags
    • Net: 8 lines
    • Safety boundary: Documentation only; no code behavior change.
  • PRA-19 yagni (src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65): N/A — add comment
    • Replacement: Function-level JSDoc with 5 source-of-truth tags
    • Net: 8 lines
    • Safety boundary: Documentation only; no code behavior change.
  • PRA-20 yagni (src/lib/actions/sandbox/rebuild-preflight-phase.ts:1): N/A — add comments
    • Replacement: Source-of-truth comments at each fail-closed bail() path
    • Net: 20 lines
    • Safety boundary: Must not weaken any fail-closed guard; comments only.
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 — planOpenClawPluginRestore rejects same-ID different-installPath collision. Runtime/sandbox/infrastructure paths need behavioral runtime validation: workflow changes (e2e.yaml, regression-e2e.yaml), new E2E test (openclaw-plugin-runtime-exdev.test.ts), custom image onboarding paths, rebuild/recovery provenance guards. Static tests cover logic but provenance collision bug (PRA-6/7) requires runtime validation of full rebuild/recovery cycle with custom images.
  • PRA-T2 Runtime validation — revalidatePreparedRecoveryBeforeDelete rejects cross-provenance collision at pre-delete boundary. Runtime/sandbox/infrastructure paths need behavioral runtime validation: workflow changes (e2e.yaml, regression-e2e.yaml), new E2E test (openclaw-plugin-runtime-exdev.test.ts), custom image onboarding paths, rebuild/recovery provenance guards. Static tests cover logic but provenance collision bug (PRA-6/7) requires runtime validation of full rebuild/recovery cycle with custom images.
  • PRA-T3 Runtime validation — hasAuthoritativeOpenClawImagePluginProvenance returns false when reconcile=true but installs invalid. Runtime/sandbox/infrastructure paths need behavioral runtime validation: workflow changes (e2e.yaml, regression-e2e.yaml), new E2E test (openclaw-plugin-runtime-exdev.test.ts), custom image onboarding paths, rebuild/recovery provenance guards. Static tests cover logic but provenance collision bug (PRA-6/7) requires runtime validation of full rebuild/recovery cycle with custom images.
  • PRA-T4 Runtime validation — classifyOpenClawRuntimeFailure rejects partial artifact presence as base_only_image. Runtime/sandbox/infrastructure paths need behavioral runtime validation: workflow changes (e2e.yaml, regression-e2e.yaml), new E2E test (openclaw-plugin-runtime-exdev.test.ts), custom image onboarding paths, rebuild/recovery provenance guards. Static tests cover logic but provenance collision bug (PRA-6/7) requires runtime validation of full rebuild/recovery cycle with custom images.
  • PRA-T5 Runtime validation — Full rebuild/recovery cycle with custom image containing cross-provenance collision (integration test). Runtime/sandbox/infrastructure paths need behavioral runtime validation: workflow changes (e2e.yaml, regression-e2e.yaml), new E2E test (openclaw-plugin-runtime-exdev.test.ts), custom image onboarding paths, rebuild/recovery provenance guards. Static tests cover logic but provenance collision bug (PRA-6/7) requires runtime validation of full rebuild/recovery cycle with custom images.
  • PRA-T6 Missing regression test for cross-provenance plugin ID collision — Add test case: planOpenClawPluginRestore with freshImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v2', loadPaths:[]}] and previousImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v1', loadPaths:[]}] should return ok:false. Add equivalent test in rebuild-prepared-recovery.test.ts for pre-delete boundary.
  • PRA-T7 Test file grew by 1 line — verify test coverage intent — Verify the new line adds meaningful test coverage; if trivial, consider if test file organization needs review.
  • PRA-T8 Acceptance clauseUnable to install custom plugin with NemoClaw (OpenClaw) #6108: Custom plugin provenance guards across onboarding, restart, recreation, rebuild — add test evidence or identify existing coverage. rebuild-backup-phase.ts has provenance guards (bailForUnsafeOpenClawPluginProvenance, authoritative checks); openclaw-plugin-restore.ts has provenance validation; BUT cross-provenance collision not validated (PRA-6, PRA-7)
Since last review details

Current findings, using the urgency labels above:

PRA-1 Resolve/justify — Source-of-truth review needed: docs/deployment/install-openclaw-plugins.mdx

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E (openclaw-plugin-runtime-exdev.test.ts)
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Document has Warning block referencing VoiceClaw integration via existing messaging and provider contracts #5998 but no structured @invalidState/@sourceBoundary/@sourceFixConstraint/@regressionTest/@removalCondition tags. PRA-16.

PRA-2 Resolve/justify — Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Function shouldDiagnoseCustomOpenClawRuntime at line 45 lacks function-level JSDoc with 5 source-of-truth tags. Module-level REMOVE-WHEN exists. PRA-17.

PRA-3 Resolve/justify — Source-of-truth review needed: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as missing.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Function classifyOpenClawRuntimeFailure at line 65 lacks function-level JSDoc with 5 source-of-truth tags. PRA-18.

PRA-4 Resolve/justify — Source-of-truth review needed: src/lib/actions/sandbox/rebuild-preflight-phase.ts / rebuild-preflight-guards.ts

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: rebuild-preflight-guards.test.ts (not in diff) should cover each fail-closed path
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Multiple bail() calls with early returns in preflight-guards.ts (checkRebuildGatewaySchemaPreflight, getRebuildSandboxEntryOrBail, isSingleAgentRebuildSupported, acquireRebuildOnboardLock) lack source-of-truth comments. PRA-19.

PRA-5 Resolve/justify — Source-of-truth review needed: test/e2e/fixtures/plugins/weather/package-lock.json

  • Location: not file-specific
  • Category: architecture
  • Problem: The advisor marked localized patch analysis as needs_followup.
  • Impact: A localized workaround can preserve or hide an invalid state when the source boundary is unclear.
  • Recommended action: Identify the invalid state, source boundary, source-fix constraint, regression test, and removal condition before merging the localized behavior.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Missing regression test: e2e-fixture-dependency-review.test.ts enforces review doc existence and lockfile digest; npm audit documented in review
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Inspect the localized patch and source-of-truth review fields for a concrete invalid state, source boundary, source-fix constraint, regression test, and removal condition.
  • Evidence: Review doc exists with advisory list and SHA-256 digest; compensating controls documented. But no CI gate to revalidate. PRA-20.

PRA-6 Required — Cross-provenance plugin ID collision not validated in planOpenClawPluginRestore

  • Location: src/lib/state/openclaw-plugin-restore.ts:447
  • Category: security
  • Problem: planOpenClawPluginRestore treats same plugin ID in both fresh and previous projections as an upgrade without verifying installPath and loadPaths are identical. A custom image installing a plugin with the same ID as a user-installed plugin (different provenance) causes the previous directory to be excluded from backup while fresh image code wins — sandbox escape via plugin substitution.
  • Impact: Attacker with custom-image build access can install a malicious plugin sharing an ID with a legitimate user plugin; during rebuild/recovery, the user's plugin directory is excluded from backup and the malicious version persists, enabling arbitrary code execution in the sandbox.
  • Required action: After both parseOpenClawImagePluginInstalls calls succeed, collect IDs from freshProjection.pluginInstalls and previousProjection.pluginInstalls. Reject with ok:false if any ID intersection exists where installPath or loadPaths differ (indicating different provenance). Only allow same-ID when installPath and loadPaths are identical (true upgrade).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/state/openclaw-plugin-restore.ts lines 423-480; search for ID intersection check between freshProjection and previousProjection pluginInstalls — currently absent.
  • Missing regression test: Add test case in openclaw-plugin-restore.test.ts: planOpenClawPluginRestore with fresh and previous having same ID but different installPath/loadPaths should return ok:false.
  • Done when: The required change is committed and verification passes: Read src/lib/state/openclaw-plugin-restore.ts lines 423-480; search for ID intersection check between freshProjection and previousProjection pluginInstalls — currently absent.
  • Evidence: Line 447 comment explicitly states 'The same ID in both projections is an image-owned plugin upgrade, not a provenance collision' without validation. PRA-6 from previous review still applies.

PRA-7 Required — Cross-provenance plugin ID collision not validated in revalidatePreparedRecoveryBeforeDelete

  • Location: src/lib/actions/sandbox/rebuild-prepared-recovery.ts:124
  • Category: security
  • Problem: Pre-delete check validates authoritativePluginProvenance but does not compare candidate.openclawImagePluginInstalls against latestManifest.openclawImagePluginInstalls for cross-provenance collisions. Comment at line 124-127 acknowledges 'fresh-vs-previous ownership is validated later by the restore planner after the replacement image has been created' but restore planner (PRA-6) does not do it.
  • Impact: Pre-delete check passes for custom-image recovery with cross-provenance collision; deletion proceeds, then restore planner silently accepts collision. User's legitimate plugin lost, malicious custom-image plugin persists.
  • Required action: After authoritativePluginProvenance validation (line 111), add explicit cross-provenance ID collision check: extract IDs from candidate.openclawImagePluginInstalls and latestManifest.openclawImagePluginInstalls, reject with failPreparedRecoveryPreDelete if any intersection exists where installPath or loadPaths differ.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Read src/lib/actions/sandbox/rebuild-prepared-recovery.ts lines 110-130; verify no collision check between candidate and latestManifest plugin installs.
  • Missing regression test: Add test in rebuild-prepared-recovery.test.ts: revalidatePreparedRecoveryBeforeDelete with candidate and latestManifest having same plugin ID but different installPath should reject with failPreparedRecoveryPreDelete.
  • Done when: The required change is committed and verification passes: Read src/lib/actions/sandbox/rebuild-prepared-recovery.ts lines 110-130; verify no collision check between candidate and latestManifest plugin installs.
  • Evidence: Comment at line 124-127 admits validation deferred to restore planner; PRA-7 from previous review still applies.

PRA-8 Required — Missing regression test for cross-provenance plugin ID collision

  • Location: src/lib/state/openclaw-plugin-restore.test.ts:395
  • Category: tests
  • Problem: Test suite covers upgrade (same ID + same path), invalid provenance (relative path), empty provenance — but no test for same ID with different installPath/loadPaths which should be rejected as collision.
  • Impact: Without this test, the collision vulnerability (PRA-6, PRA-7) cannot be caught by CI. Future refactors could reintroduce the bug undetected.
  • Required action: Add test case: planOpenClawPluginRestore with freshImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v2', loadPaths:[]}] and previousImagePluginInstalls=[{id:'weather', installPath:'/sandbox/.openclaw/extensions/weather-v1', loadPaths:[]}] should return ok:false. Add equivalent test in rebuild-prepared-recovery.test.ts for pre-delete boundary.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search openclaw-plugin-restore.test.ts for 'cross', 'provenance', 'collision', 'same.*id.*different' — no matches found.
  • Missing regression test: This finding IS the missing regression test request. Implement the test described in recommendation.
  • Done when: The required change is committed and verification passes: Search openclaw-plugin-restore.test.ts for 'cross', 'provenance', 'collision', 'same.*id.*different' — no matches found.
  • Evidence: PRA-8 from previous review still applies; test file ends at line 476 with no collision test.

PRA-9 Required — 476-line monolith combines index reading, validation, and restore planning

  • Location: src/lib/state/openclaw-plugin-restore.ts:1
  • Category: architecture
  • Problem: New file openclaw-plugin-restore.ts (476 lines) contains SQLite index reading, legacy JSON fallback, plugin install validation, ID safety checks, path validation, extension directory projection, and restore planning — three distinct responsibilities in one file.
  • Impact: Hard to review, test, and maintain. Security-critical validation logic mixed with I/O and planning. Changes to one domain risk breaking others.
  • Required action: Extract into three modules: openclaw-plugin-index-reader.ts (buildFreshOpenClawPluginIndexSqliteReadCommand, readFreshOpenClawPluginInstallIndex, discoverFreshOpenClawPluginExtensionDirs, discoverFreshOpenClawImagePluginInstalls), openclaw-plugin-validator.ts (parseOpenClawImagePluginInstalls, validateDurableOpenClawImagePluginInstall, isSafeOpenClawPluginInstallId, isSafeOpenClawExtensionDirName, hasCompleteOpenClawImagePluginProvenance), openclaw-plugin-restore-planner.ts (planOpenClawPluginRestore). Split test file correspondingly.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Count lines in openclaw-plugin-restore.ts (476) and identify distinct responsibility boundaries: lines 1-150 (SQLite/legacy reading), 150-350 (validation), 350-476 (planning).
  • Missing regression test: After extraction, each module should have its own focused test file mirroring the current test coverage split by domain.
  • Done when: The required change is committed and verification passes: Count lines in openclaw-plugin-restore.ts (476) and identify distinct responsibility boundaries: lines 1-150 (SQLite/legacy reading), 150-350 (validation), 350-476 (planning).
  • Evidence: Drift tool flagged +476 lines as blocker severity; PRA-9 from previous review still applies.

PRA-10 Required — Test file grew by 262 lines (388→650) — needs split by ownership domain

  • Location: src/lib/state/openclaw-config-merge.test.ts:1
  • Category: architecture
  • Problem: openclaw-config-merge.test.ts grew from 388 to 650 lines (+262), combining channel, plugin, provider, and tool merge tests in one file.
  • Impact: Test maintenance burden; hard to isolate failures; CI runs all tests together slowing feedback.
  • Required action: Split into: openclaw-config-merge-channels.test.ts, openclaw-config-merge-plugins.test.ts, openclaw-config-merge-providers.test.ts, openclaw-config-merge-tools.test.ts. Each with focused test setup.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check openclaw-config-merge.test.ts line count (650) and identify test describe blocks for channels, plugins, providers, tools.
  • Missing regression test: After split, each test file must pass independently with full coverage of its domain.
  • Done when: The required change is committed and verification passes: Check openclaw-config-merge.test.ts line count (650) and identify test describe blocks for channels, plugins, providers, tools.
  • Evidence: Drift tool flagged +262 lines as blocker; PRA-10 from previous review still applies.

PRA-11 Required — Test file grew by 244 lines (386→630) — needs split by agent type

  • Location: src/lib/onboard/created-sandbox-finalization.test.ts:1
  • Category: architecture
  • Problem: created-sandbox-finalization.test.ts grew from 386 to 630 lines (+244), combining OpenClaw and DCode finalization tests.
  • Impact: Agent-specific finalization logic mixed; hard to verify each agent's behavior in isolation.
  • Required action: Split into created-openclaw-finalization.test.ts and created-dcode-finalization.test.ts. Each covers its agent's finalization path independently.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check created-sandbox-finalization.test.ts line count (630) and identify OpenClaw vs DCode test describe blocks.
  • Missing regression test: After split, each test file must pass independently with full coverage of its agent's finalization.
  • Done when: The required change is committed and verification passes: Check created-sandbox-finalization.test.ts line count (630) and identify OpenClaw vs DCode test describe blocks.
  • Evidence: Drift tool flagged +244 lines as blocker; PRA-11 from previous review still applies.

PRA-12 Required — Provenance helpers belong in openclaw-plugin-restore.ts

  • Location: src/lib/state/sandbox.ts:234
  • Category: architecture
  • Problem: hasAuthoritativeOpenClawImagePluginProvenance and hasCompleteOpenClawImagePluginProvenance are defined in sandbox.ts (lines 234-268) but are OpenClaw plugin provenance logic, not general sandbox state. They are imported by rebuild-backup-phase.ts, rebuild-prepared-recovery.ts, sandbox-backup-on-recreate.ts, not-ready-recreate.ts.
  • Impact: Provenance logic scattered across sandbox.ts instead of co-located with plugin restore logic. Violates module cohesion; harder to audit security boundaries.
  • Required action: Move hasAuthoritativeOpenClawImagePluginProvenance and hasCompleteOpenClawImagePluginProvenance to openclaw-plugin-restore.ts, export them, and update imports in call sites. Add tests for hasAuthoritativeOpenClawImagePluginProvenance in openclaw-plugin-restore.test.ts (hasCompleteOpenClawImagePluginProvenance already tested).
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search sandbox.ts for 'hasAuthoritativeOpenClawImagePluginProvenance' and 'hasCompleteOpenClawImagePluginProvenance' — found at lines 234, 246, 267, 1764.
  • Missing regression test: Add test for hasAuthoritativeOpenClawImagePluginProvenance in openclaw-plugin-restore.test.ts covering reconcileOpenClawImagePluginProvenance=true with valid/invalid installs.
  • Done when: The required change is committed and verification passes: Search sandbox.ts for 'hasAuthoritativeOpenClawImagePluginProvenance' and 'hasCompleteOpenClawImagePluginProvenance' — found at lines 234, 246, 267, 1764.
  • Evidence: Drift tool flagged +187 lines in sandbox.ts as blocker; PRA-12 from previous review still applies.

PRA-13 Required — openclaw-config-merge.ts grew by 164 lines — multiple merge functions in one file

  • Location: src/lib/state/openclaw-config-merge.ts:1
  • Category: architecture
  • Problem: openclaw-config-merge.ts grew from 304 to 468 lines (+164), containing merge functions for channels, plugins, providers, tools, and subagents in one file without clear module boundaries.
  • Impact: Hard to review merge logic per domain; changes to one merge function risk affecting others.
  • Required action: Extract each merge function into separate modules or add clear /// section comments with module boundaries. Each merge function should have its own test file mirroring the split in PRA-10.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check openclaw-config-merge.ts line count (468) and identify distinct merge function exports.
  • Missing regression test: After extraction, each merge module must have its own test file with full coverage.
  • Done when: The required change is committed and verification passes: Check openclaw-config-merge.ts line count (468) and identify distinct merge function exports.
  • Evidence: Drift tool flagged +164 lines as blocker; PRA-13 from previous review still applies.

PRA-14 Required — Test file grew by 85 lines (498→583) — needs split by verification layer

  • Location: src/lib/verify-deployment.test.ts:1
  • Category: architecture
  • Problem: verify-deployment.test.ts grew from 498 to 583 lines (+85), combining gateway, dashboard, inference, messaging, and custom runtime verification tests.
  • Impact: Test file becoming monolithic; hard to run focused verification layer tests.
  • Required action: Split into verify-gateway.test.ts, verify-dashboard.test.ts, verify-inference.test.ts, verify-messaging.test.ts, verify-custom-runtime.test.ts.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Check verify-deployment.test.ts line count (583) and identify test describe blocks per verification layer.
  • Missing regression test: After split, each test file must pass independently with full coverage of its verification layer.
  • Done when: The required change is committed and verification passes: Check verify-deployment.test.ts line count (583) and identify test describe blocks per verification layer.
  • Evidence: Drift tool flagged +85 lines as blocker; PRA-14 from previous review still applies.

PRA-15 Required — verify-deployment.ts grew by 27 lines — formatVerificationDiagnostics should be extracted

  • Location: src/lib/verify-deployment.ts:1
  • Category: architecture
  • Problem: verify-deployment.ts grew from 582 to 609 lines (+27). The formatVerificationDiagnostics function (formatting logic) is mixed with core verification logic.
  • Impact: Formatting concerns mixed with verification logic; harder to test formatting in isolation.
  • Required action: Extract formatVerificationDiagnostics to verify-deployment-format.ts. Keep core verification in verify-deployment.ts. Split test file per PRA-14.
  • Expected follow-up: Fix before merge or get explicit maintainer override.
  • Verification: Search verify-deployment.ts for 'formatVerificationDiagnostics' function.
  • Missing regression test: Add test file for verify-deployment-format.ts with formatting edge cases.
  • Done when: The required change is committed and verification passes: Search verify-deployment.ts for 'formatVerificationDiagnostics' function.
  • Evidence: Drift tool flagged +27 lines as blocker; PRA-15 from previous review still applies.

PRA-16 Resolve/justify — Committed fixture lockfile has 9 vulnerable packages without CI revalidation gate

  • Location: test/e2e/fixtures/plugins/weather/package-lock.json:1
  • Category: security
  • Problem: Weather fixture package-lock.json has 9 npm advisories (3 moderate, 6 high: GHSA-22p9-wv53-3rq4, GHSA-2gcr-mfcq-wcc3, etc.). Compensating controls documented (npm ci --ignore-scripts, --no-audit --no-fund, prune dev/peer deps, lockfile integrity) but no automated CI gate to revalidate on lockfile change or advisory update.
  • Impact: If new advisories affect fixture dependencies, the E2E lane could compile/run vulnerable code. Risk is limited to secret-free test lane with read-only contents permission, but should be gated.
  • Recommended action: Add CI step (e.g., in e2e.yaml or new workflow) that runs 'npm audit --package-lock-only --ignore-scripts --json' on fixture lockfiles and fails if new advisories appear beyond documented baseline. Revalidate waiver on every fixture manifest or lockfile change. Document baseline advisory IDs in waiver doc (partially done in e2e-weather-plugin-fixture-dependency-review.md).
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Run 'npm audit --package-lock-only --ignore-scripts --json' from test/e2e/fixtures/plugins/weather — exits 1 with 9 vulnerable packages. Check .github/workflows for any npm audit step on fixtures.
  • Missing regression test: e2e-fixture-dependency-review.test.ts enforces review doc existence but does not run npm audit. Add audit step to CI or enhance test to fail on new advisories.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Run 'npm audit --package-lock-only --ignore-scripts --json' from test/e2e/fixtures/plugins/weather — exits 1 with 9 vulnerable packages. Check .github/workflows for any npm audit step on fixtures.
  • Evidence: e2e-weather-plugin-fixture-dependency-review.md documents 9 advisories and SHA-256 lockfile digest; PRA-20 from previous review still applies.

PRA-17 Resolve/justify — Source-of-truth comment missing for custom-image plugin install workaround

PRA-18 Resolve/justify — shouldDiagnoseCustomOpenClawRuntime missing function-level source-of-truth comment

  • Location: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:45
  • Category: architecture
  • Problem: Function at line 45 handles invalid state (user Dockerfile selects sandbox-base as final runtime) but lacks function-level source-of-truth comment with all 5 tags (@InvalidState, @sourceBoundary, @sourceFixConstraint, @RegressionTest, @removalCondition). Module-level comment exists but not at function.
  • Impact: Cannot trace this specific function to its invalid state, source boundary, fix constraint, test, and removal condition without reading full module.
  • Recommended action: Add JSDoc comment block at line 45 (function start) with: @InvalidState 'user Dockerfile selects sandbox-base as final runtime', @sourceBoundary 'onboard --from Dockerfile source boundary', @sourceFixConstraint 'requires static analysis of arbitrary multi-stage Dockerfiles or build-time image contract', @RegressionTest 'classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E', @removalCondition 'VoiceClaw integration via existing messaging and provider contracts #5998 managed plugin lifecycle or build-time image contract validator'.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read custom-openclaw-runtime-diagnosis.ts line 45; verify no JSDoc comment with all 5 tags.
  • Missing regression test: Classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E (openclaw-plugin-runtime-exdev.test.ts) already exist.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read custom-openclaw-runtime-diagnosis.ts line 45; verify no JSDoc comment with all 5 tags.
  • Evidence: PRA-17 from previous review still applies. Module-level REMOVE-WHEN comment exists but not function-level.

PRA-19 Resolve/justify — classifyOpenClawRuntimeFailure missing function-level source-of-truth comment

  • Location: src/lib/onboard/custom-openclaw-runtime-diagnosis.ts:65
  • Category: architecture
  • Problem: Function at line 65 distinguishes base-only image failure from normal gateway failure but lacks function-level source-of-truth comment with all 5 tags.
  • Impact: Same as PRA-17 — traceability gap for this security-critical classifier.
  • Recommended action: Add module-level or function-level source-of-truth comment with all five tags matching PRA-17.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read custom-openclaw-runtime-diagnosis.ts line 65; verify no JSDoc comment with all 5 tags.
  • Missing regression test: Classifier tests in custom-openclaw-runtime-diagnosis.test.ts and live custom-plugin E2E already exist.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read custom-openclaw-runtime-diagnosis.ts line 65; verify no JSDoc comment with all 5 tags.
  • Evidence: PRA-18 from previous review still applies.

PRA-20 Resolve/justify — Early returns after bail() in preflight phase lack source-of-truth comment

  • Location: src/lib/actions/sandbox/rebuild-preflight-phase.ts:1
  • Category: architecture
  • Problem: rebuild-preflight-phase.ts has multiple early returns after bail() calls (gateway schema mismatch, sandbox not found, multi-agent unsupported, lock contention). These are deliberate fail-closed guards but lack source-of-truth comments identifying invalid state, source boundary, why source can't be fixed, regression test, and removal condition.
  • Impact: Hard to distinguish deliberate fail-closed guards from bugs. Future changes might weaken guards without understanding their purpose.
  • Recommended action: Identify invalid state handled, source boundary, why source can't be fixed, regression test, and removal condition for each early-return path. Add source-of-truth comment if this is a deliberate workaround. Consider consolidating fail-closed patterns.
  • Expected follow-up: Resolve in this PR or explain why the risk is acceptable.
  • Verification: Read rebuild-preflight-phase.ts and rebuild-preflight-guards.ts; find all bail() calls and early returns. Check for source-of-truth comments.
  • Missing regression test: rebuild-preflight-guards.test.ts (not in diff) should cover each fail-closed path.
  • Done when: The risk is fixed or explicitly justified in the PR. Verification: Read rebuild-preflight-phase.ts and rebuild-preflight-guards.ts; find all bail() calls and early returns. Check for source-of-truth comments.
  • Evidence: PRA-19 from previous review still applies. Multiple bail() calls in preflight-guards.ts without source-of-truth comments.

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.

@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/e2e/live/openclaw-plugin-runtime-exdev.test.ts (1)

142-146: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

plugins.load.paths set overwrites rather than extends the array.

openclaw config set plugins.load.paths '["/sandbox/.openclaw/extensions/weather"]' replaces the entire load-paths array. If the managed base image ships any default plugin paths, they'd be dropped in this custom image. Likely fine for this narrow fixture, but worth a quick sanity check that the base image doesn't rely on other default plugins.load.paths entries.

🤖 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/live/openclaw-plugin-runtime-exdev.test.ts` around lines 142 - 146,
The `plugins.load.paths` update in the `openclaw` setup currently replaces the
entire array instead of extending it, which can drop any default plugin paths
from the base image. In the `openclaw config set plugins.load.paths` step,
verify the existing load paths first and append the weather plugin path rather
than overwriting the full list, keeping the fixture compatible with any default
entries used by the image.
🤖 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/e2e/live/openclaw-plugin-runtime-exdev.test.ts`:
- Around line 142-146: The `plugins.load.paths` update in the `openclaw` setup
currently replaces the entire array instead of extending it, which can drop any
default plugin paths from the base image. In the `openclaw config set
plugins.load.paths` step, verify the existing load paths first and append the
weather plugin path rather than overwriting the full list, keeping the fixture
compatible with any default entries used by the image.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c4d0e597-496f-47ca-8d3a-07a8da6e7474

📥 Commits

Reviewing files that changed from the base of the PR and between 6092ad2 and a3e9c6f.

⛔ Files ignored due to path filters (1)
  • test/e2e/fixtures/plugins/weather/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • .github/workflows/regression-e2e.yaml
  • docs/deployment/install-openclaw-plugins.mdx
  • docs/reference/commands-nemohermes.mdx
  • docs/reference/commands.mdx
  • docs/reference/troubleshooting.mdx
  • src/lib/onboard.ts
  • src/lib/verify-deployment.test.ts
  • src/lib/verify-deployment.ts
  • test/e2e/fixtures/plugins/weather/.gitignore
  • test/e2e/fixtures/plugins/weather/openclaw.plugin.json
  • test/e2e/fixtures/plugins/weather/package.json
  • test/e2e/fixtures/plugins/weather/src/index.ts
  • test/e2e/fixtures/plugins/weather/tsconfig.json
  • test/e2e/live/openclaw-plugin-runtime-exdev.test.ts
  • test/regression-e2e-workflow.test.ts

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All requested jobs passed

Run: 28668378954
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: (default — all supported)
Requested jobs: cloud-onboard
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28669765840
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: (default — all supported)
Requested jobs: cloud-onboard
Summary: 0 passed, 0 failed, 1 cancelled, 0 skipped

Job Result
cloud-onboard ⚠️ cancelled

@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

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

Inline comments:
In `@test/regression-e2e-workflow.test.ts`:
- Around line 108-123: The contract test in regression-e2e-workflow.test.ts is
asserting against raw source text from openclaw-plugin-runtime-exdev.test.ts
instead of an observable outcome. Update hardens the generated custom-plugin
image contract to verify behavior through a shared exported constant/module for
the Dockerfile and plugin-install command, or by checking the generated artifact
itself, and avoid reading the sibling test file’s source. Use the existing
identifiers readFileSync, openclaw-plugin-runtime-exdev.test.ts, and the hardens
the generated custom-plugin image contract test to relocate these assertions to
a shared boundary.
🪄 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: fc108fb5-d1d1-45f8-a8ea-fc09393c9dec

📥 Commits

Reviewing files that changed from the base of the PR and between 8be68f5 and f46ff19.

📒 Files selected for processing (3)
  • docs/deployment/install-openclaw-plugins.mdx
  • test/e2e/live/openclaw-plugin-runtime-exdev.test.ts
  • test/regression-e2e-workflow.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • docs/deployment/install-openclaw-plugins.mdx
  • test/e2e/live/openclaw-plugin-runtime-exdev.test.ts

Comment thread test/regression-e2e-workflow.test.ts Outdated
ericksoa added 2 commits July 3, 2026 08:30
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

ericksoa commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Advisor follow-up for the remaining EXDEV /dev/shm warnings:

  • Invalid state: the regression needs a real cross-filesystem source to prove that runtime-dependency replacement does not use the legacy rename path that fails with EXDEV.
  • Source boundary: the workaround is confined to this secret-free, read-only live-test checkout and the sandbox created from it; it does not change the committed production policies.
  • Source-fix constraint: OpenShell does not currently expose a test-local tmpfs mount or dedicated creation-time policy input that can provide /dev/shm without adjusting the checked-out policy sources before onboarding.
  • Regression/cleanup: the test snapshots all three policy files, registers cleanup before mutation, restores them, and asserts byte-for-byte equality before writing final artifacts. The workflow has contents: read and receives no secrets.
  • Removal condition: replace this patch with the test-local mount/policy facility as soon as OpenShell exposes one.

I accept that bounded test-only policy broadening for this PR; the production source files and runtime policy remain unchanged.

@ericksoa

ericksoa commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

Nemotron advisor disposition for the remaining nominal blockers/warnings:

  • PRA-5: the OpenClaw probe, parser/classifier, gating, and hint construction are already extracted into src/lib/onboard/custom-openclaw-runtime-diagnosis.ts, with focused tests beside it. The remaining code in verify-deployment.ts is the orchestration boundary that runs the diagnosis only after the normal gateway retry budget and applies its result to gateway/dashboard diagnostics. Moving that small caller flow into another helper would hide rather than reduce the cross-probe sequencing. codebase-growth-guardrails passes.
  • PRA-6: pure diagnosis cases are already in custom-openclaw-runtime-diagnosis.test.ts. The cases left in verify-deployment.test.ts are deliberately integration-shaped tests of the public verifyDeployment caller contract: retry timing, probe gating, generic fallback hints, and dashboard behavior. Moving them would separate the tests from the boundary they exercise. The repository test-size budget passes.
  • PRA-9: the generated Dockerfile must be at the checkout root because onboard --from uses the Dockerfile's parent as the complete build context and the stock Dockerfile copies repository paths. Moving it to an unrelated temporary directory would make that full-runtime build invalid. The lane is exclusive and registers cleanup immediately after creation.
  • PRA-10: NEMOCLAW_POLICY_MODE=skip skips optional policy-preset selection; it does not disable OpenShell's base filesystem policy. This test prebuilds/prunes plugin dependencies into the image and does not require runtime npm egress. The creation-time /dev/shm access and its accepted test-only source workaround are covered in the maintainer rationale above.
  • PRA-8: the runtime fallback comment already identifies both replacement conditions: managed plugin lifecycle issue VoiceClaw integration via existing messaging and provider contracts #5998 or a build-time image-contract validator. The conservative classifier and live full-runtime path are covered by tests.

No additional refactor is warranted for these items; the focused GPT-5.5 review has zero required fixes, and the exact-head repository guards are green.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All requested jobs passed

Run: 28670144442
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: (default — all supported)
Requested jobs: cloud-onboard
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ⚠️ Run cancelled — no signal

Run: 28672206421
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: cloud-onboard
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 0 passed, 0 failed, 1 cancelled, 0 skipped

Job Result
cloud-onboard ⚠️ cancelled

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28672329509
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: cloud-onboard
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28673496126
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: cloud-onboard
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28674366019
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: cloud-onboard
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Vitest E2E Target Results — ✅ All selected jobs passed

Run: 28676048797
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: cloud-onboard
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs hermes-gpu-startup, openshell-gateway-auth-contract, jetson-nvmap-gpu, and sandbox-rlimits-connect are skipped unless selected)
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success

@ericksoa ericksoa added the v0.0.87 Release target label Jul 3, 2026
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Final exact-head handoff — 013c910a5

@cv, PR #6250 is now conflict-free and technically merge-ready on the current base 376ebe2ed:

  • GitHub reports MERGEABLE; the worktree is clean and main has not advanced past the merged base.
  • Standard CI is green: 34 passed, 2 expected skips, 0 pending/failing.
  • Exact-head live E2E completed successfully with all eight Advisor-required targets passing: openclaw-plugin-runtime-exdev, onboard-resume, onboard-repair, cloud-onboard, state-backup-restore, sandbox-rebuild, rebuild-openclaw, and upgrade-stale-sandbox.
  • DCO, commit lint, growth guardrails, docs, CodeQL/security, macOS, and WSL checks are green. The latest signed merge commit is GitHub Verified.
  • There are zero unresolved inline review threads. CodeRabbit is green; its only latest suggestion was tested against the strict docs validator and dispositioned with evidence in comment 4907853113.
  • The exact-head GPT/Nemotron run completed successfully as a check and raised no genuinely new item. The repeated findings and the remaining fixture-risk decision are dispositioned in comment 4907661651, with the original Unable to install custom plugin with NemoClaw (OpenClaw) #6108 clause map in comment 4899164886.

GitHub's only remaining gate is REVIEW_REQUIRED; you remain the requested independent reviewer. Please review the documented residual fixture risk and advisor dispositions, then approve or request a concrete change. I contributed fixes and will not approve or merge this PR.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28899273118
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: openclaw-plugin-runtime-exdev,onboard-resume,onboard-repair,cloud-onboard,state-backup-restore,sandbox-rebuild,rebuild-openclaw,upgrade-stale-sandbox
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 8 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-plugin-runtime-exdev ✅ success
rebuild-openclaw ✅ success
sandbox-rebuild ✅ success
state-backup-restore ✅ success
upgrade-stale-sandbox ✅ success

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Refreshed exact-head handoff — 4632b94a7

@cv, the hourly base advance and resulting conflicts are resolved. PR #6250 is again conflict-free and technically merge-ready against current main 5552a5ba5:

  • GitHub reports MERGEABLE; the branch and local worktree are clean.
  • Standard CI is green: 34 passed, 2 expected skips, 0 pending/failing.
  • Exact-head live E2E completed successfully with all eight Advisor-required targets passing: openclaw-plugin-runtime-exdev, onboard-resume, onboard-repair, cloud-onboard, state-backup-restore, sandbox-rebuild, rebuild-openclaw, and upgrade-stale-sandbox.
  • The conflict resolution also passed 400 main-delta CLI tests, 126 route-containment/plugin-provenance seam tests, 109 onboarding/recovery integration tests, 42 process tests, 20 package-contract tests, 91 docs-variant tests, strict Fern docs, typecheck, source-shape, and test-size gates.
  • The merge commit is GitHub Verified; DCO and commit lint are green.
  • There are zero unresolved review threads and no new human feedback. The exact-head Advisors only renumbered findings already dispositioned in comment 4907661651; no new actionable code issue was found.

The only remaining GitHub gate is REVIEW_REQUIRED; you remain the requested independent reviewer. Please review the documented #6108 ingestion limitation and fixture residual-risk decision. I contributed fixes and will not approve or merge this PR.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28904067877
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: openclaw-plugin-runtime-exdev,onboard-resume,onboard-repair,cloud-onboard,state-backup-restore,sandbox-rebuild,rebuild-openclaw,upgrade-stale-sandbox
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 8 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-plugin-runtime-exdev ✅ success
rebuild-openclaw ✅ success
sandbox-rebuild ✅ success
state-backup-restore ✅ success
upgrade-stale-sandbox ✅ success

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Exact-head handoff — 1b77afeb5

@cv, PR #6250 is technically ready for independent human review:

  • GitHub reports MERGEABLE; the only remaining merge gate is REVIEW_REQUIRED.
  • Standard CI: 34 passed, 2 expected skips, 0 failures or pending checks.
  • Exact-head live E2E run 28904067877: all 8 required lanes passed, including openclaw-plugin-runtime-exdev; report-to-pr and scorecard also passed.
  • All 3 review threads are resolved; no new actionable CodeRabbit finding is open.
  • Current main c5a504e7f has only test-scheduling changes relative to this head. A synthetic merge succeeds cleanly; the sole shared test file changes independent hunks. The ruleset does not require strict current-base updates, so no CI-resetting merge was added.

The prior Advisor dispositions and the bounded release-fixture dependency risk remain documented in the existing thread. No approval or merge action was taken; independent human approval is still required.

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All selected jobs passed

Run: 28910070104
Workflow ref: fix/discussion-6108-plugin-image
Requested targets: openclaw-plugin-runtime-exdev,rebuild-openclaw,sandbox-rebuild,state-backup-restore,cloud-onboard,onboard-resume,onboard-repair,upgrade-stale-sandbox
Requested jobs: (default — all default-enabled free-standing jobs; explicit-only jobs openshell-gateway-auth-contract, mcp-bridge-dev, hermes-gpu-startup, sandbox-rlimits-connect, and jetson-nvmap-gpu are skipped unless selected)
Summary: 8 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard ✅ success
onboard-repair ✅ success
onboard-resume ✅ success
openclaw-plugin-runtime-exdev ✅ success
rebuild-openclaw ✅ success
sandbox-rebuild ✅ success
state-backup-restore ✅ success
upgrade-stale-sandbox ✅ success

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Refreshed exact-head handoff — 1541e3a65

@cv, PR #6250 is again technically ready for independent human review after integrating current rebuild/onboard changes from main:

  • GitHub marks merge commit 1541e3a65 Verified and reports the PR MERGEABLE; the only remaining gate is REVIEW_REQUIRED.
  • Standard exact-head CI: 34 passed, 2 expected skips, 0 failures or pending checks.
  • Exact-head live E2E run 28910070104: all 8 required lanes passed, including openclaw-plugin-runtime-exdev; report-to-pr and scorecard also passed.
  • All 3 review threads remain resolved. CodeRabbit is green. GPT reports 0 new items. Nemotron's five new items are non-binding style/docs/architecture suggestions; the documented fail-closed boundaries and regression tests already cover the relevant behavior, so no code change is warranted.
  • The documented release-pinned fixture dependency residual risk remains the only explicit human-disposition item.
  • Current main 0662be422 adds one release-notes/docs commit after this head. A synthetic merge succeeds cleanly, its sole shared file changes independent hunks, and the ruleset does not require strict current-base updates; no CI-resetting merge was added.

No approval or merge action was taken. Independent human approval is still required.

@ericksoa ericksoa added v0.0.78 Release target and removed v0.0.77 Release target labels Jul 8, 2026
# Conflicts:
#	ci/test-file-size-budget.json

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

cjagwani commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Maintainer refresh at exact signed head f132725efc8341705a0c4bb16f84701f8f9c295e:

  • Merged current main and resolved the test-size budget from the actual merged line counts.
  • Mapped the trusted Discussion #6108 correction into this branch: the documented recipe starts from the complete release-matched source Dockerfile/context, pins NemoClaw v0.0.71 / OpenClaw 2026.5.27, installs/enables/inspects the plugin as the sandbox user, and the live lane exercises gateway startup, plugin inspection, get_weather registration/invocation, gateway restart, and sandbox rebuild. The broader source-free lifecycle remains scoped to VoiceClaw integration via existing messaging and provider contracts #5998.
  • Investigated the advisor's same-ID provenance concern. candidate and latestManifest in revalidatePreparedRecoveryBeforeDelete are required to be two reads of the same prepared backup identity, so rejecting their matching plugin IDs would reject every plugin-bearing recovery. The fresh-image versus previous-image boundary is enforced later by planOpenClawPluginRestore; a matching ID there is an intentional image-owned plugin upgrade, fresh ownership wins, and the old directory is excluded from the restored archive. Added a focused regression proving that behavior and comments at both boundaries.
  • Revalidated the committed weather-fixture lockfile on 2026-07-08: 9 affected packages (3 moderate, 6 high, 0 critical; 374 dependencies). The review now records the exact package/advisory set. The residual exposure remains confined to the secret-free, read-only, npm ci --ignore-scripts, integrity-locked, dev/peer-pruned E2E lane; the runtime pin cannot be independently upgraded without invalidating this release regression.

Local verification: CLI build and typecheck; 83 focused restore/config/rebuild/dependency-review tests; repository checks; test-size budget; docs variant/route checks; Biome; and git diff --check. All pass. I am holding approval until exact-head CI and advisors complete.

@cjagwani

cjagwani commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Trusted acceptance-source map for exact head f132725efc8341705a0c4bb16f84701f8f9c295e, based on the literal body/comments of Discussion #6108:

  • Reported invalid state: the user says they followed the published install guide on NemoClaw 0.0.71, passed a Dockerfile beginning at sandbox-base, and got gateway: HTTP 0, a refused dashboard forward, and no /tmp/gateway.log.
  • Maintainer-owned root cause: @ericksoa states, “the recipe was the problem,” sandbox-base is an intermediate image, and onboard --from treats the supplied Dockerfile as the complete image. That maps to src/lib/onboard/custom-openclaw-runtime-diagnosis.ts plus its focused classifier tests, which diagnose the missing managed runtime/start contract.
  • Working construction clause: the trusted comment requires the complete release-matched NemoClaw Dockerfile/build context, sandbox-base:v0.0.71, and plugin install/enable/inspect as the sandbox user. That maps to docs/deployment/install-openclaw-plugins.mdx, the exact v0.0.71 checkout/build in test/e2e/live/openclaw-plugin-runtime-exdev.test.ts, and the release-matched OpenClaw 2026.5.27 peer/dev fixture.
  • Named lifecycle proof: the trusted comment explicitly names /tmp/gateway.log, plugin inspection, get_weather registration/invocation, gateway restart, and sandbox rebuild. The live test asserts each item and changes the fixture from v1 to v2 before rebuild so a stale restored plugin cannot satisfy the proof.
  • Removal/scope boundary: the trusted comment leaves the no-source-checkout add/list/status/remove lifecycle to VoiceClaw integration via existing messaging and provider contracts #5998; the docs state the same boundary.

Security disposition: today’s audit records the exact 9-package / 27-advisory release-pinned graph and lock digest. The fixture remains secret-free, read-only, integrity-locked, installed with lifecycle scripts disabled, dev/peer-pruned before runtime staging, and runs only after Docker credentials are removed. Replacing OpenClaw 2026.5.27 independently would stop testing the trusted v0.0.71 reproduction.

The Nemotron same-ID collision proposal is not applicable: a fresh and previous image carrying the same plugin ID at different paths is the intended image-owned upgrade case. Fresh config ownership wins and the previous directory is excluded from backup restore; the new regression proves that. At the pre-delete boundary, candidate and latestManifest are two reads of the same prepared backup identity, not two provenance domains.

All exact-head automated gates are green. Because I contributed the merge/test clarification commit, I am leaving the final approval to the independently requested reviewer.

cjagwani added 2 commits July 8, 2026 19:19
# Conflicts:
#	src/lib/actions/sandbox/rebuild-backup-phase.ts

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

cjagwani commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Current-main refresh pushed at signed head 1b979779453a5af4eac778b89e345c9093103ba6. The sole semantic conflict with newly merged #6211 was complementary: #6250 still revalidates custom OpenClaw plugin provenance before deletion, then records main's intentional --force backup skip. The merged tree passes 126 focused rebuild/provenance tests, generated CLI build, Node 22 CLI typecheck, test-size guard, and diff checks. The one-line size ratchet is also isolated in #6487 for main. Independent re-review remains requested from @cv because I authored the merge resolution.

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

cjagwani commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Growth-guard follow-up at signed head e4c712ec5: replaced the temporary 1,501-line budget entry with a formatter-clean blank-line deletion, keeping the existing 1,500 ceiling. Biome, the size guard, and diff checks pass; the behavioral merge verification remains the 126 focused tests plus Node 22 typecheck reported above.

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

Current head e4c712ec5 remains blocked by the hard contributor-compliance gate: GitHub does not mark six commits Verified (60c031a4, 00d2883f, 7eadce16, 3927277d, 5c2f9f2b, and 9f3df598). Their Signed-off-by trailers satisfy DCO, but they do not satisfy the separate Verified-commit requirement, and maintainer waiver/repair of contributor history is not permitted.

The current ci/test-file-size-budget.json conflict is mechanically resolvable, but merging main would not cure this gate. Please replace the branch history with a fresh compliant branch/PR containing only GitHub-Verified commits, then rerun exact-head CI and review. Do not force-push if the published branch rules prohibit it.

@cjagwani

cjagwani commented Jul 8, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #6490. The reviewed implementation is preserved there on current main as one fresh, signed commit with the original contributors credited. This replacement is necessary because six historical commits in #6250 cannot satisfy the repository's GitHub-Verified requirement and cannot be waived under the current release policy. Full CI and applicable live evidence will rerun on #6490's exact head.

@cjagwani cjagwani closed this Jul 8, 2026
apurvvkumaria added a commit that referenced this pull request Jul 8, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Fresh verified-history replacement for #6250. This PR preserves the
reviewed net diff on current `main` while replacing the non-compliant
historical commit chain with three newly signed, GitHub-Verified
commits.

Aaron Erickson remains the original contributor and author of superseded
PR #6250; cjagwani authored this replacement PR. Apurv Kumaria
contributed the review-driven follow-up fixes. Both Aaron and Apurv are
credited as co-authors on the replacement commit.

## Related

- Supersedes #6250
- [Discussion
#6108](#6108)
- Regression coverage for #3513 and #3127
- The no-source-checkout managed plugin lifecycle remains tracked by
#5998

## Changes

- Diagnose custom OpenClaw images that contain only the intermediate
`sandbox-base` instead of the complete managed runtime.
- Record authoritative image-plugin provenance and reconcile removed,
renamed, and same-ID upgraded plugins during recreation and rebuild.
- Preserve user-owned plugin, channel, and tool state while removing
stale image-owned configuration; fail closed on incomplete provenance.
- Add deterministic release lifecycle coverage for onboarding, restart,
recreation, rebuild, workspace preservation, and EXDEV-safe runtime
dependency replacement.
- Authenticate only for the exact digest-pinned builder pre-pull, then
remove Docker credentials before release-pinned fixture code runs.
- Document the full-image plugin recipe, troubleshooting guidance,
dependency risk controls, and the explicit `REMOVE-WHEN` condition.

## Verification

- 126 focused rebuild, restore, diagnosis, and custom-Dockerfile tests
passed.
- `npm run build:cli` passed.
- Node 22 CLI typecheck passed.
- Test-file size budget passed across 1,372 files.
- Biome passed all 64 changed supported files.
- `git diff --cached --check` passed before commit.
- Replacement history contains three commits, all GitHub Verified with
good ED25519 Git signatures.
- Full standard CI and applicable live E2E are intentionally running
again on this new exact head.

## Provenance

The implementation and tests are the reviewed work from #6250, replayed
onto current `main` because six historical commits in that PR could not
satisfy the repository's GitHub-Verified requirement. This replacement
does not claim those historical objects are verified; it provides a new,
attributable, signed history containing their reviewed net result.

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Added OpenClaw weather plugin E2E fixtures and expanded end-to-end
plugin lifecycle coverage, including a new runtime-deps EXDEV lane.
* **Bug Fixes**
* Strengthened onboarding/recovery to fail closed when OpenClaw
image-plugin provenance is incomplete, and tightened rebuild/restore
gating and hints.
* Improved handling of OpenClaw managed extensions and restore planning
with stricter symlink and identity checks.
* **Documentation**
* Updated installation, lifecycle, quickstart, commands, and
troubleshooting docs with safer recovery and pinned sandbox workflows.
* **Tests/CI**
* Updated E2E/regression workflows and added provenance-related
rebuild/restore test coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Fresh verified-history replacement for NVIDIA#6250. This PR preserves the
reviewed net diff on current `main` while replacing the non-compliant
historical commit chain with three newly signed, GitHub-Verified
commits.

Aaron Erickson remains the original contributor and author of superseded
PR NVIDIA#6250; cjagwani authored this replacement PR. Apurv Kumaria
contributed the review-driven follow-up fixes. Both Aaron and Apurv are
credited as co-authors on the replacement commit.

## Related

- Supersedes NVIDIA#6250
- [Discussion
NVIDIA#6108](NVIDIA#6108)
- Regression coverage for NVIDIA#3513 and NVIDIA#3127
- The no-source-checkout managed plugin lifecycle remains tracked by
NVIDIA#5998

## Changes

- Diagnose custom OpenClaw images that contain only the intermediate
`sandbox-base` instead of the complete managed runtime.
- Record authoritative image-plugin provenance and reconcile removed,
renamed, and same-ID upgraded plugins during recreation and rebuild.
- Preserve user-owned plugin, channel, and tool state while removing
stale image-owned configuration; fail closed on incomplete provenance.
- Add deterministic release lifecycle coverage for onboarding, restart,
recreation, rebuild, workspace preservation, and EXDEV-safe runtime
dependency replacement.
- Authenticate only for the exact digest-pinned builder pre-pull, then
remove Docker credentials before release-pinned fixture code runs.
- Document the full-image plugin recipe, troubleshooting guidance,
dependency risk controls, and the explicit `REMOVE-WHEN` condition.

## Verification

- 126 focused rebuild, restore, diagnosis, and custom-Dockerfile tests
passed.
- `npm run build:cli` passed.
- Node 22 CLI typecheck passed.
- Test-file size budget passed across 1,372 files.
- Biome passed all 64 changed supported files.
- `git diff --cached --check` passed before commit.
- Replacement history contains three commits, all GitHub Verified with
good ED25519 Git signatures.
- Full standard CI and applicable live E2E are intentionally running
again on this new exact head.

## Provenance

The implementation and tests are the reviewed work from NVIDIA#6250, replayed
onto current `main` because six historical commits in that PR could not
satisfy the repository's GitHub-Verified requirement. This replacement
does not claim those historical objects are verified; it provides a new,
attributable, signed history containing their reviewed net result.

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
* Added OpenClaw weather plugin E2E fixtures and expanded end-to-end
plugin lifecycle coverage, including a new runtime-deps EXDEV lane.
* **Bug Fixes**
* Strengthened onboarding/recovery to fail closed when OpenClaw
image-plugin provenance is incomplete, and tightened rebuild/restore
gating and hints.
* Improved handling of OpenClaw managed extensions and restore planning
with stricter symlink and identity checks.
* **Documentation**
* Updated installation, lifecycle, quickstart, commands, and
troubleshooting docs with safer recovery and pinned sandbox workflows.
* **Tests/CI**
* Updated E2E/regression workflows and added provenance-related
rebuild/restore test coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior v0.0.78 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants