# 主 Agent 线程状态文档与增量同步 Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** 让主 Agent 用“线程状态文档 + 最近进展事件 + 关键时刻深拉”的方式理解活跃线程,减少常态 token 消耗,同时保持关键时刻的接手能力与实时性。 **Architecture:** 在现有 `projectUnderstandingSnapshot` 自动同步链路上新增线程级 `ThreadStatusDocument` 和 `ThreadProgressEvent`,让 heartbeat / thread reply 先走轻量事件同步,再在关键场景触发全量理解刷新。主 Agent prompt 组装从“读项目理解快照”升级为“读线程状态文档 + 最近事件 + 项目记忆”,前台增加只读 `线程状态` 入口。 **Tech Stack:** Next.js App Router、TypeScript、文件型状态存储 `data/boss-state.json`、Android 原生客户端、Node test runner、Gradle unit tests --- ## 文件结构 ### 新增/扩展数据模型与状态归一化 - Modify: `/Users/kris/code/boss/src/lib/boss-data.ts` - Test: `/Users/kris/code/boss/tests/thread-status-sync.test.ts` - Test: `/Users/kris/code/boss/tests/device-import-draft.test.ts` 职责: - 在 `BossState` 里新增线程状态文档和进展事件 - 补 normalization / pruning / slicing - 增加全量同步与轻量同步任务排队逻辑 ### 主 Agent prompt 组装与读取逻辑 - Modify: `/Users/kris/code/boss/src/lib/boss-master-agent.ts` - Test: `/Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts` 职责: - 让主 Agent 默认读取线程状态文档和最近进展事件 - 保留关键时刻深拉线程的兜底路径 ### 线程状态 API 与会话信息展示 - Create: `/Users/kris/code/boss/src/app/api/v1/projects/[projectId]/thread-status/route.ts` - Modify: `/Users/kris/code/boss/src/components/app-ui.tsx` - Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java` - Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java` - Create: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ThreadStatusActivity.java` - Test: `/Users/kris/code/boss/tests/thread-status-route.test.ts` - Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ConversationInfoActivityTest.java` - Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ThreadStatusActivityTest.java` 职责: - 提供线程状态只读接口 - 在线程会话信息页增加 `线程状态` 入口 - Android 前台可查看线程状态 ### 文档与回归 - Modify: `/Users/kris/code/boss/README.md` - Modify: `/Users/kris/code/boss/docs/architecture/current_runtime_and_deploy_status_cn.md` - Modify: `/Users/kris/code/boss/docs/architecture/api_and_service_inventory_cn.md` 职责: - 记录线程状态文档和进展事件的运行方式 - 记录 API 与同步策略 --- ### Task 1: 新增线程状态文档与进展事件模型 **Files:** - Modify: `/Users/kris/code/boss/src/lib/boss-data.ts` - Test: `/Users/kris/code/boss/tests/thread-status-sync.test.ts` - [ ] **Step 1: 写失败测试,锁住状态模型归一化与裁剪行为** ```ts import test from "node:test"; import assert from "node:assert/strict"; let readState: (typeof import("../src/lib/boss-data"))["readState"]; let writeState: (typeof import("../src/lib/boss-data"))["writeState"]; test("thread status documents and progress events normalize and trim correctly", async () => { const state = await readState(); state.threadStatusDocuments = [ { documentId: "doc-1", projectId: "thread-a", threadId: "thread-a-id", threadDisplayName: "线程 A", folderName: "Talking", deviceId: "mac-studio", projectGoal: "完成树莓派二代查询链路", currentPhase: "功能实现", currentProgress: "已打通查询接口,正在补手机端展示", technicalArchitecture: "Next.js API + Android 原生客户端", currentBlockers: "", recommendedNextStep: "补会话页展示与排序", keyFiles: ["src/lib/boss-data.ts"], keyCommands: ["npm run build"], updatedAt: "2026-04-04T18:00:00+08:00", sourceTaskId: "task-1", sourceKind: "full_sync", }, ]; state.threadProgressEvents = Array.from({ length: 30 }, (_, index) => ({ eventId: `event-${index}`, projectId: "thread-a", threadId: "thread-a-id", threadDisplayName: "线程 A", deviceId: "mac-studio", eventType: "progress_updated", summary: `进展 ${index}`, phase: "功能实现", blockerDelta: "", nextStepDelta: "", createdAt: `2026-04-04T18:${String(index).padStart(2, "0")}:00+08:00`, sourceTaskId: `task-${index}`, })); await writeState(state); const normalized = await readState(); assert.equal(normalized.threadStatusDocuments.length, 1); assert.equal(normalized.threadStatusDocuments[0]?.projectGoal, "完成树莓派二代查询链路"); assert.equal(normalized.threadProgressEvents.length, 20); assert.equal(normalized.threadProgressEvents[0]?.eventId, "event-29"); }); ``` - [ ] **Step 2: 跑测试,确认它先失败** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-sync.test.ts ``` Expected: - FAIL,提示 `threadStatusDocuments` 或 `threadProgressEvents` 不存在,或者长度/排序不符合预期 - [ ] **Step 3: 在 `BossState` 里新增模型与归一化逻辑** 在 `/Users/kris/code/boss/src/lib/boss-data.ts` 增加接口与默认值: ```ts export interface ThreadStatusDocument { documentId: string; projectId: string; threadId: string; threadDisplayName: string; folderName: string; deviceId: string; projectGoal: string; currentPhase: string; currentProgress: string; technicalArchitecture: string; currentBlockers: string; recommendedNextStep: string; keyFiles: string[]; keyCommands: string[]; updatedAt: string; sourceTaskId: string; sourceKind: "device_import" | "full_sync" | "incremental_sync"; } export interface ThreadProgressEvent { eventId: string; projectId: string; threadId: string; threadDisplayName: string; deviceId: string; eventType: | "phase_changed" | "progress_updated" | "blocker_added" | "blocker_resolved" | "next_step_changed" | "architecture_updated" | "handoff_ready"; summary: string; phase?: string; blockerDelta?: string; nextStepDelta?: string; createdAt: string; sourceTaskId: string; sourceMessageId?: string; } ``` 并把状态接入: ```ts threadStatusDocuments: ensureArray(raw.threadStatusDocuments, []).map((item) => ({ ...item, keyFiles: ensureArray(item.keyFiles, []), keyCommands: ensureArray(item.keyCommands, []), })), threadProgressEvents: ensureArray(raw.threadProgressEvents, []) .map((item) => ({ ...item })) .sort((a, b) => b.createdAt.localeCompare(a.createdAt)) .slice(0, 400), ``` 在 `syncDerivedState` 里裁剪每线程最近事件: ```ts const eventBuckets = new Map(); for (const event of state.threadProgressEvents) { const key = `${event.projectId}:${event.threadId}`; const bucket = eventBuckets.get(key) ?? []; if (bucket.length < 20) bucket.push(event); eventBuckets.set(key, bucket); } state.threadProgressEvents = [...eventBuckets.values()].flat(); ``` - [ ] **Step 4: 重新跑测试,确认通过** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-sync.test.ts ``` Expected: - PASS - [ ] **Step 5: 提交这一小步** ```bash git add /Users/kris/code/boss/src/lib/boss-data.ts /Users/kris/code/boss/tests/thread-status-sync.test.ts git commit -m "feat: add thread status document models" ``` ### Task 2: 用线程状态文档替代常态全量理解 **Files:** - Modify: `/Users/kris/code/boss/src/lib/boss-data.ts` - Test: `/Users/kris/code/boss/tests/device-import-draft.test.ts` - Test: `/Users/kris/code/boss/tests/thread-status-sync.test.ts` - [ ] **Step 1: 写失败测试,锁住“heartbeat 优先记增量,不总是排全量理解”** ```ts test("active thread updates create lightweight progress events before full re-sync", async () => { const state = await readState(); const project = state.projects.find((item) => item.id !== "master-agent" && item.threadMeta.codexThreadRef); assert.ok(project); project!.projectUnderstanding = { projectGoal: "目标 A", currentProgress: "旧进度", technicalArchitecture: "旧架构", currentBlockers: "", recommendedNextStep: "旧下一步", sourceTaskId: "task-old", updatedAt: "2026-04-04T10:00:00+08:00", sourceKind: "thread_sync", }; state.threadStatusDocuments = [ { documentId: "doc-old", projectId: project!.id, threadId: project!.threadMeta.threadId, threadDisplayName: project!.threadMeta.threadDisplayName, folderName: project!.threadMeta.folderName, deviceId: project!.deviceIds[0]!, projectGoal: "目标 A", currentPhase: "功能实现", currentProgress: "旧进度", technicalArchitecture: "旧架构", currentBlockers: "", recommendedNextStep: "旧下一步", keyFiles: [], keyCommands: [], updatedAt: "2026-04-04T10:00:00+08:00", sourceTaskId: "task-old", sourceKind: "full_sync", }, ]; // 用已有 heartbeat 处理函数或相关 helper 驱动活跃更新 const result = await upsertThreadProgressEventInStateForTest(state, { projectId: project!.id, threadId: project!.threadMeta.threadId, threadDisplayName: project!.threadMeta.threadDisplayName, deviceId: project!.deviceIds[0]!, eventType: "progress_updated", summary: "已完成手机端排序修复", phase: "功能实现", createdAt: "2026-04-04T12:00:00+08:00", sourceTaskId: "task-new", }); assert.equal(result.threadProgressEvents[0]?.summary, "已完成手机端排序修复"); assert.equal( result.masterAgentTasks.some((task) => task.projectUnderstandingTargetProjectId === project!.id), false, ); }); ``` - [ ] **Step 2: 跑测试,确认先失败** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-sync.test.ts /Users/kris/code/boss/tests/device-import-draft.test.ts ``` Expected: - FAIL,提示没有轻量事件 helper 或仍然直接走完整理解任务 - [ ] **Step 3: 在状态层新增轻量事件写入与全量理解判定** 在 `/Users/kris/code/boss/src/lib/boss-data.ts` 增加: ```ts function upsertThreadStatusDocumentInState( state: BossState, input: { projectId: string; threadId: string; threadDisplayName: string; folderName: string; deviceId: string; projectGoal: string; currentPhase: string; currentProgress: string; technicalArchitecture: string; currentBlockers: string; recommendedNextStep: string; keyFiles: string[]; keyCommands: string[]; updatedAt: string; sourceTaskId: string; sourceKind: ThreadStatusDocument["sourceKind"]; }, ) { const existing = state.threadStatusDocuments.find( (item) => item.projectId === input.projectId && item.threadId === input.threadId, ); if (existing) { Object.assign(existing, input); return existing; } const document: ThreadStatusDocument = { documentId: randomToken("thread-status"), ...input, }; state.threadStatusDocuments.unshift(document); return document; } function appendThreadProgressEventInState( state: BossState, input: Omit, ) { state.threadProgressEvents.unshift({ eventId: randomToken("thread-event"), ...input, }); } ``` 并把 heartbeat / thread reply 的同步策略改成: ```ts if (shouldQueueProjectUnderstandingSync(project, observedActivityAt, state)) { // 仍保留关键时刻全量理解 } else { appendThreadProgressEventInState(state, { projectId: project.id, threadId: project.threadMeta.threadId, threadDisplayName: project.threadMeta.threadDisplayName, deviceId: project.deviceIds[0] ?? "mac-studio", eventType: "progress_updated", summary: "检测到线程有新活动", phase: project.projectUnderstanding ? "功能实现" : undefined, createdAt: observedActivityAt, sourceTaskId: "heartbeat-auto", }); } ``` - [ ] **Step 4: 重新跑测试,确认通过** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-sync.test.ts /Users/kris/code/boss/tests/device-import-draft.test.ts ``` Expected: - PASS - [ ] **Step 5: 提交这一小步** ```bash git add /Users/kris/code/boss/src/lib/boss-data.ts /Users/kris/code/boss/tests/thread-status-sync.test.ts /Users/kris/code/boss/tests/device-import-draft.test.ts git commit -m "feat: add lightweight thread progress events" ``` ### Task 3: 主 Agent 默认读取线程状态文档与最近事件 **Files:** - Modify: `/Users/kris/code/boss/src/lib/boss-master-agent.ts` - Test: `/Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts` - [ ] **Step 1: 写失败测试,锁住主 Agent prompt 读取顺序** ```ts import test from "node:test"; import assert from "node:assert/strict"; import { readState } from "../src/lib/boss-data.ts"; import { buildMasterAgentExecutionPromptForTest } from "../src/lib/boss-master-agent.ts"; test("master agent prompt prefers thread status documents and recent events", async () => { const state = await readState(); state.threadStatusDocuments = [ { documentId: "doc-1", projectId: "demo-thread", threadId: "thread-1", threadDisplayName: "树莓派二代查询", folderName: "Talking", deviceId: "mac-studio", projectGoal: "完成树莓派二代问答", currentPhase: "功能实现", currentProgress: "已经打通线程排序与会话时间刷新", technicalArchitecture: "Boss Web + Android + local-agent", currentBlockers: "群聊回流文案还需要收口", recommendedNextStep: "继续修群聊回流提示", keyFiles: ["src/lib/boss-data.ts"], keyCommands: ["npm run build"], updatedAt: "2026-04-04T19:00:00+08:00", sourceTaskId: "task-doc", sourceKind: "full_sync", }, ]; state.threadProgressEvents = [ { eventId: "event-1", projectId: "demo-thread", threadId: "thread-1", threadDisplayName: "树莓派二代查询", deviceId: "mac-studio", eventType: "progress_updated", summary: "已完成会话排序修复", phase: "功能实现", createdAt: "2026-04-04T19:10:00+08:00", sourceTaskId: "task-event", }, ]; const prompt = buildMasterAgentExecutionPromptForTest(state, "请接手这个项目继续推进"); assert.match(prompt, /线程状态文档/); assert.match(prompt, /完成树莓派二代问答/); assert.match(prompt, /已完成会话排序修复/); }); ``` - [ ] **Step 2: 跑测试,确认先失败** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts ``` Expected: - FAIL,提示当前 prompt 里没有线程状态文档和进展事件 - [ ] **Step 3: 修改主 Agent prompt 组装** 在 `/Users/kris/code/boss/src/lib/boss-master-agent.ts` 增加线程状态摘要: ```ts const activeThreadStatusDocs = state.threadStatusDocuments .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt)) .slice(0, 3) .map((doc) => [ `线程状态文档:${doc.threadDisplayName}`, doc.projectGoal ? `目标=${doc.projectGoal}` : undefined, doc.currentPhase ? `阶段=${doc.currentPhase}` : undefined, doc.currentProgress ? `进度=${doc.currentProgress}` : undefined, doc.technicalArchitecture ? `架构=${doc.technicalArchitecture}` : undefined, doc.currentBlockers ? `阻塞=${doc.currentBlockers}` : undefined, doc.recommendedNextStep ? `下一步=${doc.recommendedNextStep}` : undefined, ] .filter(Boolean) .join(" / "), ) .join("\\n"); const recentThreadProgressEvents = state.threadProgressEvents .sort((a, b) => b.createdAt.localeCompare(a.createdAt)) .slice(0, 5) .map((event) => `${event.threadDisplayName}:${event.summary}`) .join("\\n"); ``` 并把返回 prompt 的内容改成: ```ts "线程状态文档:", activeThreadStatusDocs || "无", "", "最近线程进展:", recentThreadProgressEvents || "无", ``` - [ ] **Step 4: 重新跑测试,确认通过** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts ``` Expected: - PASS - [ ] **Step 5: 提交这一小步** ```bash git add /Users/kris/code/boss/src/lib/boss-master-agent.ts /Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts git commit -m "feat: read thread status documents in master agent prompts" ``` ### Task 4: 新增线程状态只读 API **Files:** - Create: `/Users/kris/code/boss/src/app/api/v1/projects/[projectId]/thread-status/route.ts` - Modify: `/Users/kris/code/boss/src/lib/boss-data.ts` - Test: `/Users/kris/code/boss/tests/thread-status-route.test.ts` - [ ] **Step 1: 写失败测试,锁住路由返回格式** ```ts import test from "node:test"; import assert from "node:assert/strict"; import { GET } from "../src/app/api/v1/projects/[projectId]/thread-status/route.ts"; test("GET thread-status returns current document and recent events", async () => { const response = await GET( new Request("http://localhost/api/v1/projects/demo-thread/thread-status"), { params: Promise.resolve({ projectId: "demo-thread" }) }, ); assert.equal(response.status, 200); const body = await response.json(); assert.ok(body.threadStatusDocument); assert.ok(Array.isArray(body.recentProgressEvents)); }); ``` - [ ] **Step 2: 跑测试,确认先失败** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-route.test.ts ``` Expected: - FAIL,提示 route 不存在或返回格式不对 - [ ] **Step 3: 实现只读 route** 创建 `/Users/kris/code/boss/src/app/api/v1/projects/[projectId]/thread-status/route.ts`: ```ts import { NextResponse } from "next/server"; import { readState } from "@/src/lib/boss-data"; export async function GET( _request: Request, { params }: { params: Promise<{ projectId: string }> }, ) { const { projectId } = await params; const state = await readState(); const project = state.projects.find((item) => item.id === projectId); if (!project) { return NextResponse.json({ error: "PROJECT_NOT_FOUND" }, { status: 404 }); } const threadStatusDocument = state.threadStatusDocuments.find((item) => item.projectId === projectId) ?? null; const recentProgressEvents = state.threadProgressEvents .filter((item) => item.projectId === projectId) .sort((a, b) => b.createdAt.localeCompare(a.createdAt)) .slice(0, 5); return NextResponse.json({ projectId, threadStatusDocument, recentProgressEvents, }); } ``` - [ ] **Step 4: 重新跑测试,确认通过** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-route.test.ts ``` Expected: - PASS - [ ] **Step 5: 提交这一小步** ```bash git add /Users/kris/code/boss/src/app/api/v1/projects/[projectId]/thread-status/route.ts /Users/kris/code/boss/tests/thread-status-route.test.ts git commit -m "feat: add thread status read api" ``` ### Task 5: 在线程会话信息页接入线程状态入口 **Files:** - Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java` - Modify: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java` - Create: `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ThreadStatusActivity.java` - Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ConversationInfoActivityTest.java` - Test: `/Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ThreadStatusActivityTest.java` - [ ] **Step 1: 写失败测试,锁住入口和渲染** ```java @Test public void conversationInfoShowsThreadStatusEntryForThreadConversation() { BossUi.ViewNode root = renderConversationInfoForThread(); assertTrue(viewTreeContainsText(root, "线程状态")); } @Test public void threadStatusActivityRendersCurrentGoalProgressAndNextStep() { BossUi.ViewNode root = renderThreadStatusActivityWithFixture(); assertTrue(viewTreeContainsText(root, "当前目标")); assertTrue(viewTreeContainsText(root, "当前进度")); assertTrue(viewTreeContainsText(root, "建议下一步")); } ``` - [ ] **Step 2: 跑测试,确认先失败** Run: ```bash cd /Users/kris/code/boss/android && ./gradlew testDebugUnitTest --tests com.hyzq.boss.ConversationInfoActivityTest --tests com.hyzq.boss.ThreadStatusActivityTest --no-daemon ``` Expected: - FAIL,提示没有 `线程状态` 入口或 Activity 不存在 - [ ] **Step 3: 实现 Android 入口与只读页** 在 `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java` 增加: ```java public JSONObject getThreadStatus(String projectId) throws IOException, ApiException { return getJson("/api/v1/projects/" + Uri.encode(projectId) + "/thread-status"); } ``` 在 `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java` 中,当当前会话是线程会话时增加: ```java addMenuRow(container, "线程状态", v -> { Intent intent = new Intent(this, ThreadStatusActivity.class); intent.putExtra("projectId", projectId); startActivity(intent); }); ``` 创建 `/Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ThreadStatusActivity.java`,读取接口并展示: ```java renderSection("当前目标", document.optString("projectGoal")); renderSection("当前阶段", document.optString("currentPhase")); renderSection("当前进度", document.optString("currentProgress")); renderSection("技术架构", document.optString("technicalArchitecture")); renderSection("当前阻塞", document.optString("currentBlockers")); renderSection("建议下一步", document.optString("recommendedNextStep")); renderEvents(recentProgressEvents); ``` - [ ] **Step 4: 重新跑测试,确认通过** Run: ```bash cd /Users/kris/code/boss/android && ./gradlew testDebugUnitTest --tests com.hyzq.boss.ConversationInfoActivityTest --tests com.hyzq.boss.ThreadStatusActivityTest --no-daemon ``` Expected: - PASS - [ ] **Step 5: 提交这一小步** ```bash git add /Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/BossApiClient.java /Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java /Users/kris/code/boss/android/app/src/main/java/com/hyzq/boss/ThreadStatusActivity.java /Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ConversationInfoActivityTest.java /Users/kris/code/boss/android/app/src/test/java/com/hyzq/boss/ThreadStatusActivityTest.java git commit -m "feat: add thread status view in android" ``` ### Task 6: 完整回归、文档同步与发版 **Files:** - Modify: `/Users/kris/code/boss/README.md` - Modify: `/Users/kris/code/boss/docs/architecture/current_runtime_and_deploy_status_cn.md` - Modify: `/Users/kris/code/boss/docs/architecture/api_and_service_inventory_cn.md` - [ ] **Step 1: 同步文档** 在文档里明确新增: ```md - 主 Agent 当前会优先读取线程状态文档和最近进展事件,而不是常态反复重跑完整理解 - 已导入设备与新导入设备都走统一的线程状态同步链 - 线程会话信息页新增只读 `线程状态` ``` - [ ] **Step 2: 跑完整关键回归** Run: ```bash npx --yes tsx --test /Users/kris/code/boss/tests/thread-status-sync.test.ts /Users/kris/code/boss/tests/device-import-draft.test.ts /Users/kris/code/boss/tests/master-agent-thread-status-prompt.test.ts /Users/kris/code/boss/tests/thread-status-route.test.ts npm run lint npm run build cd /Users/kris/code/boss/android && ./gradlew testDebugUnitTest --tests com.hyzq.boss.ConversationInfoActivityTest --tests com.hyzq.boss.ThreadStatusActivityTest --no-daemon cd /Users/kris/code/boss/android && ./gradlew assembleRelease --no-daemon ``` Expected: - 全部 PASS - build 成功 - Android release 包成功生成 - [ ] **Step 3: 部署服务器** Run: ```bash sshpass -p 'Asd123456.' ssh -o StrictHostKeyChecking=no ubuntu@106.53.170.158 "sudo rm -rf /opt/boss/.next && sudo mkdir -p /opt/boss/.next && sudo chown -R ubuntu:ubuntu /opt/boss /opt/boss/.next" sshpass -p 'Asd123456.' rsync -az --delete -e "ssh -o StrictHostKeyChecking=no" --exclude '.git/' --exclude 'node_modules/' --exclude 'data/' --exclude '.superpowers/' --exclude 'public/downloads/' /Users/kris/code/boss/ ubuntu@106.53.170.158:/opt/boss/ sshpass -p 'Asd123456.' ssh -o StrictHostKeyChecking=no ubuntu@106.53.170.158 "cd /opt/boss && sudo systemctl restart boss-web && sudo systemctl restart caddy && curl -fsS http://127.0.0.1:3000/api/health" curl -fsS https://boss.hyzq.net/api/health ``` Expected: - 远端本机健康检查返回 `ok:true` - 公网健康检查返回 `ok:true` - [ ] **Step 4: 最终提交** ```bash git add /Users/kris/code/boss/README.md /Users/kris/code/boss/docs/architecture/current_runtime_and_deploy_status_cn.md /Users/kris/code/boss/docs/architecture/api_and_service_inventory_cn.md git commit -m "feat: add thread status sync pipeline" git push gitea codex/wechat-native-ui-rollback ``` --- ## 自检 ### Spec 覆盖 - 线程状态文档:Task 1 - 线程进展事件:Task 1 / Task 2 - 主 Agent 读取“文档 + 最近事件”:Task 3 - 关键时刻深拉保留:Task 2 / Task 3 - APP 只读查看线程状态:Task 4 / Task 5 - 不写入项目仓库:通过 Task 1-5 全部走 Boss 内部状态层实现 ### Placeholder 扫描 - 没有 `TBD / TODO / implement later` - 每个任务都给了文件、代码、命令和预期结果 ### 类型一致性 - 线程状态文档统一命名为 `ThreadStatusDocument` - 增量事件统一命名为 `ThreadProgressEvent` - API 字段统一用 `threadStatusDocument / recentProgressEvents`