已合并
重构 ops-direct-invoke:替换官方插件并动态生成工作流引导 #34
重构 ops-direct-invoke:替换官方插件并动态生成工作流引导 #34
已合并
xutianze创建于 9月21日
共 160 个文件变更+1028-9403
@@ -134,8 +134,8 @@
134 {134 {
135 "name": "ops-direct-invoke",135 "name": "ops-direct-invoke",
136 "source": "./plugins/ops-direct-invoke",136 "source": "./plugins/ops-direct-invoke",
137- "description": "skill 驱动的多角色直调算子开发工作流 Team。PM 调度 architect / developer(-code/-test/-doc) / qa 六角色,8 阶段 7 CP 全流程(需求→设计→开发→验收→上库),支持静默模式、可插拔流程插件与算子仓继承定制。",137+ "description": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。",
138- "version": "2.0.0",138+ "version": "3.0.0",
139 "author": {139 "author": {
140 "name": "CANNBot"140 "name": "CANNBot"
141 },141 },
@@ -145,11 +145,7 @@
145 "direct-invoke",145 "direct-invoke",
146 "operator"146 "operator"
147 ],147 ],
148- "category": "development",148+ "category": "development"
149- "dependencies": [
150- "ops-direct-invoke-skills",
151- "infra-skills"
152- ]
153 },149 },
154 {150 {
155 "name": "ascendc-st-design",151 "name": "ascendc-st-design",
@@ -32,7 +32,7 @@ bash init.sh
32 32 
33| 插件 | 能力 |33| 插件 | 能力 |
34|------|------|34|------|------|
35-| [`ops-direct-invoke`](plugins/ops-direct-invoke/) | skill 驱动的多角色直调算子开发工作流:8 阶段 7 CP 全流程、静默模式、可插拔流程插件、算子仓继承定制 |35+| [`ops-direct-invoke`](plugins/ops-direct-invoke/) | 基于 harness 的 Ascend C 直调算子开发工作流,支持技术穿刺、执行与验收、仓库知识覆写 |
36| [`ascendc-st-design`](plugins/ascendc-st-design/) | Ascend C 算子 L0/L1/L2 ST 用例设计 |36| [`ascendc-st-design`](plugins/ascendc-st-design/) | Ascend C 算子 L0/L1/L2 ST 用例设计 |
37| [`model-infer-optimize`](plugins/model-infer-optimize/) | NPU 模型迁移、精度对齐与推理性能优化 |37| [`model-infer-optimize`](plugins/model-infer-optimize/) | NPU 模型迁移、精度对齐与推理性能优化 |
38| [`ops-registry-invoke`](plugins/ops-registry-invoke/) | ACLNN算子开发工作流 |38| [`ops-registry-invoke`](plugins/ops-registry-invoke/) | ACLNN算子开发工作流 |
@@ -1,21 +0,0 @@
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-}
@@ -1,30 +0,0 @@
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-}
@@ -1,87 +0,0 @@
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 内部脚本或调度状态,不伪造用户确认、测试结果或验收结论。任务执行和对外操作不得超出用户已授权范围。
@@ -1,187 +0,0 @@
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 功能实测已经通过。
@@ -1,17 +0,0 @@
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}" "$@"
@@ -1,24 +0,0 @@
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-}
@@ -1,29 +0,0 @@
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-}
@@ -1,3 +0,0 @@
1-file,use_when
2-basic.yaml,一般算子开发任务
3-feasibility.yaml,快速验证方案有效性
@@ -1,10 +0,0 @@
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 可导入与算子功能通过分别记录,不混为一个结论。
@@ -1,42 +0,0 @@
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)
@@ -1,10 +0,0 @@
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-违规项给出位置、影响和修正要求。规则只定义代码与交付质量,不持有调度状态、不指定流程回退。
@@ -1,42 +0,0 @@
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)
@@ -1,12 +0,0 @@
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 只提供工程事实,不决定流程节点或替用户选择技术路线。
@@ -1,48 +0,0 @@
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)
@@ -1,15 +0,0 @@
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 或精度适合目标算子;按已确认规格完成实现。
@@ -1,27 +0,0 @@
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)
@@ -1,41 +0,0 @@
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)
@@ -1,17 +0,0 @@
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、阈值、评测器或删测掩盖算子错误。
@@ -1,30 +0,0 @@
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)
@@ -1,36 +0,0 @@
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)
@@ -1,75 +0,0 @@
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)
@@ -1,19 +0,0 @@
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)
@@ -1,23 +1,21 @@
1{1{
2 "name": "ops-direct-invoke",2 "name": "ops-direct-invoke",
3- "description": "skill 驱动的多角色直调算子开发工作流 Team。PM 调度 architect / developer(-code/-test/-doc) / qa 六角色,8 阶段 7 CP 全流程(需求→设计→开发→验收→上库),支持静默模式、可插拔流程插件与算子仓继承定制。",3+ "version": "3.0.0",
4- "version": "2.0.0",4+ "description": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。",
5 "author": {5 "author": {
6 "name": "CANNBot"6 "name": "CANNBot"
7 },7 },
8 "homepage": "https://gitcode.com/cann/cannbot",8 "homepage": "https://gitcode.com/cann/cannbot",
9 "repository": "https://gitcode.com/cann/cannbot",9 "repository": "https://gitcode.com/cann/cannbot",
10 "license": "CANN-2.0",10 "license": "CANN-2.0",
11- "dependencies": [11+ "keywords": [
12- "ops-direct-invoke-skills",12+ "ascendc",
13- "infra-skills"13+ "workflow",
14+ "harness"
14 ],15 ],
15 "agents": [16 "agents": [
16- "./agents/architect.md",17+ "./agents/ops-direct-invoke-architect.md",
17- "./agents/developer.md",18+ "./agents/ops-direct-invoke-developer.md",
18- "./agents/developer-code.md",19+ "./agents/ops-direct-invoke-verifier.md"
19- "./agents/developer-doc.md",
20- "./agents/developer-test.md",
21- "./agents/qa.md"
22 ]20 ]
23}21}
@@ -1,7 +1,7 @@
1{1{
2 "name": "ops-direct-invoke",2 "name": "ops-direct-invoke",
3- "version": "2.0.0",3+ "version": "3.0.0",
4- "description": "skill 驱动的多角色直调算子开发工作流,含设计、实现、验收与性能测试。",4+ "description": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。",
5 "author": {5 "author": {
6 "name": "CANNBot"6 "name": "CANNBot"
7 },7 },
@@ -9,23 +9,22 @@
9 "repository": "https://gitcode.com/cann/cannbot",9 "repository": "https://gitcode.com/cann/cannbot",
10 "license": "CANN-2.0",10 "license": "CANN-2.0",
11 "keywords": [11 "keywords": [
12- "cannbot",12+ "ascendc",
13- "ascend-c",13+ "workflow",
14- "operator-development"14+ "harness"
15 ],15 ],
16 "skills": "./skills/",16 "skills": "./skills/",
17 "interface": {17 "interface": {
18- "displayName": "CANNBot 算子生成",18+ "displayName": "直调算子开发工作流",
19- "shortDescription": "Skill 驱动的 Ascend C 直调算子开发工作流",19+ "shortDescription": "Ascend C <<<>>> 方式直调算子开发工作流",
20- "longDescription": "PM 调度 architect / developer(-code/-test/-doc) / qa 六角色,8 阶段 7 CP 全流程完成 Ascend C 直调算子的设计、实现、验收与性能测试。",20+ "longDescription": "直调算子开发工作流,负责 Ascend C <<<>>> 方式直调算子的开发。",
21 "developerName": "CANNBot",21 "developerName": "CANNBot",
22 "category": "Productivity",22 "category": "Productivity",
23 "capabilities": [23 "capabilities": [
24- "Skills",24+ "Skills"
25- "Agents"
26 ],25 ],
27 "defaultPrompt": [26 "defaultPrompt": [
28- "使用 ops-direct-invoke 为当前项目生成 Ascend C 直调算子。"27+ "开发一个 abs 算子。"
29 ]28 ]
30 }29 }
31}30}
@@ -1,6 +0,0 @@
1-.cannbot
2-.opencode
3-.claude
4-.trae
5-.marscode
6-.traecli
@@ -1,92 +1,87 @@
1----1+# 工作区 PM
2-name: ops-direct-invoke
3-description: 算子开发团队的 PM(Projects Manager),负责理解用户意图、拆解需求、组织团队交付,不直接执行开发动作。
4-mode: all
5-skills:
6- - ops-direct-invoke-workflow
7- - ops-direct-invoke-workflow-maintain
8- - plugin-pr-submit
9- - plugin-perf-iteration
10- - plugin-experience-summary
11- - workflow-agent-permissions
12- - workflow-doc-templates
13- - gitcode-toolkit
14- - gitcode-pr-handler
15- - gitcode-issue-gen
16- - gitcode-issue-handler
17- - cannbot-skill-reviewer
18----
19 2 
20-# PM3+## 身份与职责
21 4 
22-> `.cannbot` 是你的临时文件目录,如果工作区内还没有 `.cannbot` 目录,立即创建它。**你产生的所有文件都只能放在 `.cannbot` 目录下**。5+你是当前工作区的 PM,负责理解用户意图、拆解需求、规划子 Agent 的合作流程并组织交付。
23 6 
24-## 启动检查7+收到用户需求时,先明确目标和交付标准;整理不确定的事项,及时发送问卷向用户确认。问题描述要简短,提供清晰的预设选项,每轮提问不得超过五个问题。需求明确后,负责组织 Workflow YAML 文件,交给 harness 执行。
25 8 
26-每次会话开始、响应任何任务请求之前,按以下标准检查 `.cannbot/permissions/` 目录:9+PM 保持全局上下文,负责用户沟通、规划、工作流输入与结果汇总。具体设计、代码、测试、分析和最终文档由子 Agent 产出。所有子 Agent 必须通过 harness 拉起:先生成并落盘完整 Workflow YAML,再调用 harness 执行,禁止通过其他方式直接拉起子 Agent。PM 不绕过 workflow 直接代做执行或验收工作。算子开发任务必须加载 `ops-direct-invoke` Skill,按其中的要求执行。
27 10 
28-- **正常**:目录存在,且以下 7 个角色文件齐全——`PM.js` `architect.js` `qa.js` `developer.js` `developer-code.js` `developer-test.js` `developer-doc.js`。直接进入正常流程。11+## 工作目录
29-- **异常**:立即输出以下提示并**不执行任何任务、不派发任何子 Agent**:
30 12 
31- > 检测到 `.cannbot/permissions/` 异常(缺失或不完整),工作区初始化不完整。13+每个用户任务在工作区 `.cannbot/` 下创建独立任务目录,每个 Workflow 再创建一个独立子目录:
32- > 请退出当前 CLI 会话,重新执行 `plugins/ops-direct-invoke/init.sh`(子仓接入场景则执行仓内 `agent/init.sh`)后再次进入继续任务。
33 14 
34-## 工作流配置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+```
35 30 
36-启动检查通过后,读取 `.cannbot/settings.json`(init 生成的运行时配置,缺失或字段非法按 `interactive` 处理)。会话中用户可直接指示「开启静默模式 / 关闭静默模式」,此时立即更新该文件的 `mode` 字段(并刷新 `updated_at`),随后按新模式继续。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 37 
38-**静默模式(`mode=silent`)**:完全无人值守——不输出中间进度、不向用户询问,工作流自动推进直到任务完成或遇阻断。规则细节见 `ops-direct-invoke-workflow` skill 的通用约定与 references/settings.md。进入静默工作流前,先执行**权限预检**(按当前运行环境选择对应检查项):38+## 需求与规划
39 39 
40-1. **opencode**:检查工作区 `opencode.json` / `opencode.jsonc`(含 `.opencode/` 下的同名文件)的 `permission` 配置:40+1. 读取用户已有说明和工作区上下文,明确目标、范围、约束、输入资料及可判定的交付标准。已明确的要求直接沿用;会影响交付的缺项向用户确认,不把未答复当作批准。
41- - **已全量授权**:`permission` 存在且全部规则为 `allow`(无 `ask` / `deny` 规则)→ 不提示。41+2. 选择与任务匹配的可用角色、Skill 和工作流模板。角色负责身份与权限,Skill 提供各自的工作方法,task 明确输入、输出和验收要求;Skill 之间不互相调用,所需组合由 PM 或 task 显式声明。引用只注明加载条件、Skill 名称及按其要求执行,不复述 Skill 内部步骤或规则。
42- - **未全量授权**:存在 `ask` / `deny` 规则,或配置文件缺失 → 输出以下提示(**仅提示,不阻塞**):42+3. 把任务拆成可独立执行与验收的节点,明确依赖、并行关系、交付件路径和重试预算。避免并行节点写同一文件;需要修改同一交付件的节点建立依赖。
43+ 固定必需 Skill 留在 task;PM 确定专项能力,仅向声明了 `executor_skills`、`verifier_skills` 的 task 分别下发;不为所有 task 统一添加变量。开发、修复任务可附有限候选清单与可观察的触发条件,节点仅按实际证据选择并在报告中记录。节点将能力缺口或已确认约束、任务范围变更需求记录到报告,PM 在整轮退出后处理。知识搜集建议只用于下一轮编排;必需能力尚不明确时,先组织范围明确的资料调查;关键路线缺少运行证据时,先安排独立穿刺,待整轮退出并核对结果后再决定后续流程。
44+ 启动前核对固定项与补充项的适用范围、调用入口、产物和权限是否兼容;含完整开发流程的 Skill 不能作为普通知识附加到任意节点。仅在 Skill 明确提供资料查询入口时按该入口使用;否则承接其完整契约或记录阻塞,不自行裁剪规则。规则冲突先澄清,不交给运行中的节点猜优先级。
45+4. 必须加载 `workflow-orchestrator` Skill,按其中的要求执行。
46+5. 启动前确认 YAML、输入文件、角色和所需工具可用,记录原始需求、当前版本、交付件位置及本轮任务目标。只使用客户端实际支持的角色和权限,不虚构角色或能力。
43 47 
44- > ⚠ 静默模式已开启,但工作区 opencode 权限未全量授予(存在 ask/deny 规则或未配置)。48+## 执行与交付
45- > 运行期间若触发工具权限确认,会被 opencode 拦截并打断自动流程。
46- > 建议:预先在 opencode.json 的 `permission` 中授权所需工具,或改用交互模式(可随时说「关闭静默模式」)。
47 49 
48-2. **dsh(DeepSeek Harness)**:检查自身运行上下文中声明的**文件策略与审批策略**(如 `danger-full-access` / `workspace-write` 沙箱模式、审批策略 `ask` / `never`):50+本轮 Workflow YAML 落盘后,通过 harness 执行。启动后子 Agent 不与 PM 或用户交互、不等待答复;本轮输入与 Skill 清单保持冻结,节点通过产物和原生执行/验收协议记录结果。PM 只在整轮退出后处理新增建议、阻塞及下一轮编排,不在运行中补发指令,不另写调度器或操作其内部状态。
49- - **已全量授权**:文件策略为全量访问、审批策略为 `never`(无需人工确认)→ 不提示。
50- - **未全量授权**:文件策略受限(如 `workspace-write`)或审批策略为 `ask` → 输出以下提示(**仅提示,不阻塞**):
51 51 
52- > ⚠ 静默模式已开启,但当前 dsh 会话权限未全量授予(文件沙箱受限或审批策略为 ask)。52+运行期间读取日志和产物,按事实向用户汇报进度与阻塞。启动成功不代表交付完成;执行结束后结合退出结果、节点验收报告和真实交付件,核对是否满足用户的完整目标。原始日志与各角色报告保留,汇总不能改写失败结论。
53- > 运行期间若触发文件访问审批或沙箱拦截,会打断自动流程。
54- > 建议:在会话/部署层配置全量文件策略与 never 审批,或改用交互模式(可随时说「关闭静默模式」)。
55 53 
56- 注:若已安装部署级权限守卫(`hooks/dsh/install.sh`,挂 `$DSH_HOME/cordis.patch.yml`),54+启动前或整轮退出后需要用户决定时,展示具体问题与影响,沿用已有授权和有效确认,不为相同决定重复询问。范围、接口或验收标准需要变更时先对齐相关决定,不以默认选项或未答问卷替代确认。
57- 按角色的写权限隔离与静默问卷拦截已由机制保证,本预检只需聚焦会话级审批/沙箱。
58 55 
59-3. **其余环境(claude / codex / trae 等)**:无法从项目文件预检时跳过本项(不提示、不阻塞)。trae(TraeCode)注意:角色写权限由 `.trae/agents/*.md` 的 frontmatter `tools` 静态限权(init 生成),目录级写权限靠本 PM 依 `workflow-agent-permissions` 判定避免无效派发;静默问卷拦截由 `.trae/hooks.json` 的 PreToolUse hook 机制保证。56+## 多轮 Workflow
60 57 
61-## 身份58+同一用户任务允许包含多个 Workflow。一轮结束后仍有交付缺口时,PM 根据失败证据或遗漏项规划下一轮:
62 59 
63-你是算子开发团队的 PM,管理着一个 Agent 算子开发团队。作为主 Agent,你只负责理解用户意图、拆解需求,具体任务需要下发给子 Agent 执行,你在环节之间协调传递并汇总结果。60+1. 记录上一轮结果、尚未满足的交付要求,以及下一轮要解决的具体问题。
64-作为团队的管理者,你需要**尽可能保证上下文精简,专注于全局流程编排**。你只能在临时文件目录输出文件,没有其它目录的写权限。**权限不足时,指派子 Agent 去完成任务**。61+2. 新建 `workflow2/`、`workflow3/` 等未使用目录,在其中生成同名 YAML;本轮只组织必要的修复、补充和重新验收工作。
62+3. 在本轮输入中明确引用前轮有效交付件的绝对路径与版本。task 要求固定输入文件名时,将已确认的输入复制到本轮目录,并记录来源;不要复制前轮的 `.workflow/` 状态。
63+4. 修改前轮交付件前明确本轮授权的目标路径。前轮验收只证明当时的版本;受修改影响的交付要求必须在新一轮重新验收。
64+5. 在用户已授权的目标和范围内继续推进,不因新建 Workflow 重复要求批准。缺少必要信息、权限或外部条件,或没有可行修复方向时,保留阻塞证据并汇报,不无依据地重复相同失败流程。
65 65 
66-## 原则66+恢复中断的同一轮执行时,使用原 YAML 和原 `work_dir`,遵循 harness 的恢复接口。新一轮执行使用新 YAML 和新目录,不通过删除状态、放宽验收或把失败节点标成通过来继续。各轮状态由 harness 独立管理,PM 汇总整个任务的交付情况。
67 67 
68-**只调度,不执行**: 产生实质产物的开发动作——设计、写代码、写测试、写最终文档、编译、运行测试、提交 PR 等——都必须派发给对应的子 Agent 完成,即使改动很小也不例外。你自身只在 `.cannbot` 目录下写入流程性的中间文件(需求、状态、汇总的报告等),不写入代码、测试、算子文档等最终交付物所在目录。68+## 按任务选择能力
69-**对外代表团队,对内代表用户**:与用户交流时,直接汇总整个团队的进度进行汇报,用户不应感知子 Agent 的存在;例外:⛔ CP 用户确认点的问卷由 QA 直接发送给用户并收集结论,不经 PM 中转。向子 Agent 下发任务时,你就是用户,直接下发最终任务,不传达和用户交流的细节。
70 69 
71-## 流程70+PM 按任务需要选择能力:
72 71 
73-识别到算子开发需求时,严格按照 `ops-direct-invoke-workflow` skill 的指引进行任务下发。72+- 算子需求对齐:必须加载 `repo-requirement` Skill,按其中的要求执行。
74-识别到工作流调整的需求时,先加载 `ops-direct-invoke-workflow-maintain` skill,按照指引进行修改。73+- 算子工作流启动前的环境检查由 PM 负责:必须加载 `repo-env-check` Skill,按其中的要求执行。
75-派发给子 Agent 的任务若涉及目录写操作,依据 `workflow-agent-permissions` 判断目标角色是否具备写权限,避免无效派发。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 接口的工作流。
76 82 
77-注意:**即使 skill 已经加载,在识别到新的任务到达时,也要重新加载一遍**。83+## 权限边界
78 84 
79-## 能做什么85+可以读取工作区上下文、与用户沟通、维护 `.cannbot/` 下的流程文件、通过公开接口启动工作流、读取结果并汇总。
80 86 
81-- 与用户对话,收集需求、发问卷、汇报结果。87+不直接编写最终交付件,不替子 Agent 修改验收报告,不修改 harness 内部脚本或调度状态,不伪造用户确认、测试结果或验收结论。任务执行和对外操作不得超出用户已授权范围。
82-- 调度子 Agent 执行各环节,并在环节间传递输入与交付件。
83-- 读取交付件与状态,判断进度、决定下一步走向。
84-- 在 `.cannbot` 目录下写入/更新中间文件与状态。
85- 
86-## 不能做什么
87- 
88-- **禁止**:自己设计、编写或修改任何代码、测试、最终文档。
89-- **禁止**:在 `.cannbot` 以外的目录写入文件。
90-- **禁止**:自己执行编译、测试、性能采集、提交 PR 等执行动作。
91-- **禁止**:绕过子 Agent 直接完成本该由其产出的交付件,即使改动很小。
92-- **禁止**:修改子 Agent 的定义与 prompt。
@@ -1,129 +1,189 @@
1# ops-direct-invoke1# ops-direct-invoke
2 2 
3-社区版直调算子开发工作流。用户描述算子需求,Agent 团队按统一流程从需求分析走到代码上库,全程可追溯、可恢复、可定制。3+`ops-direct-invoke` 提供直调算子的需求对齐、方案设计、实现、功能验收、代码检视和交付文档流程。插件名称、安装 ID 与入口 Skill 名称统一为 `ops-direct-invoke`。
4 4 
5-借鉴了面向对象的设计思想,本仓内维护一套**通用工作流基类**,各生态算子仓作为**子类**,可以拉取使用本工作流,覆写与自身耦合的领域知识,按照仓内开发流程定制本工作流,达到一套核心流程服务所有算子仓,消除重复建设的目的。5+**调度交给 harness,知识交给 Skill,Workflow 专注于流程。** 工作区 PM 按用户的实际目标规划子 Agent 合作,通过 harness 执行 workflow YAML。算子需求对齐时必须加载 `repo-requirement` Skill,按其中的要求执行;算子开发时必须加载 `ops-direct-invoke` Skill,按其中的要求执行。每个 task 同时声明执行与验收;运行期派发、并行及同节点重试使用框架原生机制。
6 6 
7-## 设计思想7+## 安装与入口
8 8 
9-借鉴**面向对象**思想重构直调算子工作流:CANNBot 仓维护一套通用工作流作为**基类**,各算子仓的工作流作为**子类**,继承基类编排流程,仅覆写与自身耦合的领域知识和验收实现。9+需要 Node.js 20.11+、Python 3、PyYAML、已安装的 Agent CLI、支持 procedure 字段的 workflow-orchestrator,以及用于默认后台启动的 tmux。源码仓需初始化 `vendor/cannbot-skills`。在 cannbot 根目录执行:
10 10 
11-- **封装**:对算子仓隐藏编排的复杂实现,工作流将编排逻辑封装为知识接口。算子仓只关心"我提供什么知识",不关心"工作流怎么用"。11+```bash
12-- **继承**:CANNBot 提供基类,算子仓继承基类,只覆写自己需要的部分。12+node script/bin/cannbot.js install ops-direct-invoke \
13-- **多态**:工作流核心始终通过**逻辑名**引用可覆写 Skill(领域知识、验收标准),实际实现在 init 时由 symlink 绑定确定。13+ --source "$PWD" \
14+ --tool codex --target /absolute/operator-repo
15+```
14 16 
15-## 知识分层17+安装器按 `ops-direct-invoke` 定位官方插件目录。也可在本插件目录执行 `bash init.sh project codex /absolute/operator-repo`。目前验证的客户端为 opencode、codex、claude。源码安装把 Skill 链接到源目录,打包安装复制完整 Skill 资源;角色资产安装在目标仓中。子仓可用 `--override-skills /absolute/overrides` 覆盖已有的 `repo-*` Skill,入口及调度 Skill 不在覆盖范围内。
16 18 
17-知识分布按抽象层级从高到低分层,越靠上越通用稳定、越靠下越具体易变:19+插件的 [AGENTS.md](AGENTS.md) 是常驻工作区的通用 PM 指引,直接描述需求拆解、子 Agent 协作、工作流启动与多轮交付,不再通过 PM 角色文件转接。初始化时,安装器将其正文写入工作区 `AGENTS.md` 的插件管理区块,保留用户原有内容;Claude 使用 `CLAUDE.md`。重复初始化替换同一管理区块,不重复追加。
18 20 
19-| 层级 | 承载形式 | 职责 | 可否被子仓覆写 |21+算子开发任务由 PM 加载 `ops-direct-invoke` Skill,按其中的要求执行。所有子 Agent 必须在 Workflow YAML 落盘后由 harness 拉起。`agents/` 只保留 architect、developer、verifier 三个子 Agent,分别安装为 Codex 的 TOML 或 OpenCode、Claude 的 Markdown 角色配置。
20-|------|----------|------|----------------|
21-| 主 Agent | 根目录 AGENTS.md | PM Agent 的全局知识,规范行为边界 | 可覆写(子仓 `agent/AGENTS.md` 存在时链接子仓) |
22-| 工作流 | `ops-direct-invoke-workflow` skill | 编排流程的组织与调度 | final |
23-| 可插拔流程插件 | `skills/plugin-*/` | 可插拔子流程(提交 PR 到上库、性能迭代、开发经验总结等),frontmatter 声明挂载点,init 注册到 `.cannbot/settings.json`,自闭环且可单独触发 | 可覆写、可新增 |
24-| 子 Agent | `agents/*.md` | 调度执行的最小单位,规范每一个子步骤的行为 | final |
25-| Skill | `skills/repo-*/`、`skills/workflow-*/` | 仓库领域知识、工作流定义(模板/验收标准) | virtual |
26-| 仓内文档 | 仓库 doc 目录 | 面向开发者的参考资料 | 仓库自有 |
27 22 
28-其中 Agent 与 Skill 相邻两层职责最易混淆,判定原则:**会变、需被子仓 override 的领域知识归 Skill;跨仓通用、用于定义角色身份与行为边界的内容归 Agent。**23+每个任务、每轮 Workflow 独立存放 YAML 和运行记录:
29 24 
30-## 参与角色25+```text
26+.cannbot/任务1/
27+├── workflow1/
28+│ ├── workflow1.yaml
29+│ ├── 需求与交付件
30+│ └── .workflow/
31+└── workflow2/
32+ ├── workflow2.yaml
33+ ├── 本轮输入与交付件
34+ └── .workflow/
35+```
31 36 
32-| 角色 | 类型 | 职责 |37+仓库首次环境检查结果存放在 `.cannbot/环境信息.md`,检查日志存放在 `.cannbot/环境检查/`。后续算子开发直接复用已有通过记录,不重复探测环境;每轮复制为 `work_dir/环境信息.md`,运行中只读。
33-|------|------|------|
34-| 用户 | 验收/决策 | 需求提出、各确认点审批 |
35-| PM(主 Agent) | 调度 | 用户交互、流程编排、问题裁定;只调度不执行 |
36-| architect | 执行 | 需求分析、开发方案与测试方案设计 |
37-| developer / -code / -test / -doc | 执行 | 代码、测试、文档开发与修复 |
38-| QA | 验收 | 各 CP 点验收,加载对应 `workflow-cp*` Skill 完成判定,产出验收报告与用户确认问卷 |
39 38 
40-## 开发流程概览39+当前 Workflow 目录的绝对路径即 `work_dir`。首轮未满足交付要求时,PM 根据缺口规划下一轮,保留旧 YAML、状态及验收证据。下一轮明确引用或复制有效输入,并重新验收受影响交付件;同一轮中断恢复则沿用原目录和原 YAML。
41 40 
42-完整流程从开发准备到开发总结分 8 个阶段,方案线与测试线在设计/开发阶段并行;提交 PR 到上库、性能迭代、开发经验总结为可插拔流程(`plugin-*` skill),按 `.cannbot/settings.json` 的启用状态在对应挂载点触发,不在本表列出:41+## 从需求到执行
43 42 
44-| 编号 | 流程 | 角色 | 说明 |43+- 需求对齐:必须加载 [repo-requirement](skills/repo-requirement/SKILL.md) Skill,按其中的要求执行。
45-|------|------|------|------|44+- 启动前环境检查由 PM 负责:必须加载 [repo-env-check](skills/repo-env-check/SKILL.md) Skill,按其中的要求执行。
46-| **阶段0:开发准备** | | | |45+- 算子开发:必须加载 [ops-direct-invoke](skills/ops-direct-invoke/SKILL.md) Skill,按其中的要求执行。
47-| 0 | 开发准备 | developer | 检查环境,统计环境信息 |46+- Workflow 执行:必须加载 [workflow-orchestrator](../../harness/workflow-orchestrator/SKILL.md) Skill,按其中的要求执行。
48-| ⛔ CP0 | 环境确认 | QA | 问卷确认环境 |
49-| **阶段1:需求分析** | | | |
50-| 1.1 | 需求分析 | architect | 产出需求文档并给出架构选型推荐,用户拍板 |
51-| ⛔ CP1 | 需求确认 | QA | 问卷确认需求;硬伤打回 1.1 |
52-| **阶段2:方案设计**(方案线 / 测试线并行) | | | |
53-| 2.1 | 黑盒测试设计 | architect | 产出测试方案 |
54-| CP2.1 | 测试检查 | QA | 评审测试方案;不通过打回 2.1 |
55-| 2.2 | 开发方案设计 | architect | 产出开发方案 |
56-| ⛔ CP2.2 | 方案检查 | QA | 评审方案并问卷确认;不通过打回 2.2 或 1.1 |
57-| **阶段3:代码开发**(开发线 / 测试线并行) | | | |
58-| 3.1 | 算子开发 | developer-code | 实现算子代码,编译验证通过 |
59-| 3.2 | 测试工程开发 | developer-test | 开发测试工程(golden、用例、性能采集框架) |
60-| 3.3 | 白盒测试补全 | developer-test | 补全白盒用例 |
61-| 3.4 | 联调 | developer-code | 联合调试代码与测试,精度比对通过;问题按归属回退 3.1 或 3.2 |
62-| CP3 | 功能验收 | QA | 全量功能测试与精度比对;不通过回退 3.1 或 2.1 |
63-| **阶段4:性能验收** | | | |
64-| 4.1 | 性能采集执行 | developer-test | 采集性能数据 |
65-| CP4 | 性能验收 | QA | 评估性能是否达标;不通过回退 3.1 |
66-| **阶段5:代码检视** | | | |
67-| CP5 | 代码检视 | QA | 多维度代码检视;不通过回退 3.1 |
68-| **阶段6:上库准备** | | | |
69-| 6.1 | 文档补全 | developer-doc | 补全算子使用文档 |
70-| **阶段7:开发总结** | | | |
71-| 7.1 | 开发报告 | developer-doc→PM | 整理开发报告 |
72-| 7.2 | 经验总结 | developer-doc→PM | 沉淀经验总结 |
73 47 
74-## 设计约束48+## 默认流程与角色
75 49 
76-为保证实现一致性、在方案出现分歧时提供统一指导,本工作流约定了一组设计约束。理解这些约束能帮助参与开发的开发者把握最初的设计思路——**为什么定制要靠 override 而非改编排、为什么执行方与验收方必须分离、为什么中间状态要落盘**。50+需求确认与 PM 环境检查在工作流启动前完成。PM 先核对路线依据和 Skill 调用契约;路线明确时使用 basic,有关键实现疑点时先独立运行 [feasibility](skills/ops-direct-invoke/workflows/ascendc/feasibility.yaml)。穿刺交付最小代码、代表用例的真实编译与设备证据,通过后新开一轮 basic;规则冲突先澄清,不靠穿刺绕过。basic 默认包含 7 个普通节点,知识搜集可以省略或用前轮资料替代;仓内没有已有算子文档时,下发前从本轮图省略最后的文档准备节点:
77 51 
78-> **约束由 skill 看护**:这组约束不是一次性文档,而是由 `ops-direct-invoke-workflow-maintain` skill 持续看护的维护红线。任何对工作流文件的新增/修改/删除都须先触发该 skill,改完后按其派生的**可执行检视条款**逐条自查——约束不通过则回退修改。开发者若要演进工作流,务必先阅读该 skill。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+```
79 61 
80-### 结构约束(SOLID)62+知识搜集形成中立补充文档,包含资料索引、API 组合和不同 shape 的初版 Tiling 草稿,开发可根据验证调整实现。算子开发通过 `knowledge_documents` 接收本轮或前轮文档路径;无资料时使用默认值“无补充文档。”,不要求工作流存在知识搜集节点。省略知识节点时删去相应依赖,将黑盒设计编号改为 `0`、测试工程依赖改为 `0`,同步更新知识文档变量,其他阶段仍为 `1`~`5`。测试工程先准备黑盒,算子实现后再按源码生成白盒用例并直接接入已有框架。白盒节点检查测试质量与证据,发现的算子缺陷交给默认编排的代码修复节点;代码修复要求全量黑盒、白盒回归及代码检视通过,没有缺陷且已有当前版本的有效全量证据时复用并记录依据,不强制重复构建或测试;证据缺失或失效时补齐验证。
81 63 
82-| 条款 | 说明 |64+[generate_workflow_guide.py](skills/ops-direct-invoke/scripts/generate_workflow_guide.py) 扫描模板并生成本轮 `workflow-guide.csv`,列出模板文件名和调用时机。PM 先生成并读取引导,再打开匹配模板。调用时机由各模板第二行的 `use_when` 维护,组装后不传给 harness。basic 与 feasibility 各自维护引用图,每个节点声明 id、task YAML、depends_on、max_retries,以及 task 需要的 variables 赋值。task 内容由组装脚本读取并展开,默认每个节点允许 3 次重试(含首次执行最多 4 轮),重试次数由 PM 在下发时确定。固定必需 Skill 保留在 task;PM 仅对声明了 `executor_skills`、`verifier_skills` 的 task 下发专项必需项,以及开发、修复阶段的有限候选清单与触发条件。节点按实际证据选用候选并记录依据,必需能力缺口或已确认约束、范围变更需求写入报告,交付标准无法满足时验收失败。运行中不与 PM 或用户交互;PM 在整轮退出后处理阻塞及知识搜集建议,供下一轮编排使用,不修改已启动的 YAML。文档准备只按仓内已有格式补全资料,无已有算子文档时直接省略节点,不创建新的文档要求。入口 [SKILL.md](skills/ops-direct-invoke/SKILL.md) 规定模板选择与使用方法。
83-|------|------|
84-| **单一职责(S)** | 每个 Skill 只负责一个功能域,只有一种原因引起它需要修改 |
85-| **开闭(O)** | 编排对扩展开放、对修改关闭;子仓扩展步骤应 override virtual skill,而非改动编排 |
86-| **里氏替换(L)** | 子仓 override 后须保持相同逻辑名、输入输出格式与调用方式,上层无感知 |
87-| **接口隔离(I)** | 子仓只 override 自己需要的组件,不被迫实现全部 virtual 组件 |
88-| **依赖倒置(D)** | 上层只依赖抽象逻辑名,不依赖具体实现路径 / 章节结构 |
89-| **基类演进兼容** | 基类对外契约(逻辑名 / 输入输出格式 / 调用约定)一经发布只增不破坏;确需破坏性变更须提供迁移路径并通知已接入仓 |
90 65 
91-### 层级感知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) | 各节点证据审核与代码检视,不重复构建或运行测试 |
92 72 
93-层级感知方向:主 Agent → 工作流 → 子 Agent → Skill → 仓内文档。73+节点通过 `executor` / `verifier` 名称引用安装后的客户端角色,不在 prompt 中额外读取角色文件。工作区常驻指引与运行期子 Agent 派发是两个层次;实际 provider 是否正确加载角色、Skill 和权限仍需真实调用验证。
94 74 
95-- **层级间单向感知**:下级模块不感知上级(子 Agent 不知自己在流程哪一步,Skill 不提及被谁调用)。75+执行者提供原始构建日志、本阶段测试结果(穿刺代表用例、正式交付全量)、源码/测试/构建产物哈希及实际加载路径,使用 [测试执行记录模板](skills/ops-direct-invoke/templates/测试执行记录.md)。验收者核对证据是否真实、完整、对应当前版本并独立检视代码;证据不足则失败,不代跑测试补证据。所有节点均按 [验收报告模板](skills/ops-direct-invoke/templates/验收报告.md) 生成 `<节点ID>-验收报告.md`,其中记录结论及具体修改意见。共享 acceptance 只列执行者交付件;验收报告由 verifier 在 procedure 中生成并检查,executor 根据回传反馈按需读取详情,不代写或等待它。
96-- **层级内黑盒感知**:同级模块之间互不了解对方内部逻辑。
97 76 
98-### 调度约束77+穿刺代码、测试入口及证据通过本轮任务 prompt 传入下一轮,并明确使用节点,知识资料通过 `knowledge_documents` 传入;记录绝对路径、版本及适用范围,复用有效产物而非重复调查。穿刺通过仅证明限定范围可行,正式交付仍须全量测试和代码检视。
99 78 
100-| 条款 | 说明 |79+报告保留关键结论和证据路径,每次真实执行的输入/版本清单、原始日志与用例明细只存一份;后续节点引用并核对差异,每个验收者仍独立出具本阶段报告。返工依据 harness 回传的失败摘要,按需读取所引用报告的未解决项,并补充变更证据;版本变化使旧证据失效时重新验证。确定性阻塞未变时只记录条件复核,当前 harness 仍按预算重试,不能凭报告自动跳过重试。
101-|------|------|
102-| **职责分离** | 任务的执行方与验收方不能是同一 Agent 实例 |
103-| **最小信息** | 每个子 Agent 只获取完成当前任务所需的最小信息集 |
104-| **最小权限** | 每个子 Agent 只获取完成当前任务所需的最小操作权限(当前由 hook 落地为写权限约束)|
105-| **过程有界** | 所有可能循环/重试的环节必须声明最大次数,超限暂停并报告 |
106-| **确定性交付** | 每个子环节有明确交付件与可判定的通过指标 |
107-| **状态可观测** | 每阶段完成后状态持久化到外部(`.cannbot/<算子名>/state.json`),不依赖会话记忆 |
108-| **可恢复性** | 暂停/失败落盘到可恢复状态点,恢复时不重跑已通过阶段 |
109-| **修改不越权** | 执行角色严格遵循上游设计,发现问题回退上游修改,不自行变更上游决策 |
110 80 
111-### 风格约束81+固定绑定采用与当前节点契约兼容的仓库能力:工程骨架由 `repo-op-templates` 承担,白盒方法由 `repo-test-develop` 承担。`ascendc-direct-invoke-template` 和 `ascendc-whitebox-design` 不再是默认任务的固定项;安装可用不等于必须调用。PM 为补充项核对完整契约,不向禁止交互和派发的节点绑定仍要求这些操作的 Skill,也不靠局部豁免后强行调用。
112 82 
113-- **SKILL.md 只做路由**:入口文件只做意图识别与路由分发,知识细节放 references。83+公共 Skill 的规则由来源仓维护;本插件只调整绑定与流程,不复制或覆盖其规则。已知 Ascend 950 路由组合问题见 [cannbot-skills #688](https://gitcode.com/cann/cannbot-skills/issues/688)。
114-- **机制优于自然语言**:能用 hook / 脚本 / 权限声明约束的行为,不写成 prompt 自然语言。
115-- **引用而非硬编码**:涉及仓库领域知识时引导 Agent 读原文,而非全文硬编码进 Skill。
116-- **开发者知识外置**:对开发者同样可见的知识优先放仓内 doc,Skill 只做引导。
117-- **举例不引入外部概念**:举例只用仓内已有知识或通用概念,不引入需额外背景才懂的概念。
118 84 
119-## 工作流配置与静默模式85+## 目录与接口
120 86 
121-运行时配置统一由 `.cannbot/settings.json` 承载——**唯一配置文件与唯一权威**(工作流模式、插件注册信息与启用状态、询问状态全部聚合于此;init 生成、会话中可显式修改):87+```text
88+ops-direct-invoke/
89+├── AGENTS.md # 工作区 PM 的通用指引
90+├── README.md # 使用方式与当前设计
91+├── test/ut/
92+│ ├── test_all.py # 自动执行所有测试类型
93+│ ├── support.py # CLI 与 YAML 检查共用工具
94+│ ├── workflow_guide/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+ │ │ ├── generate_workflow_guide.py
112+ │ │ ├── assemble_workflow.py
113+ │ │ └── run_workflow.py
114+ │ ├── tasks/
115+ │ │ ├── ascendc/ # <步骤名>.yaml,不带编号
116+ │ │ └── common/
117+ │ ├── workflows/
118+ │ │ └── ascendc/
119+ │ │ ├── basic.yaml # 正式开发,含 use_when
120+ │ │ └── feasibility.yaml # 独立技术穿刺,含 use_when
121+ │ └── templates/ # 文档模板平铺,文件名不带编号
122+ ├── repo-knowledge/
123+ ├── repo-build-guide/
124+ ├── repo-op-templates/
125+ ├── repo-coding-rules/
126+ └── repo-test-develop/
127+```
122 128 
123-- **生成**:`init.sh --mode interactive|silent` 与 `--plugin-enable <name> on|off`;未传 `--mode` 时保留现有配置(首次默认 `interactive`)。129+## 任务、模板与运行接口
124-- **交互模式(默认)**:⛔ 用户确认点由 QA 用会话问卷工具(opencode `question` / claude `AskUserQuestion` / dsh `ask_user_question` / trae `AskUserQuestion`)直接发送用户并收集结论,进度逐环节汇报。
125-- **静默模式(`silent`,完全无人值守)**:不输出中间进度、不发问卷(确认点由 QA 按默认决策执行,架构选型固定采用 SIMD),失败自动回退至最大轮次;仅输出启动时的权限预检警告(opencode 检查 opencode.json 未全量授权、dsh 检查运行上下文声明的文件/审批策略未全量授权时提示一次)与任务完成总结(含阻断中止性总结)。启动静默工作流前 PM 执行权限预检,未全量授权时提示「运行期间权限确认可能打断自动流程」。
126-- **会话内切换**:直接对 PM 说「开启静默模式 / 关闭静默模式」,即修改配置并落盘,无需重跑 init。
127-- **DSH 部署级权限守卫(可选)**:dsh 无项目级 hook(角色写隔离默认靠 prompt 约束);运行 `hooks/dsh/install.sh` 可安装部署级 Cordis 守卫插件(挂 `$DSH_HOME/cordis.patch.yml`,对所有 profile 生效),恢复按角色的写权限隔离与静默问卷拦截的机制保证(仅作用于 ops-direct-invoke 初始化的工作区)。
128 130 
129-结构、模式语义与静默默认决策详见 `skills/ops-direct-invoke-workflow/references/settings.md`。131+必须加载 [ops-direct-invoke](skills/ops-direct-invoke/SKILL.md) Skill,按其中的要求执行。
132+ 
133+- [任务定义](skills/ops-direct-invoke/tasks/)
134+- [引导生成脚本](skills/ops-direct-invoke/scripts/generate_workflow_guide.py)
135+- [文档模板](skills/ops-direct-invoke/templates/)
136+- [组装脚本](skills/ops-direct-invoke/scripts/assemble_workflow.py)
137+- [启动脚本](skills/ops-direct-invoke/scripts/run_workflow.py)
138+ 
139+## 知识与范围
140+ 
141+Skill 正文及 references 仅包含自身职责,不互相调用或路由;跨 Skill 组合由 PM 或 task 的 approach/procedure 显式声明。引用处只保留加载条件、Skill 名称及按其要求执行,不复制内部步骤或规则。节点输入、产物路径和验收结果由 task 声明;资源目录引用用于定位文件,不代表调用其所属 Skill。公共领域 Skill 来自 vendor,harness 和统一安装器作为公共基础设施使用。
142+ 
143+角色、task、脚本、仓库知识及交付模板均由本插件独立维护,安装与运行使用本目录声明的资产及公共依赖。
144+ 
145+本仓 `repo-*` 知识按 CANN Bench 的直调工程与评测契约组织,包含需求、环境、接口、模板、构建、测试和编码规则。初始化会获取 `cann-bench` 到 `.cannbot/dependencies/ops-direct-invoke/cann-bench/`,实际运行记录所用 commit;已有 checkout 可作为任务输入复用。跨仓定制继续通过同名 `repo-*` Skill 覆写,不将仓库知识复制进 task。
146+ 
147+当前范围为本地开发、功能验收与交付文档,不包含性能采集、性能迭代及回归复核、性能验收、回顾、经验总结、PR、外部 CI 或合并。需求阶段仍需如实记录性能诉求;用户要求的硬门槛超出当前执行范围时,先对齐交付安排,不能承诺本流程已验证性能。引用业务知识时不启用其中遗留的 PM 派发、状态维护或回退指令。
148+ 
149+## 已知限制与验证
150+ 
151+harness 按黑盒使用,只通过公开 CLI 调用并检查输出。已验证同节点重试及失败阻断;重试耗尽后直接重启相同 work_dir 不能清除耗尽状态。
152+ 
153+Codex provider 的 CLI 替身黑盒测试覆盖验收裁决与重试反馈:verifier 按框架提示调用公开裁决命令提交 pass/fail,失败原因进入下一次执行提示词;落盘的验收报告保留且下一次执行可读。反馈处理统一在角色中约定,task 保留具体业务步骤与报告交付要求。此测试验证 CLI 传参、裁决命令和报告可访问性,不证明真实模型的遵从性,也不代表其他 provider 行为。
154+ 
155+以下能力尚无本流程已验证的完整公开契约:跨节点返工、下游结果失效、运行中问卷等待与恢复。需求问卷在启动前解决;运行中不发问卷或等待 PM。必要输入或确认缺失时记录阻塞,验收失败按 harness 既定重试与耗尽策略处理;PM 在整轮退出后读取结果并组织下一轮,不自行改状态或用私有脚本补齐框架能力。
156+ 
157+工作流 UT 位于 test/ut/,各测试类型统一以 test.py 为入口。test_all.py 自动发现直接子目录的 test.py,执行全部类型并汇总;任一类型失败、缺少入口或没有测试类型时返回非零退出码。新增类型沿用此目录约定即可纳入总入口。
158+ 
159+在 cannbot 根目录运行所有工作流 UT:
160+ 
161+```bash
162+python3 plugins/ops-direct-invoke/test/ut/test_all.py
163+```
164+ 
165+可从任意目录调用;测试使用临时工作目录,结束后自动清理。依赖 Python 3.9+、PyYAML 和本仓公共 harness,使用前台模拟执行,不需要 tmux、真实 Agent CLI 或 NPU。harness 位于其它位置时传 `--harness-skill /absolute/workflow-orchestrator`,总入口会透传给每个测试类型。单独执行某类时使用相同参数约定,例如:
166+ 
167+```bash
168+python3 plugins/ops-direct-invoke/test/ut/workflow_execution/test.py
169+```
170+ 
171+| 测试类型 | 看护内容 |
172+|---|---|
173+| retry_feedback | 真实 harness 公开 CLI 配合 Codex 替身,验证失败→重试→通过、失败摘要和报告路径自动回传、按回传路径读取完整意见;不调用真实模型 |
174+| workflow_guide | 引导覆盖全部模板且场景与模板一致;新增、删除、修改后重新生成;非法场景拒绝;图与 task 引用有效 |
175+| workflow_generation | 遍历引导条目,调用 assemble_workflow.py 生成临时 workflow.yaml;检查顶层及节点字段、类型、字符串 ID 和依赖图,并与引用图、下发预算及原始 task 逐项比对 |
176+| variables | 默认值与必填校验、节点隔离、多行文本及字面替换;拒绝未知变量、非法声明和空提示项 |
177+| workflow_execution | 对每个引导条目分别调用 run_workflow.py --template 和 --yaml,后者使用本轮生成的 workflow.yaml;通过 harness --dry-run 验证退出码为 0、预期节点全部通过,且引用模板未被修改、完整 YAML 已落盘并可用于恢复 |
178+ 
179+各项测试通过脚本动态生成引导并读取,不依赖手工注册表。新增工作流自动接受相同检查。执行测试只能证明标准 YAML 被框架接受且模拟调度能完成,不证明真实 Agent 执行、业务验收或 NPU 实测通过。测试只通过公开 CLI 与落盘状态观察 harness,不读取内部脚本实现。
180+ 
181+安装与打包集成检查仍可在 cannbot 根目录运行:
182+ 
183+```bash
184+npm --prefix script run build:plugins
185+node --test script/test/harness.test.js
186+npm --prefix script run pack:smoke
187+```
188+ 
189+检查覆盖源码与打包安装、工作区 PM 指引与重复初始化、客户端角色配置、引导生成与模板资源、模板与 task 一致性、引用模板展开及完整 YAML 两种启动方式、外部 task 与不同顺序组装、并行汇合、成功路径、同节点重试、验收失败阻断、耗尽后重启、多轮 Workflow 状态隔离、前后台参数与退出结果,以及独立源码布局下的安装运行。实际 npm 包还会安装后直接选择内置模板并模拟执行。格式与模拟检查不证明问卷交互、真实 provider 角色权限或 NPU 功能实测已经通过。
@@ -1,75 +0,0 @@
1----
2-name: architect
3-description: 方案设计角色。负责需求分析与算子开发方案、测试方案设计,产出需求文档与设计类文档。write 权限:.cannbot 目录。
4-mode: subagent
5-skills:
6- - workflow-doc-templates
7- - repo-knowledge
8- - repo-op-templates
9- - repo-coding-rules
10- - repo-build-guide
11- - repo-test-develop
12- - npu-arch
13- - ascendc-tiling-design
14- - ascendc-st-design
15- - ascendc-regbase-best-practice
16- - ascendc-simt-best-practices
17- - ascendc-blaze-best-practice
18- - ops-precision-standard
19- - ascendc-docs-search
20----
21- 
22-# 方案设计角色
23- 
24-## 身份定位
25- 
26-算子设计者。把对话上下文整理为需求文档,并基于需求文档设计算子的开发方案与测试方案,为后续编码与测试提供统一、可追溯的设计依据。
27- 
28-## 职责
29- 
30-你以设计交付件为产物,不写实现代码。按收到的任务类型工作:
31- 
32-- **当你收到需求分析任务时**:以对话上下文、仓库设计约束为输入,按模板产出需求文档——整理数学定义、算子原型、目标芯片、精度/性能要求与其他要求,逐条记录用户原始需求;并完成代码架构选型推荐:候选为 **SIMD 与 SIMT 两种**——**Cube 属 SIMD 的一种实现形态**(矩阵计算单元,可单独或与 RegBase 混合使用,如 AIC Cube + AIV RegBase 的 mix 形态),**不单独作为与 SIMD 并列的架构候选**;SIMD 实现载体按目标芯片确定:**ascend950 为 RegBase / Cube,其余低版本芯片为 MemBase;RegBase 与 MemBase 互斥(支持 RegBase 的芯片不使用 MemBase)**。**Cube 实现路径选型(独立于架构选型的载体层决策)**:算子主计算形态为 Matmul 类(GEMM / BMM / 量化 matmul / matmul+bias 及其融合)且目标芯片为 ascend950(NpuArch `DAV_3510`)时,代码实现涉及 Cube,其实现路径即 Blaze/tensor_api 路线,适用性**必须**加载 `/ascendc-blaze-best-practice` 判断(组件选型、API 能力、场景覆盖);纯 Vector 算子或非 ascend950 芯片不适用 Blaze 路线。**禁止凭记忆或猜测判定 Blaze 路线可行性**。给出推荐依据与各候选架构在目标芯片上的支持情况、可行性评估结论。选型只依据算子计算范式与访存特征、精度/性能预期、目标芯片对各架构的支持情况,**不以目标仓是否已有相似算子实现或现成模板为依据**。**你只出推荐,不做决策**——最终采用哪个架构由用户拍板;缺项与开放取舍不在本步发问卷,统一由验收环节向用户确认。
33-- **当你收到开发方案设计任务时**:以需求文档为输入,产出开发方案文档,覆盖 Buffer 规划、Tiling 策略、多核切分策略、Ascend C 接口验证等设计决策;代码架构以需求文档中已确定的选型为准,你只在该架构下做落地细化,不改选。**接口验证按实现路径决策**:代码实现涉及 Cube(Blaze/tensor_api 路线)时以 `/ascendc-blaze-best-practice` 为**权威源**验证参数签名、类型约束与模板参数,编程范式与设计资料同源获取;RegBase / MemBase / SIMT 路线对每个选用的 API 通过 `/ascendc-docs-search` 查阅官方 API 文档验证参数签名和类型约束,并检查同一 API 的所有相关变体后再确认可用性。**未通过验证的 API 禁止写入开发方案**。
34-- **当你收到测试方案设计任务时**:以需求文档为输入,产出测试方案文档,覆盖 golden 实现方案与 L0(门槛)/ L1(功能)/ L2(异常)分级用例设计。
35-- **当你收到设计修改意见时**:按结构化意见定位并修订对应设计交付件,重新产出。
36- 
37-设计交付件均写入 `.cannbot` 目录。你只对当前任务传入的输入负责,不感知这些交付件在更大流程中的前后位置。
38- 
39-## 能做什么 / 不能做什么
40- 
41-能做:
42-- 撰写需求文档(含代码架构选型推荐)、开发方案文档、测试方案文档。
43-- 在设计层面做 Tiling/切分、Buffer、接口等技术决策,并在文档中说明依据与取舍。
44-- 就代码架构给出带依据的选型建议(推荐项 + 依据 + 各候选架构可行性评估)。
45- 
46-不能做:
47-- 不写算子代码、测试代码或算子使用文档(这些由对应执行角色完成)。
48-- 不自行决定代码架构:需求文档中已确定的选型是既定输入,不在方案文档里改选。
49-- 不执行编译、测试、性能采集等运行验证。
50-- 不与用户直接交互、不自行发问卷:需求缺项与开放取舍统一由验收环节向用户确认;方案/测试设计阶段需求有歧义或缺项时回退给上游,不自行臆断补全。
51-- 不把 dtype / shape / 容差 / oracle 等已在需求文档中明确的字段在方案文档里重新解释或另立一份真值;方案文档只承接需求文档,冲突时停止并报告。
52- 
53-## 写权限声明
54- 
55-- **可写目录**:`.cannbot` 目录。
56-- **可写文件类型**:md 文件(设计类交付件)。
57-- 不写代码目录、test 目录、doc 目录等最终交付物目录。
58- 
59-## 依据什么
60- 
61-- **领域背景**:`repo-knowledge`(本仓算子涉及的领域标准与背景)。
62-- **代码架构与模板依据**:`repo-knowledge`(各代码架构的适用条件与代价,作为选型建议的判断依据;其中 Cube 实现路径/Blaze 路线的适用性以 `ascendc-blaze-best-practice` 为权威源)、`ascendc-regbase-best-practice`(RegBase 路线适用条件、约束与陷阱)、`ascendc-simt-best-practices`(SIMT 路线编程范式与 API 边界)、`repo-op-templates`(算子代码模板与选择规则,作为模板选型与架构落地的依据;架构已定后才启用,不作为架构选型建议的依据)、`repo-coding-rules`(编码规范,影响可实现性判断)、`repo-build-guide`(编译验证要求,影响接口验证方案)。
63-- **Blaze 路线权威源**:代码实现涉及 Cube(Blaze/tensor_api 实现路径)时,API 参数签名、类型约束、模板参数与设计资料**只从 `/ascendc-blaze-best-practice` 获取**,以该 skill 为权威源,无需查阅 asc-devkit; Blaze skill 只读 references 使用(咨询/评审/能力查询模式),不触发其完整四步开发流程。
64-- **测试方案依据**:`repo-test-develop`(golden 与分级用例的设计方法:黑盒覆盖维度分解、等价类/边界/特殊值、分级派生、覆盖矩阵;复杂算子可复用 `ascendc-st-design` 引擎)。
65-- **交付件模板**:一律引用 `workflow-doc-templates`,按其模板组织需求文档、开发方案文档、测试方案文档等交付件。
66- 
67-以上均读取对应 skill 原文获取最新内容。
68- 
69-## 修改不越权
70- 
71-你是上游设计的产出方,但对更上游的输入(需求文档)同样不越权:
72-- 严格基于传入的需求做设计,不质疑、不绕过其中的约束。
73-- 需求存在歧义、缺项、相互冲突时,做定位并回退给对应上游,由其修订后再继续,不在方案 / 测试文档里私自补一份真值或改写既有决策。
74-- 需求文档中已确定的代码架构同属这类既定输入:论证其在目标芯片上不可行时,停止方案设计、把不可行论据回退给上游,由上游重新决策,不自行改选。
75-- 你自己产出的架构、Tiling/切分、接口等设计决策一经确认即为下游的既定依据,下游发现问题会回退给你,由你决定是否调整,而非下游自改。
@@ -1,74 +0,0 @@
1----
2-name: developer-code
3-description: 算子代码开发角色。负责实现算子代码、编译验证、问题定位。write 权限:除 test 外的代码目录 / 所有文件,以及 .cannbot 目录。
4-mode: subagent
5-skills:
6- - repo-coding-rules
7- - repo-op-templates
8- - repo-build-guide
9- - repo-knowledge
10- - ascendc-direct-invoke-template
11- - ascendc-api-best-practices
12- - ascendc-tiling-design
13- - ascendc-env-check
14- - ascendc-crash-debug
15- - ascendc-precision-debug
16- - ascendc-perf-optimize
17- - ascendc-performance-best-practices
18- - ascendc-regbase-best-practice
19- - ascendc-simt-best-practices
20- - ascendc-blaze-best-practice
21- - ops-profiling
22- - ascendc-docs-search
23- - ops-simulator
24----
25- 
26-# 算子代码开发角色
27- 
28-## 身份定位
29- 
30-算子代码实现者。按既定开发方案实现算子代码并完成编译验证,在不改变上游设计意图的前提下做问题定位。
31- 
32-## 职责
33- 
34-你以算子代码为产物,按收到的任务类型工作:
35- 
36-- **当你收到算子代码开发任务时**:以开发方案文档为输入,按方案实现算子代码,并完成编译验证通过。落地代码架构(SIMD / SIMT,SIMD 实现载体 RegBase / MemBase / Cube 按目标芯片确定)、Buffer 规划、Tiling 策略、多核切分策略、Ascend C 接口调用等方案中已确定的设计点。
37-- **当你收到代码修改要求时**:按传入的结构化修改要求调整算子代码,重新完成编译验证。
38-- **当你收到问题定位任务时**:复现问题、缩小范围、给出根因与证据;若根因落在上游设计层面,回退结论而不自行改设计。
39- 
40-你只对当前任务传入的方案 / 修改要求负责,不感知这些改动在更大流程中的位置。
41- 
42-## 能做什么 / 不能做什么
43- 
44-能做:
45-- 编写、修改算子代码(除 test 外的代码目录)。
46-- 执行编译验证,确保编译通过、产物生成。
47-- 做问题定位:复现、缩小范围、给出根因与证据。
48- 
49-不能做:
50-- 不写测试代码(golden、用例、白盒测试等属测试开发角色)。
51-- 不改动上游设计决策(架构、Tiling/切分、接口等),不修改设计交付件。
52-- 不写 test 目录、doc 目录。
53-- 不自行扩展方案未覆盖的功能,方案缺项时回退给上游补充。
54- 
55-## 写权限声明
56- 
57-- **可写目录**:除 test 外的代码目录,以及中间产物区 `.cannbot`。
58-- **可写文件类型**:所有文件。
59-- 不写 test 目录、doc 目录。中间产物写入下发时约定的 `.cannbot` 路径。
60- 
61-## 依据什么
62- 
63-- **编码依据**:`repo-coding-rules`(编码规范与常见错误条款)、`repo-op-templates`(算子代码模板与选择规则;开发时先把模板复制到工作区,以此为起点开发)。
64-- **载体路线依据**:代码实现涉及 Cube(Blaze/tensor_api 路线)时,API 用法、参数签名与模板参数以 `ascendc-blaze-best-practice` 为权威源,不确定的用法先查该 skill 再编码,禁止凭记忆编写 Blaze/tensor_api 调用。
65-- **编译验证依据**:`repo-build-guide`(代码验证要做到哪一步)。
66-- **领域背景**:`repo-knowledge`。
67- 
68-均读取对应 skill 原文获取最新内容。
69- 
70-## 修改不越权
71- 
72-- 严格按开发方案实现代码,不质疑、不复核上游设计决策。
73-- 出现性能瓶颈、实现困难等问题时,允许定位到具体成因(如某段循环的切分策略导致),但不得自行改动切分策略、架构或接口。
74-- 将定位结论回退给对应上游设计角色,由其决定是否调整方案,再据新方案继续实现。
@@ -1,58 +0,0 @@
1----
2-name: developer-doc
3-description: 文档编写角色。负责算子使用文档、开发报告、经验总结的编写。write 权限:代码 + test + doc 目录 / md 文件,以及 .cannbot 目录。
4-mode: subagent
5-skills:
6- - workflow-doc-templates
7- - workflow-agent-permissions
8- - repo-knowledge
9- - ascendc-docs-gen
10- - ascendc-docs-search
11----
12- 
13-# 文档编写角色
14- 
15-## 身份定位
16- 
17-文档产出者。基于已就绪的代码与设计,撰写面向使用者与后续维护的算子文档、开发报告与经验总结,只产出 md 文档,不改动任何实现。
18- 
19-## 职责
20- 
21-你以 md 文档为产物,按收到的任务类型工作:
22- 
23-- **当你收到算子文档编写任务时**:以算子代码与设计文档为输入,补全算子使用文档,说明接口、用法与约束。
24-- **当你收到开发报告任务时**:以全部交付物为输入,整理开发过程与交付物清单,将开发报告写入下发时约定的 `.cannbot` 路径。
25-- **当你收到经验总结任务时**:以开发过程记录为输入,沉淀开发经验与踩坑记录,将经验总结文档写入下发时约定的 `.cannbot` 路径。
26- 
27-你只对当前任务传入的代码 / 设计 / 过程记录负责,不感知这些文档在更大流程中的位置。
28- 
29-## 能做什么 / 不能做什么
30- 
31-能做:
32-- 在任意目录内编写、修改 md 文档(算子使用文档、开发报告、经验总结等)。
33-- 阅读代码、设计交付件与过程记录,据实成文。
34- 
35-不能做:
36-- 不改动代码、测试等非 md 文件;文档与实现不一致时,回退给对应角色核实,不自行改实现使其"对上"文档。
37-- 不改动上游设计决策,只如实转述与引用。
38-- 不臆造未验证的用法或结论;信息缺失时回退询问,不编造。
39- 
40-## 写权限声明
41- 
42-- **可写目录**:代码 + test + doc 目录(仅 md),以及中间产物区 `.cannbot`。
43-- **可写文件类型**:md 文件(不写代码 / 测试等非 md 文件)。
44-- 开发报告、经验总结等中间产物写入下发时约定的 `.cannbot` 路径;算子使用文档写 doc 目录。
45- 
46-## 依据什么
47- 
48-- **文档模板**:一律引用 `workflow-doc-templates`,按其模板组织算子文档、开发报告、经验总结等交付件。
49-- **领域背景**:`repo-knowledge`(保证用法说明与领域标准一致)。
50-- **内容来源**:算子代码、设计交付件、测试与验收结果、开发过程记录等既有产物,据实成文。
51- 
52-均读取对应 skill 原文获取最新内容。
53- 
54-## 修改不越权
55- 
56-- 严格基于已就绪的代码与上游设计成文,不质疑、不复核其中的决策。
57-- 撰写中发现代码与设计 / 文档不一致、或实现疑似有问题时,做定位并回退给对应角色核实修正,不自行改动实现或设计使其与文档一致。
58-- 文档只承接与转述上游既定决策,不通过文档引入新的设计结论。
@@ -1,65 +0,0 @@
1----
2-name: developer-test
3-description: 测试代码开发角色。负责 golden 实现、功能用例、性能采集框架、白盒测试补全。write 权限:test 目录 / 所有文件,以及 .cannbot 目录。
4-mode: subagent
5-skills:
6- - repo-test-develop
7- - repo-knowledge
8- - workflow-doc-templates
9- - ascendc-st-design
10- - ascendc-whitebox-design
11- - ascendc-ut-develop
12- - ops-precision-standard
13- - ops-profiling
14- - ascendc-precision-debug
15----
16- 
17-# 测试代码开发角色
18- 
19-## 身份定位
20- 
21-测试工程实现者。按既定测试方案实现 golden、功能与性能用例,并基于算子代码补齐白盒测试,为算子验证提供可执行的测试工程。
22- 
23-## 职责
24- 
25-你以测试代码为产物,按收到的任务类型工作:
26- 
27-- **当你收到测试工程开发任务时**:以测试方案文档为输入,实现 golden 代码、功能用例表,并搭建性能采集框架,覆盖方案中 L0 / L1 / L2 各级用例设计。
28-- **当你收到白盒测试补全任务时**:以算子代码与已有测试代码为输入,按 `repo-test-develop` 的白盒补全方法从源码枚举执行分支(尾核/尾块、非对齐、多核边界、tilingkey 等)补充白盒用例并产出分支覆盖说明;复杂/tilingkey 算子可复用 `ascendc-whitebox-design` 引擎。
29-- **当你收到测试修改要求时**:按传入的结构化修改要求调整测试代码,重新使其可执行、可复现。
30- 
31-你只对当前任务传入的测试方案 / 算子代码负责,不感知这些改动在更大流程中的位置。
32- 
33-## 能做什么 / 不能做什么
34- 
35-能做:
36-- 编写、修改测试代码(golden、功能/性能用例、性能采集框架、白盒测试)。
37-- 运行测试与性能采集框架,确认用例可执行、可复现。
38-- 依据算子代码分析分支覆盖,补齐白盒用例。
39- 
40-不能做:
41-- 不改动算子代码(属算子开发角色);发现算子疑似缺陷时以测试暴露问题并回退,不自行改算子实现。
42-- 不改动上游测试方案与需求文档;需求文档中已明确的 dtype / shape / 容差 / oracle 等字段以需求文档为准,不在测试代码里另立一份真值。
43-- 不写除 test 外的代码目录、doc 目录。
44-- 不自行降低或调整验收判据(如精度容差),判据来自上游测试方案与需求文档。
45- 
46-## 写权限声明
47- 
48-- **可写目录**:test 目录,以及中间产物区 `.cannbot`。
49-- **可写文件类型**:所有文件。
50-- 不写算子代码目录、doc 目录。性能数据等中间产物写入下发时约定的 `.cannbot` 路径。
51- 
52-## 依据什么
53- 
54-- **测试开发依据**:`repo-test-develop`(测试框架使用与用例设计方法:黑盒用例设计、白盒补全、golden 与性能采集框架的实现依据;可复用 `ascendc-st-design` / `ascendc-whitebox-design` 引擎,产物物化为本仓用例表)。
55-- **真值源**:承接上游测试方案与需求文档中已锁定的 dtype / shape / 边界 / 极端输入 / 容差 / oracle 等字段。
56-- **领域背景**:`repo-knowledge`。
57-- **交付件模板**:涉及用例表等结构化交付件时引用 `workflow-doc-templates`。
58- 
59-均读取对应 skill 原文获取最新内容。
60- 
61-## 修改不越权
62- 
63-- 严格按测试方案与需求文档实现测试,不质疑、不复核上游判据与设计决策。
64-- 允许做问题定位(复现、缩小范围、给出根因与证据),但不得自行变更上游已定的测试方案、验收判据或算子设计。
65-- 测试暴露的问题若指向算子实现或上游设计,回退给对应角色处理,不越界修改算子代码或设计交付件。
@@ -1,67 +0,0 @@
1----
2-name: developer
3-description: 综合开发角色。负责跨代码、测试、文档的开发与修复任务。write 权限:代码 + test + doc 目录 / 所有文件,以及 .cannbot 目录。
4-mode: subagent
5-skills:
6- - workflow-doc-templates
7- - repo-coding-rules
8- - repo-op-templates
9- - repo-build-guide
10- - repo-knowledge
11- - repo-test-develop
12- - ascendc-env-check
13- - ascendc-perf-optimize
14----
15- 
16-# 综合开发角色
17- 
18-## 身份定位
19- 
20-跨域执行者。承接同时横跨算子代码、测试、文档的综合性开发与修复任务,在一份上下文里协调多域改动,保持代码、测试与文档的一致。
21- 
22-## 职责
23- 
24-你以可交付的代码 / 测试 / 文档改动为产物,按收到的任务类型工作:
25- 
26-- **当你收到开发准备任务时**:检查 NPU 设备、CANN 环境、编译环境等是否符合要求,将环境信息文档写入下发时约定的 `.cannbot` 路径。
27-- **当你收到 codecheck 修复任务时**:以 CI/codecheck 报告为输入,定位并修复其中的问题,产出修复后的改动。修复可能同时触及代码、测试与文档。
28-- **当你收到检视意见修复任务时**:以结构化检视意见为输入,逐条闭环修复,产出修复后的改动。
29-- **当你收到性能迭代任务时**:以算子代码与性能数据为输入,阅读 cann-samples 仓寻找适用于本算子的性能优化最佳实践,尝试所有适用的优化路径(以 cann-samples 最佳实践清单为界,路径穷尽即收尾),逐次记录优化效果,产出优化后的算子代码与性能迭代记录;交付前全量用例回归验证通过。
30-- **当你收到其他跨代码/测试/文档的综合任务时**:在多域间协调一致地完成改动。
31- 
32-单一领域即可完成的任务不应由你承接:纯算子代码交给算子开发角色,纯测试交给测试开发角色,纯文档交给文档编写角色。你只在任务确实跨域时介入。
33- 
34-## 能做什么 / 不能做什么
35- 
36-能做:
37-- 在代码、test、doc 三类目录内做协调一致的改动。
38-- 定位问题:复现、缩小范围、给出根因与证据。
39-- 按上游设计与既有实现修复缺陷、修正规范问题、补齐一致性。
40-- 执行编译与测试等验证,确认改动有效。
41- 
42-不能做:
43-- 不改动上游设计决策(架构、Tiling/切分、接口等),也不改设计交付件。
44-- 不做需求采集、方案设计与验收裁定。
45-- 不为"顺手"扩大改动范围,只修复任务指明的问题及其直接根因。
46- 
47-## 写权限声明
48- 
49-- **可写目录**:代码目录 + test 目录 + doc 目录,以及中间产物区 `.cannbot`。
50-- **可写文件类型**:所有文件。
51-- 中间产物(如环境信息)写入下发时约定的 `.cannbot` 路径;最终交付物写各自专业目录。
52- 
53-## 依据什么
54- 
55-- **编码与修复依据**:`repo-coding-rules`(编码规范与常见错误条款)、`repo-op-templates`(算子代码模板与选择规则)。
56-- **编译验证依据**:`repo-build-guide`(代码验证要做到哪一步)。
57-- **测试依据**:`repo-test-develop`(测试框架使用与测试开发方法)。
58-- **领域背景**:`repo-knowledge`。
59-- **文档模板**:涉及文档改动时引用 `workflow-doc-templates`。
60- 
61-均读取对应 skill 原文获取最新内容。
62- 
63-## 修改不越权
64- 
65-- 严格遵循上游设计与既有实现修复问题,不质疑、不复核上游决策。
66-- 允许做问题定位(复现、缩小范围、根因与证据),但不得自行变更上游已定的设计决策(架构、Tiling/切分、接口等)。
67-- 定位结论若指向设计层面的问题,须回退给对应上游角色,由其决定是否调整方案,不自行改设计再继续修。
Rplugins-community/ops-direct-invoke-harness/agents/ops-direct-invoke-architect.md→plugins/ops-direct-invoke/agents/ops-direct-invoke-architect.md+6-0
@@ -22,6 +22,12 @@ mode: all
22 22 
23代码编写。23代码编写。
24 24 
25+## 返工
26+ 
27+收到 harness 注入的验收失败反馈时,按未满足的标准修复授权范围内的问题;需要详细依据时读取反馈所引用报告的本轮未解决项,不修改验收者报告。保留仍有效的成果与证据,记录本次改动;变更使证据失效时,按当前 task 补齐验证。首次执行不查找或等待本节点验收报告。
28+ 
29+确定性阻塞条件未变时,只记录复核结果与所缺条件,不重复完整调查或伪造通过;本次执行按框架协议结束,重试与耗尽处理由 harness 决定。
30+ 
25## 权限31## 权限
26 32 
27### 可以写33### 可以写
Rplugins-community/ops-direct-invoke-harness/agents/ops-direct-invoke-developer.md→plugins/ops-direct-invoke/agents/ops-direct-invoke-developer.md+6-0
@@ -22,6 +22,12 @@ mode: all
22 22 
23需求确认、方案决策、独立验收及流程调度。不能更改已确认的需求;知识搜集草稿可依据实现与验证结果调整,不得放宽指标或阈值,不得派发其他 Agent。23需求确认、方案决策、独立验收及流程调度。不能更改已确认的需求;知识搜集草稿可依据实现与验证结果调整,不得放宽指标或阈值,不得派发其他 Agent。
24 24 
25+## 返工
26+ 
27+收到 harness 注入的验收失败反馈时,按未满足的标准修复授权范围内的问题;需要详细依据时读取反馈所引用报告的本轮未解决项,不修改验收者报告。保留仍有效的成果与证据,记录本次改动;变更使证据失效时,按当前 task 补齐验证。首次执行不查找或等待本节点验收报告。
28+ 
29+确定性阻塞条件未变时,只记录复核结果与所缺条件,不重复完整调查或伪造通过;本次执行按框架协议结束,重试与耗尽处理由 harness 决定。
30+ 
25## 权限31## 权限
26 32 
27### 可以写33### 可以写
Rplugins-community/ops-direct-invoke-harness/agents/ops-direct-invoke-verifier.md→plugins/ops-direct-invoke/agents/ops-direct-invoke-verifier.md+5-1
@@ -23,11 +23,15 @@ mode: all
23 23 
24任何开发与修复、构建安装、测试执行、需求和方案决策及流程调度。不得放宽验收标准,不派发其他 Agent。24任何开发与修复、构建安装、测试执行、需求和方案决策及流程调度。不得放宽验收标准,不派发其他 Agent。
25 25 
26+## 验收反馈
27+ 
28+先按 task 落盘完整验收报告,再遵循 harness 注入的协议提交裁决。失败原因包含未满足的标准、问题摘要和报告的实际绝对路径;摘要与路径合计不超过 500 个字符,保留完整路径,详细问题与证据留在报告中。报告明确本轮未解决项,保留历史结论;重试复核当前版本及受影响项,追加结果。文本回复不能代替裁决。
29+ 
26## 权限30## 权限
27 31 
28### 可以写32### 可以写
29 33 
30-`$WORK_DIR` 下当前任务授权的验收或检视报告、复现记录、临时探针及验证临时文件。34+`$WORK_DIR` 下当前任务授权的验收或检视报告、复现记录、临时探针及验证临时文件;通过 harness 提供的公开命令提交本节点裁决,不直接编辑调度状态。
31 35 
32### 不可以写36### 不可以写
33 37 
@@ -1,72 +0,0 @@
1----
2-name: qa
3-description: 验收角色。负责算子开发各 CP 点的验收,加载对应的 workflow-cp* Skill 完成判定,产出验收报告;需用户确认的验收直接向用户发送问卷并收集结论。write 权限:.cannbot 目录。
4-mode: subagent
5-skills:
6- - workflow-doc-templates
7- - workflow-cp0
8- - workflow-cp1
9- - workflow-cp2-1
10- - workflow-cp2-2
11- - workflow-cp3
12- - workflow-cp4
13- - workflow-cp5
14- - ops-precision-standard
15- - ascendc-blaze-best-practice
16- - ascendc-docs-search
17----
18- 
19-# 验收角色
20- 
21-## 身份定位
22- 
23-质量把关者。在各 CP 点对上游交付件做验收:加载对应的验收标准 Skill,按其给定的可判定指标客观裁定通过与否,产出验收报告或用户确认问卷。只验收,不产出代码 / 测试 / 文档等被验收对象。
24- 
25-## 职责
26- 
27-你以验收结论与报告为产物,按收到的验收任务加载对应 Skill 执行:
28- 
29-- **收到某 CP 点的验收任务时**:加载该 CP 点对应的 `workflow-cp*` Skill,按其规定的验收对象、通过指标与判定方式执行验收。
30-- **可机器判定的验收**(精度比对、用例执行、校验项核对等):按 Skill 指标客观裁定,产出验收报告。
31-- **需用户确认的验收**:按 Skill 给定的问卷模板生成问卷 json,用会话问卷工具(opencode `question` / claude `AskUserQuestion` / dsh `ask_user_question` / trae `AskUserQuestion`)直接发送给用户并收集结论,用户结论作为验收结果。**原样发送、原样保存**:不得擅自改动问卷模板内容,问卷条目内容必须完全依据输入件(验收对象文档)填写,不得脱离输入件自行总结结论或另行采集信息;发出的问卷与用户回复成对落盘 `questionnaires/`(回复记为问卷同名 `.reply.json`)。
32-- **插件流程内的验收**:按下发任务给定的验收对象与标准执行(如回归门禁复核、CI/检视状态核对)。
33-- **验收不通过时**:产出结构化修改意见——问题定位 + 问题语义归属(归属于需求 / 开发方案 / 算子实现等),供上游按流程回退。
34- 
35-验收报告、问卷 json 与用户回复写入 `.cannbot` 目录。你只对当前 CP 点传入的验收对象负责,不感知它在更大流程中的前后位置。
36- 
37-## 能做什么 / 不能做什么
38- 
39-能做:
40- 
41-- 加载对应 `workflow-cp*` Skill,按其指标执行验收判定。
42-- 执行验收所需的只读动作:运行测试、比对精度、核对校验项、审阅变更文件。
43-- 产出验收报告、用户确认问卷 json(直接发送用户并收集结论)、结构化修改意见。
44-- 做问题定位(复现、缩小范围、给出根因与证据)。
45- 
46-不能做:
47- 
48-- 不修改被验收对象(代码、测试、设计文档)。
49-- 不执行开发动作,不替上游修复问题——发现问题返回修改意见,由对应角色去改。
50-- 不凭主观印象裁定,验收结论必须落在 Skill 给定的可判定指标上。
51-- 问卷任务不改动问卷模板内容,不脱离输入件自行总结或采集,不代替用户作答。
52-- 任务的执行方与验收方须为不同实例:不验收由你自己产出的交付件。
53- 
54-## 写权限声明
55- 
56-- **可写目录**:`.cannbot` 目录。
57-- **可写文件类型**:md 文件(验收报告、检视结论)+ json 文件(用户确认问卷与回复)。
58-- 不写代码目录、test 目录、doc 目录等最终交付物目录。
59- 
60-## 依据什么
61- 
62-- **验收标准**:加载对应的 `workflow-cp*` Skill(各 CP 点的验收对象、通过指标、判定方式、不通过时的修改意见格式),按其标准执行。
63-- **精度容差**:`ops-precision-standard`(精度类验收的容差依据)。
64-- **验收报告模板**:`workflow-doc-templates`(按其模板组织验收报告)。
65- 
66-以上均读取对应 skill 原文获取最新内容。
67- 
68-## 修改不越权
69- 
70-- 严格按 `workflow-cp*` Skill 给定的指标验收,不自行放宽或收紧标准。
71-- 定位到的问题若根因在上游设计(架构、Tiling / 切分、接口等),只给定位结论并标注问题归属,不自行改动上游决策。
72-- 验收结论与修改意见交回上游,由其按流程处理回退,你不直接触发或跳过流程环节。
@@ -1,267 +0,0 @@
1-#!/bin/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-# CANNBot Agent Workspace Initialization Script
13-#
14-# CANNBot: https://gitcode.com/cann/cannbot
15-# This file: https://gitcode.com/cann/cannbot/blob/main/plugins/ops-direct-invoke/example/init.sh
16- 
17-set -e
18- 
19-# ============================================================
20-# Quick Start content (shown after a successful install).
21-# Customize this block for your repo. $CLI_NAME is resolved at
22-# runtime from the target tool chosen by the user (see --help).
23-# ============================================================
24-show_quick_start() {
25- echo ""
26- echo -e " ${BOLD}Quick Start:${NC}"
27- echo -e " ${CYAN}1.${NC} 启动 CLI: ${GREEN}${CLI_NAME}${NC}"
28- echo -e " ${CYAN}2.${NC} 告诉 CANNBot: ${GREEN}${BOLD}帮我开发一个 abs 算子,支持 float16,shape 主要是 [1,128]、[4,2048]${NC}"
29-}
30- 
31-# ============================================================
32-# Configuration
33-# ============================================================
34-CANNBOT_URL="https://gitcode.com/cann/cannbot.git"
35-PLUGIN_NAME="ops-direct-invoke"
36- 
37-# ============================================================
38-# Terminal output helpers
39-# ============================================================
40-if [ -t 1 ]; then
41- GREEN='\033[0;32m'; YELLOW='\033[0;33m'; RED='\033[0;31m'
42- CYAN='\033[0;36m'; BOLD='\033[1m'; DIM='\033[2m'; NC='\033[0m'
43-else
44- GREEN=''; YELLOW=''; RED=''; CYAN=''; BOLD=''; DIM=''; NC=''
45-fi
46- 
47-ok() { echo -e " ${DIM}${GREEN}✓${NC}${DIM} $*${NC}"; }
48-warn() { echo -e " ${YELLOW}⚠${NC}${DIM} $*${NC}"; }
49-err() { echo -e " ${RED}✗${NC}${DIM} $*${NC}"; }
50-info() { echo -e " ${DIM}${CYAN}→${NC}${DIM} $*${NC}"; }
51-step() { echo -e "${DIM}$*${NC}"; }
52- 
53-# ============================================================
54-# Base plugin init.sh path resolution & tools passthrough
55-# ============================================================
56-# Resolve base plugin init.sh path from SKILLS_REPO (no clone here).
57-# Echoes the path if found, empty otherwise.
58-resolve_base_init() {
59- if [ -n "${SKILLS_REPO:-}" ] && [ -f "${SKILLS_REPO}/plugins/${PLUGIN_NAME}/init.sh" ]; then
60- echo "${SKILLS_REPO}/plugins/${PLUGIN_NAME}/init.sh"
61- fi
62-}
63- 
64-# Query supported tools from the base plugin init (透传基类 --list-tools 输出).
65-# Falls back to a hint when the base is not yet available (e.g. first run,
66-# no cache, offline). The fallback intentionally does NOT hardcode tool names.
67-query_supported_tools() {
68- local base_init tools
69- base_init="$(resolve_base_init)"
70- if [ -n "${base_init}" ]; then
71- tools="$(bash "${base_init}" --list-tools 2>/dev/null)" || tools=""
72- if [ -n "${tools}" ]; then
73- echo "${tools}"
74- return
75- fi
76- fi
77- echo "(运行一次 init 或通过 --repo cannbot:<path> 指定后,此列表由基类 init 动态提供)"
78-}
79- 
80-# ============================================================
81-# Usage
82-# ============================================================
83-show_help() {
84- local tools
85- tools="$(query_supported_tools)"
86- cat << EOF
87-CANNBot Agent Workspace Initialization Script
88- 
89-Usage:
90- ./init.sh <target> [options]
91- 
92-Arguments:
93- target Target environment. Supported (from base plugin): ${tools}
94- 
95-Options:
96- -h, --help Show this help message
97- --repo <name>:<path> Use a local repository instead of cloning.
98- Supported names:
99- cannbot - plugin orchestration repo (consumed here)
100- asc-devkit / cann-samples / ops-tensor
101- - passed through to the base plugin
102- 
103-Examples:
104- ./init.sh <target> --repo cannbot:~/cannbot
105- ./init.sh <target> --repo asc-devkit:~/asc-devkit --repo cann-samples:~/cann-samples
106- (target = any tool in the list above, e.g. opencode)
107-EOF
108-}
109- 
110-# ============================================================
111-# Parse arguments (collect -h without exiting; defer help display
112-# until SKILLS_REPO is resolved so the tools list can be queried)
113-# ============================================================
114-HELP_REQUESTED=false
115-TARGET_ENV=""
116-CANNBOT_LOCAL_PATH=""
117-REPO_ARGS=()
118- 
119-while [[ $# -gt 0 ]]; do
120- case "$1" in
121- -h|--help)
122- HELP_REQUESTED=true; shift ;;
123- --repo)
124- if [[ -z "${2:-}" ]] || [[ "$2" != *:* ]]; then
125- err "--repo requires name:/path argument, got: '${2:-}'"
126- exit 1
127- fi
128- repo_name="${2%%:*}"
129- repo_path="${2#*:}"
130- case "$repo_name" in
131- cannbot|asc-devkit|cann-samples|ops-tensor) ;;
132- *)
133- err "Unknown repo name '$repo_name' " \
134- "(valid: cannbot / asc-devkit / cann-samples / ops-tensor)"
135- exit 1
136- ;;
137- esac
138- if [ ! -d "$repo_path" ]; then
139- err "Repo path not found: $repo_path (--repo $repo_name)"
140- exit 1
141- fi
142- if [[ "$repo_name" == "cannbot" ]]; then
143- CANNBOT_LOCAL_PATH="$repo_path"
144- else
145- REPO_ARGS+=("--repo" "$2")
146- fi
147- shift 2
148- ;;
149- -*)
150- err "Unknown option: '$1'"
151- echo ""
152- show_help
153- exit 1
154- ;;
155- *)
156- if [ -z "$TARGET_ENV" ]; then
157- TARGET_ENV="$1"; shift
158- else
159- err "Unexpected argument: '$1'"
160- exit 1
161- fi
162- ;;
163- esac
164-done
165- 
166-if [ "$HELP_REQUESTED" = false ] && [ -z "$TARGET_ENV" ]; then
167- err "Missing required argument: target (run ./init.sh --help to list supported tools)"
168- echo ""
169- show_help
170- exit 1
171-fi
172- 
173-# ============================================================
174-# Resolve paths
175-# ============================================================
176-SCRIPT_DIR="$(dirname "$(realpath "$0")")"
177-AGENT_DIR="${SCRIPT_DIR}"
178-REPO_DIR="$(realpath "${SCRIPT_DIR}/..")"
179-WORKSPACE_NAME="$(basename "$REPO_DIR")"
180- 
181-# Determine cannbot repository location (path only; clone happens later)
182-if [ -n "$CANNBOT_LOCAL_PATH" ]; then
183- CANNBOT_LOCAL_PATH="$(realpath "$CANNBOT_LOCAL_PATH" 2>/dev/null || echo "$CANNBOT_LOCAL_PATH")"
184- if [ ! -d "$CANNBOT_LOCAL_PATH" ]; then
185- err "cannbot directory not found: $CANNBOT_LOCAL_PATH"
186- exit 1
187- fi
188- SKILLS_REPO="$CANNBOT_LOCAL_PATH"
189-else
190- SKILLS_REPO="$REPO_DIR/.cannbot/cannbot"
191-fi
192- 
193-# ============================================================
194-# Help mode: show help immediately, no side effects.
195-# Tools list is queried only from an already-available SKILLS_REPO;
196-# if the base is not present (first run / offline), show the fallback
197-# hint. Help must not create directories or trigger git clone.
198-# ============================================================
199-if [ "$HELP_REQUESTED" = true ]; then
200- show_help
201- exit 0
202-fi
203- 
204-# ============================================================
205-# Display configuration
206-# ============================================================
207-echo ""
208-echo -e " ${BOLD}${WORKSPACE_NAME} agent${NC}"
209-echo -e " ${BOLD}Configuration:${NC}"
210-echo -e " target env: ${CYAN}${TARGET_ENV}${NC}"
211-echo -e " workspace: ${CYAN}${WORKSPACE_NAME}${NC}"
212-echo -e " repo root: ${CYAN}${REPO_DIR}${NC}"
213-if [ -n "$CANNBOT_LOCAL_PATH" ]; then
214- echo -e " cannbot: ${CYAN}${CANNBOT_LOCAL_PATH}${NC} (local)"
215-else
216- echo -e " cannbot: ${CYAN}clone from ${CANNBOT_URL}${NC}"
217-fi
218-echo ""
219- 
220-# ============================================================
221-# Step 1: Setup cannbot
222-# ============================================================
223-step "Setting up cannbot..."
224-if [ -n "$CANNBOT_LOCAL_PATH" ]; then
225- ok "Using local cannbot at $SKILLS_REPO"
226-else
227- if [ -d "$SKILLS_REPO/.git" ]; then
228- git -C "$SKILLS_REPO" pull --quiet 2>/dev/null || true
229- ok "cannbot updated (local cache)"
230- else
231- mkdir -p "$(dirname "$SKILLS_REPO")"
232- if git clone --quiet "$CANNBOT_URL" "$SKILLS_REPO" 2>/dev/null; then
233- ok "cannbot cloned from $CANNBOT_URL"
234- else
235- err "Failed to clone cannbot from $CANNBOT_URL"
236- exit 1
237- fi
238- fi
239-fi
240-echo ""
241- 
242-# ============================================================
243-# Step 2: Invoke base plugin init.sh
244-# ============================================================
245-PLUGIN_INIT="$SKILLS_REPO/plugins/${PLUGIN_NAME}/init.sh"
246- 
247-if [ ! -f "$PLUGIN_INIT" ]; then
248- err "Plugin init.sh not found at: $PLUGIN_INIT"
249- exit 1
250-fi
251- 
252-PLUGIN_ARGS=("${TARGET_ENV}" "$REPO_DIR" "--override" "$AGENT_DIR")
253-if [[ ${#REPO_ARGS[@]} -gt 0 ]]; then
254- PLUGIN_ARGS+=("${REPO_ARGS[@]}")
255-fi
256- 
257-bash "$PLUGIN_INIT" "${PLUGIN_ARGS[@]}" || {
258- err "Plugin '${PLUGIN_NAME}' init failed"
259- exit 1
260-}
261- 
262-# ============================================================
263-# Step 3: Quick Start (子仓定制;基类在 --override 时不输出)
264-# ============================================================
265-CLI_NAME="$TARGET_ENV"
266-show_quick_start
267-echo ""
@@ -1,244 +0,0 @@
1-#!/usr/bin/env node
2-// Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3-// This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4-// CANN Open Software License Agreement Version 2.0 (the "License").
5-// Please refer to the License for details. You may not use this file except in compliance with the License.
6-// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7-// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8-// See LICENSE in the root of the software repository for the full text of the License.
9- 
10-// ---------------------------------------------------------------------------
11-// permission-guard —— Claude Code 侧动态权限 hook
12-//
13-// 机制(Claude Code PreToolUse hook):
14-// hook 配置在 .claude/settings.json,matcher 命中写类工具时本脚本被调用,
15-// 事件 JSON 经 stdin 传入;其中 agent_type 字段标识当前子 Agent 名
16-// (主线程无该字段,即 PM)。据此对写类工具做按角色限权。
17-//
18-// 违规 → exit 2(阻断本次调用,stderr 原因回传模型);放行 → exit 0 且无输出。
19-//
20-// 配置来源(按角色分开文件):
21-// <项目根>/.cannbot/permissions/*.js —— 每角色一文件,ESM export default
22-// { categories, exts }。文件名即角色名(去 .js),如 developer-code.js。
23-// 由 init.sh Step 4.5 从 skills/workflow-agent-permissions/hooks/
24-// 整体复制生成;子仓 override 该 skill 时自动生效。
25-// 配置文件由 init 从工作流受控模板生成,与 hook 同属一套信任域;
26-// 本脚本以文本求值方式读取(兼容各 Node 版本,不依赖 ESM 加载)。
27-//
28-// 每次调用重新加载配置(hook 为一次性进程,天然支持热更新)。
29-// PM 启动闸口负责检测目录异常并阻断任务派发。
30-//
31-// ★ 以下 CONFIG 为工作流级约定,不暴露给仓,改这里即可。★
32-// ★ 与 hooks/opencode/permission-guard.js 保持同一套规则语义。★
33-// ---------------------------------------------------------------------------
34- 
35-"use strict"
36- 
37-const { readdirSync, readFileSync } = require("node:fs")
38-const { join, relative, resolve, sep, isAbsolute } = require("node:path")
39- 
40-// 视为主 Agent(PM) 的情形:主线程 hook 输入无 agent_type 字段;
41-// 经 `claude --agent` 以 PM 身份启动时 agent_type 为 PM/pm。
42-const PRIMARY_AGENTS = ["PM", "pm"]
43- 
44-// 未知角色(未在规则表中命中)策略:allow-warn | allow | deny
45-// deny:规则表已枚举全部角色,未命中即为配置异常或越权调用;
46-// 且 .cannbot 写入在分类阶段已短路放行,deny 只影响代码/测试/文档目录。
47-const UNKNOWN_ROLE_POLICY = "deny"
48- 
49-// 只对这些写类工具限权,其余工具一律放行(Claude Code 工具名)
50-const GUARDED_TOOLS = ["write", "edit", "multiedit", "notebookedit"]
51- 
52-// 静默模式(.cannbot/settings.json 的 mode=silent)下拦截的询问类工具。
53-// 拦截问卷发送是机制兜底;正常流程下 QA 已按静默默认决策执行(prompt 层约束)。
54-// 按**子串**匹配工具名(小写后),覆盖 AskUserQuestion 等带前后缀的命名。
55-const SILENT_GUARDED_TOOLS = ["question", "ask"]
56- 
57-// 中间产物区:锚定项目根,只认根下的 .cannbot。
58-// 不参与下方段级匹配——否则代码树里任意一个同名目录都会拿到
59-// 「所有角色可写、不限文件类型」的短路放行,成为越权口子。
60-const INTERMEDIATE_DIR = ".cannbot"
61- 
62-// 其余路径分类:按相对项目根路径的**目录段**命中(段名需完全相等)。
63-// 用段级匹配而非前缀匹配——测试/文档目录未必在顶层、也未必是单数形式
64-// (如 <工程目录>/tests/),前缀匹配会把它们兜底成 code,
65-// 使测试角色写不了自己的目录。code 为兜底类别(无目录段命中者)。
66-const CATEGORY_DIR_NAMES = {
67- test: ["test", "tests"],
68- doc: ["doc", "docs"],
69-}
70- 
71-// 内置默认值(防御性兜底,正常流程不可达)。
72-// L8 约束:必须与 skills/workflow-agent-permissions/hooks/*.js 保持同步。
73-const DEFAULT_RULES = {
74- PM: { categories: [], exts: "*" }, // 只写 .cannbot
75- architect: { categories: [], exts: "*" }, // 只写 .cannbot
76- qa: { categories: [], exts: "*" }, // 只写 .cannbot
77- developer: { categories: ["code", "test", "doc"], exts: "*" },
78- "developer-code": { categories: ["code"], exts: "*" },
79- "developer-test": { categories: ["test"], exts: "*" },
80- "developer-doc": { categories: ["code", "test", "doc"], exts: [".md"] }, // 各目录 md 文档
81-}
82- 
83-// 解析单个角色配置文件:提取 `export default { ... }` 的对象字面量并求值。
84-// 失败返回 null,外层跳过该文件。
85-function parseRuleFile(path) {
86- const text = readFileSync(path, "utf8")
87- const m = text.match(/export\s+default\s*([\s\S]*?);?\s*$/)
88- if (!m) return null
89- return new Function(`"use strict"; return (${m[1]})`)()
90-}
91- 
92-// 加载 .cannbot/permissions/*.js,按文件名(去 .js)建立角色规则。
93-// 目录缺失或为空 → 返回 null,外层回退到内置默认值。
94-function loadConfig(projectRoot) {
95- const dir = join(projectRoot, ".cannbot", "permissions")
96- const agents = {}
97- let files
98- try {
99- files = readdirSync(dir)
100- } catch {
101- return null
102- }
103- for (const f of files) {
104- if (!f.endsWith(".js")) continue
105- const role = f.slice(0, -3)
106- try {
107- const data = parseRuleFile(join(dir, f))
108- if (data && typeof data === "object") {
109- agents[role] = {
110- categories: Array.isArray(data.categories) ? data.categories : [],
111- exts: data.exts !== undefined ? data.exts : "*",
112- }
113- }
114- } catch (e) {
115- console.error(`[permission-guard] load ${f} failed: ${e.message}`)
116- }
117- }
118- return Object.keys(agents).length > 0 ? agents : null
119-}
120- 
121-// 相对项目根的 POSIX 风格路径(统一分隔符、去掉 ./ 前缀)
122-function relPosix(projectRoot, filePath) {
123- let rel = relative(projectRoot, filePath)
124- if (sep !== "/") rel = rel.split(sep).join("/")
125- return rel
126-}
127- 
128-// 判定路径类别;写到项目根之外(以 .. 开头)返回 "external"
129-function classify(rel, categoryDirNames) {
130- if (rel.startsWith("../") || rel === "..") return "external"
131- if (rel === INTERMEDIATE_DIR || rel.startsWith(INTERMEDIATE_DIR + "/")) return "intermediate"
132- const dirs = rel.split("/").slice(0, -1) // 末段是文件名,不参与目录段匹配
133- for (const [cat, names] of Object.entries(categoryDirNames)) {
134- if (dirs.some((d) => names.includes(d))) return cat
135- }
136- return "code" // 兜底:其余视为代码目录
137-}
138- 
139-function extOf(rel) {
140- const base = rel.split("/").pop() || ""
141- const dot = base.lastIndexOf(".")
142- return dot >= 0 ? base.slice(dot).toLowerCase() : ""
143-}
144- 
145-function deny(reason) {
146- // exit 2:阻断本次工具调用,stderr 内容回传给模型
147- console.error(`[permission-guard] ${reason}`)
148- process.exit(2)
149-}
150- 
151-// 读取 .cannbot/settings.json 的静默开关(hook 为一次性进程,天然实时;
152-// 读失败按非静默处理,避免误伤)
153-function readSilentMode(projectRoot) {
154- try {
155- const data = JSON.parse(
156- readFileSync(join(projectRoot, ".cannbot", "settings.json"), "utf8"),
157- )
158- return data && data.mode === "silent"
159- } catch {
160- return false
161- }
162-}
163- 
164-function main() {
165- const raw = readFileSync(0, "utf8") // stdin
166- 
167- let input
168- try {
169- input = JSON.parse(raw)
170- } catch {
171- return // 输入异常不拦(避免误伤)
172- }
173- 
174- const tool = (input.tool_name || "").toLowerCase()
175- 
176- // 静默模式:拦截问卷发送(任何角色都不得绕过)
177- if (SILENT_GUARDED_TOOLS.some((t) => tool.includes(t))) {
178- const projectRoot = process.env.CLAUDE_PROJECT_DIR || input.cwd || process.cwd()
179- if (readSilentMode(projectRoot)) {
180- deny(
181- "静默模式已启用,问卷发送被拦截:请按静默默认决策执行——不发送问卷,落盘 " +
182- '.reply.json({"mode":"silent","decision":"accepted"});如需恢复交互,请让用户关闭静默模式。',
183- )
184- }
185- return
186- }
187- 
188- if (!GUARDED_TOOLS.includes(tool)) return // 非写类工具放行
189- 
190- const toolInput = input.tool_input || {}
191- const rawPath = toolInput.file_path ?? toolInput.notebook_path
192- if (!rawPath) return // 拿不到路径,不拦(避免误伤)
193- 
194- const projectRoot = process.env.CLAUDE_PROJECT_DIR || input.cwd || process.cwd()
195- // 相对路径按会话工作目录解析后再分类:直接放行会让相对路径成为绕过口子
196- const filePath = isAbsolute(rawPath) ? rawPath : resolve(input.cwd || projectRoot, rawPath)
197- const rel = relPosix(projectRoot, filePath)
198- const cat = classify(rel, CATEGORY_DIR_NAMES)
199- 
200- // .cannbot(中间产物区)所有角色均可写,任意文件类型——短路放行。
201- // 写哪、怎么命名由任务下发时约定,不在此卡。
202- if (cat === "intermediate") return
203- 
204- const fileRules = loadConfig(projectRoot)
205- const rules = fileRules ? { ...DEFAULT_RULES, ...fileRules } : { ...DEFAULT_RULES }
206- 
207- // 主线程(无 agent_type)视为 PM
208- const agent = input.agent_type || null
209- const role = agent && PRIMARY_AGENTS.includes(agent) ? "PM" : agent ?? "PM"
210- const rule = rules[role]
211- 
212- // 未知角色(未命中规则表)
213- if (!rule) {
214- if (UNKNOWN_ROLE_POLICY === "deny") {
215- deny(`未知角色 ${agent ?? "?"} 无写权限:${rel}`)
216- }
217- if (UNKNOWN_ROLE_POLICY === "allow-warn") {
218- console.error(`[permission-guard] 未知角色放行(告警): agent=${agent ?? "?"} tool=${tool} path=${rel}`)
219- }
220- return // allow / allow-warn
221- }
222- 
223- const hint =
224- role === "PM"
225- ? " 请将此操作派发给对应的子 Agent 执行,PM 只负责调度,不直接执行。"
226- : " 如果无此权限无法完成当前任务,请立即结束任务并向主 Agent 上报。"
227- 
228- // 目录类别校验
229- if (!rule.categories.includes(cat)) {
230- deny(
231- `角色 ${role} 无权写入 ${cat} 目录:${rel}(可写类别:${rule.categories.join("/")}${hint})`,
232- )
233- }
234- // 文件类型校验
235- if (rule.exts !== "*") {
236- const e = extOf(rel)
237- if (!rule.exts.includes(e)) {
238- deny(`角色 ${role} 只能写 ${rule.exts.join("/")} 类型,拒绝:${rel}${hint}`)
239- }
240- }
241- // 通过:exit 0 且无输出
242-}
243- 
244-main()
@@ -1,12 +0,0 @@
1-name = "architect"
2-description = "方案设计角色。负责设计算子开发方案与测试方案,产出设计类文档。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical architect role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/architect.toml` (project scope) or
7-`~/.codex/agents/architect.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,12 +0,0 @@
1-name = "developer-code"
2-description = "算子代码开发角色。负责实现算子代码、编译验证、问题定位。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical developer-code role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/developer-code.toml` (project scope) or
7-`~/.codex/agents/developer-code.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,12 +0,0 @@
1-name = "developer-doc"
2-description = "文档编写角色。负责算子使用文档、开发报告、经验总结的编写。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical developer-doc role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/developer-doc.toml` (project scope) or
7-`~/.codex/agents/developer-doc.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,12 +0,0 @@
1-name = "developer-test"
2-description = "测试代码开发角色。负责 golden 实现、功能用例、性能采集框架、白盒测试补全。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical developer-test role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/developer-test.toml` (project scope) or
7-`~/.codex/agents/developer-test.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,12 +0,0 @@
1-name = "developer"
2-description = "综合开发角色。负责跨代码、测试、文档的开发与修复任务。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical developer role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/developer.toml` (project scope) or
7-`~/.codex/agents/developer.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,12 +0,0 @@
1-name = "qa"
2-description = "验收角色。负责算子开发各 CP 点的验收,加载对应的 workflow-cp* Skill 完成判定,产出验收报告与用户确认问卷。"
3-developer_instructions = """
4-This is the Codex adapter for the canonical qa role definition.
5-Before starting any task, locate this config at
6-`.codex/agents/qa.toml` (project scope) or
7-`~/.codex/agents/qa.toml` (user scope), resolve the symlink target,
8-then read the canonical Markdown file at __CANNBOT_AGENT_SOURCE__.
9-Follow that file as your complete role instructions.
10-Also follow the applicable repository AGENTS.md.
11-Do not replace or reinterpret the canonical instructions.
12-"""
@@ -1,209 +0,0 @@
1-#!/bin/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-# DSH(DeepSeek Harness)部署级权限守卫安装器
13-#
14-# 背景:dsh 无「项目级、文件驱动的 hook」机制(opencode .opencode/plugin/、
15-# claude .claude/hooks/ 在 dsh 中不存在),init.sh 无法在项目层挂载
16-# permission-guard。但 dsh 有**部署级** Cordis 插件机制:本脚本把
17-# permission-guard.js 复制到 $DSH_HOME/plugins/,并在 $DSH_HOME/cordis.patch.yml
18-# (home 级 patch 层,对所有 profile 生效,watchUserPatches 支持热加载)
19-# 幂等注册插件条目。安装后:
20-# - 角色写权限隔离恢复机制保证(tools/pre-execute allow/deny 门)
21-# - 静默模式问卷拦截恢复机制兜底(.cannbot/settings.json mode=silent)
22-# - 仅在 ops-direct-invoke 初始化的工作区(cwd 下有 .cannbot/permissions/)生效,
23-# 其它项目不受影响
24-#
25-# 用法:
26-# install.sh # 安装(交互确认)
27-# install.sh --yes # 安装(跳过确认)
28-# install.sh --remove # 卸载(移除 patch 条目,保留插件文件)
29-# install.sh --remove --yes # 卸载(跳过确认)
30-# install.sh --dsh-home <dir> # 指定 DSH_HOME(默认 ${DSH_HOME:-~/.dsh})
31-#
32-# 生效方式:patch 文件变更后 dsh 会热加载(watchUserPatches/HMR);未生效时
33-# 重启 dsh 会话即可。可用 `dsh --dump-config` 校验条目已入组合树。
34-#
35-# patch 条目格式说明(与 dsh 的 applyEntryPatches 语义一致):
36-# dsh 的用户 patch 层是对空 entry list 应用补丁——**新增条目必须用
37-# `insert:` 包装**,裸 `id: xxx / name: xxx` 条目会因 id 不存在被丢弃。
38-# 模块名用**绝对路径**(相对路径按 include 的 baseUrl=profile 目录解析,
39-# 与 $DSH_HOME 不一致,会导致加载失败)。
40- 
41-set -e
42- 
43-show_help() {
44- sed -n '24,38p' "$0" | sed 's/^# \{0,1\}//'
45-}
46- 
47-SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
48-PLUGIN_SRC="${SCRIPT_DIR}/permission-guard.js"
49-ENTRY_ID="cannbot-permission-guard"
50- 
51-DO_REMOVE=false
52-ASSUME_YES=false
53-DSH_HOME_DIR="${DSH_HOME:-${HOME}/.dsh}"
54- 
55-while [ $# -gt 0 ]; do
56- case "$1" in
57- --remove) DO_REMOVE=true; shift ;;
58- --yes|-y) ASSUME_YES=true; shift ;;
59- --dsh-home) DSH_HOME_DIR="$2"; shift 2 ;;
60- --dsh-home=*) DSH_HOME_DIR="${1#*=}"; shift ;;
61- --help|-h) show_help; exit 0 ;;
62- *) echo "unknown option: $1" >&2; exit 1 ;;
63- esac
64-done
65- 
66-if [ ! -f "${PLUGIN_SRC}" ]; then
67- echo "✗ plugin source not found: ${PLUGIN_SRC}" >&2
68- exit 1
69-fi
70- 
71-PATCH_FILE="${DSH_HOME_DIR}/cordis.patch.yml"
72-PLUGIN_DIR="${DSH_HOME_DIR}/plugins"
73-PLUGIN_DST="${PLUGIN_DIR}/cannbot-permission-guard.js"
74-# 模块名用绝对路径:dsh 的相对 name 按 include 的 baseUrl(profile 目录)解析,
75-# 与 $DSH_HOME 不一致;绝对路径不依赖解析基准(移动 DSH_HOME 后重装即可)。
76-ENTRY_NAME="${PLUGIN_DST}"
77- 
78-echo "DSH home: ${DSH_HOME_DIR}"
79-echo "Patch file: ${PATCH_FILE}"
80-echo "Plugin dst: ${PLUGIN_DST}"
81- 
82-confirm() {
83- if [ "${ASSUME_YES}" = true ]; then
84- return 0
85- fi
86- printf "继续? [Y/n] "
87- read -r ans
88- case "${ans}" in
89- [Nn]*) return 1 ;;
90- *) return 0 ;;
91- esac
92-}
93- 
94-# 整块删除 insert 条目:`- insert:` 起始、缩进的子条目,直到下一个顶格行。
95-# 仅当块内含目标 ENTRY_ID 时删除整块(含 insert 包装),避免留下 YAML 残渣。
96-remove_entry_block() {
97- awk -v id="${ENTRY_ID}" '
98- /^[[:space:]]*-[[:space:]]*insert:[[:space:]]*$/ {
99- block = $0 "\n"
100- in_block = 1
101- has_id = 0
102- next
103- }
104- in_block && /^[[:space:]]/ {
105- block = block $0 "\n"
106- if ($0 ~ ("id:[[:space:]]*" id "$")) has_id = 1
107- next
108- }
109- in_block {
110- if (has_id) skip = 1
111- in_block = 0
112- if (!skip) printf "%s", block
113- skip = 0
114- block = ""
115- }
116- { print }
117- END {
118- if (in_block) {
119- if (!has_id) printf "%s", block
120- }
121- }
122- ' "${1}" > "${1}.tmp" && mv "${1}.tmp" "${1}"
123-}
124- 
125-# ------------------------------------------------------------
126-# 卸载
127-# ------------------------------------------------------------
128-if [ "${DO_REMOVE}" = true ]; then
129- if [ ! -f "${PATCH_FILE}" ]; then
130- echo "✓ 未安装(patch 文件不存在)"
131- exit 0
132- fi
133- if ! grep -q "id: ${ENTRY_ID}" "${PATCH_FILE}" 2>/dev/null; then
134- echo "✓ 未安装(patch 中无 ${ENTRY_ID} 条目)"
135- exit 0
136- fi
137- if ! confirm; then
138- echo "已取消"
139- exit 0
140- fi
141- cp -a "${PATCH_FILE}" "${PATCH_FILE}.bak.$(date +%Y%m%d_%H%M%S)"
142- remove_entry_block "${PATCH_FILE}"
143- # 空文件/纯注释收尾为合法空 patch 层([])
144- if ! grep -qE "^- |^[^#[:space:]]" "${PATCH_FILE}" 2>/dev/null; then
145- printf '[]\n' > "${PATCH_FILE}"
146- fi
147- echo "✓ 已从 ${PATCH_FILE} 移除 ${ENTRY_ID}(原文件已备份)"
148- echo " 插件文件仍保留在 ${PLUGIN_DST};如需彻底删除请手动执行 rm"
149- echo " 建议用 \`dsh --dump-config\` 确认条目已从组合树消失"
150- exit 0
151-fi
152- 
153-# ------------------------------------------------------------
154-# 安装
155-# ------------------------------------------------------------
156-if [ -f "${PATCH_FILE}" ] && grep -q "id: ${ENTRY_ID}" "${PATCH_FILE}" 2>/dev/null; then
157- echo "✓ 已安装(patch 中已有 ${ENTRY_ID} 条目,跳过)"
158- if [ ! -f "${PLUGIN_DST}" ]; then
159- echo " ⚠ 但插件文件缺失,重新复制…"
160- mkdir -p "${PLUGIN_DIR}"
161- cp "${PLUGIN_SRC}" "${PLUGIN_DST}"
162- echo " ✓ ${PLUGIN_DST}"
163- fi
164- exit 0
165-fi
166- 
167-if ! confirm; then
168- echo "已取消"
169- exit 0
170-fi
171- 
172-mkdir -p "${PLUGIN_DIR}"
173-cp "${PLUGIN_SRC}" "${PLUGIN_DST}"
174-echo "✓ 插件已复制: ${PLUGIN_DST}"
175- 
176-# insert 条目块(dsh patch 层新增条目的唯一合法格式)
177-entry_block() {
178- cat << EOF
179-- insert:
180- - id: ${ENTRY_ID}
181- name: ${ENTRY_NAME}
182-EOF
183-}
184- 
185-if [ ! -f "${PATCH_FILE}" ]; then
186- # 新建 home 级 patch 层(顶层 YAML 数组,含一个 insert 条目)
187- mkdir -p "$(dirname "${PATCH_FILE}")"
188- {
189- cat << 'EOF'
190-# DeepSeek Harness user patch layer (home level, applied after every profile's
191-# bundle layers). Generated by cannbot ops-direct-invoke hooks/dsh/install.sh.
192-EOF
193- entry_block
194- } > "${PATCH_FILE}"
195- echo "✓ 已创建 ${PATCH_FILE} 并注册 ${ENTRY_ID}"
196-else
197- # 备份后追加 insert 条目块(幂等;保留既有内容)
198- cp -a "${PATCH_FILE}" "${PATCH_FILE}.bak.$(date +%Y%m%d_%H%M%S)"
199- if [ -n "$(tail -c 1 "${PATCH_FILE}")" ]; then
200- echo "" >> "${PATCH_FILE}"
201- fi
202- entry_block >> "${PATCH_FILE}"
203- echo "✓ 已追加 ${ENTRY_ID} 到 ${PATCH_FILE}(原文件已备份)"
204-fi
205- 
206-echo ""
207-echo "生效方式:dsh 会热加载用户 patch 层(watchUserPatches);若当前会话未生效,"
208-echo "重启 dsh 会话即可。可用 \`dsh --dump-config\` 校验条目已入组合树。"
209-echo "卸载: ${0} --remove"
@@ -1,332 +0,0 @@
1-// Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
2-// This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-// CANN Open Software License Agreement Version 2.0 (the "License").
4-// Please refer to the License for details. You may not use this file except in compliance with the License.
5-// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6-// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7-// See LICENSE in the root of the software repository for the full text of the License.
8- 
9-// ---------------------------------------------------------------------------
10-// permission-guard —— dsh(DeepSeek Harness)侧部署级权限守卫(Cordis 插件)
11-//
12-// 与 hooks/opencode/permission-guard.js、hooks/claude/permission-guard.js 同一套
13-// 规则语义(L8 约束:内置默认值与 workflow-agent-permissions skill 同步),
14-// 挂载点不同:
15-// opencode → <install>/.opencode/plugin/(项目级,init 链接)
16-// claude → <install>/.claude/hooks/ + settings.json 注册(项目级,init 链接)
17-// dsh → $DSH_HOME/cordis.patch.yml(home 级 patch 层,对所有 profile 生效;
18-// 由 hooks/dsh/install.sh 安装,非 init 自动挂载)
19-//
20-// 机制(基于 dsh-tools 工具管道):
21-// tools/pre-execute 是工具调用的可扩展 allow/deny 瀑布门。本插件以全局作用域
22-// 监听该事件:违规 → 返回 { kind: "deny", reason } 短接拒绝(原因回传模型);
23-// 合规/非受管 → 调用 next() 委托后续判定(默认放行)。
24-//
25-// 工作区识别:仅当会话 cwd 下存在 .cannbot/permissions/(ops-direct-invoke init 产物)
26-// 时启用;其它工作区一律放行(本插件挂在用户 home 层,不能影响无关项目)。
27-//
28-// 角色识别:
29-// 主 Agent(session header 无 origin: "subagent")→ PM;
30-// 子 Agent → 从持久 label 解析角色。label 即 PM 派发时传入的 description,
31-// 约定必须含角色名(如「architect:需求分析」)。label 经
32-// ctx.subagents.listChildren(parentSessionId) 枚举解析(按子会话 id 匹配)。
33-// 解析失败/未知角色 → 按 UNKNOWN_ROLE_POLICY(deny)处理(.cannbot 除外)。
34-//
35-// 静默问卷拦截:.cannbot/settings.json 的 mode=silent 时,拦截问卷类工具
36-// (ask_user_question 等,按工具名子串匹配),恢复与 opencode/claude 一致的
37-// 机制兜底。
38-//
39-// 配置来源:<cwd>/.cannbot/permissions/*.js(每角色一文件,ESM export default
40-// { categories, exts }),缺失时回退内置默认值(防御兜底)。
41-// ---------------------------------------------------------------------------
42- 
43-import { readFileSync, readdirSync, statSync } from "node:fs"
44-import { isAbsolute, join, relative, resolve, sep } from "node:path"
45-import { pathToFileURL } from "node:url"
46- 
47-// 视为主 Agent(PM)的判定:session header 无 subagent origin 即主 Agent。
48-// (与 opencode 侧 PRIMARY_AGENTS 语义对齐:主会话统一按 PM 授权)
49-const PRIMARY_ROLE = "PM"
50- 
51-// 未知角色(未在规则表中命中)策略:allow-warn | allow | deny
52-// deny:规则表已枚举全部角色,未命中即为配置异常或越权调用;
53-// 且 .cannbot 写入在分类阶段已短路放行,deny 只影响代码/测试/文档目录。
54-const UNKNOWN_ROLE_POLICY = "deny"
55- 
56-// 只对这些写类工具限权,其余工具一律放行(与 opencode 侧一致;
57-// dsh 当前实际提供 write/edit,保留列表以兼容未来新增)
58-const GUARDED_TOOLS = ["write", "edit", "patch", "multiedit"]
59- 
60-// 静默模式(.cannbot/settings.json 的 mode=silent)下拦截的询问类工具。
61-// 拦截问卷发送是机制兜底;正常流程下 QA 已按静默默认决策执行(prompt 层约束)。
62-// 按**子串**匹配工具名(小写后),覆盖带前后缀的同类命名
63-// (dsh 的 ask_user_question 命中 "ask")。
64-const SILENT_GUARDED_TOOLS = ["question", "ask"]
65- 
66-// 中间产物区:锚定项目根,只认根下的 .cannbot。
67-const INTERMEDIATE_DIR = ".cannbot"
68- 
69-// 其余路径分类:按相对项目根路径的**目录段**命中(段名需完全相等)。
70-const CATEGORY_DIR_NAMES = {
71- test: ["test", "tests"],
72- doc: ["doc", "docs"],
73-}
74- 
75-// 内置默认值(防御性兜底,正常流程不可达)。
76-// L8 约束:必须与 skills/workflow-agent-permissions/hooks/*.js 保持同步。
77-const DEFAULT_RULES = {
78- PM: { categories: [], exts: "*" }, // 只写 .cannbot
79- architect: { categories: [], exts: "*" }, // 只写 .cannbot
80- qa: { categories: [], exts: "*" }, // 只写 .cannbot
81- developer: { categories: ["code", "test", "doc"], exts: "*" },
82- "developer-code": { categories: ["code"], exts: "*" },
83- "developer-test": { categories: ["test"], exts: "*" },
84- "developer-doc": { categories: ["code", "test", "doc"], exts: [".md"] }, // 各目录 md 文档
85-}
86- 
87-// 角色名 token:按最长优先排列(developer-code 必须先于 developer 匹配)
88-const ROLE_TOKEN_RE = /\b(PM|pm|architect|qa|developer-code|developer-test|developer-doc|developer)\b/
89- 
90-// ---------------------------------------------------------------------------
91-// 纯决策逻辑(与 opencode 侧逐条对齐;导出便于独立测试)
92-// ---------------------------------------------------------------------------
93- 
94-// 加载 .cannbot/permissions/*.js,按文件名(去 .js)建立角色规则。
95-// 目录缺失或为空 → 返回 null,外层回退到内置默认值。
96-export async function loadConfig(projectRoot) {
97- const dir = join(projectRoot, ".cannbot", "permissions")
98- const agents = {}
99- let files
100- try {
101- files = readdirSync(dir)
102- } catch {
103- return null
104- }
105- for (const f of files) {
106- if (!f.endsWith(".js")) continue
107- const role = f.slice(0, -3)
108- try {
109- const mod = await import(pathToFileURL(join(dir, f)).href)
110- const data = mod.default ?? mod
111- if (data && typeof data === "object") {
112- agents[role] = {
113- categories: Array.isArray(data.categories) ? data.categories : [],
114- exts: data.exts !== undefined ? data.exts : "*",
115- }
116- }
117- } catch (e) {
118- console.warn(`[permission-guard] load ${f} failed: ${e.message}`)
119- }
120- }
121- return Object.keys(agents).length > 0 ? agents : null
122-}
123- 
124-// 相对项目根的 POSIX 风格路径(统一分隔符、去掉 ./ 前缀)
125-export function relPosix(projectRoot, filePath) {
126- let rel = relative(projectRoot, filePath)
127- if (sep !== "/") rel = rel.split(sep).join("/")
128- return rel
129-}
130- 
131-// 判定路径类别;写到项目根之外(以 .. 开头)返回 "external"
132-export function classify(rel, categoryDirNames) {
133- if (rel.startsWith("../") || rel === "..") return "external"
134- if (rel === INTERMEDIATE_DIR || rel.startsWith(INTERMEDIATE_DIR + "/")) return "intermediate"
135- const dirs = rel.split("/").slice(0, -1) // 末段是文件名,不参与目录段匹配
136- for (const [cat, names] of Object.entries(categoryDirNames)) {
137- if (dirs.some((d) => names.includes(d))) return cat
138- }
139- return "code" // 兜底:其余视为代码目录
140-}
141- 
142-export function extOf(rel) {
143- const base = rel.split("/").pop() || ""
144- const dot = base.lastIndexOf(".")
145- return dot >= 0 ? base.slice(dot).toLowerCase() : ""
146-}
147- 
148-// 读取 .cannbot/settings.json 的静默开关(每次调用实时读——会话中
149-// 「关闭静默模式」后立即解除拦截;读失败按非静默处理,避免误伤)
150-export function readSilentMode(projectRoot) {
151- try {
152- const data = JSON.parse(
153- readFileSync(join(projectRoot, ".cannbot", "settings.json"), "utf8"),
154- )
155- return data && data.mode === "silent"
156- } catch {
157- return false
158- }
159-}
160- 
161-// 从持久 label(PM 派发子 Agent 的 description)解析角色名
162-export function parseRoleFromLabel(label) {
163- if (!label) return null
164- const m = String(label).match(ROLE_TOKEN_RE)
165- if (!m) return null
166- return m[1] === "pm" ? "PM" : m[1]
167-}
168- 
169-// 判定一次写类调用是否合规:返回 null = 放行,返回字符串 = 拒绝原因
170-export async function decideWrite({ projectRoot, tool, filePath, role, rules }) {
171- const rawPath = filePath
172- if (!rawPath) return null // 拿不到路径,不拦(避免误伤)
173- 
174- // 相对路径按项目根解析后再分类:直接放行会让相对路径成为绕过口子
175- const abs = isAbsolute(rawPath) ? rawPath : resolve(projectRoot, rawPath)
176- const rel = relPosix(projectRoot, abs)
177- const cat = classify(rel, CATEGORY_DIR_NAMES)
178- 
179- // .cannbot(中间产物区)所有角色均可写,任意文件类型——短路放行。
180- if (cat === "intermediate") return null
181- 
182- const rule = role ? rules[role] : null
183- 
184- // 未知角色(未命中规则表)
185- if (!rule) {
186- if (UNKNOWN_ROLE_POLICY === "deny") {
187- return `[permission-guard] 未知角色 ${role ?? "?"} 无写权限:${rel}`
188- }
189- if (UNKNOWN_ROLE_POLICY === "allow-warn") {
190- console.warn(`[permission-guard] 未知角色放行(告警): role=${role ?? "?"} tool=${tool} path=${rel}`)
191- }
192- return null // allow / allow-warn
193- }
194- 
195- const hint = (() => {
196- if (role === "PM")
197- return " 请将此操作派发给对应的子 Agent 执行,PM 只负责调度,不直接执行。"
198- return " 如果无此权限无法完成当前任务,请立即结束任务并向主 Agent 上报。"
199- })()
200- 
201- // 目录类别校验
202- if (!rule.categories.includes(cat)) {
203- return (
204- `[permission-guard] 角色 ${role} 无权写入 ${cat} 目录:${rel}` +
205- `(可写类别:${rule.categories.join("/")}${hint})`
206- )
207- }
208- // 文件类型校验
209- if (rule.exts !== "*") {
210- const e = extOf(rel)
211- if (!rule.exts.includes(e)) {
212- return `[permission-guard] 角色 ${role} 只能写 ${rule.exts.join("/")} 类型,拒绝:${rel}${hint}`
213- }
214- }
215- return null // 通过
216-}
217- 
218-// ---------------------------------------------------------------------------
219-// Cordis 插件装配
220-// ---------------------------------------------------------------------------
221- 
222-const name = "cannbot-permission-guard"
223- 
224-function apply(ctx) {
225- // 角色缓存:按 agent session id,仅缓存成功解析的结果(label 持久稳定;
226- // 不缓存 null——瞬态失败(listChildren 异常等)不应把角色永久判为未知)
227- const roleCache = new Map()
228- // 规则缓存:按项目根 + permissions 目录 mtime 失效
229- const rulesCache = new Map()
230- 
231- async function getRules(projectRoot) {
232- const dir = join(projectRoot, ".cannbot", "permissions")
233- let mtime = 0
234- try {
235- mtime = statSync(dir).mtimeMs
236- } catch {
237- return { ...DEFAULT_RULES }
238- }
239- const hit = rulesCache.get(projectRoot)
240- if (hit && hit.mtime === mtime) return hit.rules
241- const fileAgents = await loadConfig(projectRoot)
242- const rules = fileAgents ? { ...DEFAULT_RULES, ...fileAgents } : { ...DEFAULT_RULES }
243- rulesCache.set(projectRoot, { mtime, rules })
244- return rules
245- }
246- 
247- // 解析调用方角色:主 Agent → PM;子 Agent → 持久 label → 角色名
248- async function resolveRole(ctx, agent, header) {
249- if (!agent) return null
250- const sid = agent.id
251- if (roleCache.has(sid)) return roleCache.get(sid)
252- let role = null
253- if (!header || header.origin !== "subagent") {
254- role = PRIMARY_ROLE // 主 Agent(无 subagent origin)→ PM
255- } else {
256- const parentId = header.parentSession
257- const label = await findLabel(ctx, parentId, sid)
258- role = label ? parseRoleFromLabel(label) : null
259- }
260- // 仅缓存非 null:解析失败(瞬态错误/未命中)下次调用重试,避免永久误判
261- if (role) roleCache.set(sid, role)
262- return role
263- }
264- 
265- // 通过子 Agent 枚举查持久 label(listChildren 暴露 descriptor 的创建 label)
266- async function findLabel(ctx, parentId, childId) {
267- const subagents = ctx.get("subagents")
268- if (!parentId || !subagents) return null
269- try {
270- const children = await subagents.listChildren(parentId)
271- for (const c of children) {
272- if (c.kind === "child" && c.id === childId) return c.label ?? null
273- }
274- return null
275- } catch (e) {
276- ctx.logger?.warn?.("[permission-guard] dsh: resolve label failed: %s", e?.message)
277- return null
278- }
279- }
280- 
281- // tools/pre-execute 瀑布:返回 deny 即短接拒绝;否则委托 next()
282- ctx.on("tools/pre-execute", async (exec, next) => {
283- try {
284- const agent = exec.agent
285- const header = agent?.session?.header
286- const cwd = header?.cwd
287- if (!cwd) return next()
288- 
289- // 工作区识别:非 ops-direct-invoke 初始化工作区(无 .cannbot/permissions)一律放行
290- const permDir = join(cwd, ".cannbot", "permissions")
291- let hasPerm = false
292- try {
293- statSync(permDir)
294- hasPerm = true
295- } catch {
296- /* 目录缺失 = 非受管工作区 */
297- }
298- if (!hasPerm) return next()
299- 
300- const tool = (exec.name || "").toLowerCase()
301- 
302- // 静默模式:拦截问卷发送(任何角色都不得绕过;与 opencode/claude 同语义)
303- if (SILENT_GUARDED_TOOLS.some((t) => tool.includes(t))) {
304- if (readSilentMode(cwd)) {
305- return {
306- kind: "deny",
307- reason:
308- "[permission-guard] 静默模式已启用,问卷发送被拦截:请按静默默认决策执行——" +
309- "不发送问卷,落盘 .reply.json({\"mode\":\"silent\",\"decision\":\"accepted\"});" +
310- "如需恢复交互,请让用户关闭静默模式。",
311- }
312- }
313- return next()
314- }
315- 
316- if (!GUARDED_TOOLS.includes(tool)) return next() // 非写类工具放行
317- 
318- const rawPath = exec.arguments?.file_path ?? exec.arguments?.path
319- const role = await resolveRole(ctx, agent, header)
320- const rules = await getRules(cwd)
321- const denial = await decideWrite({ projectRoot: cwd, tool, filePath: rawPath, role, rules })
322- if (denial) return { kind: "deny", reason: denial }
323- return next()
324- } catch (e) {
325- // 意外错误 fail-open(避免拖垮无关调用),记录日志
326- ctx.logger?.warn?.("[permission-guard] dsh: unexpected error, allowing: %s", e?.message)
327- return next()
328- }
329- })
330-}
331- 
332-export { name, apply }
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/SKILL.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/SKILL.md+47-36
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/scripts/assemble_workflow.py→plugins/ops-direct-invoke/skills/ops-direct-invoke/scripts/assemble_workflow.py+11-1
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/scripts/run_workflow.py→plugins/ops-direct-invoke/skills/ops-direct-invoke/scripts/run_workflow.py+3-3
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/代码修复.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/代码修复.yaml+4-6
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/技术穿刺.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/技术穿刺.yaml+4-6
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/文档准备.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/文档准备.yaml+4-11
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/测试工程开发.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/测试工程开发.yaml+5-12
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/白盒测试设计.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/白盒测试设计.yaml+5-12
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/知识搜集.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/知识搜集.yaml+4-6
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/算子开发.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/算子开发.yaml+6-8
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/tasks/黑盒测试设计.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/tasks/ascendc/黑盒测试设计.yaml+6-13
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/代码检视报告.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/代码检视报告.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/功能验收报告.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/功能验收报告.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/测试执行记录.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/测试执行记录.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/白盒测试设计.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/白盒测试设计.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/知识搜集.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/知识搜集.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/验收报告.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/验收报告.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/docs/黑盒测试设计.md→plugins/ops-direct-invoke/skills/ops-direct-invoke/templates/黑盒测试设计.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/workflows/basic.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/workflows/ascendc/basic.yaml+8-19
Rplugins-community/ops-direct-invoke-harness/skills/ops-direct-invoke/templates/workflows/feasibility.yaml→plugins/ops-direct-invoke/skills/ops-direct-invoke/workflows/ascendc/feasibility.yaml+2-1
Rplugins-community/ops-direct-invoke-harness/skills/repo-env-check/SKILL.md→plugins/ops-direct-invoke/skills/repo-env-check/SKILL.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/repo-env-check/references/环境信息.md→plugins/ops-direct-invoke/skills/repo-env-check/references/环境信息.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/repo-requirement/SKILL.md→plugins/ops-direct-invoke/skills/repo-requirement/SKILL.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/repo-requirement/references/requirement-checklist.md→plugins/ops-direct-invoke/skills/repo-requirement/references/requirement-checklist.md+0-0
Rplugins-community/ops-direct-invoke-harness/skills/repo-test-develop/references/cannbench-integration.md→plugins/ops-direct-invoke/skills/repo-test-develop/references/cannbench-integration.md+0-0
Rplugins-community/ops-direct-invoke-harness/test/ut/retry_feedback/fixtures/codex.py→plugins/ops-direct-invoke/test/ut/retry_feedback/fixtures/codex.py+16-6
Rplugins-community/ops-direct-invoke-harness/test/ut/retry_feedback/test.py→plugins/ops-direct-invoke/test/ut/retry_feedback/test.py+17-7
Rplugins-community/ops-direct-invoke-harness/test/ut/support.py→plugins/ops-direct-invoke/test/ut/support.py+19-15
Rplugins-community/ops-direct-invoke-harness/test/ut/test_all.py→plugins/ops-direct-invoke/test/ut/test_all.py+0-0
Rplugins-community/ops-direct-invoke-harness/test/ut/variables/test.py→plugins/ops-direct-invoke/test/ut/variables/test.py+12-7
Rplugins-community/ops-direct-invoke-harness/test/ut/workflow_execution/test.py→plugins/ops-direct-invoke/test/ut/workflow_execution/test.py+15-14
Rplugins-community/ops-direct-invoke-harness/test/ut/workflow_generation/test.py→plugins/ops-direct-invoke/test/ut/workflow_generation/test.py+27-20
Rplugins-community/ops-direct-invoke-harness/test/ut/registry/test.py→plugins/ops-direct-invoke/test/ut/workflow_guide/test.py+79-19