Skip to content
This repository was archived by the owner on Apr 11, 2026. It is now read-only.

Commit 4d2782a

Browse files
z23ccclaude
andcommitted
chore: Phase 0 cleanup — delete flowctl-web, fix daemon tests, update TODOS
- Delete flowctl-web crate (3700+ lines of dead Leptos code, replaced by React) - Fix 2 daemon test regressions: use valid fn-N task IDs, disable force in done handler - Update TODOS.md: remove obsolete Leptos entry, add DESIGN.md TODO - Add CEO plan design doc to docs/designs/ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent a4364cf commit 4d2782a

25 files changed

Lines changed: 133 additions & 3721 deletions

TODOS.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
**Effort:** XL (human: ~2 weeks / CC: ~2 hours)
88
**Priority:** P2
99
**Depends on:** File splits (admin/task/workflow) should happen first to reduce diff size.
10+
**Note:** The Web Platform project (React frontend + daemon POST API) partially addresses this -- the POST API endpoints will call service layer functions, establishing the pattern for full extraction.
1011

11-
## Leptos SSR Integration Cleanup
12-
**What:** Move Leptos SSR fallback routing from main.rs to server.rs.
13-
**Why:** Cosmetic separation of concerns. main.rs should only do CLI parsing, server.rs should own all HTTP routing.
14-
**Context:** Currently main.rs:534-539 has the Leptos fallback logic inline. server.rs already has build_router() and serve_tcp(). No correctness issue, just organizational.
15-
**Effort:** S (human: ~1 hour / CC: ~5 min)
12+
## Create DESIGN.md
13+
**What:** Create a formal design system document for the flow-code web platform.
14+
**Why:** No DESIGN.md exists. Design decisions are scattered across CEO plan and design review notes. A formal document ensures consistency for contributors.
15+
**Context:** Design review rated the project 4/10 → 7/10 on design completeness. Key design tokens (colors, spacing, typography) were defined during review but not persisted in a DESIGN.md. Run /design-consultation to create it.
16+
**Effort:** S (human: ~2 hours / CC: ~15 min)
1617
**Priority:** P3
17-
**Depends on:** Nothing. Revisit when server.rs grows beyond 200 lines.
18+
**Depends on:** Web platform implementation (so the design system reflects actual usage)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
---
2+
status: ACTIVE
3+
---
4+
# CEO Plan: flow-code Web Orchestration Platform (Full-Stack Rewrite)
5+
6+
Generated by /plan-ceo-review on 2026-04-05
7+
Branch: main | Mode: SCOPE EXPANSION
8+
Repo: z23cc/flow-code
9+
10+
## Vision
11+
12+
### 10x Check
13+
flow-code 从"Claude Code 插件的调试面板"升级为 **AI 开发的标准控制面板**
14+
打开浏览器即可看到所有 AI agent 在实时工作的 DAG 图、执行日志、性能指标。
15+
任何 AI coding tool 连上来就能被统一管理。
16+
Airflow 之于数据工程 = flow-code 之于 AI 编程。
17+
18+
### Success Metrics
19+
- Web UI 可完成 80%+ 的日常操作(创建 epic、启动 work、管理依赖、查看进度)
20+
- DAG 渲染 50+ 节点无卡顿(< 16ms per frame)
21+
- WebSocket 断连后 3 秒内自动重连
22+
- 页面首屏加载 < 500ms,交互响应 < 100ms
23+
- Bundle size < 1MB
24+
25+
### Platonic Ideal
26+
打开 http://127.0.0.1:17319:
27+
- 左边是 DAG 画布,任务节点在实时流动,关键路径红色高亮
28+
- 右边是 agent 日志流,每个 agent 一个 tab,实时输出代码差异
29+
- 顶部是全局状态条 HUD:3/8 tasks done, 2 agents active, 0 blocked
30+
- Cmd+K 命令面板:输入 "start" 就能启动,输入 "block" 就能阻塞
31+
- 全程零等待,WebSocket 推送一切,页面从不��新
32+
- 时间轴显示 Wave 1 → Checkpoint → Wave 2 的执行脉搏
33+
34+
## Scope Decisions
35+
36+
| # | Proposal | Effort | Decision | Reasoning |
37+
|---|----------|--------|----------|-----------|
38+
| 1 | Cmd+K 命令面板 | M | ACCEPTED | Web 取代 CLI 的核心体验 |
39+
| 2 | 实时运行统计 HUD | S | ACCEPTED | 一眼看到全局状态 |
40+
| 3 | 任务详情侧边栏 | M | ACCEPTED | 原地操作不跳转,Linear 风格 |
41+
| 4 | 波次可视化时间轴 | M | ACCEPTED | flow-code 独有功能,差异化 |
42+
| 5 | 多 AI 客户端状态页 | L | ACCEPTED | "平台"核心语义 |
43+
| 6 | 执行回放 (Replay) | L | ACCEPTED | 团队展��� + 调试利器 |
44+
| 7 | 暗色/亮色主题 + 动效系统 | M | ACCEPTED | 让平台"活"起来 |
45+
46+
## Accepted Scope (added to design doc)
47+
48+
基础范围(来自设计文档):
49+
- 9+ POST/DELETE API 端点(完整 schema)
50+
- WebSocket 协议(5 种事件类型 + 心跳重连)
51+
- 统一设计系统(CSS 变量 + 通��组件 + 状态颜色映射)
52+
- 7 个页面全部升级为交互式
53+
- 文件锁 API
54+
- 错误处理约定
55+
56+
扩展范围(CEO Review 新增):
57+
- Cmd+K 命令面板(搜索 + 执行操作,不只是过滤)
58+
- 全局 HUD 状态条(WebSocket 驱动,永不刷新)
59+
- 任务详情侧边栏(点击节点/行滑出面板)
60+
- 波次-检查点时间轴(DAG 视图下方)
61+
- 多 AI 客户端状态页:显示通过 HTTP API 连接的客户端(注册协议:`POST /api/clients` + 定期心跳)。本版本范围限于 Claude Code 单客户端 + 预留多客户端 UI。多 AI 协议设计延后。
62+
- 执行回放:范围限于单个 epic 的最近一次执行。基于已有的 `started_at`/`completed_at` 时间戳 + `duration_seconds` 字段重建时间线。不存储额外快照数据。
63+
- 完整主题系统 + 动效体系(过渡动画、骨架屏、脉冲、流光)。与设计系统同步在 Phase 1 建立基础,Phase 9 打��细节。
64+
65+
## Architecture
66+
67+
```
68+
┌──────────────────────────────────┐
69+
│ React Frontend │
70+
│ ┌─────┐ ┌──���─┐ ┌──────────────┐ │
71+
│ │Cmd+K│ │HUD │ │ Task Sidebar │ │
72+
│ └─────┘ └────┘ └──────────────┘ │
73+
│ ┌─────────┐ ┌─────────────────┐ │
74+
│ │DAG+Wave │ │ Agent Console │ │
75+
│ │Timeline │ │ Replay │ │
76+
│ └─────────┘ └─────────────────┘ │
77+
└───────┬──────────┬───────────────┘
78+
│ REST │ WebSocket
79+
┌─��─────��──────────┴───────────────┐
80+
│ Daemon (axum + tower) │
81+
│ ┌────────┐ ┌──────────────────┐ │
82+
│ │handlers│ │ event_bus (emit) │ │
83+
│ └───┬────┘ └────────┬─────────┘ │
84+
│ │ │ │
85+
│ ┌─��─┴────────────┐ │ │
86+
│ │ service layer │ │ │
87+
│ │ (lifecycle.rs) ├──┘ │
88+
│ └───┬────────────┘ │
89+
│ │ │
90+
│ ┌───┴────┐ │
91+
│ │ SQLite │ │
92+
│ └────────┘ │
93+
└──────────────────────────────────┘
94+
```
95+
96+
## Implementation Phases
97+
98+
**Phase 1-2 可并行**(设计系统不依赖后端,后端不依赖前端组件)
99+
**Phase 6-8 可并行**(Cmd+K、Agent Console、Replay 互不依赖)
100+
101+
1. 设计系统 + 主题 + 动效基础 → 输出:CSS 变量文件 + 6 个通用组件 + 暗��主题
102+
2. 后端 POST/DELETE API + WebSocket emit → 输出:10+ 可调用端点 + WS 消息流
103+
3. DAG View 升级(拖拽依赖、CPM 高亮、波次时间轴)��� 输出:可交互 DAG 页面
104+
4. Dashboard + HUD + Epic Detail → 输出:统计面板 + 全局状态条 + 操作按钮
105+
5. Cmd+K 命令面板 + 任务侧边栏 → 输出:可执行操作的搜索面板 + 详情抽屉
106+
6. Agent Console + 客户端状态页 → 输出:实时日志流 + 客户端注册页
107+
7. Replay 执行回放 → 输出:基于时间戳的 DAG 动画播放器
108+
8. 全局打磨(响应式、快捷键、亮色主题、边界处理)→ 输出:完整交付
109+
110+
## Deferred to TODOS.md
111+
- Token 使用趋势图(触发条件:daemon 开始收集 token 使用数据后)
112+
- Agent 暂停功能(触发条件:用户需求确认 + daemon 进程管理设计完成)
113+
- 多项目切换(触发条件:有用户同时管理多个项目的真实需求)
114+
- 认证系统(触发条件:daemon 暴露到网络或多用户场景)
115+
- 多 AI 客户端协议设计(触发条件:第二个非 Claude Code 客户端接入时)

flowctl/crates/flowctl-daemon/src/handlers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ pub async fn done_task_handler(
242242
summary_file: None,
243243
evidence_json: None,
244244
evidence_inline: None,
245-
force: true,
245+
force: false,
246246
actor: "daemon".to_string(),
247247
};
248248
flowctl_service::lifecycle::done_task(Some(&conn), &flow_dir, req)

flowctl/crates/flowctl-daemon/src/server.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,16 +327,16 @@ mod tests {
327327
async fn start_task_validates_transition() {
328328
// Setup: create epic + task in todo state, then start it (should succeed),
329329
// then try to start again from in_progress (should fail with CONFLICT).
330-
let (tmp, runtime, event_bus) = test_setup();
330+
let (_tmp, runtime, event_bus) = test_setup();
331331
let (state, _cancel) = create_state(runtime, event_bus).unwrap();
332332
{
333333
let conn = state.db.lock().unwrap();
334334
conn.execute(
335-
"INSERT INTO epics (id, title, status, file_path, created_at, updated_at) VALUES ('e1', 'E', 'open', 'e.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
335+
"INSERT INTO epics (id, title, status, file_path, created_at, updated_at) VALUES ('fn-1', 'E', 'open', 'e.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
336336
[],
337337
).unwrap();
338338
conn.execute(
339-
"INSERT INTO tasks (id, epic_id, title, status, domain, file_path, created_at, updated_at) VALUES ('e1.1', 'e1', 'T', 'todo', 'general', 't.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
339+
"INSERT INTO tasks (id, epic_id, title, status, domain, file_path, created_at, updated_at) VALUES ('fn-1.1', 'fn-1', 'T', 'todo', 'general', 't.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
340340
[],
341341
).unwrap();
342342
}
@@ -347,7 +347,7 @@ mod tests {
347347
.method("POST")
348348
.uri("/api/v1/tasks/start")
349349
.header("content-type", "application/json")
350-
.body(axum::body::Body::from(r#"{"task_id":"e1.1"}"#))
350+
.body(axum::body::Body::from(r#"{"task_id":"fn-1.1"}"#))
351351
.unwrap();
352352
let resp = tower::ServiceExt::oneshot(app, req).await.unwrap();
353353
assert_eq!(resp.status(), StatusCode::OK);
@@ -358,7 +358,7 @@ mod tests {
358358
.method("POST")
359359
.uri("/api/v1/tasks/done")
360360
.header("content-type", "application/json")
361-
.body(axum::body::Body::from(r#"{"task_id":"e1.1"}"#))
361+
.body(axum::body::Body::from(r#"{"task_id":"fn-1.1"}"#))
362362
.unwrap();
363363
let resp = tower::ServiceExt::oneshot(app2, req).await.unwrap();
364364
assert_eq!(resp.status(), StatusCode::OK);
@@ -369,24 +369,24 @@ mod tests {
369369
.method("POST")
370370
.uri("/api/v1/tasks/start")
371371
.header("content-type", "application/json")
372-
.body(axum::body::Body::from(r#"{"task_id":"e1.1"}"#))
372+
.body(axum::body::Body::from(r#"{"task_id":"fn-1.1"}"#))
373373
.unwrap();
374374
let resp = tower::ServiceExt::oneshot(app3, req).await.unwrap();
375375
assert_eq!(resp.status(), StatusCode::CONFLICT);
376376
}
377377

378378
#[tokio::test]
379379
async fn done_task_rejects_from_todo() {
380-
let (tmp, runtime, event_bus) = test_setup();
380+
let (_tmp, runtime, event_bus) = test_setup();
381381
let (state, _cancel) = create_state(runtime, event_bus).unwrap();
382382
{
383383
let conn = state.db.lock().unwrap();
384384
conn.execute(
385-
"INSERT INTO epics (id, title, status, file_path, created_at, updated_at) VALUES ('e2', 'E', 'open', 'e.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
385+
"INSERT INTO epics (id, title, status, file_path, created_at, updated_at) VALUES ('fn-2', 'E', 'open', 'e.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
386386
[],
387387
).unwrap();
388388
conn.execute(
389-
"INSERT INTO tasks (id, epic_id, title, status, domain, file_path, created_at, updated_at) VALUES ('e2.1', 'e2', 'T', 'todo', 'general', 't.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
389+
"INSERT INTO tasks (id, epic_id, title, status, domain, file_path, created_at, updated_at) VALUES ('fn-2.1', 'fn-2', 'T', 'todo', 'general', 't.md', '2025-01-01T00:00:00Z', '2025-01-01T00:00:00Z')",
390390
[],
391391
).unwrap();
392392
}
@@ -397,7 +397,7 @@ mod tests {
397397
.method("POST")
398398
.uri("/api/v1/tasks/done")
399399
.header("content-type", "application/json")
400-
.body(axum::body::Body::from(r#"{"task_id":"e2.1"}"#))
400+
.body(axum::body::Body::from(r#"{"task_id":"fn-2.1"}"#))
401401
.unwrap();
402402
let resp = tower::ServiceExt::oneshot(app, req).await.unwrap();
403403
assert_eq!(resp.status(), StatusCode::CONFLICT);

flowctl/crates/flowctl-web/Cargo.toml

Lines changed: 0 additions & 44 deletions
This file was deleted.

flowctl/crates/flowctl-web/public/favicon.ico

Whitespace-only changes.

0 commit comments

Comments
 (0)