Skip to content

test(e2e): define protected inference qualification - #8079

Draft
ericksoa wants to merge 14 commits into
feat/host-local-inference-lifecycle-recoveryfrom
feat/host-local-inference-protected-qualification
Draft

test(e2e): define protected inference qualification#8079
ericksoa wants to merge 14 commits into
feat/host-local-inference-lifecycle-recoveryfrom
feat/host-local-inference-protected-qualification

Conversation

@ericksoa

@ericksoa ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a dormant, provider-neutral compiler for native-runtime activation qualification
  • require the complete 24-case matrix: OpenClaw, Hermes, and DCode across amd64/arm64, CPU Ollama, and GPU Ollama/NIM/vLLM
  • require release-installer execution with Docker unavailable plus onboarding, agent-turn, lifecycle, recovery, cleanup, and protected-evidence categories for every case
  • prove an MXC-style provider can satisfy the same contract without Podman-specific central switches
  • defer the reporter, artifact verifier, and verified-evidence brand until the protected-collector slice adds their real workflow consumer

Stack identity

Qualification contract

The compiler fails closed unless the candidate declares all of the following:

  • all three supported agents: OpenClaw, Hermes, and DCode
  • Linux amd64 and arm64
  • rootless CPU Ollama and rootless NVIDIA GPU Ollama, NIM, and vLLM
  • NVIDIA CDI evidence for every GPU case and no GPU evidence for CPU cases
  • the release installer with Docker unavailable and no Docker-socket capability
  • install, onboard, agent turn, stop/start, snapshot/restore, rebuild, restart/reconciliation, and exact cleanup obligations
  • protected-run, exact-source, installer, managed-image, local-inference, lifecycle, recovery, cleanup, and GPU evidence categories

The compiler is keyed by an open provider ID. The MXC-style contract test demonstrates that another provider can plug in without a provider-name switch in central orchestration.

Inert boundary

This PR does not register or activate Podman, add a live target or workflow, change installer selection, or advertise runtime support. It intentionally contains no unconsumed protected-collector API. The follow-on collector slice must introduce authenticated run/job bindings, artifact-byte verification, and final evidence acceptance together with the protected workflow that consumes them.

No requirement was removed from the activation target. The full reporter implementation remains preserved in signed source history and on the durable follow-on backup branch for reconstruction with its consumer.

Source extraction

The qualification-only source material came from slice-pure commits eeee3f92b and d70120a47. No cross-cutting restack merge or activation commit was cherry-picked.

Validation

  • focused E2E support contract: 1 file, 6 tests passed
  • CLI typecheck passed
  • repository structural checks passed
  • Biome and Markdown validation passed
  • pre-push CLI/plugin/config typechecks and version-sync gate passed
  • advisor warning resolved by deferring the unconsumed reporter/artifact/WeakMap boundary to the collector-consumer slice
  • advisor exact-set coverage warning resolved with duplicate and unknown evidence-kind regressions
  • exact commits are signed and GitHub-verified; DCO trailers are present

Related to #7744.

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

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa self-assigned this Aug 2, 2026
@copy-pr-bot

copy-pr-bot Bot commented Aug 2, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a dormant native-runtime activation qualification contract. It compiles a provider-neutral 24-case matrix, validates protected execution evidence, supplies Podman fixtures, adds fail-closed tests, and documents the activation boundary.

Changes

Native runtime qualification

Layer / File(s) Summary
Qualification contract and dormant fixture
test/e2e/registry/activation-qualification.ts, test/e2e/support/native-runtime-qualification-fixtures.ts, test/e2e/docs/*
Defines qualification contracts, generates protected rootless profiles and Podman cases, compiles a dormant definition, and documents the activation requirements.
Qualification matrix compilation
test/e2e/registry/activation-qualification.ts
Validates case metadata, supported coverage, execution constraints, installer settings, Docker absence, inference configuration, obligations, evidence kinds, and complete matrix coverage.
Evidence and lifecycle validation
test/e2e/registry/activation-qualification.ts, test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md
Validates artifacts, URLs, engine authority, inference routes, protected-run provenance, runtime identity, managed images, lifecycle operations, recovery, cleanup, and NVIDIA CDI evidence.
Qualification coverage and fail-closed tests
test/e2e/support/e2e-native-runtime-qualification.test.ts
Tests the 24-case matrix, provider-neutral compilation, protected execution rules, exact evidence coverage, receipt integrity, runtime identity, lifecycle authority, recovery, and cleanup.

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

Suggested labels: feature, area: security

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the protected inference qualification contract added by the pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/host-local-inference-protected-qualification

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

@ericksoa ericksoa added chore Build, CI, dependency, or tooling maintenance area: e2e End-to-end tests, nightly failures, or validation infrastructure area: inference Inference routing, serving, model selection, or outputs area: architecture Architecture, design debt, major refactors, or maintainability platform: container Affects Docker, containerd, Podman, or images platform: ubuntu Affects Ubuntu Linux environments platform: arm64 Affects ARM64 or aarch64 architecture labels Aug 2, 2026
@github-code-quality

github-code-quality Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 326edb5 in the feat/host-local-infe... branch remains at 96%, unchanged from commit f93b27d in the feat/host-local-infe... branch.

Show a code coverage summary of the most impacted files.
File feat/host-local-infe... f93b27d feat/host-local-infe... 326edb5 +/-
nemoclaw/src/se...ntial-filter.ts 100% 0% -100%
nemoclaw/src/sh...er-boundary.cts 95% 0% -95%
nemoclaw/src/se...ot-sanitizer.ts 95% 0% -95%
nemoclaw/src/co...test-fixture.ts 81% 0% -81%
nemoclaw/src/co...ration-state.ts 93% 94% +1%

TypeScript / code-coverage/cli

The overall coverage in commit 326edb5 in the feat/host-local-infe... branch is 80%. The coverage in commit f93b27d in the feat/host-local-infe... branch is 81%.

Show a code coverage summary of the most impacted files.
File feat/host-local-infe... f93b27d feat/host-local-infe... 326edb5 +/-
src/lib/onboard...trap/adapter.ts 0% 63% +63%
src/lib/onboard...strap/docker.ts 0% 64% +64%
src/lib/onboard...ne-lifecycle.ts 0% 83% +83%
src/lib/onboard...cker-journal.ts 0% 83% +83%
src/lib/onboard...al-inference.ts 0% 83% +83%
src/lib/onboard...trap-journal.ts 0% 86% +86%
src/lib/actions...ne-providers.ts 0% 86% +86%
src/lib/onboard...-replacement.ts 0% 87% +87%
src/lib/onboard...-transaction.ts 0% 88% +88%
src/lib/onboard...test-fixture.ts 0% 96% +96%

Updated August 02, 2026 21:12 UTC

@ericksoa

ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
test/e2e/support/e2e-native-runtime-qualification.test.ts (1)

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

Select the case by agent instead of by index.

completeEvidence()[0] depends on the compiled sort order. The first id is podman-dcode-..., so "hermes" is currently a mismatched application. If the sort order or the agent list changes, the value can become the correct application, and the test passes without exercising the check. Find the case by agent, then set an application that belongs to a different agent.

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

In `@test/e2e/support/e2e-native-runtime-qualification.test.ts` around lines 339 -
347, Update the test around completeEvidence to locate the target runtime
evidence by its agent identifier instead of assuming index 0, then set its
application to a value belonging to a different agent. Keep the assertion
against assertNativeRuntimeQualificationEvidence and preserve the invalid
runtime identity expectation.
test/e2e/registry/activation-qualification.ts (1)

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

Consider splitting assertCaseEvidence into focused validators.

The function validates protected-run, installer, runtime identity, engine authority, managed images, route, lifecycle, and CDI evidence in one body. The neighboring helpers assertEngineAuthority, assertInferenceRoute, and assertLifecycleEvidence already show the pattern. Extract assertProtectedRun, assertInstallerReceipt, and assertRuntimeIdentity to keep function complexity low.

As per coding guidelines: "Keep function complexity low and prefix intentionally unused variables with _".

🤖 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/registry/activation-qualification.ts` around lines 565 - 651, Split
assertCaseEvidence into focused helpers for protected-run validation, installer
receipt validation, and runtime identity validation, following the existing
assertEngineAuthority, assertInferenceRoute, and assertLifecycleEvidence
pattern. Move each corresponding validation block into assertProtectedRun,
assertInstallerReceipt, and assertRuntimeIdentity, then invoke them from
assertCaseEvidence while preserving all checks and error behavior; prefix any
intentionally unused parameters or variables with an underscore.

Source: Coding guidelines

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

Inline comments:
In `@test/e2e/registry/activation-qualification.ts`:
- Around line 251-268: Update qualificationCaseId to normalize only
input.acceleration before assembling the identifier, mapping the nvidia-gpu
acceleration token to gpu while leaving provider and other tokens unchanged.
Remove the joined-string replace so provider values such as nvidia-gpu-native
cannot be altered or produce duplicate IDs.

In `@test/e2e/support/e2e-native-runtime-qualification.test.ts`:
- Around line 164-175: Update the obligations assertion in the complete-case
coverage test to include the missing "agent.onboard" obligation and compare the
collection exactly rather than using expect.arrayContaining, ensuring all and
only the nine expected obligations are required.

---

Nitpick comments:
In `@test/e2e/registry/activation-qualification.ts`:
- Around line 565-651: Split assertCaseEvidence into focused helpers for
protected-run validation, installer receipt validation, and runtime identity
validation, following the existing assertEngineAuthority, assertInferenceRoute,
and assertLifecycleEvidence pattern. Move each corresponding validation block
into assertProtectedRun, assertInstallerReceipt, and assertRuntimeIdentity, then
invoke them from assertCaseEvidence while preserving all checks and error
behavior; prefix any intentionally unused parameters or variables with an
underscore.

In `@test/e2e/support/e2e-native-runtime-qualification.test.ts`:
- Around line 339-347: Update the test around completeEvidence to locate the
target runtime evidence by its agent identifier instead of assuming index 0,
then set its application to a value belonging to a different agent. Keep the
assertion against assertNativeRuntimeQualificationEvidence and preserve the
invalid runtime identity expectation.
🪄 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: fcfa10da-ed0a-4314-b8e8-a2408df85136

📥 Commits

Reviewing files that changed from the base of the PR and between 5656397 and 6d4389d.

📒 Files selected for processing (5)
  • test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md
  • test/e2e/docs/README.md
  • test/e2e/registry/activation-qualification.ts
  • test/e2e/support/e2e-native-runtime-qualification.test.ts
  • test/e2e/support/native-runtime-qualification-fixtures.ts

Comment thread test/e2e/registry/activation-qualification.ts
Comment thread test/e2e/support/e2e-native-runtime-qualification.test.ts Outdated
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

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

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized terminology decisions differ; normalized E2E selections match; severity counts match.
3 terminology differences from the second opinion

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

  • release-installer at test/e2e/registry/activation-qualification.ts:86: selected only by the second-opinion lane as established.
  • exact-evidence at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:32: selected only by the second-opinion lane as established.
  • protected-collector at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:61: selected only by the second-opinion lane as justified.

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

4 semantic terminology decisions

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

  • justified — native runtime activation qualification at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:4: Keep this term. The document defines its inert boundary and distinguishes it from activation and support.
  • established — protected E2E at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:26: Keep the established term and use it consistently for the required protected workflow validation.
  • justified — exact evidence at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:32: Keep this modifier because the subsequent list defines the identity-bound evidence requirements.
  • justified — provider-neutral contract at test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md:10: Keep this established modifier because the document states and the compiler implements the no-provider-name-branch distinction.

E2E guidance

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

Recommended E2E: cloud-inference, cloud-onboard, security-posture

Workflow run details

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

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

ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

ericksoa commented Aug 2, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/e2e/support/e2e-native-runtime-qualification.test.ts (1)

403-419: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the frozen snapshot directly to complete the freeze claim.

Line 408 mutates the test-local evidence object. The reporter already holds an independent structuredClone, so this proves snapshot independence. It does not prove freezing. A clone without deepFreeze would produce the same passing result, because nothing writes to the reporter's copy.

Add an assertion that a write to the reporter-held evidence fails. This exercises the second half of the test title.

♻️ Proposed addition
       evidence[0]!.installer.invocation.sha256 = "e".repeat(64);
+      expect(() => {
+        (evidence as NativeRuntimeQualificationEvidence[])[0]!.protectedRun.runId = 1;
+      }).not.toThrow();
       writeEvidenceArtifacts(materialized.artifactRoot, completeEvidence());

Replace the placeholder above with a check against the frozen copy that the reporter exposes. If the reporter does not expose its evidence, add a narrow accessor in test/e2e/registry/activation-qualification.ts, or rename the test to claim independence only.

As per path instructions: "Flag copied production algorithms, broad mocks that bypass the behavior under test, and conditionals that make a test pass without exercising its claim."

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

In `@test/e2e/support/e2e-native-runtime-qualification.test.ts` around lines 403 -
419, The test verifies snapshot independence but not that the reporter’s stored
evidence is frozen. In the test around
createNativeRuntimeQualificationReporterRecord, assert that mutating the
reporter-held evidence throws; if that evidence is not exposed, add a narrow
accessor in the reporter implementation, or rename the test to claim
independence only.

Source: Path instructions

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

Inline comments:
In `@test/e2e/registry/activation-qualification.ts`:
- Around line 594-596: Update protectedRunKey to construct its serialized key
using the explicit eight-field canonical order rather than raw-object
JSON.stringify. In test/e2e/registry/activation-qualification.ts lines 658-668,
normalize entry.protectedRun with exactRecord using the same eight-key list as
line 632 before passing it to protectedRunKey; apply both changes so binding and
evidence lookups use identical normalization.

---

Nitpick comments:
In `@test/e2e/support/e2e-native-runtime-qualification.test.ts`:
- Around line 403-419: The test verifies snapshot independence but not that the
reporter’s stored evidence is frozen. In the test around
createNativeRuntimeQualificationReporterRecord, assert that mutating the
reporter-held evidence throws; if that evidence is not exposed, add a narrow
accessor in the reporter implementation, or rename the test to claim
independence only.
🪄 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: 84e4f9e8-bd31-4257-a6e5-f7d424ceb049

📥 Commits

Reviewing files that changed from the base of the PR and between da403b0 and 350f075.

📒 Files selected for processing (3)
  • test/e2e/docs/NATIVE_RUNTIME_QUALIFICATION.md
  • test/e2e/registry/activation-qualification.ts
  • test/e2e/support/e2e-native-runtime-qualification.test.ts

Comment thread test/e2e/registry/activation-qualification.ts Outdated
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: architecture Architecture, design debt, major refactors, or maintainability area: e2e End-to-end tests, nightly failures, or validation infrastructure area: inference Inference routing, serving, model selection, or outputs chore Build, CI, dependency, or tooling maintenance platform: arm64 Affects ARM64 or aarch64 architecture platform: container Affects Docker, containerd, Podman, or images platform: ubuntu Affects Ubuntu Linux environments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant