Files
.pouch/skills/ship/references/record.md
T

218 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
2-develop/test-manifest.yaml # 开发者新增/修改测试的机器清单
status.md # 给人看的一页摘要
1-spec/ # 规格、评审、根因和 handoff
2-develop/ # 开发任务和变更
3-test/ # 任务验证与集成回归
4-review/ # PR、审核与合并
5-build/ # 合并后的构建/obtain
6-publish/ # 发布产物
7-deploy/ # 部署与健康检查
stage.yaml # 阶段状态和包含的步骤
activity.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`。
阶段目录由 `create_ship.py` 初始化,由 `next_step.py` 在派发和收到结果时追加活动记录;
大日志留在原测试、构建或部署位置,阶段目录只保存摘要和路径。
新建 ship 使用可排序的 `YYYYMMDD-短语`,例如 `20261014-dynamic-editor`。旧的无日期
记录仍可读取和校验,不要为了改名移动既有 ship 目录。
## 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
manager:
lastStep: null
lastResult: null
inFlight: null
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`。
用户可见的 canonical `stopAt` 与内部里程碑映射如下:
| stopAt | 停止含义 | 内部里程碑 |
| --- | --- | --- |
| `develop_verified` | 开发验证完成:单元测试、新增功能集成测试和静态检查通过;不等于完整回归 | `verified` |
| `review_ready` | PR/MR 已创建,等待审核 | `pr_opened` |
| `release_ready` | PR 已合并且完整回归通过;尚未表示发布或部署 | `regression_passed` |
| `released` | 产物已构建并发布 | `published` |
| `deployed` | 目标环境实际部署完成并通过健康检查 | `deployed` |
为兼容旧记录,`verified` 是 `develop_verified` 的别名,`validation_ready` 是
`release_ready` 的别名;新记录应使用 canonical 名称。`delivery.state` 内部里程碑
名称保持不变。
`source.kind`:`user` | `hunt` | `ack` | `pr` | `feishu`。修 ACK 缺陷时
`source.kind: ack` 且 `ref` 为缺陷任务 id。
`manager` 由入口主会话维护,可选。`lastStep` / `lastResult` / `lastSummary` 记录刚结束的那一步;
`inFlight` 在 worker 未返回时写成步骤名,返回后清掉。worker 不要写这些字段。
`lastResult`:`pass` | `fail` | `blocked` | `ask`。
## 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 缺陷板。
新建 ship 的任务默认带 `testPlan`。开发 worker 在 manifest 中记录测试的稳定 id、
runner、target、selector、覆盖的验收项和 `added|changed` 状态。`verify` 必须逐条执行
manifest;`regress` 在完整 tester catalog 和项目原生测试之外再次确认这些条目通过。
仅文档或明确无行为变化的任务可使用 `policy: not_applicable`,但必须填写被主会话接受的
`testGap.reason` 与 `acceptedBy`。
```yaml
shipId: add-export-button
tasks:
- id: T-01
title: 在列表页增加导出按钮
dependsOn: []
expected:
- 登录用户在列表页看到「导出」
verification:
- 浏览器打开列表页,按钮可见且可点
testPlan:
policy: required
manifest: 2-develop/test-manifest.yaml
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` 新建。