Skip to content

Commit 4bae484

Browse files
committed
merge(main): resolve E2E workflow conflicts
2 parents 1691596 + b715fc7 commit 4bae484

30 files changed

Lines changed: 1352 additions & 304 deletions

.github/workflows/e2e.yaml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2497,6 +2497,9 @@ jobs:
24972497
CANDIDATE_SHA: ${{ inputs.checkout_sha || github.sha }}
24982498
E2E_JOB: "1"
24992499
INSTANCE_NAME: nclaw-e2e-${{ github.run_id }}-${{ github.run_attempt }}
2500+
E2E_AGENT_RUNTIME: "openclaw"
2501+
E2E_OBSERVABLE_OUTCOME: "Exact staging image boots and completes the full E2E scenario"
2502+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Brev Launchable Docker host; NVIDIA hosted inference"
25002503
steps:
25012504
- name: Checkout trusted Launchable lane
25022505
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -3020,6 +3023,9 @@ jobs:
30203023
env:
30213024
E2E_JOB: "1"
30223025
E2E_TARGET_ID: "openshell-gateway-auth-contract"
3026+
E2E_AGENT_RUNTIME: "none"
3027+
E2E_OBSERVABLE_OUTCOME: "Gateway mTLS and sandbox JWT authentication boundaries hold"
3028+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu Docker host; no inference endpoint"
30233029
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/openshell-gateway-auth-contract
30243030
NEMOCLAW_RUN_LIVE_E2E: "1"
30253031
NEMOCLAW_NON_INTERACTIVE: "1"
@@ -3098,9 +3104,21 @@ jobs:
30983104
fail-fast: false
30993105
matrix:
31003106
agent: [openclaw, hermes, deepagents]
3107+
include:
3108+
- agent: openclaw
3109+
agent_runtime: openclaw
3110+
coverage_variant: openclaw
3111+
- agent: hermes
3112+
agent_runtime: hermes
3113+
coverage_variant: hermes
3114+
- agent: deepagents
3115+
agent_runtime: langchain-deepagents-code
3116+
coverage_variant: deepagents
31013117
env:
31023118
E2E_JOB: "1"
31033119
E2E_TARGET_ID: "mcp-bridge"
3120+
E2E_OBSERVABLE_OUTCOME: "Stable OpenShell MCP bridge reaches tools and inference"
3121+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu Docker host; local compatible inference and MCP endpoint"
31043122
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/mcp-bridge/${{ matrix.agent }}
31053123
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
31063124
NEMOCLAW_E2E_SHARD: ${{ matrix.agent }}
@@ -3425,6 +3443,9 @@ jobs:
34253443
env:
34263444
E2E_JOB: "1"
34273445
E2E_TARGET_ID: "openshell-credential-generation-window"
3446+
E2E_AGENT_RUNTIME: "openclaw"
3447+
E2E_OBSERVABLE_OUTCOME: "Credential expiry rotation detach and rebuild preserve the intended access window"
3448+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu Docker host; local compatible inference and MCP endpoint"
34283449
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/openshell-credential-generation-window
34293450
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
34303451
NEMOCLAW_OPENSHELL_CHANNEL: stable
@@ -3583,9 +3604,21 @@ jobs:
35833604
fail-fast: false
35843605
matrix:
35853606
agent: [openclaw, hermes, deepagents]
3607+
include:
3608+
- agent: openclaw
3609+
agent_runtime: openclaw
3610+
coverage_variant: openclaw
3611+
- agent: hermes
3612+
agent_runtime: hermes
3613+
coverage_variant: hermes
3614+
- agent: deepagents
3615+
agent_runtime: langchain-deepagents-code
3616+
coverage_variant: deepagents
35863617
env:
35873618
E2E_JOB: "1"
35883619
E2E_TARGET_ID: "mcp-bridge-dev"
3620+
E2E_OBSERVABLE_OUTCOME: "Development OpenShell MCP bridge reaches tools and inference"
3621+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu Docker host; local compatible inference and MCP endpoint"
35893622
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/mcp-bridge-dev/${{ matrix.agent }}
35903623
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
35913624
NEMOCLAW_E2E_SHARD: ${{ matrix.agent }}
@@ -3784,13 +3817,19 @@ jobs:
37843817
- platform: linux/amd64
37853818
runner: ubuntu-24.04
37863819
shard: linux-amd64
3820+
environment_or_inference_endpoint: "AMD64 Ubuntu; exact managed image startup"
3821+
coverage_variant: linux-amd64
37873822
- platform: linux/arm64
37883823
runner: ubuntu-24.04-arm
37893824
shard: linux-arm64
3825+
environment_or_inference_endpoint: "Arm64 Ubuntu; exact managed image startup"
3826+
coverage_variant: linux-arm64
37903827
env:
37913828
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/managed-image-multiarch-startup/${{ matrix.shard }}
37923829
E2E_JOB: "1"
37933830
E2E_TARGET_ID: "managed-image-multiarch-startup"
3831+
E2E_AGENT_RUNTIME: "openclaw + hermes + langchain-deepagents-code"
3832+
E2E_OBSERVABLE_OUTCOME: "Exact managed images start directly on the native architecture"
37943833
RELEASE_E2E_ACTIVATION_PATH: ci/protected-managed-image-multiarch-activation-v1.json
37953834
NEMOCLAW_E2E_EXPECTED_SHA: ${{ inputs.checkout_sha }}
37963835
NEMOCLAW_PROTECTED_MANAGED_IMAGE_HEAD_SHA: ${{ inputs.checkout_sha || github.sha }}
@@ -4214,6 +4253,10 @@ jobs:
42144253
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/llama-cpp-dgx-spark-qualification
42154254
E2E_JOB: "1"
42164255
E2E_TARGET_ID: "llama-cpp-dgx-spark-qualification"
4256+
E2E_AGENT_RUNTIME: "unresolved"
4257+
E2E_OBSERVABLE_OUTCOME: "Exact NemoClaw-built llama.cpp image produces protected DGX Spark evidence"
4258+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "NVIDIA DGX Spark GB10; local llama.cpp inference"
4259+
E2E_UNRESOLVED_REASON: "The protected plan can enable or skip its OpenClaw subqualification"
42174260
NEMOCLAW_E2E_EXPECTED_SHA: ${{ inputs.checkout_sha }}
42184261
NEMOCLAW_E2E_SHARD: linux-arm64-gpu-dgx-spark-gb10
42194262
NEMOCLAW_LLAMA_CPP_QUALIFICATION_BASE_SHA: ${{ inputs.base_sha || github.event.before || github.sha }}
@@ -4405,6 +4448,9 @@ jobs:
44054448
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/managed-image-protected-runtime
44064449
E2E_JOB: "1"
44074450
E2E_TARGET_ID: "managed-image-protected-runtime"
4451+
E2E_AGENT_RUNTIME: "openclaw + hermes + langchain-deepagents-code"
4452+
E2E_OBSERVABLE_OUTCOME: "Protected GPU runtime supports Ollama vLLM NIM rollback and cleanup"
4453+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "NVIDIA GPU runner; local and hosted inference services"
44084454
E2E_WORKLOAD_SOURCE: "managed-image"
44094455
RELEASE_E2E_ACTIVATION_PATH: ci/protected-managed-image-runtime-activation-v1.json
44104456
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
@@ -4683,6 +4729,9 @@ jobs:
46834729
env:
46844730
E2E_JOB: "1"
46854731
E2E_TARGET_ID: "hermes-e2e"
4732+
E2E_AGENT_RUNTIME: "hermes"
4733+
E2E_OBSERVABLE_OUTCOME: "Install onboarding health inference lifecycle dashboard and security succeed"
4734+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu; mock or NVIDIA hosted inference"
46864735
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/hermes-e2e
46874736
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
46884737
NEMOCLAW_RUN_LIVE_E2E: "1"
@@ -4773,13 +4822,21 @@ jobs:
47734822
include:
47744823
- scenario: native
47754824
sandbox_name: e2e-hgpu-native
4825+
observable_outcome: "Native GPU startup reaches the stable Ready route"
4826+
coverage_variant: native
47764827
- scenario: fallback
47774828
sandbox_name: e2e-hgpu-fallback
4829+
observable_outcome: "Fallback GPU startup reaches the stable Ready route"
4830+
coverage_variant: fallback
47784831
- scenario: compatibility-only
47794832
sandbox_name: e2e-hgpu-compat
4833+
observable_outcome: "Compatibility-only GPU startup reaches the stable Ready route"
4834+
coverage_variant: compatibility-only
47804835
env:
47814836
E2E_JOB: "1"
47824837
E2E_TARGET_ID: "hermes-gpu-startup"
4838+
E2E_AGENT_RUNTIME: "hermes"
4839+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "NVIDIA GPU runner; local GPU inference"
47834840
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/hermes-gpu-startup/${{ matrix.scenario }}
47844841
E2E_HERMES_GPU_STARTUP_SCENARIO: ${{ matrix.scenario }}
47854842
NEMOCLAW_E2E_SHARD: ${{ matrix.scenario }}
@@ -5081,6 +5138,9 @@ jobs:
50815138
env:
50825139
E2E_JOB: "1"
50835140
E2E_TARGET_ID: "cloud-onboard"
5141+
E2E_AGENT_RUNTIME: "openclaw"
5142+
E2E_OBSERVABLE_OUTCOME: "Public install onboarding hosted inference and security checks succeed"
5143+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu; NVIDIA hosted inference"
50845144
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/cloud-onboard
50855145
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
50865146
NEMOCLAW_RUN_LIVE_E2E: "1"
@@ -5203,6 +5263,9 @@ jobs:
52035263
env:
52045264
E2E_JOB: "1"
52055265
E2E_TARGET_ID: "messaging-providers"
5266+
E2E_AGENT_RUNTIME: "openclaw"
5267+
E2E_OBSERVABLE_OUTCOME: "Provider configuration redaction and optional real sends succeed"
5268+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu; NVIDIA hosted inference and messaging providers"
52065269
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/messaging-providers
52075270
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
52085271
NEMOCLAW_RUN_LIVE_E2E: "1"
@@ -5268,6 +5331,9 @@ jobs:
52685331
env:
52695332
E2E_JOB: "1"
52705333
E2E_TARGET_ID: "openclaw-plugin-runtime-exdev-release"
5334+
E2E_AGENT_RUNTIME: "openclaw"
5335+
E2E_OBSERVABLE_OUTCOME: "Release baseline plugin runtime survives the EXDEV boundary"
5336+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu; release baseline package; no inference endpoint"
52715337
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/openclaw-plugin-runtime-exdev-release
52725338
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
52735339
NEMOCLAW_RUN_LIVE_E2E: "1"
@@ -5340,6 +5406,9 @@ jobs:
53405406
env:
53415407
E2E_JOB: "1"
53425408
E2E_TARGET_ID: "openclaw-plugin-runtime-exdev"
5409+
E2E_AGENT_RUNTIME: "openclaw"
5410+
E2E_OBSERVABLE_OUTCOME: "Current plugin lifecycle rebuild and dependencies survive the EXDEV boundary"
5411+
E2E_ENVIRONMENT_OR_INFERENCE_ENDPOINT: "Ubuntu; current package; no inference endpoint"
53435412
E2E_ARTIFACT_DIR: ${{ github.workspace }}/e2e-artifacts/live/openclaw-plugin-runtime-exdev
53445413
NEMOCLAW_CLI_BIN: ${{ github.workspace }}/bin/nemoclaw.js
53455414
NEMOCLAW_RUN_LIVE_E2E: "1"

src/lib/inference/onboard-host-docker-internal.test.ts

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -46,42 +46,46 @@ describe("host.docker.internal onboarding inference policy", () => {
4646
expect(result.message).toMatch(/host\.openshell\.internal:11435/);
4747
});
4848

49-
it("recognizes Windows-host Ollama tool calls returned through Docker stdout (#9116)", async () => {
50-
const seenCommands: Array<{ command: string; args: readonly string[] }> = [];
51-
const containerProbeSpawnSyncImpl = (
52-
command: string,
53-
args: readonly string[],
54-
): SpawnSyncReturns<string> => {
55-
seenCommands.push({ command, args });
56-
const body = JSON.stringify({
57-
choices: [
58-
{
59-
message: {
60-
tool_calls: [
61-
{
62-
id: "call_1",
63-
type: "function",
64-
function: { name: "sessions_send", arguments: '{"message":"hello"}' },
65-
},
66-
],
49+
it.each([
50+
["required", true],
51+
["optional", false],
52+
] as const)(
53+
"recognizes Windows-host Ollama tool calls when strict tool calling is %s (#9116)",
54+
async (_label, requireChatCompletionsToolCalling) => {
55+
const seenCommands: Array<{ command: string; args: readonly string[] }> = [];
56+
const containerProbeSpawnSyncImpl = (
57+
command: string,
58+
args: readonly string[],
59+
): SpawnSyncReturns<string> => {
60+
seenCommands.push({ command, args });
61+
const body = JSON.stringify({
62+
choices: [
63+
{
64+
message: {
65+
tool_calls: [
66+
{
67+
id: "call_1",
68+
type: "function",
69+
function: { name: "sessions_send", arguments: '{"message":"hello"}' },
70+
},
71+
],
72+
},
6773
},
68-
},
69-
],
70-
});
71-
const writeOutIndex = args.indexOf("-w");
72-
const writeOut = args[writeOutIndex + 1];
73-
const stdout = `${body}${writeOut.replace("%{http_code}", "200")}`;
74-
return {
75-
pid: 123,
76-
output: [stdout, ""],
77-
stdout,
78-
stderr: "",
79-
status: 0,
80-
signal: null,
74+
],
75+
});
76+
const writeOutIndex = args.indexOf("-w");
77+
const writeOut = args[writeOutIndex + 1];
78+
const stdout = `${body}${writeOut.replace("%{http_code}", "200")}`;
79+
return {
80+
pid: 123,
81+
output: [stdout, ""],
82+
stdout,
83+
stderr: "",
84+
status: 0,
85+
signal: null,
86+
};
8187
};
82-
};
8388

84-
for (const requireChatCompletionsToolCalling of [true, false]) {
8589
const result = await probeOpenAiLikeEndpointOptimized(
8690
"http://host.docker.internal:11434/v1",
8791
"openai/nemotron-mini",
@@ -99,15 +103,15 @@ describe("host.docker.internal onboarding inference policy", () => {
99103
api: "openai-completions",
100104
label: "Chat Completions API",
101105
});
102-
}
103-
expect(seenCommands).toHaveLength(2);
104-
seenCommands.forEach(({ command, args }) => {
105-
expect(command).toBe("docker");
106-
expect(args).toContain("curlimages/curl:8.10.1");
107-
expect(args).toContain("http://host.docker.internal:11434/v1/chat/completions");
108-
expect(args).not.toContain("--volume");
109-
});
110-
});
106+
expect(seenCommands).toHaveLength(1);
107+
seenCommands.forEach(({ command, args }) => {
108+
expect(command).toBe("docker");
109+
expect(args).toContain("curlimages/curl:8.10.1");
110+
expect(args).toContain("http://host.docker.internal:11434/v1/chat/completions");
111+
expect(args).not.toContain("--volume");
112+
});
113+
},
114+
);
111115

112116
it.each([
113117
{

src/lib/onboard/machine/definition.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const expectedStateOrder = [
2828
"failed",
2929
];
3030

31+
const progressStateDefinitions = ONBOARD_MACHINE_STATE_DEFINITIONS.flatMap((definition) =>
32+
"progress" in definition ? [definition] : [],
33+
);
34+
3135
describe("onboard machine definition", () => {
3236
it("is the canonical ordered state catalog", () => {
3337
expect(ONBOARD_MACHINE_STATE_IDS).toEqual(expectedStateOrder);
@@ -76,16 +80,16 @@ describe("onboard machine definition", () => {
7680
expect(ONBOARD_SESSION_STEP_TO_MACHINE_STATE).toEqual(mappingFromDefinitions);
7781
});
7882

79-
it("keeps progress metadata attached only to state-backed steps", () => {
80-
for (const definition of ONBOARD_MACHINE_STATE_DEFINITIONS) {
81-
if (!("progress" in definition)) continue;
83+
it.each(progressStateDefinitions)(
84+
"keeps progress metadata attached to state-backed step $state",
85+
(definition) => {
8286
expect("stepName" in definition).toBe(true);
8387
expect(definition.progress.total).toBe(8);
8488
expect(definition.progress.number).toBeGreaterThanOrEqual(1);
8589
expect(definition.progress.number).toBeLessThanOrEqual(definition.progress.total);
8690
expect(definition.progress.title).not.toHaveLength(0);
87-
}
88-
});
91+
},
92+
);
8993

9094
it("looks up definitions by state", () => {
9195
expect(getOnboardMachineStateDefinition("gateway")).toMatchObject({

src/lib/onboard/machine/progress.test.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ import { getOnboardProgressStep, ONBOARD_PROGRESS_STEPS } from "./progress";
1010

1111
vi.mock("../prompt-helpers", () => ({ step: vi.fn() }));
1212

13+
const progressStateDefinitions = ONBOARD_MACHINE_STATE_DEFINITIONS.flatMap((definition) =>
14+
"progress" in definition ? [definition] : [],
15+
);
16+
1317
describe("onboard progress metadata", () => {
14-
it("derives state-backed progress labels from machine definitions", () => {
15-
for (const definition of ONBOARD_MACHINE_STATE_DEFINITIONS) {
16-
if (!("progress" in definition)) continue;
18+
it.each(progressStateDefinitions)(
19+
"derives the $state progress label from its machine definition",
20+
(definition) => {
1721
expect(ONBOARD_PROGRESS_STEPS[definition.stepName]).toEqual(definition.progress);
18-
}
19-
});
22+
},
23+
);
2024

2125
it("preserves the existing eight-step onboarding labels", () => {
2226
expect(ONBOARD_PROGRESS_STEPS).toEqual({

src/lib/onboard/managed-startup-profile.test.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ import {
2828
} from "./managed-startup/profile";
2929

3030
const CA_SHA256 = "a".repeat(64);
31+
const HERMES_RESERVED_API_PORTS = [
32+
8_642, 8_643, 8_644, 8_645, 8_646, 8_647, 8_648, 8_649, 8_650, 8_651, 8_652, 18_642,
33+
];
3134

3235
const MESSAGING_PLAN = {
3336
schemaVersion: 1,
@@ -1138,20 +1141,18 @@ describe("managed startup profile", () => {
11381141
).toThrow(/reserved API ports 8642-8652 or 18642/);
11391142
});
11401143

1141-
it.each(
1142-
Array.from([HERMES_API_PORT_RANGE_START - 1, HERMES_API_PORT_RANGE_END + 1], (value) => [
1143-
value,
1144-
]),
1145-
)("rejects port %s outside the reserved Hermes API port range", (port) => {
1146-
for (let port = HERMES_API_PORT_RANGE_START; port <= HERMES_API_PORT_RANGE_END; port += 1) {
1144+
it.each(HERMES_RESERVED_API_PORTS)("rejects reserved Hermes API port %s", (port) => {
11471145
expect(() =>
11481146
validateManagedStartupProfile({
11491147
...HERMES_PROFILE,
11501148
dashboard: { ...HERMES_PROFILE.dashboard, publicPort: port },
11511149
}),
11521150
).toThrow(/reserved API ports/);
1153-
}
1151+
});
11541152

1153+
it.each([HERMES_API_PORT_RANGE_START - 1, HERMES_API_PORT_RANGE_END + 1])(
1154+
"accepts dashboard port %s outside the reserved Hermes API port range",
1155+
(port) => {
11551156
expect(() =>
11561157
validateManagedStartupProfile({
11571158
...HERMES_PROFILE,
@@ -1162,7 +1163,8 @@ describe("managed startup profile", () => {
11621163
},
11631164
}),
11641165
).not.toThrow();
1165-
});
1166+
},
1167+
);
11661168

11671169
it.each([
11681170
"-----BEGIN CERTIFICATE-----\nMIIB\n-----END CERTIFICATE-----",

0 commit comments

Comments
 (0)