# 02-V-界面与交互 管理后台是黑灯工厂的"驾驶舱"(架构文档第 13 节),不只是配置页面,而是覆盖项目创建、目标提出、bug 反馈、实时看板、过程检查、Artifact/Skill 管理的完整人机交互控制台。MVP 单用户,无角色权限矩阵;MVP 单项目,页面里预留项目筛选但不强制做完整的项目列表/切换体验。 实时性原则:凡标注"实时"的页面/组件,均通过 WebSocket 订阅 `execution_event` 流更新(架构文档 13.1 节决策 3),不做轮询。 ## 2.0 导航壳层(新增,2026-07-30,源自 `docs/wireframes/` 连页原型) 此前各页面只逐条描述字段/事件,没有定义跨页共享的导航结构,会导致同一个信息架构问题被不同实现者各自猜测。以下结构在制作 `docs/wireframes/*.html` 连页原型时确定,供实现时直接采用: - **常驻顶部导航**(除 `v_project_setup` 外全部页面共享):`仪表盘`(`v_dashboard`)→ `任务`(`v_task_board`)→ `产物`(`v_artifact_browser`)→ `技能库`(`v_skill_library`)→ `设置`(下拉菜单,含并发数/预算护栏/日志保留三个子项,分别指向 `v_concurrency_settings`/`v_budget_settings`/`v_log_retention_settings`) - **不进常驻导航的页面**: - `v_project_setup`——首次使用或点导航栏右上角"切换项目"链接进入,属于项目切换流程,不是常规导航项 - `v_goal_composer`/`v_bug_feedback`——通过 `v_dashboard` 的按钮进入(`click_propose_goal`/`click_report_bug`),原型阶段做成独立路由页面而非弹层(02-V 原描述"可作为弹层,也可独立路由"在此处收敛为"独立路由",弹层与否是纯 UI 实现细节,不影响信息结构,实现时如改用弹层不需要回来改本节) - `v_task_detail`/`v_skill_audit_log`——分别从 `v_task_board`/`v_skill_library` 的列表项点击进入,不是导航项 - **导航栏右侧**:当前项目名 + "切换项目"链接(指向 `v_project_setup`) 参照实现(无构建步骤的静态 HTML,DOM/class 命名与本文档字段一一对应,可直接作为实现起点):`docs/wireframes/v_project_setup.html` 起,共 12 个路由页面 + `v_graph_visualizer.html` 内嵌组件示范。 ## 2.1 页面:`v_project_setup` 项目创建/选择 - 参照原型:`docs/wireframes/v_project_setup.html` - 路由:`/setup`(首次使用或需要更换目标项目时进入) - 载体说明(架构文档 13.1 节决策 5):控制台是本地 Web 应用,不是桌面应用;点击"选择文件夹"时前端调用 `c_pick_folder`,由本机常驻的后端进程代为拉起 OS 原生文件夹选择对话框并返回真实绝对路径,不使用浏览器 File System Access API - 字段: - `folder_path` 默认只读文本展示(由 `c_pick_folder` 回填,避免手动输入拼错路径),必填;仅当 `c_pick_folder` 返回 `DIALOG_UNAVAILABLE` 时,字段切换为可编辑的手动输入兜底 - `project_name` 文本输入,非必填(留空则取文件夹名) - 交互事件:`click_pick_folder` → 触发 `c_pick_folder`,成功回填 `folder_path`;用户取消系统对话框则 `folder_path` 保持原值不变;返回 `DIALOG_UNAVAILABLE` 时提示"当前环境不支持弹窗选择,请手动输入路径"并解锁手动编辑 - 提交流程: 1. 选择文件夹后先校验 `has_git_repo`(探测 `.git` 是否存在) 2. 若不是 Git 仓库,弹出确认态"该文件夹还不是 Git 仓库,是否代为初始化(`git init`)?"——用户确认前不写入任何文件(对应护栏规则:`Prohibited`/`Explicit permission required` 类操作不能静默执行) 3. 确认后调用 `c_project_create`,创建 `.graphlemon/` 子目录 4. 成功 → 跳转 `v_dashboard`;失败 → 展示具体错误(如路径不可写) - 异常态:文件夹不存在、无写权限、路径已被注册为其他项目(幂等命中,直接跳转已有项目看板而非报错) ## 2.2 页面:`v_dashboard` 实时看板首页 - 参照原型:`docs/wireframes/v_dashboard.html` - 路由:`/`(默认首页) - 权限:`all` - 展示内容(全部实时刷新): - Org Graph 三节点状态卡片:`planner`/`coder`/`validator` 各自当前是否有 `active` 的 `work_graph_run`,高亮当前 `task.assigned_org_node` - 当前任务概要:`goal_text` 摘要、`loop_round`、`status` - 预算用量条:引用 `budget_guardrail_config.current_usage`/`limit_value`,实时更新 - 最近事件时间线:最近 N 条 `execution_event`,滚动追加(新事件从顶部滑入,对应 WebSocket 推送到达) - 交互事件: - `click_propose_goal` → 打开 `v_goal_composer` - `click_report_bug` → 打开 `v_bug_feedback` - `click_task_card` → 跳转 `v_task_detail` - 异常态:无任何任务时展示"暂无运行中任务"空态 + 醒目的"提出第一个目标"引导按钮;WebSocket 连接断开时展示"实时连接已断开,正在重连"提示条,不阻塞页面其余只读内容展示 - **信息态(新增,2026-07-29)**:有任务处于 `waiting_for_quota` 时展示"等待 Claude Code 额度恢复({session\|weekly\|opus}),预计 {剩余等待时长}"提示条——样式是信息性的浅色条,不是 `blocked_pending_human` 那种醒目告警样式,因为这是自愈型阻塞不需要人工操作;`click` 可展开跳转到对应 `v_task_detail` ## 2.3 页面:`v_goal_composer` 提出目标 - 参照原型:`docs/wireframes/v_goal_composer.html` - 路由:`/goals/new`(可作为 `v_dashboard` 的弹层,也可独立路由) - 字段: - `goal_text` 多行文本输入,必填,校验 `maxLen:4000` - 提交流程:提交前校验非空 → 确认态展示即将创建的任务摘要 → 调用 `c_task_create`(`created_via=human_console`)→ 成功跳转 `v_task_detail` - 异常态:为空提交时内联校验提示,不发起请求 ## 2.4 页面:`v_bug_feedback` 人工反馈 bug - 参照原型:`docs/wireframes/v_bug_feedback.html` - 路由:`/bugs/new` - 字段: - `description` 多行文本,必填 - `repro_steps` 多行文本,非必填(允许先反馈现象,复现步骤后补) - `related_task_id` 下拉选择器,非必填(关联到某个已有任务;留空则视为新发现的独立问题) - 提交流程:提交 → 调用 `c_bug_report_create`(创建 `bug_record(source=human, status=open)`)→ 成功提示"已提交,Validator 将进行归因确认" → 跳转到该 bug 的详情视图(复用 `v_task_detail` 的 bug 展示区,或独立 `v_bug_detail`,MVP 复用前者) - 异常态:`description` 为空时内联校验拦截 ## 2.5 页面:`v_task_board` 任务看板 - 参照原型:`docs/wireframes/v_task_board.html` - 路由:`/tasks` - 字段: - `keyword` 搜索框,非必填,校验 `maxLen:128` - `status_filter` 下拉,选项对应 `task.status` 枚举 - `org_node_filter` 下拉,选项 `planner`\|`coder`\|`validator` - 展示列表项(实时):`task_id`、`goal_text` 摘要、`status`、`assigned_org_node`、`loop_round`、`updated_at`,`status` 变化时该行有动效高亮(对应收到 `task_status_changed` 事件) - 交互事件:`click_row` → 跳转 `v_task_detail`;`click_search` → 触发 `c_task_list` - 异常态:空态"暂无任务";加载失败态提示重试 ## 2.6 页面:`v_task_detail` 任务详情 / 过程检查 - 参照原型:`docs/wireframes/v_task_detail.html` - 路由:`/tasks/:task_id` - 字段:只读展示 `task` 全部字段 + 关联 `artifact` 列表 + 关联 `bug_record` 列表 - 子模块: - 内嵌 `v_graph_visualizer`(该 task 当前 `work_graph_run` 的实时图结构) - **`org_node=coder` 的 to-do 树视图(新增,2026-07-30,回应"task 层级关系看不出来"的核对)**:把当前 `work_graph_run.graph_manifest`(即 to-do list 本身,见 01-M §1.3 补充说明)渲染为缩进树,而不只是 `v_graph_visualizer` 的按层 DAG 行;每个 to-do 节点标注对应 `work_node_execution.status`,点开能展开到该节点的执行详情/日志(复用下方"每个 work_node_execution 支持展开"能力)。体现的层级是 `project → task → work_graph_run → to-do 树(graph_manifest)→ work_node_execution → execution_log_file`,明确这是 task 内部单个 Coder Work Graph 的结构,不是多个 task 组成的树。 - 事件时间线:该 task 全部 `execution_event`,按时间正序展示,支持展开查看 `payload` 详情(这是"检查过程"诉求的核心落地) - 每个 `work_node_execution` 支持展开查看 `input_payload`/`output_payload`/`reflection_notes`/`retry_count` - 内嵌 `v_log_viewer`(该 `work_node_execution` 的原始执行日志,控制台内直接查看,见 2.7.1) - 交互事件: - `click_artifact_link` → 打开对应文件(目标项目内 `.graphlemon/runs/` 或源码路径) - `click_view_raw_log` → 展开 `v_log_viewer`(不再是外部深链,见架构文档 13.1 节决策 4 的修正) - `click_retry`(仅 `status=blocked_pending_human` 时可见)→ 触发人工干预(`manual_resume`) - 异常态:`blocked_pending_human` 状态需醒目告警样式 ## 2.7 页面:`v_graph_visualizer` Org/Work Graph 实时可视化 - 参照原型:`docs/wireframes/v_graph_visualizer.html` - 内嵌组件,非独立路由 - 展示内容: - Org Graph 层:固定三节点图,高亮当前节点 - Work Graph 层:当前 `work_graph_run.graph_manifest` 渲染的节点/边图,节点按 `work_node_execution.status` 实时着色(`done`=绿、`running`=蓝、`reflecting`/`retrying`=黄、`waiting_for_quota`=浅蓝+时钟图标(信息性,非告警样式,见 03-C 3.6 节)、`blocked`/`failed`=红、`pending`=灰),状态变化时对应节点有过渡动效(对应收到 `node_status_changed` 事件) - 交互事件:`hover_node` → tooltip 展示 `input_schema_ref`/`output_schema_ref`/`retry_count` 摘要;`waiting_for_quota` 态额外展示 `quota_limit_type` 和已等待时长 - 无可执行变化时可回归条件:无 `work_graph_run` 记录时展示"尚未开始规划"占位态 ## 2.7.1 组件:`v_log_viewer` 原始执行日志查看器(架构文档 13.1 节决策 4) - 内嵌组件,非独立路由,被 `v_task_detail` 按 `node_exec_id` 引用 - 字段:`node_exec_id`(必填,决定查看哪个 Work Node 的日志) - 展示内容: - `work_node_execution.status IN (pending, running, reflecting, retrying)` 时:实时滚动模式,通过 WebSocket 订阅该节点日志流,新内容持续追加到底部(对应 `execution_event(event_type=log_appended)`) - `status IN (done, blocked, failed)` 时:静态模式,一次性拉取 `execution_log_file` 全量内容(大文件分页加载,避免一次性渲染卡顿) - 交互事件: - `toggle_auto_scroll` → 前端本地状态,是否自动滚动到最新一行 - `click_download` → 下载完整日志文件(`c_execution_log_get` 的下载态) - 异常态: - `execution_log_file.status=purged`(已被定时清理)→ 展示"该日志已超过保留期限被清理,保留天数可在设置中调整",不报错 - 日志文件本身写入失败/丢失 → 展示"日志暂不可用"而非空白页面 ## 2.8 页面:`v_artifact_browser` Artifact 浏览器 - 参照原型:`docs/wireframes/v_artifact_browser.html` - 路由:`/artifacts` - 字段:`artifact_type_filter` 下拉、`task_id_filter` 下拉 - 展示:列表 + 预览(Markdown 类型直接渲染,代码类型语法高亮,均为只读) - 交互事件:`click_row` → 展示 `depends_on_artifact_ids` 血缘链(图形化展示版本依赖关系) - 异常态:空态"暂无产物" ## 2.9 页面:`v_skill_library` Skill 库管理 - 参照原型:`docs/wireframes/v_skill_library.html` - 路由:`/skills` - 展示:`skill` 列表(按 `owner_org_node` 分组:Planner/Coder/Validator),每项展示 `source`(是否迁移自 Hermes profile / 新建 / 自动迭代产生) - 交互事件:`click_skill` → 跳转 `v_skill_audit_log` ## 2.10 页面:`v_skill_audit_log` Skill 变更审计日志 - 参照原型:`docs/wireframes/v_skill_audit_log.html` - 路由:`/skills/:skill_id/audit` - 字段:只读列表,展示 `skill_iteration` 记录:`applied_at`、`triggered_by_bug_id`、`change_summary`、`before/after_git_commit_sha` - 交互事件: - `click_diff` → 展示 Git diff - `click_rollback` → 触发 `c_skill_rollback`,生成新的 `skill_iteration` 记录 - 异常态:空态"该 Skill 尚无自主迭代记录" ## 2.11 页面:`v_concurrency_settings` 并发数配置 - 参照原型:`docs/wireframes/v_concurrency_settings.html` - 路由:`/settings/concurrency` - 字段:`max_concurrent_goals` 数字输入,必填,校验 `range:1-50` - 交互事件:`submit_save` → 触发 `c_concurrency_config_update` - 提交流程:校验 → 确认态 → 成功提示"已更新,下一个新 Goal 起生效" ## 2.12 页面:`v_budget_settings` 预算护栏配置 - 参照原型:`docs/wireframes/v_budget_settings.html` - 路由:`/settings/budget` - 字段:`scope` 下拉、`limit_type` 下拉、`limit_value` 数字输入,均必填 - 展示:当前用量进度条(实时) - 交互事件:`submit_save` → 触发 `c_budget_config_update` - 异常态:超限时展示告警条 + "查看已暂停任务"链接(跳转 `v_task_board` 预置 `status_filter=blocked_pending_human`) ## 2.13 页面:`v_log_retention_settings` 日志保留策略配置(架构文档 13.1 节决策 4) - 参照原型:`docs/wireframes/v_log_retention_settings.html` - 路由:`/settings/log-retention` - 字段: - `retention_days` 数字输入,必填,校验 `>0` - `max_total_size_mb` 数字输入,非必填 - 展示:当前日志总占用大小(汇总所有 `status=active|closed` 的 `execution_log_file.size_bytes`) - 交互事件:`submit_save` → 触发 `c_log_retention_config_update` - 异常态:`retention_days` 填 0 或负数时内联校验拦截