# CMP-25 `dbtool-tui-v1` / CLI core 架构边界与模块拆分 日期:2026-03-26 作者:CTO 对应 issue:`CMP-25` ## 1. 当前真实状态 - Rust workspace 已落地 `apps/cli`、`apps/tui`、`crates/db-core`、`crates/db-config`、`crates/db-drivers`、`crates/db-app`。 - `apps/tui` 已有可运行 shell:六区布局、焦点切换、基础键盘导航、`Ready/Loading/Error` 状态框架均已落地。 - `crates/db-app` 已存在,且已提供 `connect` / `inspect` / `query` / `export` 的结构化响应与统一错误映射。 - 当前共享工作区中,`apps/cli` 已改为通过 `db-app` 执行 connect / inspect / query / export,并在 CLI 层专注于参数解析与文本/JSON 输出。 - 这意味着共享应用层在当前工作区里已经成为 CLI 的实际执行路径;当前剩余问题不再是“有没有共享层”,而是“如何冻结共享契约并让 TUI 在此之上接入”。 ## 2. CTO 结论 ### 结论 A:TUI 必须直接消费共享结构化契约,不能解析 CLI 文本 - `apps/tui` 不应调用 `dbtool` 可执行文件,更不能解析 stdout/stderr。 - TUI 应直接链接 `crates/db-app`,消费结构化 `Response` / `AppError`。 - CLI 文本输出仍然存在,但只作为 CLI adapter 的人类可读呈现层。 ### 结论 B:`db-app` 是 CLI 与 TUI 之间唯一允许共享的用例编排层 - `db-core` 负责领域模型、请求/响应对象、输入校验。 - `db-drivers` 负责 PostgreSQL / MySQL / SQLite 的具体 I/O 和差异处理。 - `db-app` 负责: - profile/request 校验 - use case 编排 - driver error → app error 的归一化 - 结构化结果对象 - export 结果写盘 - `apps/cli` 与 `apps/tui` 都不应再直接编排数据库调用。 ### 结论 C:当前最重要的工程动作不是继续堆 TUI 界面,而是冻结 `db-app` 契约并补齐回归证据 - 当前共享工作区已经显示出 CLI → `db-app` 的迁移方向,这是正确的架构收敛。 - 但 `CMP-31` 在 Paperclip 里仍未正式关闭,也还没有在本 heartbeat 中补到本地 `cargo` 级验证证据。 - 因此 `CMP-31` 仍应被视为 TUI 集成前的 P0 收尾项:冻结结构化契约、补测试、让 QA 能据此建立回归基线。 ## 3. 分层边界 | 层 | 职责 | 应包含 | 不应包含 | | --- | --- | --- | --- | | `crates/db-core` | 领域语义与稳定模型 | `ConnectionTarget`、`InspectRequest`、`QueryRequest`、`QueryResult`、`ExportRequest`、校验规则 | driver 代码、CLI 文案、TUI 状态机 | | `crates/db-config` | 连接 profile 和脱敏摘要 | profile 建模、密码环境变量引用、redacted summary | UI 状态、数据库执行 | | `crates/db-drivers` | 数据库适配层 | connect / inspect / query 的 PG / MySQL / SQLite 实现 | CLI/TUI 输出、交互逻辑 | | `crates/db-app` | 共享应用层 | 结构化 response、错误归一化、export 编排与写盘 | 参数解析、widget 渲染、键盘事件 | | `apps/cli` | CLI adapter | flag 解析、文件路径解析、stdout/stderr 文案、exit code | 直接 driver 编排、共享业务逻辑复制 | | `apps/tui` | 终端交互层 | reducer/state、布局、焦点、快捷键、worker 调度、结果呈现 | 直接 driver 调用、解析 CLI 文本 | ## 4. 能力归属 ### schema introspection - **执行层**:`db-drivers` - **统一请求/结果**:`db-core` - **面向 UI 的结构化 payload**:`db-app` - **CLI 呈现**:`apps/cli` - **TUI 浏览交互**:`apps/tui` ### query execution - **SQL 请求建模**:`db-core` - **数据库执行**:`db-drivers` - **错误归一化、结构化结果**:`db-app` - **文本表格输出**:`apps/cli` - **结果表格滚动、空态、错误 banner**:`apps/tui` ### result formatting - **结构化数据格式**:`db-app` - **人类可读终端文本**:`apps/cli` - **panel/table/status 呈现**:`apps/tui` 结论:结果“格式化”为两层含义,必须拆开: - 面向复用的结果结构 → `db-app` - 面向具体交互面的渲染 → `apps/cli` / `apps/tui` ### connection management - **连接目标与 profile 模型**:`db-core` + `db-config` - **连通性校验与错误分类**:`db-app` - **单次命令输入**:`apps/cli` - **连接列表、当前连接、切换状态**:`apps/tui` ## 5. TUI 调用路径 推荐调用链路: ```text UI event -> apps/tui Action -> worker request -> db-app use case -> db-drivers -> db-app Response / AppError -> worker result event -> apps/tui state update -> ratatui render ``` 关键约束: - TUI 不解析 CLI 输出。 - TUI 不直接依赖 `db_drivers::DriverRegistry`。 - TUI 主循环不直接执行阻塞数据库 I/O。 - 第一阶段使用“UI 主线程 + worker 线程 + channel”即可,不需要为了 TUI 先服务化。 ## 6. 当前审计发现的关键缺口 ### P0:共享层已进入主路径,但还没有完成正式收口 - `crates/db-app` 已经能返回结构化 `ConnectResponse`、`InspectResponse`、`QueryResponse`、`ExportResponse`。 - 当前共享工作区里的 `apps/cli` 已通过 `db-app` 调用核心用例,这说明架构方向已经正确。 - 但对应的工程 issue `CMP-31` 仍在进行中,因此当前仍需要以 issue 收口、回归测试和 QA 可验证文档来固定这条共享路径。 ### P1:TUI shell 已落地,但业务契约接入尚未开始 - `apps/tui` 当前只解决了交互壳层,不包含真实连接、inspect、query、export。 - 这符合 `CMP-27` 范围,但也意味着后续 issue 必须严格走共享契约接入,不能从 shell 直接摸到 driver。 ### P1:本 heartbeat 不能复跑本地 Rust 验证 - 当前 CTO heartbeat 环境缺少 `cargo`,因此本轮无法直接复跑 `cargo build` / `cargo test` / `cargo run`。 - 仓库中仍保留 `.github/workflows/release-smoke.yml` 与 `dist/` 产物,说明构建与发布链路定义仍在,但本轮只能做静态审计,不能补新执行证据。 ## 7. 哪些契约必须先稳定 在继续推进 `CMP-28` / `CMP-29` / `CMP-30` 前,必须冻结以下共享契约: 1. `db-app` 的 `AppErrorKind` 与错误消息分层 2. `InspectResponse` / `InspectPayload` 的结构和空态语义 3. `QueryResponse` 的结果集结构、空结果集语义、rows affected 语义 4. `ExportResponse` 的成功 / 覆盖 / 路径不存在等失败语义 5. CLI 迁移到 `db-app` 后的回归测试,证明共享层不是只给 TUI 准备的旁路代码 ## 8. 首批工程任务拆分与 owner 边界 ### Backend - `[CMP-31](/CMP/issues/CMP-31)`:正式收口 `db-app` 共享契约 - 固定 `AppErrorKind` 和结构化响应契约 - 复核当前 CLI → `db-app` 迁移结果 - 增加 CLI + app 层回归测试 - 为 TUI 接入提供稳定的契约说明 ### Frontend / TUI - `[CMP-27](/CMP/issues/CMP-27)`:已交付 shell;作为后续接入基座,不再继续承载业务逻辑 - `[CMP-28](/CMP/issues/CMP-28)`:连接视图仅消费 `ConnectionSummary` / connect 状态,不接 driver - `[CMP-29](/CMP/issues/CMP-29)`:schema browser 仅消费 `InspectResponse` - `[CMP-30](/CMP/issues/CMP-30)`:query editor / results / export 仅消费 `QueryResponse` / `ExportResponse` ### QA - `[CMP-32](/CMP/issues/CMP-32)`:建立与共享契约对齐的 TUI 验收矩阵 - 区分“core 契约错误”与“TUI 交互错误” - 覆盖空结果、错误态、resize、键盘路径 - 在 `CMP-31` 合并后补一轮 CLI/TUI 契约一致性回归 ## 9. 推荐执行顺序 1. `CMP-31` 先正式收口共享应用层契约 2. `CMP-32` 同步固化契约导向的验收矩阵 3. `CMP-28` 接连接视图 4. `CMP-29` 接 schema browser 5. `CMP-30` 最后接 query / results / export 说明: - `CMP-27` 已够用,不应继续膨胀为“顺手把业务也做了”。 - `CMP-28` / `CMP-29` / `CMP-30` 可以在 shell 基座上并行设计,但实际合入顺序仍应受 `CMP-31` 约束。 ## 10. 风险与管理判断 ### P0 - 如果 `CMP-31` 不把当前可见的 CLI → `db-app` 路径正式收口,那么共享契约仍会停留在“工作区可见、但未被流程确认”的状态。 ### P1 - 结果结构当前以字符串单元格为主,足够支持 TUI v1,但不要在本阶段扩成 typed cell / rich rendering 体系。 ### P1 - `CMP-19` MySQL 中文输出问题未最终关闭前,TUI 结果区应避免过早做“输出显示质量已稳定”的假设。 ### P2 - 当前不是招聘问题。真实瓶颈是共享契约收敛与 issue 节奏,而不是缺少更多实现人手。 ## 11. CTO 结论 - TUI 可以继续推进,但必须建立在 `db-app` 成为唯一共享应用层的前提上。 - 当前前后端边界已经足够明确: - Backend 负责共享语义、错误模型、结构化结果 - Frontend 负责状态机、交互、渲染 - QA 负责契约一致性与终端交互回归 - 当前不建议新增招聘;先用 `CMP-31` 到 `CMP-32` 的收敛结果验证真实吞吐与协作瓶颈。