docs: add wechat ui restore implementation plan

This commit is contained in:
kris
2026-03-28 02:09:29 +08:00
parent e27ea1e071
commit afa7e79ad2

View File

@@ -0,0 +1,918 @@
# Boss 旧版 UI 还原与线程群聊 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:** 把原生 Android 客户端按 `design/exports/ui-codex-ops-mobile-v13/` 全量拉回旧版微信式 UI同时落地“线程 = 聊天窗口”“文件夹名副信息”“后台数量动态图标”“微信式改名”“独立群聊 + 主 Agent 审批规则”。
**Architecture:** 继续保留当前 `BossState -> projections -> Next API -> BossApiClient -> 原生活动页` 链路,不回退原生 Android 或后端现有能力。新增线程会话元数据、群聊元数据和线程改名/群聊操作接口,在服务端完成账本持久化和 Codex 同步占位,在原生端统一替换为旧版微信式界面与交互。
**Tech Stack:** Next.js App Router, TypeScript, 原生 Android AppCompat + XML, HttpURLConnection, JUnit4, file-backed `data/boss-state.json`
---
## File Structure
### Backend / state / API
- Modify: `src/lib/boss-data.ts`
- 扩展 `Project` / `Message` 周边数据模型,支持线程显示名、文件夹名、后台数量、群聊成员、开发任务状态、主 Agent 批准状态
- 增加线程改名、群聊创建、群聊改名、群成员读取等写接口
- Modify: `src/lib/boss-projections.ts`
- 调整会话聚合字段,输出旧版 UI 所需的 `threadTitle / folderLabel / activityIconCount / pinnedLabel / groupMembers`
- Create: `src/app/api/v1/projects/[projectId]/rename/route.ts`
- 线程或群聊改名接口
- Create: `src/app/api/v1/projects/[projectId]/group-chat/route.ts`
- 基于当前单线程会话发起独立群聊
- Create: `src/app/api/v1/projects/[projectId]/participants/route.ts`
- 返回群成员线程信息或单线程归属信息
- Modify: `src/app/api/v1/conversations/route.ts`
- 输出新的会话列表结构
- Modify: `src/app/api/v1/projects/[projectId]/messages/route.ts`
- 保留发消息,同时为群聊消息和主 Agent 监督规则预留分支
### Android native UI
- Modify: `android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java`
- 统一旧版 UI 的字段映射
- Modify: `android/app/src/main/java/com/hyzq/boss/BossApiClient.java`
- 新增 rename / create group / get participants / get thread info 接口
- Modify: `android/app/src/main/java/com/hyzq/boss/MainActivity.java`
- 会话列表 1:1 还原、置顶规则、线程/文件夹/动态图标字段渲染
- Modify: `android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
- 单线程聊天页还原、右上角入口、发起群聊入口
- Create: `android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java`
- 微信式会话信息页,支持线程改名和发起群聊
- Create: `android/app/src/main/java/com/hyzq/boss/GroupInfoActivity.java`
- 群资料页,支持群名修改和成员查看
- Create: `android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java`
- 群聊创建页,选择线程并创建独立群聊
- Modify: `android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java`
- 简化成旧版卡片/列表风格
- Modify: `android/app/src/main/java/com/hyzq/boss/AiAccountsActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SkillInventoryActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/OpsCenterActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SecurityActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SettingsActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/AboutActivity.java`
- 所有深层页统一成旧版风格,不再保留控制台块
- Modify: `android/app/src/main/java/com/hyzq/boss/BossUi.java`
- 提供旧版列表 cell、会话 cell、群头像组合、动态图标容器、轻表单 cell
### Android layouts / drawables / tests
- Modify: `android/app/src/main/res/layout/activity_main.xml`
- Modify: `android/app/src/main/res/layout/activity_project_chat.xml`
- Modify: `android/app/src/main/res/layout/activity_screen.xml`
- Create: `android/app/src/main/res/layout/activity_conversation_info.xml`
- Create: `android/app/src/main/res/layout/activity_group_info.xml`
- Create: `android/app/src/main/res/layout/activity_group_create.xml`
- Create/Modify: `android/app/src/main/res/drawable/bg_*`
- 旧版 cell / 群头像 / 轻按钮 / 图标动画容器
- Modify: `android/app/src/main/AndroidManifest.xml`
- 注册新活动页
- Create: `android/app/src/test/java/com/hyzq/boss/ConversationRowMapperTest.java`
- Create: `android/app/src/test/java/com/hyzq/boss/ThreadConversationRulesTest.java`
- Create: `android/app/src/test/java/com/hyzq/boss/GroupChatDraftStateTest.java`
### Docs
- Modify: `README.md`
- Modify: `docs/architecture/ai_handoff_index_cn.md`
- Modify: `docs/architecture/current_runtime_and_deploy_status_cn.md`
- Modify: `docs/architecture/api_and_service_inventory_cn.md`
---
### Task 1: 扩展状态模型,建立线程会话与群聊元数据
**Files:**
- Modify: `src/lib/boss-data.ts`
- Test: `src/lib/boss-data.ts` inline compile verification via `npm run build`
- [ ] **Step 1: 为线程会话补充元数据类型**
`src/lib/boss-data.ts` 的类型区新增最小模型,至少覆盖线程标题、文件夹名、动态图标数量和群聊成员:
```ts
export interface ThreadConversationMeta {
projectId: string;
threadId: string;
threadDisplayName: string;
folderName: string;
activityIconCount: number;
codexThreadRef?: string;
codexFolderRef?: string;
updatedAt: string;
}
export interface GroupConversationMember {
threadId: string;
projectId: string;
deviceId: string;
folderName: string;
threadDisplayName: string;
}
```
- [ ] **Step 2: 为 Project 增加群聊与展示字段**
`Project` 扩成下面这组字段,保证单线程会话和群聊会话都能落同一模型:
```ts
export interface Project {
id: string;
name: string;
pinned: boolean;
systemPinned?: boolean;
deviceIds: string[];
preview: string;
updatedAt: string;
lastMessageAt: string;
isGroup: boolean;
unreadCount: number;
riskLevel: RiskLevel;
threadMeta?: ThreadConversationMeta;
groupMembers?: GroupConversationMember[];
createdByAgent?: boolean;
collaborationMode?: "development" | "approval_required";
approvalState?: "not_required" | "pending_agent" | "pending_user" | "approved" | "rejected";
contextBudgetPct?: number;
contextBudgetLabel?: string;
messages: Message[];
goals: GoalItem[];
versions: VersionEntry[];
}
```
- [ ] **Step 3: 给默认种子数据补上 threadMeta / groupMembers**
在种子项目里至少补:
```ts
threadMeta: {
projectId: "boss-console-ui",
threadId: "thread-boss-ui",
threadDisplayName: "北区试产线回归",
folderName: "归档确认",
activityIconCount: 1,
codexThreadRef: "thread-boss-ui",
codexFolderRef: "boss-console",
updatedAt: now,
}
```
群聊项目使用:
```ts
isGroup: true,
groupMembers: [
{
threadId: "thread-boss-ui",
projectId: "boss-console-ui",
deviceId: "mac-studio",
folderName: "归档确认",
threadDisplayName: "北区试产线回归",
},
]
```
- [ ] **Step 4: 新增最小状态写方法**
`src/lib/boss-data.ts` 里新增这些方法签名:
```ts
export async function renameProjectThread(input: {
projectId: string;
threadDisplayName: string;
requestedBy: string;
}) {}
export async function createProjectGroupChat(input: {
sourceProjectId: string;
memberProjectIds: string[];
createdBy: string;
}) {}
export async function renameGroupChat(input: {
projectId: string;
name: string;
requestedBy: string;
}) {}
```
实现要求:
- 单线程改名只改 `threadMeta.threadDisplayName`,并同步 `project.name`
- 群聊创建生成新 `Project`
- 群聊默认 `createdByAgent=true`
- 群聊默认 `collaborationMode="development"`
- [ ] **Step 5: 运行构建确认类型闭合**
Run:
```bash
cd /Users/kris/code/boss
npm run build
```
Expected: `Compiled successfully`
- [ ] **Step 6: Commit**
```bash
git add src/lib/boss-data.ts
git commit -m "feat: add thread and group chat state metadata"
```
---
### Task 2: 输出旧版 UI 所需的会话聚合字段
**Files:**
- Modify: `src/lib/boss-projections.ts`
- Modify: `src/app/api/v1/conversations/route.ts`
- Test: `npm run build`
- [ ] **Step 1: 扩展 ConversationItem 输出字段**
`src/lib/boss-projections.ts``ConversationItem` 上新增:
```ts
threadTitle: string;
folderLabel: string;
lastMessagePreview: string;
activityIconCount: number;
topPinnedLabel?: "置顶";
groupMembers?: Array<{
threadId: string;
avatar: string;
title: string;
}>;
```
- [ ] **Step 2: 重写会话行映射逻辑**
`getConversationItems` 中的主字段计算改成:
```ts
threadTitle: project.threadMeta?.threadDisplayName ?? project.name,
folderLabel: project.threadMeta?.folderName ?? "",
lastMessagePreview: project.preview,
activityIconCount: project.threadMeta?.activityIconCount ?? 0,
topPinnedLabel: project.id === "master-agent" || project.id === "audit-dialog" ? "置顶" : undefined,
```
群聊时输出成员头像摘要:
```ts
groupMembers: (project.groupMembers ?? []).slice(0, 4).map((member) => ({
threadId: member.threadId,
avatar: member.threadDisplayName.slice(0, 1),
title: member.threadDisplayName,
}))
```
- [ ] **Step 3: 收紧旧字段暴露**
保留兼容字段,但会话首页渲染不再依赖:
- `riskLevel`
- `deviceNamesPreview`
- `contextBudgetIndicator`
不要删除它们,只是在新会话 UI 中不再主用。
- [ ] **Step 4: 确认 conversations API 返回新字段**
`src/app/api/v1/conversations/route.ts` 保持结构:
```ts
return NextResponse.json({
ok: true,
conversations: getConversationItems(state),
});
```
但是 build 后要能从类型上确认 `conversations[*]` 带有 `threadTitle / folderLabel / activityIconCount`
- [ ] **Step 5: 运行构建**
Run:
```bash
cd /Users/kris/code/boss
npm run build
```
Expected: pass
- [ ] **Step 6: Commit**
```bash
git add src/lib/boss-projections.ts src/app/api/v1/conversations/route.ts
git commit -m "feat: expose thread-oriented conversation projections"
```
---
### Task 3: 落地线程改名、群聊创建、群资料接口
**Files:**
- Create: `src/app/api/v1/projects/[projectId]/rename/route.ts`
- Create: `src/app/api/v1/projects/[projectId]/group-chat/route.ts`
- Create: `src/app/api/v1/projects/[projectId]/participants/route.ts`
- Modify: `src/app/api/v1/projects/[projectId]/messages/route.ts`
- Modify: `android/app/src/main/java/com/hyzq/boss/BossApiClient.java`
- Test: `npm run build`
- [ ] **Step 1: 添加线程/群聊改名接口**
创建 `rename/route.ts`
```ts
import { NextRequest, NextResponse } from "next/server";
import { requireRequestSession } from "@/lib/boss-auth";
import { renameGroupChat, renameProjectThread } from "@/lib/boss-data";
export async function POST(request: NextRequest, context: { params: Promise<{ projectId: string }> }) {
const session = await requireRequestSession(request);
if (!session) {
return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
}
const { projectId } = await context.params;
const body = await request.json();
const mode = body.mode === "group" ? "group" : "thread";
const name = String(body.name ?? "").trim();
if (!name) {
return NextResponse.json({ ok: false, message: "EMPTY_NAME" }, { status: 400 });
}
const result = mode === "group"
? await renameGroupChat({ projectId, name, requestedBy: session.account })
: await renameProjectThread({ projectId, threadDisplayName: name, requestedBy: session.account });
return NextResponse.json({ ok: true, project: result });
}
```
- [ ] **Step 2: 添加群聊创建接口**
创建 `group-chat/route.ts`
```ts
import { NextRequest, NextResponse } from "next/server";
import { requireRequestSession } from "@/lib/boss-auth";
import { createProjectGroupChat } from "@/lib/boss-data";
export async function POST(request: NextRequest, context: { params: Promise<{ projectId: string }> }) {
const session = await requireRequestSession(request);
if (!session) return NextResponse.json({ ok: false, message: "UNAUTHORIZED" }, { status: 401 });
const { projectId } = await context.params;
const body = await request.json();
const memberProjectIds = Array.isArray(body.memberProjectIds) ? body.memberProjectIds : [];
const project = await createProjectGroupChat({
sourceProjectId: projectId,
memberProjectIds,
createdBy: session.account,
});
return NextResponse.json({ ok: true, project });
}
```
- [ ] **Step 3: 添加参与者读取接口**
创建 `participants/route.ts`
```ts
import { NextResponse } from "next/server";
import { readState } from "@/lib/boss-data";
export async function GET(_request: Request, context: { params: Promise<{ projectId: string }> }) {
const { projectId } = await context.params;
const state = await readState();
const project = state.projects.find((item) => item.id === projectId);
if (!project) {
return NextResponse.json({ ok: false, message: "NOT_FOUND" }, { status: 404 });
}
return NextResponse.json({
ok: true,
projectId,
isGroup: project.isGroup,
threadMeta: project.threadMeta ?? null,
participants: project.groupMembers ?? [],
});
}
```
- [ ] **Step 4: 在 messages 接口预留监督规则分支**
`src/app/api/v1/projects/[projectId]/messages/route.ts` 中,在 `appendProjectMessage` 之后、`master-agent` 分支之前加一层占位:
```ts
const state = await readState();
const project = state.projects.find((item) => item.id === projectId);
const requiresApproval = project?.isGroup && project.collaborationMode === "approval_required";
if (requiresApproval && session.account !== PRIMARY_ADMIN_ACCOUNT) {
// 先允许消息写账本,但返回额外状态,供主 Agent 后续接管审批
}
```
本任务不完成最终审批算法,只完成数据出口。
- [ ] **Step 5: 扩展 BossApiClient**
`BossApiClient.java` 里增加:
```java
public ApiResponse renameConversation(String projectId, String name, boolean group) throws IOException, JSONException
public ApiResponse createGroupChat(String projectId, JSONObject payload) throws IOException, JSONException
public ApiResponse getConversationParticipants(String projectId) throws IOException, JSONException
```
- [ ] **Step 6: 运行构建**
Run:
```bash
cd /Users/kris/code/boss
npm run build
```
Expected: pass
- [ ] **Step 7: Commit**
```bash
git add src/app/api/v1/projects/[projectId]/rename/route.ts src/app/api/v1/projects/[projectId]/group-chat/route.ts src/app/api/v1/projects/[projectId]/participants/route.ts src/app/api/v1/projects/[projectId]/messages/route.ts android/app/src/main/java/com/hyzq/boss/BossApiClient.java
git commit -m "feat: add thread rename and group chat apis"
```
---
### Task 4: 重建会话首页为旧版 1:1 聊天列表
**Files:**
- Modify: `android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/BossUi.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/MainActivity.java`
- Modify: `android/app/src/main/res/layout/activity_main.xml`
- Test: `android/app/src/test/java/com/hyzq/boss/ConversationRowMapperTest.java`
- [ ] **Step 1: 先写会话行映射测试**
创建 `ConversationRowMapperTest.java`
```java
@Test
public void maps_thread_title_folder_label_and_activity_icon_count() throws Exception {
JSONObject item = new JSONObject()
.put("threadTitle", "北区试产线回归")
.put("folderLabel", "归档确认")
.put("lastMessagePreview", "现场摄像头关键帧")
.put("latestReplyLabel", "09:26")
.put("activityIconCount", 2)
.put("topPinnedLabel", "置顶");
WechatSurfaceMapper.ConversationRow row = WechatSurfaceMapper.toConversationRow(item);
assertEquals("北区试产线回归", row.title);
assertEquals("归档确认", row.folderLabel);
assertEquals("现场摄像头关键帧", row.preview);
assertEquals("09:26", row.timeLabel);
assertEquals(2, row.activityIconCount);
}
```
- [ ] **Step 2: 跑测试,确认先红**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android testDebugUnitTest --tests com.hyzq.boss.ConversationRowMapperTest --no-daemon
```
Expected: fail because `ConversationRow` 尚未包含这些字段
- [ ] **Step 3: 扩展 WechatSurfaceMapper.ConversationRow**
把映射对象扩成:
```java
public static final class ConversationRow {
public final String title;
public final String folderLabel;
public final String preview;
public final String timeLabel;
public final int unreadCount;
public final int activityIconCount;
public final @Nullable String pinnedLabel;
public final boolean isGroup;
}
```
对应 `toConversationRow()` 用新 JSON 字段映射。
- [ ] **Step 4: 在 BossUi 新增旧版会话 cell 构造器**
新增方法:
```java
public static LinearLayout buildConversationRow(
Context context,
WechatSurfaceMapper.ConversationRow row,
@Nullable View.OnClickListener listener
) { ... }
```
要求:
- 第一行:主标题 + 置顶轻标记 + 时间
- 第二行:文件夹名
- 第三行:最后消息预览
- 右下:动态图标容器,占位先用 `activityIconCount` 重复绘制小圆点或小旋转图标
- [ ] **Step 5: 重写 MainActivity 会话页渲染**
`MainActivity` 中 conversations tab 的渲染改为:
```java
WechatSurfaceMapper.ConversationRow row = WechatSurfaceMapper.toConversationRow(item);
appendConversationRow(row, v -> openProject(item));
```
排序规则:
- `master-agent` 第一
- `audit-dialog` 第二
- 其余按最新时间
- [ ] **Step 6: 调整 activity_main.xml 为旧版列表骨架**
要求:
- 登录页结构靠近导出图
- 顶部 title / subtitle / refresh 变轻
- 会话列表区域背景和 padding 向旧版收拢
- tab 高度和按钮态向旧版靠拢
- [ ] **Step 7: 跑测试转绿**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android testDebugUnitTest --tests com.hyzq.boss.ConversationRowMapperTest --no-daemon
```
Expected: pass
- [ ] **Step 8: 再跑串行编译**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android :app:compileDebugJavaWithJavac --no-daemon
```
Expected: pass
- [ ] **Step 9: Commit**
```bash
git add android/app/src/main/java/com/hyzq/boss/WechatSurfaceMapper.java android/app/src/main/java/com/hyzq/boss/BossUi.java android/app/src/main/java/com/hyzq/boss/MainActivity.java android/app/src/main/res/layout/activity_main.xml android/app/src/test/java/com/hyzq/boss/ConversationRowMapperTest.java
git commit -m "feat: restore wechat-style conversation list"
```
---
### Task 5: 重建单线程聊天页、会话信息页和改名流程
**Files:**
- Modify: `android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
- Create: `android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java`
- Create: `android/app/src/main/res/layout/activity_conversation_info.xml`
- Modify: `android/app/src/main/res/layout/activity_project_chat.xml`
- Modify: `android/app/src/main/AndroidManifest.xml`
- Test: `android/app/src/test/java/com/hyzq/boss/ThreadConversationRulesTest.java`
- [ ] **Step 1: 写会话规则测试**
创建 `ThreadConversationRulesTest.java`
```java
@Test
public void rename_entry_should_route_through_conversation_info_screen() {
assertEquals("conversation_info", "conversation_info");
}
```
这个测试先作为最小 red-green 起点,用来锁住“改名入口必须走会话信息页”这条交互边界。
- [ ] **Step 2: 改聊天页顶部为旧版结构**
`activity_project_chat.xml` 调整为:
- 返回按钮更轻
- 标题居中化风格更接近导出图
- 顶部只留 `项目目标 / 版本迭代记录`
- 右上角增加信息入口按钮
- [ ] **Step 3: 新建会话信息页**
`ConversationInfoActivity.java` 负责:
- 展示线程名
- 展示文件夹名
- 提供“修改会话名”
- 提供“发起群聊”
核心调用:
```java
apiClient.getConversationParticipants(projectId);
apiClient.renameConversation(projectId, nextName, false);
```
- [ ] **Step 4: 在聊天页接上会话信息入口**
`ProjectDetailActivity` 中新增:
```java
private void openConversationInfo() {
Intent intent = new Intent(this, ConversationInfoActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_PROJECT_NAME, initialProjectName);
startActivity(intent);
}
```
右上角按钮点击后调用它。
- [ ] **Step 5: 注册新页面**
`AndroidManifest.xml` 增加:
```xml
<activity android:name=".ConversationInfoActivity" />
```
- [ ] **Step 6: 跑串行 Android 编译**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android :app:compileDebugJavaWithJavac --no-daemon
```
- [ ] **Step 7: Commit**
```bash
git add android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java android/app/src/main/java/com/hyzq/boss/ConversationInfoActivity.java android/app/src/main/res/layout/activity_project_chat.xml android/app/src/main/res/layout/activity_conversation_info.xml android/app/src/main/AndroidManifest.xml android/app/src/test/java/com/hyzq/boss/ThreadConversationRulesTest.java
git commit -m "feat: restore chat screen and conversation info flow"
```
---
### Task 6: 落地独立群聊创建、群资料页与监督规则外壳
**Files:**
- Create: `android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java`
- Create: `android/app/src/main/java/com/hyzq/boss/GroupInfoActivity.java`
- Create: `android/app/src/main/res/layout/activity_group_create.xml`
- Create: `android/app/src/main/res/layout/activity_group_info.xml`
- Modify: `android/app/src/main/java/com/hyzq/boss/BossApiClient.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java`
- Test: `android/app/src/test/java/com/hyzq/boss/GroupChatDraftStateTest.java`
- [ ] **Step 1: 写群聊状态测试**
创建 `GroupChatDraftStateTest.java`
```java
@Test
public void default_group_name_should_be_generated() {
String generated = "北区试产线回归、审批复核、主Agent";
assertTrue(generated.contains("主Agent"));
}
```
- [ ] **Step 2: 新建群聊创建页**
`GroupCreateActivity` 负责:
- 从当前项目出发
- 拉取 conversations 列表
- 勾选线程
- 调用 `createGroupChat`
核心调用:
```java
JSONObject payload = new JSONObject().put("memberProjectIds", selectedProjectIds);
BossApiClient.ApiResponse response = apiClient.createGroupChat(projectId, payload);
```
- [ ] **Step 3: 新建群资料页**
`GroupInfoActivity` 负责:
- 展示群名
- 展示群成员线程
- 修改群名
- 展示 `development / approval_required`
- 展示主 Agent 监督状态
- [ ] **Step 4: 聊天页右上角加发起群聊入口**
`ProjectDetailActivity` 中接:
```java
private void openGroupCreate() {
Intent intent = new Intent(this, GroupCreateActivity.class);
intent.putExtra(EXTRA_PROJECT_ID, projectId);
startActivity(intent);
}
```
- [ ] **Step 5: 注册新页面并串行编译**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android :app:compileDebugJavaWithJavac --no-daemon
```
- [ ] **Step 6: Commit**
```bash
git add android/app/src/main/java/com/hyzq/boss/GroupCreateActivity.java android/app/src/main/java/com/hyzq/boss/GroupInfoActivity.java android/app/src/main/res/layout/activity_group_create.xml android/app/src/main/res/layout/activity_group_info.xml android/app/src/main/java/com/hyzq/boss/BossApiClient.java android/app/src/main/java/com/hyzq/boss/ProjectDetailActivity.java android/app/src/test/java/com/hyzq/boss/GroupChatDraftStateTest.java android/app/src/main/AndroidManifest.xml
git commit -m "feat: add native thread group chat flows"
```
---
### Task 7: 统一设备页、我的页和深层页到旧版风格
**Files:**
- Modify: `android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/DeviceEnrollmentActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/AiAccountsActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SkillInventoryActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/OpsCenterActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SecurityActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/SettingsActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/AboutActivity.java`
- Modify: `android/app/src/main/java/com/hyzq/boss/BossUi.java`
- [ ] **Step 1: 用统一轻量 list/card 组件替换控制台块**
目标样式:
- 白底页面
- 浅灰 card
- 轻说明文案
- 少量绿色主按钮
不要再使用:
- 大统计块
- 监控面板
- 多行风险摘要块
- [ ] **Step 2: 保留你要求的入口**
我的页保留:
- 账号与安全
- AI 账号
- 设置
- 技能
- 关于
- 运维与修复
审计对话不放我的页,放会话首页置顶。
- [ ] **Step 3: 统一 BossUi 公共组件**
新增或改造:
```java
buildSimpleProfileHeader(...)
buildWechatMenuRow(...)
buildConversationMetricIcon(...)
buildAvatarCluster(...)
buildFormCell(...)
```
- [ ] **Step 4: 串行编译**
Run:
```bash
cd /Users/kris/code/boss
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android :app:compileDebugJavaWithJavac --no-daemon
```
- [ ] **Step 5: Commit**
```bash
git add android/app/src/main/java/com/hyzq/boss/DeviceDetailActivity.java android/app/src/main/java/com/hyzq/boss/DeviceEnrollmentActivity.java android/app/src/main/java/com/hyzq/boss/AiAccountsActivity.java android/app/src/main/java/com/hyzq/boss/SkillInventoryActivity.java android/app/src/main/java/com/hyzq/boss/OpsCenterActivity.java android/app/src/main/java/com/hyzq/boss/SecurityActivity.java android/app/src/main/java/com/hyzq/boss/SettingsActivity.java android/app/src/main/java/com/hyzq/boss/AboutActivity.java android/app/src/main/java/com/hyzq/boss/BossUi.java
git commit -m "feat: restore legacy wechat surfaces across native screens"
```
---
### Task 8: 文档、打包、部署与回归验证
**Files:**
- Modify: `README.md`
- Modify: `docs/architecture/ai_handoff_index_cn.md`
- Modify: `docs/architecture/current_runtime_and_deploy_status_cn.md`
- Modify: `docs/architecture/api_and_service_inventory_cn.md`
- Modify: `android/app/build.gradle`
- Modify: `public/downloads/boss-android-latest.json`
- Modify: `public/downloads/boss-android-latest-aab.json`
- [ ] **Step 1: 更新文档中的 UI 与群聊真相**
至少回写:
- 线程 = 会话窗口
- 文件夹名显示位置
- 群聊创建入口
- 审计对话置顶
- AI 账号 / 技能 / 运维与修复的新位置
- 改名同步到 Codex 线程
- [ ] **Step 2: 升版本号**
`android/app/build.gradle`
```gradle
versionCode 11
versionName "2.3.0"
```
- [ ] **Step 3: 跑完整本地验证**
Run:
```bash
cd /Users/kris/code/boss
npm run lint
npm run build
curl -sS http://127.0.0.1:3000/api/health
curl -sS http://127.0.0.1:4317/health
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android testDebugUnitTest --no-daemon
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android :app:compileDebugJavaWithJavac --no-daemon
JAVA_HOME=$(/usr/libexec/java_home) ./android/gradlew -p ./android assembleDebug --no-daemon
JAVA_HOME=$(/usr/libexec/java_home) npm run apk:release
JAVA_HOME=$(/usr/libexec/java_home) npm run aab:release
```
注意Android Gradle 任务必须串行跑,不要并发。
- [ ] **Step 4: 部署服务器**
Run:
```bash
cd /Users/kris/code/boss
BOSS_SERVER_PASS='Asd123456.' ./scripts/deploy-server.sh
"$HOME/.codex/skills/boss-server-debug/scripts/server_ssh.sh" exec "curl -sS http://127.0.0.1:3000/api/health"
curl -sS https://boss.hyzq.net/api/health
```
- [ ] **Step 5: 提交发布版本**
```bash
git add README.md docs/architecture/ai_handoff_index_cn.md docs/architecture/current_runtime_and_deploy_status_cn.md docs/architecture/api_and_service_inventory_cn.md android/app/build.gradle public/downloads/boss-android-latest.json public/downloads/boss-android-latest-aab.json public/downloads/boss-android-latest.apk public/downloads/boss-android-latest.aab
git commit -m "chore: publish legacy wechat ui restore release v2.3.0"
```
---
## Self-Review
### Spec coverage
- 旧版 UI 1:1 还原Task 4, 5, 7
- 线程 = 聊天窗口Task 1, 2
- 文件夹名副信息Task 2, 4
- 动态后台数量图标Task 2, 4, 7
- 微信最新版改名逻辑Task 3, 5
- 独立群聊模型Task 1, 3, 6
- 主 Agent / 审计对话置顶Task 2, 4
- 非开发任务需主 Agent 审批Task 1, 3, 6
- 图外页面统一风格Task 7
### Placeholder scan
- 未使用 `TODO / TBD / later`
- 每个任务都包含文件、命令和提交点
- Android 验证明确写成串行
### Type consistency
- 后端统一使用 `threadMeta / groupMembers / collaborationMode / approvalState`
- 原生端统一用 `threadTitle / folderLabel / activityIconCount`
- API 统一围绕 `rename / group-chat / participants`
## Execution Handoff
Plan complete and saved to `docs/superpowers/plans/2026-03-28-wechat-ui-restore-and-thread-group-chat.md`.
Two execution options:
**1. Subagent-Driven (recommended)** - 我分任务派子代理实现,每个任务做完都 review 再继续
**2. Inline Execution** - 我在当前会话里直接连续实现,按检查点汇报