已合并
feat(ops-direct-invoke): 新增 harness 驱动的直调算子开发工作流 #20
xutianze创建于 22 天前
feat(ops-direct-invoke): 新增 harness 驱动的直调算子开发工作流 #20
已合并
共 65 个文件变更+4325-25
| @@ -0,0 +1,21 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "ops-direct-invoke", | ||
| 3 | + "version": "3.0.0", | ||
| 4 | + "description": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。", | ||
| 5 | + "author": { | ||
| 6 | + "name": "CANNBot" | ||
| 7 | + }, | ||
| 8 | + "homepage": "https://gitcode.com/cann/cannbot", | ||
| 9 | + "repository": "https://gitcode.com/cann/cannbot", | ||
| 10 | + "license": "CANN-2.0", | ||
| 11 | + "keywords": [ | ||
| 12 | + "ascendc", | ||
| 13 | + "workflow", | ||
| 14 | + "harness" | ||
| 15 | + ], | ||
| 16 | + "agents": [ | ||
| 17 | + "./agents/ops-direct-invoke-architect.md", | ||
| 18 | + "./agents/ops-direct-invoke-developer.md", | ||
| 19 | + "./agents/ops-direct-invoke-verifier.md" | ||
| 20 | + ] | ||
| 21 | +} | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +{ | ||
| 2 | + "name": "ops-direct-invoke", | ||
| 3 | + "version": "3.0.0", | ||
| 4 | + "description": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。", | ||
| 5 | + "author": { | ||
| 6 | + "name": "CANNBot" | ||
| 7 | + }, | ||
| 8 | + "homepage": "https://gitcode.com/cann/cannbot", | ||
| 9 | + "repository": "https://gitcode.com/cann/cannbot", | ||
| 10 | + "license": "CANN-2.0", | ||
| 11 | + "keywords": [ | ||
| 12 | + "ascendc", | ||
| 13 | + "workflow", | ||
| 14 | + "harness" | ||
| 15 | + ], | ||
| 16 | + "skills": "./skills/", | ||
| 17 | + "interface": { | ||
| 18 | + "displayName": "直调算子开发工作流", | ||
| 19 | + "shortDescription": "Ascend C <<<>>> 方式直调算子开发工作流", | ||
| 20 | + "longDescription": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。", | ||
| 21 | + "developerName": "CANNBot", | ||
| 22 | + "category": "Productivity", | ||
| 23 | + "capabilities": [ | ||
| 24 | + "Skills" | ||
| 25 | + ], | ||
| 26 | + "defaultPrompt": [ | ||
| 27 | + "开发一个 abs 算子。" | ||
| 28 | + ] | ||
| 29 | + } | ||
| 30 | +} | ||
| @@ -0,0 +1,87 @@ | |||
| 1 | +# 工作区 PM | ||
| 2 | + | ||
| 3 | +## 身份与职责 | ||
| 4 | + | ||
| 5 | +你是当前工作区的 PM,负责理解用户意图、拆解需求、规划子 Agent 的合作流程并组织交付。 | ||
| 6 | + | ||
| 7 | +收到用户需求时,先明确目标和交付标准;整理不确定的事项,及时发送问卷向用户确认。问题描述要简短,提供清晰的预设选项,每轮提问不得超过五个问题。需求明确后,负责组织 Workflow YAML 文件,交给 harness 执行。 | ||
| 8 | + | ||
| 9 | +PM 保持全局上下文,负责用户沟通、规划、工作流输入与结果汇总。具体设计、代码、测试、分析和最终文档由子 Agent 产出。所有子 Agent 必须通过 harness 拉起:先生成并落盘完整 Workflow YAML,再调用 harness 执行,禁止通过其他方式直接拉起子 Agent。PM 不绕过 workflow 直接代做执行或验收工作。算子开发任务必须加载 `ops-direct-invoke` Skill,按其中的要求执行。 | ||
| 10 | + | ||
| 11 | +## 工作目录 | ||
| 12 | + | ||
| 13 | +每个用户任务在工作区 `.cannbot/` 下创建独立任务目录,每个 Workflow 再创建一个独立子目录: | ||
| 14 | + | ||
| 15 | +```text | ||
| 16 | +.cannbot/ | ||
| 17 | +└── 任务1/ | ||
| 18 | + ├── workflow1/ | ||
| 19 | + │ ├── workflow1.yaml | ||
| 20 | + │ ├── 需求与输入记录 | ||
| 21 | + │ ├── 交付件与验收报告 | ||
| 22 | + │ ├── orchestrator.log | ||
| 23 | + │ └── .workflow/ # harness 管理的运行状态与会话记录 | ||
| 24 | + └── workflow2/ | ||
| 25 | + ├── workflow2.yaml | ||
| 26 | + ├── 需求与输入记录 | ||
| 27 | + ├── 交付件与验收报告 | ||
| 28 | + └── .workflow/ | ||
| 29 | +``` | ||
| 30 | + | ||
| 31 | +- 任务目录名反映用户目标;同名任务不得覆盖已有目录。 | ||
| 32 | +- `work_dir` 是当前 Workflow 目录的绝对路径,如 `<工作区>/.cannbot/任务1/workflow1/`。启动时将该路径传给 harness,由框架向子 Agent 提供 `$WORK_DIR`。 | ||
| 33 | +- 每轮启动前,将完整 workflow YAML 写入本轮目录,文件名与目录对应,例如 `workflow1/workflow1.yaml`。使用引用模板时先确定本轮节点图与重试预算,展开为本轮完整 YAML 再启动;不直接修改共享模板。 | ||
| 34 | +- Workflow 节点输出的所有中间报告文件名必须为 `<产出节点ID>-<报告名>`,例如 `0.1-黑盒测试设计.md`。同节点的执行与验收报告共用该 ID,上下游引用保持一致;文档模板源文件不加编号。启动前的需求清单与环境检查记录不是调度节点产物,沿用其既定文件名。 | ||
| 35 | +- 仓库级环境记录持久化在 `.cannbot/环境信息.md`,首次检查日志位于 `.cannbot/环境检查/`;本轮采用只读副本。其他本轮输入记录、方案、日志、临时探针、分析文件和报告均放在当前 `work_dir`。最终交付件默认也放在此目录;用户明确要求写入项目中的代码、测试或文档等交付件,在 task 中声明目标路径和写入角色。 | ||
| 36 | +- PM 只在 `.cannbot/` 下写入规划、需求、环境检查、输入快照、workflow YAML 和汇总记录。harness 的 `.workflow/` 状态只读,不自行修改。 | ||
| 37 | + | ||
| 38 | +## 需求与规划 | ||
| 39 | + | ||
| 40 | +1. 读取用户已有说明和工作区上下文,明确目标、范围、约束、输入资料及可判定的交付标准。已明确的要求直接沿用;会影响交付的缺项向用户确认,不把未答复当作批准。 | ||
| 41 | +2. 选择与任务匹配的可用角色、Skill 和工作流模板。角色负责身份与权限,Skill 提供各自的工作方法,task 明确输入、输出和验收要求;Skill 之间不互相调用,所需组合由 PM 或 task 显式声明。引用只注明加载条件、Skill 名称及按其要求执行,不复述 Skill 内部步骤或规则。 | ||
| 42 | +3. 把任务拆成可独立执行与验收的节点,明确依赖、并行关系、交付件路径和重试预算。避免并行节点写同一文件;需要修改同一交付件的节点建立依赖。 | ||
| 43 | + 固定必需 Skill 留在 task;PM 确定专项能力,通过 `executor_skills`、`verifier_skills` 分别下发。设计和文档任务以明确加载为主;开发、修复任务可附有限候选清单与可观察的触发条件,节点仅按实际证据选择并在报告中记录。节点将能力缺口或已确认约束、任务范围变更需求记录到报告,PM 在整轮退出后处理。知识搜集建议只用于下一轮编排;必需能力尚不明确时,先组织范围明确的资料调查;关键路线缺少运行证据时,先安排独立穿刺,待整轮退出并核对结果后再决定后续流程。 | ||
| 44 | + 启动前核对固定项与补充项的适用范围、调用入口、产物和权限是否兼容;含完整开发流程的 Skill 不能作为普通知识附加到任意节点。仅在 Skill 明确提供资料查询入口时按该入口使用;否则承接其完整契约或记录阻塞,不自行裁剪规则。规则冲突先澄清,不交给运行中的节点猜优先级。 | ||
| 45 | +4. 必须加载 `workflow-orchestrator` Skill,按其中的要求执行。 | ||
| 46 | +5. 启动前确认 YAML、输入文件、角色和所需工具可用,记录原始需求、当前版本、交付件位置及本轮任务目标。只使用客户端实际支持的角色和权限,不虚构角色或能力。 | ||
| 47 | + | ||
| 48 | +## 执行与交付 | ||
| 49 | + | ||
| 50 | +本轮 Workflow YAML 落盘后,通过 harness 执行。启动后子 Agent 不与 PM 或用户交互、不等待答复;本轮输入与 Skill 清单保持冻结,节点通过产物和原生执行/验收协议记录结果。PM 只在整轮退出后处理新增建议、阻塞及下一轮编排,不在运行中补发指令,不另写调度器或操作其内部状态。 | ||
| 51 | + | ||
| 52 | +运行期间读取日志和产物,按事实向用户汇报进度与阻塞。启动成功不代表交付完成;执行结束后结合退出结果、节点验收报告和真实交付件,核对是否满足用户的完整目标。原始日志与各角色报告保留,汇总不能改写失败结论。 | ||
| 53 | + | ||
| 54 | +启动前或整轮退出后需要用户决定时,展示具体问题与影响,沿用已有授权和有效确认,不为相同决定重复询问。范围、接口或验收标准需要变更时先对齐相关决定,不以默认选项或未答问卷替代确认。 | ||
| 55 | + | ||
| 56 | +## 多轮 Workflow | ||
| 57 | + | ||
| 58 | +同一用户任务允许包含多个 Workflow。一轮结束后仍有交付缺口时,PM 根据失败证据或遗漏项规划下一轮: | ||
| 59 | + | ||
| 60 | +1. 记录上一轮结果、尚未满足的交付要求,以及下一轮要解决的具体问题。 | ||
| 61 | +2. 新建 `workflow2/`、`workflow3/` 等未使用目录,在其中生成同名 YAML;本轮只组织必要的修复、补充和重新验收工作。 | ||
| 62 | +3. 在本轮输入中明确引用前轮有效交付件的绝对路径与版本。task 要求固定输入文件名时,将已确认的输入复制到本轮目录,并记录来源;不要复制前轮的 `.workflow/` 状态。 | ||
| 63 | +4. 修改前轮交付件前明确本轮授权的目标路径。前轮验收只证明当时的版本;受修改影响的交付要求必须在新一轮重新验收。 | ||
| 64 | +5. 在用户已授权的目标和范围内继续推进,不因新建 Workflow 重复要求批准。缺少必要信息、权限或外部条件,或没有可行修复方向时,保留阻塞证据并汇报,不无依据地重复相同失败流程。 | ||
| 65 | + | ||
| 66 | +恢复中断的同一轮执行时,使用原 YAML 和原 `work_dir`,遵循 harness 的恢复接口。新一轮执行使用新 YAML 和新目录,不通过删除状态、放宽验收或把失败节点标成通过来继续。各轮状态由 harness 独立管理,PM 汇总整个任务的交付情况。 | ||
| 67 | + | ||
| 68 | +## 按任务选择能力 | ||
| 69 | + | ||
| 70 | +PM 按任务需要选择能力: | ||
| 71 | + | ||
| 72 | +- 算子需求对齐:必须加载 `repo-requirement` Skill,按其中的要求执行。 | ||
| 73 | +- 算子工作流启动前的环境检查由 PM 负责:必须加载 `repo-env-check` Skill,按其中的要求执行。 | ||
| 74 | +- 需要安装、配置 CANN 或处理安装问题时,必须加载 `cann-env-setup` Skill,按其中的要求执行;环境变更任务通过 harness 执行。 | ||
| 75 | +- 算子开发:必须加载 `ops-direct-invoke` Skill,按其中的要求执行。 | ||
| 76 | +- 需求阶段需要工程依据时,必须加载 `repo-knowledge` Skill,按其中的要求执行。 | ||
| 77 | +- 需要核对目标芯片或架构候选时,必须加载 `npu-arch`、`ascendc-tiling-design` Skill,按其中的要求执行;候选为 RegBase 或 SIMT 时,分别必须加载 `ascendc-regbase-best-practice` 或 `ascendc-simt-best-practices` Skill,按其中的要求执行。 | ||
| 78 | +- 需要评估或采用 Blaze 路线时,必须加载 `ascendc-blaze-best-practice` Skill,按其中的要求执行;下发前核对其与已选 Skill 的调用契约是否兼容。 | ||
| 79 | +- 需要明确仓库精度判定口径时,必须加载 `repo-test-develop` Skill,按其中的要求执行。 | ||
| 80 | +- 为子任务选择补充 Skill 时,按需求、架构和已有证据判断:SIMT 切分选 `ascendc-simt-tiling-design`,多卡通信或通算融合选 `ascendc-mc2-best-practice`,已知精度故障选 `ascendc-precision-debug`,已知卡死或崩溃选 `ascendc-crash-debug`;尚未发生的运行故障可将上述调试 Skill 作为带触发条件的候选。架构相关能力沿用上述选择规则。将选定项写为“必须加载 xxx Skill,按其中的要求执行”,分别绑定到需要它的执行或验收阶段,不复制 Skill 内容。 | ||
| 81 | +- 其他任务:按实际目标选择可用的领域能力与角色,生成符合 harness 接口的工作流。 | ||
| 82 | + | ||
| 83 | +## 权限边界 | ||
| 84 | + | ||
| 85 | +可以读取工作区上下文、与用户沟通、维护 `.cannbot/` 下的流程文件、通过公开接口启动工作流、读取结果并汇总。 | ||
| 86 | + | ||
| 87 | +不直接编写最终交付件,不替子 Agent 修改验收报告,不修改 harness 内部脚本或调度状态,不伪造用户确认、测试结果或验收结论。任务执行和对外操作不得超出用户已授权范围。 | ||
| @@ -0,0 +1,187 @@ | |||
| 1 | +# ops-direct-invoke | ||
| 2 | + | ||
| 3 | +`ops-direct-invoke` 提供直调算子的需求对齐、方案设计、实现、功能验收、代码检视和交付文档流程。插件名称、安装 ID 与入口 Skill 名称统一为 `ops-direct-invoke`。 | ||
| 4 | + | ||
| 5 | +**调度交给 harness,知识交给 Skill,Workflow 专注于流程。** 工作区 PM 按用户的实际目标规划子 Agent 合作,通过 harness 执行 workflow YAML。算子需求对齐时必须加载 `repo-requirement` Skill,按其中的要求执行;算子开发时必须加载 `ops-direct-invoke` Skill,按其中的要求执行。每个 task 同时声明执行与验收;运行期派发、并行及同节点重试使用框架原生机制。 | ||
| 6 | + | ||
| 7 | +## 安装与入口 | ||
| 8 | + | ||
| 9 | +需要 Node.js 20.11+、Python 3、PyYAML、已安装的 Agent CLI、支持 procedure 字段的 workflow-orchestrator,以及用于默认后台启动的 tmux。源码仓需初始化 `vendor/cannbot-skills`。在 cannbot 根目录执行: | ||
| 10 | + | ||
| 11 | +```bash | ||
| 12 | +node script/bin/cannbot.js install ops-direct-invoke \ | ||
| 13 | + --source "$PWD" --plugin-dir plugins-community/ops-direct-invoke-harness \ | ||
| 14 | + --tool codex --target /absolute/operator-repo | ||
| 15 | +``` | ||
| 16 | + | ||
| 17 | +`--plugin-dir` 明确选择源码目录;目录名不作为安装 ID。也可在本插件目录执行 `bash init.sh project codex /absolute/operator-repo`。目前验证的客户端为 opencode、codex、claude。源码安装把 Skill 链接到源目录,打包安装复制完整 Skill 资源;角色资产安装在目标仓中。子仓可用 `--override-skills /absolute/overrides` 覆盖已有的 `repo-*` Skill,入口及调度 Skill 不在覆盖范围内。 | ||
| 18 | + | ||
| 19 | +插件的 [AGENTS.md](AGENTS.md) 是常驻工作区的通用 PM 指引,直接描述需求拆解、子 Agent 协作、工作流启动与多轮交付,不再通过 PM 角色文件转接。初始化时,安装器将其正文写入工作区 `AGENTS.md` 的插件管理区块,保留用户原有内容;Claude 使用 `CLAUDE.md`。重复初始化替换同一管理区块,不重复追加。 | ||
| 20 | + | ||
| 21 | +算子开发任务由 PM 加载 `ops-direct-invoke` Skill,按其中的要求执行。所有子 Agent 必须在 Workflow YAML 落盘后由 harness 拉起。`agents/` 只保留 architect、developer、verifier 三个子 Agent,分别安装为 Codex 的 TOML 或 OpenCode、Claude 的 Markdown 角色配置。 | ||
| 22 | + | ||
| 23 | +每个任务、每轮 Workflow 独立存放 YAML 和运行记录: | ||
| 24 | + | ||
| 25 | +```text | ||
| 26 | +.cannbot/任务1/ | ||
| 27 | +├── workflow1/ | ||
| 28 | +│ ├── workflow1.yaml | ||
| 29 | +│ ├── 需求与交付件 | ||
| 30 | +│ └── .workflow/ | ||
| 31 | +└── workflow2/ | ||
| 32 | + ├── workflow2.yaml | ||
| 33 | + ├── 本轮输入与交付件 | ||
| 34 | + └── .workflow/ | ||
| 35 | +``` | ||
| 36 | + | ||
| 37 | +仓库首次环境检查结果存放在 `.cannbot/环境信息.md`,检查日志存放在 `.cannbot/环境检查/`。后续算子开发直接复用已有通过记录,不重复探测环境;每轮复制为 `work_dir/环境信息.md`,运行中只读。 | ||
| 38 | + | ||
| 39 | +当前 Workflow 目录的绝对路径即 `work_dir`。首轮未满足交付要求时,PM 根据缺口规划下一轮,保留旧 YAML、状态及验收证据。下一轮明确引用或复制有效输入,并重新验收受影响交付件;同一轮中断恢复则沿用原目录和原 YAML。 | ||
| 40 | + | ||
| 41 | +## 从需求到执行 | ||
| 42 | + | ||
| 43 | +- 需求对齐:必须加载 [repo-requirement](skills/repo-requirement/SKILL.md) Skill,按其中的要求执行。 | ||
| 44 | +- 启动前环境检查由 PM 负责:必须加载 [repo-env-check](skills/repo-env-check/SKILL.md) Skill,按其中的要求执行。 | ||
| 45 | +- 算子开发:必须加载 [ops-direct-invoke](skills/ops-direct-invoke/SKILL.md) Skill,按其中的要求执行。 | ||
| 46 | +- Workflow 执行:必须加载 [workflow-orchestrator](../../harness/workflow-orchestrator/SKILL.md) Skill,按其中的要求执行。 | ||
| 47 | + | ||
| 48 | +## 默认流程与角色 | ||
| 49 | + | ||
| 50 | +需求确认与 PM 环境检查在工作流启动前完成。PM 先核对路线依据和 Skill 调用契约;路线明确时使用 basic,有关键实现疑点时先独立运行 [feasibility](skills/ops-direct-invoke/templates/workflows/feasibility.yaml)。穿刺交付最小代码、代表用例的真实编译与设备证据,通过后新开一轮 basic;规则冲突先澄清,不靠穿刺绕过。basic 默认包含 7 个普通节点,知识搜集可以省略或用前轮资料替代;仓内没有已有算子文档时,下发前从本轮图省略最后的文档准备节点: | ||
| 51 | + | ||
| 52 | +```mermaid | ||
| 53 | +flowchart TD | ||
| 54 | + K[0.0 知识搜集] --> T[1 测试工程开发] | ||
| 55 | + B[0.1 黑盒测试设计] --> T | ||
| 56 | + T --> D[2 算子开发] | ||
| 57 | + D --> W[3 白盒测试设计与用例接入] | ||
| 58 | + W --> R[4 代码修复] | ||
| 59 | + R --> U[5 文档准备:仅仓内已有算子文档时] | ||
| 60 | +``` | ||
| 61 | + | ||
| 62 | +知识搜集形成中立补充文档,包含资料索引、API 组合和不同 shape 的初版 Tiling 草稿,开发可根据验证调整实现。算子开发通过 `knowledge_documents` 接收本轮或前轮文档路径;无资料时使用默认值“无补充文档。”,不要求工作流存在知识搜集节点。省略知识节点时删去相应依赖,将黑盒设计编号改为 `0`、测试工程依赖改为 `0`,同步更新知识文档变量,其他阶段仍为 `1`~`5`。测试工程先准备黑盒,算子实现后再按源码生成白盒用例并直接接入已有框架。白盒节点检查测试质量与证据,发现的算子缺陷交给默认编排的代码修复节点;代码修复要求全量黑盒、白盒回归及代码检视通过,没有缺陷且已有当前版本的有效全量证据时复用并记录依据,不强制重复构建或测试;证据缺失或失效时补齐验证。 | ||
| 63 | + | ||
| 64 | +[registry.csv](skills/ops-direct-invoke/templates/workflows/registry.csv) 索引 basic 与 feasibility,各自维护引用图,每个节点声明 id、task YAML、depends_on、max_retries 及 variables 赋值。task 内容由组装脚本读取并展开,默认每个节点允许 3 次重试(含首次执行最多 4 轮),重试次数由 PM 在下发时确定。固定必需 Skill 保留在 task;PM 通过 `executor_skills`、`verifier_skills` 下发专项必需项,以及开发、修复阶段的有限候选清单与触发条件。节点按实际证据选用候选并记录依据,必需能力缺口或已确认约束、范围变更需求写入报告,交付标准无法满足时验收失败。运行中不与 PM 或用户交互;PM 在整轮退出后处理阻塞及知识搜集建议,供下一轮编排使用,不修改已启动的 YAML。文档准备只按仓内已有格式补全资料,无已有算子文档时直接省略节点,不创建新的文档要求。入口 [SKILL.md](skills/ops-direct-invoke/SKILL.md) 规定模板选择与使用方法。 | ||
| 65 | + | ||
| 66 | +| 角色 | 职责 | | ||
| 67 | +|---|---| | ||
| 68 | +| [工作区 PM](AGENTS.md) | 理解用户目标、规划协作与多轮交付;不进入 task 图 | | ||
| 69 | +| [ops-direct-invoke-architect](agents/ops-direct-invoke-architect.md) | 知识搜集与黑盒方案设计 | | ||
| 70 | +| [ops-direct-invoke-developer](agents/ops-direct-invoke-developer.md) | 代码开发、调试、构建与本阶段测试执行、文档编写 | | ||
| 71 | +| [ops-direct-invoke-verifier](agents/ops-direct-invoke-verifier.md) | 各节点证据审核与代码检视,不重复构建或运行测试 | | ||
| 72 | + | ||
| 73 | +节点通过 `executor` / `verifier` 名称引用安装后的客户端角色,不在 prompt 中额外读取角色文件。工作区常驻指引与运行期子 Agent 派发是两个层次;实际 provider 是否正确加载角色、Skill 和权限仍需真实调用验证。 | ||
| 74 | + | ||
| 75 | +执行者提供原始构建日志、本阶段测试结果(穿刺代表用例、正式交付全量)、源码/测试/构建产物哈希及实际加载路径,使用 [测试执行记录模板](skills/ops-direct-invoke/templates/docs/测试执行记录.md)。验收者核对证据是否真实、完整、对应当前版本并独立检视代码;证据不足则失败,不代跑测试补证据。所有节点均按 [验收报告模板](skills/ops-direct-invoke/templates/docs/验收报告.md) 生成 `<节点ID>-验收报告.md`,其中记录结论及具体修改意见。共享 acceptance 只列执行者交付件;验收报告由 verifier 在 procedure 中生成并检查,executor 只在重试时读取,不代写或等待它。 | ||
| 76 | + | ||
| 77 | +穿刺代码、测试入口及证据通过现有 `task_requirements` 传入下一轮,知识资料通过 `knowledge_documents` 传入;记录绝对路径、版本及适用范围,复用有效产物而非重复调查。穿刺通过仅证明限定范围可行,正式交付仍须全量测试和代码检视。 | ||
| 78 | + | ||
| 79 | +报告保留关键结论和证据路径,每次真实执行的输入/版本清单、原始日志与用例明细只存一份;后续节点引用并核对差异,每个验收者仍独立出具本阶段报告。返工先读验收报告,补充未解决项及变更证据;版本变化使旧证据失效时重新验证。确定性阻塞未变时只记录条件复核,当前 harness 仍按预算重试,不能凭报告自动跳过重试。 | ||
| 80 | + | ||
| 81 | +固定绑定采用与当前节点契约兼容的仓库能力:工程骨架由 `repo-op-templates` 承担,白盒方法由 `repo-test-develop` 承担。`ascendc-direct-invoke-template` 和 `ascendc-whitebox-design` 不再是默认任务的固定项;安装可用不等于必须调用。PM 为补充项核对完整契约,不向禁止交互和派发的节点绑定仍要求这些操作的 Skill,也不靠局部豁免后强行调用。 | ||
| 82 | + | ||
| 83 | +公共 Skill 的规则由来源仓维护;本插件只调整绑定与流程,不复制或覆盖其规则。已知 Ascend 950 路由组合问题见 [cannbot-skills #688](https://gitcode.com/cann/cannbot-skills/issues/688)。 | ||
| 84 | + | ||
| 85 | +## 目录与接口 | ||
| 86 | + | ||
| 87 | +```text | ||
| 88 | +ops-direct-invoke-harness/ | ||
| 89 | +├── AGENTS.md # 工作区 PM 的通用指引 | ||
| 90 | +├── README.md # 使用方式与当前设计 | ||
| 91 | +├── test/ut/ | ||
| 92 | +│ ├── test_all.py # 自动执行所有测试类型 | ||
| 93 | +│ ├── support.py # CLI 与 YAML 检查共用工具 | ||
| 94 | +│ ├── registry/test.py | ||
| 95 | +│ ├── retry_feedback/test.py | ||
| 96 | +│ ├── variables/test.py | ||
| 97 | +│ ├── workflow_generation/test.py | ||
| 98 | +│ └── workflow_execution/test.py | ||
| 99 | +├── agents/ # architect / developer / verifier | ||
| 100 | +├── init.sh # 统一安装器的薄入口 | ||
| 101 | +├── plugin-sources.json # 公共 Skill 来源与安装方式 | ||
| 102 | +├── plugin-install.json # 外部依赖仓声明 | ||
| 103 | +└── skills/ | ||
| 104 | + ├── repo-env-check/ # PM 的启动前环境检查 | ||
| 105 | + ├── repo-requirement/ | ||
| 106 | + │ ├── SKILL.md | ||
| 107 | + │ └── references/requirement-checklist.md | ||
| 108 | + ├── ops-direct-invoke/ | ||
| 109 | + │ ├── SKILL.md # 按注册文件选用模板 | ||
| 110 | + │ ├── scripts/ | ||
| 111 | + │ │ ├── assemble_workflow.py | ||
| 112 | + │ │ └── run_workflow.py | ||
| 113 | + │ ├── tasks/ # <步骤名>.yaml,不带编号 | ||
| 114 | + │ └── templates/ | ||
| 115 | + │ ├── docs/ # 文档名称.md,不带编号 | ||
| 116 | + │ └── workflows/ | ||
| 117 | + │ ├── registry.csv # 模板索引与适用条件 | ||
| 118 | + │ ├── basic.yaml # 正式开发:task 引用图、依赖和重试预算 | ||
| 119 | + │ └── feasibility.yaml # 独立技术穿刺 | ||
| 120 | + ├── repo-knowledge/ | ||
| 121 | + ├── repo-build-guide/ | ||
| 122 | + ├── repo-op-templates/ | ||
| 123 | + ├── repo-coding-rules/ | ||
| 124 | + └── repo-test-develop/ | ||
| 125 | +``` | ||
| 126 | + | ||
| 127 | +## 任务、模板与运行接口 | ||
| 128 | + | ||
| 129 | +必须加载 [ops-direct-invoke](skills/ops-direct-invoke/SKILL.md) Skill,按其中的要求执行。 | ||
| 130 | + | ||
| 131 | +- [任务定义](skills/ops-direct-invoke/tasks/) | ||
| 132 | +- [模板注册文件](skills/ops-direct-invoke/templates/workflows/registry.csv) | ||
| 133 | +- [文档模板](skills/ops-direct-invoke/templates/docs/) | ||
| 134 | +- [组装脚本](skills/ops-direct-invoke/scripts/assemble_workflow.py) | ||
| 135 | +- [启动脚本](skills/ops-direct-invoke/scripts/run_workflow.py) | ||
| 136 | + | ||
| 137 | +## 知识与范围 | ||
| 138 | + | ||
| 139 | +Skill 正文及 references 仅包含自身职责,不互相调用或路由;跨 Skill 组合由 PM 或 task 的 approach/procedure 显式声明。引用处只保留加载条件、Skill 名称及按其要求执行,不复制内部步骤或规则。节点输入、产物路径和验收结果由 task 声明;资源目录引用用于定位文件,不代表调用其所属 Skill。公共领域 Skill 来自 vendor,harness 和统一安装器作为公共基础设施使用。 | ||
| 140 | + | ||
| 141 | +角色、task、脚本、仓库知识及交付模板均由本插件独立维护,安装与运行使用本目录声明的资产及公共依赖。 | ||
| 142 | + | ||
| 143 | +本仓 `repo-*` 知识按 CANN Bench 的直调工程与评测契约组织,包含需求、环境、接口、模板、构建、测试和编码规则。初始化会获取 `cann-bench` 到 `.cannbot/dependencies/ops-direct-invoke/cann-bench/`,实际运行记录所用 commit;已有 checkout 可作为任务输入复用。跨仓定制继续通过同名 `repo-*` Skill 覆写,不将仓库知识复制进 task。 | ||
| 144 | + | ||
| 145 | +当前范围为本地开发、功能验收与交付文档,不包含性能采集、性能迭代及回归复核、性能验收、回顾、经验总结、PR、外部 CI 或合并。需求阶段仍需如实记录性能诉求;用户要求的硬门槛超出当前执行范围时,先对齐交付安排,不能承诺本流程已验证性能。引用业务知识时不启用其中遗留的 PM 派发、状态维护或回退指令。 | ||
| 146 | + | ||
| 147 | +## 已知限制与验证 | ||
| 148 | + | ||
| 149 | +harness 按黑盒使用,只通过公开 CLI 调用并检查输出。已验证同节点重试及失败阻断;重试耗尽后直接重启相同 work_dir 不能清除耗尽状态。 | ||
| 150 | + | ||
| 151 | +Codex provider 的 CLI 替身黑盒测试已确认:当前重试执行提示词与首次相同,不自动附带 verifier 的失败意见;落盘的验收报告保留且下一次执行可读。task 因此明确要求读取该报告返工,不增加调度脚本或修改框架。此测试验证的是 CLI 传参和报告可访问性,不证明真实模型的遵从性,也不代表其他 provider 行为。 | ||
| 152 | + | ||
| 153 | +以下能力尚无本流程已验证的完整公开契约:跨节点返工、下游结果失效、运行中问卷等待与恢复。需求问卷在启动前解决;运行中不发问卷或等待 PM。必要输入或确认缺失时记录阻塞,验收失败按 harness 既定重试与耗尽策略处理;PM 在整轮退出后读取结果并组织下一轮,不自行改状态或用私有脚本补齐框架能力。 | ||
| 154 | + | ||
| 155 | +工作流 UT 位于 test/ut/,各测试类型统一以 test.py 为入口。test_all.py 自动发现直接子目录的 test.py,执行全部类型并汇总;任一类型失败、缺少入口或没有测试类型时返回非零退出码。新增类型沿用此目录约定即可纳入总入口。 | ||
| 156 | + | ||
| 157 | +在 cannbot 根目录运行所有工作流 UT: | ||
| 158 | + | ||
| 159 | +```bash | ||
| 160 | +python3 plugins-community/ops-direct-invoke-harness/test/ut/test_all.py | ||
| 161 | +``` | ||
| 162 | + | ||
| 163 | +可从任意目录调用;测试使用临时工作目录,结束后自动清理。依赖 Python 3.9+、PyYAML 和本仓公共 harness,使用前台模拟执行,不需要 tmux、真实 Agent CLI 或 NPU。harness 位于其它位置时传 `--harness-skill /absolute/workflow-orchestrator`,总入口会透传给每个测试类型。单独执行某类时使用相同参数约定,例如: | ||
| 164 | + | ||
| 165 | +```bash | ||
| 166 | +python3 plugins-community/ops-direct-invoke-harness/test/ut/workflow_execution/test.py | ||
| 167 | +``` | ||
| 168 | + | ||
| 169 | +| 测试类型 | 看护内容 | | ||
| 170 | +|---|---| | ||
| 171 | +| retry_feedback | 真实 harness 公开 CLI 配合 Codex 替身,验证失败→重试→通过、提示词是否携带失败意见、验收报告可读取;不调用真实模型 | | ||
| 172 | +| registry | 注册清单完整且唯一;每项适用条件、引用模板路径、task 路径、节点编号顺序、依赖引用及无环性 | | ||
| 173 | +| workflow_generation | 遍历注册项,调用 assemble_workflow.py 生成临时 workflow.yaml;检查顶层及节点字段、类型、字符串 ID 和依赖图,并与引用图、下发预算及原始 task 逐项比对 | | ||
| 174 | +| variables | 默认值与必填校验、节点隔离、多行文本及字面替换;拒绝未知变量、非法声明和空提示项 | | ||
| 175 | +| workflow_execution | 对每个注册项分别调用 run_workflow.py --template 和 --yaml,后者使用本轮生成的 workflow.yaml;通过 harness --dry-run 验证退出码为 0、预期节点全部通过,且引用模板未被修改、完整 YAML 已落盘并可用于恢复 | | ||
| 176 | + | ||
| 177 | +注册项由 registry.csv 自动读取,不写死基础模板名。新增工作流自动接受相同检查。执行测试只能证明标准 YAML 被框架接受且模拟调度能完成,不证明真实 Agent 执行、业务验收或 NPU 实测通过。测试只通过公开 CLI 与落盘状态观察 harness,不读取内部脚本实现。 | ||
| 178 | + | ||
| 179 | +安装与打包集成检查仍可在 cannbot 根目录运行: | ||
| 180 | + | ||
| 181 | +```bash | ||
| 182 | +npm --prefix script run build:plugins | ||
| 183 | +node --test script/test/harness.test.js | ||
| 184 | +npm --prefix script run pack:smoke | ||
| 185 | +``` | ||
| 186 | + | ||
| 187 | +检查覆盖源码与打包安装、工作区 PM 指引与重复初始化、客户端角色配置、模板注册资源、模板与 task 一致性、引用模板展开及完整 YAML 两种启动方式、外部 task 与不同顺序组装、并行汇合、成功路径、同节点重试、验收失败阻断、耗尽后重启、多轮 Workflow 状态隔离、前后台参数与退出结果,以及独立源码布局下的安装运行。实际 npm 包还会安装后直接选择内置模板并模拟执行。格式与模拟检查不证明问卷交互、真实 provider 角色权限或 NPU 功能实测已经通过。 | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +--- | ||
| 2 | +name: ops-direct-invoke-architect | ||
| 3 | +description: 架构师,负责知识搜集与方案设计 | ||
| 4 | +mode: all | ||
| 5 | +--- | ||
| 6 | + | ||
| 7 | +# 架构师 | ||
| 8 | + | ||
| 9 | +## 工作目录 | ||
| 10 | + | ||
| 11 | +本角色产生的所有文档与分析记录,必须放在 `$WORK_DIR` 路径下。 | ||
| 12 | + | ||
| 13 | +阶段中间报告文件名必须以当前节点 ID 加 `-` 开头,具体路径以当前任务为准;引用上游报告时保留其产出节点的 ID。 | ||
| 14 | + | ||
| 15 | +## 职责 | ||
| 16 | + | ||
| 17 | +### 负责 | ||
| 18 | + | ||
| 19 | +知识搜集与方案设计。 | ||
| 20 | + | ||
| 21 | +### 不负责 | ||
| 22 | + | ||
| 23 | +代码编写。 | ||
| 24 | + | ||
| 25 | +## 权限 | ||
| 26 | + | ||
| 27 | +### 可以写 | ||
| 28 | + | ||
| 29 | +`$WORK_DIR` 下当前任务授权的知识记录、方案草稿与分析记录。 | ||
| 30 | + | ||
| 31 | +### 不可以写 | ||
| 32 | + | ||
| 33 | +算子代码、测试实现、需求清单、其他角色的验收报告及调度状态。 | ||
| @@ -0,0 +1,33 @@ | |||
| 1 | +--- | ||
| 2 | +name: ops-direct-invoke-developer | ||
| 3 | +description: 开发者,负责代码开发、调试 | ||
| 4 | +mode: all | ||
| 5 | +--- | ||
| 6 | + | ||
| 7 | +# 开发者 | ||
| 8 | + | ||
| 9 | +## 工作目录 | ||
| 10 | + | ||
| 11 | +本角色产生的所有中间产物,必须放在 `$WORK_DIR` 路径下。算子代码、测试代码及算子使用文档等交付件,放在目标仓约定目录中。 | ||
| 12 | + | ||
| 13 | +阶段中间报告文件名必须以当前节点 ID 加 `-` 开头,具体路径以当前任务为准;引用上游报告时保留其产出节点的 ID。 | ||
| 14 | + | ||
| 15 | +## 职责 | ||
| 16 | + | ||
| 17 | +### 负责 | ||
| 18 | + | ||
| 19 | +代码开发、调试、测试执行及文档编写。按 task 完成构建和指定范围的测试,提供当前源码、测试与构建产物版本对应的原始证据;不把自测记录写成验收者结论。 | ||
| 20 | + | ||
| 21 | +### 不负责 | ||
| 22 | + | ||
| 23 | +需求确认、方案决策、独立验收及流程调度。不能更改已确认的需求;知识搜集草稿可依据实现与验证结果调整,不得放宽指标或阈值,不得派发其他 Agent。 | ||
| 24 | + | ||
| 25 | +## 权限 | ||
| 26 | + | ||
| 27 | +### 可以写 | ||
| 28 | + | ||
| 29 | +目标仓约定目录中当前任务授权的算子代码、测试代码及使用文档;`$WORK_DIR` 下当前任务授权的调试记录、临时构建产物及报告。 | ||
| 30 | + | ||
| 31 | +### 不可以写 | ||
| 32 | + | ||
| 33 | +已确认的需求清单、上游方案文档、验收者报告、调度状态及当前任务范围以外的文件。 | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +--- | ||
| 2 | +name: ops-direct-invoke-verifier | ||
| 3 | +description: 验收者,负责所有环节的验收 | ||
| 4 | +mode: all | ||
| 5 | +--- | ||
| 6 | + | ||
| 7 | +# 验收者 | ||
| 8 | + | ||
| 9 | +## 工作目录 | ||
| 10 | + | ||
| 11 | +本角色产生的所有文件,必须放在 `$WORK_DIR` 路径下。 | ||
| 12 | + | ||
| 13 | +阶段中间报告文件名必须以当前节点 ID 加 `-` 开头,具体路径以当前任务为准;引用上游报告时保留其产出节点的 ID。 | ||
| 14 | + | ||
| 15 | +## 职责 | ||
| 16 | + | ||
| 17 | +### 负责 | ||
| 18 | + | ||
| 19 | +验收及代码检视。核对执行者的原始日志、本阶段要求的用例结果与当前源码/测试/构建产物版本、运行时加载路径;不重复构建或执行测试。所有结论都需要给出证据,所有违反规范、条款的内容,需要指出对应内容的位置。 | ||
| 20 | +核对真实产物和可复核证据,给出结论、问题位置、依据和修改建议;证据缺失、版本不符、缺少必要确认或存在未解决的阻断问题时不得通过。所有节点都必须产出当前节点 ID 前缀的验收报告;失败时给出具体修改意见,验收者独立核对产物,不用执行者的自述代替证据。 | ||
| 21 | + | ||
| 22 | +### 不负责 | ||
| 23 | + | ||
| 24 | +任何开发与修复、构建安装、测试执行、需求和方案决策及流程调度。不得放宽验收标准,不派发其他 Agent。 | ||
| 25 | + | ||
| 26 | +## 权限 | ||
| 27 | + | ||
| 28 | +### 可以写 | ||
| 29 | + | ||
| 30 | +`$WORK_DIR` 下当前任务授权的验收或检视报告、复现记录、临时探针及验证临时文件。 | ||
| 31 | + | ||
| 32 | +### 不可以写 | ||
| 33 | + | ||
| 34 | +被验收的算子代码、测试实现、需求清单、设计文档及其他交付件,其他角色的报告及调度状态。 | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +#!/usr/bin/env bash | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +set -euo pipefail | ||
| 13 | +PLUGIN_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| 14 | +if [[ -f "${PLUGIN_DIR}/../../script/bin/source-plugin-init.sh" ]]; then | ||
| 15 | + exec bash "${PLUGIN_DIR}/../../script/bin/source-plugin-init.sh" "${PLUGIN_DIR}" "$@" | ||
| 16 | +fi | ||
| 17 | +exec bash "${PLUGIN_DIR}/../../../bin/source-plugin-init.sh" "${PLUGIN_DIR}" "$@" | ||
| @@ -0,0 +1,24 @@ | |||
| 1 | +{ | ||
| 2 | + "dependencies": [ | ||
| 3 | + { | ||
| 4 | + "name": "asc-devkit", | ||
| 5 | + "repository": "https://gitcode.com/cann/asc-devkit.git", | ||
| 6 | + "ref": "master", | ||
| 7 | + "cleanMarkdownWithSkill": "ascendc-docs-search" | ||
| 8 | + }, | ||
| 9 | + { | ||
| 10 | + "name": "cann-samples", | ||
| 11 | + "repository": "https://gitcode.com/cann/cann-samples.git" | ||
| 12 | + }, | ||
| 13 | + { | ||
| 14 | + "name": "ops-tensor", | ||
| 15 | + "repository": "https://gitcode.com/cann/ops-tensor.git", | ||
| 16 | + "recursive": true | ||
| 17 | + }, | ||
| 18 | + { | ||
| 19 | + "name": "cann-bench", | ||
| 20 | + "repository": "https://gitcode.com/cann/cann-bench.git", | ||
| 21 | + "ref": "master" | ||
| 22 | + } | ||
| 23 | + ] | ||
| 24 | +} | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +{ | ||
| 2 | + "skillsRepository": ".", | ||
| 3 | + "skillInstallMode": "symlink", | ||
| 4 | + "skills": [ | ||
| 5 | + "harness/workflow-orchestrator", | ||
| 6 | + "vendor/cannbot-skills/ops/ascendc-api-best-practices", | ||
| 7 | + "vendor/cannbot-skills/ops/ascendc-blaze-best-practice", | ||
| 8 | + "vendor/cannbot-skills/ops/ascendc-crash-debug", | ||
| 9 | + "vendor/cannbot-skills/ops/ascendc-direct-invoke-template", | ||
| 10 | + "vendor/cannbot-skills/ops/ascendc-docs-gen", | ||
| 11 | + "vendor/cannbot-skills/ops/ascendc-docs-search", | ||
| 12 | + "vendor/cannbot-skills/ops/ascendc-env-check", | ||
| 13 | + "vendor/cannbot-skills/ops/ascendc-mc2-best-practice", | ||
| 14 | + "vendor/cannbot-skills/ops/ascendc-performance-best-practices", | ||
| 15 | + "vendor/cannbot-skills/ops/ascendc-precision-debug", | ||
| 16 | + "vendor/cannbot-skills/ops/ascendc-regbase-best-practice", | ||
| 17 | + "vendor/cannbot-skills/ops/ascendc-simt-best-practices", | ||
| 18 | + "vendor/cannbot-skills/ops/ascendc-simt-tiling-design", | ||
| 19 | + "vendor/cannbot-skills/ops/ascendc-st-design", | ||
| 20 | + "vendor/cannbot-skills/ops/ascendc-tiling-design", | ||
| 21 | + "vendor/cannbot-skills/ops/ascendc-ut-develop", | ||
| 22 | + "vendor/cannbot-skills/ops/ascendc-whitebox-design", | ||
| 23 | + "vendor/cannbot-skills/ops/cann-env-setup", | ||
| 24 | + "vendor/cannbot-skills/ops/npu-arch", | ||
| 25 | + "vendor/cannbot-skills/ops/ops-precision-standard", | ||
| 26 | + "vendor/cannbot-skills/ops/ops-profiling", | ||
| 27 | + "vendor/cannbot-skills/ops/ops-simulator" | ||
| 28 | + ] | ||
| 29 | +} | ||
| @@ -0,0 +1,225 @@ | |||
| 1 | +--- | ||
| 2 | +name: ops-direct-invoke | ||
| 3 | +description: 根据已确认的需求清单选择直调算子工作流模板,组装 workflow YAML 并通过脚本启动 harness 执行。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 直调算子开发 | ||
| 7 | + | ||
| 8 | +本 Skill 根据模板注册文件选择引用模板,将 tasks 展开为完整 workflow YAML 后启动执行。每个 `tasks/<步骤名>.yaml` 只收录节点的 9 个必填任务字段、可选 procedure 与 variables 声明(当前均提供),不包含 id、depends_on 或 max_retries。模板提供节点引用、依赖与下发时确定的重试次数;task 决定具体执行和验收内容。组装完成后,调度交给 harness。 | ||
| 9 | + | ||
| 10 | +## 启动前置条件 | ||
| 11 | + | ||
| 12 | +本 Skill 接收调用方已对齐的需求清单 `work_dir/需求分析.md` 和 PM 从仓库级缓存复制的只读环境记录 `work_dir/环境信息.md`。启动前确认内容完整、无待决阻断项,且用户答复覆盖当前版本;已有有效清单与确认可直接复用。仓库级环境结果固定为 `<目标仓>/.cannbot/环境信息.md`,存在通过记录时直接复用,不因新算子重复校验;首次检查与缓存规则由调用方执行。 | ||
| 13 | + | ||
| 14 | +需求分析与环境检查不属于 tasks。存在未答问卷或缺失信息时,将缺项报告给调用方,不组装或启动工作流,不用 silent 或默认选项代替用户拍板。 | ||
| 15 | + | ||
| 16 | +## 运行输入 | ||
| 17 | + | ||
| 18 | +沿用用户已经提供的目标代码仓绝对路径、算子名、原始需求、目标芯片、相关资料路径、已明确的架构选择与确认记录。把这些业务信息和已确认需求清单、环境检查记录的绝对路径、版本及确认摘要组织成传给 harness 的原始任务 prompt,不增加运行时私有输入文件或环境变量。任务提示中引用文件时使用绝对路径。 | ||
| 19 | + | ||
| 20 | +确认 provider、work_dir 和所选 workflow 模板的绝对路径。缺少启动所需信息时先向用户询问。work_dir 必须设为目标仓下 `.cannbot/<任务名>/workflow<序号>/` 的绝对路径,目录由调用方按任务与执行轮次分配。除仓库级环境缓存与首次检查日志外,所有本轮开发中间产物(需求、设计、报告、日志、临时探针、构建临时文件和框架状态)必须放在此目录下;代码、测试和使用文档等算子交付件写入目标代码仓约定目录。使用独立工作目录及 checkout 隔离不同任务,避免覆盖已有运行。 | ||
| 21 | + | ||
| 22 | +工作流启动后不与 PM 或用户交互。各节点只使用已确认输入、固定 Skill 和本阶段下发清单,不发问卷、不等待答复,也不修改本轮 YAML。必要输入、确认或能力缺失时,executor 停止受阻操作,将证据写入本阶段报告并按 harness 原生执行协议结束;verifier 无法确认交付标准满足时判定失败,由 harness 按既定预算和耗尽策略处理。记录阻塞不代表交付通过。 | ||
| 23 | + | ||
| 24 | +PM 仅在启动前确定输入与清单、整轮退出后读取结果并处理补充确认或下一轮编排。运行中可以只读观察日志、向用户汇报进度,不向节点补发指令。 | ||
| 25 | + | ||
| 26 | +## 先查注册文件,再选择调度模板 | ||
| 27 | + | ||
| 28 | +**每次启动前先读取 [templates/workflows/registry.csv](templates/workflows/registry.csv),确认当前有哪些工作流模板,按已确认的需求核对 use_when 中的建议使用场景,再选择其中一个。** 不凭记忆假定模板存在,也不直接把 tasks 目录的文件全部拼起来。选择后向用户说明模板名称及匹配理由;用户已授权开发且条件明确时无需额外审批。 | ||
| 29 | + | ||
| 30 | +注册文件采用 CSV,仅包含 file(模板文件)与 use_when(建议使用场景)两列。节点图只在 file 指向的引用模板内维护,不在注册文件重复。file 相对 templates/workflows/;模板中的节点 yaml 路径相对该模板文件。 | ||
| 31 | + | ||
| 32 | +当前注册 [basic](templates/workflows/basic.yaml)(正式开发)和 [feasibility](templates/workflows/feasibility.yaml)(独立技术穿刺)。PM 在需求确认与环境核对后,按证据选择: | ||
| 33 | + | ||
| 34 | +- 路线已有适用实现或有效设备证据、无关键技术疑点:启动 basic。 | ||
| 35 | +- API 组合、目标芯片适配或关键端到端链路尚无运行证据:先独立启动 feasibility,不同时展开完整黑盒矩阵与测试工程。判断依据是技术缺口,不是算子名字或复杂程度标签。 | ||
| 36 | +- 已知 Skill 规则冲突、必要权限或平台能力缺失:启动前先处理。不能靠穿刺绕过规则,也不能把资料调查通过当作路线验证通过。 | ||
| 37 | + | ||
| 38 | +PM 用 feasibility 的 `spike_scope` 明确候选路线、关键疑点和代表用例范围,`task_requirements` 指定可复用资产及授权路径,分别绑定执行/验收 Skill。默认穿刺验证完整关键组合;例如 GQA 须覆盖 QK→Softmax→PV 的组合与同步,不以各 API 分别存在替代。范围可缩小,用户确认的接口、架构、精度和单 Kernel 等约束不降低。 | ||
| 39 | + | ||
| 40 | +穿刺验收通过后,PM 新建下一轮目录,复制有效需求和环境输入;在 basic 相关节点的 `task_requirements` 中填入前轮代码、测试入口、证据的绝对路径、版本和适用范围,保留前轮原始证据。测试工程复用入口并扩展覆盖,算子开发复用有效实现;本轮仍完成正式全量验收。已有知识文档通过 `knowledge_documents` 传入,可省略重复搜集。穿刺失败时不启动完整开发;根据原因处理规则/环境阻塞或调整已授权候选,新一轮仍需真实穿刺证据。 | ||
| 41 | + | ||
| 42 | +PM 在下发前确定各节点的 max_retries,模板默认允许 3 次重试(首次执行加重试,最多 4 轮);需要调整时在本轮引用图中修改,不改 task。仓内无已有算子文档时,从本轮引用图移除最后的文档准备节点,保留其他节点及验收;不新增模板或凭空创建文档。PM 编排时检查目标仓当前文档,不将历史环境缓存中的文档现状当成永久事实。 | ||
| 43 | + | ||
| 44 | +basic 默认知识搜集与黑盒测试设计并行;两者通过后依次进行测试工程开发、算子开发、白盒测试设计、代码修复、文档准备。代码修复是 basic 的默认节点,没有待修复缺陷且已有当前版本的有效全量证据时,核对并复用,记录无需修改;证据不满足条件时补齐验证。每个节点已包含执行与验收,不另设 CP。 | ||
| 45 | + | ||
| 46 | +知识搜集是可选步骤。PM 可移除本轮图中的知识搜集节点及依赖边,将黑盒测试设计改为 `0`,测试工程依赖 `0`,后续仍为 `1`~`5`。算子开发通过 `knowledge_documents` 接收中立补充文档的路径;可以引用前轮产物,也可以为“无补充文档。”,不再要求同图知识搜集上游。basic 的默认值指向 `$WORK_DIR/0.0-知识搜集.md`;删去节点或改变编号时,PM 同步清空或更新该变量。 | ||
| 47 | + | ||
| 48 | +知识搜集产物是可溯源的资料与初版实现草稿,开发可根据验证调整 API、Tiling 和分支处理,不要求照搬草稿;已确认需求仍是约束。测试工程先准备黑盒用例,算子开发由 executor 构建并执行全量黑盒,verifier 核对证据和检视代码。白盒在实现后依据源码生成可执行用例并接入已有框架。 | ||
| 49 | + | ||
| 50 | +白盒节点验收的是用例质量、框架接入及真实证据;正确用例暴露的算子缺陷记录后交下游修复,不能将该节点通过表述为算子功能通过。测试或框架自身问题仍会阻断。代码修复验收要求最终全量黑盒、白盒回归与代码检视通过,之后才能进入文档交付。 | ||
| 51 | + | ||
| 52 | +若没有适用模板,说明具体差异,不擅自套用模板或删除验收。在用户已授权范围内,按本轮交付缺口选择任务、明确依赖与预算,在当前 work_dir 组装并验证一次性 YAML。只有要发布为可复用模板时,才更新 tasks、模板及注册文件;运行期不修改已安装的共享资源。 | ||
| 53 | + | ||
| 54 | +## 维护工作流模板 | ||
| 55 | + | ||
| 56 | +引用具体 Skill 时,只写“必须加载 `<skill-name>` Skill,按其中的要求执行”,不复制其内部步骤、规则或知识。固定必需项写在 task;PM 选定与芯片、架构及已知问题匹配的专项必需项,分别绑定 `executor_skills`、`verifier_skills`。设计和文档任务以明确加载为主;算子开发、代码修复可在同一变量中接收有限候选清单及可观察的触发条件,按实际证据选择,task 不重复维护具体场景路由。节点输入、交付件和验收标准仍由 task 声明。引用文档模板只是读取资源。 | ||
| 57 | + | ||
| 58 | +知识搜集可以记录有依据的 Skill 建议及适用节点、执行/验收阶段,供 PM 在整轮退出后编排下一轮时参考;本轮下游仍使用启动前绑定的清单,不从报告自动加载新增 Skill。资料不足时可先独立组织知识搜集;该节点只交付中立参考。关键路线需要实测时选择 feasibility,不能连续用资料调查替代编译和设备验证。节点可在已下发候选内按证据选择;清单外能力仅有帮助时记为建议,缺少它导致交付标准无法满足时记录阻塞并验收失败。 | ||
| 59 | + | ||
| 60 | +**task 编写原则:具体流程步骤集中在 approach(执行)和 procedure(验收);acceptance 只写简短的结果标准,明确交付件,不放资料读取、操作顺序、检查方法或异常处理。涉及文件交付件时,acceptance 先列 `test -s` 非空检查,再列内容与质量结果。** 固定报告使用明确的 `$WORK_DIR/<产出节点ID>-<文件名>`;源码、测试和使用文档沿用已确认的项目布局,其检查命令所需小写 shell 变量在 approach/procedure 中用实际绝对路径赋值,不新增 harness 输入字段。多文件交付逐文件检查,不能用目录或任意非空文件代替。共享 acceptance 只列执行者交付件与质量结果;验收报告不放入 executor 的交付清单。所有节点的 procedure 明确由 verifier 写入 `$WORK_DIR/<id>-验收报告.md` 后执行 `test -s`,通过、失败及阻塞均落盘。executor 不生成或等待验收报告,只在重试开始时读取已有报告的修改意见。 | ||
| 61 | + | ||
| 62 | +引用模板格式如下;goal、approach、procedure、acceptance、角色及其它任务内容都从 task YAML 读取,不能复制进模板: | ||
| 63 | + | ||
| 64 | +```yaml | ||
| 65 | +workflow: ops-direct-invoke | ||
| 66 | +max_parallel: 2 | ||
| 67 | +nodes: | ||
| 68 | +- id: '0' | ||
| 69 | + yaml: ../../tasks/知识搜集.yaml | ||
| 70 | + depends_on: [] | ||
| 71 | + max_retries: 3 | ||
| 72 | + variables: | ||
| 73 | + research_focus: 重点搜集目标芯片的 API 组合和小 shape 的 Tiling 依据。 | ||
| 74 | +``` | ||
| 75 | + | ||
| 76 | +- 节点提供 id、yaml、depends_on、max_retries,可选 variables;max_retries 必须是非负整数,由下发方明确决定,不从 task 获取或隐式补默认值。 | ||
| 77 | +- id 和 depends_on 使用字符串。节点 id 按最长依赖路径分层,单节点层使用数字,同层并行节点使用数字.分支序号;按编号排序。组装器生成 ID 并核对其与模板声明一致,发现重复、未知依赖、环或编号不符时拒绝生成。 | ||
| 78 | +- `scripts/assemble_workflow.py --template <引用模板路径> --output <本轮完整YAML路径>` 按模板文件的位置解析 task 路径,展开具体内容与报告编号。输出只包含 harness 标准字段,不包含 yaml 引用或 variables 声明。 | ||
| 79 | +- PM 需修改预算、设置变量或省略文档节点时,将选中的引用图存为本轮 `workflow<序号>.template.yaml`,其中 task 路径转换为实际绝对路径,再调整本轮图并组装为 `workflow<序号>.yaml`。不修改已安装的共享模板或 task。 | ||
| 80 | +- 脚本也接受按任意顺序提供的 task 文件位置,必须同时传 `--max-retries N` 为本次所有输入设置明确预算;不同节点预算和变量值用引用模板声明。默认顺序串行,`--depends-on N:M,K` 覆盖第 N 个输入的依赖,`N:` 表示无依赖,位置从 1 开始。重复 task 可出现在不同节点,产物编号分别展开。 | ||
| 81 | +- task 的 procedure 若提供,必须为非空字符串列表。goal 写简短目标,approach 为执行步骤,procedure 为独立验收步骤,acceptance 为双方共享的结果标准。 | ||
| 82 | +- 更新 task 后,无需手工同步模板正文;下次组装读取最新 task 内容。已经生成的运行 YAML 保持不变,避免改变正在执行或恢复中的流程。 | ||
| 83 | +- 所有组装输出都使用新文件,拒绝覆盖。恢复使用原完整 YAML 和 work_dir;新一轮使用新目录,保留前轮状态与证据。 | ||
| 84 | + | ||
| 85 | +## task 提示词变量 | ||
| 86 | + | ||
| 87 | +每个 task YAML 顶部用 `variables` 声明变量;正文在需要填入提示词的固定位置写 `{{var:变量名}}`。变量在该节点内全局可见,不跨节点共享。相同 task 被引用多次时分别绑定。所有 task 提供以下三个变量;技术穿刺额外提供必填的 `spike_scope`,知识搜集提供 `research_focus`,算子开发提供可选的 `knowledge_documents`,代码修复提供必填的 `repair_requirements`。 | ||
| 88 | + | ||
| 89 | +| 变量 | 注入位置 | 填写内容 | | ||
| 90 | +|---|---|---| | ||
| 91 | +| `task_requirements` | approach、procedure | 执行与验收共同遵守的本轮补充要求 | | ||
| 92 | +| `executor_skills` | 仅 approach | 执行阶段专项必需项;开发、修复可附有限候选与触发条件 | | ||
| 93 | +| `verifier_skills` | 仅 procedure | 验收阶段专项必需项;必要时附仅用于证据分析的候选与触发条件 | | ||
| 94 | +| `spike_scope` | 技术穿刺的 approach、procedure | 本轮候选路线、关键疑点及代表用例范围;引用模板提供默认范围,PM 下发前具体化 | | ||
| 95 | +| `knowledge_documents` | 算子开发的 approach | 中立补充知识文档路径;无资料时为“无补充文档。”,允许引用前轮文件 | | ||
| 96 | + | ||
| 97 | +补充 Skill 变量填写完整指令,例如“必须加载 `ascendc-simt-tiling-design` Skill,按其中的要求执行。”;多项可用多行文本。无补充项明确填写“无补充 Skill。”,也是 task 的默认值。专项必需项不留待节点重新决定;候选项必须逐项给出 Skill 名称和可观察的触发条件,不写“自行寻找合适 Skill”。命中才加载,未命中无需加载,多个独立条件有证据时可分别命中。加载项及选择依据写入当前阶段已有报告,无加载则记无;不新增报告文件或调度状态。不把阶段专用 Skill 放入双方共享的 `task_requirements`。 | ||
| 98 | + | ||
| 99 | +PM 核对 task 固定项与补充必需项、候选均已安装、适用当前平台且符合角色权限,不重复下发固定 Skill。组合还须核对公开调用入口与产物契约:含完整开发流程的 Skill 不作为普通知识补充;只有明确支持资料查询入口时才限定使用该入口,否则按完整契约编排或报告阻塞。引用仍只写加载要求,不复制 Skill 内部步骤,不用本仓提示词豁免其规则。候选使用不扩大写入权限、不改变任务、验收标准、依赖或重试;verifier 只分析证据和判定,不修复对象、不重新构建或运行测试。必需能力超出清单、所需 Skill 不可用或能力不足时,按上述运行阻塞规则处理,不等待补发。 | ||
| 100 | + | ||
| 101 | +basic 只在算子开发、代码修复的 `executor_skills` 中提供精度错误和卡死/崩溃的候选,默认不为 verifier 或其他节点添加决策树。PM 在本轮引用图中核对、增删候选;使用自定义变量会整体替换该节点的原值,需要保留的候选须一并写入。 | ||
| 102 | + | ||
| 103 | +代码修复 task 的声明与正文示例(节选): | ||
| 104 | + | ||
| 105 | +```yaml | ||
| 106 | +variables: | ||
| 107 | + task_requirements: 无额外要求。 | ||
| 108 | + repair_requirements: null | ||
| 109 | + executor_skills: 无补充 Skill。 | ||
| 110 | + verifier_skills: 无补充 Skill。 | ||
| 111 | +approach: | ||
| 112 | +- '{{var:executor_skills}}' | ||
| 113 | +- '本轮修复要求:{{var:repair_requirements}}' | ||
| 114 | +procedure: | ||
| 115 | +- '{{var:verifier_skills}}' | ||
| 116 | +- '本轮修复要求:{{var:repair_requirements}}' | ||
| 117 | +``` | ||
| 118 | + | ||
| 119 | +PM 在引用该 task 的 workflow 节点中赋值;例如单独组织一轮修复时: | ||
| 120 | + | ||
| 121 | +```yaml | ||
| 122 | +workflow: ops-direct-invoke | ||
| 123 | +max_parallel: 1 | ||
| 124 | +nodes: | ||
| 125 | +- id: '0' | ||
| 126 | + yaml: /absolute/skills/ops-direct-invoke/tasks/代码修复.yaml | ||
| 127 | + depends_on: [] | ||
| 128 | + max_retries: 3 | ||
| 129 | + variables: | ||
| 130 | + executor_skills: | | ||
| 131 | + 必需:必须加载 `ascendc-precision-debug` Skill,按其中的要求执行。 | ||
| 132 | + 候选:复现出现卡死、超时或崩溃时,必须加载 `ascendc-crash-debug` Skill,按其中的要求执行。 | ||
| 133 | + verifier_skills: 无补充 Skill。 | ||
| 134 | + repair_requirements: | | ||
| 135 | + 修复 /absolute/repo/op_kernel/abs_kernel.cpp 的尾块结果错误。 | ||
| 136 | + 复现证据:/absolute/repo/.cannbot/abs/workflow1/3-验收报告.md。 | ||
| 137 | + 使用已有 ST 框架回归,不修改精度阈值。 | ||
| 138 | +``` | ||
| 139 | + | ||
| 140 | +- 变量名只允许字母、数字和下划线,首字符不能是数字。默认值为字符串时可以省略赋值;默认值为 null 时必须提供非空字符串。显式赋值仅接受字符串,多行内容使用 YAML `|`。 | ||
| 141 | +- 只在 goal、approach、procedure、acceptance、out_of_scope 的文本项中替换。角色、依赖、预算等字段不使用变量;模板仍需显式声明调度信息。 | ||
| 142 | +- 未声明引用、未知赋值、必填缺失、非文本值、重复 YAML 键、错误占位符或替换后空提示项都会拒绝组装,不输出部分 workflow。 | ||
| 143 | +- 先展开 task 正文里的报告 ID,再一次性替换变量。变量值作为普通文本原样插入,不再解释其中的占位符、shell 表达式或 Python 代码;需引用前轮报告时由 PM 填写实际路径。 | ||
| 144 | +- variables 只用于组装,展开后从完整 YAML 移除。harness 接收标准节点字段,无需改动框架。运行中的 YAML 保持冻结,后续变量调整只能用于新的组装输出。 | ||
| 145 | + | ||
| 146 | +## 中间报告编号 | ||
| 147 | + | ||
| 148 | +所有节点输出的中间报告按 `<产出节点ID>-<报告名>` 命名。同一节点的执行报告与验收报告使用同一 ID;引用上游报告时使用产出节点的 ID。文档模板源文件保持无编号,启动前的 `需求分析.md` 和 `环境信息.md` 作为运行输入沿用原名。 | ||
| 149 | + | ||
| 150 | +子 task 不写死数字:自身报告路径使用 `$WORK_DIR/{{id}}-报告名.md`;上游报告路径使用 `$WORK_DIR/{{id:上游任务title}}-报告名.md`。组装脚本在分配节点 ID 后展开这些标记,所有说明和 `test -s` 引用同步替换。传给 harness 的 YAML 只含具体编号,不新增运行时变量或 harness 字段。 | ||
| 151 | + | ||
| 152 | +知识补充文档通过 `knowledge_documents` 按路径输入,不使用上游 ID 占位符;其他必需上游引用按依赖关系解析,重跑同名上游任务时取依赖链中最新的一次;有多个并行同名产出者或缺少产出者时拒绝组装。局部或后续轮次引用外部报告时,在本轮 task 中明确填写已存在的实际路径。改变节点顺序或依赖后重新组装,不手工修改生成模板中的编号。 | ||
| 153 | + | ||
| 154 | +例如基础模板输出 `0.0-知识搜集.md`、`0.1-黑盒测试设计.md`、`1-测试工程说明.md`、`2-实现记录.md`、`2-测试执行记录.md`、`3-白盒测试设计.md`、`3-测试执行记录.md`、`4-修复记录.md` 和 `4-测试执行记录.md`。全部节点另由 verifier 产出 `<id>-验收报告.md`;算子开发还产出 `2-代码检视报告.md`。 | ||
| 155 | + | ||
| 156 | +## 报告与返工范围 | ||
| 157 | + | ||
| 158 | +报告按当前阶段交付标准填写:知识搜集保留关键引用、建议与未知项;穿刺复用测试执行记录,提交最小代码和代表用例设备证据;正式开发保留全量测试证据与代码检视。报告只列关键结论、变更和证据路径,原始输出、用例明细与文件哈希清单单独保存,不在多份报告中重复全文。知识节点不要求所有检索文件的哈希或与关键结论无关的网络快照。 | ||
| 159 | + | ||
| 160 | +每次真实构建或测试只维护一份带节点 ID 和执行轮次的证据清单,记录输入版本与原始结果索引;其格式与复用判据见测试执行记录模板。后续节点引用具体清单与结果,并记录差异核对,不抄录整份明细。代码修复节点始终执行,但满足复用条件时无需重复构建和测试,verifier 仍独立出具本节点报告。 | ||
| 161 | + | ||
| 162 | +重试先读同节点验收报告,只修复未解决项。输入与产物版本未变且证据有效的内容可引用复用;源码、测试、golden、构建配置或环境变化导致执行证据失效时,按当前 task 重新验证,正式交付仍要求全量通过。verifier 复核当前版本与受影响项,追加结论并保留历史,不重新开展整轮资料搜集或构建测试。 | ||
| 163 | + | ||
| 164 | +已知规则冲突等确定性阻塞条件未变时,执行者仅记录复核与条件缺口,验收者保持失败,不重复完整调查。当前公开接口只有 pass/fail,此约定不会跳过 harness 的重试;默认仍最多重试 3 次,耗尽后由 PM 处理,不新增失败类型或私有调度器。 | ||
| 165 | + | ||
| 166 | +## 文档模板 | ||
| 167 | + | ||
| 168 | +文档模板统一存放在本 Skill 的 templates/docs/,文件名只使用文档名称,不带步骤编号。执行和验收角色按 task 中给出的 `ops-direct-invoke/templates/docs/<文档名>.md` 定位已安装的资源并直接读取,不为使用模板重新执行入口或启动工作流。 | ||
| 169 | + | ||
| 170 | +| 文档 | 模板 | | ||
| 171 | +|---|---| | ||
| 172 | +| 知识搜集 | [知识搜集](templates/docs/知识搜集.md) | | ||
| 173 | +| 黑盒测试设计 | [黑盒测试设计](templates/docs/黑盒测试设计.md) | | ||
| 174 | +| 白盒测试设计 | [白盒测试设计](templates/docs/白盒测试设计.md) | | ||
| 175 | +| 测试执行记录(executor) | [测试执行记录](templates/docs/测试执行记录.md) | | ||
| 176 | +| 验收报告(verifier,全部节点) | [验收报告](templates/docs/验收报告.md) | | ||
| 177 | +| 功能证据核对参考(verifier) | [功能验收报告](templates/docs/功能验收报告.md) | | ||
| 178 | +| 代码检视报告 | [代码检视报告](templates/docs/代码检视报告.md) | | ||
| 179 | + | ||
| 180 | +模板规定交付格式,验收标准在 task 的 acceptance 中。文档和报告按已组装 task 声明的带阶段 ID 的 $WORK_DIR 路径落盘,算子文档按仓内已有格式写入既定目录,无已有算子文档时不创建;需求清单由调用方维护。产物须与当前需求、实际代码和精度口径一致;知识草稿的假设、建议及后续实现调整须如实区分,问题及依据写入对应报告;超出当前任务范围的失效产物列明问题,不自行派发或批准继续。未开展的性能测量、回顾和经验总结不得填成已完成。 | ||
| 181 | + | ||
| 182 | +## 交给 harness 执行 | ||
| 183 | + | ||
| 184 | +先按注册场景完成路线判断,准备本轮需求、环境记录与任务 prompt,核对选中模板的 Skill 清单、范围、预算及节点。以下以 basic 启动为例;独立穿刺将模板改为 feasibility.yaml。需要调整 Skill 清单或节点图时,使用下方的本轮自定义引用图方式。脚本先在 work_dir 下生成与目录同名的完整 YAML,例如 `workflow1/workflow1.yaml`,再通过 harness 公开 CLI 执行: | ||
| 185 | + | ||
| 186 | +```bash | ||
| 187 | +python3 scripts/run_workflow.py \ | ||
| 188 | + --template basic.yaml \ | ||
| 189 | + --work-dir /absolute/operator-repo/.cannbot/abs/workflow1 --provider codex \ | ||
| 190 | + --harness-skill /absolute/installed-skills/workflow-orchestrator \ | ||
| 191 | + --prompt-file /absolute/operator-repo/.cannbot/abs/workflow1/original-task.txt | ||
| 192 | +``` | ||
| 193 | + | ||
| 194 | +`--template` 相对本 Skill 的 templates/workflows/,与当前目录无关;只能指向该目录内的引用模板。引用模板通过组装脚本展开,harness 始终收到完整 YAML。模板不因启动而修改,输出文件已存在时拒绝覆盖,并提示使用 `--yaml` 恢复。 | ||
| 195 | + | ||
| 196 | +使用本轮自定义引用图时先组装,再启动;恢复同一轮也使用 `--yaml` 指向已经生成的完整文件: | ||
| 197 | + | ||
| 198 | +```bash | ||
| 199 | +python3 scripts/assemble_workflow.py \ | ||
| 200 | + --template /absolute/operator-repo/.cannbot/abs/workflow1/workflow1.template.yaml \ | ||
| 201 | + --output /absolute/operator-repo/.cannbot/abs/workflow1/workflow1.yaml | ||
| 202 | +python3 scripts/run_workflow.py \ | ||
| 203 | + --yaml /absolute/operator-repo/.cannbot/abs/workflow1/workflow1.yaml \ | ||
| 204 | + --work-dir /absolute/operator-repo/.cannbot/abs/workflow1 --provider codex \ | ||
| 205 | + --harness-skill /absolute/installed-skills/workflow-orchestrator \ | ||
| 206 | + --prompt-file /absolute/operator-repo/.cannbot/abs/workflow1/original-task.txt | ||
| 207 | +``` | ||
| 208 | + | ||
| 209 | +`--yaml` 与 `--template` 互斥且必选其一。`--yaml` 只接受完整 harness YAML,不展开引用或修改预算。脚本不自动选择模板、决定重试次数或判断文档是否需要;这些由 PM 在下发前确定。 | ||
| 210 | + | ||
| 211 | +`--prompt-file` 的 UTF-8 内容原样作为 harness 的 `--prompt` 参数传递,也可直接使用 `--prompt '任务内容'`,二者互斥。首次运行必须提供原始任务;再次调用已有运行时可省略,由 harness 决定恢复行为。省略 prompt 不会清除耗尽状态。 | ||
| 212 | + | ||
| 213 | +`--harness-skill` 默认取启动脚本调用路径所在安装 Skill 的同级 workflow-orchestrator 目录;直接从源码目录调用或布局不同时显式指定。脚本只调用该目录下公开的 orchestrator.py CLI,不读取或修改内部实现。 | ||
| 214 | + | ||
| 215 | +默认使用 tmux 后台启动,返回会话名及 work_dir/orchestrator.log。启动成功不代表任务执行成功:用脚本打印的 tmux has-session 命令检查会话,结束后完整回传日志及其中的 exit status。同一 work_dir 使用固定会话名,已有活动会话时启动失败,不覆盖其运行。 | ||
| 216 | + | ||
| 217 | +加 `--foreground` 可前台运行,直接输出 harness 日志并返回其退出码;加 `--dry-run` 透传原 harness 的模拟执行选项。启动脚本不自行重试或读写调度状态。 | ||
| 218 | + | ||
| 219 | +每个普通节点先由 executor 执行,再由 verifier 按 acceptance 验收。harness 把 goal、acceptance 和 out_of_scope 发给两者,把 approach 仅发给 executor,把 procedure 仅发给 verifier。executor 据共享标准交付,负责构建与本阶段规定的测试范围(穿刺为代表用例,正式交付为全量),按测试执行模板保存命令、退出码、源码/测试/构建产物哈希、加载路径及逐用例原始结果。verifier 只读核对证据有效性及交付物质量,并独立检视代码;不重复构建或测试,不接受只有通过自述的证据。验收报告只由 verifier 交付。执行器最终回复 executed,验证器最终回复 pass/fail;调度、同节点重试和耗尽处理均使用框架原生机制。 | ||
| 220 | + | ||
| 221 | +整轮退出后,PM 读取日志、退出结果和真实产物,汇总已完成步骤及阻塞证据。交付目标未满足时,使用 workflow2 等新目录规划下一轮必要的修复与验收;前轮确认有效的输入可复制到本轮固定路径并记录来源,前轮状态不得复制或重置。已通过 Codex CLI 替身黑盒探测:当前 harness 重试时下发相同的执行提示词,不自动注入 verifier 的修改意见。因此所有 task 在执行开始时读取已有 `<id>-验收报告.md`;verifier 在返回 pass/fail 前落盘具体意见,报告作为普通任务产物,不参与调度状态。该测试不证明真实模型一定遵守读取指令。跨节点回退、下游失效及用户待答恢复仍无本流程已验证的契约,不另写状态机或调度脚本。 | ||
| 222 | + | ||
| 223 | +入口由工作区 PM 在当前用户会话中承接;PM 不进入调度图。节点角色仅使用 ops-direct-invoke-architect(方案)、ops-direct-invoke-developer(代码、调试与文档)及 ops-direct-invoke-verifier(验收与检视)。角色信息由安装后的客户端角色配置和 executor/verifier 名称衔接,不在任务里额外要求读取 agents 文件。真实 provider 的角色和 Skill 加载仍需验证,模拟执行通过不代表角色权限或 NPU 实测通过。 | ||
| 224 | + | ||
| 225 | +范围包含本地开发与交付;不包含性能采集、迭代、回归复核、性能验收、回顾、经验总结、PR、外部 CI 和合并。Skill 正文和参考资料只描述自身职责,不调用或路由到其他 Skill;跨 Skill 的组合由 Agent 或 task 的 approach/procedure 显式声明。 | ||
Aplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/scripts/assemble_workflow.py+296-0
| @@ -0,0 +1,296 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +"""Assemble task files, assigning numeric IDs by dependency layer and parallel branch.""" | ||
| 13 | +import argparse | ||
| 14 | +import logging | ||
| 15 | +import re | ||
| 16 | +import sys | ||
| 17 | +from pathlib import Path | ||
| 18 | + | ||
| 19 | +import yaml | ||
| 20 | + | ||
| 21 | +LOGGER = logging.getLogger(__name__) | ||
| 22 | + | ||
| 23 | +TASK_FIELDS = {'task_type', 'title', 'goal', 'approach', 'acceptance', | ||
| 24 | + 'out_of_scope', 'executor', 'verifier', 'on_exhaust'} | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +VARIABLE_NAME = re.compile(r'[A-Za-z_][A-Za-z0-9_]*') | ||
| 28 | +VARIABLE_REFERENCE = re.compile(r'\{\{var:([A-Za-z_][A-Za-z0-9_]*)\}\}') | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +class UniqueLoader(yaml.SafeLoader): | ||
| 32 | + """Reject duplicate YAML keys instead of silently losing task instructions.""" | ||
| 33 | + | ||
| 34 | + | ||
| 35 | +def unique_mapping(loader, node): | ||
| 36 | + result = {} | ||
| 37 | + for key_node, value_node in node.value: | ||
| 38 | + key = loader.construct_object(key_node) | ||
| 39 | + if not isinstance(key, str) or key in result: | ||
| 40 | + raise ValueError(f'non-string or duplicate YAML key: {key!r}') | ||
| 41 | + result[key] = loader.construct_object(value_node) | ||
| 42 | + return result | ||
| 43 | + | ||
| 44 | + | ||
| 45 | +UniqueLoader.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, unique_mapping) | ||
| 46 | + | ||
| 47 | + | ||
| 48 | +def load_yaml(path): | ||
| 49 | + """Use only SafeLoader constructors, with duplicate-key validation.""" | ||
| 50 | + loader = UniqueLoader(path.read_text(encoding='utf-8')) | ||
| 51 | + try: | ||
| 52 | + return loader.get_single_data() | ||
| 53 | + finally: | ||
| 54 | + loader.dispose() | ||
| 55 | + | ||
| 56 | + | ||
| 57 | +def bind_variables(declarations, supplied): | ||
| 58 | + """Bind task-local string variables; null declarations require a value.""" | ||
| 59 | + if not isinstance(declarations, dict) or not isinstance(supplied, dict): | ||
| 60 | + raise ValueError('variables must be a mapping') | ||
| 61 | + if any(not isinstance(key, str) or not VARIABLE_NAME.fullmatch(key) for key in declarations): | ||
| 62 | + raise ValueError('variable names must be identifiers') | ||
| 63 | + unknown = set(supplied) - set(declarations) | ||
| 64 | + if unknown: | ||
| 65 | + raise ValueError(f'undeclared variables: {sorted(unknown)}') | ||
| 66 | + values = {**declarations, **supplied} | ||
| 67 | + for key, default in declarations.items(): | ||
| 68 | + if default is not None and not isinstance(default, str): | ||
| 69 | + raise ValueError(f'variable {key}: default must be a string or null') | ||
| 70 | + value = values.get(key) | ||
| 71 | + if not isinstance(value, str) or (default is None and not value.strip()): | ||
| 72 | + raise ValueError(f'variable {key}: a string value is required (null declarations require nonempty input)') | ||
| 73 | + return values | ||
| 74 | + | ||
| 75 | + | ||
| 76 | +def expand_variables(text, values): | ||
| 77 | + """Replace only explicit placeholders once, without evaluating supplied text.""" | ||
| 78 | + if '{{var' in VARIABLE_REFERENCE.sub('', text): | ||
| 79 | + raise ValueError('malformed variable placeholder') | ||
| 80 | + | ||
| 81 | + def replace(match): | ||
| 82 | + name = match.group(1) | ||
| 83 | + if name not in values: | ||
| 84 | + raise ValueError(f'undeclared variable reference: {name}') | ||
| 85 | + return values[name] | ||
| 86 | + | ||
| 87 | + result = VARIABLE_REFERENCE.sub(replace, text) | ||
| 88 | + if not result.strip(): | ||
| 89 | + raise ValueError('variable expansion produced an empty prompt item') | ||
| 90 | + return result | ||
| 91 | + | ||
| 92 | + | ||
| 93 | +def dependency_overrides(dependencies, count): | ||
| 94 | + overrides = {} | ||
| 95 | + for specification in dependencies: | ||
| 96 | + target, separator, sources = specification.partition(':') | ||
| 97 | + if not separator: | ||
| 98 | + raise ValueError('--depends-on requires N:M,K or N: for an independent task') | ||
| 99 | + index = int(target) | ||
| 100 | + parents = [int(value) for value in sources.split(',')] if sources else [] | ||
| 101 | + if index not in range(1, count + 1) or any(value not in range(1, count + 1) for value in parents): | ||
| 102 | + raise ValueError(f'dependency positions must be between 1 and {count}') | ||
| 103 | + if index in overrides or len(set(parents)) != len(parents): | ||
| 104 | + raise ValueError(f'duplicate dependency specification: {specification}') | ||
| 105 | + overrides[index] = parents | ||
| 106 | + return overrides | ||
| 107 | + | ||
| 108 | + | ||
| 109 | +def read_task(source, supplied): | ||
| 110 | + task = load_yaml(source) | ||
| 111 | + if not isinstance(task, dict) or set(task) - {'procedure', 'variables'} != TASK_FIELDS: | ||
| 112 | + raise ValueError(f'{source}: require 9 task fields and optional procedure/variables; ' | ||
| 113 | + 'id, depends_on and max_retries are supplied during assembly') | ||
| 114 | + values = bind_variables(task.pop('variables', {}), supplied) | ||
| 115 | + if task['task_type'] != 'normal': | ||
| 116 | + raise ValueError(f'{source}: assembly currently accepts normal tasks') | ||
| 117 | + for key in ['title', 'executor', 'verifier']: | ||
| 118 | + if not isinstance(task[key], str) or not task[key].strip(): | ||
| 119 | + raise ValueError(f'{source}: {key} must be a nonempty string') | ||
| 120 | + for key in ['goal', 'approach', 'acceptance', 'out_of_scope'] + (['procedure'] if 'procedure' in task else []): | ||
| 121 | + value = task[key] | ||
| 122 | + if not isinstance(value, list) or not value or any(not isinstance(x, str) or not x.strip() for x in value): | ||
| 123 | + raise ValueError(f'{source}: {key} must be a nonempty list of nonempty strings') | ||
| 124 | + if task['on_exhaust'] not in ('exit', 'continue'): | ||
| 125 | + raise ValueError(f'{source}: on_exhaust must be exit or continue') | ||
| 126 | + return task, values | ||
| 127 | + | ||
| 128 | + | ||
| 129 | +def assign_node_ids(nodes): | ||
| 130 | + by_id = {node['id']: node for node in nodes} | ||
| 131 | + depths, visiting = {}, set() | ||
| 132 | + | ||
| 133 | + def depth(tid): | ||
| 134 | + if tid in visiting: | ||
| 135 | + raise ValueError(f'dependency cycle at input position {int(tid) + 1}') | ||
| 136 | + if tid in depths: | ||
| 137 | + return depths[tid] | ||
| 138 | + visiting.add(tid) | ||
| 139 | + depths[tid] = 1 + max((depth(parent) for parent in by_id[tid]['depends_on']), default=-1) | ||
| 140 | + visiting.remove(tid) | ||
| 141 | + return depths[tid] | ||
| 142 | + | ||
| 143 | + for tid in by_id: | ||
| 144 | + depth(tid) | ||
| 145 | + # Preserve branch order across layers even when task inputs list the other branch first. | ||
| 146 | + ranks = {} | ||
| 147 | + for layer in sorted(set(depths.values())): | ||
| 148 | + peers = [tid for tid in by_id if depths[tid] == layer] | ||
| 149 | + peers.sort(key=lambda tid: (tuple(sorted(ranks.get(parent) for parent in by_id[tid]['depends_on'])), | ||
| 150 | + int(tid))) | ||
| 151 | + for branch, tid in enumerate(peers): | ||
| 152 | + ranks[tid] = (layer, branch) if len(peers) > 1 else (layer,) | ||
| 153 | + identifiers = {tid: '.'.join(map(str, rank)) for tid, rank in ranks.items()} | ||
| 154 | + for node in nodes: | ||
| 155 | + node['id'] = identifiers[node['id']] | ||
| 156 | + node['depends_on'] = [identifiers[parent] for parent in node['depends_on']] | ||
| 157 | + | ||
| 158 | + | ||
| 159 | +def resolve_report_references(nodes, bindings): | ||
| 160 | + # Resolve report path IDs before handing the standard YAML to harness. | ||
| 161 | + by_id = {node['id']: node for node in nodes} | ||
| 162 | + ancestors = {} | ||
| 163 | + | ||
| 164 | + def upstream(tid): | ||
| 165 | + if tid not in ancestors: | ||
| 166 | + ancestors[tid] = set(by_id[tid]['depends_on']) | ||
| 167 | + for parent in by_id[tid]['depends_on']: | ||
| 168 | + ancestors[tid].update(upstream(parent)) | ||
| 169 | + return ancestors[tid] | ||
| 170 | + | ||
| 171 | + for node, values in zip(nodes, bindings): | ||
| 172 | + expand_node_prompts(node, values, by_id, upstream) | ||
| 173 | + | ||
| 174 | + | ||
| 175 | +def expand_node_prompts(node, values, by_id, upstream): | ||
| 176 | + def resolve_id(match): | ||
| 177 | + title = match.group(1) | ||
| 178 | + if title is None: | ||
| 179 | + return node['id'] | ||
| 180 | + candidates = {tid for tid in upstream(node['id']) if by_id[tid]['title'] == title} | ||
| 181 | + # A later run of the same producer supersedes its earlier ancestor. | ||
| 182 | + nearest = candidates - {tid for candidate in candidates for tid in upstream(candidate)} | ||
| 183 | + if len(nearest) != 1: | ||
| 184 | + raise ValueError(f"node {node['id']}: report producer {title!r} must resolve to one upstream node") | ||
| 185 | + return next(iter(nearest)) | ||
| 186 | + | ||
| 187 | + for field in ['goal', 'approach', 'procedure', 'acceptance', 'out_of_scope']: | ||
| 188 | + if field in node: | ||
| 189 | + node[field] = [re.sub(r'\{\{id(?::([^{}]+))?\}\}', resolve_id, item) for item in node[field]] | ||
| 190 | + if any('{{id' in item for item in node[field]): | ||
| 191 | + raise ValueError(f"node {node['id']}: malformed report ID placeholder") | ||
| 192 | + node[field] = [expand_variables(item, values) for item in node[field]] | ||
| 193 | + | ||
| 194 | + | ||
| 195 | +def assemble(files, dependencies, retries, variables=None): | ||
| 196 | + count = len(files) | ||
| 197 | + if not count: | ||
| 198 | + raise ValueError('at least one task is required') | ||
| 199 | + if len(retries) != count or any(type(value) is not int or value < 0 for value in retries): | ||
| 200 | + raise ValueError('max_retries must be a nonnegative integer for every task') | ||
| 201 | + supplied = [{} for _ in files] if variables is None else variables | ||
| 202 | + if len(supplied) != count: | ||
| 203 | + raise ValueError('variables must be supplied for each task position') | ||
| 204 | + overrides = dependency_overrides(dependencies, count) | ||
| 205 | + nodes, bindings = [], [] | ||
| 206 | + for index, source in enumerate(files, 1): | ||
| 207 | + task, values = read_task(source, supplied[index - 1]) | ||
| 208 | + bindings.append(values) | ||
| 209 | + parents = overrides.get(index, [index - 1] if index > 1 else []) | ||
| 210 | + nodes.append({'id': str(index - 1), **task, 'max_retries': retries[index - 1], | ||
| 211 | + 'depends_on': [str(value - 1) for value in parents]}) | ||
| 212 | + assign_node_ids(nodes) | ||
| 213 | + resolve_report_references(nodes, bindings) | ||
| 214 | + return {'workflow': 'ops-direct-invoke', 'max_parallel': 2, 'nodes': nodes} | ||
| 215 | + | ||
| 216 | + | ||
| 217 | +def template_positions(nodes): | ||
| 218 | + positions = {} | ||
| 219 | + for index, node in enumerate(nodes, 1): | ||
| 220 | + if not isinstance(node, dict) or set(node) - {'variables'} != {'id', 'yaml', 'depends_on', 'max_retries'}: | ||
| 221 | + raise ValueError('template nodes require id, yaml, depends_on and max_retries; optional variables') | ||
| 222 | + identifier = node['id'] | ||
| 223 | + if not isinstance(identifier, str) or not re.fullmatch(r'\d+(?:\.\d+)?', identifier): | ||
| 224 | + raise ValueError('template id must be a numeric string') | ||
| 225 | + if identifier in positions: | ||
| 226 | + raise ValueError(f'duplicate template id: {identifier}') | ||
| 227 | + positions[identifier] = index | ||
| 228 | + if not isinstance(node['yaml'], str) or not node['yaml'].strip(): | ||
| 229 | + raise ValueError('task yaml must be a nonempty path') | ||
| 230 | + return positions | ||
| 231 | + | ||
| 232 | + | ||
| 233 | +def assemble_template(path): | ||
| 234 | + """Expand a reference graph using paths relative to the template file.""" | ||
| 235 | + template = load_yaml(path) | ||
| 236 | + if not isinstance(template, dict) or set(template) != {'workflow', 'max_parallel', 'nodes'}: | ||
| 237 | + raise ValueError('template requires workflow, max_parallel and nodes') | ||
| 238 | + if not isinstance(template['workflow'], str) or not template['workflow'].strip(): | ||
| 239 | + raise ValueError('workflow must be a nonempty string') | ||
| 240 | + if type(template['max_parallel']) is not int or template['max_parallel'] < 1: | ||
| 241 | + raise ValueError('max_parallel must be a positive integer') | ||
| 242 | + nodes = template['nodes'] | ||
| 243 | + if not isinstance(nodes, list) or not nodes: | ||
| 244 | + raise ValueError('template nodes must be a nonempty list') | ||
| 245 | + positions = template_positions(nodes) | ||
| 246 | + dependencies = [] | ||
| 247 | + for index, node in enumerate(nodes, 1): | ||
| 248 | + parents = node['depends_on'] | ||
| 249 | + if (not isinstance(parents, list) | ||
| 250 | + or any(not isinstance(parent, str) or parent not in positions for parent in parents)): | ||
| 251 | + raise ValueError('depends_on must reference template node IDs') | ||
| 252 | + dependencies.append(f"{index}:" + ','.join(str(positions.get(parent)) for parent in parents)) | ||
| 253 | + definition = assemble([path.parent / node['yaml'] for node in nodes], dependencies, | ||
| 254 | + [node['max_retries'] for node in nodes], [node.get('variables', {}) for node in nodes]) | ||
| 255 | + if [node['id'] for node in definition['nodes']] != list(positions): | ||
| 256 | + raise ValueError('template IDs must match dependency layers and branch order') | ||
| 257 | + definition.update(workflow=template['workflow'], max_parallel=template['max_parallel']) | ||
| 258 | + return definition | ||
| 259 | + | ||
| 260 | + | ||
| 261 | +def write_workflow(definition, output): | ||
| 262 | + """Freeze a complete harness input without overwriting an existing run.""" | ||
| 263 | + rendered = yaml.safe_dump(definition, allow_unicode=True, sort_keys=False, width=110) | ||
| 264 | + output.parent.mkdir(parents=True, exist_ok=True) | ||
| 265 | + with output.open('x', encoding='utf-8') as stream: | ||
| 266 | + stream.write(rendered) | ||
| 267 | + | ||
| 268 | + | ||
| 269 | +def main(): | ||
| 270 | + logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout) | ||
| 271 | + parser = argparse.ArgumentParser(description=__doc__) | ||
| 272 | + parser.add_argument('tasks', nargs='*', type=Path, help='task YAML paths; positions start at 1') | ||
| 273 | + parser.add_argument('--template', type=Path, help='reference workflow template path') | ||
| 274 | + parser.add_argument('--max-retries', type=int, help='required with task paths; retry budget for each task') | ||
| 275 | + parser.add_argument('--output', required=True, type=Path, help='new workflow.yaml path; never overwritten') | ||
| 276 | + parser.add_argument('--depends-on', action='append', default=[], metavar='N:M,K', | ||
| 277 | + help='override dependencies of input N with M,K; N: means none; repeat for multiple tasks') | ||
| 278 | + args = parser.parse_args() | ||
| 279 | + try: | ||
| 280 | + if args.template is not None: | ||
| 281 | + if args.tasks or args.depends_on or args.max_retries is not None: | ||
| 282 | + raise ValueError('--template cannot be combined with task paths, --depends-on or --max-retries') | ||
| 283 | + definition = assemble_template(args.template.resolve(strict=True)) | ||
| 284 | + else: | ||
| 285 | + if args.max_retries is None: | ||
| 286 | + raise ValueError('--max-retries is required with task paths') | ||
| 287 | + definition = assemble(args.tasks, args.depends_on, [args.max_retries] * len(args.tasks)) | ||
| 288 | + output = args.output.absolute() | ||
| 289 | + write_workflow(definition, output) | ||
| 290 | + except (OSError, ValueError, yaml.YAMLError) as error: | ||
| 291 | + parser.error(str(error)) | ||
| 292 | + LOGGER.info("%s (%s tasks)", output, len(definition["nodes"])) | ||
| 293 | + | ||
| 294 | + | ||
| 295 | +if __name__ == '__main__': | ||
| 296 | + main() | ||
| @@ -0,0 +1,121 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +"""Launch the unchanged workflow-orchestrator CLI, in tmux by default.""" | ||
| 13 | +import argparse | ||
| 14 | +import hashlib | ||
| 15 | +import logging | ||
| 16 | +import shlex | ||
| 17 | +import shutil | ||
| 18 | +import subprocess | ||
| 19 | +import sys | ||
| 20 | +from pathlib import Path | ||
| 21 | + | ||
| 22 | +import yaml | ||
| 23 | + | ||
| 24 | +from assemble_workflow import assemble_template, write_workflow | ||
| 25 | + | ||
| 26 | +LOGGER = logging.getLogger(__name__) | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +def argument_parser(): | ||
| 30 | + parser = argparse.ArgumentParser(description=__doc__) | ||
| 31 | + definitions = parser.add_mutually_exclusive_group(required=True) | ||
| 32 | + definitions.add_argument('--yaml', type=Path, help='path to a complete workflow YAML') | ||
| 33 | + definitions.add_argument('--template', type=Path, | ||
| 34 | + help='workflow template path relative to this Skill templates/workflows directory') | ||
| 35 | + parser.add_argument('--work-dir', required=True, type=Path) | ||
| 36 | + parser.add_argument('--provider', required=True) | ||
| 37 | + prompts = parser.add_mutually_exclusive_group() | ||
| 38 | + prompts.add_argument('--prompt', help='original task text; required by harness on first run') | ||
| 39 | + prompts.add_argument('--prompt-file', type=Path, help='UTF-8 task text, passed unchanged as --prompt') | ||
| 40 | + parser.add_argument('--harness-skill', type=Path, | ||
| 41 | + help='workflow-orchestrator directory; defaults to installed sibling Skill') | ||
| 42 | + parser.add_argument('--foreground', action='store_true', help='stream output and return harness exit code directly') | ||
| 43 | + parser.add_argument('--dry-run', action='store_true', help='forward the public harness simulation flag') | ||
| 44 | + return parser | ||
| 45 | + | ||
| 46 | + | ||
| 47 | +def resolve_workflow(args): | ||
| 48 | + if args.template is not None: | ||
| 49 | + template_root = (Path(__file__).absolute().parents[1] / 'templates/workflows').resolve() | ||
| 50 | + workflow = (template_root / args.template).resolve(strict=True) | ||
| 51 | + if not workflow.is_relative_to(template_root): | ||
| 52 | + raise ValueError('--template must stay inside templates/workflows; use --yaml for external files') | ||
| 53 | + else: | ||
| 54 | + workflow = args.yaml.resolve(strict=True) | ||
| 55 | + if not workflow.is_file(): | ||
| 56 | + raise ValueError('workflow must be a file') | ||
| 57 | + return workflow | ||
| 58 | + | ||
| 59 | + | ||
| 60 | +def launch_background(command, work, tmux): | ||
| 61 | + session = 'ops-direct-invoke-' + hashlib.sha256(str(work).encode()).hexdigest()[:12] | ||
| 62 | + log = work / 'orchestrator.log' | ||
| 63 | + # Only process launch and output capture; retries and workflow state belong to harness. | ||
| 64 | + shell_command = (shlex.join(command) + ' > ' + shlex.quote(str(log)) + ' 2>&1; ' | ||
| 65 | + 'launch_exit=$?; printf "\\nexit status: %s\\n" "$launch_exit" >> ' | ||
| 66 | + + shlex.quote(str(log)) + '; exit "$launch_exit"') | ||
| 67 | + result = subprocess.run([tmux, 'new-session', '-d', '-s', session, '-c', str(work), shell_command], | ||
| 68 | + capture_output=True, text=True) | ||
| 69 | + if result.returncode: | ||
| 70 | + raise ValueError(result.stderr.strip() or 'tmux failed to start workflow') | ||
| 71 | + LOGGER.info('session: %s\nlog: %s', session, log) | ||
| 72 | + LOGGER.info('Check completion with: %s', shlex.join([tmux, 'has-session', '-t', session])) | ||
| 73 | + return 0 | ||
| 74 | + | ||
| 75 | + | ||
| 76 | +def launch(args): | ||
| 77 | + workflow = resolve_workflow(args) | ||
| 78 | + # Keep the invocation path before resolving: source installations use Skill symlinks. | ||
| 79 | + harness = args.harness_skill or Path(__file__).absolute().parents[2] / 'workflow-orchestrator' | ||
| 80 | + orchestrator = (harness / 'scripts/orchestrator.py').resolve(strict=True) | ||
| 81 | + if not orchestrator.is_file(): | ||
| 82 | + raise ValueError('workflow-orchestrator CLI not found; specify --harness-skill') | ||
| 83 | + definition = assemble_template(workflow) if args.template is not None else None | ||
| 84 | + prompt = args.prompt_file.read_text(encoding='utf-8') if args.prompt_file else args.prompt | ||
| 85 | + work = args.work_dir.resolve() | ||
| 86 | + tmux = None | ||
| 87 | + if not args.foreground: | ||
| 88 | + executable = shutil.which('tmux') | ||
| 89 | + if executable is None: | ||
| 90 | + raise ValueError('tmux is required for background execution; use --foreground to run directly') | ||
| 91 | + tmux = str(Path(executable).resolve(strict=True)) | ||
| 92 | + if definition is not None: | ||
| 93 | + workflow = work / f'{work.name}.yaml' | ||
| 94 | + if workflow.exists(): | ||
| 95 | + raise ValueError(f'workflow already exists; resume with --yaml {workflow}') | ||
| 96 | + write_workflow(definition, workflow) | ||
| 97 | + command = [sys.executable, str(orchestrator), '--yaml', str(workflow), | ||
| 98 | + '--work-dir', str(work), '--provider', args.provider] | ||
| 99 | + if prompt is not None: | ||
| 100 | + command += ['--prompt', prompt] | ||
| 101 | + if args.dry_run: | ||
| 102 | + command.append('--dry-run') | ||
| 103 | + work.mkdir(parents=True, exist_ok=True) | ||
| 104 | + if args.foreground: | ||
| 105 | + return subprocess.run(command, cwd=work).returncode | ||
| 106 | + return launch_background(command, work, tmux) | ||
| 107 | + | ||
| 108 | + | ||
| 109 | +def main(): | ||
| 110 | + logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout) | ||
| 111 | + parser = argument_parser() | ||
| 112 | + args = parser.parse_args() | ||
| 113 | + try: | ||
| 114 | + exit_code = launch(args) | ||
| 115 | + except (OSError, ValueError, yaml.YAMLError) as error: | ||
| 116 | + parser.error(str(error)) | ||
| 117 | + return exit_code | ||
| 118 | + | ||
| 119 | + | ||
| 120 | +if __name__ == '__main__': | ||
| 121 | + sys.exit(main()) | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + repair_requirements: null | ||
| 4 | + executor_skills: 无补充 Skill。 | ||
| 5 | + verifier_skills: 无补充 Skill。 | ||
| 6 | +task_type: normal | ||
| 7 | +title: 代码修复 | ||
| 8 | +goal: | ||
| 9 | +- 完成下发范围内的代码修复并通过回归与检视。 | ||
| 10 | +approach: | ||
| 11 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 12 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 13 | +- 必须加载 `repo-coding-rules`、`repo-build-guide`、`repo-test-develop` Skill,按其中的要求执行。 | ||
| 14 | +- '{{var:executor_skills}}' | ||
| 15 | +- 补充 Skill 中的必需项直接加载,候选项仅在实际证据满足所列条件时加载;未命中不加载。所需能力超出清单或需改变已确认约束、任务范围时,记录阻塞,不自行扩展。 | ||
| 16 | +- 本轮修复要求:{{var:repair_requirements}}。读取问题证据、目标代码和测试入口,确认授权路径、预期行为及回归范围;必要信息缺失时记录阻塞,不猜测修复目标。 | ||
| 17 | +- 定位根因并修复授权代码,补齐用例;实现分支改变时同步白盒用例和覆盖记录。按已安装的 ops-direct-invoke/templates/docs/测试执行记录.md 中的证据复用规则,确定重建、回归或复用范围,写入 $WORK_DIR/{{id}}-测试执行记录.md。没有待修复缺陷且已有当前版本的有效全量证据时,记录无需修改与复用依据,不重复构建或测试;不满足复用条件时补齐验证。 | ||
| 18 | +- 将修复目标、改动摘要、测试证据路径及补充 Skill 使用依据写入 $WORK_DIR/{{id}}-修复记录.md;将授权对象的实际绝对路径赋给 repair_file,多文件逐一检查。 | ||
| 19 | +procedure: | ||
| 20 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 21 | +- 必须加载 `repo-coding-rules`、`repo-build-guide`、`repo-test-develop` Skill,按其中的要求执行。 | ||
| 22 | +- '{{var:verifier_skills}}' | ||
| 23 | +- 补充 Skill 中的必需项直接加载,候选项仅在实际证据满足所列条件时加载;未命中不加载。所需能力超出清单或需改变已确认约束、任务范围时,记录阻塞,不自行扩展。诊断仅限已有证据分析与判定,不修改被验收对象。 | ||
| 24 | +- 本轮修复要求:{{var:repair_requirements}}。读取原问题证据、当前代码、测试入口及 $WORK_DIR/{{id}}-修复记录.md;给 repair_file 赋实际路径,多文件逐一检查。 | ||
| 25 | +- 只读核对 $WORK_DIR/{{id}}-测试执行记录.md、原问题复现及当前版本的全量黑盒/白盒原始日志、当前源码/测试/构建产物哈希和加载路径,确认问题解决且无遗漏或跳过;检视全部修复变更及受影响分支覆盖。按测试执行记录模板核对证据复用条件、版本差异及受影响项;无代码改动也核对完整证据,不重复构建或运行测试。 | ||
| 26 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 27 | +acceptance: | ||
| 28 | +- test -s "$repair_file" | ||
| 29 | +- test -s "$WORK_DIR/{{id}}-修复记录.md" | ||
| 30 | +- test -s "$WORK_DIR/{{id}}-测试执行记录.md" | ||
| 31 | +- 下发问题已修复,变更范围明确,相关源码与用例一致。 | ||
| 32 | +- 现有全量回归与代码检视通过,证据及补充 Skill 使用依据完整,未放宽需求或测试标准。 | ||
| 33 | +out_of_scope: | ||
| 34 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 35 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 36 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 37 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 38 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 39 | +executor: ops-direct-invoke-developer | ||
| 40 | +verifier: ops-direct-invoke-verifier | ||
| 41 | +on_exhaust: exit | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + spike_scope: null | ||
| 4 | + executor_skills: 无补充 Skill。 | ||
| 5 | + verifier_skills: 无补充 Skill。 | ||
| 6 | +task_type: normal | ||
| 7 | +title: 技术穿刺 | ||
| 8 | +goal: | ||
| 9 | +- 用最小可运行实现验证关键技术路线。 | ||
| 10 | +approach: | ||
| 11 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 12 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 13 | +- 必须加载 `repo-knowledge`、`repo-op-templates`、`repo-build-guide`、`repo-test-develop`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 14 | +- '{{var:executor_skills}}' | ||
| 15 | +- 穿刺范围:{{var:spike_scope}}。只验证下发路线及关键疑点;代表用例覆盖关键组合,不展开完整测试矩阵、白盒工程或交付文档。 | ||
| 16 | +- 复用目标仓已有工程和测试入口,编写最小实现及精度断言;临时实现、用例和构建文件放在 $WORK_DIR/{{id}}-穿刺/ 下,保留工程要求的文件名,明确授权的项目交付件按目标仓路径写入。将实现及测试入口实际文件路径赋给 spike_source、spike_test_entry,多文件逐一检查。 | ||
| 17 | +- 在目标芯片真实编译并运行代表用例,覆盖待验证的端到端关键组合;保持已确认接口、架构、精度与单 Kernel 等约束。只查到 API、各子步骤分别可用、CPU 自检或模拟执行不能代替设备证据。 | ||
| 18 | +- 按已安装的 ops-direct-invoke/templates/docs/测试执行记录.md 写入 $WORK_DIR/{{id}}-测试执行记录.md,记录疑点、采用路线、代码/测试/构建产物版本、真实编译和设备原始日志、代表用例及结果、未验证范围和下一轮复用路径;不另写长篇方案。缺少设备、规则冲突或路线不可行时保存阻塞证据,停止受阻操作,不宣称穿刺成功。 | ||
| 19 | +procedure: | ||
| 20 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 21 | +- 必须加载 `repo-coding-rules` Skill,按其中的要求执行。 | ||
| 22 | +- '{{var:verifier_skills}}' | ||
| 23 | +- 穿刺范围:{{var:spike_scope}}。读取实现、测试入口及 $WORK_DIR/{{id}}-测试执行记录.md,给 spike_source、spike_test_entry 赋实际文件路径,逐一核对;静态检视关键组合、调用真实性及已确认约束,并检视本节点实现、测试和脚本代码的编码规范。 | ||
| 24 | +- 只读核对当前源码/测试/构建产物哈希、实际加载路径、目标设备、编译退出码及代表用例精度结果;不重新构建或运行。验收本次关键疑点是否有设备证据闭合,不要求未下发的全量覆盖或正式文档。 | ||
| 25 | +- 未验证关键组合、只有资料推导或 CPU/模拟证据、规则冲突未解时判失败;明确记录失败条件及未验证范围。通过仅证明穿刺范围可行,不证明完整算子已交付。 | ||
| 26 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 27 | +acceptance: | ||
| 28 | +- test -s "$spike_source" | ||
| 29 | +- test -s "$spike_test_entry" | ||
| 30 | +- test -s "$WORK_DIR/{{id}}-测试执行记录.md" | ||
| 31 | +- 关键技术组合在目标芯片编译和运行成功,代表用例满足已确认的精度及架构约束。 | ||
| 32 | +- 实现、测试和脚本代码符合编码规则;证据对应当前版本,已验证范围、剩余风险及可复用路径明确。 | ||
| 33 | +out_of_scope: | ||
| 34 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 35 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 36 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 37 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 38 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 39 | +- 把少量代表用例通过当作完整交付,展开与穿刺疑点无关的资料搜集或全量测试工程。 | ||
| 40 | +executor: ops-direct-invoke-developer | ||
| 41 | +verifier: ops-direct-invoke-verifier | ||
| 42 | +on_exhaust: exit | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + executor_skills: 无补充 Skill。 | ||
| 4 | + verifier_skills: 无补充 Skill。 | ||
| 5 | +task_type: normal | ||
| 6 | +title: 文档准备 | ||
| 7 | +goal: | ||
| 8 | +- 按仓内已有算子文档规范补全本算子的相关资料。 | ||
| 9 | +approach: | ||
| 10 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 11 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 12 | +- 必须加载 `repo-knowledge` Skill,按其中的要求执行。 | ||
| 13 | +- '{{var:executor_skills}}' | ||
| 14 | +- 读取当前实现、测试及 $WORK_DIR/{{id:代码修复}}-修复记录.md、$WORK_DIR/{{id:代码修复}}-验收报告.md,以修复后版本为准。 | ||
| 15 | +- 对照仓内已有同类算子文档,确定路径、章节与示例;若无已有文档,记录本节点前置条件不满足的证据,不凭空创建格式或文档要求。 | ||
| 16 | +- 按仓内格式补全接口、参数、约束和使用资料,写入约定位置;给 operator_doc 赋实际绝对路径,多文件逐一检查。 | ||
| 17 | +procedure: | ||
| 18 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 19 | +- '{{var:verifier_skills}}' | ||
| 20 | +- 读取本次文档、仓内同类文档、当前代码/测试和 $WORK_DIR/{{id:代码修复}}-验收报告.md;给 operator_doc 赋实际路径,多文件逐一检查。 | ||
| 21 | +- 核对格式、内容完整性及接口/约束/示例与最终交付的一致性,不要求未开展的性能产物。 | ||
| 22 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 23 | +acceptance: | ||
| 24 | +- test -s "$operator_doc" | ||
| 25 | +- 算子相关资料符合仓内已有格式和内容要求,与当前交付实现及验收证据一致。 | ||
| 26 | +out_of_scope: | ||
| 27 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 28 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 29 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 30 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 31 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 32 | +executor: ops-direct-invoke-developer | ||
| 33 | +verifier: ops-direct-invoke-verifier | ||
| 34 | +on_exhaust: exit | ||
| @@ -0,0 +1,40 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + executor_skills: 无补充 Skill。 | ||
| 4 | + verifier_skills: 无补充 Skill。 | ||
| 5 | +task_type: normal | ||
| 6 | +title: 测试工程开发 | ||
| 7 | +goal: | ||
| 8 | +- 准备可执行的 ST 测试工程与完整黑盒用例。 | ||
| 9 | +approach: | ||
| 10 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 11 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 12 | +- 必须加载 `repo-test-develop`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 13 | +- '{{var:executor_skills}}' | ||
| 14 | +- 读取 $WORK_DIR/{{id:黑盒测试设计}}-黑盒测试设计.md;环境记录中的框架信息仅作线索,检查目标仓当前测试入口,复用已有 ST 框架,仅在不存在框架时按目标仓布局搭建,必要信息不足时记录阻塞,不猜测框架布局。 | ||
| 15 | +- 本轮补充要求提供穿刺测试入口时,核对当前接口后复用并扩展,不重新搭建已有可用框架;穿刺的少量用例不代替完整黑盒覆盖。 | ||
| 16 | +- 复用现有 golden、数据生成、精度判定与统一入口,补齐目标任务和全部黑盒用例;缺失内容按已确认规格实现,保留方案用例 ID,并支持后续白盒接入。将入口及用例文件的实际绝对路径赋给 test_entry、test_cases,多文件逐一检查。 | ||
| 17 | +- 先按仓库测试契约完成代表用例的任务发现、golden 参数绑定、数据生成与报告输出自检,再补齐全部用例并核对发现数;提交前检查本节点新增或修改的代码符合编码规则。写入 $WORK_DIR/{{id}}-测试工程说明.md,记录框架位置、复用或新建依据、文件与用例映射、代码哈希、自检命令、退出码及原始日志路径。 | ||
| 18 | +procedure: | ||
| 19 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 20 | +- 必须加载 `repo-test-develop`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 21 | +- '{{var:verifier_skills}}' | ||
| 22 | +- 读取黑盒方案、测试工程及 $WORK_DIR/{{id}}-测试工程说明.md,核对框架复用情况和全部用例的参数、预期结果及断言;给 test_entry、test_cases 赋实际路径,多文件逐一检查。 | ||
| 23 | +- 检视本节点新增或修改的测试与脚本代码是否符合编码规则;核对 golden 参数绑定、数据生成、用例发现、报告输出与比对逻辑的代码及自检日志,证据应对应当前文件哈希;不代跑执行者的测试。本节点只验收测试工程就绪,不要求执行尚未实现的算子,也不宣称算子全量通过。 | ||
| 24 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 25 | +acceptance: | ||
| 26 | +- test -s "$test_entry" | ||
| 27 | +- test -s "$test_cases" | ||
| 28 | +- test -s "$WORK_DIR/{{id}}-测试工程说明.md" | ||
| 29 | +- ST 框架可用,已有框架得到复用;黑盒用例完整符合方案,入口支持后续白盒用例接入。 | ||
| 30 | +- golden、参数绑定、数据生成与精度断言可运行,报告可生成,发现数与预期一致。 | ||
| 31 | +- 本节点交付的测试与脚本代码符合编码规则,无遗留阻断项。 | ||
| 32 | +out_of_scope: | ||
| 33 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 34 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 35 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 36 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 37 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 38 | +executor: ops-direct-invoke-developer | ||
| 39 | +verifier: ops-direct-invoke-verifier | ||
| 40 | +on_exhaust: exit | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + executor_skills: 无补充 Skill。 | ||
| 4 | + verifier_skills: 无补充 Skill。 | ||
| 5 | +task_type: normal | ||
| 6 | +title: 白盒测试设计 | ||
| 7 | +goal: | ||
| 8 | +- 依据实际代码生成白盒用例并纳入现有测试框架。 | ||
| 9 | +approach: | ||
| 10 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 11 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 12 | +- 必须加载 `repo-test-develop`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 13 | +- '{{var:executor_skills}}' | ||
| 14 | +- 读取当前源码、$WORK_DIR/{{id:算子开发}}-实现记录.md、$WORK_DIR/{{id:黑盒测试设计}}-黑盒测试设计.md 和 $WORK_DIR/{{id:测试工程开发}}-测试工程说明.md,按实际代码枚举有效控制流与边界。 | ||
| 15 | +- 按需求允许范围生成触发用例,直接写入现有 ST 框架并接入统一入口;沿用已确认的 golden、预期错误和阈值,不另建框架、不修改算子。将全部用例文件路径赋给 whitebox_cases,多文件逐一检查。 | ||
| 16 | +- 运行全量黑盒与白盒用例,按已安装的 ops-direct-invoke/templates/docs/测试执行记录.md 写入 $WORK_DIR/{{id}}-测试执行记录.md,保存原始日志与问题归属证据;按已安装的 ops-direct-invoke/templates/docs/白盒测试设计.md | ||
| 17 | + 写入 $WORK_DIR/{{id}}-白盒测试设计.md,记录源码位置/条件、用例映射、文件和执行命令。暴露的算子缺陷连同复现证据交下游修复。 | ||
| 18 | +procedure: | ||
| 19 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 20 | +- 必须加载 `repo-test-develop`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 21 | +- '{{var:verifier_skills}}' | ||
| 22 | +- 读取源码、ST 框架与 $WORK_DIR/{{id}}-白盒测试设计.md,独立核对有效分支、触发用例和接入情况;给 whitebox_cases 赋实际路径,多文件逐一检查。 | ||
| 23 | +- 只读核对 $WORK_DIR/{{id}}-测试执行记录.md、全量黑盒与白盒原始日志及当前源码/测试哈希,区分设计覆盖、实际命中与受阻路径;不重复构建或运行用例。 | ||
| 24 | +- 检视本节点新增或修改的测试与脚本代码是否符合编码规则;本节点验收用例及接入质量:测试/框架错误或设计遗漏导致失败;正确用例暴露的算子缺陷须有归属证据,连同受影响覆盖交下游修复,不将节点通过表述为算子功能通过。 | ||
| 25 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 26 | +acceptance: | ||
| 27 | +- test -s "$whitebox_cases" | ||
| 28 | +- test -s "$WORK_DIR/{{id}}-白盒测试设计.md" | ||
| 29 | +- test -s "$WORK_DIR/{{id}}-测试执行记录.md" | ||
| 30 | +- 白盒用例已进入现有框架,覆盖全部已识别的有效源码分支,测试实现符合需求、精度标准与编码规则。 | ||
| 31 | +- 运行记录真实、问题归属与证据完整,算子缺陷及受影响覆盖明确;无未解决的测试实现或框架接入问题。 | ||
| 32 | +out_of_scope: | ||
| 33 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 34 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 35 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 36 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 37 | +- 修改被测算子实现;算子缺陷交下游代码修复。 | ||
| 38 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 39 | +executor: ops-direct-invoke-developer | ||
| 40 | +verifier: ops-direct-invoke-verifier | ||
| 41 | +on_exhaust: exit | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + research_focus: 目标芯片、算子专项资料、可组合 API 与需求 shape 范围的初版 Tiling。 | ||
| 4 | + executor_skills: 无补充 Skill。 | ||
| 5 | + verifier_skills: 无补充 Skill。 | ||
| 6 | +task_type: normal | ||
| 7 | +title: 知识搜集 | ||
| 8 | +goal: | ||
| 9 | +- 形成可溯源的算子知识资料与初版实现草稿。 | ||
| 10 | +approach: | ||
| 11 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 12 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 13 | +- 必须加载 `repo-knowledge`、`npu-arch`、`ascendc-docs-search` Skill,按其中的要求执行。 | ||
| 14 | +- '{{var:executor_skills}}' | ||
| 15 | +- 按 {{var:research_focus}} 检索目标仓、Skill 库和可用资料库,仅记录与本轮重点相关的关键资料、路径、版本和适用范围;不遍历无关资料,不给所有读过的文件逐一计算哈希;新增 Skill 建议注明适用任务、执行/验收阶段及依据,仅供整轮结束后的编排参考,不改变本轮 Skill | ||
| 16 | + 清单。 | ||
| 17 | +- 归纳算法路线、API 签名与组合、数据流及平台约束;按需求中的代表性 shape 分组给出多核、块大小、Buffer 和尾块处理草稿,区分证据、推导和待验证项;非关键资料未命中或无法复核时,删去无依据断言并标注未知。 | ||
| 18 | +- 按已安装的 ops-direct-invoke/templates/docs/知识搜集.md 写入 $WORK_DIR/{{id}}-知识搜集.md;草稿供实现尝试,不作为必须照搬的方案。 | ||
| 19 | +procedure: | ||
| 20 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 21 | +- 必须加载 `ascendc-docs-search`、`npu-arch` Skill,按其中的要求执行。 | ||
| 22 | +- '{{var:verifier_skills}}' | ||
| 23 | +- 读取 $WORK_DIR/{{id}}-知识搜集.md,按 {{var:research_focus}} 核对决定路线和 API 使用的关键引用、芯片/版本/dtype 适用范围;不重新执行全库检索,不扩展本轮搜集范围。 | ||
| 24 | +- 核对 API 组合与代表性 shape 分组的 Tiling 草稿具有可尝试的方向;关键引用虚构、证据矛盾或遗漏搜集要求时失败。非关键资料未命中或无法复核但已标注未知且未被当作事实使用时,不以其单独阻断;残留无依据断言时指出位置并要求执行者修正;待验证假设不等于路线已验证。 | ||
| 25 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 26 | +acceptance: | ||
| 27 | +- test -s "$WORK_DIR/{{id}}-知识搜集.md" | ||
| 28 | +- 资料及专项 Skill 检索记录可溯源,结论与适用条件准确。 | ||
| 29 | +- API 组合与代表性 shape 分组的初版 Tiling 草稿齐备,事实、建议和待验证项区分清楚。 | ||
| 30 | +out_of_scope: | ||
| 31 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 32 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 33 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 34 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 35 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 36 | +executor: ops-direct-invoke-architect | ||
| 37 | +verifier: ops-direct-invoke-verifier | ||
| 38 | +on_exhaust: exit | ||
| @@ -0,0 +1,49 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + executor_skills: 无补充 Skill。 | ||
| 4 | + verifier_skills: 无补充 Skill。 | ||
| 5 | + knowledge_documents: 无补充文档。 | ||
| 6 | +task_type: normal | ||
| 7 | +title: 算子开发 | ||
| 8 | +goal: | ||
| 9 | +- 完成满足已确认需求的直调算子实现。 | ||
| 10 | +approach: | ||
| 11 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 12 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 13 | +- 必须加载 `repo-op-templates`、`repo-coding-rules`、`repo-build-guide`、`repo-knowledge`、`ascendc-api-best-practices`、`ascendc-docs-search` | ||
| 14 | + Skill,按其中的要求执行。 | ||
| 15 | +- 补充知识文档:{{var:knowledge_documents}}。有则读取,作为中立参考,区分证据、建议与待验证项;无则直接依据需求、固定 Skill 和测试工程开发,不要求图中存在知识搜集节点。 | ||
| 16 | +- '{{var:executor_skills}}' | ||
| 17 | +- 补充 Skill 中的必需项直接加载,候选项仅在实际证据满足所列条件时加载;未命中不加载。所需能力超出清单或需改变已确认约束、任务范围时,记录阻塞,不自行扩展。 | ||
| 18 | +- 读取 $WORK_DIR/{{id:黑盒测试设计}}-黑盒测试设计.md 和 $WORK_DIR/{{id:测试工程开发}}-测试工程说明.md,复用资料及测试入口。 | ||
| 19 | +- 本轮补充要求提供前轮穿刺代码或证据时,核对其路径、版本与适用范围,复用有效实现和测试入口,仅补齐正式交付缺口;穿刺通过不代替本节点全量黑盒与代码检视。 | ||
| 20 | +- 按目标仓布局实现算子,可根据验证调整草稿中的 API、Buffer、Tiling 与分支;已确认接口、芯片、架构和精度仍是约束。将源码、注册封装和构建入口的实际路径赋给 operator_source、registration_source、build_entry,多文件逐一检查。 | ||
| 21 | +- 独立构建当前代码并运行全量黑盒用例;将实现路线、关键分支、变更摘要及补充 Skill 使用依据写入 $WORK_DIR/{{id}}-实现记录.md。按已安装的 ops-direct-invoke/templates/docs/测试执行记录.md 写入 | ||
| 22 | + $WORK_DIR/{{id}}-测试执行记录.md,保存构建及全量测试原始日志;实现记录仅引用证据路径,不再抄录命令输出和逐用例明细。代码检视由 verifier 执行,白盒由后续节点生成。 | ||
| 23 | +procedure: | ||
| 24 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 25 | +- 必须加载 `repo-build-guide`、`repo-test-develop`、`repo-knowledge`、`repo-coding-rules` Skill,按其中的要求执行。 | ||
| 26 | +- '{{var:verifier_skills}}' | ||
| 27 | +- 补充 Skill 中的必需项直接加载,候选项仅在实际证据满足所列条件时加载;未命中不加载。所需能力超出清单或需改变已确认约束、任务范围时,记录阻塞,不自行扩展。诊断仅限已有证据分析与判定,不修改被验收对象。 | ||
| 28 | +- 读取当前代码、$WORK_DIR/{{id}}-实现记录.md、黑盒方案与测试工程说明;给 operator_source、registration_source、build_entry 赋实际路径,多文件逐一检查。 | ||
| 29 | +- 读取 $WORK_DIR/{{id}}-测试执行记录.md 与原始构建、测试日志,核对当前源码、测试、构建产物的哈希与运行时加载路径一致;全量黑盒生成数、执行数及结果可核对,无缺失、跳过、待验或失败,不虚构白盒覆盖。只读核验现有证据,不重新构建或运行测试。 | ||
| 30 | +- 检视全部算子变更与关联接口,核对需求、硬件约束、编码规则及实现记录;草稿仅作参考。按已安装的 ops-direct-invoke/templates/docs/代码检视报告.md 写入 $WORK_DIR/{{id}}-代码检视报告.md,两个维度均通过才通过本节点;验收报告记录本阶段实际加载的补充 | ||
| 31 | + Skill 与选择依据(未加载记无)。 | ||
| 32 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 33 | +acceptance: | ||
| 34 | +- test -s "$operator_source" | ||
| 35 | +- test -s "$registration_source" | ||
| 36 | +- test -s "$build_entry" | ||
| 37 | +- test -s "$WORK_DIR/{{id}}-实现记录.md" | ||
| 38 | +- test -s "$WORK_DIR/{{id}}-测试执行记录.md" | ||
| 39 | +- 黑盒用例全量通过,当前代码构建成功,接口与精度满足需求,无缺失、跳过或待验项。 | ||
| 40 | +- 代码检视通过,当前实现满足需求与编码规则,无阻塞或高级问题;记录和报告与实际交付一致,补充 Skill 使用及依据可追溯。 | ||
| 41 | +out_of_scope: | ||
| 42 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 43 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 44 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 45 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 46 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 47 | +executor: ops-direct-invoke-developer | ||
| 48 | +verifier: ops-direct-invoke-verifier | ||
| 49 | +on_exhaust: exit | ||
| @@ -0,0 +1,34 @@ | |||
| 1 | +variables: | ||
| 2 | + task_requirements: 无额外要求。 | ||
| 3 | + executor_skills: 无补充 Skill。 | ||
| 4 | + verifier_skills: 无补充 Skill。 | ||
| 5 | +task_type: normal | ||
| 6 | +title: 黑盒测试设计 | ||
| 7 | +goal: | ||
| 8 | +- 形成覆盖算子规格的黑盒测试方案。 | ||
| 9 | +approach: | ||
| 10 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,停止依赖该输入的操作,在本阶段报告中记录阻塞证据,按 harness 原生协议结束执行。补充要求:{{var:task_requirements}} | ||
| 11 | +- 重试先读已有 $WORK_DIR/{{id}}-验收报告.md,只处理未解决项并记录变更与证据路径;输入及产物未变时复用可核对记录,不重写整份调查。确定性阻塞条件未变时,仅记录复核结果并结束本次执行,不重复调查或伪造通过;仅改授权范围,不修改验收报告。 | ||
| 12 | +- 必须加载 `repo-test-develop`、`ascendc-st-design` Skill,按其中的要求执行。 | ||
| 13 | +- '{{var:executor_skills}}' | ||
| 14 | +- 依据已确认规格设计 golden、L0/L1/L2 用例、覆盖矩阵、预期错误及逐输出精度标准;按已安装的 ops-direct-invoke/templates/docs/黑盒测试设计.md 写入 $WORK_DIR/{{id}}-黑盒测试设计.md。 | ||
| 15 | +procedure: | ||
| 16 | +- 读取 $USER_PROMPT、$WORK_DIR/需求分析.md 和 $WORK_DIR/环境信息.md;必要输入缺失、失效或冲突时,记录阻塞证据并判定验收失败。补充要求:{{var:task_requirements}} | ||
| 17 | +- 必须加载 `repo-test-develop` Skill,按其中的要求执行。 | ||
| 18 | +- '{{var:verifier_skills}}' | ||
| 19 | +- 对照需求和已安装的 ops-direct-invoke/templates/docs/黑盒测试设计.md,检查 $WORK_DIR/{{id}}-黑盒测试设计.md 的规格覆盖、golden、预期结果及精度口径,记录缺口与依据。 | ||
| 20 | +- 由 verifier 按已安装的 ops-direct-invoke/templates/docs/验收报告.md 写入 $WORK_DIR/{{id}}-验收报告.md,执行 test -s "$WORK_DIR/{{id}}-验收报告.md";通过、失败或阻塞均记录逐项结论与证据路径。重试仅追加问题处理和受影响项复核结果;当前版本缺少有效证据即失败,不补造或重跑测试。 | ||
| 21 | +acceptance: | ||
| 22 | +- test -s "$WORK_DIR/{{id}}-黑盒测试设计.md" | ||
| 23 | +- golden 与测试方案符合已确认需求。 | ||
| 24 | +- L0/L1/L2 覆盖完整,覆盖矩阵、补充用例和预期错误明确。 | ||
| 25 | +- 逐输出精度口径完整、权威且可执行,无未说明的差异。 | ||
| 26 | +out_of_scope: | ||
| 27 | +- 改动已确认需求或放宽精度标准、以篡改 golden/用例掩盖失败、伪造确认或验证证据。 | ||
| 28 | +- 加载固定项及当前阶段下发清单以外的 Skill、向 PM 或用户发起交互、等待其答复、派发 Agent、修改 harness 或调度状态、重置或回退其他节点。 | ||
| 29 | +- 将中间产物写出 $WORK_DIR,或使用不以 {{id}}- 开头的中间报告名;算子交付件按目标仓约定路径写入。 | ||
| 30 | +- 性能采集与优化验收、回顾与经验总结、PR、外部 CI 或合并事务。 | ||
| 31 | +- executor 编写或修改验收者报告、为等待验收报告而停止交付;verifier 重新构建、安装或运行测试、替执行者补造执行证据。 | ||
| 32 | +executor: ops-direct-invoke-architect | ||
| 33 | +verifier: ops-direct-invoke-verifier | ||
| 34 | +on_exhaust: exit | ||
| @@ -0,0 +1,70 @@ | |||
| 1 | +# {算子名称} 代码检视报告 | ||
| 2 | + | ||
| 3 | +> 算子开发节点的 verifier 产出,与该节点的全量黑盒验收共同构成放行条件。对全部变更文件做多维度检视。本仓采用 direct launch 工程架构,须额外核对提交反作弊红线(当前任务指定的 A 类条款,违反 = 提交无效)。不通过时列出具体问题和证据,不自行回退上游任务。 | ||
| 4 | + | ||
| 5 | +## 检视摘要 | ||
| 6 | + | ||
| 7 | +- 产出节点 ID:{节点 ID} | ||
| 8 | +- 被检视代码版本:{提交号或变更快照标识} | ||
| 9 | + | ||
| 10 | +| 维度 | 结果 | 详情 | | ||
| 11 | +|------|------|------| | ||
| 12 | +| 提交反作弊(A 类) | {通过/有问题} | A1–A7 全部通过,附代码证据 | | ||
| 13 | +| 代码规范(B 类) | {通过/有问题} | B 类编码规则全部通过,附代码证据 | | ||
| 14 | +| 需求与实现 | {通过/有问题} | 满足已确认需求和硬件约束,schema 对齐;不要求照搬知识搜集草稿 | | ||
| 15 | +| 文档与实现同步 | {通过/有问题} | 见下方核对表 | | ||
| 16 | +| 潜在风险 | {通过/有问题} | 越界、精度、并发等 | | ||
| 17 | +| 冗余清理 | {通过/有问题} | | | ||
| 18 | + | ||
| 19 | +## 文档与实现同步核对 | ||
| 20 | + | ||
| 21 | +> 算子开发阶段尚未生成白盒用例,不要求预先交付;尚未执行的文档准备不作为缺失产物。经历过回退迭代的交付件为重点核对对象——代码多轮更新而文档停留在早期快照。 | ||
| 22 | + | ||
| 23 | +| 文档 | 声明内容 | 代码实际 | 是否一致 | 应刷新点 | | ||
| 24 | +|------|----------|----------|----------|----------| | ||
| 25 | +| {分支覆盖说明} | | | {一致 / 不一致} | | | ||
| 26 | +| {当前实现记录与调整依据} | | | | | | ||
| 27 | +| {交付说明 / 算子文档} | | | | | | ||
| 28 | + | ||
| 29 | +## 提交反作弊核对(A 类,零容忍) | ||
| 30 | + | ||
| 31 | +| 红线编号 | 条款 | 结果 | | ||
| 32 | +|----------|------|------| | ||
| 33 | +| A1 | 不调 PyTorch/torch_npu 计算代算 | {通过/违规} | | ||
| 34 | +| A2 | 不用 PyTorch/torch_npu 处理输入输出 tensor | {通过/违规} | | ||
| 35 | +| A3 | 不路由 CANN 内置同名算子 | {通过/违规} | | ||
| 36 | +| A4 | 不 CPU fallback | {通过/违规} | | ||
| 37 | +| A5 | 不缓存/固定/按地址命中输出 | {通过/违规} | | ||
| 38 | +| A6 | 不篡改 profiler/timing API | {通过/违规} | | ||
| 39 | +| A7 | 不返回 FakeTensor/懒求值包装器 | {通过/违规} | | ||
| 40 | + | ||
| 41 | +## 变更范围 | ||
| 42 | + | ||
| 43 | +| 文件 | 变更类型 | 说明 | | ||
| 44 | +|------|----------|------| | ||
| 45 | + | ||
| 46 | +## 问题清单 | ||
| 47 | + | ||
| 48 | +### {编号}. {问题标题} | ||
| 49 | + | ||
| 50 | +- **维度**:{规范/一致性/风险} | ||
| 51 | +- **严重程度**:{阻塞/高/中/低} | ||
| 52 | +- **位置**:{文件:行} | ||
| 53 | +- **描述**:{问题表现} | ||
| 54 | +- **建议**:{修改建议} | ||
| 55 | + | ||
| 56 | +## 总结 | ||
| 57 | + | ||
| 58 | +{整体质量评价} | ||
| 59 | + | ||
| 60 | +## 检视结论 | ||
| 61 | + | ||
| 62 | +**结论**:{通过 / 不通过} | ||
| 63 | + | ||
| 64 | +{不通过时汇总结构化修改意见,指明 算子实现中的具体修改点} | ||
| 65 | + | ||
| 66 | +## 附录:修订记录 | ||
| 67 | + | ||
| 68 | +| 版本 | 日期 | 修改内容 | | ||
| 69 | +|------|------|----------| | ||
| 70 | +| v1.0 | {YYYY-MM-DD} | 初始检视 | | ||
| @@ -0,0 +1,80 @@ | |||
| 1 | +# {算子名称} 功能验收报告 | ||
| 2 | + | ||
| 3 | +> verifier 核对 executor 提供的本阶段真实用例运行证据,不重复构建或执行测试。算子开发节点检查全量黑盒;白盒测试节点记录黑盒回归与白盒运行,用例正确但暴露的算子缺陷交给代码修复。测试任务通过不代表所有算子用例通过,必须分别记录。 | ||
| 4 | + | ||
| 5 | +## 验证摘要 | ||
| 6 | + | ||
| 7 | +- 产出节点 ID:{节点 ID} | ||
| 8 | +- 被验收代码与测试版本:{提交号或变更快照标识} | ||
| 9 | +- 验收范围:{本阶段已确认的完整用例集} | ||
| 10 | + | ||
| 11 | +| 验证项 | 结果 | 详情 | | ||
| 12 | +|--------|------|------| | ||
| 13 | +| 编译验证 | {通过/失败} | {构建命令、退出码和日志路径} | | ||
| 14 | +| schema 注册 | {通过/失败} | {与需求接口一致,`torch.ops.<pkg>.<op>` 可调用} | | ||
| 15 | +| 精度验证 | {通过/失败} | {通过数}/{总数} 用例通过 | | ||
| 16 | +| 白盒覆盖 | {通过/失败/本阶段未生成} | 源码路径与用例对应,实际命中、失败及受阻项分别列证据 | | ||
| 17 | + | ||
| 18 | +## 关键指标 | ||
| 19 | + | ||
| 20 | +| 指标 | 值 | | ||
| 21 | +|------|----| | ||
| 22 | +| 评测/测试报告 | {测试入口输出和比对结果路径} | | ||
| 23 | +| 用例总数 | {全量用例表条目数,含补充用例} | | ||
| 24 | +| 通过率 | | | ||
| 25 | +| golden 实现 | {测试方案约定的 golden 文件路径与版本} | | ||
| 26 | +| 执行计数一致性 | {生成数 == 用例数 == 执行数} | | ||
| 27 | + | ||
| 28 | +## 测试明细 | ||
| 29 | + | ||
| 30 | +| 用例编号 | 名称 | 结果 | 说明 | | ||
| 31 | +|----------|------|------|------| | ||
| 32 | + | ||
| 33 | +## 源码与白盒用例对应 | ||
| 34 | + | ||
| 35 | +| 源码分支 ID | 白盒设计条目 | 源码位置与条件 | 用例 ID | 实际命中证据 | 结论 | | ||
| 36 | +|-------------|--------------------|----------------|---------|--------------|------| | ||
| 37 | + | ||
| 38 | +> 白盒用例覆盖以实际源码为准,不要求与知识搜集草稿一致。区分测试问题与被测算子缺陷,不能伪造覆盖;受算子缺陷影响的覆盖交给修复节点验证。 | ||
| 39 | + | ||
| 40 | +## 失败用例 | ||
| 41 | + | ||
| 42 | +{逐条列失败用例、现象、初步定位(附测试报告失败明细);无则填"无"} | ||
| 43 | + | ||
| 44 | +## 精度说明 | ||
| 45 | + | ||
| 46 | +> 按测试方案精度判定口径表逐**输出张量**填写。实测值从 executor 提供的原始结果核对,并核验其对应当前源码、测试与构建产物版本(不只采信自述结论),最差用例指该输出张量上指标最差的那条用例。 | ||
| 47 | + | ||
| 48 | +| 输出张量 | dtype | 判定指标 | 阈值 | 最差用例 | 实测值 | 权威源出处 | 结论 | | ||
| 49 | +|----------|-------|----------|------|----------|--------|------------|------| | ||
| 50 | +| | | | | | | | {达标 / 不达标} | | ||
| 51 | + | ||
| 52 | +| 项目 | 内容 | | ||
| 53 | +|------|------| | ||
| 54 | +| 比对基准 | {测试方案约定的 golden 文件路径与版本} | | ||
| 55 | +| 权威口径实例化方式 | {口径断言的执行位置与本次执行方式} | | ||
| 56 | +| 交叉核对(自建容差) | {结论;与权威口径不一致时标注该分叉,并说明以权威口径为准} | | ||
| 57 | +| 口径一致性 | {口径表取值与权威源逐项一致 / 差异项及处理} | | ||
| 58 | + | ||
| 59 | +## 验收结论 | ||
| 60 | + | ||
| 61 | +**用例运行结论**:{通过 / 不通过 / 本阶段未执行的范围} | ||
| 62 | + | ||
| 63 | +**当前任务结论**:{通过 / 不通过;白盒任务按用例质量与框架接入判定,算子缺陷列入修复交接} | ||
| 64 | + | ||
| 65 | +{不通过时给出结构化修改意见,标注问题语义归属并指明问题所在环节(算子实现 / 测试方案的精度判定口径)的具体修改点} | ||
| 66 | + | ||
| 67 | +## 测试环境 | ||
| 68 | + | ||
| 69 | +| 项目 | 内容 | | ||
| 70 | +|------|------| | ||
| 71 | +| 目标芯片/架构 | {芯片} / {ascend910b / ascend910_93 / ascend950} | | ||
| 72 | +| CANN 版本 | {版本} | | ||
| 73 | +| 执行方式 | {测试入口命令及运行目录} | | ||
| 74 | +| 测试依赖 | {实际使用的依赖和版本} | | ||
| 75 | + | ||
| 76 | +## 附录:修订记录 | ||
| 77 | + | ||
| 78 | +| 版本 | 日期 | 修改内容 | | ||
| 79 | +|------|------|----------| | ||
| 80 | +| v1.0 | {YYYY-MM-DD} | 初始版本 | | ||
| @@ -0,0 +1,73 @@ | |||
| 1 | +# {节点 ID} {步骤名称} 测试执行记录 | ||
| 2 | + | ||
| 3 | +> executor 产出,不代写验收结论。技术穿刺记录下发范围的代表用例;算子开发提供全量黑盒证据,白盒测试与代码修复提供全量黑盒和已接入白盒的证据;符合下述条件时可引用已有有效执行结果。原始输出、哈希清单和逐用例结果独立保存,本报告只给摘要与路径,不复制全文。 | ||
| 4 | + | ||
| 5 | +## 验证范围 | ||
| 6 | + | ||
| 7 | +- 本节点要验证的目标、关键疑点与采用路线: | ||
| 8 | +- 本次范围及未验证范围: | ||
| 9 | +- 下一轮可复用的代码、测试入口及证据绝对路径与版本: | ||
| 10 | + | ||
| 11 | +穿刺必须记录关键端到端组合在目标设备的运行结果;资料推导、CPU 自检或模拟执行不能代替。只对穿刺范围给结论,不宣称正式全量交付。 | ||
| 12 | + | ||
| 13 | +## 证据清单与引用 | ||
| 14 | + | ||
| 15 | +- 执行或复用:{本次新执行 / 复用;复用不计为新增设备执行} | ||
| 16 | +- 输入与版本清单绝对路径:{每次真实执行生成一次 `<节点ID>-证据-r<轮次>/<节点ID>-清单.json` 或清单文本} | ||
| 17 | +- 原始结果索引:{构建日志、测试命令及退出码、逐用例结果、加载记录的路径与哈希} | ||
| 18 | +- 本次变更及复用判断:{差异路径、受影响项、复用来源与适用范围} | ||
| 19 | + | ||
| 20 | +清单覆盖需求、源码、注册/打包/构建配置、测试及用例 ID、golden、checker/阈值配置、随机种子、实际工具链/设备环境、wheel 和加载库。大清单单独保存,下文引用路径与条目,不重复抄写哈希或用例明细。清单与日志保留原版本,变更生成新的清单,引用必须落到具体执行轮次,不能使用会被覆盖的 latest 路径。只记录决定本次结果的输入,不对所有阅读资料重复计算哈希。 | ||
| 21 | + | ||
| 22 | +## 版本与构建 | ||
| 23 | + | ||
| 24 | +- 需求及测试方案版本: | ||
| 25 | +- 源码、测试、golden 和构建入口的路径与哈希(包含未提交变更): | ||
| 26 | +- 构建命令、工作目录、环境及退出码: | ||
| 27 | +- 原始构建日志绝对路径: | ||
| 28 | +- 构建产物绝对路径与哈希: | ||
| 29 | +- 运行时实际加载模块路径与哈希(应与本次构建一致): | ||
| 30 | + | ||
| 31 | +## 本阶段运行 | ||
| 32 | + | ||
| 33 | +- 测试入口、实际命令、运行目录及退出码: | ||
| 34 | +- 原始输出、机器可读结果与逐用例明细路径: | ||
| 35 | +- 本阶段用例清单及版本(正式交付全量;穿刺列代表用例): | ||
| 36 | +- 实际设备型号与执行位置: | ||
| 37 | + | ||
| 38 | +| 范围 | 应执行数 | 实际执行数 | 通过 | 失败 | 跳过 | 未执行 | | ||
| 39 | +|------|----------|------------|------|------|------|--------| | ||
| 40 | +| 穿刺代表用例(正式开发不适用) | | | | | | | | ||
| 41 | +| 黑盒(正式开发) | | | | | | | | ||
| 42 | +| 白盒(未生成时不适用) | | | | | | | | ||
| 43 | + | ||
| 44 | +计数应与原始结果逐条一致,不能只给汇总通过率。逐输出记录精度指标、阈值、实测值及判定结果;源码分支覆盖区分设计覆盖、实际命中与受阻路径。复用与重跑按以下规则确定;不能使用旧版本日志掩盖当前失败。 | ||
| 45 | + | ||
| 46 | +## 证据复用规则 | ||
| 47 | + | ||
| 48 | +| 当前变化 | 必须完成的验证 | | ||
| 49 | +|----------|----------------| | ||
| 50 | +| 无待修复缺陷;决定结果的输入、版本、配置及设备环境一致;已有本阶段要求的全量成功记录 | 引用原始证据并核对当前交付与清单一致,不重复构建或测试 | | ||
| 51 | +| 仅报告文字或许可注释变化 | 核对完整差异确实不影响执行,保留新旧哈希及映射;符合条件时复用,不声称重新构建或重跑 | | ||
| 52 | +| Python logging 等可执行语句变化 | 不能按纯注释处理;验证受影响的输出、计数、退出码与异常行为。只有证实计算、参数、断言、控制流和执行环境未受影响时,才能复用原设备结果,否则重跑 | | ||
| 53 | +| 算子计算、注册/包装、打包、编译配置或工具链变化 | 重建并运行本阶段要求的全量回归,复核实际加载路径和二进制 | | ||
| 54 | +| 用例、golden、checker/阈值、数据生成、种子或测试逻辑变化 | 重新运行本阶段全量回归;候选构建输入未变时可复用 wheel。不得放宽标准消除失败 | | ||
| 55 | +| 设备或运行环境变化;原证据缺失、不完整、含失败或无法对应当前版本 | 补齐当前环境下的完整验证;不能证明构建仍适用时重建 | | ||
| 56 | + | ||
| 57 | +穿刺代表用例不能替代正式全量;上一阶段黑盒通过不能替代新增白盒的执行。后续节点仍核对全量用例 ID 与结果,不能只引用上一份报告的 pass。复用时在本阶段报告记录来源及差异判断,verifier 独立确认复用条件;有疑点即要求执行者补证据,不由验收者代跑。 | ||
| 58 | + | ||
| 59 | +## 失败与归属 | ||
| 60 | + | ||
| 61 | +| 用例 ID | 现象与复现命令 | 原始证据 | 算子 / 测试 / 框架问题 | 影响范围 | | ||
| 62 | +|---------|----------------|----------|-------------------------|----------| | ||
| 63 | + | ||
| 64 | +白盒阶段允许如实记录被正确用例暴露的算子缺陷,供下一节点修复;算子开发与修复交付要求本阶段全量通过。不能删测、放宽阈值或隐藏失败来取得通过。 | ||
| 65 | + | ||
| 66 | +## 重试记录 | ||
| 67 | + | ||
| 68 | +- 对应验收报告的问题编号及修复内容: | ||
| 69 | +- 本次证据目录:{使用节点 ID 前缀及不同轮次后缀,保留前次日志} | ||
| 70 | +- 修改后的文件与新哈希: | ||
| 71 | +- 复用证据路径及有效性依据,或阻塞条件未变的复核结果: | ||
| 72 | + | ||
| 73 | +重试只补差异;失败、未运行和未验证项如实记录,不以重复生成报告替代修复。 | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | +# {算子名称} 白盒测试设计与用例接入 | ||
| 2 | + | ||
| 3 | +> 算子实现后,developer 依据真实源码生成用例,直接写入已有 ST 框架。本文记录设计依据和接入结果,不能代替可执行用例。 | ||
| 4 | + | ||
| 5 | +## 输入与版本 | ||
| 6 | + | ||
| 7 | +- 算子源码及当前版本: | ||
| 8 | +- 已确认需求与黑盒方案: | ||
| 9 | +- 现有测试框架、入口与版本: | ||
| 10 | + | ||
| 11 | +## 源码分支清单 | ||
| 12 | + | ||
| 13 | +| 分支 ID | 文件/函数/行号或条件原文 | 触发条件 | 边界及适用依据 | | ||
| 14 | +|---------|-------------------------|----------|----------------| | ||
| 15 | + | ||
| 16 | +> 枚举全部有效的尾核、尾块、非对齐、多核、dtype 与 tilingkey 等分支;不适用项给出源码依据。知识搜集草稿不限制实际分支。 | ||
| 17 | + | ||
| 18 | +## 白盒用例与框架接入 | ||
| 19 | + | ||
| 20 | +| 用例 ID | 源码分支 | shape/dtype/参数 | 数据构造与预期结果 | 测试文件/入口 | 复用的黑盒用例 | | ||
| 21 | +|---------|----------|-----------------|--------------------|---------------|----------------| | ||
| 22 | + | ||
| 23 | +- 全量执行命令: | ||
| 24 | +- 新增/修改文件与用例发现方式: | ||
| 25 | +- golden、精度及预期异常依据: | ||
| 26 | + | ||
| 27 | +## 覆盖记录 | ||
| 28 | + | ||
| 29 | +| 源码分支 | 对应用例 | 设计覆盖依据 | 实际命中或受阻状态 | 证据路径 | | ||
| 30 | +|----------|----------|--------------|--------------------|----------| | ||
| 31 | + | ||
| 32 | +## 问题交接 | ||
| 33 | + | ||
| 34 | +| 问题 | 算子缺陷/测试问题/框架问题 | 复现步骤与证据 | 受影响路径 | 修复要求 | | ||
| 35 | +|------|--------------------------|----------------|------------|----------| | ||
| 36 | + | ||
| 37 | +> 测试与框架问题须在本节点修正;用例正确但暴露的算子缺陷交给下游代码修复。没有缺陷时如实记录,无需制造问题。 | ||
| @@ -0,0 +1,25 @@ | |||
| 1 | +# {算子名称} 知识搜集与实现草稿 | ||
| 2 | + | ||
| 3 | +> 中立参考,不是锁定方案或路线可行性证明。只记录本轮重点,引用需求文件而非复述全文;不要求遍历资料库或给全部阅读文件计算哈希。 | ||
| 4 | + | ||
| 5 | +## 关键资料与结论 | ||
| 6 | + | ||
| 7 | +| 要解决的问题 | 关键结论 | 来源路径/链接、版本与位置 | 适用条件及限制 | | ||
| 8 | +|-------------|----------|--------------------------|----------------| | ||
| 9 | + | ||
| 10 | +决定路线或 API 使用的引用须可核对。非关键资料未找到时记录未知,删除无依据断言;不为凑齐参考资料展开无关检索。新增 Skill 建议注明适用节点与阶段,仅供整轮结束后编排,不改变本轮清单。 | ||
| 11 | + | ||
| 12 | +## 初版实现草稿 | ||
| 13 | + | ||
| 14 | +| 候选路线及 API 组合/数据流 | 代表性 shape 分组 | 多核/块大小/Buffer/尾块设想 | 依据与待验证项 | | ||
| 15 | +|---------------------------|------------------|----------------------------|----------------| | ||
| 16 | + | ||
| 17 | +区分资料已证实、推导建议和待验证假设;不逐个展开完整 shape 笛卡尔积,不宣称已实测或已完成性能验证。 | ||
| 18 | + | ||
| 19 | +## 关键风险与下一步 | ||
| 20 | + | ||
| 21 | +- 建议优先验证的关键组合与理由: | ||
| 22 | +- 未确认限制或规则冲突及依据: | ||
| 23 | +- 本次未覆盖的范围: | ||
| 24 | + | ||
| 25 | +重试只追加问题编号、修正结论及证据变化;保留历史,不重写未变内容。 | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | +# {节点 ID} {步骤名称} 验收报告 | ||
| 2 | + | ||
| 3 | +> 仅 verifier 编写。通过、失败及阻塞均须落盘。验收者核对当前产物和执行证据,不代替执行者构建、运行全量测试或补造日志。 | ||
| 4 | + | ||
| 5 | +## 验收对象与证据 | ||
| 6 | + | ||
| 7 | +- 本轮节点及验收次数: | ||
| 8 | +- 需求及输入版本: | ||
| 9 | +- 当前交付件路径、源码/测试哈希或变更快照: | ||
| 10 | +- 执行报告、固定版本的证据清单与原始结果索引路径: | ||
| 11 | +- 本次变更及复用核对:{新执行 / 复用来源;当前版本差异与有效性判断} | ||
| 12 | +- 实际加载的补充 Skill 与依据(无则记无): | ||
| 13 | + | ||
| 14 | +## 逐项结论 | ||
| 15 | + | ||
| 16 | +| 验收项 | 通过 / 失败 / 阻塞 / 不适用 | 事实依据与文件位置 | | ||
| 17 | +|--------|--------------------------|--------------------| | ||
| 18 | + | ||
| 19 | +涉及执行结果时,核对命令、工作目录、退出码、源码/测试/构建产物哈希、运行时加载路径和当前阶段用例计数、逐项结果。穿刺只要求下发范围的关键组合与代表用例真实设备证据;正式交付要求全量,二者不能互相代替。执行者自述通过不足以证明通过;缺失或无法核对的证据判失败。知识和文档节点按其交付标准审阅,不要求构建日志;知识搜集重点核对关键引用,不重做全库检索或要求所有阅读文件的哈希。报告只列结论和证据位置,不复制原始输出或已有哈希清单。按测试执行记录模板的证据复用规则核对当前版本及差异,原始日志与结果仍须可读取,不能只信上游 pass;复用结果不记为本次新执行。 | ||
| 20 | + | ||
| 21 | +涉及代码检视时,列明检查范围、规则、问题位置和结论,可引用本节点的代码检视报告。白盒节点分别给出测试质量与算子功能结论:正确用例暴露算子缺陷时列出证据和下游修复要求,不宣称算子功能通过。 | ||
| 22 | + | ||
| 23 | +## 问题与修改意见 | ||
| 24 | + | ||
| 25 | +| 问题编号 | 严重程度 | 位置与证据 | 要求修正的内容 | 完成判据 | | ||
| 26 | +|----------|----------|------------|----------------|----------| | ||
| 27 | + | ||
| 28 | +无问题写“无”。失败时给出可执行的修改要求,不只写 fail;超出本节点授权范围的缺口明确记录,不要求执行者越权修改。 | ||
| 29 | + | ||
| 30 | +## 最终结论 | ||
| 31 | + | ||
| 32 | +- 本节点:{pass / fail;阻塞属于 fail,并说明依据} | ||
| 33 | +- 本阶段测试:{通过 / 不通过 / 本节点不适用;注明穿刺代表用例或正式全量范围} | ||
| 34 | +- 代码检视:{通过 / 不通过 / 本节点不适用} | ||
| 35 | +- 下游修复事项(仅已有流程允许时): | ||
| 36 | + | ||
| 37 | +同节点重试时,执行者只读本报告;验收者核对当前产物版本,复用未变且仍有效的证据,仅复核受影响项并追加本次结论,保留此前问题与处理记录,旧通过结论不能批准新版本。 | ||
| 38 | + | ||
| 39 | +确定性阻塞条件未变时注明条件与依据,维持失败;不要求执行者重复同一完整调查,也不把阻塞标为通过。 | ||
Aplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/黑盒测试设计.md+130-0
| @@ -0,0 +1,130 @@ | |||
| 1 | +# {算子名称} 黑盒测试设计 | ||
| 2 | + | ||
| 3 | +> 黑盒测试设计阶段产出。本仓采用 direct launch 工程架构。architect 依据已确认需求设计 golden、分级用例与覆盖矩阵,复用符合契约的测试资产并补齐覆盖缺口。 | ||
| 4 | +> 本模板规定方案文档的格式与填写要求,覆盖维度分解、用例设计、精度口径及覆盖矩阵。 | ||
| 5 | + | ||
| 6 | +## 1. 概述 | ||
| 7 | + | ||
| 8 | +### 1.1 算子信息 | ||
| 9 | + | ||
| 10 | +| 项目 | 内容 | | ||
| 11 | +|------|------| | ||
| 12 | +| 算子名称 | {算子名} | | ||
| 13 | +| 接口原型 | `{签名}` | | ||
| 14 | +| 支持数据类型 | {dtype 列表} | | ||
| 15 | +| 目标芯片/架构 | {芯片} / {archXX} | | ||
| 16 | + | ||
| 17 | +### 1.2 算子功能 | ||
| 18 | + | ||
| 19 | +{一句话描述算子功能} | ||
| 20 | + | ||
| 21 | +## 2. Golden 对齐方案 | ||
| 22 | + | ||
| 23 | +### 2.1 Golden 计算方案 | ||
| 24 | + | ||
| 25 | +| 项目 | 内容 | | ||
| 26 | +|------|------| | ||
| 27 | +| golden 实现位置 | {现有或计划实现的文件路径、调用入口} | | ||
| 28 | +| Golden 计算路径 | {与需求数学定义一致,独立于被测 Kernel} | | ||
| 29 | +| 精度比对方式 | {逐元素 / 统计指标;具体判定指标与阈值填 2.3 口径表} | | ||
| 30 | + | ||
| 31 | +### 2.2 测试工程与执行入口 | ||
| 32 | + | ||
| 33 | +| 项目 | 内容 | | ||
| 34 | +|------|------| | ||
| 35 | +| 用例文件 | {实际或计划交付的用例文件路径} | | ||
| 36 | +| 数据生成 | {输入生成入口、随机种子及预期输出生成方式} | | ||
| 37 | +| 测试入口 | {编译、运行和比对命令,包含全量用例和补充用例} | | ||
| 38 | +| 结果记录 | {用例计数、逐输出误差与判定的报告路径} | | ||
| 39 | + | ||
| 40 | +### 2.3 精度判定口径表(权威源对齐) | ||
| 41 | + | ||
| 42 | +> **本节记录精度判定的生效取值及权威来源,不得留「参考 XXX 标准」式引用**。逐**输出张量**填写:不同输出可能走不同口径(如整型输出按逐元素误差、浮点输出按相对误差统计量),不合并、不省略。逐项记录需求依据、指标定义和实际断言位置。 | ||
| 43 | +> | ||
| 44 | +> 指标和阈值以已确认需求为准,逐项记录出处;资料或判定实现与需求冲突时记录差异及阻塞证据,不自行选取或放宽标准。 | ||
| 45 | + | ||
| 46 | +| 输出张量 | dtype | 判定指标(公式或名称) | 阈值 | 权威源出处(文件路径 / 字段) | 实际 checker / 附加断言位置 | | ||
| 47 | +|----------|-------|------------------------|------|------------------------------|------------------| | ||
| 48 | +| | | | | | | | ||
| 49 | + | ||
| 50 | +**辅助交叉核对**(可选,不作通过依据): | ||
| 51 | + | ||
| 52 | +| 输出张量 | 辅助容差(atol / rtol 等) | 用途 | | ||
| 53 | +|----------|---------------------------|------| | ||
| 54 | +| | | 交叉核对,与权威口径结论不一致时以权威口径为准 | | ||
| 55 | + | ||
| 56 | +**口径一致性声明**:{本地判定口径与权威源逐项一致 / 存在差异——逐条列出差异项、差异原因、风险评估,并明确该差异对当前验收的阻塞影响} | ||
| 57 | + | ||
| 58 | +## 3. 覆盖维度分解 | ||
| 59 | + | ||
| 60 | +> 把每个输入/属性拆成正交因子,逐因子列出取值集,作为下方场景与用例的推导源与覆盖矩阵的行。 | ||
| 61 | + | ||
| 62 | +### 3.1 参数因子表 | ||
| 63 | + | ||
| 64 | +| 参数 | 因子(存在性/format/rank/dtype/取值域/长度/值) | 取值集 | 来源(需求文档条目) | | ||
| 65 | +|------|------|------|------| | ||
| 66 | + | ||
| 67 | +### 3.2 边界与特殊值清单 | ||
| 68 | + | ||
| 69 | +> 按算子语义勾选适用项,删不适用带(如非负输入删负值)。 | ||
| 70 | + | ||
| 71 | +- 数值边界:{ dtype min/max / 最小正规 / 次正规 } | ||
| 72 | +- shape 边界:{ 最小 shape [1] / 单元素 / 末维非对齐 / 空 tensor / 0 维 } | ||
| 73 | +- 特殊值:{ ±0 / +inf / -inf / nan } | ||
| 74 | +- 广播(如适用):{ 等长 / 少维 / 多维 / 含 1 维 / 扩 1 轴 } | ||
| 75 | + | ||
| 76 | +## 4. 测试场景 | ||
| 77 | + | ||
| 78 | +### 4.1 正常场景 | ||
| 79 | + | ||
| 80 | +| 编号 | 场景描述 | 参数 | | ||
| 81 | +|------|----------|------| | ||
| 82 | + | ||
| 83 | +### 4.2 边界场景 | ||
| 84 | + | ||
| 85 | +| 编号 | 场景描述 | 参数 | | ||
| 86 | +|------|----------|------| | ||
| 87 | + | ||
| 88 | +### 4.3 异常场景(参数校验) | ||
| 89 | + | ||
| 90 | +| 编号 | 异常输入 | 预期行为 | | ||
| 91 | +|------|----------|----------| | ||
| 92 | + | ||
| 93 | +### 4.4 特殊值场景 | ||
| 94 | + | ||
| 95 | +| 编号 | 场景描述 | 参数 | | ||
| 96 | +|------|----------|------| | ||
| 97 | + | ||
| 98 | +## 5. 分级用例设计 | ||
| 99 | + | ||
| 100 | +> L0 门槛(单因子最小覆盖,常规 shape/dtype,快,开发时验证);L1 功能(离散因子 pairwise + 典型/竞品 shape);L2 异常(每异常场景一条 + 空 tensor 派生)。逐项记录选值及其覆盖的需求维度。 | ||
| 101 | + | ||
| 102 | +### 5.1 L0 门槛用例 | ||
| 103 | + | ||
| 104 | +| 编号 | 描述 | 参数 | 预期结果 | | ||
| 105 | +|------|------|------|----------| | ||
| 106 | + | ||
| 107 | +### 5.2 L1 功能用例 | ||
| 108 | + | ||
| 109 | +| 编号 | 描述 | 参数 | 预期结果 | | ||
| 110 | +|------|------|------|----------| | ||
| 111 | + | ||
| 112 | +### 5.3 L2 异常用例 | ||
| 113 | + | ||
| 114 | +| 编号 | 描述 | 参数 | 预期结果 | | ||
| 115 | +|------|------|------|----------| | ||
| 116 | + | ||
| 117 | +## 6. 覆盖矩阵 | ||
| 118 | + | ||
| 119 | +> 从需求独立枚举声明维度,与全部用例逐维对照,供 verifier 核对。不得留「任意 / 不限」式开放上界;覆盖缺口在补充用例列标注。 | ||
| 120 | + | ||
| 121 | +| 声明维度(dtype / shape 范围 / 边界 / 特殊值 / 广播) | 取值 | 命中用例编号 | 是否命中 | 补充用例编号(未命中时) | | ||
| 122 | +|------|------|------|------|------| | ||
| 123 | + | ||
| 124 | +## 7. 汇总 | ||
| 125 | + | ||
| 126 | +| 分级 | 用例数 | | ||
| 127 | +|------|--------| | ||
| 128 | +| L0 | | | ||
| 129 | +| L1 | | | ||
| 130 | +| L2 | | | ||
Aplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/workflows/basic.yaml+68-0
| @@ -0,0 +1,68 @@ | |||
| 1 | +# 仅在路线明确或穿刺通过后启动。PM 下发 Skill、复用路径和预算;task 路径相对本文件。 | ||
| 2 | +workflow: ops-direct-invoke | ||
| 3 | +max_parallel: 2 | ||
| 4 | +nodes: | ||
| 5 | +- id: '0.0' | ||
| 6 | + yaml: ../../tasks/知识搜集.yaml | ||
| 7 | + depends_on: [] | ||
| 8 | + max_retries: 3 | ||
| 9 | + variables: | ||
| 10 | + executor_skills: 无补充 Skill。 | ||
| 11 | + verifier_skills: 无补充 Skill。 | ||
| 12 | + research_focus: 重点搜集算子专项资料、目标芯片 API 组合和不同 shape 的初版 Tiling。 | ||
| 13 | +- id: '0.1' | ||
| 14 | + yaml: ../../tasks/黑盒测试设计.yaml | ||
| 15 | + depends_on: [] | ||
| 16 | + max_retries: 3 | ||
| 17 | + variables: | ||
| 18 | + executor_skills: 无补充 Skill。 | ||
| 19 | + verifier_skills: 无补充 Skill。 | ||
| 20 | +- id: '1' | ||
| 21 | + yaml: ../../tasks/测试工程开发.yaml | ||
| 22 | + depends_on: | ||
| 23 | + - '0.0' | ||
| 24 | + - '0.1' | ||
| 25 | + max_retries: 3 | ||
| 26 | + variables: | ||
| 27 | + executor_skills: 无补充 Skill。 | ||
| 28 | + verifier_skills: 无补充 Skill。 | ||
| 29 | +- id: '2' | ||
| 30 | + yaml: ../../tasks/算子开发.yaml | ||
| 31 | + depends_on: | ||
| 32 | + - '1' | ||
| 33 | + max_retries: 3 | ||
| 34 | + variables: | ||
| 35 | + executor_skills: | | ||
| 36 | + 候选 Skill(仅在实际证据命中时加载): | ||
| 37 | + - 自测或复现出现输出错误、精度不达标时,必须加载 `ascendc-precision-debug` Skill,按其中的要求执行。 | ||
| 38 | + - 自测或复现出现卡死、超时、崩溃或内存访问异常时,必须加载 `ascendc-crash-debug` Skill,按其中的要求执行。 | ||
| 39 | + verifier_skills: 无补充 Skill。 | ||
| 40 | + knowledge_documents: $WORK_DIR/0.0-知识搜集.md | ||
| 41 | +- id: '3' | ||
| 42 | + yaml: ../../tasks/白盒测试设计.yaml | ||
| 43 | + depends_on: | ||
| 44 | + - '2' | ||
| 45 | + max_retries: 3 | ||
| 46 | + variables: | ||
| 47 | + executor_skills: 无补充 Skill。 | ||
| 48 | + verifier_skills: 无补充 Skill。 | ||
| 49 | +- id: '4' | ||
| 50 | + yaml: ../../tasks/代码修复.yaml | ||
| 51 | + depends_on: | ||
| 52 | + - '3' | ||
| 53 | + max_retries: 3 | ||
| 54 | + variables: | ||
| 55 | + executor_skills: | | ||
| 56 | + 候选 Skill(仅在实际证据命中时加载): | ||
| 57 | + - 自测或复现出现输出错误、精度不达标时,必须加载 `ascendc-precision-debug` Skill,按其中的要求执行。 | ||
| 58 | + - 自测或复现出现卡死、超时、崩溃或内存访问异常时,必须加载 `ascendc-crash-debug` Skill,按其中的要求执行。 | ||
| 59 | + verifier_skills: 无补充 Skill。 | ||
| 60 | + repair_requirements: 根据本轮白盒测试设计节点的验收报告、测试执行记录与源码覆盖记录,修复暴露的算子代码缺陷;同步受影响的白盒用例,完成全量黑盒、白盒回归并提供证据供代码检视。没有待修复缺陷且当前版本已有有效全量证据时复用并记录依据,否则补齐验证。 | ||
| 61 | +- id: '5' | ||
| 62 | + yaml: ../../tasks/文档准备.yaml | ||
| 63 | + depends_on: | ||
| 64 | + - '4' | ||
| 65 | + max_retries: 3 | ||
| 66 | + variables: | ||
| 67 | + executor_skills: 无补充 Skill。 | ||
| 68 | + verifier_skills: 无补充 Skill。 | ||
| @@ -0,0 +1,12 @@ | |||
| 1 | +# 路线有关键疑点时先独立穿刺;PM 下发前具体化范围和 Skill 清单,退出后再编排正式开发。 | ||
| 2 | +workflow: ops-direct-invoke | ||
| 3 | +max_parallel: 1 | ||
| 4 | +nodes: | ||
| 5 | +- id: '0' | ||
| 6 | + yaml: ../../tasks/技术穿刺.yaml | ||
| 7 | + depends_on: [] | ||
| 8 | + max_retries: 3 | ||
| 9 | + variables: | ||
| 10 | + spike_scope: 在已确认需求的芯片、架构和精度约束下,用最小代表 shape 验证待开发算子的关键端到端组合;覆盖原始任务中列出的技术疑点,记录未验证范围。不改变已确认的单 Kernel 或数据驻留要求。 | ||
| 11 | + executor_skills: 无补充 Skill。 | ||
| 12 | + verifier_skills: 无补充 Skill。 | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-build-guide | ||
| 3 | +description: 构建可供 CANN Bench 评测的 Ascend C 直调源码和 cann_bench wheel,检查真实加载路径与版本。编译、安装、调试构建问题时使用。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 仓库构建指南 | ||
| 7 | + | ||
| 8 | +本仓采用 cann-bench `examples/direct_launch_example` 工程:bisheng 编译 kernel,g++ 编译注册包装,链接 `_C.abi3.so` 并生成 `dist/cann_bench*.whl`。评测器可从源码根目录调用 `bash build.sh`。 | ||
| 9 | + | ||
| 10 | +读取 [构建与验证](references/build-guide.md),按当前环境、源码快照和目标芯片构建。构建成功、wheel 可导入与算子功能通过分别记录,不混为一个结论。 | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +# 构建与版本核对 | ||
| 2 | + | ||
| 3 | +## 构建输入 | ||
| 4 | + | ||
| 5 | +记录 `source_dir`、cann-bench commit、Python 环境、CANN 路径和目标 SoC。环境信息来自本轮记录,不重复全面探测。构建在 `$WORK_DIR/<节点ID>-构建工程/` 的源码快照中执行,包含本次未提交代码,排除 `.cannbot/`、本轮工作目录、旧构建目录和二进制;记录与交付源码的对应哈希。算子计算、注册、打包代码、编译配置或工具链变化后更新快照并重建;仅测试用例变化不强制重建候选 wheel,但须记录与当前源码的对应关系。纯许可注释变更须核对完整差异、保留旧构建输入哈希及与当前源码的映射,不将旧 wheel 声称为新源码重新构建。 | ||
| 6 | + | ||
| 7 | +官方脚本接受 `--soc=ascend910b`、`--soc=ascend910_93`、`--soc=ascend950`;前两者映射 `dav-2201`,950 映射 `dav-3510`。该值是编译平台名,不是性能 metadata 的硬件标签。根 `build.sh` 无参数时会自动检测;若检测无法确定平台,应先修正明确的环境/启动配置,保证评测器执行的 `bash build.sh` 也能复现,不能只验证一个外部手工命令。 | ||
| 8 | + | ||
| 9 | +## 构建和导入 | ||
| 10 | + | ||
| 11 | +在已选定的隔离 Python 环境中执行,以下 `build_dir` 为本轮快照绝对路径,`soc` 为已确认编译平台: | ||
| 12 | + | ||
| 13 | +```bash | ||
| 14 | +cd "$build_dir" | ||
| 15 | +bash build.sh --soc="$soc" | ||
| 16 | +python3 -m pip install dist/cann_bench*.whl --force-reinstall --no-deps | ||
| 17 | +``` | ||
| 18 | + | ||
| 19 | +保留退出码和原始日志;wheel 应唯一且对应当前架构。示例 `build.sh --install` 也可安装,但须保证它调用的 pip 与评测 Python 是同一环境。不要在不同任务中并发重装同一个 `cann_bench` 包。 | ||
| 20 | + | ||
| 21 | +从工程目录之外的新进程检查 `cann_bench.__file__`、`cann_bench._C.__file__`、目标 callable 与 schema,并记录实际加载文件哈希;不要让 `PYTHONPATH` 中旧工程或已安装 golden wheel 抢占导入。golden 自验证包与候选包同名,不能混用。Python 检查脚本使用 logging 输出。 | ||
| 22 | + | ||
| 23 | +评测器发现预构建 wheel 时可能跳过编译;因此必须保存所用 wheel 的真实编译证据和源码→wheel→加载库的关联;有效复用时引用原构建轮次,不虚构本次编译。仅见到一个 dist 文件不代表它来自当前代码。不要使用 `--skip-install` 掩盖 wheel 更新遗漏。 | ||
| 24 | + | ||
| 25 | +## 依赖与常见故障 | ||
| 26 | + | ||
| 27 | +- 软件版本以当前 cann-bench 的 `pyproject.toml`、`uv.lock`、`requirements.txt` 和所选示例为依据;torch/torch_npu 必须匹配,不能单独升级 torch 破坏环境。 | ||
| 28 | +- 保留示例 CMake 的 `CMAKE_LINK_DEPENDS_USE_LINKER FALSE`,避免较新 CMake 给 bisheng linker 传入不支持的参数。 | ||
| 29 | +- 缺失 symbol、导入错误先核对目标架构、CANN 库路径、Python 环境和实际加载的 `_C`,不要把候选切换成 CPU/Torch 实现“修复”。 | ||
| 30 | +- cann-bench 的 `cann_bench_utils` 是独立的评测辅助扩展,不能把它当作候选 `cann_bench` 或删除它;缺失时按其官方构建入口在准备阶段处理。 | ||
| 31 | +- 官方评测会写编译日志并安装 wheel;使用快照和独立环境,避免污染交付源码或其它任务。构建失败直接保存原始错误,不临时挪走其它算子掩盖整批失败。 | ||
| 32 | + | ||
| 33 | +构建记录包含命令、工作目录、环境来源、退出码、源码/测试清单及哈希、wheel 与实际加载库路径及哈希。功能结果另由真实设备评测提供,`test.sh` 的示例 pytest 不是完整验收。 | ||
| 34 | + | ||
| 35 | +## 核对依据 | ||
| 36 | + | ||
| 37 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;运行时记录实际 checkout 版本,版本变化时核对相关接口。 | ||
| 38 | + | ||
| 39 | +- [examples/direct_launch_example/build.sh](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/build.sh) | ||
| 40 | +- [examples/direct_launch_example/setup.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/setup.py) | ||
| 41 | +- [src/kernel_eval/data/package_manager.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/data/package_manager.py) | ||
| 42 | +- [docs/spec/submission_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/submission_spec.md) | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-coding-rules | ||
| 3 | +description: CANN Bench 候选算子的实现真实性、包装边界、工程接口与 Ascend C 代码质量要求。编码、修复和检视时使用。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 仓库编码规则 | ||
| 7 | + | ||
| 8 | +算子计算必须来自本工程的真实 NPU kernel,并符合 CANN Bench 的提交与运行接口。读取 [编码检查表](references/red-lines.md),按实际代码和证据检视;不要把静态规则套到测试 golden 上,也不把样例结构当作所有算子都适用的算法方案。 | ||
| 9 | + | ||
| 10 | +违规项给出位置、影响和修正要求。规则只定义代码与交付质量,不持有调度状态、不指定流程回退。 | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +# 编码检查表 | ||
| 2 | + | ||
| 3 | +## A 类:候选实现真实性 | ||
| 4 | + | ||
| 5 | +对应官方 `SUB-BEH-001`~`SUB-BEH-007`,违反时不能作为有效候选交付。适用范围是候选执行路径;独立 golden 和测试输入生成可以使用 Torch,不得因此被误判为候选代算。 | ||
| 6 | + | ||
| 7 | +| 本仓编号 / 官方规则 | 检视内容 | 修正方向 | | ||
| 8 | +|--------------------|----------|----------| | ||
| 9 | +| A1 / SUB-BEH-001 | 包装层是否把全部或部分计算交给 Torch/torch_npu 内置计算 API | 由提交 kernel 实现;kernel 内 Ascend C 原语不属于包装层代算 | | ||
| 10 | +| A2 / SUB-BEH-002 | 是否在包装层通过 transpose/contiguous/cast 等完成实质性数据或布局变换 | 变换纳入 kernel;参数读取、Tiling 准备和输出分配可以保留 | | ||
| 11 | +| A3 / SUB-BEH-003 | 是否只转发到 CANN 内置同名算子 | 提供自有实现,不把接口包装当开发完成 | | ||
| 12 | +| A4 / SUB-BEH-004 | CPU fallback、没有实际执行提交的 NPU kernel | 在目标设备真实执行并记录证据 | | ||
| 13 | +| A5 / SUB-BEH-005 | 缓存输出、固定结果或按公开 case/data pointer 命中 | 对每次合法输入真实计算;有依据的 shape 分派不是预置答案 | | ||
| 14 | +| A6 / SUB-BEH-006 | 篡改 profiler、同步、计时或安全检查 | 保持评测器及环境接口完整 | | ||
| 15 | +| A7 / SUB-BEH-007 | FakeTensor、伪对象、惰性结果或非法返回结构 | 返回实际计算的 Tensor,符合输出结构与连续性要求 | | ||
| 16 | + | ||
| 17 | +自动保护没有报错不代表所有规则都通过;I/O 变换等仍需代码检视。报告应引用具体违规位置,不能只凭关键字命中判定。 | ||
| 18 | + | ||
| 19 | +## B 类:工程与代码质量 | ||
| 20 | + | ||
| 21 | +| 检查项 | 要求 | | ||
| 22 | +|--------|------| | ||
| 23 | +| 提交接口 | 根 build.sh 可复现生成 cann_bench wheel,Python callable、schema、C++ 注册与 proto 一致 | | ||
| 24 | +| 版本与载入 | 当前源码、测试、构建 wheel 和实际加载库一致;没有旧包或 golden wheel 冒充候选 | | ||
| 25 | +| 硬件资源 | 核数、UB/Buffer 与分块满足目标平台;动态资源查询或固定参数的适用依据明确,不无依据写死硬件假设 | | ||
| 26 | +| 搬运与边界 | 用目标平台支持的 API 处理对齐、尾块和边界,地址/长度计算无溢出或越界;不以强制 wrapper 拷贝隐藏不支持输入 | | ||
| 27 | +| 并发与同步 | 当前 stream/设备正确,依赖有对应同步,分配与释放、队列生产与消费成对;不把数调用次数当完整正确性证明 | | ||
| 28 | +| 类型与数值 | dtype 分派与计算精度符合规格,未初始化变量、非法转换及未覆盖分支有检查 | | ||
| 29 | +| API 可用性 | 关键 API 及变体有目标版本依据;不凭空推荐不存在的接口,不把一个示例的可用性推广到所有芯片 | | ||
| 30 | +| 代码边界 | kernel 中不使用目标工具链不支持的动态分配、递归或库功能;具体支持情况按平台资料和编译证据核实 | | ||
| 31 | +| 许可与输出 | 新增代码带仓库 license 头,保留上游来源许可;Python 日志使用 logging | | ||
| 32 | +| 测试可信性 | 不改评测器、golden、阈值或删测掩盖失败;公开任务只读,新增用例和来源可追溯 | | ||
| 33 | + | ||
| 34 | +检视仅记录本次授权范围的问题与证据,不要求实现照搬知识搜集草稿,也不自行决定回退或放宽标准。 | ||
| 35 | + | ||
| 36 | +## 核对依据 | ||
| 37 | + | ||
| 38 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;按实际 checkout 记录版本和差异。 | ||
| 39 | + | ||
| 40 | +- [docs/guide/submission_rules.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/guide/submission_rules.md) | ||
| 41 | +- [docs/spec/submission_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/submission_spec.md) | ||
| 42 | +- [examples/direct_launch_example/README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/README.md) | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-env-check | ||
| 3 | +description: PM 检查 CANN Bench 直调算子开发及评测环境,持久化 .cannbot/环境信息.md;后续任务复用已有通过记录。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 仓库环境检查 | ||
| 7 | + | ||
| 8 | +由 PM 在当前用户会话执行,不进入节点图。只检查环境,不安装、升级或修复依赖。首次需求缺项应先向用户发问,不等完整环境检查结束。 | ||
| 9 | + | ||
| 10 | +## 复用与路径 | ||
| 11 | + | ||
| 12 | +仓库级记录为 `<目标仓>/.cannbot/环境信息.md`。存在非空通过记录时直接复用,不因开发新算子重新运行 NPU、编译器或版本探测;复制为本轮 `$WORK_DIR/环境信息.md`,记录原始时间及来源,运行中只读。 | ||
| 13 | + | ||
| 14 | +空记录、失败记录或当前任务超出记录支持范围时报告差异,不把文件存在当通过,也不自动重新校验。用户明确要求重新检查时保留旧版本,更新发生在工作流运行前或整轮退出后。 | ||
| 15 | + | ||
| 16 | +## 首次检查清单 | ||
| 17 | + | ||
| 18 | +仅在没有仓库级记录时执行;结果及原始日志放在 `.cannbot/环境检查/`,通过后按 [环境信息](references/环境信息.md) 发布仓库级记录。 | ||
| 19 | + | ||
| 20 | +| 检查项 | 方法与通过依据 | | ||
| 21 | +|--------|----------------| | ||
| 22 | +| 评测源码 | 定位用户指定 checkout,或 `.cannbot/dependencies/ops-direct-invoke/cann-bench/`;记录 commit,确认 direct_launch_example、目标任务格式、kernel_eval CLI 可用 | | ||
| 23 | +| NPU | `npu-smi info` 与所用 torch_npu 的设备信息;记录实际型号、可用设备 ID、状态及与需求目标的关系,不拿需求当检测结果 | | ||
| 24 | +| CANN/编译器 | 已生效的 `ASCEND_HOME_PATH`、CANN 版本、bisheng/g++ 路径;核对当前 checkout 的要求与所选 SoC 映射 | | ||
| 25 | +| Python/依赖 | 记录 Python 环境和版本、torch/torch_npu 的版本与导入;核对当前 pyproject/uv.lock/requirements 和示例依赖,不能盲目升级或重装 | | ||
| 26 | +| 构建工具 | CMake、build/setuptools/wheel;直调示例要求 CMake ≥ 3.16,保留其新 CMake 链接兼容设置 | | ||
| 27 | +| 评测组件 | 检查 kernel_eval CLI 的 help/任务发现、`cann_bench_utils` 是否可导入及其来源;缺失时报告准备项,不在检查中静默触发安装 | | ||
| 28 | +| 仓库资产 | 记录候选源码目录、任务目录、已有 pytest/评测入口与算子文档线索;不把一次快照当作以后永久现状 | | ||
| 29 | + | ||
| 30 | +核对版本的官方快速入门要求 Python 3.10+、CANN 9.1.0+,实际依赖以当前 checkout 为准;torch/torch_npu 组合须按该版本的依赖和平台匹配。上述最低版本不等于任意版本组合都兼容,不宣称本次检查已完成 kernel 编译或设备精度验收。 | ||
| 31 | + | ||
| 32 | +不要用 `scripts/run_evaluation.sh` 作无副作用探测:它可能构建辅助组件、安装候选包并运行评测。环境准备缺项由调用方安排修复,完成后再按授权复核;不得通过禁用保护组件绕过。 | ||
| 33 | + | ||
| 34 | +## 完成条件 | ||
| 35 | + | ||
| 36 | +缓存与本轮副本均非空,结论通过,包含 checkout/commit、Python 环境、设备、版本、支持范围和证据路径。后续源码构建、设备测试属于正常开发执行,不属于重复环境调查。 | ||
| 37 | + | ||
| 38 | +## 核对依据 | ||
| 39 | + | ||
| 40 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;按实际 checkout 记录版本和差异。 | ||
| 41 | + | ||
| 42 | +- [docs/guide/quick_start.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/guide/quick_start.md) | ||
| 43 | +- [requirements.txt](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/requirements.txt) | ||
| 44 | +- [scripts/run_evaluation.sh](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/scripts/run_evaluation.sh) | ||
| @@ -0,0 +1,42 @@ | |||
| 1 | +# 仓库环境信息 | ||
| 2 | + | ||
| 3 | +- 目标仓绝对路径: | ||
| 4 | +- 检查时间、检查依据及日志目录: | ||
| 5 | +- 结论:{通过 / 阻塞;仅通过版本发布为仓库级缓存} | ||
| 6 | + | ||
| 7 | +## CANN Bench 与工程 | ||
| 8 | + | ||
| 9 | +| 项目 | 实际值与依据 | | ||
| 10 | +|------|--------------| | ||
| 11 | +| cann-bench checkout / commit | | | ||
| 12 | +| direct_launch_example 路径 | | | ||
| 13 | +| source_dir / 已有工程 | | | ||
| 14 | +| 任务目录与版本 | | | ||
| 15 | +| kernel_eval CLI / help或任务发现结果 | | | ||
| 16 | +| cann_bench_utils 来源、版本与导入 | | | ||
| 17 | +| 已安装 cann_bench 来源 | {候选 / golden / 未安装;不混用} | | ||
| 18 | + | ||
| 19 | +## 设备与软件 | ||
| 20 | + | ||
| 21 | +| 项目 | 实际值 / 命令与结果 | | ||
| 22 | +|------|--------------------| | ||
| 23 | +| 实际 NPU 型号、数量、状态与可用 ID | | | ||
| 24 | +| 目标 SoC 与实际设备是否对应 | | | ||
| 25 | +| CANN 版本、ASCEND_HOME_PATH | | | ||
| 26 | +| bisheng / g++ 路径与版本 | | | ||
| 27 | +| Python 可执行文件与隔离环境 | | | ||
| 28 | +| torch / torch_npu 版本与导入结果 | | | ||
| 29 | +| CMake / build / setuptools / wheel | | | ||
| 30 | +| 其它评测依赖与兼容性依据 | | | ||
| 31 | + | ||
| 32 | +## 资产线索与限制 | ||
| 33 | + | ||
| 34 | +- 当前测试任务/入口与可复用内容: | ||
| 35 | +- 当前算子文档目录与格式线索:{无则明确无} | ||
| 36 | +- 支持的芯片、软件及用途范围: | ||
| 37 | +- 未决问题及所需准备动作: | ||
| 38 | +- 尚未执行的验证:{不得把检查包装成 kernel 编译或设备精度通过} | ||
| 39 | + | ||
| 40 | +## 复用 | ||
| 41 | + | ||
| 42 | +仓库级路径为 `.cannbot/环境信息.md`,原始日志在 `.cannbot/环境检查/`。本轮复制到 `$WORK_DIR/环境信息.md`,记录原始时间和来源;不因换算子重新探测,也不改写运行中的副本。任务目录、代码和文档是否仍适用由使用者轻量核对当前文件。 | ||
| @@ -0,0 +1,12 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-knowledge | ||
| 3 | +description: CANN Bench 直调算子工程知识:评测任务、源码提交接口、精度与评分契约。理解本仓交付和评测要求时使用。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 仓库领域知识 | ||
| 7 | + | ||
| 8 | +本仓开发通过 Ascend C `<<<>>>` 启动的算子,提交给 CANN Bench 的 CANN 评测后端。候选源码工程、评测任务数据与评测器是三个独立对象:源码实现算子,任务描述规格与 golden,用例由评测器加载并执行。 | ||
| 9 | + | ||
| 10 | +源码交付保留 `cann_bench` 包及同名算子命名空间,以 `examples/direct_launch_example` 为工程基础。评测任务按 `proto.yaml`、`golden.py`、`cases.yaml`、`desc.md` 组织;同一评测接口承接黑盒、白盒和回归,不按用例来源划分工作模式。 | ||
| 11 | + | ||
| 12 | +需要核对目录、接口发现、精度或评分含义时,读取 [评测契约](references/evaluation-contract.md)。本 Skill 只提供工程事实,不决定流程节点或替用户选择技术路线。 | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-knowledge/references/evaluation-contract.md+48-0
| @@ -0,0 +1,48 @@ | |||
| 1 | +# CANN Bench 评测契约 | ||
| 2 | + | ||
| 3 | +## 三个路径 | ||
| 4 | + | ||
| 5 | +| 路径 | 内容 | 使用边界 | | ||
| 6 | +|------|------|----------| | ||
| 7 | +| `bench_root` | cann-bench checkout,含 `src/kernel_eval`、`scripts`、`examples` 与 `tasks` | 记录 commit;评测器、原始 golden 和公开用例不作为候选代码修改对象 | | ||
| 8 | +| `source_dir` | 独立算子源码工程,含根 `build.sh`、`setup.py`、`cann_bench/`、`csrc/` | 构建产出 `dist/cann_bench*.whl`;不得依赖工作区外未交付的代码 | | ||
| 9 | +| `task_dir` | 本次评测任务目录或其集合根 | 必须能发现实际目标算子和非空用例集;新增测试沿用相同格式 | | ||
| 10 | + | ||
| 11 | +插件依赖 checkout 位于 `<目标仓>/.cannbot/dependencies/ops-direct-invoke/cann-bench/`;已有用户指定 checkout 可直接使用,以本轮输入记录的绝对路径为准。CANN Bench 的 `kernel_eval` 是算子评测器,与负责 Agent 调度的 harness 不同。 | ||
| 12 | + | ||
| 13 | +## 任务文件 | ||
| 14 | + | ||
| 15 | +- `proto.yaml`:`operator.name/category/difficulty/formula/inputs/outputs/attrs/schema`,是接口和输入次序的依据;`desc.md` 补充语义。 | ||
| 16 | +- `golden.py`:与算子函数匹配的独立参考实现;评测器构造输入并调用它,候选执行路径不能调用它代算。 | ||
| 17 | +- `cases.yaml`:顶层 `cases` 列表,记录 `operator`、整数 `case_id`、`input_shape`、`dtype`、`attrs`、`value_range` 等;当前 CANN loader 读取此文件,只有 `cases.csv` 不足以执行。 | ||
| 18 | +- `metadata/<hardware>.json` 与 `metadata/VERSION`:对应硬件的性能锚点及版本。不能把示例 fixture 的零占位值当作真实基线。 | ||
| 19 | +- `tasks/level1`~`level4` 是算子难度分层,不是测试设计中的 L0/L1/L2 覆盖标签。 | ||
| 20 | + | ||
| 21 | +`examples/tasks` 中 Add/Sqrt 用于验证评测链路,生产目标从当前评测任务中选择;名称匹配不证明 shape、dtype 和数学语义都匹配,需核对需求。 | ||
| 22 | + | ||
| 23 | +## 源码、wheel 与接口 | ||
| 24 | + | ||
| 25 | +1. 评测器接收已解包的 `source_dir`。没有 `dist/cann_bench*.whl` 时调用根目录 `bash build.sh`,要求返回 0 且生成 wheel。 | ||
| 26 | +2. wheel 必须可安装并 `import cann_bench`。本仓使用 `_C.abi3.so` 加载注册、`torch.ops.cann_bench.<schema函数>` 分派,`cann_bench/__init__.py` 必须导出目标同名 callable;只注册 C++ schema 而不导出 Python callable 不完整。 | ||
| 27 | +3. schema 的参数次序、类型、默认值与返回结构承接任务;不要把 `cann_bench` 当作任意可改的包名。用户要求另一外部接口时须保留评测适配契约并明确差异。 | ||
| 28 | +4. 原有 wheel 会影响评测是否重新构建。源码改变后不得用旧 wheel 冒充当前结果;交付目录中仅保留本次目标架构的有效产物。 | ||
| 29 | +5. 一份工程整体构建失败会影响该提交的所有算子;不能以只筛选某算子来掩盖工程其余编译错误。 | ||
| 30 | + | ||
| 31 | +## 编译、精度与评分 | ||
| 32 | + | ||
| 33 | +编译、功能精度、性能是不同结论。官方评测包含 HAP 性能评分;`--no-perf` 只证明相应功能精度与编译结果,不证明最终跑分或性能达标。输出报告需要保留实际评测版本、任务版本、目标硬件、源码和 wheel 版本。 | ||
| 34 | + | ||
| 35 | +精度使用 CANN 后端的 `relative_error` checker,覆盖逐输出结构、整型精确比较、浮点正常值域、小值域和相消判定。指标取值来自当前评测器及算子配置;不得用 `allclose` 冒充整套判定,也不能修改评测器来迎合实现。 | ||
| 36 | + | ||
| 37 | +性能以真实硬件 metadata 为锚点:`HAP = (T_baseline - T_HW) / ((T_cand - T_HW) + (T_baseline - T_HW))`。HAP 不是加速比;无效或缺失锚点不能推算可信分数。是否采集性能及采用什么交付门槛由任务明确,本 Skill 不擅自增加优化或提交步骤。 | ||
| 38 | + | ||
| 39 | +网站上传规则与本地评测接口不同;未检查网站规则时不承诺打包目录可直接上传,也不执行 PR、上传或外部 CI。 | ||
| 40 | + | ||
| 41 | +## 核对依据 | ||
| 42 | + | ||
| 43 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;运行时记录实际 checkout 版本,版本变化时核对相关接口。 | ||
| 44 | + | ||
| 45 | +- [docs/spec/submission_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/submission_spec.md) | ||
| 46 | +- [examples/tasks/README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/tasks/README.md) | ||
| 47 | +- [src/kernel_eval/benches/cann_loader.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/benches/cann_loader.py) | ||
| 48 | +- [README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/README.md) | ||
| @@ -0,0 +1,15 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-op-templates | ||
| 3 | +description: 从 cann-bench 的 direct_launch_example 复用直调工程骨架和算子模板;新建工程或新增算子时使用。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 算子工程模板 | ||
| 7 | + | ||
| 8 | +工程来源为 cann-bench 的 `examples/direct_launch_example/`,保留它的构建、接口注册和 Python 导出约定。目标仓已经有兼容工程时就地扩展,不重建或覆盖已有代码。 | ||
| 9 | + | ||
| 10 | +| 工作 | 参考 | | ||
| 11 | +|------|------| | ||
| 12 | +| 取得官方模板、建立工程骨架 | [工程骨架](references/project-skeleton.md) | | ||
| 13 | +| 添加 kernel、launch、注册和 Python 接口 | [算子模板](references/operator-template.md) | | ||
| 14 | + | ||
| 15 | +模板是可运行工程的起点,不证明其 Add/Sqrt 的算法、dtype 或精度适合目标算子;按已确认规格完成实现。 | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-op-templates/references/operator-template.md+27-0
| @@ -0,0 +1,27 @@ | |||
| 1 | +# 新增直调算子 | ||
| 2 | + | ||
| 3 | +以当前 checkout 中 `examples/direct_launch_example/csrc/ops/add/` 或 `sqrt/` 的真实文件为结构参考,复制到 `source_dir/csrc/ops/<op>/` 后调整名称与实现,保留许可头。 | ||
| 4 | + | ||
| 5 | +| 文件 | 必须完成的内容 | | ||
| 6 | +|------|----------------| | ||
| 7 | +| `op_kernel/<op>_kernel.cpp` | Ascend C kernel、Tiling 与 `<<<>>>` 启动函数,bisheng 编译 | | ||
| 8 | +| `op_kernel/<op>_launch.h` | g++ 可见的声明,保持参数、类型和 `extern "C"` 链接一致 | | ||
| 9 | +| `op_plugin/<op>_plugin.cpp` | schema、Meta/输出分配、PrivateUse1 注册、当前设备 stream 与自有 kernel 调用 | | ||
| 10 | +| `CMakeLists.txt` | 通过 `register_direct_launch_op` 注册源码和 include 目录 | | ||
| 11 | +| `cann_bench/__init__.py` | 加载 `_C`,增加与目标函数匹配的 Python callable,转发到 `torch.ops.cann_bench` | | ||
| 12 | + | ||
| 13 | +注册宏有四个参数:kernel 源文件、kernel include 目录、plugin 源文件、plugin include 目录。使用官方同版本示例中的调用,不能把它缩写成只有两个源码参数的伪接口。 | ||
| 14 | + | ||
| 15 | +schema 以本次任务 `proto.yaml` 的 `operator.schema` 为准:参数次序、可选值、attrs 默认值、输出结构都应一致。C++ 注册和 Python 导出同步更新;禁止保留示例的 Add/Sqrt 符号却声称实现了新算子。 | ||
| 16 | + | ||
| 17 | +包装层可以查询 shape/dtype、做参数和 Tiling 计算、分配输出、获取 stream 并启动 kernel;不在这里调用 Torch/CANN 内置算子代算,也不对输入输出做实质性搬运、类型转换或布局变换。Meta 只定义输出元信息,不执行目标计算。 | ||
| 18 | + | ||
| 19 | +API、Buffer、尾块、非对齐和 dtype 分派必须按目标算子验证。不能把示例只覆盖的类型和规模扩写成已支持范围;未知平台 API 用目标版本官方资料核实,缺少能力时记录限制。 | ||
| 20 | + | ||
| 21 | +## 核对依据 | ||
| 22 | + | ||
| 23 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;运行时记录实际 checkout 版本,版本变化时核对相关接口。 | ||
| 24 | + | ||
| 25 | +- [examples/direct_launch_example/csrc/ops/add/CMakeLists.txt](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/csrc/ops/add/CMakeLists.txt) | ||
| 26 | +- [examples/direct_launch_example/csrc/ops/add/op_plugin/add_plugin.cpp](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/csrc/ops/add/op_plugin/add_plugin.cpp) | ||
| 27 | +- [examples/direct_launch_example/cann_bench/__init__.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/cann_bench/__init__.py) | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-op-templates/references/project-skeleton.md+41-0
| @@ -0,0 +1,41 @@ | |||
| 1 | +# direct launch 工程骨架 | ||
| 2 | + | ||
| 3 | +## 获取与复用 | ||
| 4 | + | ||
| 5 | +优先使用本轮输入指定的 cann-bench checkout;插件依赖位置为 `<目标仓>/.cannbot/dependencies/ops-direct-invoke/cann-bench/`。读取其 commit 与 `examples/direct_launch_example/README.md`。来源缺失时,取得官方仓库到一个新目录并记录版本,不从文档中的省略代码拼造工程;下载和依赖准备不能阻塞首次需求问卷。 | ||
| 6 | + | ||
| 7 | +新建工程时将 `examples/direct_launch_example/` 复制到已授权的 `source_dir`。现有工程只引入缺失部分,保留原来的算子和用户改动。官方示例源码与许可头一并保留;新增代码也带仓库 license 头,Python 输出使用 logging。 | ||
| 8 | + | ||
| 9 | +## 应保留的文件 | ||
| 10 | + | ||
| 11 | +```text | ||
| 12 | +source_dir/ | ||
| 13 | +├── build.sh | ||
| 14 | +├── setup.py | ||
| 15 | +├── CMakeLists.txt | ||
| 16 | +├── cmake/ # func、ascend、python、torch、torch_npu | ||
| 17 | +├── scripts/build_wheel.sh | ||
| 18 | +├── cann_bench/__init__.py # 加载 _C,导出候选函数 | ||
| 19 | +├── csrc/extension.cpp | ||
| 20 | +├── csrc/CMakeLists.txt | ||
| 21 | +├── csrc/ops/CMakeLists.txt # 自动发现算子目录 | ||
| 22 | +├── csrc/ops/<op>/ | ||
| 23 | +│ ├── CMakeLists.txt | ||
| 24 | +│ ├── op_kernel/ | ||
| 25 | +│ └── op_plugin/ | ||
| 26 | +└── tests/ # pytest 仅作本地快速自检 | ||
| 27 | +``` | ||
| 28 | + | ||
| 29 | +`cann_bench` 包名和导出接口是 CANN 评测输入的一部分,不做统一重命名。保留双编译器设置、平台映射、链接依赖和 ABI3 打包;不要用手写的近似 CMake/setup.py 取代现成工程。是否保留 Add/Sqrt 示例依据本次交付范围决定;在新复制的工程中去除示例时同步去除注册、Python 导出和对应测试,不能留下失效 import。 | ||
| 30 | + | ||
| 31 | +构建和评测在 `$WORK_DIR/<节点ID>-构建工程/` 的本轮源码快照执行,避免官方脚本把 `build/`、`_compile.log` 等中间文件写到交付源码中。快照记录来源与哈希,排除 `.cannbot/`,不递归复制本轮工作目录,也不包含旧 `build/`、`dist/`、`*.egg-info` 或本地 `_C*.so`;已完成的源码仍交付在授权目录,构建快照不作为第二份源码继续独立修改。 | ||
| 32 | + | ||
| 33 | +正式测试使用 cann-bench 任务目录与评测器;复制示例的 `tests/` 或执行其 `test.sh` 不能自动产生目标算子的完整评测用例。 | ||
| 34 | + | ||
| 35 | +## 核对依据 | ||
| 36 | + | ||
| 37 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;运行时记录实际 checkout 版本,版本变化时核对相关接口。 | ||
| 38 | + | ||
| 39 | +- [examples/direct_launch_example/README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/README.md) | ||
| 40 | +- [examples/direct_launch_example/setup.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/setup.py) | ||
| 41 | +- [examples/direct_launch_example/CMakeLists.txt](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/direct_launch_example/CMakeLists.txt) | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-requirement | ||
| 3 | +description: 收到算子开发需求后立即提取已知条件并填写 checklist,尽早对未决关键项发送简短问卷,形成可交接的需求清单。也用于后续需求修订。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 直调算子需求对齐 | ||
| 7 | + | ||
| 8 | +在当前用户会话中完成,不作为 harness 节点执行。交付 `work_dir/需求分析.md`;work_dir 沿用调用方分配的 `.cannbot/<任务名>/workflow<序号>/`。内容按 [需求 checklist](references/requirement-checklist.md) 填写,任务是明确用户意图与开发边界,不替开发阶段完成技术方案或设备穿刺。 | ||
| 9 | + | ||
| 10 | +## 首轮先识别缺项并提问 | ||
| 11 | + | ||
| 12 | +开始需求对齐时,先向用户提示:“请先不要离开,我会先理解需求,可能需要和你对齐几个问题。”随后立即提取已知信息、识别关键缺项并发问,不等调查结束才提示。 | ||
| 13 | + | ||
| 14 | +1. 从用户原话、已有答复和附件提取目标与限制;快速定位已有本地同名任务的 proto、golden 和接口说明,比较数学语义、布局、shape/dtype、attrs 及默认值,再提出候选规格。将影响交付的差异合并进首轮问卷,不先假定布局再返确认。只做可直接定位的读取;未找到或资料尚未下载时记录未知,及时提问,不先遍历源码、下载依赖或完成环境/API 调查。 | ||
| 15 | +2. 按 checklist 预填参数,给每项标明值、来源和状态。明确事实直接沿用;能由规格或仓库契约唯一推导的值填入并注明推导依据,不重复询问。名称相同但语义或范围可能不同的资料不能自动视为匹配。 | ||
| 16 | +3. 发现影响交付的未知项或冲突即整理首轮问卷,在深入调查前发出。不等所有技术细节查清才收集用户决定。优先确认算子语义/范围、接口、目标芯片和会改变交付标准的限制;每轮最多五题,工具限制更低时遵守工具限制。 | ||
| 17 | +4. 每题一句话说明待决事项,给出清晰且可区分的预设选项;能给出合理建议时推荐一项并简述依据,允许自由补充。不把整张 checklist 当问卷,不问用户已说明或仓库已有确定答案的字段。 | ||
| 18 | + | ||
| 19 | +没有关键缺项时,不为凑问卷发问,直接进入清单核对。用户未提出且不会影响交付的用途背景、截止时间、偏好等记“未指定”,不为了填表逐一追问。 | ||
| 20 | + | ||
| 21 | +## 推导边界 | ||
| 22 | + | ||
| 23 | +- 本仓提交是 Ascend C `<<<>>>`、`cann_bench` Python 包与同名注册命名空间;已有目标 proto 的 schema、golden 和用例范围作为工程依据,保留具体来源与版本。不默认把所有 dtype/shape 都扩展到任意值。 | ||
| 24 | +- 精度承接当前 cann-bench CANN checker 及算子配置,记录取值和出处;用户没有额外精度要求时不要求用户重新选择每个阈值。标准冲突或用户提出另一指标时,说明区别并确认,不自行降低评测门槛。 | ||
| 25 | +- 芯片优先使用用户明确目标;没有指定时,可用已核对缓存中唯一可用目标作有依据的建议。目标与缓存不一致或存在多个可选目标时提问,不能将缓存事实写成用户已经选择。 | ||
| 26 | +- 技术路线只记录用户的硬约束和授权范围。未指定 SIMD/SIMT、Cube、框架或融合方式时记“未限定,在目标平台上按验证结果选择”,不强制用户预先拍板所有内部实现细节。不把技术可行性待验证误作需求缺失;是否需要穿刺交给调用方规划。 | ||
| 27 | +- 本地功能交付与实际跑分是不同结果。沿用用户的性能目标;仅要求开发算子且无额外性能门槛时,记录可评测源码及功能验证范围,不自行添加 HAP 阈值。用户明确要求实际分数或性能达标时,将其作为交付要求交调用方安排,不能因为现有模板没有性能节点就悄悄删去。 | ||
| 28 | + | ||
| 29 | +## 答复、确认与交接 | ||
| 30 | + | ||
| 31 | +问卷发出后保持待答,可并行核对不依赖答案的资料,但不启动依赖未决项的开发。真实答复回填对应条目;未答、预选项、超时或问卷消失都不算确认。问题工具不可继续使用时保留待答清单并在当前会话接续。 | ||
| 32 | + | ||
| 33 | +向用户简短展示已提取的目标、关键范围及未决决定,让用户容易纠正。已有明确指令和答复足以覆盖当前需求时,记录确认依据,直接沿用,不再追加逐字段问卷或一次重复的总批准。存在影响实现或交付标准的推断/新取舍时,把它们汇入同一轮关键问题确认,不能把“推断”写成“用户已确认”。 | ||
| 34 | + | ||
| 35 | +完成条件:必需规格有具体值或明确的授权范围,推导可追溯,关键冲突已解决,无需用户决定的内部技术选择明确留给后续验证。清单中没有阻断项后,返回绝对路径、版本、目标仓、算子及确认摘要。环境尚待检查、路线尚待穿刺分别交接,不宣称已验证,也不因这些调查延迟首轮问卷。 | ||
| 36 | + | ||
| 37 | +全部需求已确认、问卷已答复且没有待用户决定的事项后,明确提示:“需求已确认,后续可以静默开发了,你可以先离开;完成后我会汇报结果,需要你决定的阻塞也会说明。”已有信息充分、无需发问时,在完成清单核对后同样提示。仍有待答问题时不得发出该提示;静默开发只在已确认的范围内推进,不把后续新增取舍视为已获批准。 | ||
| 38 | + | ||
| 39 | +本 Skill 不编排 workflow、不调用其他 Skill、不修改 harness 状态。后续发现需求变更时,在当前用户会话中仅核对受影响条目并更新版本;旧确认不能批准新增限制或放宽标准。 | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | +# {算子名称} 需求清单 | ||
| 2 | + | ||
| 3 | +## 基本记录 | ||
| 4 | + | ||
| 5 | +- 清单版本与时间: | ||
| 6 | +- 目标代码仓、source_dir 与 work_dir 绝对路径: | ||
| 7 | +- cann-bench checkout/commit 与目标任务路径:{已定位则填写;未定位记待技术核对,不虚构} | ||
| 8 | +- 用户目标摘要: | ||
| 9 | +- 当前状态:{草稿待答 / 无阻断项可交接} | ||
| 10 | + | ||
| 11 | +## Checklist:先预填,再确认缺口 | ||
| 12 | + | ||
| 13 | +每行记录实际值或可定位的规格引用,不把下表整份发送给用户。状态使用“用户明确 / 仓库契约 / 有依据推导 / 待用户决定 / 待技术核对 / 不适用”;只有需要用户选择的关键项未解决才构成需求阻断。 | ||
| 14 | + | ||
| 15 | +| 完成 | ID | 核对项 | 预填来源与推导方法 | 何时需要提问 | 实际值、来源与状态 | | ||
| 16 | +|------|----|--------|------------------|--------------|------------------| | ||
| 17 | +| [ ] | R1 | 开发目标与范围 | 用户原话、已有实现;区分新建、修复或扩展 | 目标不同会改变产物或成功标准 | | | ||
| 18 | +| [ ] | R2 | 算子数学语义 | 指定描述、proto、golden;核对同名任务 | 存在多个语义变体或资料冲突 | | | ||
| 19 | +| [ ] | R3 | 接口与输出 | 沿用 schema、参数次序、attrs 默认值及输出结构 | 用户要求与现有接口不一致或必需字段未知 | | | ||
| 20 | +| [ ] | R4 | shape/dtype/布局 | 提取用户范围及匹配规格;用例是覆盖依据,不自动扩大范围 | 支持范围、布局或边界语义存在影响实现的歧义 | | | ||
| 21 | +| [ ] | R5 | 目标芯片及版本约束 | 用户目标优先;已有缓存给出事实与可选建议 | 多个目标可选、没有目标线索或软硬件要求冲突 | | | ||
| 22 | +| [ ] | R6 | 精度标准 | cann-bench checker、thresholds 与 proto 配置 | 标准冲突、用户有额外要求或无有效依据 | | | ||
| 23 | +| [ ] | R7 | 实现硬约束 | 用户指定的架构、单 Kernel、内存/依赖限制 | 存在需取舍的限制;未指定内部路线不必询问 | | | ||
| 24 | +| [ ] | R8 | 交付与性能要求 | 源码、用例、证据、仓内文档及用户指定跑分目标 | 是否实际跑分/性能硬门槛不明确且影响交付 | | | ||
| 25 | +| [ ] | R9 | 现有资产与路径 | 当前仓、匹配任务、源码及测试目录 | 授权修改范围冲突或存在多个无法判断的目标仓 | | | ||
| 26 | +| [ ] | R10 | 原始要求与冲突 | 逐条映射原话到以上内容 | 仍有遗漏、矛盾或影响交付的新推断 | | | ||
| 27 | + | ||
| 28 | +## 已确定规格 | ||
| 29 | + | ||
| 30 | +| 项目 | 内容与依据 | | ||
| 31 | +|------|------------| | ||
| 32 | +| 数学定义及特殊语义 | | | ||
| 33 | +| schema/调用示例 | | | ||
| 34 | +| 每个输入的 shape、dtype、layout | | | ||
| 35 | +| 每个 attrs 的取值/缺省 | | | ||
| 36 | +| 输出 shape/dtype/数量/结构 | | | ||
| 37 | +| 广播、optional、空 tensor、异常输入约定 | {只填写适用范围,不凭空扩展} | | ||
| 38 | +| 目标芯片与用户软件版本约束 | {要求与缓存实际值分开} | | ||
| 39 | +| 架构及实现限制 | {未限定的内部技术选择注明由后续验证决定} | | ||
| 40 | +| 代码/测试/文档交付位置 | | | ||
| 41 | +| 性能目标与本轮验收范围 | {实际跑分、性能硬门槛或无额外门槛;不伪造测量结果} | | ||
| 42 | + | ||
| 43 | +### 精度依据 | ||
| 44 | + | ||
| 45 | +| 输出/类型 | checker 与指标 | 实际阈值/生效配置 | 文件位置与版本 | 用户额外要求/冲突 | | ||
| 46 | +|-----------|----------------|------------------|----------------|-------------------| | ||
| 47 | + | ||
| 48 | +常用标准已有来源时直接填入,不逐项问用户选数值;缺少技术取值时记待核对,启动相关任务前补齐。不能只写“参考某标准”,也不能用人工选定 atol/rtol 替代 cann-bench 判定。 | ||
| 49 | + | ||
| 50 | +## 首轮待决项与答复 | ||
| 51 | + | ||
| 52 | +| 问题 ID / 关联条目 | 简短问题与预设选项 | 推荐依据 | 用户答复/待答 | 对应版本 | | ||
| 53 | +|-------------------|-------------------|----------|---------------|----------| | ||
| 54 | + | ||
| 55 | +只有真实需要选择的项放在此处。已明确内容不重复询问;未知但不影响交付的偏好记未指定。未回答的推荐值保留“待答”。 | ||
| 56 | + | ||
| 57 | +## 原始要求与交接 | ||
| 58 | + | ||
| 59 | +| 用户原话/答复位置 | 对应条目 | 沿用或变更说明 | | ||
| 60 | +|------------------|----------|----------------| | ||
| 61 | + | ||
| 62 | +- 当前确认依据:{已给指令/真实答复及覆盖范围;不能将推断伪装成用户决定} | ||
| 63 | +- 未解决的用户决定:{无则写无;存在则保持草稿} | ||
| 64 | +- 后续技术核对项:{环境检查、路线证据等;不写成已通过} | ||
| 65 | +- 源码/评测资产复用线索: | ||
| 66 | +- 本轮交付与非目标: | ||
| 67 | + | ||
| 68 | +最终检查:原话无遗漏;关键参数有来源;范围明确;无未决关键取舍;内部技术选择有授权边界;源码与评测契约的冲突没有被静默忽略。 | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +--- | ||
| 2 | +name: repo-test-develop | ||
| 3 | +description: 基于 CANN Bench 组织 proto、golden、cases.yaml,复用 kernel_eval 执行直调算子的黑盒、白盒及回归测试。设计测试或接入评测工程时使用。 | ||
| 4 | +--- | ||
| 5 | + | ||
| 6 | +# 仓库测试开发 | ||
| 7 | + | ||
| 8 | +本仓使用 CANN Bench 的 CANN 任务格式与 `kernel_eval` 评测器。测试工程的工作是准备目标任务、补齐用例并接入评测入口,不另建一套 gen_data/run/精度比对框架。已有评测任务与代码可复用,全部需求范围内的用例统一验收。 | ||
| 9 | + | ||
| 10 | +| 工作 | 参考 | | ||
| 11 | +|------|------| | ||
| 12 | +| 任务目录、用例格式、统一执行入口及证据 | [测试工程](references/test-framework.md) | | ||
| 13 | +| 按规格设计黑盒覆盖与补充用例 | [黑盒设计](references/blackbox-design.md) | | ||
| 14 | +| 将源码分支用例写入现有任务集 | [白盒设计](references/whitebox-design.md) | | ||
| 15 | +| 精度 checker、阈值与评分含义 | [精度与性能](references/precision-and-perf.md) | | ||
| 16 | + | ||
| 17 | +任务决定执行代表用例还是全量回归;穿刺的局部通过不能代替正式全量交付。原始评测文件和候选工程分开,禁止改 golden、阈值、评测器或删测掩盖算子错误。 | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-test-develop/references/blackbox-design.md+30-0
| @@ -0,0 +1,30 @@ | |||
| 1 | +# 黑盒用例设计 | ||
| 2 | + | ||
| 3 | +以确认规格及任务 `proto.yaml`、`desc.md`、`golden.py`、`cases.yaml` 为输入。核对已有用例与需求范围,补充真正的覆盖缺口;不把已有用例反向当作全部需求,也不盲目展开参数笛卡尔积。 | ||
| 4 | + | ||
| 5 | +## 覆盖与规模 | ||
| 6 | + | ||
| 7 | +| 维度 | 设计要点 | | ||
| 8 | +|------|----------| | ||
| 9 | +| 接口 | 参数次序、attrs 默认值、optional、输出数与 dtype | | ||
| 10 | +| shape | rank、广播、归约轴、相等/不等约束、最小值、对齐与非对齐、典型规模 | | ||
| 11 | +| 数值 | 需求范围内的正负、小值、极值、零与适用的 NaN/Inf 语义 | | ||
| 12 | +| 交互 | 对会影响结果的跨参数依赖做代表组合,避免无依据的全组合 | | ||
| 13 | +| 异常 | 只测试规格定义的拒绝行为,正常边界与非法输入分开 | | ||
| 14 | + | ||
| 15 | +L0 标记快速代表集,L1 标记常规功能组合,L2 标记边界或异常。它们是测试设计标签,可写在 `note` 和覆盖矩阵中,不改 proto 的算子难度 `L1`~`L4`,也不使用评测器的 `--level` 过滤测试标签。 | ||
| 16 | + | ||
| 17 | +每个新增 case 保留唯一整数 ID、输入参数、预期语义和覆盖目的。需求中的不适用值域不强加,例如数学定义不接受的负数不能塞进正常精度用例。空 tensor 与 rank=0 标量是不同语义;是否支持依据需求和 golden,而非自动都加进范围。 | ||
| 18 | + | ||
| 19 | +## 产物 | ||
| 20 | + | ||
| 21 | +在本轮方案中列出规格→case ID 的覆盖矩阵、golden 函数与版本、逐输出 checker/阈值的实际取值和来源、评测命令及补充测试入口。测试工程将其物化为 `cases.yaml` 和必要测试代码,按 [测试工程](test-framework.md) 的格式与入口执行。 | ||
| 22 | + | ||
| 23 | +公开原始用例保持只读;新任务或补充用例写入授权测试目录并记录来源。已有 golden 满足规格时直接复用,不为形式完整重新实现。只有资料冲突或无法确定语义时报告待决项,不修改预期结果配合当前 kernel。 | ||
| 24 | + | ||
| 25 | +## 核对依据 | ||
| 26 | + | ||
| 27 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;实际运行记录所用版本。 | ||
| 28 | + | ||
| 29 | +- [docs/spec/cases_yaml_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/cases_yaml_spec.md) | ||
| 30 | +- [examples/tasks/README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/tasks/README.md) | ||
| @@ -0,0 +1,75 @@ | |||
| 1 | +# CANN Bench 最小接入自检 | ||
| 2 | + | ||
| 3 | +以下接口已按 `08d519c503843bce5fd4672ffa2259abeb22fb00` 核对。使用实际 checkout 时核对版本;不要根据类名猜接口。自检记录按当前节点编号放入工作目录,先跑代表用例,再做正式全量发现与验证。 | ||
| 4 | + | ||
| 5 | +## 目录、签名与调用 | ||
| 6 | + | ||
| 7 | +- 工程源码与评测任务分开。任务采用 `tests/cannbench/tasks/levelN/<op>/`;CLI `--task-dir` 指向 tasks 根目录,`--operator` 选择目标。直接使用官方任务时也以其 tasks 目录为根。 | ||
| 8 | +- `CannTaskLoader`、`CannCaseLoader`、`GoldenLoader` 均从 `kernel_eval.benches.cann_loader` 导入;当前没有 `CannGoldenLoader`。传任务根目录,方法参数使用 `levelN/<op>`。 | ||
| 9 | +- `proto.yaml` 提供 `operator.name`、`schema`、`difficulty`、有序 inputs、attrs 和 outputs;difficulty 使用官方枚举,目录 level 分类与 proto 难度字段分别保留,不凭名称推测。 | ||
| 10 | +- golden 函数名与 schema 一致。Tensor 参数必须有含 `Tensor` 的类型注解,例如 `x1: torch.Tensor`;TensorList、Optional 按实际接口标注,属性给出正确类型及默认值。`ParamBuilder.build_call_params` 用签名区分 Tensor 和 attrs,未标注的参数可能漏绑;函数能直接调用不等于 loader 接入成功。 | ||
| 11 | +- 用真实 `ParamBuilder` 生成参数并用 `inspect.signature(...).bind(**params)` 检查缺项;再实际调用 golden。输入和输出 dtype、shape、数量及结构按接口核对,FP16 输出合同不要求 FP64 中间结果 bit-exact。CPU 测试不能代替设备精度验收;golden 需要设备能力时记录限制并在相应环境验证。 | ||
| 12 | +- 报告冒烟必须包含非空算子条目及真实 `rel_path`,覆盖 JSON、Markdown、HTML 输出;空报告无法暴露 level 路径解析错误。报告中的模拟条目明确标为自检,不计作候选运行或通过证据。 | ||
| 13 | + | ||
| 14 | +## 可运行的 Add 接入样例 | ||
| 15 | + | ||
| 16 | +在已准备依赖的环境中,设置 `PYTHONPATH="$bench_root/src"`。下面的 Python 片段保存为当前工作目录下带节点 ID 的自检脚本;参数依次为 `$bench_root/examples/tasks`、本节点新建的自检输出目录、`<节点ID>-接入自检-r<轮次>` 报告前缀。它只调用官方 Add golden 的一个代表用例,并用一个标为 skipped 的占位条目检查报告输出链路(零设备执行),不安装候选包。 | ||
| 17 | + | ||
| 18 | +```python | ||
| 19 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 20 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 21 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 22 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 23 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 24 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 25 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 26 | +import inspect | ||
| 27 | +import logging | ||
| 28 | +import sys | ||
| 29 | +from pathlib import Path | ||
| 30 | +from kernel_eval.config import Config, set_config | ||
| 31 | + | ||
| 32 | +set_config(Config(device_type="cpu")) | ||
| 33 | +from kernel_eval.benches.cann_loader import CannTaskLoader, CannCaseLoader, GoldenLoader | ||
| 34 | +from kernel_eval.data.data_generator import DataGenerator | ||
| 35 | +from kernel_eval.utils.param_builder import ParamBuilder | ||
| 36 | +from kernel_eval.report.report_generator import EvalReport, EvalResult, OperatorReport, ReportGenerator | ||
| 37 | + | ||
| 38 | +logging.basicConfig(level=logging.INFO, format="%(message)s") | ||
| 39 | +root, output, report_id = sys.argv[1:] | ||
| 40 | +rel_path = "level2/add" | ||
| 41 | +task = CannTaskLoader(root).get_task(rel_path) | ||
| 42 | +cases = CannCaseLoader(root).scan_by_rel_path(rel_path) | ||
| 43 | +assert task is not None and cases, "任务或用例未发现" | ||
| 44 | +golden = GoldenLoader(root).get_golden_function(rel_path) | ||
| 45 | +case = cases[0] | ||
| 46 | +inputs = DataGenerator().generate_input_tensors_from_case( | ||
| 47 | + case.input_shapes, case.dtypes, case.value_ranges, seed=0) | ||
| 48 | +params = ParamBuilder().build_call_params(golden, case, inputs) | ||
| 49 | +inspect.signature(golden).bind(**params) | ||
| 50 | +result = golden(**params) | ||
| 51 | +assert result.device.type == "cpu" | ||
| 52 | +assert result.shape == inputs[0].shape and result.dtype == inputs[0].dtype | ||
| 53 | +logging.info("CPU golden 接入成功:发现 %d 例,执行 1 例;未运行候选 kernel", len(cases)) | ||
| 54 | +report = EvalReport( | ||
| 55 | + framework_version="selfcheck", tasks_version="selfcheck", eval_code=report_id, | ||
| 56 | + timestamp="selfcheck", device="cpu", total_operators=1, total_cases=1, | ||
| 57 | + passed_cases=0, failed_cases=0, overall_score=0, | ||
| 58 | + operators=[OperatorReport(rel_path=rel_path, operator="Add", total_cases=1, | ||
| 59 | + cases=[EvalResult(rel_path=rel_path, operator="Add", case_id="selfcheck", | ||
| 60 | + status="skipped", error_msg="仅报告接口自检,未执行候选")])], | ||
| 61 | + summary={"pass_rate": 0.0, "purpose": "报告接口自检,无候选执行"}) | ||
| 62 | +paths = ReportGenerator(output_dir=output, eval_code=report_id).save_all(report) | ||
| 63 | +assert all(Path(path).stat().st_size for path in paths.values()) | ||
| 64 | +logging.info("JSON/Markdown/HTML 生成成功:%s", paths) | ||
| 65 | +``` | ||
| 66 | + | ||
| 67 | +实际目标任务自检必须替换为目标路径、代表用例及输出合同,不能以 Add 通过证明目标已接入。进一步核对完整用例 ID 和数量;使用同一 checker 做适用的正负对照,确保错误输出会失败,不能只比较 golden 自身得出精度结论。CPU 自检结果与 NPU 评测结果分别记录。 | ||
| 68 | + | ||
| 69 | +## 核对来源 | ||
| 70 | + | ||
| 71 | +- [官方 Add 任务](https://gitcode.com/cann/cann-bench/tree/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/tasks/level2/add) | ||
| 72 | +- [加载器](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/benches/cann_loader.py) | ||
| 73 | +- [参数绑定](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/utils/param_builder.py) | ||
| 74 | +- [目录解析](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/utils/path_resolver.py) | ||
| 75 | +- [报告生成](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/report/report_generator.py) | ||
| @@ -0,0 +1,36 @@ | |||
| 1 | +# 精度与评分口径 | ||
| 2 | + | ||
| 3 | +## 精度执行 | ||
| 4 | + | ||
| 5 | +本仓用 CANN 后端注册的 `relative_error` checker。标准来源是所用版本的 `src/kernel_eval/utils/thresholds.py`、`compare.py`、`checkers/relative_error_checker.py` 及算子 proto 中的 `precision_thresholds` 配置;在测试方案中记录实际生效配置,不另写近似判定器。 | ||
| 6 | + | ||
| 7 | +已核对版本的正常浮点值域采用 MERE 与 MARE 双条件,MARE 门槛是 threshold 的 10 倍,均使用严格小于;常用 dtype 基础 threshold 如下,算子覆写和实际配置必须另行核对: | ||
| 8 | + | ||
| 9 | +| dtype | threshold | | ||
| 10 | +|-------|-----------| | ||
| 11 | +| float16 | `2**-10` | | ||
| 12 | +| bfloat16 | `2**-7` | | ||
| 13 | +| float32 | `2**-13` | | ||
| 14 | +| 整型 | 精确匹配 | | ||
| 15 | + | ||
| 16 | +这张表不构成完整判定。checker 还处理输出结构/连续性、小值域、相消、NaN/Inf 等;不能只实现上述两个指标或 `torch.allclose` 就宣布等价。浮点判定使用评测器提供的高精度 golden 与需要时的同精度 CPU 对照,输入生成和 dtype 处理交给现有实现。 | ||
| 17 | + | ||
| 18 | +逐输出保留实际生效的指标、阈值、实测统计与 pass/fail;保留原始机器可读报告,不把内部 checker 结果改写为更宽松的自建结论。用户标准更严格时另做附加断言;与正式评测契约冲突时在需求阶段明确差异,不放宽 cann-bench 标准以换取通过。 | ||
| 19 | + | ||
| 20 | +## 性能与跑分 | ||
| 21 | + | ||
| 22 | +`--no-perf` 适用于功能验证;不能据此报告 HAP、性能通过或最终综合分达标。任务明确要求跑分时,使用同版本评测器开启性能采集,保留硬件标签、metadata 版本、每例候选耗时、baseline 与硬件锚点及真实报告。 | ||
| 23 | + | ||
| 24 | +`metadata/<hardware>.json` 保存 `baseline_perf_us` 和 `t_hw_us`。`examples/tasks` 的零值 fixture 不能用于真实性能比较,补充黑盒/白盒缺少锚点时不能伪造得分;官方原始任务的跑分与扩展用例回归分别记录,不能用扩展集合冒充官方分数。 | ||
| 25 | + | ||
| 26 | +HAP 是硬件锚定评分而非 speedup,不能擅自给所有算子添加 HAP ≥ 0.5、带宽差 20% 等门槛。是否有性能硬目标由需求决定,流程未安排性能测量时仅声明功能验证与可评测工程交付,不宣称性能达标。 | ||
| 27 | + | ||
| 28 | +## 核对依据 | ||
| 29 | + | ||
| 30 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;实际运行记录所用版本。 | ||
| 31 | + | ||
| 32 | +- [src/kernel_eval/utils/thresholds.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/utils/thresholds.py) | ||
| 33 | +- [src/kernel_eval/utils/compare.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/utils/compare.py) | ||
| 34 | +- [src/kernel_eval/checkers/relative_error_checker.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/checkers/relative_error_checker.py) | ||
| 35 | +- [docs/design/precision_comparison_design.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/design/precision_comparison_design.md) | ||
| 36 | +- [README.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/README.md) | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-test-develop/references/test-framework.md+75-0
| @@ -0,0 +1,75 @@ | |||
| 1 | +# CANN Bench 测试工程 | ||
| 2 | + | ||
| 3 | +## 目录与复用 | ||
| 4 | + | ||
| 5 | +`bench_root` 为已记录版本的 cann-bench checkout;`source_dir` 为候选源码;`task_dir` 为本轮采用的任务根目录(`tests/cannbench/tasks/`),`rel_path` 为 `levelN/<op>`;`bench_root` 不与任务根目录混用。检查已有任务的算子名、schema、规格和用例,复用匹配资产;补充内容写入目标仓授权的 `tests/cannbench/tasks/levelN/<op>/`,使用同一文件格式与同一评测器,不更改上游任务。 | ||
| 6 | + | ||
| 7 | +```text | ||
| 8 | +tests/cannbench/tasks/levelN/<op>/ | ||
| 9 | +├── proto.yaml # operator、schema、输入输出和属性 | ||
| 10 | +├── desc.md # 数学及接口语义 | ||
| 11 | +├── golden.py # 与 schema 匹配的独立参考函数 | ||
| 12 | +└── cases.yaml # cases 列表:保留原用例并加入黑盒/白盒补充 | ||
| 13 | +``` | ||
| 14 | + | ||
| 15 | +已有任务也保留 `tasks/levelN/<op>` 层次,CLI 的 `--task-dir` 传 tasks 根目录,并用 `--operator` 选择目标;loader 传同一根目录及相对路径。当前 HTML 报告器解析 `levelN/<op>`,不要把裸 `<op>` 目录当评测根目录。N 沿用已有分类或记录新的分类,不由算子名猜测。原始任务根目录可作为只读 `task_dir`;需要补充时创建上述可交付任务目录,保留原有用例 ID 和内容,记录来源 commit、新增 ID 与覆盖映射。没有目标任务时按确认规格创建完整目录。两者使用相同测试契约,不增加工作流分支。`metadata/` 只在确需真实性能锚点时按当前版本格式使用,不制造 baseline。 | ||
| 16 | + | ||
| 17 | +## 先验证接入 | ||
| 18 | + | ||
| 19 | +先按 [最小接入自检](cannbench-integration.md) 验证 loader、golden 签名与参数绑定、代表输入和报告生成,再展开全量用例。接入自检通过只证明测试工程能工作,不是 NPU 精度通过。 | ||
| 20 | + | ||
| 21 | +## cases.yaml | ||
| 22 | + | ||
| 23 | +例为双输入 Add 的数据格式,不代表目标算子的完整测试集: | ||
| 24 | + | ||
| 25 | +```yaml | ||
| 26 | +cases: | ||
| 27 | +- operator: Add | ||
| 28 | + case_id: 1 | ||
| 29 | + input_shape: [[17, 33], [17, 33]] | ||
| 30 | + dtype: [float32, float32] | ||
| 31 | + attrs: {} | ||
| 32 | + value_range: [[-1, 1], [-1, 1]] | ||
| 33 | + note: 黑盒边界;非对齐 | ||
| 34 | +``` | ||
| 35 | + | ||
| 36 | +- `operator` 与 proto 一致,`case_id` 为目录内唯一整数;`input_shape`、`dtype`、`value_range` 按 proto 输入顺序对应。 | ||
| 37 | +- optional 缺省使用 `null` 占位;TensorList 用嵌套列表,不能靠省略位置改变参数绑定。 | ||
| 38 | +- 当前 loader 读取 `cases.yaml`,不是 `cases.csv`;如保留 CSV 展示文件要同步它,不能只改 CSV。 | ||
| 39 | +- 不添加评测器不认识的 `expected_exception` 等字段并假设会执行。异常输入若无法用当前 loader/checker 表达,使用明确的补充 pytest 检查接口异常,单独报告结果,不混入正常精度用例的通过数。 | ||
| 40 | +- 使用评测器的数据生成、golden 加载及 checker。特殊确定性输入若不能由现有字段表达,依据当前接口实现必要的补充测试,并复用相同 checker;不得默默退回 `allclose`。 | ||
| 41 | + | ||
| 42 | +## 执行入口 | ||
| 43 | + | ||
| 44 | +先确认 Python 环境及 `cann_bench_utils` 已准备好。官方 `scripts/run_evaluation.sh` 会准备辅助组件并安装候选包;本仓记录报告编号时直接使用同仓 CLI。以下路径均为绝对路径,`build_dir` 是位于 `$WORK_DIR` 的当前源码构建快照;`node_id`、`attempt` 和 `device_id` 来自本次任务,设备必须属于授权资源。 | ||
| 45 | + | ||
| 46 | +```bash | ||
| 47 | +PYTHONPATH="$bench_root/src${PYTHONPATH:+:$PYTHONPATH}" python3 -m kernel_eval.cli eval \ | ||
| 48 | + --bench-name cann --source-dir "$build_dir" --task-dir "$task_dir" \ | ||
| 49 | + --operator "$op" --device npu --device-id "$device_id" \ | ||
| 50 | + --reports-dir "$WORK_DIR/$node_id-评测-r$attempt" \ | ||
| 51 | + --eval-code "$node_id-精度-r$attempt" --eval-seed 0 --no-perf | ||
| 52 | +``` | ||
| 53 | + | ||
| 54 | +命令完整保留原始日志和退出码;每次使用新报告目录。精度执行不需要性能采集,`--no-perf` 不等于关闭真实性检查。显式传设备避免默认占用全部卡;相同 Python 环境的候选安装不得并发互相覆盖。 | ||
| 55 | + | ||
| 56 | +开发期可加 `--case-id <整数>` 定位或穿刺,正式全量验收去掉该筛选。先核对实际发现数,再与报告执行数逐项对齐;零用例、漏算子、跳过或部分通过都不能称为全量通过。补充 pytest 也必须记录其数量、结果和日志。 | ||
| 57 | + | ||
| 58 | +## 不同任务的交付边界 | ||
| 59 | + | ||
| 60 | +- 测试工程准备:核对 proto/cases 可发现、golden 可调用、数据生成与断言可用,提供入口和用例映射;尚无 kernel 时不能伪报设备精度通过。 | ||
| 61 | +- 算子开发:执行完整黑盒,记录当前源码构建与设备结果。 | ||
| 62 | +- 白盒接入:在已有 cases 中加入源码分支用例,运行黑盒和白盒;归属明确的算子失败交修复,测试自身错误须修好。 | ||
| 63 | +- 修复交付:黑盒、白盒及必要补充测试全量通过;已有有效证据的复用遵从当前 task,不使用旧代码日志证明新代码。 | ||
| 64 | + | ||
| 65 | +官方 JSON/Markdown/HTML 报告保存原样,阶段记录给出带节点 ID 的结果路径、任务/源码/wheel/加载库版本和哈希、用例计数及失败归属。验收者只读证据,不重新构建或执行。示例 `test.sh` 仅运行示例 pytest,不代表目标算子已通过 cann-bench。 | ||
| 66 | + | ||
| 67 | +## 核对依据 | ||
| 68 | + | ||
| 69 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;实际运行记录所用版本。 | ||
| 70 | + | ||
| 71 | +- [examples/tasks/level2/add/proto.yaml](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/tasks/level2/add/proto.yaml) | ||
| 72 | +- [examples/tasks/level2/add/cases.yaml](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/examples/tasks/level2/add/cases.yaml) | ||
| 73 | +- [docs/spec/cases_yaml_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/cases_yaml_spec.md) | ||
| 74 | +- [src/kernel_eval/cli.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/cli.py) | ||
| 75 | +- [src/kernel_eval/report/report_generator.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/report/report_generator.py) | ||
Aplugins-community/ops-direct-invoke-harness/skills/repo-test-develop/references/whitebox-design.md+19-0
| @@ -0,0 +1,19 @@ | |||
| 1 | +# 白盒用例接入 | ||
| 2 | + | ||
| 3 | +从当前 kernel、Tiling 和 dispatch 源码出发,记录有效分支的文件、函数、条件与版本;覆盖尾核/尾块、对齐、dtype、多核划分及适用的 tilingkey。知识搜集草稿不约束实际分支。 | ||
| 4 | + | ||
| 5 | +1. 对每个分支反推需求范围内的输入,采用阈值两侧、整除/非整除等代表参数;已有黑盒命中时复用 ID,不为凑数量重复造例。 | ||
| 6 | +2. 把新增正常用例写入同一授权任务目录的 `cases.yaml`,使用未占用的整数 ID,在 `note` 和阶段覆盖记录中注明源码条件。沿用原 proto、golden 与 checker,不另建数据生成/比对框架。 | ||
| 7 | +3. 需求定义的异常或无法由 YAML 表达的输入按 [测试工程](test-framework.md) 接入补充测试;必须进入统一回归清单,不只提交设计文档。 | ||
| 8 | +4. 运行当前任务要求的黑盒与白盒,记录实际执行数、结果和证据。区分源码推导可覆盖、执行中实际命中和因缺陷受阻,不能把推导当实测覆盖。 | ||
| 9 | + | ||
| 10 | +测试或接入错误由测试工作修复;正确用例暴露 kernel 缺陷时记录失败 ID、复现命令和证据,保留用例及失败结果,供代码修复使用。源码修改后复核受影响分支与用例映射,最终交付必须通过全量回归。 | ||
| 11 | + | ||
| 12 | +测试文件是目标仓交付件;分支映射和运行报告按本节点 ID 写入 `$WORK_DIR`。不修改被测算子、原始评测任务、golden 或阈值掩盖失败。 | ||
| 13 | + | ||
| 14 | +## 核对依据 | ||
| 15 | + | ||
| 16 | +已核对 cann-bench `08d519c503843bce5fd4672ffa2259abeb22fb00`;实际运行记录所用版本。 | ||
| 17 | + | ||
| 18 | +- [docs/spec/cases_yaml_spec.md](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/docs/spec/cases_yaml_spec.md) | ||
| 19 | +- [src/kernel_eval/benches/cann_loader.py](https://gitcode.com/cann/cann-bench/blob/08d519c503843bce5fd4672ffa2259abeb22fb00/src/kernel_eval/benches/cann_loader.py) | ||
| @@ -0,0 +1,72 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +"""Guard the registry inventory, node IDs, dependencies and task references.""" | ||
| 13 | +import sys | ||
| 14 | +import unittest | ||
| 15 | +from pathlib import Path | ||
| 16 | + | ||
| 17 | +sys.dont_write_bytecode = True | ||
| 18 | +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | ||
| 19 | +from support import WORKFLOWS, assert_graph, load_yaml, registered_workflows, run_tests | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +class RegistryTests(unittest.TestCase): | ||
| 23 | + def test_registry_covers_all_workflow_templates(self): | ||
| 24 | + entries = registered_workflows() | ||
| 25 | + for field in ['file']: | ||
| 26 | + values = [entry[field] for entry in entries] | ||
| 27 | + self.assertTrue(all(isinstance(value, str) and value.strip() for value in values)) | ||
| 28 | + self.assertEqual(len(values), len(set(values)), f'duplicate workflow {field}') | ||
| 29 | + files = {str(path.relative_to(WORKFLOWS)) for path in WORKFLOWS.rglob('*') | ||
| 30 | + if path.suffix in {'.yaml', '.yml'}} | ||
| 31 | + self.assertEqual({entry['file'] for entry in entries}, files, 'missing or obsolete registry entry') | ||
| 32 | + | ||
| 33 | + def test_basic_keeps_research_implementation_whitebox_and_repair_order(self): | ||
| 34 | + entries = registered_workflows() | ||
| 35 | + self.assertEqual({entry['file'] for entry in entries}, {'basic.yaml', 'feasibility.yaml'}) | ||
| 36 | + graph = load_yaml(WORKFLOWS / 'basic.yaml')['nodes'] | ||
| 37 | + actual = [(node['id'], load_yaml(WORKFLOWS / node['yaml'])['title'], node['depends_on']) | ||
| 38 | + for node in graph] | ||
| 39 | + self.assertEqual(actual, [ | ||
| 40 | + ('0.0', '知识搜集', []), ('0.1', '黑盒测试设计', []), | ||
| 41 | + ('1', '测试工程开发', ['0.0', '0.1']), ('2', '算子开发', ['1']), | ||
| 42 | + ('3', '白盒测试设计', ['2']), ('4', '代码修复', ['3']), ('5', '文档准备', ['4'])]) | ||
| 43 | + self.assertTrue(all(node['max_retries'] == 3 for node in graph)) | ||
| 44 | + for node in graph[:2]: | ||
| 45 | + self.assertEqual(load_yaml(WORKFLOWS / node['yaml'])['executor'], 'ops-direct-invoke-architect') | ||
| 46 | + | ||
| 47 | + def test_every_registered_graph_and_task_reference(self): | ||
| 48 | + for entry in registered_workflows(): | ||
| 49 | + with self.subTest(workflow=entry['file']): | ||
| 50 | + self.assertEqual(set(entry), {'file', 'use_when'}) | ||
| 51 | + self.assertTrue(entry['use_when'].strip()) | ||
| 52 | + path = (WORKFLOWS / entry['file']).resolve() | ||
| 53 | + self.assertTrue(path.is_relative_to(WORKFLOWS.resolve()), 'workflow escapes template directory') | ||
| 54 | + self.assertTrue(path.is_file(), path) | ||
| 55 | + self.assertNotIn('nodes', entry, 'graph belongs only in the referenced template') | ||
| 56 | + template = load_yaml(path) | ||
| 57 | + self.assertEqual(set(template), {'workflow', 'max_parallel', 'nodes'}) | ||
| 58 | + assert_graph(self, template['nodes']) | ||
| 59 | + for node in template['nodes']: | ||
| 60 | + self.assertEqual(set(node), {'id', 'yaml', 'depends_on', 'max_retries', 'variables'}) | ||
| 61 | + self.assertIsInstance(node['yaml'], str) | ||
| 62 | + task = load_yaml((WORKFLOWS / node['yaml']).resolve()) | ||
| 63 | + self.assertIsInstance(task, dict) | ||
| 64 | + self.assertNotIn('max_retries', task) | ||
| 65 | + self.assertIs(type(node['max_retries']), int) | ||
| 66 | + self.assertEqual(node['max_retries'], 3, 'registered templates default to three retries') | ||
| 67 | + self.assertNotIn('id', task, 'identity belongs in the registry, not the task') | ||
| 68 | + self.assertNotIn('depends_on', task, 'dependencies belong in the registry, not the task') | ||
| 69 | + | ||
| 70 | + | ||
| 71 | +if __name__ == '__main__': | ||
| 72 | + run_tests() | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +"""Deterministic Codex CLI stand-in; no model, network or harness internals.""" | ||
| 13 | +import json | ||
| 14 | +import logging | ||
| 15 | +import os | ||
| 16 | +import sys | ||
| 17 | +from pathlib import Path | ||
| 18 | + | ||
| 19 | +logging.basicConfig(level=logging.INFO, format='%(message)s', stream=sys.stdout) | ||
| 20 | +work = Path(os.environ['WORKFLOW_PROBE_DIR']) | ||
| 21 | +prompt = sys.argv[-1] | ||
| 22 | +verification = 'Procedure:' in prompt | ||
| 23 | +capture = work / 'provider-calls.jsonl' | ||
| 24 | +calls = [json.loads(line) for line in capture.read_text().splitlines()] if capture.exists() else [] | ||
| 25 | +report = work / '0-验收报告.md' | ||
| 26 | +seen_report = report.read_text() if report.exists() else '' | ||
| 27 | +with capture.open('a') as stream: | ||
| 28 | + stream.write(json.dumps({'prompt': prompt, 'verification': verification, | ||
| 29 | + 'report': seen_report}, ensure_ascii=False) + '\n') | ||
| 30 | +if verification: | ||
| 31 | + prior_verifications = [call for call in calls if call['verification']] | ||
| 32 | + if not prior_verifications: | ||
| 33 | + report.write_text('RETRY_FEEDBACK_SENTINEL: missing boundary case') | ||
| 34 | + logging.info(json.dumps({'type': 'item.completed', 'item': { | ||
| 35 | + 'type': 'agent_message', 'text': report.read_text()}})) | ||
| 36 | + reply = 'fail' | ||
| 37 | + else: | ||
| 38 | + reply = 'pass' if any('RETRY_FEEDBACK_SENTINEL' in call['report'] | ||
| 39 | + for call in calls if not call['verification']) else 'fail' | ||
| 40 | + report.write_text('pass: prior feedback addressed' if reply == 'pass' else 'fail') | ||
| 41 | +else: | ||
| 42 | + reply = 'executed' | ||
| 43 | +logging.info(json.dumps({'type': 'item.completed', 'item': {'type': 'agent_message', 'text': reply}})) | ||
| @@ -0,0 +1,63 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# ---------------------------------------------------------------------------- | ||
| 3 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 5 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 8 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +"""Probe retry feedback through the real public CLI with a deterministic provider.""" | ||
| 13 | +import json | ||
| 14 | +import os | ||
| 15 | +import shutil | ||
| 16 | +import subprocess | ||
| 17 | +import sys | ||
| 18 | +import tempfile | ||
| 19 | +import unittest | ||
| 20 | +from pathlib import Path | ||
| 21 | + | ||
| 22 | +sys.dont_write_bytecode = True | ||
| 23 | +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | ||
| 24 | +import support | ||
| 25 | +from support import SCRIPTS, SKILL_ROOT, run_tests | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +class RetryFeedbackTests(unittest.TestCase): | ||
| 29 | + def test_retry_preserves_report_but_does_not_inject_verifier_feedback(self): | ||
| 30 | + with tempfile.TemporaryDirectory(prefix='workflow-feedback-') as temp: | ||
| 31 | + work = Path(temp) | ||
| 32 | + binaries = work / 'bin' | ||
| 33 | + binaries.mkdir() | ||
| 34 | + cli = binaries / 'codex' | ||
| 35 | + shutil.copyfile(Path(__file__).parent / 'fixtures/codex.py', cli) | ||
| 36 | + cli.chmod(0o755) | ||
| 37 | + definition = work / 'workflow.yaml' | ||
| 38 | + assembled = subprocess.run([ | ||
| 39 | + sys.executable, str(SCRIPTS / 'assemble_workflow.py'), | ||
| 40 | + str(SKILL_ROOT / 'tasks/知识搜集.yaml'), '--max-retries', '1', | ||
| 41 | + '--output', str(definition)], capture_output=True, text=True, timeout=30) | ||
| 42 | + self.assertEqual(assembled.returncode, 0, assembled.stderr) | ||
| 43 | + env = {**os.environ, 'PATH': str(binaries) + os.pathsep + os.environ['PATH'], | ||
| 44 | + 'WORKFLOW_PROBE_DIR': str(work)} | ||
| 45 | + result = subprocess.run([ | ||
| 46 | + sys.executable, str(support.HARNESS_SKILL / 'scripts/orchestrator.py'), | ||
| 47 | + '--yaml', str(definition), '--work-dir', str(work), '--provider', 'codex', | ||
| 48 | + '--prompt', 'CLI contract probe only; no real operator development'], | ||
| 49 | + env=env, capture_output=True, text=True, timeout=30) | ||
| 50 | + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) | ||
| 51 | + calls = [json.loads(line) for line in (work / 'provider-calls.jsonl').read_text().splitlines()] | ||
| 52 | + self.assertEqual([call['verification'] for call in calls], [False, True, False, True]) | ||
| 53 | + initial, retry = calls[0], calls[2] | ||
| 54 | + self.assertEqual(initial['prompt'], retry['prompt']) | ||
| 55 | + self.assertNotIn('RETRY_FEEDBACK_SENTINEL', retry['prompt']) | ||
| 56 | + self.assertIn('0-验收报告.md', retry['prompt']) | ||
| 57 | + self.assertIn('RETRY_FEEDBACK_SENTINEL', retry['report']) | ||
| 58 | + status = json.loads((work / '.workflow/status.json').read_text())['tasks']['0'] | ||
| 59 | + self.assertEqual((status['status'], status['retries']), ('pass', 1)) | ||
| 60 | + | ||
| 61 | + | ||
| 62 | +if __name__ == '__main__': | ||
| 63 | + run_tests() | ||