Files
pikasTech-HWLAB/scripts/dev-cloud-workbench-smoke.test.mjs
T
2026-05-23 03:57:09 +00:00

268 lines
8.6 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
classifyCodeAgentBrowserJourney,
classifyLiveDeploymentIdentity,
classifyLiveWebAssetIdentity,
sanitizeAgentChatBody
} from "./src/dev-cloud-workbench-smoke-lib.mjs";
import {
classifyCodeAgentChatReadiness
} from "./src/code-agent-response-contract.mjs";
const sourceIdentity = Object.freeze({
status: "observed",
commitId: "ff4b3f928f76a0b46cd7998a2a865f3e1caf02c8",
shortCommitId: "ff4b3f928f76",
reportCommitId: "ff4b3f928f76",
worktreeState: "clean",
dirty: false
});
const expectedRuntimeIdentity = Object.freeze({
status: "observed",
serviceId: "hwlab-cloud-api",
source: "deploy/artifact-catalog.dev.json+deploy/deploy.json",
commitId: "7de6edd",
imageTag: "7de6edd",
image: "127.0.0.1:5000/hwlab/hwlab-cloud-api:7de6edd"
});
test("live workbench identity passes only when runtime commit or image tag matches current source", () => {
assert.equal(
classifyLiveDeploymentIdentity(sourceIdentity, {
status: "observed",
commitId: "7de6edd2c41f",
imageTag: "c7de474"
}, expectedRuntimeIdentity).status,
"pass"
);
assert.equal(
classifyLiveDeploymentIdentity(sourceIdentity, {
status: "observed",
commitId: "unknown",
imageTag: "7de6edd"
}, expectedRuntimeIdentity).status,
"pass"
);
const stale = classifyLiveDeploymentIdentity(sourceIdentity, {
status: "observed",
commitId: "c7de474",
imageTag: "c7de474"
}, expectedRuntimeIdentity);
assert.equal(stale.status, "blocked");
assert.match(stale.summary, /Deployment drift/u);
assert.match(stale.reason, /does not match current source desired runtime identity/u);
});
test("live workbench identity blocks when source identity is dirty or runtime identity is absent", () => {
const dirty = classifyLiveDeploymentIdentity(
{ ...sourceIdentity, worktreeState: "dirty", dirty: true, reportCommitId: "unknown" },
{ status: "observed", commitId: "7de6edd", imageTag: "7de6edd" },
expectedRuntimeIdentity
);
assert.equal(dirty.status, "blocked");
assert.match(dirty.reason, /not cleanly attributable/u);
const missingRuntime = classifyLiveDeploymentIdentity(sourceIdentity, {
status: "not_observed",
commitId: "not_observed",
imageTag: "not_observed"
}, expectedRuntimeIdentity);
assert.equal(missingRuntime.status, "blocked");
assert.match(missingRuntime.reason, /not observed/u);
});
test("live workbench identity uses deploy desired runtime identity instead of git HEAD", () => {
const deployed = classifyLiveDeploymentIdentity(sourceIdentity, {
status: "observed",
commitId: "7de6edd",
imageTag: "7de6edd"
}, expectedRuntimeIdentity);
assert.equal(deployed.status, "pass");
assert.equal(deployed.expectedCommit, "7de6edd");
assert.equal(deployed.expectedReportCommitId, "ff4b3f928f76");
assert.equal(deployed.expectedSource, "deploy/artifact-catalog.dev.json+deploy/deploy.json");
});
test("live web asset identity blocks stale deployed primary assets", () => {
const pass = classifyLiveWebAssetIdentity([
{ path: "index.html", status: "match" },
{ path: "styles.css", status: "match" },
{ path: "app.mjs", status: "match" }
]);
assert.equal(pass.status, "pass");
const stale = classifyLiveWebAssetIdentity([
{ path: "index.html", status: "match" },
{ path: "styles.css", status: "mismatch" },
{ path: "app.mjs", status: "mismatch" }
]);
assert.equal(stale.status, "blocked");
assert.deepEqual(stale.mismatches, ["styles.css", "app.mjs"]);
assert.match(stale.summary, /Deployment drift/u);
});
test("Code Agent browser classifier blocks provider 502 response shapes", () => {
const summary = sanitizeAgentChatBody({
status: "completed",
provider: "openai-responses",
model: "gpt-5.5",
backend: "hwlab-cloud-api/openai-responses",
traceId: "trc_provider_502",
reply: {
content: "must not count"
},
error: {
code: "provider_unavailable",
message: "OpenAI Responses returned HTTP 502: request rejected",
providerStatus: 502,
missingEnv: []
}
}, { httpStatus: 502 });
assert.equal(summary.status, "failed");
assert.equal(summary.hasReply, false);
assert.equal(summary.error.code, "provider_unavailable");
assert.equal(summary.error.providerStatus, 502);
const classification = classifyCodeAgentBrowserJourney({
responseSummary: summary,
httpOk: false,
httpStatus: 502,
ui: {
agentChatStatus: "DEV-LIVE 回复",
completedMessageVisible: true,
failedMessageVisible: false
}
});
assert.equal(classification.status, "blocked");
assert.equal(classification.blocker, "provider-upstream");
});
test("Code Agent browser classifier treats sanitized 服务受阻 UI as blocked provider evidence", () => {
const summary = sanitizeAgentChatBody({
status: "failed",
provider: "openai-responses",
model: "gpt-5.5",
backend: "hwlab-cloud-api/openai-responses",
traceId: "trc_provider_502",
error: {
code: "provider_unavailable",
message: "OpenAI Responses returned HTTP 502: request rejected",
providerStatus: 502,
missingEnv: []
}
}, { httpStatus: 200 });
const classification = classifyCodeAgentBrowserJourney({
responseSummary: summary,
httpOk: true,
httpStatus: 200,
ui: {
agentChatStatus: "服务受阻",
completedMessageVisible: false,
failedMessageVisible: true
}
});
assert.equal(classification.status, "blocked");
assert.equal(classification.blocker, "provider-upstream");
});
test("Code Agent readiness classifier blocks completed payloads over any non-2xx HTTP status", () => {
const completedPayload = {
conversationId: "cnv_completed_non_2xx",
sessionId: "cnv_completed_non_2xx",
messageId: "msg_completed_non_2xx",
status: "completed",
provider: "openai-responses",
model: "gpt-5.5",
backend: "hwlab-cloud-api/openai-responses",
traceId: "trc_completed_non_2xx",
reply: {
content: "must only count over HTTP 2xx"
}
};
const accepted = classifyCodeAgentChatReadiness(completedPayload, { realDevLive: true, httpStatus: 200 });
assert.equal(accepted.status, "pass");
assert.equal(accepted.devLiveReplyPass, true);
for (const httpStatus of [400, 401, 403, 429, 500, 502, 503, 504]) {
const blocked = classifyCodeAgentChatReadiness(completedPayload, { realDevLive: true, httpStatus });
assert.equal(blocked.status, "blocked", `HTTP ${httpStatus} must block`);
assert.equal(blocked.blocker, "provider-upstream", `HTTP ${httpStatus} blocker`);
assert.equal(blocked.devLiveReplyPass, false, `HTTP ${httpStatus} must not pass DEV-LIVE`);
assert.equal(blocked.providerStatus, httpStatus, `HTTP ${httpStatus} providerStatus`);
assert.match(blocked.reason, /HTTP non-2xx|upstream response/u, `HTTP ${httpStatus} reason`);
}
});
test("Code Agent browser classifier accepts only completed HTTP success plus completed UI and real provider evidence", () => {
const summary = sanitizeAgentChatBody({
status: "completed",
provider: "openai-responses",
model: "gpt-5.5",
backend: "hwlab-cloud-api/openai-responses",
traceId: "trc_completed",
reply: {
content: "ok"
}
}, { httpStatus: 200 });
const pass = classifyCodeAgentBrowserJourney({
responseSummary: summary,
httpOk: true,
httpStatus: 200,
ui: {
agentChatStatus: "DEV-LIVE 回复",
completedMessageVisible: true,
failedMessageVisible: false
}
});
assert.equal(pass.status, "pass");
const blocked = classifyCodeAgentBrowserJourney({
responseSummary: summary,
httpOk: false,
httpStatus: 500,
ui: {
agentChatStatus: "DEV-LIVE 回复",
completedMessageVisible: true,
failedMessageVisible: false
}
});
assert.equal(blocked.status, "blocked");
assert.equal(blocked.blocker, "provider-upstream");
});
test("Code Agent browser classifier blocks completed payloads without backend evidence", () => {
const summary = sanitizeAgentChatBody({
status: "completed",
provider: "openai-responses",
model: "gpt-5.5",
traceId: "trc_missing_backend",
reply: {
content: "must not count"
}
}, { httpStatus: 200 });
const classification = classifyCodeAgentBrowserJourney({
responseSummary: summary,
httpOk: true,
httpStatus: 200,
ui: {
agentChatStatus: "DEV-LIVE 回复",
completedMessageVisible: true,
failedMessageVisible: false
}
});
assert.equal(classification.status, "blocked");
assert.equal(classification.blocker, "untrusted-completion");
});