124 lines
9.1 KiB
Markdown
124 lines
9.1 KiB
Markdown
# AGENTS.md — ChuSQL 开发契约
|
||||
|
|
|
|||
|
|
给 AI agent 的项目规则。**约束优先于便利**:任何"暂时放宽"都必须先在此文件里改数字,并说明理由,否则视为违约。
|
|||
|
|
进度与待办的唯一事实来源是 `projectplan.txt`;本文件只管"什么算做完"。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 硬约束(CONSTRAINTS)
|
|||
|
|
|
|||
|
|
违反任一条 = 改动不算完成,不许提交、不许进 `projectplan.txt` 的 ✅。
|
|||
|
|
|
|||
|
|
| # | 约束 | 当前值 | 校验方式 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| C1 | Haskell 测试全绿 | **381 条**(engine 200 + web 181) | `cd chusql-engine && stack test`、`cd chusql-web && stack test` |
|
|||
|
|
| C2 | Rust 测试全绿 | **78 条** | `cd chusql-storage && cargo test` |
|
|||
|
|
| C3 | Haskell 编译零警告 | `-Wall` 下 **0 warning** | `stack build` 输出无 `warning:`(engine 与 web 两个包都要看) |
|
|||
|
|
| C4 | 不引入抑制手段 | 禁止 `{-# OPTIONS_GHC -Wno-... #-}`、`#[allow(...)]`、`@ts-ignore`、`--no-verify`、跳过/删除测试、注释掉断言 | 看 diff |
|
|||
|
|
| C5 | 不吞错误 | Rust 拿不到 `unwrap()/expect()` 当控制流;Haskell 不用 `error`/`head` 兜底。能返回错误的走 `Result` / `Either` | 看 diff + clippy 提示 |
|
|||
|
|
| C6 | 索引语义不得回退 | "索引列必须唯一"是**决策 14**,不是实现细节;放宽它必须同时改 `projectplan.txt` 的已知问题 6/9 | 看 diff |
|
|||
|
|
| C7 | 性能结论必须同轮交叉测 | 机器漂移 15~25%(已知问题 4);**小于 2 倍的差异不当结论**,改前改后必须同轮前后跑 | 基准记录 |
|
|||
|
|
| C8 | 已实测的功能不许只留"应该能跑" | 新能力要么有测试断言,要么在 `projectplan.txt` 标 ⬜ 未做 | 看 `projectplan.txt` |
|
|||
|
|
| C9 | 测试数下降 = 阻塞 | 新增测试可以增数;数字变小必须解释哪条被移除及原因 | 前后对比 |
|
|||
|
|
|
|||
|
|
**已知的历史违约模式**(别重复):
|
|||
|
|
- P1 遗留:`Spec.hs` 的 "INSERT ... via IPC" 用例只断言了结果,**没断言"没走 scan"** —— 需求被"测试绿了"掩盖。补法是检查服务端 debug 日志里不出现 `scan`。
|
|||
|
|
- 若哪天要"为了跑通先注释掉断言" —— 停手,改成把这条写进 `projectplan.txt` 的 ⬜。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 改动规则
|
|||
|
|
|
|||
|
|
1. **改 `chusql-engine` 源码后**,跑全链路基准前必须先 `stack build --force-dirty`,否则基准可能链到旧引擎(plan 第 146 行)。
|
|||
|
|
2. **表存在性判据**以 `catalog` 为准(不是文件长度),空表也是合法表;改这条要先搜它**所有**调用点(决策 7、8)。
|
|||
|
|
3. **索引元数据只放一处**(数据字典)。优化器只把"单列等值条件"标成"可点查",有没有索引由存储层回答(`no_index` → 上层退回全表扫描)。不许在优化器里缓存一份索引表(决策 13)。
|
|||
|
|
4. **等价改造不许改结果**。典型:等值连接换哈希表,输出顺序必须和嵌套循环一致(左表序为主、右表序为辅,同键下右行保序);认不出等值键或某侧空表时退回嵌套循环(决策 9)。
|
|||
|
|
5. **存储接口分 `schema` 与 `snapshot`**:语义检查与优化只走 `schema`,不许再拉全库行(决策 10)。
|
|||
|
|
6. **测试的位置约定**:Haskell 引擎测试全部在 `chusql-engine/test/Spec.hs`;Web 在 `chusql-web/test/Spec.hs`(web 是独立包,不能反向依赖 engine 的测试);Rust 在 `chusql-storage/tests/*_test.rs`,另有 `src/log.rs` 里 3 条单元测试。新增测试放同一处,不另起目录。
|
|||
|
|
7. **只留根目录一个 README**:性能基准的跑法/结果/踩坑都写进 `README.md`;设计长文写 `docs/ENGINE_INTRO.md`、`docs/STORAGE_INTRO.md`,P3 的规格写 `docs/WEB_SPEC.md`。
|
|||
|
|
8. 改任何**决策**或**已知问题**,同一轮内更新 `projectplan.txt`。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 已知正确性缺口(最高优先级)
|
|||
|
|
|
|||
|
|
- **重放不幂等**(已知问题 1):断电卡在"数据已落盘"与"日志清空"之间时,重启会把同一操作再作用一遍,`INSERT` 多一行。**这是当前唯一的正确性缺口**,不是功能缺失。
|
|||
|
|
做 P7 完整版 WAL 时,验收标准 = 给每次操作记 LSN、重放前比对是否已作用过,并有一条"中途断电重放两次、行数不变"的测试。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Skill 路由表
|
|||
|
|
|
|||
|
|
已安装 7 个相关 skill(源:`addyosmani/agent-skills`,全局位于 `~/.agents/skills`)。按阶段加载,**不要全部加载**。
|
|||
|
|
|
|||
|
|
| 阶段 | 先加载 | 用途 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 任何阶段开工 | `constraint-driven-development` | 对照本文件 C1–C9,检查本轮有没有偷偷降标准 |
|
|||
|
|
| 写代码 / 修 bug(全程) | `test-driven-development` | 先红后绿;C1/C2 的 200/181/78 是底线 |
|
|||
|
|
| 编译失败、测试失败、行为不符预期、IPC/FFI 异常 | `debugging-and-error-recovery` | 根因定位,禁止"试一下看看"式修改 |
|
|||
|
|
| P3 Web(✅ 已完成,改动 Web 时仍照此走) | `spec-driven-development` → `api-and-interface-design` → `security-and-hardening` | 先出 spec 再定接口,最后过输入校验与 Session 安全 |
|
|||
|
|
| P3 启动前(无 spec 时) | `spec-driven-development` | Web 涉及 5 块能力,必须先拆能力图 |
|
|||
|
|
| P4 CLI | `api-and-interface-design` | 与 Web 共用 Haskell 后端,接口一次定稳 |
|
|||
|
|
| P5 FFI(C ABI + 跨语言所有权) | `api-and-interface-design` → `debugging-and-error-recovery` | ABI 契约 + 内存所有权问题定位 |
|
|||
|
|
| P2 遗留 A/B(字节键、重复键、范围扫描) | `test-driven-development` → `performance-optimization` | 重写比较器与分裂节点,必须有前后同轮数字 |
|
|||
|
|
| P6 SQL 功能补齐 | `test-driven-development` | 每条语法/语义能力都要有用例 |
|
|||
|
|
| P7 代价优化 / 统计信息被"用"上 | `performance-optimization` | 遵 C7;已知问题 3(池淘汰 O(池容量))绝对值 2.8 µs/次,先证明值得改 |
|
|||
|
|
| P7 完整版 WAL(含重放幂等) | `debugging-and-error-recovery` + 对抗式复核 | 见上面第 3 节,正确性问题 |
|
|||
|
|
|
|||
|
|
**明确不用**(本项目场景不匹配,别加载):
|
|||
|
|
`browser-testing-with-devtools`(需 chrome-devtools MCP,本机没配;Web 的端到端用
|
|||
|
|
`stack test` 里那条真 HTTP 用例顶着)、
|
|||
|
|
`deprecation-and-migration`、`observability-and-instrumentation`、`shipping-and-launch`(无生产部署)、
|
|||
|
|
`planning-and-task-breakdown`(路线图已在 `projectplan.txt`)、
|
|||
|
|
`git-workflow-and-versioning` / `code-review-and-quality` / `refactor` / `code-simplification`(与既有习惯重叠,只增流程噪音)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 每轮收尾清单
|
|||
|
|
|
|||
|
|
- [ ] `cd chusql-engine && stack test` → 200 条全绿
|
|||
|
|
- [ ] `cd chusql-web && stack test` → 181 条全绿(含一条真起 Rust 存储进程的端到端;`static/` 未构建时 14 条构建产物契约测试记 pending)
|
|||
|
|
- [ ] `cd chusql-storage && cargo test` → 78 条全绿
|
|||
|
|
- [ ] `stack build` 输出 0 warning(`-Wall`,engine 与 web 两个包)
|
|||
|
|
- [ ] diff 里没有 C4 列的抑制手段
|
|||
|
|
- [ ] 动过性能路径 → 同轮交叉测,数字进 `README.md` 表格
|
|||
|
|
- [ ] 动过决策/已知问题 → `projectplan.txt` 同一轮更新
|
|||
|
|
- [ ] 新能力的测试数只增不减(C9)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 常用命令
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Haskell 引擎测试
|
|||
|
|
cd chusql-engine && stack test
|
|||
|
|
|
|||
|
|
# Web 测试(端到端那条会自己 cargo build --bin chusql-storage 并起真进程)
|
|||
|
|
cd chusql-web && stack test
|
|||
|
|
|
|||
|
|
# Rust 测试
|
|||
|
|
cd chusql-storage && cargo test
|
|||
|
|
|
|||
|
|
# 一键把三个模块都起来(Rust 存储 + Haskell Web + 浏览器)
|
|||
|
|
# .\script\chusql.ps1 web -Port 9000 临时端口(关掉即失效)
|
|||
|
|
# .\script\chusql.ps1 config set port 9000 存成设置(script\chusql.settings.json)
|
|||
|
|
# .\script\chusql.ps1 config / cli / help 看设置 / CLI 占位(会起 web)/ 帮助
|
|||
|
|
# (每个开关都能换成 CHUSQL_* 环境变量;清单见 README 的配置表)
|
|||
|
|
# 手动分开起(一条命令连 Rust 存储进程一起拉)
|
|||
|
|
cd chusql-storage && cargo build --release
|
|||
|
|
cd chusql-web && stack run chusql-web -- --storage ../chusql-storage/target/release/chusql-storage.exe
|
|||
|
|
# 浏览器打开 http://127.0.0.1:7777/ ;
|
|||
|
|
# 端口被占或被系统保留时换一个:--port 7778
|
|||
|
|
# (Windows 查保留段:netsh interface ipv4 show excludedportrange protocol=tcp)
|
|||
|
|
|
|||
|
|
# 全链路基准(Haskell 引擎 + Rust 存储进程一起起)
|
|||
|
|
cd chusql-storage && cargo build --release
|
|||
|
|
cd benchmark/fullchain && stack run chusql-fullchain -- 1000 1000
|
|||
|
|
# ⚠️ 改过 chusql-engine 源码 → 先 stack build --force-dirty
|
|||
|
|
|
|||
|
|
# 分层基准
|
|||
|
|
cd benchmark/chusql-engine && stack run # 查询层(内存数据,隔离优化器)
|
|||
|
|
cd benchmark/chusql-storage && cargo bench --offline # 存储层微基准
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
> 上一轮评估:2026-09-25(P3 ⑰ 全部完成:按 DataGrip 截图把界面整个重做——主工具栏 + "Database Explorer" 工具窗(标题栏窗口动作/小工具栏/连接→库→schema→Database Objects→表→列的树)+ 标签页 + 数据编辑器工具栏 + 带行号槽与类型字形的网格 + 状态栏;图标换成 IDEA 风格线稿,配色换 IDEA 深浅两套;顺手做实了标签页、行号槽、单元格游标与方向键、工具栏加减行、DDL 只读查看、树过滤、折叠全部、工具窗三个窗口动作与下拉菜单)。下一项:P2 遗留 A/B(复合键 + 字节键 → 非唯一索引)。
|