feat: overhaul task board and cross-conversation workflows
This commit is contained in:
3
.trellis/tasks/08-11-task-board/check.jsonl
Normal file
3
.trellis/tasks/08-11-task-board/check.jsonl
Normal file
@@ -0,0 +1,3 @@
|
||||
{"file":".trellis/spec/backend/quality-guidelines.md","reason":"检查后端实现的兼容性、错误边界和可维护性"}
|
||||
{"file":".trellis/spec/frontend/quality-guidelines.md","reason":"检查任务看板视图的可用性和回归风险"}
|
||||
{"file":".trellis/tasks/08-11-task-board/research/integration-contract.md","reason":"验证跨模块契约、优先级与文件边界没有漂移"}
|
||||
3
.trellis/tasks/08-11-task-board/implement.jsonl
Normal file
3
.trellis/tasks/08-11-task-board/implement.jsonl
Normal file
@@ -0,0 +1,3 @@
|
||||
{"file":".trellis/spec/backend/index.md","reason":"遵循项目后端模块、错误处理和质量约束入口"}
|
||||
{"file":".trellis/spec/frontend/index.md","reason":"遵循项目现有前端结构与交互约束入口"}
|
||||
{"file":".trellis/tasks/08-11-task-board/research/integration-contract.md","reason":"三个并行实现必须共享同一数据、状态、错误码和文件边界契约"}
|
||||
195
.trellis/tasks/08-11-task-board/info.md
Normal file
195
.trellis/tasks/08-11-task-board/info.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# 技术设计与并行边界
|
||||
|
||||
## 共享模型
|
||||
|
||||
会话 JSON 新增可选字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"taskTracking": {
|
||||
"enabled": true,
|
||||
"statusId": "in_progress",
|
||||
"baseStatus": "in_progress",
|
||||
"source": "user",
|
||||
"reason": "",
|
||||
"summary": "",
|
||||
"progress": null,
|
||||
"reportingStatus": "reported",
|
||||
"version": 1,
|
||||
"enabledAt": "ISO-8601",
|
||||
"disabledAt": null,
|
||||
"statusUpdatedAt": "ISO-8601",
|
||||
"completedAt": null,
|
||||
"archivedAt": null,
|
||||
"archivedBy": null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
状态定义:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "waiting_deploy",
|
||||
"label": "等待部署",
|
||||
"baseStatus": "waiting_user",
|
||||
"description": "实现完成,等待部署环境或发布窗口",
|
||||
"color": "#f59e0b",
|
||||
"order": 40,
|
||||
"system": false,
|
||||
"enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
## 服务契约
|
||||
|
||||
MCP 对话负责产出 `lib/task-board-service.js`,导出:
|
||||
|
||||
```text
|
||||
createTaskBoardService(deps)
|
||||
.getStatusDefinitions()
|
||||
.upsertStatusDefinition(input, actor)
|
||||
.removeStatusDefinition(id, migrateTo, actor)
|
||||
.listTasks(filters)
|
||||
.setTracking(sessionId, enabled, actor)
|
||||
.updateStatus(sessionId, update, actor)
|
||||
.setArchived(sessionId, archived, actor)
|
||||
.recordLifecycleEvent(sessionId, event)
|
||||
```
|
||||
|
||||
服务通过依赖注入读取/保存会话和状态配置,不直接 import `server.js`。所有修改使用版本号和统一校验。
|
||||
|
||||
## WebSocket 契约
|
||||
|
||||
客户端请求:
|
||||
|
||||
- `task_board_query`
|
||||
- `task_tracking_set`
|
||||
- `task_status_set`
|
||||
- `task_status_definition_upsert`
|
||||
- `task_status_definition_remove`
|
||||
- `task_archive_set`
|
||||
|
||||
服务端响应/广播:
|
||||
|
||||
- `task_board_result`
|
||||
- `task_board_event`
|
||||
- `task_tracking_result`
|
||||
- `task_status_result`
|
||||
- `task_status_definitions_result`
|
||||
- `task_archive_result`
|
||||
|
||||
所有请求携带 `requestId`;所有写响应返回规范化任务、状态定义或稳定错误码。
|
||||
|
||||
## MCP 契约
|
||||
|
||||
### ccweb_task_status_list
|
||||
|
||||
无业务参数;来源会话从 MCP 上下文解析。返回 `trackingEnabled`、当前状态和状态定义。
|
||||
|
||||
### ccweb_task_update
|
||||
|
||||
```json
|
||||
{
|
||||
"statusId": "in_progress",
|
||||
"reason": "可选,最长 2000 字符",
|
||||
"summary": "可选,最长 4000 字符",
|
||||
"progress": 0
|
||||
}
|
||||
```
|
||||
|
||||
`progress` 范围 0-100。跟踪关闭返回 `task_tracking_disabled`,未知状态返回 `task_status_unknown`。
|
||||
|
||||
## 生命周期契约
|
||||
|
||||
Hook 模块只接收事实事件,不自行读写文件:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "turn_completed",
|
||||
"turnId": "可选",
|
||||
"occurredAt": "ISO-8601",
|
||||
"outcome": "completed",
|
||||
"pendingUserInput": false,
|
||||
"hadTaskStatusUpdate": false,
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
规则:
|
||||
|
||||
- 未开启跟踪:忽略。
|
||||
- 用户消息:若归档则取消归档;状态进入 `in_progress`。
|
||||
- turn started:非终态进入 `in_progress`。
|
||||
- structured user input:进入 `waiting_user`。
|
||||
- turn failed:进入 `blocked` 并记录错误。
|
||||
- turn completed 且本轮无 MCP:保持状态,设置 `reportingStatus=missing`。
|
||||
- 本轮已有 MCP:不得被 Hook 覆盖。
|
||||
|
||||
## 并行文件所有权
|
||||
|
||||
### 前端对话(只允许修改)
|
||||
|
||||
- `public/task-board.js`
|
||||
- `public/task-board.css`
|
||||
- `scripts/task-board-frontend-unit.js`
|
||||
|
||||
不得修改:`public/index.html`、`public/app.js`、`public/style.css`、`server.js`、`scripts/regression.js`。
|
||||
|
||||
### MCP/状态服务对话(只允许修改)
|
||||
|
||||
- `lib/task-board-service.js`
|
||||
- `lib/task-board-mcp.js`
|
||||
- `scripts/task-board-service-unit.js`
|
||||
|
||||
不得修改:`server.js`、`lib/ccweb-mcp-server.js`、`scripts/regression.js`、任何 `public/*` 现有文件。
|
||||
|
||||
### Hook 对话(只允许修改)
|
||||
|
||||
- `lib/task-board-lifecycle.js`
|
||||
- `scripts/task-board-lifecycle-unit.js`
|
||||
|
||||
不得修改:`server.js`、`lib/codex-app-runtime.js`、`scripts/regression.js`、任何 `public/*` 文件。
|
||||
|
||||
### 集成对话(前三路完成后独占)
|
||||
|
||||
可以修改中心文件并调整前三路模块:
|
||||
|
||||
- `server.js`
|
||||
- `lib/ccweb-mcp-server.js`
|
||||
- `lib/codex-app-runtime.js`(仅必要时)
|
||||
- `public/index.html`
|
||||
- `public/app.js`
|
||||
- `public/style.css`(优先不改,使用独立 CSS)
|
||||
- `scripts/regression.js`
|
||||
- 前三路新模块
|
||||
|
||||
## 视觉方向
|
||||
|
||||
- 视觉论点:延续 cc-web 的安静暗色操作界面,以克制的青色主强调和少量状态色构建密集、清晰的横向看板。
|
||||
- 内容计划:顶层视图入口与工具条;横向状态工作区;归档视图;状态编辑面板。
|
||||
- 交互论点:视图切换轻淡入、卡片悬停与状态变化使用短促位移/颜色过渡、窄屏保持流畅横向滚动。
|
||||
|
||||
## 验证命令
|
||||
|
||||
```bash
|
||||
node --check lib/task-board-service.js
|
||||
node --check lib/task-board-mcp.js
|
||||
node --check lib/task-board-lifecycle.js
|
||||
node --check public/task-board.js
|
||||
node scripts/task-board-service-unit.js
|
||||
node scripts/task-board-lifecycle-unit.js
|
||||
node scripts/task-board-frontend-unit.js
|
||||
node --check server.js
|
||||
timeout 60s npm run regression
|
||||
```
|
||||
|
||||
视觉验收使用隔离端口和临时配置目录启动测试服务,不提前重启 pm2 生产服务。
|
||||
|
||||
## 重启门禁
|
||||
|
||||
1. 调用 `ccweb_list_conversations(status="running")`。
|
||||
2. 当前来源对话 ID 固定记录为 `56bb82c6-4fa3-4cb8-bb84-6969e6547d3a`;标题“设计任务看板状态机制”仅作人工交叉核验。
|
||||
3. 三个实现对话和集成对话必须全部为 idle,且 `ccweb_list_pending_replies` 无 waiting/delivering。
|
||||
4. 任何其他 conversation 状态为 running 都暂停重启并报告。
|
||||
5. 满足条件后执行 `pm2 restart ccweb --update-env`,随后检查 pm2 状态和 HTTP/WebSocket 健康。
|
||||
79
.trellis/tasks/08-11-task-board/prd.md
Normal file
79
.trellis/tasks/08-11-task-board/prd.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# 独立任务看板 PRD
|
||||
|
||||
## 目标
|
||||
|
||||
为 cc-web 增加一个与现有聊天功能解耦的任务看板。只有显式开启“加入任务看板”的会话才参与状态跟踪;Agent 可通过 MCP 主动上报,cc-web 生命周期 Hook 在缺少上报时提供保守兜底。完成状态与软归档分离。
|
||||
|
||||
## 用户场景
|
||||
|
||||
1. 用户从普通聊天页开启“加入任务看板”,该会话立即出现在看板。
|
||||
2. 用户从任务看板创建会话,新会话默认开启任务跟踪。
|
||||
3. 用户查看系统固定状态列,并新增、编辑、排序或停用自定义状态。
|
||||
4. Agent 调用状态 MCP 上报处理中、等待用户、阻碍、完成或自定义状态。
|
||||
5. Agent 没有上报时,cc-web 根据 turn 生命周期和结构化事件更新基础状态或标记“未上报”。
|
||||
6. 用户手动归档已完成任务;以后可取消归档。归档不删除会话。
|
||||
|
||||
## 功能要求
|
||||
|
||||
### 任务跟踪开关
|
||||
|
||||
- 普通新对话默认 `taskTracking.enabled=false`。
|
||||
- 从任务看板创建的会话默认 `true`。
|
||||
- 关闭开关后不进入看板、不运行自动分类;保留已有状态用于审计。
|
||||
- Agent 不能通过状态 MCP 偷偷开启、关闭或归档任务。
|
||||
|
||||
### 状态
|
||||
|
||||
- 系统固定状态 ID:`unassigned`、`in_progress`、`waiting_user`、`blocked`、`completed`。
|
||||
- 系统 ID 和语义不可删除;展示名称、颜色、顺序允许配置。
|
||||
- 自定义状态必须映射到一个系统 `baseStatus`,并包含名称、说明、颜色、顺序和启用状态。
|
||||
- 删除仍被任务引用的自定义状态前必须指定迁移目标。
|
||||
- 状态优先级:用户操作 > MCP 明确上报 > 生命周期 Hook > 默认状态。
|
||||
|
||||
### MCP
|
||||
|
||||
- `ccweb_task_status_list`:读取当前会话是否启用跟踪及可用状态定义。
|
||||
- `ccweb_task_update`:当前来源会话上报 `statusId`、`reason`、`summary`、`progress`。
|
||||
- 跟踪关闭时 `ccweb_task_update` 返回 `task_tracking_disabled`,不得自动加入看板。
|
||||
- 不提供 Agent 归档 MCP。
|
||||
|
||||
### 生命周期 Hook
|
||||
|
||||
- 使用 cc-web 内部事件,不修改用户 `.codex/hooks.json`。
|
||||
- 处理 `turn_started`、`user_input_requested`、`turn_completed`、`turn_failed`、`user_message_received`。
|
||||
- `turn_started` 可进入处理中;结构化用户输入进入等待用户;失败进入阻碍。
|
||||
- `turn_completed` 不等于任务完成。若本轮没有 MCP 上报,保留业务状态并标记 `reportingStatus=missing`。
|
||||
- 已归档会话收到新用户消息时自动取消归档并进入处理中。
|
||||
|
||||
### 看板
|
||||
|
||||
- 提供独立任务看板视图,不替换现有聊天页与会话列表。
|
||||
- 支持搜索、会话/Agent 筛选、优先级筛选、横向状态列、归档视图和状态管理面板。
|
||||
- 卡片点击打开原会话;运行态和任务态分开显示。
|
||||
- 支持桌面横向看板和窄屏横向滚动,不破坏现有响应式布局。
|
||||
|
||||
### 归档
|
||||
|
||||
- 归档使用 `archivedAt`/`archivedBy` 软标记,不移动或删除会话文件。
|
||||
- 用户可手动归档/取消归档。
|
||||
- 自动归档策略保留扩展点,本期不默认启用定时归档。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不修改 Codex Hook 配置。
|
||||
- 不把所有历史对话自动加入任务池。
|
||||
- 不从自由文本强行推断任务完成。
|
||||
- 不删除、移动或迁移现有会话文件。
|
||||
- 不在三个并行实现对话中修改中心接线文件。
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. 现有普通会话默认不出现在任务看板。
|
||||
2. 开关启用后会话可进入看板,关闭后立即退出但状态保留。
|
||||
3. 系统状态存在,自定义状态可创建、编辑、排序、停用并安全迁移。
|
||||
4. 两个 MCP 工具可发现、可调用,并遵守来源会话和开关边界。
|
||||
5. cc-web 生命周期事件正确驱动基础状态,且不会把 turn 完成误判为任务完成。
|
||||
6. 归档不删除会话,重新发消息可恢复。
|
||||
7. 前端视图与现有 cc-web 风格一致,桌面和窄屏可用。
|
||||
8. `node --check`、新模块单元测试和 `timeout 60s npm run regression` 全部通过。
|
||||
9. 隔离测试服务完成真实浏览器验收;生产服务仅在重启门禁通过后重启。
|
||||
@@ -0,0 +1,38 @@
|
||||
# 并行实现共享契约
|
||||
|
||||
本文件是三个实现对话与最终集成对话的唯一共享协议摘要。实现前必须同时阅读 `prd.md` 和 `info.md`。
|
||||
|
||||
## 核心不变量
|
||||
|
||||
1. 普通会话默认不跟踪;`taskTracking.enabled` 是进入任务池的唯一开关。
|
||||
2. `archivedAt` 与 `statusId` 分离;归档绝不删除或移动会话。
|
||||
3. 系统状态 ID 稳定;自定义状态必须映射到系统 `baseStatus`。
|
||||
4. 用户写入优先于 MCP,MCP 优先于 Hook,Hook 不覆盖同轮 MCP。
|
||||
5. `turn_completed` 绝不自动等价为 `completed`。
|
||||
6. 三个并行对话不得修改中心接线文件;第四个对话统一接线。
|
||||
|
||||
## 系统状态
|
||||
|
||||
| ID | 默认标签 | 语义 |
|
||||
|---|---|---|
|
||||
| unassigned | 待认领 | 已加入看板但尚未开始 |
|
||||
| in_progress | 处理中 | 任务仍在推进 |
|
||||
| waiting_user | 等待确认 | 等待用户输入、验收或外部条件 |
|
||||
| blocked | 遇到阻碍 | 发生错误或无法继续 |
|
||||
| completed | 已完成 | 任务业务目标已经完成 |
|
||||
|
||||
## 错误码
|
||||
|
||||
- `task_tracking_disabled`
|
||||
- `task_status_unknown`
|
||||
- `task_status_invalid`
|
||||
- `task_status_in_use`
|
||||
- `task_version_conflict`
|
||||
- `task_session_not_found`
|
||||
|
||||
## 集成原则
|
||||
|
||||
- 公共服务模块不依赖 `server.js`,由集成层注入 IO。
|
||||
- 前端模块通过适配器接收 `send`、`openSession` 和初始数据,不直接依赖现有全局变量。
|
||||
- 所有新增消息和工具使用 `task_` / `ccweb_task_` 前缀,避免覆盖现有协议。
|
||||
- 单元测试可独立运行,不启动生产 cc-web。
|
||||
26
.trellis/tasks/08-11-task-board/task.json
Normal file
26
.trellis/tasks/08-11-task-board/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "task-board",
|
||||
"name": "task-board",
|
||||
"title": "独立任务看板",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "shiyue",
|
||||
"assignee": "shiyue",
|
||||
"createdAt": "2026-08-11",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user