From 8e12fa1e8c16ad745474cbb517d10a6ad730f640 Mon Sep 17 00:00:00 2001 From: kris Date: Sat, 4 Apr 2026 10:47:47 +0800 Subject: [PATCH] docs: add thread status sync implementation plan --- ...6-04-04-master-agent-thread-status-sync.md | 785 ++++++++++++++++++ 1 file changed, 785 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-04-master-agent-thread-status-sync.md diff --git a/docs/superpowers/plans/2026-04-04-master-agent-thread-status-sync.md b/docs/superpowers/plans/2026-04-04-master-agent-thread-status-sync.md new file mode 100644 index 0000000..84ed70a --- /dev/null +++ b/docs/superpowers/plans/2026-04-04-master-agent-thread-status-sync.md @@ -0,0 +1,785 @@ +# 主 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` +