diff --git a/src/lib/boss-data.ts b/src/lib/boss-data.ts index cf89e33..1ae1726 100644 --- a/src/lib/boss-data.ts +++ b/src/lib/boss-data.ts @@ -2882,8 +2882,6 @@ function appendThreadProgressEventInState( return event; } -const THREAD_STATUS_FULL_SYNC_INTERVAL_MS = 15 * 60_000; - function normalizeState(raw: Partial | undefined): BossState { const base = cloneInitialState(); if (!raw) return syncDerivedState(base); @@ -7635,6 +7633,15 @@ function shouldQueueProjectUnderstandingSync( state: BossState, reason: "heartbeat_activity" | "thread_reply" = "heartbeat_activity", ) { + // 主 Agent 自动向线程发隐藏理解对话当前整体关闭。 + // 保留现有数据模型,后续如果需要恢复,可在明确产品决策后重新开启。 + void project; + void observedActivityAt; + void state; + void reason; + return false; + + /* if (!isDispatchableThreadProject(project)) { return false; } @@ -7681,6 +7688,7 @@ function shouldQueueProjectUnderstandingSync( task.projectUnderstandingTargetProjectId === project.id && (task.status === "queued" || task.status === "running"), ); + */ } function buildProjectUnderstandingSyncPrompt(project: Project, reason: "heartbeat_activity" | "thread_reply") { diff --git a/src/lib/boss-master-agent.ts b/src/lib/boss-master-agent.ts index de27af9..5818cc8 100644 --- a/src/lib/boss-master-agent.ts +++ b/src/lib/boss-master-agent.ts @@ -1775,35 +1775,6 @@ function buildDeviceImportResolutionPrompt(params: { ].join("\n"); } -function buildDeviceImportUnderstandingPrompt(params: { - deviceName: string; - draftId: string; - candidateId: string; - threadDisplayName: string; - folderName: string; - lastActiveAt: string; -}) { - return [ - "你正在协助 Boss 控制台完成新设备导入前的项目理解。", - "请以当前活跃线程的视角,直接总结这个项目当前最关键的信息。", - "输出必须是 JSON,对象结构如下:", - '{ "projectGoal": "一句中文目标", "currentProgress": "一句中文进度", "technicalArchitecture": "一句中文架构说明", "currentBlockers": "一句中文阻塞说明", "recommendedNextStep": "一句中文建议动作" }', - "要求:", - "1. 只输出 JSON,不要输出额外解释。", - "2. 用中文,句子短而明确。", - "3. 如果某项信息不确定,也要明确写出当前已知范围,不要留空。", - "", - `deviceName: ${params.deviceName}`, - `draftId: ${params.draftId}`, - `candidateId: ${params.candidateId}`, - `threadDisplayName: ${params.threadDisplayName}`, - `folderName: ${params.folderName}`, - `lastActiveAt: ${params.lastActiveAt}`, - "", - "请回答当前项目:目标、进度、技术架构、阻塞点、下一步建议。", - ].join("\n"); -} - export async function queueDeviceImportResolutionTask(params: { deviceId: string; reviewedBy: string; @@ -1824,35 +1795,7 @@ export async function queueDeviceImportResolutionTask(params: { const selectedCandidates = draft.candidates.filter((candidate) => draft.selectedCandidateIds.includes(candidate.candidateId), ); - const understandingTasks = await Promise.all( - selectedCandidates - .filter((candidate) => candidate.codexThreadRef?.trim()) - .map((candidate) => - queueMasterAgentTask({ - projectId: "master-agent", - taskType: "conversation_reply", - requestMessageId: draft.draftId, - requestText: `请总结线程 ${candidate.threadDisplayName} 当前项目目标与进度`, - executionPrompt: buildDeviceImportUnderstandingPrompt({ - deviceName: device.name, - draftId: draft.draftId, - candidateId: candidate.candidateId, - threadDisplayName: candidate.threadDisplayName, - folderName: candidate.folderName, - lastActiveAt: candidate.lastActiveAt, - }), - requestedBy: params.reviewedBy, - requestedByAccount: params.reviewedBy, - deviceId: device.id, - deviceImportDraftId: draft.draftId, - deviceImportCandidateId: candidate.candidateId, - deviceImportCandidateFolderName: candidate.folderName, - targetThreadDisplayName: candidate.threadDisplayName, - targetCodexThreadRef: candidate.codexThreadRef, - targetCodexFolderRef: candidate.codexFolderRef ?? candidate.folderRef, - }), - ), - ); + const understandingTasks: Array>> = []; const task = await queueMasterAgentTask({ projectId: "master-agent", taskType: "device_import_resolution", diff --git a/tests/device-import-draft.test.ts b/tests/device-import-draft.test.ts index 52e8cc1..1a1aed0 100644 --- a/tests/device-import-draft.test.ts +++ b/tests/device-import-draft.test.ts @@ -83,7 +83,7 @@ async function createAuthedRequestFor( }); } -test("device import draft review queues a master-agent task, then completion writes back a ready resolution and apply still works", async () => { +test("device import draft review queues only the resolution task, then completion writes back a ready resolution and apply still works", async () => { await setup(); const enrollmentResponse = await createEnrollmentRoute( @@ -190,8 +190,7 @@ test("device import draft review queues a master-agent task, then completion wri assert.equal(reviewPayload.task.status, "queued"); assert.equal(reviewPayload.draft?.status, "pending_resolution"); assert.equal(reviewPayload.resolution, undefined); - assert.equal(reviewPayload.understandingTasks?.length, 1); - assert.equal(reviewPayload.understandingTasks?.[0]?.status, "queued"); + assert.equal(reviewPayload.understandingTasks?.length ?? 0, 0); const reviewedState = await readState(); const resolutionTask = reviewedState.masterAgentTasks.find( @@ -207,8 +206,11 @@ test("device import draft review queues a master-agent task, then completion wri task.deviceImportDraftId === draftPayload.draft?.draftId && task.status === "queued", ); - assert.ok(understandingTask, "expected import review to leave a queued thread understanding task trace"); - assert.equal(understandingTask?.targetThreadDisplayName, "北区试产线回归"); + assert.equal( + understandingTask, + undefined, + "device import review should no longer auto-queue hidden thread sync tasks", + ); const completionResponse = await completeMasterTaskRoute( await createAuthedRequest( @@ -237,30 +239,6 @@ test("device import draft review queues a master-agent task, then completion wri ); assert.equal(completionResponse.status, 200); - const understandingCompletionResponse = await completeMasterTaskRoute( - await createAuthedRequest( - `http://127.0.0.1:3000/api/v1/master-agent/tasks/${understandingTask?.taskId}/complete`, - "POST", - { - deviceId: enrollmentPayload.device.id, - status: "completed", - replyBody: JSON.stringify( - { - projectGoal: "完成北区试产线树莓派二代接入与联调。", - currentProgress: "已经完成线程导入准备,当前在核对设备接线和控制链路。", - technicalArchitecture: "前台是 Next.js 控制台,设备端通过 local-agent 与 Codex 线程联动。", - currentBlockers: "还缺少树莓派二代的串口稳定性验证。", - recommendedNextStep: "先确认接线和串口日志,再继续设备控制指令联调。", - }, - null, - 2, - ), - }, - ), - { params: Promise.resolve({ taskId: understandingTask?.taskId ?? "" }) }, - ); - assert.equal(understandingCompletionResponse.status, 200); - const completedState = await readState(); const completedDraft = completedState.deviceImportDrafts.find( (draft) => draft.deviceId === enrollmentPayload.device.id, @@ -291,13 +269,8 @@ test("device import draft review queues a master-agent task, then completion wri }>; understandingTasks?: Array<{ taskId: string; status: string }>; }; - assert.equal(refreshedDraftPayload.projectUnderstandings?.length, 1); - assert.equal(refreshedDraftPayload.projectUnderstandings?.[0]?.threadDisplayName, "北区试产线回归"); - assert.match( - refreshedDraftPayload.projectUnderstandings?.[0]?.projectGoal ?? "", - /树莓派二代接入与联调/, - ); - assert.equal(refreshedDraftPayload.understandingTasks?.[0]?.status, "completed"); + assert.equal(refreshedDraftPayload.projectUnderstandings?.length ?? 0, 0); + assert.equal(refreshedDraftPayload.understandingTasks?.length ?? 0, 0); const applyResponse = await applyImportDraftRoute( await createAuthedRequest( @@ -321,23 +294,13 @@ test("device import draft review queues a master-agent task, then completion wri assert.ok(importedProject, "expected selected candidate to become a real chat window"); assert.equal(importedProject?.threadMeta.threadDisplayName, "北区试产线回归"); assert.equal(importedProject?.threadMeta.folderName, "北区试产线"); - assert.equal(importedProject?.projectUnderstanding?.projectGoal, "完成北区试产线树莓派二代接入与联调。"); - assert.match(importedProject?.projectUnderstanding?.technicalArchitecture ?? "", /local-agent 与 Codex 线程联动/); - assert.equal(importedProject?.projectUnderstanding?.sourceKind, "device_import"); - assert.ok(importedProject?.threadMeta.lastProjectUnderstandingSyncedAt); + assert.equal(importedProject?.projectUnderstanding, undefined); + assert.equal(importedProject?.threadMeta.lastProjectUnderstandingSyncedAt, undefined); const importedMemories = nextState.masterAgentMemories.filter( (memory) => memory.projectId === importedProject?.id, ); - assert.equal(importedMemories.length, 5); - assert.equal( - importedMemories.find((memory) => memory.title === "项目目标 · 北区试产线回归")?.content, - "完成北区试产线树莓派二代接入与联调。", - ); - assert.match( - importedMemories.find((memory) => memory.title === "下一步建议 · 北区试产线回归")?.content ?? "", - /确认接线和串口日志/, - ); + assert.equal(importedMemories.length, 0); const device = nextState.devices.find((item) => item.id === enrollmentPayload.device.id); assert.deepEqual(device?.projects, ["北区试产线"]); @@ -394,7 +357,7 @@ test("device import draft review queues a master-agent task, then completion wri assert.equal(appliedResolution?.status, "applied"); }); -test("imported thread projects queue hidden understanding sync tasks on newer activity and refresh project understanding", async () => { +test("imported thread projects append progress events on newer activity without queuing hidden understanding sync tasks", async () => { await setup(); const enrollmentResponse = await createEnrollmentRoute( @@ -493,7 +456,7 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac task.deviceImportCandidateId && task.status === "queued", ); - assert.ok(initialUnderstandingTask); + assert.equal(initialUnderstandingTask, undefined); assert.equal( ( @@ -524,34 +487,6 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac 200, ); - assert.equal( - ( - await completeMasterTaskRoute( - await createAuthedRequest( - `http://127.0.0.1:3000/api/v1/master-agent/tasks/${initialUnderstandingTask.taskId}/complete`, - "POST", - { - deviceId: enrollmentPayload.device.id, - status: "completed", - replyBody: JSON.stringify( - { - projectGoal: "让智能看板项目能够稳定接入主控面板。", - currentProgress: "已经完成导入前梳理,准备开始界面和设备联调。", - technicalArchitecture: "Android 原生端连接 Boss Web,再通过 local-agent 对接 Codex 线程。", - currentBlockers: "还缺少设备端实时推送状态的统一协议。", - recommendedNextStep: "先对齐状态推送协议,再做前后端联调。", - }, - null, - 2, - ), - }, - ), - { params: Promise.resolve({ taskId: initialUnderstandingTask.taskId }) }, - ) - ).status, - 200, - ); - const applyResponse = await applyImportDraftRoute( await createAuthedRequest( `http://127.0.0.1:3000/api/v1/devices/${enrollmentPayload.device.id}/import-draft/apply`, @@ -567,7 +502,7 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac (project) => project.threadMeta.codexThreadRef === "thread-smart-board", ); assert.ok(importedProject); - assert.equal(importedProject?.projectUnderstanding?.currentProgress, "已经完成导入前梳理,准备开始界面和设备联调。"); + assert.equal(importedProject?.projectUnderstanding, undefined); const progressEventsBefore = currentState.threadProgressEvents.filter( (event) => event.projectId === importedProject?.id, ).length; @@ -599,7 +534,7 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac task.projectUnderstandingReason === "heartbeat_activity" && task.status === "queued", ); - assert.ok(hiddenSyncTask); + assert.equal(hiddenSyncTask, undefined); const progressEventsAfter = currentState.threadProgressEvents.filter( (event) => event.projectId === importedProject?.id, @@ -608,41 +543,11 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac assert.equal(progressEventsAfter[0]?.eventType, "progress_updated"); assert.match(progressEventsAfter[0]?.summary ?? "", /北区试产线回归|新活动/); - assert.equal( - ( - await completeMasterTaskRoute( - await createAuthedRequest( - `http://127.0.0.1:3000/api/v1/master-agent/tasks/${hiddenSyncTask.taskId}/complete`, - "POST", - { - deviceId: enrollmentPayload.device.id, - status: "completed", - replyBody: JSON.stringify( - { - projectGoal: "让智能看板项目能够稳定接入主控面板。", - currentProgress: "已完成状态推送协议对齐,正在推进前后端联调。", - technicalArchitecture: "Android 原生端连接 Boss Web,再通过 local-agent 对接 Codex 线程。", - currentBlockers: "还缺少最终的真机联调回归。", - recommendedNextStep: "先完成真机联调,再收口回归问题。", - }, - null, - 2, - ), - }, - ), - { params: Promise.resolve({ taskId: hiddenSyncTask.taskId }) }, - ) - ).status, - 200, - ); - currentState = await readState(); const refreshedProject = currentState.projects.find((project) => project.id === importedProject?.id); - assert.equal(refreshedProject?.projectUnderstanding?.currentProgress, "已完成状态推送协议对齐,正在推进前后端联调。"); - assert.match(refreshedProject?.projectUnderstanding?.technicalArchitecture ?? "", /Android 原生端连接 Boss Web/); - assert.equal(refreshedProject?.projectUnderstanding?.sourceKind, "thread_sync"); - assert.ok(refreshedProject?.threadMeta.lastProjectUnderstandingSyncedAt); + assert.equal(refreshedProject?.projectUnderstanding, undefined); + assert.equal(refreshedProject?.threadMeta.lastProjectUnderstandingSyncedAt, undefined); assert.equal( currentState.masterAgentMemories.find( @@ -650,7 +555,7 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac memory.projectId === refreshedProject?.id && memory.title === "项目进度 · 智能看板主线程", )?.content, - "已完成状态推送协议对齐,正在推进前后端联调。", + undefined, ); assert.equal( currentState.masterAgentMemories.find( @@ -658,16 +563,14 @@ test("imported thread projects queue hidden understanding sync tasks on newer ac memory.projectId === refreshedProject?.id && memory.title === "下一步建议 · 智能看板主线程", )?.content, - "先完成真机联调,再收口回归问题。", + undefined, ); const masterAgentProject = currentState.projects.find((project) => project.id === "master-agent"); const collaborationNotice = (masterAgentProject?.messages ?? []) .map((message) => message.body) .find((body) => body.includes("协同推进")); - assert.match(collaborationNotice ?? "", /主 Agent 已同步:智能看板主线程/); - assert.match(collaborationNotice ?? "", /不会中断你继续直接控制线程开发/); - assert.ok(!(collaborationNotice ?? "").includes("可接手")); + assert.equal(collaborationNotice, undefined); }); test("heartbeat candidates no longer auto-create chat windows from legacy projects when import draft is present", async () => {