- API.md 新增第 5 节:列表/详情/手记/改内容/状态动作/从事项沉淀 + 7xxx 错误码 - ROADMAP 增 M3 全节与 DOD,验收用例补 11–13,明确 3.8 向量索引未跑 - README 状态表:知识已通、pgvector 只有配置 - DEVELOPMENT 补三条 e2e 命令与「先想一条能失败的断言」
This commit is contained in:
+90
-2
@@ -1,4 +1,4 @@
|
||||
# 接口约定(M0–M2 已实现)
|
||||
# 接口约定(M0–M3 已实现)
|
||||
|
||||
> 只写**已经在跑**的接口。写完没验证的东西不进这份文档。
|
||||
> 前缀 `/api/v1`。所有响应都是同一个信封,**HTTP 200 不代表业务成功**。
|
||||
@@ -301,7 +301,95 @@ canceled→ todo (恢复)
|
||||
|
||||
---
|
||||
|
||||
## 5. 健康与版本
|
||||
## 5. 知识 `/workspaces/{ws_id}`
|
||||
|
||||
### 5.1 `GET /knowledge`
|
||||
|
||||
| 参数 | 说明 |
|
||||
|---|---|
|
||||
| `status` | 可重复;`draft`/`in_review`/`published`/`archived`,不传为全部 |
|
||||
| `doc_type` | `note`/`howto`/`faq`/`postmortem`/`decision` |
|
||||
| `source_item_id` | 按来源事项筛 |
|
||||
| `q` | 标题 / 正文 / 摘要子串 |
|
||||
| `limit` | 1–100,默认 30 |
|
||||
| `cursor` | 上一页的 `next_cursor` |
|
||||
|
||||
返回 `{items, next_cursor, has_more}`。每条是 `item` 字段 + `knowledge` + `source`:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "…", "kind": "knowledge", "title": "发票原件必须一起寄",
|
||||
"body_md": "…", "status": "published", "tags": [],
|
||||
"knowledge": {
|
||||
"doc_type": "howto", "summary": "…", "status_hint": "published",
|
||||
"source_kind": "task", "source_item_id": "…", "generated_by": "human",
|
||||
"published_at": "2026-10-28T05:54:44Z", "archived_at": null,
|
||||
"chunk_count": 0, "author_id": "…"
|
||||
},
|
||||
"source": {"id": "…", "kind": "task", "title": "发票原件必须一起寄", "status": "done"}
|
||||
}
|
||||
```
|
||||
|
||||
> `status` 与 `knowledge.status_hint` 是同一件事:前者在 `item` 上(复用事项表),
|
||||
> 后者在 `knowledge_doc` 上(列表按知识口径筛时不必回连 `item`)。**两者必须同步**,
|
||||
> 状态动作接口会一起写。
|
||||
|
||||
### 5.2 `GET /knowledge/{item_id}`
|
||||
|
||||
详情,附最近 50 条 `activities`。不存在或跨租户统一 `7001`。
|
||||
|
||||
### 5.3 `POST /knowledge` — 手记或指定来源
|
||||
|
||||
```json
|
||||
{"title": "报销单要贴发票原件", "body_md": "…", "doc_type": "note",
|
||||
"source_item_id": "可选的来源事项 id"}
|
||||
```
|
||||
|
||||
- 不带 `source_item_id` → `source_kind=manual`(手记),允许没有来源。
|
||||
- 带 → 来源必须是同工作区的 `task`/`ticket`,否则 `7005`。
|
||||
- 新知识一律 `draft`,不会直接对外可见。
|
||||
|
||||
### 5.4 `PATCH /knowledge/{item_id}` — 修改内容
|
||||
|
||||
必须带 `version`(乐观锁,冲突 `4009`)。可改 `title`/`body_md`/`summary`/`doc_type`。
|
||||
**已发布的不许直接改**(`7003`,先撤回审议或归档),避免"发布后被悄悄改写"。
|
||||
|
||||
### 5.5 `POST /knowledge/{item_id}/status` — 状态动作
|
||||
|
||||
| action | 允许的前置状态 | 结果 | 谁能做 |
|
||||
|---|---|---|---|
|
||||
| `submit_review` | draft | in_review | 成员 |
|
||||
| `withdraw` | in_review | draft | 成员 |
|
||||
| `publish` | draft / in_review | published | owner / admin |
|
||||
| `archive` | draft / in_review / published | archived | 成员 |
|
||||
| `restore` | archived | draft | 成员 |
|
||||
|
||||
非法动作返回 `7003`,`details.allowed_from` 是动作要求的前置状态,`details.allowed_actions`
|
||||
是当前状态下还能做什么——前端据此渲染按钮,不用自己维护一份状态机。
|
||||
|
||||
**发布要 owner/admin 的理由**:发布等于团队为这条结论背书,不能谁都能推。
|
||||
|
||||
### 5.6 `POST /items/{item_id}/knowledge` — 把一件事沉淀成知识
|
||||
|
||||
Query:`doc_type`(默认 `postmortem`)。来源可以是任务或工单;工单会带出验收结论。
|
||||
返回与 5.2 相同的知识对象;同一来源重复沉淀 → `7002`。
|
||||
|
||||
**工单验收通过时,后端会自动调用这条逻辑**(`generated_by=rule`,`doc_type=postmortem`,
|
||||
正文开头固定一句"这份草稿由系统根据来源自动整理,请先核对再发布"),所以用户不需要记得点。
|
||||
|
||||
### 5.7 知识的错误码
|
||||
|
||||
| 码 | HTTP | 含义 |
|
||||
|---|---|---|
|
||||
| 7001 | 404 | 知识不存在,或不是知识 |
|
||||
| 7002 | 409 | 这个来源已经有知识了 |
|
||||
| 7003 | 409 | 当前状态不允许这个动作 |
|
||||
| 7004 | 403 | 权限不足(如非管理员发布) |
|
||||
| 7005 | 409 | 来源事项无效或缺失 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 健康与版本
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
|
||||
@@ -84,11 +84,16 @@ ruff check . && ruff format --check .
|
||||
|
||||
```bash
|
||||
cd web
|
||||
node e2e/smoke.mjs # 登录→建任务→详情保存→看板拖拽→非法流转被拒,7 项断言
|
||||
node e2e/smoke.mjs # 登录→建任务→详情保存→看板拖拽→非法流转被拒,7 项断言
|
||||
node e2e/tickets.mjs # 双人:升级工单→受理→提交→验收→原任务回流,8 项断言
|
||||
node e2e/knowledge.mjs # 沉淀成知识→待核对→发布,7 项断言
|
||||
```
|
||||
|
||||
用本机缓存的 Chromium(`playwright-core`,不下载浏览器),截图落在 `web/e2e/artifacts/`。
|
||||
|
||||
> e2e 抓的都是"手动点几下看不出来"的问题:字段缺失导致整页白屏、请求竞态导致的空列表、
|
||||
> 点错按钮的 404。加功能时**先想一条能失败的断言**,再动手写页面。
|
||||
|
||||
### 1000 条下的首屏耗时
|
||||
|
||||
```bash
|
||||
|
||||
@@ -261,7 +261,36 @@
|
||||
|
||||
---
|
||||
|
||||
## 关键验收用例(M0–M2 必须通过)
|
||||
## M3 · 知识库(第 7–8 周,10 人日)
|
||||
|
||||
| # | 任务 | 人日 | 状态 |
|
||||
|---|---|---|---|
|
||||
| 3.1 | `knowledge_doc`(1:1 于 item,`source_kind` + `source_item_id` 必填约束)+ 迁移 0004 + RLS | 1.0 | [x] 已跑通,隔离测试覆盖 |
|
||||
| 3.2 | 状态机 `draft / in_review / published / archived`,发布要 owner/admin | 0.5 | [x] 5 个动作,非法动作回 `allowed_from` + `allowed_actions` |
|
||||
| 3.3 | 结构化编辑:标题 / 正文 / 摘要 / 类型,乐观锁,已发布禁改 | 1.0 | [x] 含 `4009` 冲突用例 |
|
||||
| 3.4 | **闭环沉淀**:工单验收通过自动生成草稿(`generated_by=rule`),同一来源只生成一次 | 1.5 | [x] 只转述不推断,正文带"请先核对再发布" |
|
||||
| 3.5 | 手动沉淀:任务/工单详情里"沉淀成知识" | 0.5 | [x] 有 e2e |
|
||||
| 3.6 | 手记:没有来源的知识(唯一允许 `source_kind=manual` 的入口) | 0.5 | [x] 手记页 + 列表 |
|
||||
| 3.7 | 检索:标题/正文/摘要子串 + 类型/状态筛选 + 游标分页 | 1.0 | [x] trigram 索引在 0002 已建 |
|
||||
| 3.8 | 切片与向量索引(`chunk` 表、pgvector HNSW) | 2.0 | [ ] 见下方说明 |
|
||||
| 3.9 | 安卓知识列表 | 1.0 | [ ] 与工单一起延后到编译链就绪 |
|
||||
| 3.10 | 文档与 e2e | 1.0 | [x] `web/e2e/knowledge.mjs` 7 项断言绿 |
|
||||
|
||||
### M3 完成定义(DOD)
|
||||
- [x] 一件事办完 → 自动出现一份草稿 → 核对 → 发布,全程不用手动复制粘贴
|
||||
- [x] 每条知识都能追到来源(除手记),点开能看到来源事项
|
||||
- [x] 非管理员发布被拒;跨租户看不到别人的知识
|
||||
- [ ] 向量切片与语义检索(需要独立 pgvector 实例真正跑起来)
|
||||
- [ ] 真实用两周:新同事靠知识库自己解决过一次问题(需要真实团队)
|
||||
|
||||
**关于 3.8 的说明**:本机 Docker 起不来、fnsvr-01 上也没有 pgvector 扩展,
|
||||
所以 `deploy/docker-compose.vector.yml` 与 `VECTOR_DATABASE_URL` 只有配置,**没有跑过**。
|
||||
按"写完不算完成"的规矩,它在真跑起来之前保持未勾。切片表设计要点已写进
|
||||
`2.Design/PRODUCT-PLAN.md` 的 D8,落地时不要改 `EMBEDDING_DIM`(改了要重算全量)。
|
||||
|
||||
---
|
||||
|
||||
## 关键验收用例(M0–M3 必须通过)
|
||||
|
||||
| # | 用例 | 期望 | 现状 |
|
||||
|---|---|---|---|
|
||||
@@ -275,14 +304,16 @@
|
||||
| 8 | 部署后 `/version` | commit 与仓库 HEAD 一致 | [~] 机制已有,等部署验证 |
|
||||
| 9 | 办理人验收自己的工单 | 403 `6004`,不能自己给自己过 | ✅ 已覆盖 |
|
||||
| 10 | 工单验收通过后原任务 | 自动从"被阻塞"回到"待办",事件流留痕 | ✅ 已覆盖(含 e2e) |
|
||||
| 11 | 工单验收通过后知识库 | 自动出现一份草稿,且只生成一次 | ✅ 已覆盖 |
|
||||
| 12 | 成员发布知识 | 403 `7004`;owner 发布成功且记录发布时间 | ✅ 已覆盖 |
|
||||
| 13 | 知识有没有来源 | 非手记必须有 `source_item_id`,否则 7005 / 库级约束拒绝 | ✅ 已覆盖 |
|
||||
|
||||
---
|
||||
|
||||
## 下一步排期建议
|
||||
|
||||
```
|
||||
已完成 0.1–0.9 骨架与认证 + 1.1–1.7 任务域 + 2.1–2.6 工单协同(含双人 e2e)
|
||||
待补 0.11 部署 / 0.12 契约 / 0.14 微信 spike / CI 在 Gitea 实跑 / 安卓编译链
|
||||
第7–8周 M3 知识:knowledge_doc + chunk、切片与索引、工单关闭生成草稿、带引用问答
|
||||
已完成 0.1–0.9 骨架与认证 + 1.1–1.7 任务域 + 2.1–2.6 工单协同 + 3.1–3.7、3.10 知识库
|
||||
待补 0.11 部署 / 0.12 契约 / 0.14 微信 spike / CI 在 Gitea 实跑 / 安卓编译链 / 3.8 向量索引
|
||||
第9–10周 M4 AI:结构化录入、人物工作侧写、主动提醒、20 条黄金用例回归
|
||||
```
|
||||
|
||||
@@ -21,13 +21,15 @@
|
||||
|---|---|
|
||||
| 手机号验证码登录、刷新令牌、幂等请求 | ✅ 已实现并有测试 |
|
||||
| 工作区 / 成员 / 邀请码加入,跨租户隔离(RLS) | ✅ 同上 |
|
||||
| 任务:收件箱→待办→进行中→完成、截止时间、标签、评论、事件流、乐观锁 | ✅ 后端 + Web 已通,57 个测试全绿 |
|
||||
| 任务:收件箱→待办→进行中→完成、截止时间、标签、评论、事件流、乐观锁 | ✅ 后端 + Web 已通 |
|
||||
| Web 列表 / 看板拖拽 / 详情侧栏编辑 / 键盘流 / 快速录入语法 | ✅ e2e 7 项断言全绿,构建通过 |
|
||||
| 1000 条任务下的首屏性能 | ✅ 实测 P50 38–55ms(目标 < 300ms) |
|
||||
| 安卓端任务列表与详情 | ⚠️ 代码已写,**本机无 JDK/Gradle,未编译验证** |
|
||||
| 工单:升级不搬数据、受理→办理→提交→验收、驳回、改派、站内通知 | ✅ 后端 + Web 已通,双人 e2e 8 项全绿 |
|
||||
| 后端测试 | ✅ 57 passed,ruff 干净 |
|
||||
| 知识库、LLM 能力 | ⬜ M3–M4 |
|
||||
| 知识:工单验收自动生成草稿、核对后发布、来源可追、手记 | ✅ 后端 + Web 已通,e2e 7 项全绿 |
|
||||
| 后端测试 | ✅ 65 passed,ruff 干净 |
|
||||
| 知识切片与语义检索(pgvector) | ⬜ 配置已就绪(`deploy/docker-compose.vector.yml`),本机 Docker 起不来,未跑过 |
|
||||
| 安卓端知识页 / LLM 能力 | ⬜ M3 收尾 / M4 |
|
||||
|
||||
## 快速开始
|
||||
|
||||
|
||||
Reference in New Issue
Block a user