diff --git a/.agents/skills/tilelang-pass-agents-guide.md b/.agents/skills/tilelang-pass-agents-guide.md index b68dfee13..2ce5d7fb1 100644 --- a/.agents/skills/tilelang-pass-agents-guide.md +++ b/.agents/skills/tilelang-pass-agents-guide.md @@ -32,7 +32,7 @@ Pass 在仓库中的实现通常分为两层: | `tilelang-pass-analyzer` | 分析单个 Pass 的功能、原理、差异、分类 | 用户询问某个 Pass 是做什么的,或要对比/分类查询时 | | `tilelang-pass-workflow-analyzer` | 分析 Pass 工作流、顺序、依赖关系、定位新 Pass | 用户询问 Pass pipeline、依赖、顺序、插入位置时 | | `tilelang-pass-design` | 生成 Pass 设计文档 | 用户要设计 Pass、写 pass-design.md、明确方案时 | -| `tilelang-pass-generate` | Pass 实现相关 | 用户要根据设计文档开始实现、修改、补测试时 | +| `tilelang-pass-generate` | 根据设计文档生成 Pass **实现侧**最终代码(先输出 `pass-impl-skeleton.md` 框架文档,再落 C++/Python wrapper/pass_config/phase.py,最后做最小冒烟验证)。**不生成 UT/ST**,UT/ST 由独立的 Pass 测试生成 skill 处理 | 用户要根据设计文档开始实现 Pass、修改 Pass、重构 Pass 时 | --- @@ -142,6 +142,8 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 - 对局部改动,先跑最小范围验证;对影响面较大的改动,再补更广的算子或集成验证 - 若变更影响多个算子或通用 pipeline,可进一步运行更广范围的验证,例如相关测试集或 `examples/bench_test.sh` +> 测试**编写**由独立的 Pass 测试生成 skill(待创建)负责。`tilelang-pass-generate` 只做实现侧代码 + 冒烟验证,并在收尾报告里把上述测试需求列为「测试待补清单」,作为给测试 skill 的输入。 + --- ## 总体执行流程 @@ -173,7 +175,8 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 | Pass 功能分析 | `tilelang-pass-analyzer` | 功能分析报告 | | Pass 工作流分析 | `tilelang-pass-workflow-analyzer` | 工作流/依赖分析报告 | | Pass 方案设计 | `tilelang-pass-design` | `pass-design.md` | -| Pass 代码执行 | `tilelang-pass-generate` | 代码实现、修改、重构与验证 | +| Pass 代码执行 | `tilelang-pass-generate` | `pass-impl-skeleton.md`(框架)+ 实现侧代码(C++/Python wrapper/pass_config/phase.py)+ 最小冒烟验证;**不含 UT/ST** | +| Pass 测试生成 | Pass 测试生成 skill(**待创建**) | UT / ST 测试代码(接续 `tilelang-pass-generate` 与设计文档 §5)| 若用户目标是“最终把 Pass 改好”,则整体流程通常为: @@ -239,15 +242,15 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 执行阶段由 `tilelang-pass-generate` 为主,必须覆盖以下检查项。 -#### 新增 Pass 检查项 +#### 新增 Pass 检查项(实现侧由 `tilelang-pass-generate` 完成) 1. 新建或补充 `src/transform/.cc` 2. 确认 `TVM_REGISTER_GLOBAL("tl.transform.")` 3. 增加 `tilelang/transform/__init__.py` Python 封装 4. 必要时增加 `pass_config.py` 配置键 5. 将 Pass 接入 `tilelang/engine/phase.py` -6. 增加或更新测试 -7. 补充相关设计文档或参考资料 +6. 补充相关设计文档或参考资料 +7. **测试由独立的 Pass 测试生成 skill(待创建)补充**,本步骤只在收尾报告里列出测试待补清单,不在 `tilelang-pass-generate` 内写测试 #### 修改已有 Pass 检查项 @@ -255,7 +258,7 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 2. 做最小行为修改 3. 检查是否影响中间属性、注解、循环结构或 buffer 访问 4. 检查 phase 中上下游 Pass 是否仍然兼容 -5. 更新测试预期或补充回归测试 +5. **回归测试由 Pass 测试生成 skill 补充**,本阶段在报告里写明需要覆盖的目标行为差异 #### 重构已有 Pass 检查项 @@ -267,12 +270,14 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 ### 阶段六:验证与收尾 -按如下优先级验证: +`tilelang-pass-generate` 阶段只做不依赖 UT/ST 的冒烟验证: + +1. 导入冒烟(Python 封装 ↔ C++ 注册一致) +2. 跨文件命名 grep 一致(`PassName` 三处一致、配置键两处一致) +3. 已有最小 example 跑通,确认 pipeline 没有因为新 Pass 接入而崩 +4. (可选)本机能跑则做最小构建冒烟 -1. 最小范围的行为验证 -2. 受影响测试 -3. 最小构建或编译检查 -4. 路径、引用、配置项校验 +UT/ST 测试相关验证由后续独立的 Pass 测试生成 skill 处理。 收尾输出必须至少包含: @@ -362,6 +367,9 @@ Pass 开发常常不止修改一个 `.cc` 文件,还可能需要同步修改 - `.agents/skills/tilelang-pass-workflow-analyzer/references/` - `.agents/skills/tilelang-pass-design/` - `.agents/skills/tilelang-pass-generate/` +- `.agents/skills/tilelang-pass-generate/templates/pass-impl-skeleton-template.md` +- `.agents/skills/tilelang-pass-generate/references/code-generation-checklist.md` +- `.agents/skills/tilelang-pass-generate/references/integration-points.md` --- diff --git a/.agents/skills/tilelang-pass-design/SKILL.md b/.agents/skills/tilelang-pass-design/SKILL.md index 7534dd25a..42e807029 100644 --- a/.agents/skills/tilelang-pass-design/SKILL.md +++ b/.agents/skills/tilelang-pass-design/SKILL.md @@ -232,7 +232,7 @@ description: "根据 Pass 需求生成 TileLang-Ascend Pass 设计文档(pass- ### 后续步骤建议 1. 查看详细 Pass 工作流:使用 **tilelang-pass-workflow-analyzer** skill 2. 查看类似 Pass 实现:使用 **tilelang-pass-analyzer** skill -3. 开始实现 Pass:使用 **tilelang-pass-generate** skill(待创建) +3. 开始实现 Pass:使用 **tilelang-pass-generate** skill ``` --- @@ -258,4 +258,4 @@ description: "根据 Pass 需求生成 TileLang-Ascend Pass 设计文档(pass- |------|------|----------| | `tilelang-pass-workflow-analyzer` | 依赖 | 查阅 Pipeline 架构、Pass 定位、依赖关系 | | `tilelang-pass-analyzer` | 依赖 | 查阅现有 Pass 实现细节、IR 变换示例 | -| `tilelang-pass-generate`(待创建) | 后续 | 根据设计文档生成 Pass 代码 | \ No newline at end of file +| `tilelang-pass-generate` | 后续 | 根据设计文档生成 Pass 代码(先输出 `pass-impl-skeleton.md` 框架,再落 C++/Python/Pipeline/测试) | \ No newline at end of file diff --git a/.agents/skills/tilelang-pass-generate/SKILL.md b/.agents/skills/tilelang-pass-generate/SKILL.md new file mode 100644 index 000000000..b0db218bf --- /dev/null +++ b/.agents/skills/tilelang-pass-generate/SKILL.md @@ -0,0 +1,315 @@ +--- +name: tilelang-pass-generate +description: "根据 pass-design.md 与 workflow 分析结果生成 TileLang-Ascend Pass 的最终实现代码(不含 UT/ST)。先输出实现骨架文档(pass-impl-skeleton.md)确认框架设计,再生成 C++ 实现、Python 封装、Pipeline 接入,并完成最小冒烟验证。测试生成由后续独立 skill 负责。触发关键词:实现 Pass、生成 Pass 代码、Pass 编码、根据设计文档实现 Pass、写 Pass 代码、落地 Pass、新增 Pass 实现。" +--- + +# TileLang-Ascend Pass 代码生成 Skill + +--- + +## 1. 目标与边界 + +### 1.1 本 skill 负责(In Scope) + +把已经定型的 Pass 设计文档(`pass-design.md`)落到代码上,覆盖: + +- **C++ 实现**:`src/transform/.cc` +- **Python 封装**:`tilelang/transform/__init__.py` +- **配置键(可选)**:`tilelang/transform/pass_config.py` +- **Pipeline 接入**:`tilelang/engine/phase.py` +- **最小冒烟验证**:导入是否成功、Pipeline 是否仍然能跑通最小 example、跨文件命名是否一致 + +### 1.2 本 skill 不做(Out of Scope) + +- ❌ **不生成 UT / ST 测试代码** —— 由后续单独的测试生成 skill 负责 +- ❌ 不重做 Pass 定位与方案决策(属于 `tilelang-pass-design`) +- ❌ 不修改 TVM 原生 Pass + +> 所有重大决策必须沿用 `pass-design.md` 已经写定的内容;如果设计文档里某项是「待确认」或缺失,则停下来回到 `tilelang-pass-design` 补齐,不在本 skill 里临时拍板。 + +> 完成代码生成后,提示用户调用「Pass 测试生成 skill(待创建)」补 UT/ST,不在本 skill 里偷跑。 + +--- + +## 2. 必需输入 + +| 字段 | 说明 | 缺失处理 | +|------|------|----------| +| `pass-design.md` | 已通过 `tilelang-pass-design` 自检的 Pass 设计文档 | 询问用户位置;若没有则建议先跑 `tilelang-pass-design` | +| Pass 名称 | C++ 类名、Python 函数名、注册名 | 从 `pass-design.md` §1.1 读取 | +| 阶段归属与位置 | `Phase 1 / Phase 2`,以及插入位点 | 从 `pass-design.md` §2 读取 | +| 父类与核心方法 | `IRMutatorWithAnalyzer` / `StmtExprVisitor` / `StmtExprMutator` 等 | 从 `pass-design.md` §4.1 读取 | +| 输入/输出 attrs | 上下游数据传递 | 从 `pass-design.md` §2.4、§3 读取 | + +> 设计文档 §5「测试方案」本 skill 不消费,仅作为下游测试 skill 的输入保留。 + +**输入校验规则**: + +1. 若 `pass-design.md` 不存在 → 立即停止,引导用户使用 `tilelang-pass-design` +2. 若设计文档中 §2 / §3 / §4 任一关键章节出现「待确认」「待补充」「TODO」 → 立即停止,列出缺口并要求补齐 +3. 若 Pass 名称、阶段归属、Pipeline 位置任何一项不明确 → 立即停止,要求用户先回到 design skill + +--- + +## 3. 工作流程 + +「**先骨架、再代码、最后冒烟**」三段式流程,骨架阶段不可跳过。 + +``` +[输入校验] + ↓ +[Phase A: 信息收集] + ↓ +[Phase B: 生成实现骨架文档 pass-impl-skeleton.md] ← 框架设计文档 + ↓ +[用户确认骨架] + ↓ +[Phase C: 落代码(C++ / Python / pass_config / phase.py)] + ↓ +[Phase D: 最小冒烟验证(不跑 UT/ST)] + ↓ +[Phase E: 收尾报告 + 引导补测试] +``` + +### Phase A:信息收集 + +按以下顺序读取,禁止一上来就 grep 整个 `src/transform/`: + +1. **设计文档**:用户指定路径,或默认在当前目录 `pass-design.md` +2. **总体约束**:`.agents/skills/tilelang-pass-agents-guide.md` +3. **实现模式**:`.agents/skills/tilelang-pass-design/references/pass-impl-patterns.md` +4. **Pipeline 现状**:`tilelang/engine/phase.py`(确认插入位点的上下文与函数签名) +5. **Python 封装现状**:`tilelang/transform/__init__.py`(确认现有命名风格、`_ffi_api` 调用方式) +6. **相似 Pass 源码**:`pass-design.md` §4.1 指定的参考 Pass,仅读 1–2 个最接近的实现,不得扫整目录 + +> 信息源冲突时,优先级:`pass-design.md` > `pass-impl-patterns.md` > 相似 Pass 源码 > 自身经验。 + +### Phase B:生成实现骨架文档(pass-impl-skeleton.md) + +骨架文档是「**代码层面的最后一次结构化对齐**」。它比 `pass-design.md` 更落地,但又比真实代码更轻量,目的是在写代码前一次性把以下决策列清楚: + +1. **改动文件清单**(含状态:新建 / 修改),**仅限实现侧 4 个文件**:`.cc` / `__init__.py` / `pass_config.py` / `phase.py` +2. **C++ 类骨架**:类名、父类、成员变量、构造函数签名、所有要重写的 `VisitStmt_` / `VisitExpr_` 方法签名(不写实现体) +3. **Substitute 入口流程**:步骤化伪代码(读取 attrs → 构造 mutator → MutateFunc → 设置 attrs) +4. **辅助类/辅助函数清单**(如 `Detector`、`Analyzer`、`Rewriter` 模式拆分) +5. **Attr 读写表**:键名 / 类型 / 来源 Pass / 缺失策略 +6. **注册与配置键**:`TVM_REGISTER_GLOBAL` 完整字符串、可选的 `TVM_REGISTER_PASS_CONFIG_OPTION` +7. **Python 封装函数签名**:参数、docstring 要点 +8. **Pipeline 接入点**:在 `phase.py` 哪一行(具体到上下游 Pass 名称) +9. **最小冒烟验证步骤**:先跑哪一条命令(导入冒烟 / 编译冒烟 / 最小 example 能跑) + +> ⚠️ 骨架文档不写测试用例。测试相关内容由后续独立 skill 负责,本骨架里仅在末尾留一行「测试待补由 Pass 测试生成 skill 处理」作为交棒标记。 + +骨架文档基于 `templates/pass-impl-skeleton-template.md` 填写,输出到 `pass-impl-skeleton.md`。完成后**必须停下来等用户确认**,再进入 Phase C。 + +> 骨架阶段禁止做的事:写完整 `VisitStmt_` 函数体、动除骨架文档外的任何文件。 + +### Phase C:落代码 + +在用户确认骨架后,按以下顺序逐文件落地。**每完成一个文件,立即做最小检查再走下一个**(参见 §6 增量验证策略)。 + +| 顺序 | 文件 | 主要内容 | 完成后立即检查 | +|------|------|----------|----------------| +| 1 | `src/transform/.cc` | C++ 实现,按骨架填充 Visit 方法体、辅助函数、注册宏 | 语法/include 完整性、注册宏字符串、namespace 闭合 | +| 2 | `tilelang/transform/__init__.py` | Python 封装函数 + 必要的 import | `python -c "from tilelang.transform import "` | +| 3 | `tilelang/transform/pass_config.py` | 仅当骨架声明需要新增配置键时改动 | 读一次该文件确认没有重名 | +| 4 | `tilelang/engine/phase.py` | 在指定 Pass 前/后插入一行调用 | 视觉对齐上下文,避免插错阶段 | + +> 本 skill 不写、不改 `testing/python/` 下任何文件。 + +#### 落代码硬约束 + +- **禁止脱离 `pass-impl-patterns.md` 模板**:父类继承、`Substitute` 静态入口、`CreatePrimFuncPass` 调用方式必须与模板一致 +- **禁止改动 `tir.transform.*` 等 TVM 原生 Pass**(来自 `tilelang-pass-agents-guide.md` 约束 3) +- **禁止只改 `.cc` 不改 Python 封装**(约束 4) +- **禁止把多种职责塞进一个 Pass**(约束 4:功能正交) +- **配置键缺省值默认 `False`**:新增 Pass 默认不开启,需要走 `pass_configs` 显式启用,除非 `pass-design.md` §4.5 明确写了「默认开启」并给出理由 +- **Attr 读取必须做 defined() 检查**:缺失时按设计文档的策略处理(报错 / 跳过 / 默认值),不得静默崩溃 +- **C++ 注释保持最小**:仅在 WHY 不直观时写一行(来自仓库总规约) + +### Phase D:最小冒烟验证 + +本 skill 只做不依赖 UT/ST 的冒烟验证,按优先级顺序执行(完成第一项即可继续,但必须至少做一项): + +1. **导入冒烟**: + ```bash + python -c "import tilelang; from tilelang.transform import ; print(())" + ``` + 验证 Python 封装、`_ffi_api` 注册、C++ 端 `TVM_REGISTER_GLOBAL` 字符串四方一致。 +2. **构建冒烟**(如本地能跑构建):项目根目录的最小重新构建,验证 C++ 文件能编过。 +3. **Pipeline 冒烟**:跑一条**已存在**的最小 example(如 `examples/elementwise/...`)确认 pipeline 没有因为本 Pass 的接入而崩。 +4. **跨文件一致性 grep**: + ```bash + grep -n "" src/transform/.cc tilelang/transform/__init__.py tilelang/engine/phase.py + grep -n "tl." src/transform/.cc tilelang/transform/pass_config.py + ``` + +> ⚠️ **本阶段不写、不跑 UT/ST 单测**。如果配套的 `testing/python/` 下已有更早的相关测试,可以顺便跑一下作为额外冒烟,但**禁止为本 Pass 新建任何测试文件**。 + +若验证失败,按以下顺序定位: + +- 编译错误 → 头文件缺失、TVM API 签名变化、命名空间问题 +- 注册错误 → `TVM_REGISTER_GLOBAL` 字符串与 Python 调用名不一致 +- Attr 读取错误 → 类型签名(`Map` vs `Map`)不匹配 +- Pipeline 顺序错误 → 上游 attrs 未产生时本 Pass 已被调用 + +**禁止失败后无脑加 try/except 把异常吞掉**(仓库总规约:不要遮住问题)。 + +### Phase E:收尾报告 + 引导补测试 + +参考 §7 模板输出报告,必须包含: +- 已生成 / 修改的实现侧文件 +- 已跑过的冒烟项 与 未即时验证项 +- **明确提示「UT/ST 待补,建议下一步使用 Pass 测试生成 skill」** + +--- + +## 4. 落地阶段决策速查 + +| 场景 | 默认做法 | +|------|----------| +| 父类是 `IRMutatorWithAnalyzer` | 在 `Substitute` 中执行 `mutator.MutateFunc(f)`,构造函数传 `f->body` | +| 父类是 `StmtExprVisitor` | 在 `Substitute` 中执行 `collector.VisitStmt(f->body)`,最后 `f.WithAttrs({...})` | +| 父类是 `StmtExprMutator` | 不需要 analyzer,直接重写 `VisitStmt_/VisitExpr_` | +| Pass 有输入 attrs | `f->GetAttr<...>(key)` + `defined()` 检查;缺失策略走设计文档 | +| Pass 有输出 attrs | 在 `Substitute` 末尾 `f.WithAttrs({{key, value}})` | +| Pass 是 Ascend 特定 | 加 `is_npu` 判断或仅在 `OptimizeForTarget` 中调用 | +| Pass 与现有 Pass 功能重合 | **回退**:在现有 Pass 内做增量改动,不新增 Pass | +| 设计文档与相似 Pass 实现冲突 | 以设计文档为准;如设计文档不合理,停下来回到 design skill | + +--- + +## 5. 修改 / 重构 Pass 的差异化流程 + +本 skill 也处理「修改已有 Pass」「重构已有 Pass」,差异如下: + +### 5.1 修改已有 Pass + +- 跳过 Phase B 中的「类骨架」「注册键」部分,仅写出**「目标行为差异点 + 关键修改方法清单」** +- 必须先在骨架文档里列出: + - 当前行为 vs 目标行为 + - 真正控制该行为的函数(精确到方法名 / 关键 if 分支) + - 最小修改范围(行数 / 受影响 Visit 方法) +- Phase C 强制做最小修改,不允许顺手重排其他无关代码 +- Phase D 冒烟之外,**不在本 skill 内补回归测试**;在收尾报告里明确写「需补 X 类回归 case」,交棒给测试 skill + +### 5.2 重构已有 Pass + +- 默认语义保持不变,注册名、Python 封装签名、phase.py 调用位置都不动 +- 骨架文档里要写出: + - 重构前后的类划分对照(旧类 → 新类) + - 哪些是「纯结构整理」,哪些是「为了整理而不得不动的语义点」 +- 禁止在同一个重构 PR 里混入功能性改动 +- Phase D 冒烟跑一条 example 确认 pipeline 不退化即可;广覆盖回归留给测试 skill + +--- + +## 6. 增量验证策略 + +每完成一个**有实质行为的修改**就停一次,禁止连续大改后再一次性验证。 + +| 修改点 | 立即验证手段 | +|--------|--------------| +| 改了 C++ 文件 | 至少 `clang-format` / 本地 build;如时间不允许,至少 grep 注册宏字符串 | +| 改了 Python `__init__.py` | `python -c "from tilelang.transform import "` | +| 改了 `phase.py` | 跑一条最小 example 编译(如 `examples/elementwise/...`)确认 pipeline 不炸 | +| 改了 `pass_config.py` | grep 一次配置键名,确认与 C++ 字符串完全一致 | + +如果某一步无法立即验证(环境问题、build 缓慢),**必须明确告诉用户**「这一步未即时验证,待用户在本机确认」,不得伪装成已验证。 + +--- + +## 7. 完成报告模板 + +``` +## Pass 代码生成报告 + +- Pass 名称: {Pass 名称} +- 任务类型: 新增 / 修改 / 重构 +- 阶段归属: {Phase 1 / Phase 2} +- Pipeline 位置: {具体位置} + +### 骨架文档 +- 路径: {pass-impl-skeleton.md 路径} +- 用户确认状态: ✅ 已确认 / ⚠️ 未确认即落代码(不应出现) + +### 已生成 / 修改文件(仅实现侧,不含测试) +| 文件 | 状态 | 行数变化 | +| `src/transform/.cc` | 新建 | +XXX | +| `tilelang/transform/__init__.py` | 修改 | +X | +| `tilelang/transform/pass_config.py` | 修改 / 未改 | +X | +| `tilelang/engine/phase.py` | 修改 | +1 | + +### 已执行的冒烟验证 +1. 导入冒烟: ✅ / ❌(失败原因) +2. 跨文件命名 grep 一致: ✅ / ❌ +3. 最小 example 跑通: ✅ / ❌ / 未即时验证 +4. 构建冒烟: ✅ / ❌ / 未即时验证 + +### 未即时验证项(需用户在本机确认) +- {项目} + +### 剩余风险 +- {风险 1} +- {风险 2} + +### ⚠️ 测试待补(交棒) +- 本 skill 仅做实现侧代码生成,不生成 UT/ST。 +- 建议下一步使用「Pass 测试生成 skill」(待创建)补充以下测试: + - 功能测试:{设计文档 §5.1 已列} + - 依赖测试:{设计文档 §5.2 已列} + - 边界测试:{设计文档 §5.3 已列} + - (修改任务)回归测试:{在本次修改中需要覆盖的目标行为差异} +``` + +--- + +## 8. 与其他 Skill 的关系 + +| Skill | 关系 | 衔接点 | +|-------|------|--------| +| `tilelang-pass-agents-guide` | 上层指导 | 总体执行流程、约束、文件清单 | +| `tilelang-pass-analyzer` | 依赖 | 相似 Pass 实现、IR 示例 | +| `tilelang-pass-workflow-analyzer` | 依赖 | Pipeline 位置、依赖图 | +| `tilelang-pass-design` | **强依赖(输入)** | 提供 `pass-design.md` | +| `tilelang-pass-generate`(本 skill) | 实现代码生成终点 | 输出 `pass-impl-skeleton.md` + 落实现侧代码 + 冒烟验证 | +| Pass 测试生成 skill(**待创建**) | **下游交棒** | 接收本 skill 输出 + 设计文档 §5,生成 UT/ST | + +--- + +## 9. 错误处理 + +| 场景 | 处理方式 | +|------|----------| +| `pass-design.md` 缺失 | 停止,引导用户先跑 `tilelang-pass-design` | +| 设计文档中阶段归属、Pipeline 位置不明确 | 停止,列出缺口,要求补齐 | +| 设计文档与现有 Pass 注册名冲突 | 停止,询问是否复用现有 Pass 而不是新增 | +| 用户跳过骨架直接要求落代码 | 仍然先输出骨架(可压缩),不允许跳过 | +| 用户要求顺手把 UT/ST 也写了 | 拒绝,引用本 skill §1.2 边界,引导去用测试生成 skill | +| 落代码阶段编译失败 | 不要加规避分支;定位真实原因后告诉用户 | +| 用户要求把 Pass 放到 TVM 原生 Pass 里 | 拒绝,引用 `tilelang-pass-agents-guide` 约束 3 | + +--- + +## 10. 参考资料 + +| 文件 | 路径 | 用途 | +|------|------|------| +| Pass 总体约束 | `.agents/skills/tilelang-pass-agents-guide.md` | 工作流、约束、文件清单 | +| Pass 设计文档模板 | `.agents/skills/tilelang-pass-design/templates/pass-design-template.md` | 反查设计文档结构 | +| Pass 实现模式 | `.agents/skills/tilelang-pass-design/references/pass-impl-patterns.md` | C++ 类模板、Visit 模式、注册方式 | +| 骨架文档模板 | `templates/pass-impl-skeleton-template.md`(本 skill) | 实现骨架格式 | +| 落地清单 | `references/code-generation-checklist.md`(本 skill) | 实现侧文件检查项 | +| 接入位点参考 | `references/integration-points.md`(本 skill) | `__init__.py` / `phase.py` / `pass_config.py` 接入示例 | + +--- + +## 11. 注意事项 + +1. **骨架阶段不可跳过**:哪怕用户着急,也要先输出 `pass-impl-skeleton.md`。骨架可以压缩,但不能省。 +2. **设计文档是源真相**:所有重大决策都按设计文档来;设计文档不合理就回到 design skill,不要在生成阶段拍板。 +3. **每改一处立刻冒烟**:禁止连续多文件改动后再一次性测试。 +4. **不修 TVM 原生 Pass**:除非设计文档明确写了无法绕开的理由。 +5. **Python 封装、phase.py、pass_config.py 三处一致**:Pass 名称、配置键名称、参数顺序必须三边对齐,grep 一次确认。 +6. **不写测试**:本 skill 只生成实现侧代码,UT/ST 由独立 skill 处理;收尾报告里要把测试缺口列清楚以便交棒。 +7. **报告要诚实**:未跑过的冒烟就标「未即时验证」,不要冒充已验证。 diff --git a/.agents/skills/tilelang-pass-generate/references/code-generation-checklist.md b/.agents/skills/tilelang-pass-generate/references/code-generation-checklist.md new file mode 100644 index 000000000..8df69968f --- /dev/null +++ b/.agents/skills/tilelang-pass-generate/references/code-generation-checklist.md @@ -0,0 +1,107 @@ +# Pass 代码生成 Checklist + +每完成一个文件落地后逐项过一遍,全部通过才算该文件完成。 + +> ⚠️ 本 checklist **只覆盖实现侧 4 类文件**:C++ / Python wrapper / pass_config / phase.py。 +> UT/ST 测试不在本 skill 范围内,由后续独立的 Pass 测试生成 skill 负责。 + +--- + +## 1. C++ 实现文件 `src/transform/.cc` + +| # | 检查项 | 失败处理 | +|---|--------|----------| +| 1 | `#include` 完整:``、``(如继承 `IRMutatorWithAnalyzer`)等 | 缺什么补什么 | +| 2 | `namespace tvm { namespace tl { ... } }` 闭合正确 | 修正 | +| 3 | 主类继承的父类与骨架文档一致 | 退回骨架,不要在代码层临时换父类 | +| 4 | `static PrimFunc Substitute(PrimFunc f, PassContext ctx)` 入口存在 | 补 | +| 5 | 上游 attr 读取做了 `defined()` 检查 | 补 | +| 6 | 缺失策略与设计文档一致(报错 / 跳过 / 默认值) | 修正 | +| 7 | 输出 attr 通过 `f.WithAttr(s)` 设置(如有) | 补 | +| 8 | `CreatePrimFuncPass(pass_func, 0, "tl.{PassName}", {})` 第三个字符串与类名一致 | 修正 | +| 9 | `TVM_REGISTER_GLOBAL("tl.transform.{PassName}").set_body_typed(...)` 字符串与 Python 调用对齐 | 修正 | +| 10 | 配置键(如有):`TVM_REGISTER_PASS_CONFIG_OPTION(...)` 一次注册,键名与 `pass_config.py` 完全一致 | 修正 | +| 11 | 注释保持最少:仅在 WHY 不直观时一行注释 | 删除冗余注释 | +| 12 | 没有 `TODO` / `FIXME` / 占位符 | 删除或落实 | +| 13 | 没有引入对 `tir::transform::*` 原生 Pass 的修改 | 退回设计 | + +--- + +## 2. Python 封装 `tilelang/transform/__init__.py` + +| # | 检查项 | 失败处理 | +|---|--------|----------| +| 1 | 函数名与 C++ `TVM_REGISTER_GLOBAL` 字符串对齐(去掉 `tl.transform.` 前缀) | 修正 | +| 2 | 调用 `_ffi_api.{PassName}(...)` 而不是 `tvm.tl.transform.*` | 修正 | +| 3 | docstring 至少一句说明 + Returns 段 | 补充 | +| 4 | 参数顺序与 C++ Pass 注册函数一致 | 修正 | +| 5 | 没有破坏现有 import 顺序 | 调整 | + +> 验证:`python -c "from tilelang.transform import {PassName}; print({PassName}())"` + +--- + +## 3. 配置键 `tilelang/transform/pass_config.py` + +仅在新增配置键时改动。 + +| # | 检查项 | 失败处理 | +|---|--------|----------| +| 1 | 新键放在合适的分组下(参考现有键的分类) | 调整位置 | +| 2 | 键名 `tl.xxx` 与 C++ 中的字符串完全一致 | 修正 | +| 3 | 默认值与 C++ `GetConfig(key, default)` 中的默认值一致 | 修正 | +| 4 | 注释一句话说明用途与默认值 | 补充 | + +--- + +## 4. Pipeline 接入 `tilelang/engine/phase.py` + +| # | 检查项 | 失败处理 | +|---|--------|----------| +| 1 | 插入位置与设计文档 §2.3 一致 | 修正 | +| 2 | 上游 Pass 在本 Pass 之前调用 | 修正 | +| 3 | 下游 Pass 在本 Pass 之后调用 | 修正 | +| 4 | 没有插到错误的阶段(Phase 1 vs Phase 2) | 修正 | +| 5 | 一行调用风格与上下文 Pass 保持一致(缩进、注释) | 调整 | +| 6 | (Ascend 特定 Pass)仅在 NPU 路径触发,必要时配 `is_npu` 检查 | 修正 | + +--- + +## 5. 跨文件一致性 + +最后做一次跨文件对齐: + +| # | 检查项 | 命令 | +|---|--------|------| +| 1 | Pass 名称在 C++ 类、注册宏、Python 函数三处一致 | `grep -n "{PassName}" src/transform/{pass_name}.cc tilelang/transform/__init__.py` | +| 2 | 配置键在 C++ 字符串、`pass_config.py` 两处一致 | `grep -n "tl.{pass_name_lower}" src/transform/{pass_name}.cc tilelang/transform/pass_config.py` | +| 3 | `phase.py` 中的调用与 `__init__.py` 中的封装函数同名 | `grep -n "{PassName}" tilelang/engine/phase.py tilelang/transform/__init__.py` | +| 4 | 无残留的 TODO / FIXME / 占位符 | `grep -rn "TODO\|FIXME\|XXX" src/transform/{pass_name}.cc` | + +--- + +## 6. 冒烟验证(不依赖 UT/ST) + +| # | 项目 | 通过判定 | +|---|------|----------| +| 1 | 导入冒烟 | `python -c "from tilelang.transform import {PassName}; print({PassName}())"` 无异常 | +| 2 | 跨文件命名 grep 一致 | §5 中 4 条命令的输出都符合预期 | +| 3 | 最小 example 跑通 | 已有 example(如 `examples/elementwise/...`)能正常编译/运行 | +| 4 | 构建冒烟 | C++ 文件能通过项目构建脚本编译(如本机能跑) | + +> 至少跑通 1、2 两项。3、4 视环境而定,未跑过的必须在报告里如实标注「未即时验证」。 + +--- + +## 7. 验证报告 + +最后确认报告里如实写明: + +- 已跑通的命令 +- 未即时验证的项 +- 已知剩余风险 +- 是否覆盖所有设计文档承诺的**实现行为**(测试覆盖由下游 skill 处理) +- **测试待补清单**(从设计文档 §5 抽取,作为给测试 skill 的交棒) + +> 不要把「未跑过」写成「已通过」。 +> 不要在本 skill 内顺手写测试,那是下游 skill 的职责。 diff --git a/.agents/skills/tilelang-pass-generate/references/integration-points.md b/.agents/skills/tilelang-pass-generate/references/integration-points.md new file mode 100644 index 000000000..f59fd275c --- /dev/null +++ b/.agents/skills/tilelang-pass-generate/references/integration-points.md @@ -0,0 +1,223 @@ +# Pass 接入点参考 + +本文件汇总落代码阶段三个核心接入位置的现成模板与对齐原则。代码生成时按这里的样式照搬,不要自创风格。 + +> ⚠️ 本文件**只覆盖实现侧**:`tilelang/transform/__init__.py` / `tilelang/engine/phase.py` / `tilelang/transform/pass_config.py` / C++ 注册块。 +> 测试文件接入由 Pass 测试生成 skill(待创建)单独处理,本文件不涉及。 + +--- + +## 1. `tilelang/transform/__init__.py` + +### 1.1 现有风格 + +打开 `tilelang/transform/__init__.py`,所有 Pass 封装统一是「**函数 + docstring + 一行 `_ffi_api` 调用**」。 + +### 1.2 无参 Pass 模板 + +```python +def {PassName}(): + """{一句话功能描述}。 + + {可选:补充上下文,如依赖的 attrs、典型使用场景} + + Returns + ------- + fpass : tvm.transform.Pass + The result pass. + """ + return _ffi_api.{PassName}() # type: ignore +``` + +### 1.3 带参 Pass 模板 + +```python +def {PassName}(target=None, is_npu: bool = False): + """{一句话功能描述}。 + + Parameters + ---------- + target : tvm.target.Target, optional + The compilation target. + is_npu : bool + Whether the current target is Ascend NPU. + + Returns + ------- + fpass : tvm.transform.Pass + The result pass. + """ + return _ffi_api.{PassName}(target, is_npu) # type: ignore +``` + +### 1.4 对齐要点 + +- 函数名:与 C++ `TVM_REGISTER_GLOBAL("tl.transform.{PassName}")` 中的尾段一致 +- `_ffi_api.{PassName}` 中的方法名:和 `TVM_REGISTER_GLOBAL` 第二段一致(去掉 `tl.transform.`) +- 不要写复杂逻辑:Python 封装就是一层透传 + +--- + +## 2. `tilelang/engine/phase.py` + +### 2.1 Phase 1 当前结构(节选) + +```python +def LowerAndLegalize(mod: IRModule, target: Target) -> IRModule: + mod = tilelang.transform.InjectTmpBuffer(target)(mod) + mod = tilelang.transform.AscendInferBufferScope()(mod) + mod = tilelang.transform.AscendVidReduction()(mod) + mod = tilelang.transform.BufferShapeCollector()(mod) + mod = tir.transform.BindTarget(target)(mod) + mod = tilelang.transform.HostProcesser()(mod) + mod = tir.transform.Simplify()(mod) + mod = tilelang.transform.AscendLowerParallelToVector()(mod) + mod = tilelang.transform.LayoutInference()(mod) + mod = tilelang.transform.CollectBufferShapes()(mod) + mod = tilelang.transform.LowerTileOp()(mod) + mod = tilelang.transform.LegalizeVectorizedLoop()(mod) + mod = tilelang.transform.LegalizeSafeMemoryAccess()(mod) + mod = tir.transform.Simplify()(mod) + return mod +``` + +### 2.2 Phase 2 当前结构(节选) + +```python +def OptimizeForTarget(mod: IRModule, target: Target, platform: str) -> IRModule: + mod = tir.transform.PlanAndUpdateBufferAllocationLocation()(mod) + mod = tilelang.transform.CrossCorePipeline()(mod) + mod = tilelang.transform.CombineCV()(mod) + mod = tilelang.transform.PipelinePlanning()(mod) + mod = tilelang.transform.InjectSoftwarePipeline()(mod) + mod = tilelang.transform.AscendLowerOpaqueBlock()(mod) + mod = tir.transform.NarrowDataType(32)(mod) + mod = tilelang.transform.ConfigIndexBitwidth()(mod) + mod = tilelang.transform.Flatten2DBuffer()(mod) + mod = tilelang.transform.FlattenBuffer()(mod) + mod = tir.transform.Simplify()(mod) + mod = tilelang.transform.VectorizeLoop(...)(mod) + mod = tilelang.transform.AscendStorageRewrite(is_npu=...)(mod) + # ... 后续 Pass + return mod +``` + +### 2.3 接入风格 + +- 一行一个 `mod = tilelang.transform.{Pass}()(mod)` +- 缩进与上下文一致(4 空格) +- 每行不写注释,除非需要解释「为什么必须放在这里」 +- 配置驱动:若 Pass 受 `pass_configs` 控制,仍然写在 phase.py 中调用,由 Pass 自己读 config 决定是否生效(避免 phase.py 出现复杂 if) + +### 2.4 接入位置 diff 模板 + +```python + mod = tilelang.transform.{上游 Pass}()(mod) ++ mod = tilelang.transform.{PassName}()(mod) + mod = tilelang.transform.{下游 Pass}()(mod) +``` + +> 不要插到错误阶段:Phase 1 是「Lowering + 合法化」,Phase 2 是「目标后端优化」,看 `pass-design.md` §2.1 决定。 + +--- + +## 3. `tilelang/transform/pass_config.py` + +### 3.1 现有风格 + +`PassConfigKey(str, Enum)` 类内每个键一行,附 docstring 简述用途和默认值。 + +### 3.2 新增键模板 + +```python +class PassConfigKey(str, Enum): + # ... 已有键 ... + + TL_{PASS_NAME_UPPER} = "tl.{pass_name_lower}" + """Enable/disable {PassName}. Default: False. + + {补充:何时启用、对哪些算子有效} + """ +``` + +### 3.3 对齐要点 + +- 键名 `tl.xxx` 全小写,下划线分词,与 C++ `static constexpr const char *` 字符串完全一致 +- 默认值通过 C++ 端 `ctx->GetConfig(key, Bool(false))` 决定,Python 这边不重复声明默认值 +- Ascend 特定 Pass 默认 `False`,由用户显式开启 + +--- + +## 4. C++ 注册块完整模板 + +放在每个 `src/transform/.cc` 文件末尾: + +```cpp +namespace tvm { +namespace tl { + +// ========== Pass 实现 ========== +// class {PassName} : public ... { ... }; + +// ========== Pass 注册 ========== +tvm::transform::Pass {PassName}() { + auto pass_func = [=](PrimFunc f, IRModule m, PassContext ctx) { + return {PassName}::Substitute(std::move(f), ctx); + }; + return CreatePrimFuncPass(pass_func, 0, "tl.{PassName}", {}); +} + +TVM_REGISTER_GLOBAL("tl.transform.{PassName}") + .set_body_typed({PassName}); + +// ========== 配置键(可选) ========== +static constexpr const char *k{PassName}Config = "tl.{pass_name_lower}"; +TVM_REGISTER_PASS_CONFIG_OPTION(k{PassName}Config, Bool); + +} // namespace tl +} // namespace tvm +``` + +### 4.1 命名约定 + +| 元素 | 形态 | +|------|------| +| C++ 类名 | `PascalCase`,如 `AscendMemoryPlanning` | +| 注册函数名 | 与类名一致 | +| `CreatePrimFuncPass` 第三参数 | `"tl.{PascalCase}"` | +| `TVM_REGISTER_GLOBAL` | `"tl.transform.{PascalCase}"` | +| 配置键字符串 | `"tl.{lower_snake_case}"` | +| Python 函数名 | 与 C++ 类名一致(`PascalCase`) | +| 文件名 | `lower_snake_case.cc`(与 `src/transform/` 现有文件一致) | +| Python 配置 enum | `TL_{UPPER_SNAKE_CASE}` | + +--- + +## 5. 跨文件命名对齐速查 + +落代码完成后跑一次: + +```bash +grep -n "{PassName}" \ + src/transform/{pass_name}.cc \ + tilelang/transform/__init__.py \ + tilelang/engine/phase.py + +grep -n "tl.{pass_name_lower}" \ + src/transform/{pass_name}.cc \ + tilelang/transform/pass_config.py +``` + +三处 + 配置键两处都能命中且一致 → 命名通过。 + +--- + +## 6. 与测试 skill 的交棒 + +实现侧代码生成完毕后,本 skill 的产出可以作为测试 skill 的输入: + +- **本 skill 的产出**:实现完成的 `.cc` / `__init__.py` / `pass_config.py` / `phase.py` +- **测试 skill 的输入**:上述实现文件 + `pass-design.md` §5 测试方案 +- **测试 skill 的产出**:`testing/python/...` 下的 UT/ST + +> 本 skill 完成报告里要把「测试待补清单」明确列出,便于测试 skill 直接接续。 diff --git a/.agents/skills/tilelang-pass-generate/templates/pass-impl-skeleton-template.md b/.agents/skills/tilelang-pass-generate/templates/pass-impl-skeleton-template.md new file mode 100644 index 000000000..57a06e20c --- /dev/null +++ b/.agents/skills/tilelang-pass-generate/templates/pass-impl-skeleton-template.md @@ -0,0 +1,260 @@ +# {Pass 名称} 实现骨架文档(pass-impl-skeleton.md) + +> 本文件是「**代码层面的最后一次结构化对齐**」。比 `pass-design.md` 更落地,但比真实代码更轻量。 +> 在用户确认本骨架前,**禁止生成任何 .cc / .py 代码**。 +> +> ⚠️ 本骨架**只覆盖实现侧**(C++ / Python wrapper / pass_config / phase.py)。 +> UT/ST 测试不在本骨架范围内,由后续独立 skill 处理。 + +--- + +## 0. 任务摘要 + +- **任务类型**:{新增 / 修改 / 重构} +- **设计文档**:{pass-design.md 路径} +- **Pass 名称**:{PassName} +- **阶段归属**:{Phase 1: LowerAndLegalize / Phase 2: OptimizeForTarget} +- **Pipeline 位置**:{在 PassA 后、PassB 前} +- **平台范围**:{平台无关 / Ascend 特定} + +--- + +## 1. 改动文件清单(实现侧,仅 4 类) + +| 序号 | 文件 | 状态 | 说明 | +|------|------|------|------| +| 1 | `src/transform/{pass_name}.cc` | {新建 / 修改} | C++ 主实现 | +| 2 | `tilelang/transform/__init__.py` | 修改 | Python 封装 | +| 3 | `tilelang/transform/pass_config.py` | {修改 / 不动} | 配置键定义(可选) | +| 4 | `tilelang/engine/phase.py` | 修改 | Pipeline 接入 | +| 5 | (可选)`src/transform/common/{helper}.h` | 新建 | 公共辅助类 | + +> 测试文件(`testing/python/...`)**不在本骨架范围内**,由 Pass 测试生成 skill 处理。 + +--- + +## 2. C++ 类骨架(仅签名,不写实现体) + +### 2.1 主类 + +```cpp +namespace tvm { +namespace tl { + +class {PassName} : public {父类: arith::IRMutatorWithAnalyzer / StmtExprVisitor / StmtExprMutator} { +public: + // Pass 入口 + static PrimFunc Substitute(PrimFunc f, PassContext ctx); + +private: + // 构造函数 + {PassName}(PrimFunc f, PassContext ctx, {输入 attrs 参数}); + + // 成员变量 + {Map>} input_attr_; // 来自 {上游 Pass} + {Map} output_attr_; // 供给 {下游 Pass} + // ... 其他状态 + + // 重写的 Visit 方法(仅列签名) + Stmt VisitStmt_(const ForNode* op) final; + Stmt VisitStmt_(const BufferStoreNode* op) final; + Expr VisitExpr_(const BufferLoadNode* op) final; + // ... 仅列将要重写的节点类型 + + // 辅助方法 + bool IsTargetPattern(const {NodeType}* op) const; + Stmt RewriteStmt(const {NodeType}* op); +}; + +} // namespace tl +} // namespace tvm +``` + +### 2.2 辅助类(如有,按 CrossCorePipeline 模式拆分) + +```cpp +class {PassName}Detector : public StmtExprVisitor { ... }; +class {PassName}Analyzer { ... }; +class {PassName}Rewriter : public IRMutatorWithAnalyzer { ... }; +``` + +> 仅当设计文档 §4.1 明确表示需要多类协作时才拆分;否则保持单类。 + +--- + +## 3. Substitute 入口流程(伪代码,逐行) + +``` +PrimFunc Substitute(PrimFunc f, PassContext ctx): + 1. 读取配置(若有配置键) + bool enabled = ctx->GetConfig(k{PassName}Config, Bool({默认值})).value(); + if (!enabled) return f; + + 2. 读取上游 attrs + auto attr = f->GetAttr<{Type}>("{key}"); + if (!attr.defined()) { + // 缺失策略:{报错 / 跳过 / 默认值} + } + + 3. 构造变换器实例 + {PassName} mutator(f, ctx, attr.value()); + + 4. 执行变换 + PrimFunc new_f = mutator.MutateFunc(f); # IRMutatorWithAnalyzer + // 或 mutator.VisitStmt(f->body); # StmtExprVisitor + + 5. 设置输出 attrs(如有) + new_f = new_f.WithAttrs({{"{out_key}", mutator.GetOutput()}}); + + 6. 返回 + return new_f; +``` + +--- + +## 4. Attr 读写表 + +### 4.1 输入 attrs + +| 键名 | 类型 | 来源 Pass | 缺失策略 | +|------|------|-----------|----------| +| `{key1}` | `Map>` | `{产生 Pass}` | {报错 / 跳过 / 默认值} | +| `{key2}` | `Map` | `{产生 Pass}` | {报错 / 跳过 / 默认值} | + +### 4.2 输出 attrs + +| 键名 | 类型 | 下游消费 Pass | +|------|------|----------------| +| `{out_key1}` | `{Type}` | `{消费 Pass}` | + +--- + +## 5. 注册与配置键 + +### 5.1 Pass 注册 + +```cpp +tvm::transform::Pass {PassName}() { + auto pass_func = [=](PrimFunc f, IRModule m, PassContext ctx) { + return {PassName}::Substitute(std::move(f), ctx); + }; + return CreatePrimFuncPass(pass_func, 0, "tl.{PassName}", {}); +} + +TVM_REGISTER_GLOBAL("tl.transform.{PassName}").set_body_typed({PassName}); +``` + +### 5.2 配置键(可选) + +```cpp +static constexpr const char *k{PassName}Config = "tl.{pass_name_lower}"; +TVM_REGISTER_PASS_CONFIG_OPTION(k{PassName}Config, Bool); +``` + +> 默认值:`Bool(false)`。Ascend 特定 Pass 默认不开启,由 `pass_configs` 显式启用。 + +--- + +## 6. Python 封装函数签名 + +```python +# tilelang/transform/__init__.py + +def {PassName}({可选参数: target=None / is_npu=False}): + """{一句话说明}。 + + {补充说明:上下游依赖、典型使用场景} + + Returns + ------- + fpass : tvm.transform.Pass + The result pass. + """ + return _ffi_api.{PassName}({可选参数}) +``` + +--- + +## 7. Pipeline 接入点(具体到上下文) + +### 7.1 接入位置 + +**目标函数**:`{LowerAndLegalize / OptimizeForTarget}`,文件 `tilelang/engine/phase.py` + +**插入位置**:在 `{上游 Pass 行}` 之后、`{下游 Pass 行}` 之前 + +### 7.2 接入 diff(伪 diff) + +```python + mod = tilelang.transform.{上游 Pass}()(mod) ++ # ===== 新增 Pass ===== ++ mod = tilelang.transform.{PassName}()(mod) ++ # ===== + mod = tilelang.transform.{下游 Pass}()(mod) +``` + +### 7.3 配置键索引(如有) + +```python +# tilelang/transform/pass_config.py + +class PassConfigKey(str, Enum): + TL_{PASS_NAME_UPPER} = "tl.{pass_name_lower}" + """Enable/disable {PassName}. Default: False.""" +``` + +--- + +## 8. 最小冒烟验证步骤(生成代码后立即跑,不依赖 UT/ST) + +按顺序执行,遇到第一个失败就停下来定位: + +1. **导入冒烟**: + ```bash + python -c "import tilelang; from tilelang.transform import {PassName}; print({PassName}())" + ``` +2. **跨文件命名一致性 grep**: + ```bash + grep -n "{PassName}" src/transform/{pass_name}.cc tilelang/transform/__init__.py tilelang/engine/phase.py + grep -n "tl.{pass_name_lower}" src/transform/{pass_name}.cc tilelang/transform/pass_config.py + ``` +3. **最小 example 跑通**(已有 example,不新建): + ```bash + python {仓库已有的最小 example,例如 examples/elementwise/...} + ``` +4. **构建冒烟**(如果本机能跑):{按仓库脚本} + +--- + +## 9. 风险与待确认项 + +### 9.1 已知风险 + +- {风险 1:例如 attr 类型与上游 Pass 是否完全一致} +- {风险 2:例如 Pipeline 顺序是否与现有 Pass 冲突} + +### 9.2 待用户确认 + +- {项 1:是否需要新增配置键,默认值是否合理} +- {项 2:Pipeline 位置是否需要进一步收敛} + +--- + +## 10. 测试待补(交棒标记) + +> 本骨架文档**不展开测试细节**。 +> +> 设计文档 §5 已经列出测试方案(功能/依赖/边界),由后续独立的 Pass 测试生成 skill 负责落地。 +> 实现代码生成完成后,请使用 Pass 测试生成 skill 接续这部分工作。 + +--- + +## 11. 用户确认提示 + +请用户确认以下三件事后,才进入代码生成阶段: + +1. ☐ 上述 C++ 类骨架(父类、Visit 方法、辅助类)符合预期 +2. ☐ Pipeline 接入位置(具体到上下游 Pass)符合预期 +3. ☐ Python 封装函数签名(参数、命名)符合预期 + +确认后回复「确认骨架」或指出需要调整的具体条目。