Files
storage-labos/flashops/docs/workflow-spec.md
T
yuanshuai c91a64fddb
CI / Python 3.12 (push) Waiting to run
CI / Python 3.9 (push) Waiting to run
chore(repo): initialize team collaboration repository
2026-07-27 20:40:12 +08:00

124 lines
4.7 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.
# 工作流规范:SOP → 可执行状态机
> **当前状态**:这是待实现的发布与物化规范。数据库中已经保存一份符合该结构的
> 演示工作流,但 `WorkflowSpec` 完整 schema 校验、YAML 发布器与 `planner.py`
> 尚未落地;当前 API 不接受任意工作流上传。
工作流必须是**确定性的结构化配置**,不是让大模型自由生成命令(方案 §6.3、§8.1)。
AI 可以把自然语言 SOP 草拟成下面这份 YAML,但**必须过 schema 校验 + 人工发布**才能执行。
目标实现位置:`engine/planner.py`(物化)、`schemas.py::WorkflowSpec`(校验)
`workflows/fw-ab-regression.yaml`(版本化示例)。
## Schema
```yaml
key: fw-ab-regression # 全局唯一,改 key = 新工作流
name: 固件 A/B 回归
version: 3 # 每次发布 +1spec_hash 变了但 version 没变 → 拒绝发布
danger_level: high # none | low | high —— high 需要审批记录
source_sop: "客户X_固件回归SOP_v2.1(脱敏)"
params: # 运行时参数,带类型与默认值
loops: {type: int, default: 100, min: 1, max: 10000}
dut_serial: {type: string, required: true}
host: {type: string, required: true}
fw_a: {type: string, required: true} # firmware_artifact id
fw_b: {type: string, required: true}
resources: # 独占锁,PREFLIGHT 阶段获取,终态释放
- {type: dut, ref: params.dut_serial, exclusive: true}
- {type: test_host, ref: params.host, exclusive: true}
policy:
heartbeat_timeout_s: 30
max_recovery_per_loop: 3 # 单轮循环内恢复超过 3 次 → FREEZE
max_recovery_total: 20
on_data_integrity_failure: freeze # 硬编码值,写在这里只是为了显式
steps:
- key: preflight
type: precheck
adapter: safety
- key: flash-fw-a
type: command
adapter: nvme_cli
template: nvme_fw_download_commit # 只能引用已注册的签名模板
params: {firmware: "{{ params.fw_a }}", slot: 1, action: 3}
danger: high
timeout_s: 300
idempotent: false # 默认值,写出来是为了提醒:挂了不自动重跑
checkpoint: true
- key: regression-loop
type: loop
count: "{{ params.loops }}"
body:
- key: workload
type: command
adapter: fio
template: fio_seq_rw
timeout_s: 600
retry: 1
idempotent: true
- key: enumeration-check
type: device_check
adapter: nvme_cli
expect: {enumerated: true, link_speed_min: "8GT/s"}
- key: integrity-check
type: command
adapter: shell
template: sha256_readback
on_fail: freeze # 覆盖默认处置
checkpoint: true # 每轮结束落检查点
- key: report
type: report
adapter: builtin
```
## 步骤类型(MVP 六种)
| type | 语义 | 备注 |
|---|---|---|
| `command` | 执行签名命令模板 | 唯一能碰危险动作的类型 |
| `device_check` | 设备探针断言(枚举/固件版本/链路速率/SMART) | 不改变设备状态 |
| `wait` | 等待固定时长或条件 | 用于温度稳定、上电间隔 |
| `loop` | 固定次数循环,body 是步骤列表 | 支持嵌套一层 |
| `precheck` | 安全门禁 | 每个工作流的第一步都应该是它 |
| `report` | 生成报告与 Evidence Bundle | 内置适配器 |
企业版才加的:`http``parallel``subflow``approval``instrument`
这一波故意不做——`planner.py` 里遇到未知 type 直接拒绝发布,不静默跳过。
## 模板变量
只支持 `{{ params.X }}``{{ loop.index }}` 两种插值,**不支持表达式求值**。
理由:能求值就能注入。需要计算的场景写进适配器,不写进 YAML。
## 版本与 Git
工作流 YAML 进 `workflows/` 目录、进 Git。发布时控制平面记录:
```
workflows.spec 原文
workflows.spec_hash sha256(规范化后的 spec)
workflows.version 发布号
```
`spec_hash` 变了而 `version` 没变 → 拒绝发布。理由:A/B 对比的结论必须能追溯到
**具体哪一版流程**,否则"上周跑的和这周跑的是不是同一个流程"就说不清了。
## `on_fail` 的可选处置
| 值 | 行为 |
|---|---|
| `retry`(默认,受 `retry:` 次数约束) | 重试该步骤 |
| `fail_run` | 整个 Run 判 FAIL 并结束 |
| `continue` | 记失败,继续下一步(用于非关键采集步骤) |
| `freeze` | 立刻冻结现场,停止一切覆盖性动作 |
| `recover` | 进入恢复阶梯 |
数据完整性相关的步骤**只允许** `freeze`planner 校验时强制。