import test from "node:test"; import assert from "node:assert/strict"; import { describeThreadConversationExecutionConflict, labelForThreadConversationExecutionConflictDecision, } from "../src/lib/thread-execution-conflict-ui.ts"; test("describeThreadConversationExecutionConflict explains preferred gui mode with project-scoped guidance", () => { const description = describeThreadConversationExecutionConflict({ projectId: "thread-ui", projectName: "Boss UI 主线程", deviceId: "mac-studio", deviceName: "Mac Studio", folderKey: "mac-studio:boss", preferredExecutionMode: "gui", allowPolicy: "forbid", conflictState: "blocked", reason: "preferred_gui_mode", actions: ["forbid", "allow_once", "allow_always"], }); assert.equal(description.title, "当前项目默认先走 GUI"); assert.match(description.summary, /Mac Studio/); assert.match(description.summary, /只对这个项目/); assert.match(description.summary, /Boss UI 主线程/); }); test("describeThreadConversationExecutionConflict explains project-level forbid without implying a global lock", () => { const description = describeThreadConversationExecutionConflict({ projectId: "thread-ui", projectName: "Boss UI 主线程", deviceId: "mac-studio", deviceName: "Mac Studio", folderKey: "mac-studio:boss", preferredExecutionMode: "cli", allowPolicy: "forbid", conflictState: "blocked", reason: "project_conflict_forbid", actions: ["forbid", "allow_once", "allow_always"], }); assert.equal(description.title, "当前项目已命中并发保护"); assert.match(description.summary, /最近检测到 GUI \/ CLI 同时活动/); assert.match(description.summary, /只影响这个项目/); }); test("labelForThreadConversationExecutionConflictDecision keeps the three project-scoped actions concise", () => { assert.equal(labelForThreadConversationExecutionConflictDecision("forbid"), "禁止"); assert.equal(labelForThreadConversationExecutionConflictDecision("allow_once"), "允许本次"); assert.equal(labelForThreadConversationExecutionConflictDecision("allow_always"), "永久放行"); });