cmdr-mcp 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +29 -6
  3. package/docs/README.zh-CN.md +29 -6
  4. package/docs/agent-integration.md +2 -2
  5. package/docs/dashboard-plan.md +327 -0
  6. package/docs/dashboard.md +101 -0
  7. package/docs/implementation.md +25 -4
  8. package/docs/publishing.md +10 -8
  9. package/docs/setup.md +1 -1
  10. package/docs/troubleshooting.md +2 -2
  11. package/marketplace.json +1 -1
  12. package/package.json +9 -1
  13. package/plugins/cmdr/.claude-plugin/plugin.json +1 -1
  14. package/plugins/cmdr/.codex-plugin/plugin.json +1 -1
  15. package/plugins/cmdr/.zcode-plugin/plugin.json +1 -1
  16. package/plugins/cmdr/README.md +3 -1
  17. package/plugins/cmdr/THIRD_PARTY_NOTICES.txt +130 -0
  18. package/plugins/cmdr/bin/cmdr-check.mjs +3 -0
  19. package/plugins/cmdr/commands/cmdr.md +2 -0
  20. package/plugins/cmdr/dist/cli.mjs +121 -31
  21. package/plugins/cmdr/dist/daemon.mjs +4729 -137
  22. package/plugins/cmdr/dist/dashboard/app.css +1 -0
  23. package/plugins/cmdr/dist/dashboard/app.js +10 -0
  24. package/plugins/cmdr/dist/dashboard/index.html +13 -0
  25. package/plugins/cmdr/dist/hook.mjs +2 -2
  26. package/plugins/cmdr/dist/integrity.json +20 -17
  27. package/plugins/cmdr/dist/mcp.mjs +140 -64
  28. package/plugins/cmdr/skills/cmdr/SKILL.md +3 -1
  29. package/plugins/cmdr/skills/cmdr/references/commander.md +2 -0
  30. package/plugins/cmdr/skills/cmdr/references/executor.md +2 -0
  31. package/plugins/cmdr/skills/cmdr-commander/SKILL.md +2 -0
  32. package/plugins/cmdr/skills/cmdr-executor/SKILL.md +2 -0
  33. package/plugins/cmdr/skills/using-cmdr/SKILL.md +2 -2
@@ -7,7 +7,7 @@
7
7
  {
8
8
  "name": "cmdr",
9
9
  "source": "./plugins/cmdr",
10
- "version": "0.4.0",
10
+ "version": "0.5.0",
11
11
  "description": "Local multi-agent squads with durable messages, roles and lifecycle reminders."
12
12
  }
13
13
  ],
package/README.md CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  Requires macOS or Linux and **Node.js ≥22.5** (24 recommended). The development branch contains source and plugin metadata. npm packages and the generated `marketplace` branch include the runtime bundles.
10
10
 
11
- **One-command setup (0.4.0):** replace `claude-code` with `codex` or `zcode` for your host.
11
+ **One-command setup (0.5.0):** replace `claude-code` with `codex` or `zcode` for your host.
12
12
 
13
13
  ```sh
14
14
  npx -y --package=cmdr-mcp@latest cmdr setup --agent claude-code
@@ -42,7 +42,7 @@ For distribution, `npm pack` (or `npm publish`) runs `prepack` to build the four
42
42
 
43
43
  ```sh
44
44
  npm pack
45
- npm install --global ./cmdr-mcp-0.4.0.tgz
45
+ npm install --global ./cmdr-mcp-0.5.0.tgz
46
46
  cmdr --help
47
47
  ```
48
48
 
@@ -101,7 +101,7 @@ Codex wakes through app-server proxy or the `codex queue` fallback. Claude uses
101
101
 
102
102
  ## Tools
103
103
 
104
- Exactly seven MCP tools are exposed, independently of the host:
104
+ Exactly nine MCP tools are exposed, independently of the host:
105
105
 
106
106
  | Tool | Purpose |
107
107
  | --- | --- |
@@ -109,17 +109,40 @@ Exactly seven MCP tools are exposed, independently of the host:
109
109
  | `list` | Task ownership, unacknowledged age, progress, connection state and listener health |
110
110
  | `send` | Commands, cancel, answers and info; task_key deduplication and gated reassign |
111
111
  | `report` | Executor ready, working, blocked, done, failed or cancelled reports |
112
- | `ask` | Executor questions, optionally waiting for a correlated answer |
112
+ | `ask` | Executor questions, or commander `target=user` dashboard questions and handling receipts |
113
113
  | `read` | Priority dequeue, peek/history, recover, ID lookup and long polling |
114
114
  | `leave` | Leave, orphan or dissolve a squad |
115
+ | `task` | Create, update, query and archive persistent dashboard tasks |
116
+ | `artifact` | Publish/query isolated HTML explanations for tasks and questions |
115
117
 
116
118
  Every successful tool result includes identity, recommended wait and unread count. Reports carry their status in `message.data.status`. Unread messages are retained across daemon restarts; reads mark them delivered and leave history. Delivery is distinct from acceptance and completion. `read(recover=true)` non-destructively lists all unfinished commands, including already-read work. `pending=0`, `unread=0` and `offline` never release task ownership. `read`/`list` are compact by default; use `full=true` for expanded metadata. ID lookups also enforce the reassignment gate before exposing queued replacement work. Listings never include command bodies; use `read(id=...)` for your own inbox or operator `tail --full` for observation. No exactly-once execution guarantee is made.
117
119
 
120
+ ## Local dashboard
121
+
122
+ Run `cmdr dashboard` (or the stable CLI path printed by setup) to open the built-in React dashboard. `--no-open` prints short-lived access URLs for `127.0.0.1` and the machine’s non-loopback IPv4 addresses. The server binds to `0.0.0.0` on a system-assigned port; each address has its own single-use token, so opening the local link does not consume the LAN links. One page switches between squads, with a task workspace, a member/activity dock, and a persistent confirmation panel. Users can submit structured answers or send a note to the selected squad’s commander; notes enter the existing user-message queue without directly changing tasks. The HTTP/SSE service runs inside the existing daemon; closing the page does not stop collaboration.
123
+
124
+ Dashboard UI copy follows the system/browser’s preferred language: Chinese (`zh-*`) uses Simplified Chinese; other languages use English. Agent/user content and HTML artifacts remain unchanged. Reload after changing the browser language.
125
+
126
+ Example dashboard with demo data: multiple squads, task progress, member status, HTML explanations and user answers. Agent content in this example was written in English; it is not automatically translated.
127
+
128
+ ![English dashboard showing the task board and user decision panel](.github/assets/dashboard/main-en.png)
129
+
130
+ <details>
131
+ <summary>Task details with the answer form kept open</summary>
132
+
133
+ ![English task details, execution history and user answer form](.github/assets/dashboard/detail-en.png)
134
+
135
+ </details>
136
+
137
+ [View the Chinese dashboard example](.github/assets/dashboard/main.jpg).
138
+
139
+ Commanders create tasks with `task(action="create", title=...)`, dispatch using `send(task_id=..., to=..., message=...)`, and ask the user with `ask(target="user", question=..., kind="single|multiple|text|confirm")`. Answers enter the stable commander inbox; explicitly use `ask(target="user", action="handle", id=..., version=..., result=...)` after processing. `artifact` publishes self-contained sandboxed HTML explanations. See [dashboard operations and limits](docs/dashboard.md).
140
+
118
141
  ## Installation diagnostics and member CLI
119
142
 
120
143
  If cmdr tools are absent, inspect the host's actual plugin cache with `cmdr doctor --plugin-root /path/to/cached/plugin`. Add `--deep` to check MCP and daemon access in a temporary state directory. The checker works even when the inspected CLI bundle is missing. Refresh/reinstall damaged caches from the complete npm package and start a new session.
121
144
 
122
- `cmdr session join|list|send|report|ask|read|leave` provides member operations when MCP tools are unavailable. Supply `--agent` and `--native-id` (or `CMDR_AGENT`/`CMDR_SESSION_ID`); use the same native ID as the host. These commands retain membership and messages after exit, and display connection presence as `cli`; execution state is reported separately.
145
+ `cmdr session join|list|send|report|ask|read|leave|task|artifact` provides member operations when MCP tools are unavailable. Supply `--agent` and `--native-id` (or `CMDR_AGENT`/`CMDR_SESSION_ID`); use the same native ID as the host. These commands retain membership and messages after exit, and display connection presence as `cli`; execution state is reported separately.
123
146
 
124
147
  ```sh
125
148
  cmdr session join --agent zcode --native-id YOUR_SESSION_ID --squad-name my-project
@@ -172,7 +195,7 @@ npm run check
172
195
  npm run verify:zcode # optional: requires the locally installed ZCode desktop runtime
173
196
  ```
174
197
 
175
- `npm run check` checks formatting/types, builds the four entry points, runs unit/real-process tests, then packs and installs the npm tarball offline in a temporary prefix to verify the CLI and seven MCP tools. CI runs on macOS/Linux with Node 22/24 and checks generated bundles are not tracked by Git. The optional ZCode check validates, installs and connects the plugin using an isolated desktop runtime, without making a model request.
198
+ `npm run check` checks formatting/types, builds the four entry points, runs unit/real-process tests, then packs and installs the npm tarball offline in a temporary prefix to verify the CLI and nine MCP tools. CI runs on macOS/Linux with Node 22/24 and checks generated bundles are not tracked by Git. The optional ZCode check validates, installs and connects the plugin using an isolated desktop runtime, without making a model request.
176
199
 
177
200
  For development, `claude --plugin-dir ./plugins/cmdr` loads the plugin directly. Installed hosts use cached copies: reinstall/refresh after changing a plugin. Version numbers come from `package.json`; after same-version changes, restart the daemon explicitly. Generated bundles and third-party license notices are ignored by Git and included in the npm package.
178
201
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  支持 macOS / Linux,需要 Node.js ≥22.5(推荐 24)。开发分支保存源码和插件元数据;npm 发布包及自动生成的 `marketplace` 分支包含完整运行时。
10
10
 
11
- **一条命令完整安装(0.4.0)**,将 `claude-code` 换成实际使用的 `codex` 或 `zcode`:
11
+ **一条命令完整安装(0.5.0)**,将 `claude-code` 换成实际使用的 `codex` 或 `zcode`:
12
12
 
13
13
  ```sh
14
14
  npx -y --package=cmdr-mcp@latest cmdr setup --agent claude-code
@@ -42,7 +42,7 @@ npm run build
42
42
 
43
43
  ```sh
44
44
  npm pack
45
- npm install --global ./cmdr-mcp-0.4.0.tgz
45
+ npm install --global ./cmdr-mcp-0.5.0.tgz
46
46
  cmdr --help
47
47
  ```
48
48
 
@@ -92,7 +92,7 @@ ZCode 桌面端:打开工作区,在 **设置 → 插件 → 创建 → 添
92
92
 
93
93
  ## 工具和运维
94
94
 
95
- 固定 7 个 MCP 工具:`join`、`list`、`send`、`report`、`ask`、`read`、`leave`。读取即出队,`peek` 不出队,`history` 可回看。报告状态保存在 `message.data.status`。指挥官离队后小队变为 orphaned,可按原 ID 接管;`leave(dissolve=true)` 解散小队,但已经排队的消息仍可读取。
95
+ 固定 9 个 MCP 工具:`join`、`list`、`send`、`report`、`ask`、`read`、`leave`、`task`、`artifact`。读取即出队,`peek` 不出队,`history` 可回看。报告状态保存在 `message.data.status`。指挥官离队后小队变为 orphaned,可按原 ID 接管;`leave(dissolve=true)` 解散小队,但已经排队的消息仍可读取。
96
96
 
97
97
  ```sh
98
98
  plugins/cmdr/bin/cmdr status
@@ -122,7 +122,7 @@ npm run check
122
122
  npm run verify:zcode
123
123
  ```
124
124
 
125
- `check` 包括格式、类型、打包、单元/真实进程测试,以及 npm tarball 在临时目录中的离线安装和 7 个工具验证。ZCode 验证可选,需要已安装桌面端;它在临时目录使用 App 内置运行时验证插件和 7 个 MCP 工具连接,不发起模型请求。
125
+ `check` 包括格式、类型、打包、单元/真实进程测试,以及 npm tarball 在临时目录中的离线安装和 9 个工具验证。ZCode 验证可选,需要已安装桌面端;它在临时目录使用 App 内置运行时验证插件和 9 个 MCP 工具连接,不发起模型请求。
126
126
 
127
127
  插件版本由 `package.json` 统一生成。源码修改后需重新打包,并更新宿主缓存;同版本代码变更需手动重启 daemon。CI 验证 macOS/Linux、Node 22/24、npm 包可运行性,并确保生成产物没有被 Git 跟踪。
128
128
 
@@ -130,9 +130,9 @@ npm run verify:zcode
130
130
 
131
131
  ## 安装诊断与成员 CLI
132
132
 
133
- 工具未出现时,用 `cmdr doctor --plugin-root /实际宿主缓存中的插件目录` 检查缓存里的文件校验和与版本。加 `--deep` 会在临时数据目录中完成 MCP 握手、7 个工具检查及 daemon 访问,不操作正常小队。基础检查器独立于 dist,CLI bundle 缺失时仍可诊断;Node 缺失时先安装 Node。修复采用完整 npm 包重新注册市场、刷新/重装缓存并打开新会话,不跨安装目录链接 dist。
133
+ 工具未出现时,用 `cmdr doctor --plugin-root /实际宿主缓存中的插件目录` 检查缓存里的文件校验和与版本。加 `--deep` 会在临时数据目录中完成 MCP 握手、9 个工具检查及 daemon 访问,不操作正常小队。基础检查器独立于 dist,CLI bundle 缺失时仍可诊断;Node 缺失时先安装 Node。修复采用完整 npm 包重新注册市场、刷新/重装缓存并打开新会话,不跨安装目录链接 dist。
134
134
 
135
- `cmdr session join|list|send|report|ask|read|leave` 提供完整成员操作,原有运维命令含义不变。显式传 `--agent`、`--native-id`,或设置 `CMDR_AGENT`、`CMDR_SESSION_ID`;与 MCP/hook 共享会话时必须使用相同原生 ID,共享 MCP 进程不能配置一个固定 ID。CLI 显示 `presence=cli`,退出后保留成员关系和任务状态;连接结束不代表模型停工。监听由 daemon 独立管理。
135
+ `cmdr session join|list|send|report|ask|read|leave|task|artifact` 提供完整成员操作,原有运维命令含义不变。显式传 `--agent`、`--native-id`,或设置 `CMDR_AGENT`、`CMDR_SESSION_ID`;与 MCP/hook 共享会话时必须使用相同原生 ID,共享 MCP 进程不能配置一个固定 ID。CLI 显示 `presence=cli`,退出后保留成员关系和任务状态;连接结束不代表模型停工。监听由 daemon 独立管理。
136
136
 
137
137
  ```sh
138
138
  cmdr session join --agent zcode --native-id YOUR_SESSION_ID --squad-name my-project
@@ -143,3 +143,26 @@ cmdr session report --agent zcode --native-id YOUR_SESSION_ID --status done --re
143
143
  指挥官必须显式声明 role=commander,report/ask 由执行者调用。结果为 JSON,失败使用非零退出码。`--input` 接受该操作完整 JSON 参数;`--timeout`、SIGINT/SIGTERM 可取消等待,等待中的 read 取消不消费后续消息。ask 取消前可能已发送,不能盲目重试。
144
144
 
145
145
  `CMDR_HOME/logs/diagnostics/` 保存有界、限频的元数据快照。hook 仍失败放行,不写消息正文;unknown 表示尚未观察到,配置存在不代表真实触发。doctor 显示 provisional 会话及等待推荐来源;升级诊断不进入任务消息队列。详细案例见[排障说明](troubleshooting.md)。
146
+
147
+ ## 内置看板
148
+
149
+ 运行 `cmdr dashboard` 打开本机看板;setup 安装使用其返回的稳定 CLI 路径。`--no-open` 输出 `127.0.0.1` 及本机非回环网卡 IPv4 的短时访问地址。服务默认监听 `0.0.0.0`,端口由系统分配;各地址使用独立的一次性凭证,本机自动打开不影响局域网链接使用。单个 React 页面切换多个小队,以任务工作区、底部成员/活动坞和常驻确认面板展示进展。用户通过内置表单提交答复,也可向当前小队的指挥官留言;留言复用现有用户消息队列,不直接修改任务。普通进展更新不会整页刷新,切换小队保留表单草稿。
150
+
151
+ 看板文案默认跟随系统/浏览器首选语言:中文(`zh-*`)显示简体中文,其他语言显示英文。Agent/用户内容与 HTML 展示保持原样;更改浏览器语言后刷新页面生效。
152
+
153
+ 看板示例(演示数据):同页查看多个小队、任务进展和成员状态,通过右侧表单回复问题或向指挥官留言。
154
+
155
+ ![中文看板:任务进展、成员状态和用户答复面板](../.github/assets/dashboard/main.jpg)
156
+
157
+ <details>
158
+ <summary>查看英文版看板及任务详情</summary>
159
+
160
+ 英文示例的任务、问题和 HTML 内容使用预先准备的英文演示数据,不是自动翻译的 Agent 消息。
161
+
162
+ ![英文看板示例](../.github/assets/dashboard/main-en.png)
163
+
164
+ ![英文任务详情与常驻答复表单](../.github/assets/dashboard/detail-en.png)
165
+
166
+ </details>
167
+
168
+ 指挥官通过 `task` 管理任务,`send(task_id=...)` 关联派发,`ask(target="user")` 创建问题,`artifact` 发布隔离的 HTML 补充说明。用户答案持久化后进入当前指挥官收件箱;读取不代表处理,使用 `ask(target="user", action="handle", id=..., version=..., result=...)` 明确记录结果。关闭页面不结束小队。数据隔离、重试、恢复、HTML 限制和升级见[看板使用说明](dashboard.md)。
@@ -2,7 +2,7 @@
2
2
 
3
3
  Build a source checkout with `npm ci && npm run build`, or use the unpacked/installed npm package. Git does not contain generated runtime bundles. `npm pack` / `npm publish` builds and includes them automatically.
4
4
 
5
- The daemon and message model accept arbitrary lowercase Agent IDs (`[a-z][a-z0-9_-]{0,63}`), not a closed Claude/Codex enum. All hosts share the same seven MCP tools. Specialized adapters add identity, working-directory discovery and lifecycle reminders; none is required to use the queue.
5
+ The daemon and message model accept arbitrary lowercase Agent IDs (`[a-z][a-z0-9_-]{0,63}`), not a closed Claude/Codex enum. All hosts share the same nine MCP tools. Specialized adapters add identity, working-directory discovery and lifecycle reminders; none is required to use the queue.
6
6
 
7
7
  For automatic runtime, skill and user MCP/hooks installation, use [standalone setup](setup.md). The manual and native-plugin contracts follow below.
8
8
 
@@ -73,7 +73,7 @@ npm run verify:zcode
73
73
  ZCODE_RUNTIME_PATH=/path/to/glm/zcode.cjs npm run verify:zcode
74
74
  ```
75
75
 
76
- By default this command builds an npm tarball and tests its unpacked contents. An existing unpacked package root can be passed as `npm run verify:zcode -- /path/to/package`. The test invokes the actual desktop runtime's stdio app-server, validates and installs cmdr in an isolated workspace/storage directory, checks discovered components, and confirms a connected MCP server with seven tools. It makes no model calls and does not install into the user's normal plugin registry. GUI-driven model collaboration remains a separate manual check.
76
+ By default this command builds an npm tarball and tests its unpacked contents. An existing unpacked package root can be passed as `npm run verify:zcode -- /path/to/package`. The test invokes the actual desktop runtime's stdio app-server, validates and installs cmdr in an isolated workspace/storage directory, checks discovered components, and confirms a connected MCP server with nine tools. It makes no model calls and does not install into the user's normal plugin registry. GUI-driven model collaboration remains a separate manual check.
77
77
 
78
78
  References checked 2026-09-08: [ZCode plugin format](https://zcode.z.ai/cn/docs/plugin), [MCP configuration](https://zcode.z.ai/cn/docs/mcp-services), [hook contracts](https://zcode.z.ai/cn/docs/hooks). Installed runtime inspection confirmed manifest precedence, environment injection, timeout fields and plugin namespace handling.
79
79
 
@@ -0,0 +1,327 @@
1
+ # cmdr 内置 Dashboard 方案
2
+
3
+ 状态:首版已在 `feat/dashboard` 分支实现,基于 `main` 的 `9c95e8f`。本文保留设计约束与验收范围;实际工具、容量与操作方式见[看板使用说明](dashboard.md)。真实模型宿主的唤醒仍需独立验证。
4
+
5
+ ## 1. 目标与已确认的约束
6
+
7
+ 为本机用户提供一个由 cmdr 运行时内置的 Dashboard,查看不同小队的任务与成员状态,并直接回答指挥官提出的问题。看板随原生插件或 setup 安装的完整运行时提供,二者共用同一套实现。
8
+
9
+ - 使用 React;样式、布局、导航和常规交互由 cmdr 维护并随完整运行时分发。
10
+ - Agent 通过工具操作任务数据、报告进展、设置问题;常规流程无需编写或修改 HTML。
11
+ - 同一个 Dashboard 展示多个小队,通过页面导航切换。每个小队的数据独立,当前指挥官负责管理本小队。
12
+ - 简单数据结构难以解释的问题,允许 Agent 编写原始 HTML,通过工具发布为任务或问题的补充展示块。
13
+ - 页面根据数据局部更新,保持稳定的组件与 DOM 节点。普通进展变化不触发整页刷新。
14
+ - 使用常规 React 状态管理,不为连续交互引入专门的状态恢复协议、更新握手、延迟替换机制或 HTML 交互 SDK。
15
+ - 保持本机、单用户、已有 Agent 会话的范围。现有任务归属、取消、接管和宿主唤醒语义继续有效。
16
+
17
+ ## 2. 用户看到的页面
18
+
19
+ 一个本地入口对应当前 `CMDR_HOME` 管理的数据。不同数据目录之间不自动聚合;多个宿主配置目录可以共享同一个 `CMDR_HOME`,此时共用看板,不按宿主 profile 再拆分数据。页面应能查看当前连接的数据目录,便于区分多套安装。
20
+
21
+ 左侧为小队列表,显示名称、执行中任务数和待用户回复数。中间展示选中小队的四列任务看板,底部固定成员/活动坞;右侧常驻待确认事项与用户留言框。顶部使用一行指标,任务详情替换中间看板而不遮挡答复表单。未选中小队的摘要继续更新,便于发现需要处理的问题。
22
+
23
+ | 区域 | 内容与行为 |
24
+ | --- | --- |
25
+ | 任务看板 | 展示待派发、待接单、执行中、阻塞、已完成、失败与取消的任务;进入详情查看说明、执行记录和成果 |
26
+ | 待确认事项 | 展示问题、关联任务、选项、补充输入和提交状态;复杂说明可以附带 HTML 展示块 |
27
+ | 成员状态 | 展示角色、当前任务、最近报告、连接状态、监听健康与自动响应能力;有证据时展示唤醒投递状态 |
28
+ | 活动记录 | 展示任务派发、接单、进展、终态及用户决策,便于追溯 |
29
+
30
+ 页面明确区分连接、监听、唤醒投递和工作状态:离线不代表任务停止,监听健康不代表模型已开始处理,宿主接受唤醒不代表任务已接单,用户答案已接收或已读不代表指挥官已处理。没有可靠依据时显示未知或最近观测时间,不生成推测性的完成百分比。
31
+
32
+ 用户切换小队只改变页面选择,不改变任何 Agent 的成员关系或 commander 身份。看板数据归属小队,指挥官更换会话或发生接管后,任务、问题和回复继续保留。
33
+
34
+ 首版不提供通过拖动卡片直接修改执行状态的能力。用户可以查看进展、回答问题、向指挥官留言;任务执行状态由实际协作事件驱动。留言只复用现有消息队列,不增加任务管理入口。
35
+
36
+ ## 3. 职责与运行结构
37
+
38
+ | 层次 | 职责 |
39
+ | --- | --- |
40
+ | Agent / MCP 工具 | 指挥官维护计划、任务说明和问题,派发工作;执行者报告接单、进展与结果 |
41
+ | daemon / SQLite | 保存任务、问题和展示块,校验操作权限,维护执行关联,路由用户答复并发布事件 |
42
+ | 本地 Web 接口 | 提供内置静态资源、状态快照、事件订阅和用户答案提交入口 |
43
+ | React 页面 | 渲染数据,管理当前小队、展开项和表单草稿,提交用户输入 |
44
+
45
+ 已确定采用单 daemon 进程:按需启动一个默认监听 `0.0.0.0`、由系统分配端口的 HTTP 服务,同时提供静态资源和业务接口。浏览器通过 HTTP 与 SSE 访问 daemon;Agent 继续使用现有 MCP / Unix socket 链路。两种入口共用业务方法、SQLite 事务和提交后的事件,不维护额外的前端数据库或独立 Dashboard 服务进程。
46
+
47
+ HTTP 层采用 Hono 路由与 `@hono/node-server` 适配器,运行在现有 daemon 中。使用内置 JSON 请求上限和 Cookie 辅助函数,以 `streamSSE` 提供浏览器通知;连接缓冲上限、鉴权、CSP 和关闭清理由看板维护,不引入独立服务或通用控制器层。
48
+
49
+ HTTP 模块负责会话与请求校验、调用业务方法和返回结果,不直接修改数据库,也不将本机用户伪装成 Agent。业务操作提交成功后才发布变更通知。React 构建为随完整运行时发布的静态资源,由正在运行的 daemon 从自身运行时目录提供,不需要 SSR 或额外前端运行进程。
50
+
51
+ 使用 `cmdr dashboard` 打开看板,`--no-open` 返回 `127.0.0.1` 与本机非回环网卡 IPv4 的多个访问地址。每个地址使用独立且绑定来源的 60 秒一次性凭证;自动打开本机地址不会消耗局域网凭证。重新运行命令时刷新网卡地址及 Host 白名单,写请求 Origin 必须与当前访问地址一致。入口负责启动或定位本地服务并打开页面。关闭浏览器只结束查看,不关闭小队、不取消任务,也不停止成员监听。
52
+
53
+ setup 安装使用其返回的稳定 CLI 路径打开看板,沿用启动器绑定的 `CMDR_HOME`;原生插件使用对应安装的 CLI。资源定位不依赖当前工作目录、skill 目录或 npx 临时缓存。仅通过 `npx skills add` 安装技能不会安装运行时或启用看板,仍需已有可用集成或完成 setup。
54
+
55
+ 浏览器是本机用户的操作界面,可查看当前数据目录中的各小队;Agent 的写权限仍由 daemon 按身份、角色和小队归属校验。Web 接口不暴露任意 RPC 转发,写请求校验看板会话凭证与来源,HTML 展示块不能取得这些凭证。
56
+
57
+ 服务生命周期沿用 daemon 管理:重复打开复用同一 HTTP 服务;活跃的 Dashboard 连接计入使用状态,仅监听端口不阻止空闲退出;关闭页面后恢复原有空闲退出判断。daemon 停止时显式关闭 SSE 连接和 HTTP 服务,避免长连接阻塞退出。
58
+
59
+ ## 4. 数据模型
60
+
61
+ ### 4.1 任务 Task
62
+
63
+ 现有 command 跟踪已派发工作的交付与执行,看板还需要尚未派发的计划及已完成历史,因此增加独立任务记录。
64
+
65
+ 任务的最小信息包括:稳定 ID、小队 ID、标题、说明、验收条件、排序位置、关联执行记录、可选展示块以及创建和更新时间。负责人使用稳定成员 ID 表达,具体执行记录仍保留实际会话和 command ID。
66
+
67
+ 任务与执行的关系如下:
68
+
69
+ - 指挥官创建任务时,它可以尚未派发、尚无负责人。
70
+ - 派发时关联现有 command;接单与终态继续由 `report + reply_to` 推进。
71
+ - 重新分配保留同一个任务,关联新的 command,继续遵守原有取消与替代任务放行规则。
72
+ - Task 保留执行摘要和关联历史。消息保留期清理不能让看板上的任务或终态凭空消失。
73
+ - 执行中状态来自 command 和关联报告,不提供另一套任意修改为“完成”的路径。
74
+
75
+ | 看板状态 | 依据 |
76
+ | --- | --- |
77
+ | 待派发 | Task 已创建,没有当前执行记录 |
78
+ | 待接单 | command 为 queued / read;已读可作为附加标记 |
79
+ | 执行中 | 当前执行者已发送关联的 working 报告 |
80
+ | 阻塞 | 当前执行者已发送关联的 blocked 报告,或替代执行仍受取消门控 |
81
+ | 已完成 / 失败 / 已取消 | 当前有效执行链产生对应终态 |
82
+
83
+ “待用户确认”作为问题关联产生的提示,不直接改写底层 WorkState。问题需要用户回复不等于当前执行者已停止;要求停止正在进行的工作时,仍使用现有合作式取消机制。新执行记录尚未放行时,也不能用前一条执行的终态把整个任务误标为结束。
84
+
85
+ 维护状态和执行摘要时,应与对应消息、事件在同一事务中更新;不引入依赖后台扫描才能保持正确的第二套状态机。
86
+
87
+ ### 4.2 用户问题 Question
88
+
89
+ 首版支持单选、多选、文本输入和确认/拒绝;选择类问题可以附带补充说明。控件由插件根据类型渲染,不让 Agent 描述组件树或编写常规表单 HTML。
90
+
91
+ 最小信息包括:稳定 ID、小队 ID、可选任务 ID、题目与说明、类型、带稳定 ID 的选项、内容版本、状态、可选展示块及答案。
92
+
93
+ 问题流程为:
94
+
95
+ `待回复 → 答复已接收 → 指挥官已处理`
96
+
97
+ 另支持撤回问题。撤回不等于用户拒绝;“已处理”需要指挥官明确记录处理结果,不能因为读取消息就自动成立。
98
+
99
+ 题目、选项或影响决策的说明修改时增加内容版本。用户提交携带问题 ID、版本和提交 ID;版本不匹配时保留用户输入并提示核对新内容。普通任务进展不改变问题版本。
100
+
101
+ 用户答案提交按提交 ID 去重。同一次提交重试返回原回执;不同内容不能复用同一提交 ID。首版只接受问题当前版本的首个有效答案;已回答的问题再次征询需创建新问题,不增加复杂的多方编辑机制。
102
+
103
+ ### 4.3 HTML 展示块 Artifact
104
+
105
+ 展示块包括稳定 ID、小队 ID、标题、HTML 内容及内容版本,可以关联到任务或问题。首版保存当前内容,不建设完整的成品版本管理系统;问题提交时保存题目、选项及关联 HTML 说明的快照,满足答复追溯需求。
106
+
107
+ 任务、问题和 HTML 的保存边界独立于短期事件日志,不使用消息 TTL 自动删除。首版每小队每类记录最多 200 条(含归档),每任务最多 100 次执行;单份 HTML 最大 256 KiB,每小队当前 HTML 合计最大 8 MiB。归档不删除记录,显式 `purge --all` 会连同协作数据一起清除持久数据,详见[容量与保留](dashboard.md#容量与保留)。
108
+
109
+ ## 5. 工具操作与权限
110
+
111
+ 本分支实现以下操作语义,尚未发布;完整参数和用例见看板使用说明。
112
+
113
+ | 操作 | 建议接入位置 | 权限与约束 |
114
+ | --- | --- | --- |
115
+ | 创建、编辑、查看、归档任务 | `task` | 当前指挥官管理本小队;执行状态不能通过编辑任意覆盖,未完成执行不能用归档释放归属 |
116
+ | 派发与重新分配 | 扩展现有 `send` 的任务关联 | 复用角色校验、task_key、取消与替代任务门控 |
117
+ | 接单、进展与终态 | 现有 `report` | 执行者针对其拥有的 command 使用 reply_to;同步相关 Task |
118
+ | 创建、修改、撤回用户问题、记录处理结果 | 扩展 `ask` 的用户目标和管理操作 | 当前指挥官管理本小队的问题;原有 executor 向 commander 提问的行为保留 |
119
+ | 发布或更新 HTML 展示块 | `artifact` | 当前指挥官发布本小队的说明内容;不开放页面布局或主应用脚本修改 |
120
+ | 读取用户答复 | 现有 `read` 与问题查询 | 答复送入小队的稳定指挥官收件箱;只有当前指挥官消费该收件箱 |
121
+
122
+ 工具优先接收结构化参数。首版 HTML 工具直接接收内容,保存成功后再发布;不监听 Agent 文件的每次写入,也不直接让浏览器读取任意本机路径。
123
+
124
+ 本分支暴露九个 MCP 工具,新增 `task`、`artifact` 并扩展 `ask` 和 `send`。schemas、daemon、MCP/CLI、角色技能、工具发现及离线包验证同步更新;doctor/setup 的 `probeMcp` 按当前 schema 工具集合检查。
125
+
126
+ Agent 使用说明以 `plugins/cmdr/skills/cmdr/references/commander.md` 和 `executor.md` 为角色协议源,构建会同步生成兼容的 `cmdr-commander`/`cmdr-executor` 技能正文。新增看板操作在这些源文件中维护,并同步主技能、命令和安装说明,避免 setup 与原生插件各有一套协议。
127
+
128
+ 现有 `list` 不暴露 command 正文的约定保留。Dashboard 的任务详情使用面向本机用户的专用查询,Agent 的新增任务查询遵循小队权限,不借扩展 `list(full=true)` 绕过原有约定。
129
+
130
+ 留言使用单独的 `POST /api/messages` 入口,校验看板会话、同源请求、小队与文本长度。daemon 以用户身份将 `info` 消息送入相同的指挥官角色收件箱,设置 attention 并复用已有通知/唤醒。提交 ID 在原消息保留期间去重,沿用消息 TTL 与队列容量;它不创建 Question、处理回执或任务。浏览器按小队保留草稿,发送失败使用原内容与 ID 重试。只有问题答复具有独立于消息 TTL 的持久化决策记录。
131
+
132
+ ## 6. 用户答复如何回到指挥官
133
+
134
+ ### 6.1 答案入队与处理回执
135
+
136
+ 1. 指挥官创建问题,daemon 保存并发布事件,页面显示内置表单和可选 HTML 说明。
137
+ 2. 用户选择或输入后明确点击提交。控件变化只修改草稿,不立即发送。
138
+ 3. daemon 校验小队、问题、内容版本与提交 ID,在一个事务中保存答案并写入指挥官角色收件箱。
139
+ 4. 页面收到持久化成功的回执后显示“答复已接收”;超时或失败保留草稿,以同一提交 ID 重试。
140
+ 5. 答案入站消息具备明确的 attention 标记,通过现有 actionable 与宿主唤醒机制通知当前指挥官。仅在事务提交后通知;重复提交返回原回执,不再产生一条消息。没有健康唤醒能力时保留答案,如实显示等待、监听异常或 manual 状态。
141
+ 6. 指挥官读取答案,决定如何调整任务或回复执行者,再显式记录问题已处理及简短结果。
142
+
143
+ 用户来源由 Web 提交入口在服务端确定,不允许 Agent 在普通消息参数中自行声明“用户已确认”。现有 `send(type=answer)` 用于 commander 回答 executor 的 ask,用户答案需要独立的内部入站语义,不能绕过校验伪装成该调用。
144
+
145
+ 角色收件箱在没有指挥官时仍保存答案,后续接管者可以继续处理。浏览器切换小队不会改变已经发出的提交所属小队。用户的答复只应用于具体问题,不自动转化成额外任务授权。
146
+
147
+ ### 6.2 复用现有宿主唤醒
148
+
149
+ 目标是让轻量监听进程等待事件,再由宿主调度已有 Agent 会话。Unix socket、HTTP 长连接或心跳只能维持通信与健康检查,不能单独唤醒已经结束当前轮次的模型。Dashboard 的 SSE 仅服务浏览器;Agent 继续走现有 MCP / Unix socket 与宿主适配器,无需另建 Agent SSE、WebSocket 或无限前台 `poll` 通道。
150
+
151
+ 以下能力已在基线代码中实现,不列为 Dashboard 的新增基础设施:
152
+
153
+ | 宿主 | 当前唤醒路径 | 等待与恢复方式 |
154
+ | --- | --- | --- |
155
+ | Codex | daemon 优先使用 app-server proxy,不可用时检查 `codex queue` 能力 | 注册 auto 并确认健康后可结束空闲轮次;复用忙时合并、持久化唤醒请求与投递核对 |
156
+ | Claude Code | 宿主 Monitor 运行内置 watcher,每行输出产生原生通知 | 正常等待时保持监听,过期或退出后重新启动;仅在支持后台完成通知时使用 `--once` 后备路径 |
157
+ | ZCode | 宿主后台 Bash 运行同一 watcher,输出后退出,由完成通知恢复会话 | 空闲时静默;处理通知后核对后台任务状态并重新启动监听 |
158
+ | 不支持的宿主或无法建立唤醒路径 | 明确为 manual 或监听异常 | 使用现有有界等待/人工继续,不承诺后台自动响应 |
159
+
160
+ Claude/ZCode watcher 先订阅事件,再检查当前待处理工作,避免启动时遗漏消息;观察本身不消费消息。watcher 每 30 秒续租,租约为 90 秒,同一成员只允许一个有效监听租约。心跳、页面查询和 SSE 重连不应单独触发模型;watcher 检查发现需处理的消息时才输出通知元数据。实际断线或租约过期更新健康状态;daemon 重启导致 watcher 退出,由宿主通知 Agent 重新建立监听。
161
+
162
+ 宿主工具不保证继承 MCP 启动器的环境。当前 `listener.arm.command` 已包含 daemon 的 `CMDR_HOME` 与实际运行时命令路径,必须完整使用该指引,不能省略环境绑定或自行拼接全局 `cmdr` 路径。看板如展示重新监听指引,也直接使用此返回值,防止监听误连另一套数据目录。
163
+
164
+ 报告的唤醒判断使用入队时计算的 `attn`。默认实时事件与回放事件均可能省略 `data`,不能通过 `data.status` 再判断报告是否需要唤醒。`working`/`ready` 和无 attention 的广播保持安静,`done`/`failed`/`blocked`/`cancelled` 等需关注的报告按现有策略通知。长时间没有输出是正常等待状态,不采用定时重连来维持“活跃”。
165
+
166
+ Codex 的宿主投递复用现有 `requested → accepted → observed` 跟踪与不确定结果核对,不能因超时就盲目重复提交唤醒。该路径的请求状态与 Claude/ZCode 的监听租约含义不同,看板按各宿主已有证据展示,不虚构统一的“模型已唤醒”确认。
167
+
168
+ ### 6.3 阻塞等待、重新监听与恢复
169
+
170
+ 已接单任务可以在等待用户或指挥官答复期间保持归属。watcher 初次检查时,将没有待处理取消请求的 accepted command 记为已知,不因这条未完成任务立即重复通知。因此“已接单 → blocked → 等答复 → 重新监听”不会反复触发同一工作。
171
+
172
+ - queued 或 read 但尚未接单的 command、未读答案和待处理取消请求仍需通知;取消消息已读但取消请求尚未完成,也不能被忽略。
173
+ - 启动、上下文丢失或收到唤醒后,Agent 使用 `read` 与 `read(recover=true)` 检查消息和未完成工作,优先处理取消,核对实际文件/进程后再继续已接单任务。
174
+ - 指挥官恢复时还需查询本小队“答复已接收但未处理”的问题。`read(recover=true)` 恢复 command,不替代问题查询;答案消息已经读过,也不能使未处理决策丢失。
175
+ - 新任务通过关联的 `report(working, reply_to)` 接单,终态继续关联原 command;用户问题通过显式处理结果结束。消息读取、宿主接受唤醒和任务完成分别记录,不增加 exactly-once 执行承诺。
176
+ - 需要重新启动 watcher 时,先完成消息处理与状态核对,再确认旧后台任务已退出,按宿主提供的 arm 指引操作。Claude 的健康流式 Monitor 无需每次收到通知都重启。
177
+
178
+ 这些规则复用当前恢复和去重语义。Dashboard 新增的是用户问题的持久化状态、答案入站事件及处理回执;关闭页面只断开浏览器,不改变 Agent 的监听、任务归属或取消状态。
179
+
180
+ ## 7. React 更新与多小队状态
181
+
182
+ ### 7.1 通信选择:SSE
183
+
184
+ 选定 SSE,配合普通 HTTP 查询和写请求;首版不同时实现 WebSocket 或传输自动切换。
185
+
186
+ | 对比项 | SSE | WebSocket | 本看板的判断 |
187
+ | --- | --- | --- | --- |
188
+ | 通信方向 | 服务端向浏览器推送 | 双向消息通道 | 持续通信只需要发送变更通知 |
189
+ | 用户提交 | 使用独立 HTTP 请求与响应 | 可使用消息协议,也可继续走 HTTP | 保留 HTTP 状态码、校验错误和持久化回执 |
190
+ | 连接恢复 | 浏览器 EventSource 提供断线重连机制 | 原生接口需要应用或库处理重连 | SSE 减少连接管理代码;数据恢复仍由应用负责 |
191
+ | 二进制和高频双向交互 | 文本事件流 | 支持文本和二进制双向消息 | 当前没有此类需求 |
192
+
193
+ 这一选择基于交互模式与实现量,不宣称 SSE 在性能或可靠性上普遍优于 WebSocket。SSE 的单向事件与重连行为见 [WHATWG EventSource 标准](https://html.spec.whatwg.org/multipage/server-sent-events.html);WebSocket 的双向发送接口见 [WHATWG WebSockets 标准](https://websockets.spec.whatwg.org/)。
194
+
195
+ 每个 Dashboard 标签页只建立一个 EventSource,复用它接收所有小队的变更通知,切换小队不新建连接。HTTP/1.x 下浏览器的同源连接数量有限,大量标签页会竞争连接;首版面向一个页面切换多个小队,不为此引入跨标签页连接共享或 HTTP/2 部署。[浏览器连接限制说明](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#listening_for_custom_events)
196
+
197
+ 静态资源、HTTP API 和 SSE 使用同一来源及会话认证。原生 EventSource 不提供任意请求头配置,采用同源会话 Cookie,无需把长期凭证放在事件 URL 中。流使用 `text/event-stream`、及时输出和低频注释心跳;心跳只维持连接,不触发模型调用。
198
+
199
+ ### 7.2 数据同步:变更通知 + 重新查询
200
+
201
+ 任务、成员或用户问题变化时,SSE 只通知受影响的小队;HTTP 快照是页面数据的依据。前端不根据原始 command/report 日志重建业务状态,也不要求 SSE 精确交付每一条历史事件。
202
+
203
+ 1. 服务端先注册变更订阅,再向浏览器确认事件流已建立;页面在连接打开后获取小队摘要和当前小队快照。
204
+ 2. 收到变更通知时,重新获取受影响的摘要或当前小队数据,并合并到 React state。未选中小队仅更新摘要,进入时再查询详情。
205
+ 3. 同一资源短时间内的多次通知合并为一次查询;若查询期间又有变化,查询完成后补读一次,避免遗漏。避免同一资源的重叠请求让旧响应覆盖新状态。
206
+ 4. 连接中断时保留当前内容并标记连接状态;EventSource 重连成功后重新读取摘要及当前小队快照,无需回放断开期间的全部事件。快照读取失败时保留待刷新标记并重试,不能只等下一次业务变化。
207
+ 5. HTML 正文单独按展示块读取,普通任务快照只携带展示块 ID 和内容版本;版本不变时不重新加载 iframe。
208
+
209
+ daemon 内部继续使用现有事件和事务机制。Dashboard 通知是提交后生成的轻量失效提示,首版无需依赖 Last-Event-ID 建设持久化重放协议;原有 CLI 事件游标与回放语义保持不变。
210
+
211
+ 重新查询只更新 React 数据,不执行浏览器整页刷新。看板观察不消费成员消息,也不会把任务标成已读或接单。通知生成需要覆盖 working/ready 等影响展示的变化,不能只复用用于唤醒模型的 actionable 过滤结果。
212
+
213
+ ### 7.3 页面状态
214
+
215
+ - 小队、任务、成员、问题和展示块使用各自稳定 ID 作为 React key;不用更新时间、事件序号或内容版本充当 key。
216
+ - React state 保存当前小队、展开项和草稿。草稿以小队 ID 与问题 ID 索引,避免小队切换导致丢失或串用。
217
+ - 服务端数据与本地草稿分开保存;接收状态更新不能覆盖正在编辑的输入。
218
+ - 列表使用稳定排序,普通进展报告不重新洗牌。输入控件和提交表单保持稳定组件位置与类型。
219
+ - 小队切换只需常规 state 和必要的滚动位置记录,不建设复杂页面缓存。首版不承诺任意浏览器重载后的草稿恢复。
220
+ - 断线时保留现有内容并标记连接状态;恢复时更新数据,不用全屏加载状态替换正在使用的页面。
221
+
222
+ React 重新渲染是正常行为,重点是稳定的组件身份和 DOM 节点。状态切换造成卡片正常移动可以接受;不为每种移动增加焦点捕获、延迟迁移或交互锁定机制。
223
+
224
+ ## 8. 原始 HTML 展示能力
225
+
226
+ 复杂的方案对比、架构说明、图表和交互演示可以用 HTML 表达。Dashboard 提供固定外框、标题和展开查看入口,内部内容由 Agent 发布。
227
+
228
+ 首版使用稳定的 sandbox iframe,通过 `srcDoc` 或等价的受控内容入口渲染。允许内部演示脚本,但不授予 same-origin、父页面访问、看板凭证或任意任务写接口;不把原始 HTML 直接插入主应用 DOM。
229
+
230
+ 首版要求自包含 HTML:样式和脚本内联,必要图片可内嵌,不建设本地目录映射、任意文件服务或外部依赖管理。内容设置明确的大小限制,发布成功才更新可见内容。
231
+
232
+ 更新规则保持简单:
233
+
234
+ - task/member 等普通数据变化不改变 iframe 的 key、src 或 srcDoc,因而不会重新加载其文档。
235
+ - 只有展示块内容变化时才更新对应内容,允许这一次更新重置其内部状态。
236
+ - 切换小队使展示块卸载后,再次进入可以正常重新加载;不保证任意 HTML 内部交互状态跨切换保留。
237
+ - 不引入 HTML 状态保存接口、更新握手、延迟替换、DOM 自动合并或专门的交互 SDK。
238
+
239
+ 正式的用户问题仍使用 iframe 外的内置表单。HTML 内的控件可以用于模拟和说明,首版不从任意脚本动作推断用户已提交答案。影响问题含义的展示块更新应同时更新该问题的内容版本;仅用于任务展示的修改无需使无关问题失效。
240
+
241
+ ## 9. 对 Lavish 的借鉴范围
242
+
243
+ 借鉴其围绕成品展示问题的方式,以及原生表单、明确提交、草稿与已发送状态分离、稳定反馈身份等机制。复杂问题可附带 HTML 说明,使用户在上下文中作决定。
244
+
245
+ 本方案由 cmdr 内置 React 页面和数据接口完成协作闭环,不把 Lavish CLI、`poll` 或 Agent 重写整个 HTML 文件作为运行时依赖。用户答案直接进入 cmdr 的持久化与回复路由,不从自然语言反馈中猜测是否完成确认。
246
+
247
+ Lavish 对等待的关键约束值得沿用:后台任务必须由能将结果通知回原会话的宿主管理,单纯使用 shell `&` 或 `nohup` 不能构成模型唤醒路径;等待时保持安静,只在反馈等有意义的事件到达后恢复处理。其默认前台长轮询、HTTP 保活和 CLI 等待提示服务于自身执行环境,不照搬为 cmdr 的新机制。cmdr 已有宿主适配器、watcher 与租约,应复用这些能力。浏览器断线与协作结束仍分开处理,在本方案中关闭看板不结束小队。
248
+
249
+ 源码调研参考为 Lavish v0.1.71,固定提交 `4413dcc8eff35cdc659e2035b94194d3c9be55fa`:
250
+
251
+ - [输入交互指导](https://github.com/kunchenguid/lavish-axi/blob/4413dcc8eff35cdc659e2035b94194d3c9be55fa/src/playbooks.js):结构化控件、明确提交、选择与发送状态分离。
252
+ - [浏览器 SDK](https://github.com/kunchenguid/lavish-axi/blob/4413dcc8eff35cdc659e2035b94194d3c9be55fa/src/artifact-sdk.js):HTML 内反馈控件与展示上下文。
253
+ - [会话存储](https://github.com/kunchenguid/lavish-axi/blob/4413dcc8eff35cdc659e2035b94194d3c9be55fa/src/session-store.js):反馈身份、去重与结束状态处理。
254
+ - [CLI 等待与宿主唤醒约束](https://github.com/kunchenguid/lavish-axi/blob/4413dcc8eff35cdc659e2035b94194d3c9be55fa/src/cli.js):前台等待、后台完成通知与结果交付的边界。
255
+
256
+ ## 10. 首版范围与实施拆分
257
+
258
+ 首版覆盖一条完整闭环:
259
+
260
+ `工具维护任务 → 多小队看板展示 → 成员报告自动更新 → 用户回答问题 → 对应指挥官继续处理`
261
+
262
+ 建议按以下顺序实施,每一步仍需满足原有协作语义:
263
+
264
+ 1. 增加 Task、Question、Artifact 数据及工具操作,复用 command/report 状态和角色收件箱,完成持久化、权限和答复去重;答案入站接入现有 actionable 策略及宿主唤醒路径。
265
+ 2. 增加本地 Web 服务、快照和事件接口,构建 React 固定布局,接通多小队切换、任务、成员与问题表单。
266
+ 3. 增加隔离的 HTML 展示组件和发布工具,完成用户答复、既有宿主唤醒、指挥官读取与处理回执的联调,以及打包和浏览器验证。
267
+
268
+ 现有 proxy/queue 适配、watcher 长连接、续租、重新监听去重、忙时合并和唤醒投递核对均直接复用,不重复实现。看板只增加业务接入和状态展示,不以模型定时轮询或周期重连维持可响应状态。
269
+
270
+ 看板允许局域网浏览器访问同一个本机用户的数据;首版不包含公网部署、多用户账户、跨机器小队、创建新 Agent、executor 互发消息、可视化页面搭建、复杂工作流编辑器或任意 HTML 的状态恢复。无需先建设通用插件 UI 框架,也不加入与本看板无关的全局请求重试改造。
271
+
272
+ 构建与分发沿用 0.4.0 的两条安装路径:
273
+
274
+ - 前端资源放在随完整运行时复制的目录中,例如 `plugins/cmdr/dist/dashboard/`;在生成 `dist/integrity.json` 前完成前端构建,并将前端依赖的许可证纳入分发声明。现有完整性清单递归覆盖运行时文件,setup 根据该清单生成构建摘要,只有前端内容变化时也应得到新的运行时目录。
275
+ - 原生插件从宿主缓存使用资源;setup 将完整运行时持久化到 `<CMDR_HOME>/runtimes/<version>-<digest>/`,通过稳定启动器访问。两种路径均使用预构建资源,不启动开发服务器、不现场安装前端依赖;删除 npx 缓存或安装源不能影响看板运行。
276
+ - setup 升级保留旧运行时,更新稳定启动器,但不自动重启已有 daemon。看板静态资源与接口均由当前 daemon 对应的运行时提供;启用新版按既有流程使用新 CLI 显式重启 daemon、重连 MCP,并按宿主要求重新监听。原生插件另外需要刷新/重装缓存,不增加看板热切换协议。
277
+
278
+ 上述安装与升级能力已有实现;新增工作是将前端资源纳入现有构建、完整性检查、复制和包验证流程。
279
+
280
+ ## 11. 验收标准
281
+
282
+ | 场景 | 预期结果 |
283
+ | --- | --- |
284
+ | 两个小队同时有任务 | 一个入口可以切换查看,各自任务与成员清晰隔离,后台小队待确认数量更新 |
285
+ | 任务从计划到派发再完成 | 看板与实际 command 接单、终态一致,不能用编辑任务绕过执行语义 |
286
+ | 成员离线或消息已读 | 不误报任务完成、停止或已接单,不释放任务归属 |
287
+ | 用户输入期间连续收到报告 | 输入、选择、焦点不被普通数据更新重置,页面不整页刷新 |
288
+ | 用户切换小队后返回 | 结构化表单草稿仍在,答案不会提交到另一个小队 |
289
+ | HTML 展示块保持不变 | 其他状态更新不重载 iframe;HTML 自身更新允许局部状态重置 |
290
+ | HTML 内部脚本运行 | 可以做局部演示,不能读写 Dashboard 状态或直接确认任务 |
291
+ | 重复提交或响应丢失 | 同一提交 ID 返回原回执,只记录一次答案,不产生重复指挥官通知消息 |
292
+ | 问题已被修改或撤回 | 旧表单不被静默接受,用户输入保留,并得到明确提示 |
293
+ | 指挥官退出后有人接管 | 任务、问题及已提交答案保留,新指挥官能继续处理 |
294
+ | 用户回答时指挥官空闲或正忙 | 答案持久化并接入现有宿主通知/队列;忙时沿用宿主适配语义,不新建竞争会话 |
295
+ | 已接单任务阻塞后重新监听 | 无新消息时保持静默;答案、新的未接单工作和待处理取消仍可通知,原任务归属与恢复能力不变 |
296
+ | 答案已读但指挥官尚未记录处理结果 | 问题仍显示待处理,恢复或接管时可通过问题查询继续核对 |
297
+ | 监听健康、唤醒已投递或宿主状态未知 | 分别展示已有证据,不把连接、监听或投递状态显示成模型已处理或任务已接单 |
298
+ | 浏览器断线后恢复 | SSE 重连后重新查询快照,保持外层交互状态,展示实际连接情况 |
299
+ | 首次查询或重新查询期间发生变化 | 订阅已经生效,查询期间的通知触发补读,旧响应不覆盖新状态 |
300
+ | 一个页面切换多个小队 | 始终复用一条 SSE 连接,不按小队或组件增加长连接 |
301
+ | daemon 重启或历史消息过期 | 任务、未处理问题和答案可恢复;不依赖短期消息日志维持看板事实 |
302
+ | 关闭 Dashboard | 小队、任务和宿主监听继续按原有规则运行 |
303
+ | 原生插件或 setup 安装后移除安装源/npx 缓存 | 各自完整运行时仍可提供页面和接口,不依赖临时路径或技能目录 |
304
+ | 多个宿主 profile 或自定义数据目录 | 相同 `CMDR_HOME` 共用看板;不同目录保持隔离,打开入口与 watcher 均指向预期目录 |
305
+ | 升级或扩展 MCP 工具 | doctor/setup 自检识别新版工具集合;完整性检查包含前端资源,显式重启后页面与接口来自同一运行时 |
306
+
307
+ 基线回归测试覆盖 watcher 重新启动、daemon 重启后重新监听、未读答案、未接单工作、待处理取消,以及省略 `data` 的实时/回放事件和同一订阅上的连续报告通知;standby 测试还覆盖忙时合并、投递结果不确定时的核对及无进展停滞。本分支保留这些测试,并新增用户答案去重入队、当前指挥官路由、问题恢复与处理回执验证。
308
+
309
+ setup 测试与离线包验证覆盖持久运行时、升级、配置保留、profile 隔离、watcher 数据目录绑定及清除 npx 缓存后的检查。本分支补充静态资源、HTTP/SSE 和新版工具集合验证;安装自检成功仍不代表宿主信任、hooks 执行或模型自动响应已经通过验证。
310
+
311
+ 本分支已通过 `npm run check`、最低 Node 版本下的看板测试和 ZCode runtime 插件验证,并完成真实浏览器的输入、切换、iframe 保留、答复提交和 CLI 指挥官处理回执验证。真实宿主中的空闲唤醒、忙时积压及原生任务过期后的重新监听仍需单独验证;已有进程测试和浏览器/CLI 流程均不代表真实模型已处理。
312
+
313
+ 自动化测试与浏览器验证的实际结果记录在 `docs/implementation.md`,不将进程测试等同于真实模型协作验证。
314
+
315
+ ## 12. 仓库实现入口
316
+
317
+ - [长期协作语义](long-running-collaboration.md):归属、取消、角色收件箱、恢复、事件游标与宿主唤醒。
318
+ - [当前实现与验证范围](implementation.md):已有能力和验证边界。
319
+ - [安装与升级](setup.md)、[安装实现](../src/cli/setup.ts):持久运行时、稳定启动器、数据目录及宿主 profile。
320
+ - [安装诊断](../src/cli/doctor.ts)、[离线包验证](../scripts/verify-package.mjs)、[setup 进程测试](../tests/setup-process.test.ts):MCP 工具集合检查及移除缓存后的验证入口。
321
+ - [协议与模型](../src/shared/protocol.ts)、[工具 schema](../src/shared/schemas.ts):现有类型和九个工具。
322
+ - [核心逻辑](../src/daemon/core.ts)、[持久化](../src/daemon/store.ts):事务、任务执行和消息路由。
323
+ - [看板业务](../src/daemon/dashboard.ts)、[HTTP/SSE 服务](../src/daemon/dashboard-http.ts)、[React 页面](../src/dashboard/app.tsx):任务、问题、HTML 与浏览器交互。
324
+ - [事件观察](../src/cli/tail.ts)、[唤醒策略](../src/shared/wake.ts):非消费式观察与 actionable 分类。
325
+ - [宿主 watcher](../src/cli/watch.ts)、[standby 调度](../src/daemon/standby.ts):监听、续租、重新监听去重与宿主投递。
326
+ - [watcher 进程测试](../tests/host-watch-process.test.ts)、[standby 测试](../tests/standby.test.ts):已有自动化覆盖,区别于真实宿主与看板联调。
327
+ - [daemon 服务](../src/daemon/server.ts)、[构建脚本](../scripts/build.mjs):本地服务生命周期、打包和完整性校验。