Files
lserp_cs_6.0/插件库/Lskj.AgentPet/tests/pet-runtime.test.js
2026-08-14 14:28:28 +08:00

792 lines
30 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const pet = require("../pet-runtime.js");
const bridge = require("../bridge-client.js");
const wireContract = require("../../Contracts/erp-agent-wire-contract-v1.json");
test("Codex v1 atlas geometry and all nine rows are exact", () => {
assert.deepEqual(pet.ATLAS, {
columns: 8,
rows: 9,
frameWidth: 192,
frameHeight: 208,
width: 1536,
height: 1872
});
assert.equal(pet.ANIMATIONS.idle.row, 0);
assert.equal(pet.ANIMATIONS["running-right"].frames, 8);
assert.equal(pet.ANIMATIONS["running-left"].row, 2);
assert.deepEqual(pet.ANIMATIONS.waiting.durations, [150, 150, 150, 150, 150, 260]);
assert.equal(pet.ANIMATIONS.review.row, 8);
});
test("semantic ERP states map to visible pet states", () => {
assert.equal(pet.animationForSemanticState("thinking"), "review");
assert.equal(pet.animationForSemanticState("awaiting_confirmation"), "waiting");
assert.equal(pet.animationForSemanticState("executing"), "running");
assert.equal(pet.animationForSemanticState("success"), "jumping");
assert.equal(pet.animationForSemanticState("error"), "failed");
assert.throws(() => pet.animationForSemanticState("write_without_confirmation"), /Unknown pet state/);
});
test("frame CSS selects the correct atlas cell", () => {
const first = pet.frameStyle("idle", 0, "asset.webp");
const last = pet.frameStyle("review", 5, "asset.webp");
assert.equal(first.backgroundSize, "800% 900%");
assert.equal(first.backgroundPosition, "0% 0%");
assert.equal(last.backgroundPosition, (5 / 7) * 100 + "% 100%");
assert.throws(() => pet.frameStyle("waving", 4, "asset.webp"), RangeError);
});
test("animator follows per-frame duration and cancels stale schedules", () => {
const scheduled = [];
const element = { style: {}, dataset: {} };
const animator = new pet.AtlasAnimator(element, {
setTimer(callback, delay) {
scheduled.push({ callback, delay });
return scheduled.length;
},
clearTimer() {}
});
animator.play("waving");
assert.equal(scheduled[0].delay, 140);
scheduled[0].callback();
assert.equal(element.dataset.frame, "1");
animator.play("waiting");
assert.equal(element.dataset.animation, "waiting");
scheduled[1].callback();
assert.equal(element.dataset.animation, "waiting");
});
test("bridge client keeps one idempotency key for retries of the same plan", async () => {
const requests = [];
const transport = {
async send(request) {
requests.push(request);
return validResponse(request, executionData());
}
};
const client = new bridge.BridgeClient(transport, { clientSessionId: "session-test" });
const planId = "0123456789abcdef0123456789abcdef";
const correlationId = "plan-correlation-01234567";
await client.execute(planId, correlationId);
await client.execute(planId, correlationId);
assert.equal(requests.length, 2);
assert.equal(requests[0].payload.idempotencyKey, requests[1].payload.idempotencyKey);
assert.equal(requests[0].clientSessionId, "session-test");
assert.equal(requests[0].correlationId, correlationId);
assert.equal(requests[1].correlationId, correlationId);
});
test("bridge client gives a followup plan an independent idempotency key", async () => {
const requests = [];
const transport = {
async send(request) {
requests.push(request);
return validResponse(request, executionData());
}
};
const client = new bridge.BridgeClient(transport, { clientSessionId: "session-followup" });
await client.execute(
"0123456789abcdef0123456789abcdef",
"plan-correlation-01234567");
await client.execute(
"fedcba9876543210fedcba9876543210",
"plan-correlation-01234567");
assert.notEqual(requests[0].payload.idempotencyKey, requests[1].payload.idempotencyKey);
});
test("bridge client binds followup plans to the trusted ERP correlation", async () => {
const correlationId = "plan-correlation-76543210";
const followupPlan = {
planId: "fedcba9876543210fedcba9876543210",
commandName: "hr.leave.submit"
};
const client = new bridge.BridgeClient({
async send(request) {
return validResponse(request, executionData({
followupPlan: { ...followupPlan, bridgeCorrelationId: "forged-correlation" }
}));
}
}, { clientSessionId: "session-correlated-followup" });
const data = await client.execute(
"0123456789abcdef0123456789abcdef",
correlationId);
assert.equal(data.bridgeCorrelationId, correlationId);
assert.equal(data.followupPlan.bridgeCorrelationId, correlationId);
assert.equal(data.followupPlan.planId, followupPlan.planId);
});
test("bridge client binds response protocol request and correlation", async () => {
const mismatches = [
request => ({ ...validResponse(request, {}), protocolVersion: "2.0" }),
request => ({ ...validResponse(request, {}), requestId: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" }),
request => ({ ...validResponse(request, {}), correlationId: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" }),
request => ({ ...validResponse(request, {}), unexpected: true }),
request => ({ ...validResponse(request, {}), success: 1 })
];
for (const makeResponse of mismatches) {
const client = new bridge.BridgeClient({
async send(request) { return makeResponse(request); }
}, { clientSessionId: "session-protocol" });
await assert.rejects(
client.health(),
error => error && error.code === "bridge_protocol_error"
);
}
});
test("bridge client preserves a valid business error only after binding", async () => {
const recovery = {
action: "inspect_existing_record",
retryable: false,
planInvalidated: true,
message: "先查询现有发票,再重新生成预览。"
};
const client = new bridge.BridgeClient({
async send(request) {
return {
...validResponse(request, { recovery }),
success: false,
code: "duplicate_invoice",
message: "该供应商的发票号码已经存在。"
};
}
}, { clientSessionId: "session-business-error" });
let boundError;
await assert.rejects(
client.health(),
error => {
boundError = error;
return error
&& error.code === "duplicate_invoice"
&& error.message === "该供应商的发票号码已经存在。"
&& error.response.data.recovery.action === "inspect_existing_record";
}
);
const summary = pet.bridgeFailureSummary(boundError);
assert.equal(summary.planInvalidated, true);
assert.equal(summary.retryable, false);
assert.match(summary.text, /下一步:先查询现有发票.*错误码:duplicate_invoice/);
assert.match(summary.text, /关联 ID/);
const timeout = pet.bridgeFailureSummary({
code: "bridge_timeout",
message: "untrusted SQL SELECT password"
});
assert.equal(timeout.retryable, true);
assert.equal(timeout.planInvalidated, false);
assert.doesNotMatch(timeout.text, /password|SELECT/);
const malformedRecoveries = [
{},
{ recovery: { ...recovery, action: "run_sql" } },
{ recovery: { ...recovery, retryable: "false" } },
{ recovery: { ...recovery, sql: "select secret" } },
{ recovery: { ...recovery, message: "下一步\n执行" } }
];
for (const data of malformedRecoveries) {
const malformedClient = new bridge.BridgeClient({
async send(request) {
return {
...validResponse(request, data),
success: false,
code: "duplicate_invoice",
message: "该供应商的发票号码已经存在。"
};
}
}, { clientSessionId: "session-malformed-recovery" });
await assert.rejects(
malformedClient.health(),
error => error && error.code === "bridge_protocol_error"
);
}
});
test("diagnostic execution receipt is strict and gives a safe next-turn summary", async () => {
const correlationId = "diagnostic-correlation-01234567";
const client = new bridge.BridgeClient({
async send(request) {
return validResponse(
request,
diagnosticExecutionData(request.correlationId));
}
}, { clientSessionId: "session-diagnostic-result" });
const data = await client.execute(
"0123456789abcdef0123456789abcdef",
correlationId);
const summary = pet.diagnosticExecutionSummary(data.result);
assert.match(summary, /数据库字段不存在.*下一轮对话.*具体哪里配置错了/);
assert.doesNotMatch(summary, /password|SELECT|physical_table/i);
const malformedClient = new bridge.BridgeClient({
async send(request) {
const responseData = diagnosticExecutionData(request.correlationId);
responseData.result.data.sql = "SELECT password FROM physical_table";
return validResponse(request, responseData);
}
}, { clientSessionId: "session-diagnostic-injection" });
await assert.rejects(
malformedClient.execute(
"fedcba9876543210fedcba9876543210",
correlationId),
error => error && error.code === "bridge_protocol_error"
);
});
test("bridge client rejects invalid request shapes before transport", async () => {
let calls = 0;
const client = new bridge.BridgeClient({
async send(request) {
calls += 1;
return validResponse(request, {});
}
}, { clientSessionId: "session-request-shape" });
await assert.rejects(client.plan("module.diagnose", []), /计划请求格式无效/);
await assert.rejects(
client.execute("not-a-server-plan", "plan-correlation-01234567"),
/执行请求格式无效/);
await assert.rejects(
client.execute("0123456789abcdef0123456789abcdef"),
/执行请求格式无效/);
assert.equal(calls, 0);
});
test("atlas validation rejects dimensions that could crop guga", () => {
assert.equal(pet.validateAtlas(1536, 1872), true);
assert.equal(pet.validateAtlas(1536, 1792), false);
});
test("anchor click focuses a hover-opened panel before allowing toggle close", () => {
assert.equal(pet.panelOpenAfterAnchorClick(false, false), true);
assert.equal(pet.panelOpenAfterAnchorClick(true, true), true);
assert.equal(pet.panelOpenAfterAnchorClick(true, false), false);
assert.throws(
() => pet.panelOpenAfterAnchorClick("open", false),
TypeError);
});
test("pet quick actions are fixed context-aware prompts", () => {
assert.match(
pet.quickActionPrompt("purchase_invoice_entry"),
/先读取当前 ERP 上下文和能力.*不要生成写入计划/
);
assert.match(
pet.quickActionPrompt("leave_request"),
/原始日期表达与时段.*不得替我补全或猜测/
);
assert.equal(
pet.quickActionPrompt("current_module_help"),
"当前 ERP 界面有哪些功能?请先读取实时上下文,并只根据当前模块的用户级功能说明回答。"
);
assert.match(
pet.quickActionPrompt("current_module_diagnosis"),
/只读配置诊断.*不要复现初始化.*不要生成修复 SQL/
);
assert.match(
pet.quickActionPrompt("workflow_readiness"),
/ERP 内置管理员.*adapters\.status.*不要泄露配置证据、SQL 或物理字段/
);
assert.throws(
() => pet.quickActionPrompt("execute_current_module"),
/Unknown pet quick action/
);
});
test("admin workflow readiness quick action requires trusted administrator scope", () => {
const context = {
userId: "1",
userName: "管理员",
accountBook: "测试账套",
subSystemId: "SCM",
subSystemName: "供应链",
databaseScopeFingerprint: "b".repeat(64),
isAdministrator: true
};
assert.equal(pet.quickActionVisible("workflow_readiness", context), true);
assert.equal(pet.quickActionVisible("purchase_invoice_entry", null), true);
const ordinaryUser = structuredClone(context);
ordinaryUser.userId = "2";
ordinaryUser.userName = "普通用户";
ordinaryUser.isAdministrator = false;
assert.equal(pet.quickActionVisible("workflow_readiness", ordinaryUser), false);
const malformedAdministrator = structuredClone(context);
malformedAdministrator.databaseScopeFingerprint = "B".repeat(64);
assert.equal(
pet.quickActionVisible("workflow_readiness", malformedAdministrator),
false
);
assert.throws(
() => pet.quickActionVisible("unknown_action", context),
/Unknown pet quick action/
);
});
test("ERP session scope summary is complete bounded and database-evidence only", () => {
const context = {
userId: "USER-001",
userName: "测试用户",
accountBook: "生产账套甲",
subSystemId: "SCM-01",
subSystemName: "采购管理",
databaseScopeFingerprint: "a".repeat(64),
isAdministrator: false
};
const summary = pet.erpSessionScopeSummary(context);
assert.equal(summary.complete, true);
assert.equal(summary.userId, "USER-001");
assert.equal(summary.accountBook, "生产账套甲");
assert.equal(summary.subSystemId, "SCM-01");
assert.equal(summary.databaseEvidence, "a".repeat(12));
assert.equal("databaseScopeFingerprint" in summary, false);
const missingAccount = structuredClone(context);
delete missingAccount.accountBook;
assert.equal(pet.erpSessionScopeSummary(missingAccount).complete, false);
const uppercaseFingerprint = structuredClone(context);
uppercaseFingerprint.databaseScopeFingerprint = "A".repeat(64);
assert.equal(
pet.erpSessionScopeSummary(uppercaseFingerprint).complete,
false);
const controlText = structuredClone(context);
controlText.userName = "测试\u0085用户";
assert.equal(pet.erpSessionScopeSummary(controlText).complete, false);
const forgedAdministrator = structuredClone(context);
forgedAdministrator.isAdministrator = "false";
assert.equal(
pet.erpSessionScopeSummary(forgedAdministrator).complete,
false);
assert.equal(pet.erpSessionScopeSummary(null).complete, false);
});
test("purchase execution requires complete trusted header and line previews", () => {
const plan = structuredClone(wireContract.scenarios.find(
scenario => scenario.name === "purchase_resolve_to_create").plan);
const preview = pet.purchaseLinePreview(plan);
assert.equal(preview.required, true);
assert.equal(preview.complete, true);
assert.equal(preview.header.invoiceNumber, "INV-CONTRACT-1");
assert.equal(preview.header.sourceDocumentCount, 1);
assert.equal(preview.lines[0].sourceOrderNumber, "PO-1");
assert.equal(pet.isExecutablePlan(plan), true);
const missingSupplier = structuredClone(plan);
delete missingSupplier.preview["供应商"];
delete missingSupplier.data.preview["供应商"];
assert.equal(pet.purchaseLinePreview(missingSupplier).complete, false);
assert.equal(pet.isExecutablePlan(missingSupplier), false);
const forgedHeaderTotal = structuredClone(plan);
forgedHeaderTotal.preview["价税合计"] = 999;
forgedHeaderTotal.data.preview["价税合计"] = 999;
assert.equal(pet.purchaseLinePreview(forgedHeaderTotal).complete, false);
assert.equal(pet.isExecutablePlan(forgedHeaderTotal), false);
const forgedLineCount = structuredClone(plan);
forgedLineCount.preview["发票行数"] = 2;
forgedLineCount.data.preview["发票行数"] = 2;
assert.equal(pet.purchaseLinePreview(forgedLineCount).complete, false);
assert.equal(pet.isExecutablePlan(forgedLineCount), false);
const missingQuantity = structuredClone(plan);
delete missingQuantity.data.lineMatches[0].invoiceQuantity;
assert.equal(pet.purchaseLinePreview(missingQuantity).complete, false);
assert.equal(pet.isExecutablePlan(missingQuantity), false);
const ambiguous = structuredClone(plan);
ambiguous.data.lineMatches[0].candidateCount = 2;
assert.equal(pet.purchaseLinePreview(ambiguous).complete, false);
assert.equal(pet.isExecutablePlan(ambiguous), false);
assert.equal(pet.previewReviewComplete(0, 340, 800), false);
assert.equal(pet.previewReviewComplete(458, 340, 800), true);
assert.equal(pet.previewReviewComplete(460, 340, 800), true);
assert.equal(pet.previewReviewComplete(Number.NaN, 340, 800), false);
});
test("leave create and submit require complete trusted confirmation previews", () => {
const createPlan = wireContract.scenarios.find(
scenario => scenario.name === "leave_resolve_to_create").plan;
const createPreview = pet.leaveConfirmationPreview(createPlan);
assert.equal(createPreview.required, true);
assert.equal(createPreview.complete, true);
assert.equal(createPreview.employeeId, "EMP-1");
assert.equal(createPreview.calculatedHours, 4);
assert.equal(pet.isExecutablePlan(createPlan), true);
const unicodeErpCode = structuredClone(createPlan);
unicodeErpCode.preview["员工"] = "员工一号";
unicodeErpCode.data.preview["员工"] = "员工一号";
assert.equal(pet.leaveConfirmationPreview(unicodeErpCode).complete, true);
const missingReason = structuredClone(createPlan);
delete missingReason.preview["原因"];
delete missingReason.data.preview["原因"];
assert.equal(pet.leaveConfirmationPreview(missingReason).complete, false);
assert.equal(pet.isExecutablePlan(missingReason), false);
const forgedSubmitIntent = structuredClone(createPlan);
forgedSubmitIntent.preview["创建后提交"] = true;
forgedSubmitIntent.data.preview["创建后提交"] = true;
assert.equal(pet.leaveConfirmationPreview(forgedSubmitIntent).complete, false);
assert.equal(pet.isExecutablePlan(forgedSubmitIntent), false);
const zonedTime = structuredClone(createPlan);
zonedTime.preview["开始时间"] = "2026-08-12T13:00:00+08:00";
zonedTime.data.preview["开始时间"] = "2026-08-12T13:00:00+08:00";
assert.equal(pet.leaveConfirmationPreview(zonedTime).complete, false);
const submitPlan = wireContract.scenarios.find(
scenario => scenario.name === "leave_submit_followup").plan;
assert.equal(pet.leaveConfirmationPreview(submitPlan).complete, true);
assert.equal(pet.isExecutablePlan(submitPlan), true);
const forgedAction = structuredClone(submitPlan);
forgedAction.preview["动作"] = "删除申请";
forgedAction.data.preview["动作"] = "删除申请";
assert.equal(pet.leaveConfirmationPreview(forgedAction).complete, false);
assert.equal(pet.isExecutablePlan(forgedAction), false);
});
test("initialization trace requires complete scope limits and risk disclosure", () => {
const plan = wireContract.scenarios.find(
scenario => scenario.name === "module_trace_initialization").plan;
const preview = pet.initializationTracePreview(plan);
assert.equal(preview.required, true);
assert.equal(preview.complete, true);
assert.equal(preview.moduleName, "采购订单");
assert.equal(preview.forceTerminationSupported, false);
assert.equal(pet.isExecutablePlan(plan), true);
const missingModuleName = structuredClone(plan);
delete missingModuleName.preview.moduleName;
delete missingModuleName.data.preview.moduleName;
assert.equal(pet.initializationTracePreview(missingModuleName).complete, false);
assert.equal(pet.isExecutablePlan(missingModuleName), false);
const forcedTermination = structuredClone(plan);
forcedTermination.preview.forceTerminationSupported = true;
forcedTermination.data.preview.forceTerminationSupported = true;
assert.equal(pet.initializationTracePreview(forcedTermination).complete, false);
assert.equal(pet.isExecutablePlan(forcedTermination), false);
const changedLimit = structuredClone(plan);
changedLimit.preview.maxEvents = 201;
changedLimit.data.preview.maxEvents = 201;
changedLimit.data.maxEvents = 201;
assert.equal(pet.initializationTracePreview(changedLimit).complete, false);
const missingWarning = structuredClone(plan);
missingWarning.warnings = [];
assert.equal(pet.initializationTracePreview(missingWarning).complete, false);
assert.equal(pet.isExecutablePlan(missingWarning), false);
});
test("dynamic module create requires bounded opaque master and detail previews", () => {
const plan = structuredClone(wireContract.scenarios.find(
scenario => scenario.name === "dynamic_module_resolve_to_create").plan);
const preview = pet.dynamicModuleConfirmationPreview(plan);
assert.equal(preview.required, true);
assert.equal(preview.complete, true);
assert.equal(preview.mode, "create");
assert.equal(preview.totalValues, 2);
assert.equal(preview.masterValues[0].parameterId, "m0123456789abcdef");
assert.equal(preview.detailRows[0].values[0].value, "第一行");
assert.equal(pet.isExecutablePlan(plan), true);
const emptyValue = structuredClone(plan);
emptyValue.preview.masterValues[0].value = "";
bindDynamicCreateProjections(emptyValue);
assert.equal(pet.dynamicModuleConfirmationPreview(emptyValue).complete, true);
const projectionMismatch = structuredClone(plan);
projectionMismatch.data.parameterPreview.masterValues[0].value = "被篡改";
assert.equal(
pet.dynamicModuleConfirmationPreview(projectionMismatch).complete,
false);
assert.equal(pet.isExecutablePlan(projectionMismatch), false);
const physicalFieldLeak = structuredClone(plan);
physicalFieldLeak.preview.masterValues[0].physicalField = "CUSTOMER_NAME";
bindDynamicCreateProjections(physicalFieldLeak);
assert.equal(
pet.dynamicModuleConfirmationPreview(physicalFieldLeak).complete,
false);
const duplicateParameter = structuredClone(plan);
duplicateParameter.preview.masterValues.push(
structuredClone(duplicateParameter.preview.masterValues[0]));
bindDynamicCreateProjections(duplicateParameter);
assert.equal(
pet.dynamicModuleConfirmationPreview(duplicateParameter).complete,
false);
const wrongRowNumber = structuredClone(plan);
wrongRowNumber.preview.detailRows[0].rowNumber = 2;
bindDynamicCreateProjections(wrongRowNumber);
assert.equal(
pet.dynamicModuleConfirmationPreview(wrongRowNumber).complete,
false);
const controlCharacter = structuredClone(plan);
controlCharacter.preview.detailRows[0].values[0].value = "第一行\u0085";
bindDynamicCreateProjections(controlCharacter);
assert.equal(
pet.dynamicModuleConfirmationPreview(controlCharacter).complete,
false);
const aggregateTooLarge = structuredClone(plan);
aggregateTooLarge.preview.masterValues = Array.from({ length: 5 }, (_, index) => ({
parameterId: "m" + index.toString(16).padStart(16, "0"),
label: "大字段" + index,
valueType: "string",
value: "值".repeat(30000)
}));
bindDynamicCreateProjections(aggregateTooLarge);
assert.equal(
pet.dynamicModuleConfirmationPreview(aggregateTooLarge).complete,
false);
const exposedBlocker = structuredClone(plan);
exposedBlocker.data.writeExecutionBlocker = "adapter_missing";
assert.equal(
pet.dynamicModuleConfirmationPreview(exposedBlocker).complete,
false);
const changedVersion = structuredClone(plan);
changedVersion.commandVersion = "2.0";
assert.equal(pet.dynamicModuleConfirmationPreview(changedVersion).complete, false);
assert.equal(pet.isExecutablePlan(changedVersion), false);
});
test("dynamic module update requires a bounded concurrent before-after preview", () => {
const plan = structuredClone(wireContract.scenarios.find(
scenario => scenario.name === "dynamic_module_resolve_to_update").plan);
const preview = pet.dynamicModuleConfirmationPreview(plan);
assert.equal(preview.required, true);
assert.equal(preview.complete, true);
assert.equal(preview.mode, "update");
assert.equal(preview.recordDisplay, "客户 C-001 / 朗速客户");
assert.equal(preview.changes[0].previousValue, "100.00");
assert.equal(preview.changes[0].newValue, "120.50");
assert.equal(pet.isExecutablePlan(plan), true);
const missingPrevious = structuredClone(plan);
delete missingPrevious.preview.changes[0].previousValue;
bindDynamicUpdateProjection(missingPrevious);
assert.equal(
pet.dynamicModuleConfirmationPreview(missingPrevious).complete,
false);
const noActualChange = structuredClone(plan);
noActualChange.preview.changes[0].newValue = "100.00";
bindDynamicUpdateProjection(noActualChange);
assert.equal(
pet.dynamicModuleConfirmationPreview(noActualChange).complete,
false);
assert.equal(pet.isExecutablePlan(noActualChange), false);
const physicalFieldLeak = structuredClone(plan);
physicalFieldLeak.preview.changes[0].columnName = "CREDIT_LIMIT";
bindDynamicUpdateProjection(physicalFieldLeak);
assert.equal(
pet.dynamicModuleConfirmationPreview(physicalFieldLeak).complete,
false);
const duplicateParameter = structuredClone(plan);
const duplicate = structuredClone(duplicateParameter.preview.changes[0]);
duplicate.newValue = "130.00";
duplicateParameter.preview.changes.push(duplicate);
bindDynamicUpdateProjection(duplicateParameter);
assert.equal(
pet.dynamicModuleConfirmationPreview(duplicateParameter).complete,
false);
const unsafeValue = structuredClone(plan);
unsafeValue.preview.changes[0].newValue = "120.50\u0000";
bindDynamicUpdateProjection(unsafeValue);
assert.equal(
pet.dynamicModuleConfirmationPreview(unsafeValue).complete,
false);
const projectionMismatch = structuredClone(plan);
projectionMismatch.data.preview.changes[0].newValue = "999.99";
assert.equal(
pet.dynamicModuleConfirmationPreview(projectionMismatch).complete,
false);
const forgedAdapter = structuredClone(plan);
forgedAdapter.data.adapter.evidenceSha256 = "not-a-hash";
assert.equal(
pet.dynamicModuleConfirmationPreview(forgedAdapter).complete,
false);
assert.equal(pet.isExecutablePlan(forgedAdapter), false);
});
test("atlas asset must decode at the exact production dimensions", async () => {
const loaded = await pet.loadAtlasAsset("https://asset.test/guga.webp", {
createImage: () => fakeImage(1536, 1872)
});
assert.deepEqual(loaded, {
url: "https://asset.test/guga.webp",
width: 1536,
height: 1872
});
});
test("atlas asset fails closed on crop corruption and timeout", async () => {
await assert.rejects(
pet.loadAtlasAsset("https://asset.test/cropped.webp", {
createImage: () => fakeImage(1536, 1792)
}),
error => error && error.code === "pet_sprite_dimensions_invalid"
);
await assert.rejects(
pet.loadAtlasAsset("https://asset.test/corrupt.webp", {
createImage: () => fakeImage(1536, 1872, true)
}),
error => error && error.code === "pet_sprite_decode_failed"
);
await assert.rejects(
pet.loadAtlasAsset("https://asset.test/hung.webp", {
createImage: () => ({ naturalWidth: 0, naturalHeight: 0 }),
setTimer(callback) { callback(); return 1; },
clearTimer() {}
}),
error => error && error.code === "pet_sprite_load_timeout"
);
});
test("invalid server plans can never enable execution", () => {
assert.equal(pet.isExecutablePlan({
planId: "p1", valid: true, executionAllowed: true, risk: "write"
}), true);
assert.equal(pet.isExecutablePlan({
planId: "p2", valid: true, executionAllowed: true, risk: "navigate"
}), true);
assert.equal(pet.isExecutablePlan({
planId: "p3", valid: true, executionAllowed: true, risk: "critical"
}), true);
assert.equal(pet.isExecutablePlan({
planId: "p4", valid: true, executionAllowed: false, risk: "draft"
}), false);
assert.equal(pet.isExecutablePlan({
planId: "p5", valid: true, executionAllowed: false, risk: "read"
}), false);
assert.equal(pet.isExecutablePlan({
planId: "p6", valid: false, executionAllowed: true, risk: "write"
}), false);
assert.equal(pet.isExecutablePlan({ valid: true, executionAllowed: true, risk: "write" }), false);
assert.equal(pet.isExecutablePlan(null), false);
});
function validResponse(request, data) {
return {
protocolVersion: "1.0",
requestId: request.requestId,
correlationId: request.correlationId,
success: true,
code: "ok",
message: null,
data: data || {}
};
}
function executionData(overrides) {
return {
result: {
success: true,
code: "purchase_document_created",
message: "采购业务单据已创建。",
recordId: null,
replayed: false,
data: {}
},
followupPlan: null,
followupCode: null,
...(overrides || {})
};
}
function diagnosticExecutionData(correlationId) {
return executionData({
result: {
success: true,
code: "initialization_failure_captured",
message: "已捕获模块初始化失败的诊断证据。",
recordId: "hr_4011",
replayed: false,
data: {
diagnosticContextSchemaVersion: "1.0",
diagnosticId: "diag-0123456789abcdef0123456789abcdef",
correlationId,
evidencePersisted: true,
evidenceContentHash: "b".repeat(64),
outcome: "failed",
primaryFindingCode: "missing_column",
moduleOpenSucceeded: false,
eventCount: 1,
failedEventCount: 1,
slowEventCount: 0,
traceTruncated: false,
summaryTruncated: false,
findings: [{
severity: "error",
code: "missing_column",
category: "low_code_configuration",
stage: "initialization_sql",
confidence: "observed",
message: "初始化引用的数据库字段不存在。",
recommendation: "检查低代码字段映射、客户扩展字段和账套升级版本。",
occurrenceCount: 1,
sqlFingerprint: "c".repeat(64),
caller: "caller_0001"
}],
staticDiagnosis: {
moduleCode: "hr_4011",
moduleKind: "base",
healthy: false,
issueCount: 1,
issues: [{
severity: "error",
code: "base.fields_missing",
source: "base_field_config"
}]
},
contextAvailable: true
}
}
});
}
function fakeImage(width, height, decodeFails) {
const image = {
naturalWidth: width,
naturalHeight: height,
async decode() {
if (decodeFails) throw new Error("decode failed");
}
};
Object.defineProperty(image, "src", {
set() { queueMicrotask(() => image.onload()); }
});
return image;
}
function bindDynamicCreateProjections(plan) {
plan.data.preview = structuredClone(plan.preview);
plan.data.parameterPreview = structuredClone(plan.preview);
return plan;
}
function bindDynamicUpdateProjection(plan) {
plan.data.preview = structuredClone(plan.preview);
return plan;
}