Home() useState 66->52, useRef 41->39. Shell-facing fields merge into one object; subtree state lives in useRectificationSurface. Chat props 20->7. Growth contract rebaselined. Zero behavior/copy change.
75 lines
4.2 KiB
TypeScript
75 lines
4.2 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import { readFileSync } from "node:fs";
|
||
import test from "node:test";
|
||
|
||
import { cssDeclarations } from "./css-contract-test-support.ts";
|
||
import { homeSurface as page } from "./home-surface.ts";
|
||
|
||
const read = (relativePath: string) => readFileSync(new URL(relativePath, import.meta.url), "utf8");
|
||
const sidebar = read("../src/components/app-sidebar.tsx");
|
||
const sidebarRow = read("../src/components/sidebar-session-row.tsx");
|
||
const starter = read("../src/components/starter-home.tsx");
|
||
const styles = read("../src/app/globals.css");
|
||
const pageSource = read("../src/app/page.tsx");
|
||
const hook = read("../src/hooks/use-rectification-surface.ts");
|
||
const sessions = read("../src/hooks/use-session-management.ts");
|
||
const caseService = read("../src/lib/rectification-agentic/v9/case-service.ts");
|
||
|
||
test("history session open uses the bound skill identity instead of the live registry version", () => {
|
||
// 原值:openRectificationCase 对 session 也把 resolveActiveSkillPackage() 交给 v2
|
||
// 新值:session 先 v1 取 Case,再读绑定身份,注册表核验后把绑定身份交给 v2
|
||
// 决策 1:打开 RPC 不再要求等于当前版本
|
||
assert.match(caseService, /request\.intent === "session"/);
|
||
assert.match(caseService, /open_agentic_rectification_case"/);
|
||
assert.match(caseService, /get_agentic_rectification_skill_identity"/);
|
||
assert.match(caseService, /resolveExactSkillPackage\(/);
|
||
assert.match(caseService, /skill_identity_missing/);
|
||
const homepageOpen = caseService.slice(
|
||
caseService.indexOf("export async function openRectificationCase"),
|
||
caseService.indexOf("export async function getRectificationEntrySummary"),
|
||
);
|
||
assert.match(homepageOpen, /intent === "homepage" \|\| request\.intent === "new"/);
|
||
assert.match(homepageOpen, /open_agentic_rectification_case_v2/);
|
||
});
|
||
|
||
test("skill_identity_mismatch maps to 409 instead of the 500 fallback", () => {
|
||
// 原值:KNOWN_RPC_ERROR_CODES 没有 mismatch,落到 校正服务暂时不可用
|
||
// 新值:409 skill_identity_mismatch,文案要求刷新
|
||
// 决策 2:修完决策 1 后不应再出现;映射只为不再露 500
|
||
assert.match(
|
||
caseService,
|
||
/"agentic_rectification_skill_identity_mismatch", \{ status: 409, code: "skill_identity_mismatch", message: "该校正绑定的规则版本与当前不一致,请刷新后重试" \}/,
|
||
);
|
||
});
|
||
|
||
test("a history-list open failure shows under the clicked row, not on the starter card", () => {
|
||
// 原值:rectificationError 只由 starter-home 画;selectSession 不切会话,表现为点了没反应
|
||
// 新值:session 失败绑到被点的那一行;首页起始卡不重复同一条
|
||
// 决策 3:错误就地显示
|
||
// 原值:const [rectificationErrorSessionId, setRectificationErrorSessionId] = useState(...)
|
||
// 新值:外壳 9 个校正字段合成一个 rectification 对象;errorSessionId 仍叫 rectificationErrorSessionId,setter 仍叫 setRectificationErrorSessionId
|
||
// 原因:外壳也要读的校正状态合并成一个对象,散装 useState 下降
|
||
assert.match(pageSource, /errorSessionId: rectificationErrorSessionId,/);
|
||
assert.match(pageSource, /setRectificationErrorSessionId,/);
|
||
assert.match(
|
||
pageSource,
|
||
/rectificationError=\{rectificationErrorSessionId \? "" : rectificationError\}/,
|
||
);
|
||
assert.match(pageSource, /openErrorSessionId=\{rectificationErrorSessionId\}/);
|
||
assert.match(
|
||
pageSource,
|
||
/openErrorMessage=\{rectificationErrorSessionId \? rectificationErrorMessage : ""\}/,
|
||
);
|
||
assert.match(starter, /rectificationError && !rectificationSurfaceOpen && \(/);
|
||
assert.match(sidebar, /openErrorSessionId/);
|
||
assert.match(sidebarRow, /error \? \(/);
|
||
assert.match(sidebarRow, /className="session-open-error"/);
|
||
assert.match(sidebarRow, /role="alert"/);
|
||
assert.match(hook, /setRectificationErrorSessionId\(intent === "session" \? exactSessionId : null\)/);
|
||
assert.match(sessions, /setRectificationErrorSessionId\(null\)/);
|
||
const notice = cssDeclarations(".session-open-error", styles);
|
||
assert.match(notice, /color:\s*var\(--color-danger\)/);
|
||
assert.match(notice, /font-size:\s*var\(--type-overline\)/);
|
||
assert.match(page, /openErrorSessionId=\{rectificationErrorSessionId\}/);
|
||
});
|