joy-cli/docs/joy-panel-cli-architecture-plan.md
feibisi 4093b2c6fa fix(web): 一级 tab 固定 12,修正合并后的布局混乱
- 恢复清晰一级:总览/神兽/会话/活动/任务/协作/数据/消息/流水线/运维/飞轮/安全
- 总览瘦身:5 决策卡 + issues + 入口卡(想法/好奇链到飞轮·灵感)
- 飞轮子导航 诊断|资源/LLM|灵感;运维/数据/活动保留分组
- 想法/好奇仅飞轮·灵感一处编辑;旧 hash 兼容
2026-07-09 11:45:27 +08:00

427 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# joy Web 面板 + joy CLI 架构收口方案
> 状态:**MVP 已执行**Phase 03**布局修正**:一级 tab **固定阈值 12**(总览+11 功能),飞轮/运维/数据/活动子导航
> 日期2026-07-09
> 确认菲比斯「按你的方案来」2026-07-09
> 范围:`~/Projects/joy-cli`(主)+ 关联 `linuxjoy` 文档/watchdog 仅在必要时
> 原则:**不横向加功能;收口、分层、对齐人机同源**
### 已锁定决策
| 编号 | 选择 | 含义 |
|------|------|------|
| **A1** | `joy data` 与现有 `cluster-data` **语义对齐** | catalog/search/sql 同名;逻辑进 `joy/core`;非另起炉灶 |
| **B1** | 默认首页 = **总览** | 不再默认神兽 |
| **C1** | 执行序 **0 → 1 → 3 → 2 → 4** | lite API 在 data 同源之后Phase 4 后置 |
### 分工(执行时)
- **主代理**契约、TABS/路由、总览、三态、接口形状、联调验收
- **子代理**:按卡搬 tab 合并、`cluster_data` 抽取、deprecated 转调、测试、Phase 4 拆分
---
## 0. 一句话目标
把 joy 从「55 命令 + 13 tab 的功能堆叠」收成:
- **CLI** = 飞轮运行时标准库(核心 ≤15 主命令,其余 deprecated/插件)
- **Web** = 给人的决策台≤10 意图 tab读多写少写操作三态
- **同源** = 数据资产 / Board / 健康信号 不在 web.py 与 CLI 各写一套
---
## 1. 背景与问题
### 1.1 已验证的合理分层(保留)
| 层 | 角色 | 形态 |
|----|------|------|
| joy CLI | agent / 脚本 | JSON、identity、可脚本 |
| joy web | 人 | 可见性 + 白名单写 |
| Board / NATS / dispatch | 集群执行 | web 不替代 |
### 1.2 当前痛点
| # | 问题 | 证据 |
|---|------|------|
| P1 | 面板 IA 按数据源堆叠 | 13 tab运维 10 sectionLLM 健康出现 3 处 |
| P2 | 写操作语义混杂 | 登记 / 轻量 route / 真 inject / 重建 不易区分 |
| P3 | 前端/采集单体 | app.js ~4800 行dashboard.py ~2300 行;单 API 大象 |
| P4 | CLI 表面积过大 | ~55 顶级命令README 与 help 漂移;大量重叠 |
| P5 | 人机不同源 | 数据资产检索逻辑在 web.pyCLI 无 `joy data` |
| P6 | 空壳稀释信任 | Langfuse 0 行曾与真探针并排 |
### 1.3 非目标(本方案不做)
- 重写整个 joy-cli 框架或换前端框架
- 把 Grafana 迁回主力
- 实现完整 dispatch inject 闭环(仅预留接口与标签)
- 改生产防火墙 / NATS ACL / 跨 VM 批量 prlctl
- 删除历史命令的 git 历史(只标 deprecated软删入口
---
## 2. 目标架构
### 2.1 三层契约(铁律)
```
┌─────────────────────────────────────────────────────────┐
│ 人(菲比斯 / 麟悦) │
│ joy web :8899 —— 读为主;写 = 白名单三态 │
└───────────────────────────┬─────────────────────────────┘
│ /api/* (lite + 分域)
┌───────────────────────────▼─────────────────────────────┐
│ joy CLI —— 飞轮标准库 │
│ A 核心运行时 B 领域扩展 C 遗留(deprecated) │
└───────────────────────────┬─────────────────────────────┘
│ board / journal / NATS / SSH
┌───────────────────────────▼─────────────────────────────┐
│ 集群执行面 Board · dispatch-loop · 神兽/work · VM │
└─────────────────────────────────────────────────────────┘
```
**禁止**
- web 直接 `prlctl` 批量 / 生产变更
- web action 绕过白名单
- 同一业务逻辑在 `web.py``commands/*.py` 各维护一份
### 2.2 写操作三态(全局)
| 态 | 含义 | UI 标签 | 例子 |
|----|------|---------|------|
| **observe** | 只读 / 刷新 | 灰 | 刷新缓存、journal last |
| **register** | 登记意图,不保证执行 | 黄 | board create、轻量 route |
| **execute** | 改变运行态,可破坏上下文 | 红 + 二次确认 | work_rebuild、clone restart、tmux restart |
规则:
1. 每个按钮/action 必须标一态
2. register 必须有可深链回执task_id
3. execute 必须 confirm + audit log
4. register ≠ inject文案强制
### 2.3 面板目标 IA9 入口)
| # | Tab id | 中文 | 合并来源 | 默认 section |
|---|--------|------|----------|--------------|
| 1 | `overview` | **总览** | 现 Hero 强化,作为默认 tab | pulse / 瓶颈 / 关键 5 指标 |
| 2 | `runtime` | **运行** | 神兽 + 会话 + 活动 | 神兽列表tmuxevents |
| 3 | `dispatch` | **派活** | 任务 + 协作 + dispatch 队列 | 看板;组建团队;回执 |
| 4 | `data` | **数据** | 数据资产 + 知识库(次) | 检索+台账;记忆/cocobook section |
| 5 | `messages` | **消息** | 消息 | 现有 |
| 6 | `pipelines` | **流水线** | 流水线 | 现有 |
| 7 | `ops` | **运维** | 运维(已有 4 组) | 健康 \| 网关 \| 宿主机 \| 名册 |
| 8 | `analysis` | **飞轮** | 飞轮诊断 + 资源路由 + 能力 | 七环;预算/容量LLM |
| 9 | `security` | **安全** | 安全告警 | 告警;端口(默认非常见) |
**从 13 → 9**:去掉独立的 sessions/activity/collab/budget/memory/data-assets/flywheel-diag 一级入口,变为 section。
**Hero**:只在总览 tab 顶部;其它 tab 不再重复整块 hero可保留 1 行 sticky 状态stale / 失败率)。
**关键 5 指标(总览固定)**
1. 健康 `healthy/total`
2. 分发失败率 `failed/(completed+failed)`
3. 瓶颈一句话
4. 数据 `searchable 库 / 总行`
5. Mac 负载·内存%
### 2.4 CLI 目标表面(核心 15
| 主命令 | 职责 | 吸收/替代 |
|--------|------|-----------|
| `help` / `tools` | 发现 | — |
| `patrol` | 单点/全景快检 | 部分 cluster_health 场景 |
| `health` | provider + self | — |
| `resources` | 资源并行总览 | uptime/disk 作 sub 或 flag |
| `vm` | Parallels 电源 | **prlctl → deprecated 指向 vm** |
| `clone` | 分身 | **clone_restart → clone restart** |
| `work` | work session | work_rebuild 作 sub |
| `tmux` | Mac 会话可观测 | — |
| `board` | Task Board | create/route/ls… |
| `journal` | 记录+heartbeat | — |
| `message` | NATS | inbox/poke 保留但文档标「通信族」 |
| `recall` | 集群记忆 | — |
| `data` | **新建** 数据资产 catalog/search | 与 web 同源 |
| `dashboard` | 采集 | — |
| `web` | HTTP 服务 | — |
**B 类保留**(不进「核心 15」宣传help 里第二段):
`sop` `budget` `meter` `cocobook` `intel` `domain` `delegate` `curiosity` `daily` `konqi` `tux` `mind` `infra` `backup` `api` `config` `state` `who` `verify` `grow` `signal` `scan` `wake` `team` `profile` `project` `env` `output` `report` `bootstrap`
**C 类 deprecatedhelp 标废,半年后可删)**
| 命令 | 迁移 |
|------|------|
| `prlctl` | `joy vm` |
| `clone_restart` | `joy clone restart` |
| `wake`(若与 clone wake / vm wake 重复) | 文档指向明确 sub |
### 2.5 API 分层
| 端点 | 内容 | 刷新 |
|------|------|------|
| `GET /api/dashboard/lite` | ts, pulse, issues, flywheel 摘要, bottleneck, mac_host 摘要, stale | 1015s |
| `GET /api/dashboard` | 全量(兼容现前端) | 1530s collect |
| `GET /api/tab/<name>` | 可选懒加载security / data_assets / pipelines | 按 tab |
| 现有 | `/api/action` `/api/cluster-data/*` `/api/cocobook/*` | 保持 |
Phase 1 可只加 `lite`,全量仍用现 APIPhase 2 再懒加载。
### 2.6 数据同源:`joy data` ≡ `cluster-data`A1
linuxjoy 已有 bash`scripts/cluster/cluster-data`catalog / show / sql / search
```
joy data catalog # 同 cluster-data catalog
joy data search <id> "<q>" # 同 cluster-data search
joy data sql <id> "<SQL>" # 同 cluster-data sql可选 Phase 3
joy data stats # 摘要agent 省 token
```
实现:
-`joy/core/cluster_data.py`registry 解析 + search/sql SSH
- `commands/data.py` + `web.py` 共用同一 core
- 禁止 web.py 再内嵌大段 py_scriptbash `cluster-data` 可逐步改为调 joy 或双轨读同一 registry
- **不另发明第二套资产 ID 或路径规则**
### 2.7 Web 白名单分档
| 档 | 默认 | 命令例 |
|----|------|--------|
| observe | 开 | dashboard --json, journal last |
| register | 开 | board create, board route(轻量), journal heartbeat, poke |
| execute | 开但强确认 | work_rebuild, clone restart, tmux restart, vm wake, docker * |
| control | **默认关** | board route --full, flywheel resume, 未来 prlctl kill |
控制:`JOY_WEB_ALLOW_CONTROL=1` 或配置文件开启。
---
## 3. 分阶段执行计划
### Phase 0 — 契约落地文档0.5 天)
| 步骤 | 产出 | 验收 |
|------|------|------|
| 0.1 | 本方案合入 joy-cli `docs/` + README 链到方案 | 文件存在 |
| 0.2 | README「命令一览」改为 核心15 + B/C 分层 | 与 help 不矛盾 |
| 0.3 | 写操作三态表写入 web.py 注释 + 前端常量 `ACTION_TIER` | 可查 |
**不改运行行为。**
### Phase 1 — 面板 IA 收口23 天)
| 步骤 | 内容 | 风险 |
|------|------|------|
| 1.1 | TABS 重组为 9 入口hash 路由 `#tab=` 兼容旧 id 重定向 | 中:书签 |
| 1.2 | 总览 tab = 强化 Hero其它 tab 去大 hero | 低 |
| 1.3 | 运行 = beasts+sessions+activity sections | 低 |
| 1.4 | 派活 = board+collab+dispatch | 低 |
| 1.5 | 数据 = data-assets + memory/sources 作 section | 中:知识库路径 |
| 1.6 | 飞轮 = flywheel-diag + budget | 低 |
| 1.7 | 全局 action 按钮三态样式(灰/黄/红) | 低 |
| 1.8 | cache bust手动点检 9 tab | — |
**兼容**:旧 hash `tab=beasts``runtime``tab=collab``dispatch` 等映射表。
### Phase 2 — API + 采集分频12 天)
| 步骤 | 内容 |
|------|------|
| 2.1 | `/api/dashboard/lite` |
| 2.2 | 总览优先 lite全量仍 15s watch |
| 2.3 | collect 内 security/data_assets 可 60s 缓存戳(可选) |
| 2.4 | Langfuse 空壳保持降级展示(已有则巩固) |
### Phase 3 — CLI 收口 + data 同源2 天)
| 步骤 | 内容 |
|------|------|
| 3.1 | `joy/core/cluster_data.py` 抽取 |
| 3.2 | `joy data catalog|search|stats` |
| 3.3 | web search/catalog 改调 core |
| 3.4 | `prlctl` / `clone_restart` help 标 deprecated实现转调 |
| 3.5 | `joy help` 分组:核心 / 扩展 / 遗留 |
| 3.6 | pytestdata catalog 解析deprecated 转调 smoke |
### Phase 4 — 工程拆分可并行23 天)
| 步骤 | 内容 |
|------|------|
| 4.1 | `src/joy/web/js/` 拆 tab 模块build 可仍拼接或 ES modules |
| 4.2 | dashboard.py 按 collect_* 文件拆 `dashboard/` 包(可选) |
| 4.3 | 静态测试 + mac-collab 无关则只 joy-cli pytest |
**Phase 4 可后置**13 完成后即可宣布「架构收口 MVP」。
---
## 4. 详细设计要点
### 4.1 旧 tab → 新 tab 映射
| 旧 id | 新 id | section |
|-------|-------|---------|
| beasts | runtime | beasts |
| sessions | runtime | tmux |
| activity | runtime | events/journals/audit |
| board | dispatch | board-tasks, dispatch-hub |
| collab | dispatch | collab-compose, collab-matrix, 回执 |
| data-assets | data | da-hub |
| memory | data | memory-hub, sources-hub |
| messages | messages | — |
| pipelines | pipelines | — |
| monitoring | ops | 四组不变 |
| flywheel-diag | analysis | fly-* cap2-* |
| budget | analysis | budget/cap/llm |
| security | security | — |
| overview | overview | hero 指标 |
### 4.2 `joy data` 行为
```text
joy data catalog
→ { assets, total_rows, total_assets, by_type, by_vm, searchable, archive, registry }
joy data search --asset ailab-mbawiki --query "品牌定位" [--limit 5]
→ { query, asset, results: [{distance, text, title, url}] }
joy data stats
→ 摘要数字(给 agent 省 token
```
Registry 路径优先级(与现 collect 一致):
1. `~/Projects/linuxjoy/configs/cluster-data-registry.yml`
2. `~/mnt/shared-context/cluster-data-registry.yml`
3. `/mnt/shared-context/cluster-data-registry.yml`
### 4.3 前端模块边界Phase 4
```
src/joy/web/
index.html
styles.css
app.js # 壳路由、load、action、TABS 注册
js/
api.js
actions.js # doActionRaw + 三态
tabs/
overview.js
runtime.js
dispatch.js
data.js
ops.js
analysis.js
security.js
messages.js
pipelines.js
```
MVP 可用 IIFE + 顺序 script 标签,不强制打包器。
### 4.4 测试与验收
| 项 | 命令/方法 |
|----|-----------|
| 语法 | `py_compile` + `node --check` |
| 单测 | `pytest tests/`(现有 14+data 新增 23 |
| 面板 | 9 tab 手动点检;深链 `#tab=dispatch&task=BT-` |
| CLI | `joy data catalog \| jq .total_assets``joy prlctl` 转调提示 |
| 回归 | journal_stale 不被错误抬高lite 与 full ts 一致 |
### 4.5 回滚
- 仅 git revert 对应 commit
- tab 映射保留旧 id 一周
- `/api/dashboard` 全量不删lite 失败则回退 full
---
## 5. 工作量与依赖
| Phase | 估时 | 依赖 |
|-------|------|------|
| 0 文档 | 0.5d | 无 |
| 1 面板 IA | 23d | 0 |
| 2 lite API | 12d | 1 可并行后半 |
| 3 CLI data | 2d | 与 1 可并行 |
| 4 拆分 | 23d | 1+3 后 |
合计 MVP03**约 57 人日**。
---
## 6. 风险与缓解
| 风险 | 影响 | 缓解 |
|------|------|------|
| 用户习惯旧 tab 名 | 找不到 | hash 重定向 + 一周内双显示 tip |
| 合并后 section 过多 | 仍刷屏 | 运维/飞轮保持子导航 |
| `joy data search` 慢 | SSH+ollama | 超时 40s 保持;错误明文 |
| deprecated 仍被脚本调用 | 破脚本 | 转调兼容,不立刻 delete |
| 白名单 control 误关 | 运维不便 | 默认 execute 仍开;仅 full route 进 control |
| 大 PR 难审 | 返工 | 严格按 Phase 提交 |
---
## 7. 成功标准MVP = Phase 03
1. 一级 tab ≤ 10默认进入 **总览**
2. 写操作可见三态;协作 register/route 文案与代码一致
3. `joy data catalog` 与面板资产数一致
4. `joy help` 核心段 ≤ 20 行主命令deprecated 可发现
5. README 与 help 不再互相打架
6. pytest 全绿;手动 9 tab 无白屏
---
## 8. 评审清单
- [x] 9 tab IA 按意图(已确认)
- [x] A1`joy data``cluster-data` 语义(已确认)
- [x] B1默认总览已确认
- [x] C10→1→3→2→4已确认
- [x] 轻量 route 保持默认
- [x] Phase 4 后置,不进 MVP 强制范围
- [x] 本轮不强制改 linuxjoy watchdog除非 journal 相关已改过)
---
## 9. 建议执行顺序(确认后)
```
Phase 0 文档契约
Phase 1 面板 IA人立刻感到变清爽
Phase 3 joy data 同源 + CLI deprecated人机对齐
Phase 2 lite API性能
Phase 4 拆分(可另开迭代)
```
---
## 10. 变更影响面
| 路径 | Phase |
|------|-------|
| `src/joy/web/app.js` `index.html` `styles.css` | 1, 4 |
| `src/joy/commands/web.py` | 13 |
| `src/joy/commands/dashboard.py` | 2 |
| `src/joy/core/cluster_data.py` **新建** | 3 |
| `src/joy/commands/data.py` **新建** | 3 |
| `src/joy/commands/prlctl.py` `clone_restart.py` | 3 |
| `src/joy/commands/help.py` `README.md` | 0, 3 |
| `docs/joy-panel-cli-architecture-plan.md` | 0 |
---
**文档结束。下一步:评审(见会话内评审意见)→ 你确认 → 按 Phase 0 开工。**