feat: rename bugfix-ship/requirement-flow to short-ship/long-ship with shared ship records
short-ship and long-ship share one ship-id record under .pouch/ship/<id>/. specifier writes PRDs into spec/; delivery-loop appends evidence pointers. Old names stay as deprecation stubs so existing installs keep working.
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
# Ship 记录契约
|
||||
|
||||
## 目录
|
||||
|
||||
- [布局](#布局)
|
||||
- [current.yaml](#currentyaml)
|
||||
- [short 与 long](#short-与-long)
|
||||
- [任务](#任务)
|
||||
- [证据指针](#证据指针)
|
||||
- [旧 specifier 目录](#旧-specifier-目录)
|
||||
|
||||
## 布局
|
||||
|
||||
```text
|
||||
.pouch/ship/<ship-id>/
|
||||
current.yaml # 总账:kind、状态、stopAt、指针
|
||||
spec.md # 短需求说明(short 和 long 都有)
|
||||
tasks.yaml # 本 ship 的任务 DAG
|
||||
status.md # 给人看的一页摘要
|
||||
spec/ # 仅 long:PRD 版本、评审、handoff
|
||||
brief.md
|
||||
prd-v001.html
|
||||
review.yaml
|
||||
decisions.yaml
|
||||
risks.yaml
|
||||
handoff.yaml # 仅 approved 后
|
||||
```
|
||||
|
||||
`status.md` 给人看;Agent 以 `current.yaml` 为准。两份不一致时改 `status.md`。
|
||||
|
||||
## current.yaml
|
||||
|
||||
必填:`shipId`、`kind`、`status`、`title`、`spec`、`tasks`、`evidence`。
|
||||
`shipId` 必须等于目录名。
|
||||
|
||||
```yaml
|
||||
shipId: add-export-button
|
||||
kind: short
|
||||
title: 列表页增加导出按钮
|
||||
status: in_progress
|
||||
stopAt: review_ready
|
||||
source:
|
||||
kind: user
|
||||
ref: null
|
||||
parentShipId: null
|
||||
childShipIds: []
|
||||
spec:
|
||||
path: spec.md
|
||||
revision: null
|
||||
specStatus: null
|
||||
prd: null
|
||||
approvedRevision: null
|
||||
reviews: null
|
||||
handoff: null
|
||||
tasks:
|
||||
path: tasks.yaml
|
||||
delivery:
|
||||
stopAt: review_ready
|
||||
state: change_ready
|
||||
evidence:
|
||||
testRuns: []
|
||||
artifacts: []
|
||||
deploys: []
|
||||
prs: []
|
||||
commits: []
|
||||
```
|
||||
|
||||
`kind`:`short` | `long`。
|
||||
|
||||
`status`:`draft`、`spec_review`、`approved`、`in_progress`、`blocked`、`done`、`parked`、`superseded`。
|
||||
|
||||
`delivery.state` 使用 delivery-loop 内部里程碑:`change_ready`、`verified`、
|
||||
`pr_opened`、`merged`、`regression_passed`、`artifact_built`、`published`、`deployed`。
|
||||
|
||||
`source.kind`:`user` | `hunt` | `ack` | `pr` | `feishu`。修 ACK 缺陷时
|
||||
`source.kind: ack` 且 `ref` 为缺陷任务 id。
|
||||
|
||||
## short 与 long
|
||||
|
||||
同一套字段,厚度不同。
|
||||
|
||||
| 字段 | short | long |
|
||||
| --- | --- | --- |
|
||||
| `spec.md` | 四段:要做什么、不做什么、可观察验收、怎么验。有故障证据时加复现和根因 | 同一四段作摘要 |
|
||||
| `spec/` | 不要创建 | specifier 写入 PRD、评审、决策、风险、handoff |
|
||||
| `spec.revision` 等 | 保持 `null` | 与 PRD 版本同步 |
|
||||
| `tasks.yaml` | 恰好 1 条 | DAG;`dependsOn` 指向本文件内 id |
|
||||
| 子项 | 无 | 默认是 task。只有该切片有独立 `stopAt` 并单独发布时才晋升为子 ship,写入 `childShipIds` |
|
||||
|
||||
范围变大时保持同一 `shipId`,把 `kind` 改成 `long`,补 `spec/` 并拆任务。
|
||||
|
||||
`spec.md` 不要写成 HTML PRD。long 的评审稿是 `spec/prd-vNNN.html`。
|
||||
|
||||
## 任务
|
||||
|
||||
`tasks.yaml` 只描述本 ship 的工作项,不是 ACK 缺陷板。
|
||||
|
||||
```yaml
|
||||
shipId: add-export-button
|
||||
tasks:
|
||||
- id: T-01
|
||||
title: 在列表页增加导出按钮
|
||||
dependsOn: []
|
||||
expected:
|
||||
- 登录用户在列表页看到「导出」
|
||||
verification:
|
||||
- 浏览器打开列表页,按钮可见且可点
|
||||
status: open
|
||||
stopAt: review_ready
|
||||
```
|
||||
|
||||
允许的任务 `status`:`open`、`in_progress`、`blocked`、`verified`、`merged`、`done`。
|
||||
|
||||
long 的子任务默认 `stopAt` 为 `pr_opened` 或 `merged`,不要单独打生产 tag 或升级生产。
|
||||
父 ship 在依赖任务完成后做集成回归,再按父记录的 `delivery.stopAt` 继续。
|
||||
|
||||
从 `spec/handoff.yaml` 建任务时复制 `id`、`title`、`dependsOn`、`expected`、
|
||||
`verification`,不要写进 `.pouch/ack/tasks.yaml`。
|
||||
|
||||
## 证据指针
|
||||
|
||||
不要把 tester 快照、镜像层或 compose 日志复制进 ship 目录。追加指针:
|
||||
|
||||
```yaml
|
||||
evidence:
|
||||
testRuns:
|
||||
- path: .pouch/tester/runs/20261013T031000Z-smoke-ab12.yaml
|
||||
result: pass
|
||||
suite: smoke
|
||||
artifacts:
|
||||
- sha: 0123456789abcdef0123456789abcdef01234567
|
||||
digest: sha256:abc
|
||||
ref: harbor.example.com/app:1.2.3
|
||||
venue: ci
|
||||
deploys:
|
||||
- env: test
|
||||
revision: 0123456789abcdef0123456789abcdef01234567
|
||||
health: pass
|
||||
prs:
|
||||
- url: https://git.example.com/app/-/merge_requests/12
|
||||
status: opened
|
||||
commits:
|
||||
- sha: 0123456789abcdef0123456789abcdef01234567
|
||||
role: baseline
|
||||
```
|
||||
|
||||
delivery-loop 阶段与指针:
|
||||
|
||||
| 阶段 | 至少追加 |
|
||||
| --- | --- |
|
||||
| `change_ready` | `commits` `role: baseline` |
|
||||
| `verified` | `testRuns` |
|
||||
| `pr_opened` | `prs` |
|
||||
| `merged` | `commits` `role: merged` |
|
||||
| `regression_passed` | `testRuns`(回归) |
|
||||
| `artifact_built` / `published` | `artifacts` |
|
||||
| `deployed` | `deploys` |
|
||||
|
||||
`path` 相对项目根。文件不存在则校验失败。用 `scripts/append_evidence.py` 追加后立刻
|
||||
`validate_ship.py`。
|
||||
|
||||
## 旧 specifier 目录
|
||||
|
||||
打开某个 id 时按这个顺序:
|
||||
|
||||
1. `.pouch/ship/<id>/` 已存在:用它。若同时还留着
|
||||
`.pouch/specifier/features/<id>/`,报告旧路径为遗留,不要两处同时写。
|
||||
2. 只有 `.pouch/specifier/features/<id>/`:把它移到 `.pouch/ship/<id>/spec/`,按旧
|
||||
`current.yaml` 生成 ship `current.yaml`(`kind: long`),用 `brief.md` 补
|
||||
`spec.md` 摘要,再校验。
|
||||
3. 两处都没有:由入口 skill 调用 `create_ship.py` 新建。
|
||||
Reference in New Issue
Block a user