chore(repo): initialize team collaboration repository
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
# 工作流规范: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 # 每次发布 +1;spec_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 校验时强制。
|
||||
Reference in New Issue
Block a user