From 2aeaec40824df8e433e99651427b7395537d8764 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 21 Jul 2026 03:50:17 +0200 Subject: [PATCH] fix: propagate failed hwpod operation result --- tools/hwlab-cli/hwpod.test.ts | 19 +++++++++++++++++++ tools/src/hwpod-harness-lib.ts | 6 ++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/hwlab-cli/hwpod.test.ts b/tools/hwlab-cli/hwpod.test.ts index 0f56c051..f486f2cf 100644 --- a/tools/hwlab-cli/hwpod.test.ts +++ b/tools/hwlab-cli/hwpod.test.ts @@ -196,6 +196,25 @@ test("HWPOD operation status requires explicit over-api mode", async () => { assert.equal(result.payload.error.code, "hwpod_operation_status_over_api_required"); }); +test("HWPOD operation status fails when the Temporal result failed", async () => { + const operationId = "hwpod_failed_001"; + const fetchImpl = async () => Response.json({ + ok: true, + operationId, + status: "completed", + result: { ok: false, status: "failed", response: { error: { code: "node_unavailable" } } } + }); + + const result = await runHwpodCli([ + "operation", "status", operationId, "--over-api", "--api-base-url", "http://hwpod.test" + ], { fetchImpl: fetchImpl as typeof fetch }); + + assert.equal(result.exitCode, 1); + assert.equal(result.payload.ok, false); + assert.equal(result.payload.status, "failed"); + assert.equal(result.payload.body.result.response.error.code, "node_unavailable"); +}); + test("HWPOD over-api resolves a registry spec from the API envelope", async () => { let submitted: any = null; const fetchImpl = async (input: string | URL | Request, init?: RequestInit) => { diff --git a/tools/src/hwpod-harness-lib.ts b/tools/src/hwpod-harness-lib.ts index 44e4bb81..3ecdc937 100644 --- a/tools/src/hwpod-harness-lib.ts +++ b/tools/src/hwpod-harness-lib.ts @@ -124,7 +124,9 @@ export async function runHwpodCli(argv: string[], options: { env?: EnvLike; fetc if (parsed.overApi !== true) throw cliError("hwpod_operation_status_over_api_required", "HWPOD operation status requires --over-api", { next: "pass --over-api" }); const operationId = requiredText(parsed.operationId ?? parsed._[2], "operationId"); const response = await getHwpodOperationStatus({ parsed, env, fetchImpl: options.fetchImpl, operationId }); - const exitCode = response.body?.ok === false || response.status >= 400 ? 1 : 0; + const terminalStatus = text(response.body?.status).toLowerCase(); + const operationFailed = response.body?.result?.ok === false || ["failed", "blocked", "canceled"].includes(terminalStatus); + const exitCode = response.body?.ok === false || operationFailed || response.status >= 400 ? 1 : 0; const payload = ok("hwpod-cli.operation.status", { mode: "l1-native-api", transport: "over-api", @@ -135,7 +137,7 @@ export async function runHwpodCli(argv: string[], options: { env?: EnvLike; fetc runtimeEndpoint: response.runtimeEndpoint, body: response.body, httpStatus: response.status - }, response.body?.status ?? (exitCode === 0 ? "succeeded" : "failed")); + }, exitCode === 0 ? response.body?.status ?? "succeeded" : response.body?.result?.status ?? "failed"); if (exitCode !== 0) payload.ok = false; return result(exitCode, payload, now); }