插件开发与发布¶
UCAgent 插件用于独立交付领域能力。一个插件可以按需提供 Tool、Checker、Skill、 Guide_Doc 和工作流中的任意一种或多种能力;这些贡献都是一级可选项,互不依赖,也不 要求插件提供完整工作流。插件是普通 Python 发行包:安装后通过标准 entry point 自动 发现;源码开发时也可以通过显式配置的搜索路径发现。插件必须由用户选择后才会导入和 激活,UCAgent 不会扫描或执行任意 workspace Python 文件。
plugins/RTL2Spec/ 提供文档生成插件;plugins/DesignWithPPA/ 展示自定义 Tool、Checker、模板、Skill 与工作流的组合。
同仓维护的可选插件¶
plugins/ 用于维护随 UCAgent 一同开发、独立打包的插件。安装核心包不会安装或启用 这些插件。插件的日常开发应限定在自己的目录中:依赖、入口、配置、资源、测试和维护 命令均由插件管理,不向核心的依赖清单、默认配置或 Tool/Checker 导出表添加插件内容。
| 内容 | 维护位置 |
|---|---|
| 插件 API、加载机制、通用贡献流程和漏洞报告渠道 | UCAgent 核心及仓库根目录 |
| 清单、打包配置、依赖、实现、工作流、资源和测试 | 各插件目录 |
| 插件专用忽略规则、编辑规范、文件属性、使用与维护说明 | 各插件目录,可继承仓库通用规则 |
| 核心和仓库公共 CI | 根目录 .github/workflows/ |
| 插件安装、验证、打包和安装态测试命令 | 插件目录中的脚本或 Makefile |
子目录的 .gitignore、.editorconfig 和 .gitattributes 不代表独立仓库,也不是插件 运行的必需文件;按实际维护需求保留,避免将插件专用规则扩散到整个仓库。插件维护者 使用同一提交的 UCAgent 在本地执行插件验证;新增插件无需添加根目录 CI workflow。 只有公共插件接口或仓库级基础设施发生变化时,才需要同步修改对应核心文件。
当前同仓插件如下。各插件的运行依赖、案例及维护命令见对应 README:
| 项目 | 插件 ID / 工作流 | 主要用途 |
|---|---|---|
| DesignWithPPA | design-with-ppa:unit-design-tdd | 测试驱动 RTL 设计与 PPA 优化 |
| RTL2Spec | rtl2spec:design-document | 基于 XiangShan 源码和生成 RTL 的证据,交付版本化中文设计与功能检测点文档 |
先安装核心,再从 UCAgent 仓库根目录按需安装,例如:
运行时显式选择 --plugin rtl2spec 和 --plugin-workflow rtl2spec:design-document。 源码开发时可将插件 ID 换成 --plugin ./plugins/RTL2Spec,无需先安装插件。 工作区独立于插件实现;随包指导文档和其他资源由选中的工作流自动定位和复制。
名称约定¶
一个插件通常有四种名称,分别服务于目录、Python 打包、插件选择和代码导入:
同仓插件的项目目录建议使用 PascalCase(大驼峰),如 DesignWithPPA、RTL2Spec。 这是目录风格约定,加载器不依赖目录名的大小写。
| 层级 | DesignWithPPA 示例 | RTL2Spec 示例 | 用途 |
|---|---|---|---|
| 项目目录 | DesignWithPPA | RTL2Spec | 文件系统路径 |
| 发行包名 | ucagent-design-with-ppa | ucagent-rtl2spec | pip 安装和发行包 metadata |
| 插件 ID | design-with-ppa | rtl2spec | entry point、清单、CLI 选择器 |
| Python 包名 | design_with_ppa | rtl2spec | Python import 路径 |
插件 ID 必须匹配 ^[a-z0-9]+(?:[._-][a-z0-9]+)*$:使用小写字母、数字,分隔符 -、_、. 只能出现在非空片段之间。ID 在同一 Python 环境和同一次 UCAgent 运行中 保持唯一。插件不应保留已废弃名称的兼容入口,否则发现结果和 配置容易产生歧义。
必须完全一致的是清单 name、ucagent.plugins entry point 的键和 provider 返回的 Plugin.name;清单 entry 与 entry point 的值也应指向同一个 provider。项目目录和 Python 包名不必与插件 ID 字面一致,文档示例的大小写及 ucagent- 前缀不是额外的加载 规则。--plugin 使用插件 ID 或项目路径,不能用发行包名或 Python 包名代替插件 ID。 工作流名遵守同样的 ID 字符规则,在所属插件内唯一,以 <插件 ID>:<工作流名> 选择。
标准项目结构¶
只创建实际发布的资源目录。纯 Tool、纯 Checker、纯 Skill、纯 Guide_Doc 或纯工作流 插件都是有效插件。后续可以在同一发行包中增加其他贡献,无需修改 UCAgent 核心包。 运行时脚本可放在包内的 scripts/;测试和维护配置放在插件项目根目录。 同仓插件遵守相同结构,项目根位于 plugins/<项目目录>/。加载器按清单定位项目, 不依赖父目录名称。标准结构不要求保留空目录。
本地引导清单¶
源码态项目根目录必须包含 ucagent-plugin.toml:
清单只允许这四个字段:
schema_version:当前必须为1;name:稳定插件 ID,必须和 provider 返回的Plugin.name完全一致;entry:module.path:provider形式的 provider;python_path:相对项目根目录的 Python 导入根。
清单和 python_path 仅用于本地源码加载。安装后的 wheel 使用发行包 entry point, 不依赖本地清单,但 wheel 中可以保留同一份项目清单用于源码开发和审查。
安装态自动发现¶
插件的 pyproject.toml 必须注册 ucagent.plugins entry point:
核心和插件必须安装到同一 Python 环境。先按 UCAgent 安装说明安装核心,再安装插件的 本地目录、wheel 或已经发布的发行包;不能假定示例包已在 PyPI 发布。requires_ucagent 和发行包的 UCAgent 依赖范围应一致,下限使用实际验证过的版本。
安装后,Python 的 distribution metadata 会提供发现信息,例如从 UCAgent 根目录运行:
--list-plugins 只读取 entry point 名称和本地清单,不导入 provider。 --validate-plugin 才会导入被选择的 provider,并校验插件 API、UCAgent 版本、Python 依赖、外部命令和资源。UCAgent 不会在运行时自动安装依赖;缺失项会作为可操作错误返回。
源码态配置搜索¶
不安装插件时,在任一正常配置层增加 plugin.search_paths:
该字段必须是字符串列表,经过正常配置分层与 {WORKSPACE} 模板解析。每个路径可以:
- 直接指向包含
ucagent-plugin.toml的插件项目; - 指向包含多个插件项目的集合目录,UCAgent 只检查其一级子目录。
路径必须存在;不会递归扫描整个目录树。发现时只读取严格清单,按 name 精确匹配后才 导入 provider。若安装态 entry point 和搜索路径存在同 ID,启动会列出安装 distribution 和本地清单路径并报歧义;不得依赖来源优先级静默选择。
相对搜索路径以启动 UCAgent 时的当前工作目录为基准。用户级或 workspace 配置需要跨 目录稳定运行时,应使用绝对路径或 {WORKSPACE} 模板。
需要强制调试某个源码副本时,直接传项目路径:
使用稳定 ID 的配置示例:
配置列表按 UCAgent 的整体替换语义处理。工作区配置覆盖用户配置时,应写出完整的预期 搜索路径列表。
Provider 与运行时上下文¶
Provider 返回 ucagent.plugins.Plugin:
Plugin 的能力字段均默认为空:
| 字段 | 独立贡献合同 |
|---|---|
tool_factories | 创建一个或多个 UCTool;不依赖工作流 |
checkers | 注册一个或多个 Checker 子类;不依赖 Tool 或工作流 |
guide_doc_paths | 插件激活时合入 runtime Guide_Doc 的文件或目录 |
skill_paths | 插件激活且 Skill 功能开启时复制的 Skill 集合目录 |
workflows | 可选择的完整配置入口及该工作流专属资源 |
允许所有能力字段为空,便于先发布和验证插件的 metadata、依赖及资产合同,再逐步增加 能力。实际发行版本应至少提供一种对用户有用的能力或资产。
PluginContext 在配置解析完成后传给工具工厂,包含:
| 字段 | 合同 |
|---|---|
workspace | 当前 workspace 的绝对 Path |
output_dir | 相对 workspace 的输出目录 |
write_dirs | 最终解析的可写目录元组 |
un_write_dirs | 最终解析的禁止写目录元组 |
cfg | 最终解析、已冻结的 UCAgent 配置;不得整体写入日志或报告 |
plugin_root | 当前插件 provider 包目录的绝对 Path |
工具必须继承 UCTool,使用 Pydantic BaseModel 作为 args_schema,并遵守 workspace 路径和读写策略。一个工厂可以返回一个工具或工具列表。UCAgent 会拒绝非 UCTool、 插件间同名工具以及和核心/外部工具同名的工具。插件工具进入 Agent 与 MCP 的同一标准 过滤流程,因此 tools.ignore_tools 和 tools.selected_tools 都会生效。
Checker¶
checkers 中的每一项必须是 ucagent.checkers.base.Checker 的子类。激活插件后,任意 正常配置文件都可以通过类的短名引用它,不要求配置属于该插件的工作流:
UCAgent 会显式地把插件 Checker 注册表传给阶段解析器,不会把类写入全局 ucagent.checkers 模块。Checker 类名在所有已激活插件之间必须唯一,也不能与核心 Checker 同名。完整 dotted path 仍可用于普通可导入类,但正式的 checkers 声明提供 启动时类型校验、短名引用、冲突检测和插件摘要。
隔离执行生成代码¶
Checker 不得在 UCAgent 主进程中导入或执行 workspace 生成的 Python 模块。需要验证 Python DUT、coverage definition、测试配置或其他生成代码时,应使用 RunTestCases; 若必须检查仅能通过执行获得的结构,则使用有超时、输出上限和副作用隔离的子进程。
使用 python -I 启动隔离子进程时,不能依赖 PYTHONPATH:isolated mode 会忽略该 环境变量。父进程必须显式传入并由子进程加入 sys.path 的受信任导入根至少包括:
- 从当前已加载
ucagent包位置推导出的精确 UCAgent import root; - 当前运行已激活的源码插件 import root;
- 目标生成模块目录和 workspace,仅在上述受信任运行时路径之后加入。
导入顺序是安全合同的一部分。当前 UCAgent 根必须先于 workspace,避免生成目录中的 同名 ucagent 包遮蔽正在运行的实现。不要从当前目录名、仓库名、环境变量或另一个已 安装 distribution 猜测 UCAgent 路径;源码运行、editable install 和 wheel 安装都必须 解析到同一份正在运行的包。
此类 Checker 的测试应同时证明:源码插件能够在隔离子进程中导入当前 UCAgent;目标 模块不会出现在父进程的 sys.modules;子进程对环境变量、模块全局状态和 bytecode 的 修改不会污染主进程或 workspace;导入失败、超时和超量输出会返回有界诊断。
独立 Guide_Doc 与 Skill¶
guide_doc_paths 和 skill_paths 是插件级贡献,选中插件后即可生效,不要求选择 --plugin-workflow。Guide_Doc 可以声明单个文件或目录;Skill 路径必须是包含至少一个 有效 SKILL.md 的集合目录。每个 Skill 的 YAML frontmatter 必须包含规范的 name 和 非空 description,且 name 必须与目录名一致。Guide_Doc 贡献要求最终配置的 guide_doc.enable 为 true;禁用 runtime Guide_Doc 的特殊运行模式会明确拒绝 Doc 插件,而不会把文件复制到一个不会被使用的位置。插件 Skill 被复制到:
Skill 始终是可选能力。最终配置 skill.use_skill: false 或 CLI --no-use-skill 会跳过 所有插件 Skill 的复制、工具和使用证据门禁,但不会禁用同一插件的 Tool、Checker、 Guide_Doc 或工作流。插件级 Guide_Doc 仍会正常加载。阶段配置通过 ext/<plugin-id>/<skill-relative-path> 引用已复制的插件 Skill。
组合核心 Guide_Doc¶
插件或插件工作流可以在自己的配置 YAML 中通过 guide_doc.core_copy_policy 精确选择如何 复用当前语言默认配置提供的 Guide_Doc 文件:
四个字段必须同时存在,含义如下:
| 字段 | 行为 |
|---|---|
default_action | 未在列表中出现的核心文档默认执行 retain 或 ignore |
retain | 复制并保留核心文档;插件提供内容不同的同路径文件时启动失败 |
override | 不复制该核心文档,改为复制插件提供的同路径文件;插件未提供时启动失败 |
ignore | 不复制该核心文档;插件也不得提供同路径文件 |
列表项是相对于当前语言默认 Guide_Doc 根目录的精确 POSIX 文件路径。路径必须使用规范 形式,不能是绝对路径,不能含 ..、反斜杠、前后空白或重复项;三个动作列表也不能 相交。显式列出的路径必须确实存在于当前语言默认文档中。插件新增且不与核心重名的文档 无需列入策略,会照常复制。
该配置跟随普通配置分层规则:插件工作流 YAML 可以声明默认组合,workspace 配置、显式 --config 和 CLI --override 可以继续覆盖它。列表采用完整替换语义,因此覆盖某个动作 列表时应给出该层需要的完整列表。未声明策略时,核心默认值等价于全部 retain,保持普通 工作流的原有行为。
插件自身贡献的文档可通过 guide_doc.plugin_copy_policy 选择。该策略适合按最终配置只公开 当前工作流需要的语言或目标文档;模板变量会在策略解析前完成替换:
三个字段必须同时存在。default_action 及显式动作只能是 retain 或 ignore;路径规则与 核心策略相同,并且显式路径必须由当前已激活插件实际提供。ignore 还会删除 workspace 中 同路径的旧插件文档,防止切换配置后继续读取过期资源。插件与核心同路径文档是否替换仍由 guide_doc.core_copy_policy 的 retain/override/ignore 决定。
工作流及其专属资源¶
插件可以声明 PluginWorkflow,把未来工作流和发行包绑定:
调用时先激活插件,再选择工作流:
--plugin-workflow 和 --config 可以同时使用。工作流配置是独立基线层,不会冒充用户 配置文件;最终优先级为:核心全局、用户全局、核心语言默认、插件工作流、workspace 设置、显式 --config、CLI --override。未限定插件 ID 的短工作流名只有在已激活插件 中唯一时才允许。运行元数据会分别保留显式配置、插件与工作流选择器和工作流配置来源。 同一信息也写入 .ucagent/runtime_config.json 的 launch_context;插件显式声明的非秘密 最终配置标量单独写入 plugin_options,不会把完整配置或凭据复制到运行时快照。
PluginWorkflow 的资源和依赖字段都可选:
| 字段 | 工作流选择后的合同 |
|---|---|
config_file | 独立工作流配置层;必须是插件根内的 YAML 文件 |
guide_doc_paths | 追加该工作流专属 runtime Guide_Doc |
template_dir | 该工作流模板源目录 |
template_target | workspace 相对目标模板,例如 {OUT};不得解析为 workspace 根、逃逸路径或与只读路径重叠 |
template_context_factory | 可选受信任函数;根据最终配置与核心模板上下文返回额外模板变量,不能覆盖 DUT、OUT、WORKSPACE 等核心值 |
skill_paths | Skill 启用时追加的可选工作流 Skill 集合 |
python_requirements | 仅选择该工作流时检查的 Python 依赖 |
command_requirements | 仅选择该工作流时检查的外部命令能力 |
runtime_config_keys | 明确允许写入 runtime snapshot plugin_options 的非秘密标量路径 |
插件级依赖在插件激活时检查;工作流依赖只在工作流被选择后检查。因此仅使用 AnalyzePPA 不要求 Picker,而选择 unit-design-tdd 后才要求 picker console command。 不要为未验证的工具声明推测的 PyPI 版本;应校验真实 console command、版本输出和工作流 所需子命令。
工作流的 guide_doc_paths 和 skill_paths 只在选择该工作流时,追加到插件级资源;重复 声明的同一路径会去重。template_dir 仍是工作流专属资源,因为模板渲染必须和该次运行 的完整配置入口保持一致。不同 Skill 根不能包含会复制到同一插件相对路径的 Skill;该类 目标冲突会在启动时失败,而不是静默覆盖。
所有声明的工作流配置、Guide_Doc、模板、Skill 和资产必须存在并位于 Plugin.root 内部;符号链接也不能逃逸。插件自身的多个 Guide_Doc 来源若向同一路径提供不同内容会 启动失败。插件与核心文档同名时按照 guide_doc.core_copy_policy 处理;未显式允许 override 时不会静默覆盖。完全相同的保留文件允许幂等复用。插件 Skill 是可选加速路径: --no-use-skill 下不复制 Skill,工作流提示、工具和 Checker 仍必须提供完整的非 Skill 路径并保持同一验收标准。指定 template_target 时,渲染器只合入并渲染该模板源拥有的 文件,不会遍历或重写目标目录中的其他既有产物,也会在写入前拒绝目标与 {DUT} 等 最终 un_write_dirs 中的具体只读路径重叠。
template_context_factory(cfg, base_context) 在最终配置层合并后、阶段与模板渲染前调用。 它适合由已解析的语言、目标平台等配置同时选择提示变量、模板文件名和模板内容。返回值 必须是有限 JSON mapping,键必须是非空字符串;工厂不能覆盖核心上下文。动态值的优先级 高于工作流 YAML 的静态 template_overwrite,显式 --template-cfg-override 仍可覆盖最终 文件渲染值。
在 pyproject.toml 的 package data 中显式包含非 Python 资源,例如:
sdist 还应通过 MANIFEST.in 递归包含同一资源集合以及本地 ucagent-plugin.toml 和测试; 不能只依赖源码树中恰好存在的文件。
校验、构建、安装与发布¶
先准备插件声明的外部工具。以下命令从 UCAgent 仓库根目录验证同一份核心和插件源码:
其他插件将上述插件路径替换为自己的项目目录。python3 -m build 的默认流程先构建 sdist、再由 sdist 构建 wheel,可以隔离源码树中既有的 build/ 缓存,避免陈旧文件进入发布包。 也可以使用等价的 uv build 默认流程。不要只对可能含旧缓存的源码树运行 python3 -m build --wheel。
对生成的 wheel 还必须做安装态验证,不能只从源码目录导入:
发布检查清单:
- 清单
name、entry point 名称和Plugin.name完全一致; Plugin.version与发行包版本一致,requires_ucagent覆盖实际测试版本;- Python 依赖同时出现在发行包 metadata 和
Plugin.python_requirements校验声明中; - 外部命令提供准确名称和可接受的可执行文件替代项;
- wheel 中包含所有配置、文档、模板、Skill、脚本和资产;
- sdist 中包含
ucagent-plugin.toml、测试和构建 wheel 所需的全部文件; - 本地路径、配置搜索路径和安装 entry point 三种发现方式经过测试;
- 每个 Tool 通过直接调用、失败边界、MCP schema 转换和工具过滤测试;
- 每个 Checker 通过类型校验、短名解析、生命周期及名称冲突测试;
- 独立 Guide_Doc、Skill 和工作流分别在不提供其他能力时经过激活测试;
- 每个工作流在 Skill 启用、显式禁用及 Skill 目录不存在时都能完成;
- 安装态测试从 wheel 运行,不依赖仓库内的
src路径; - 发布新版本后,用
python3 -m pip install --upgrade <发行包或 wheel 路径>更新, 再运行ucagent --validate-plugin <插件 ID>。
常见失败¶
available=[]:插件未安装,且最终配置的plugin.search_paths未包含项目或父目录;manifest name ... does not match:本地清单 ID 与 provider 的Plugin.name不一致;requires Python package:当前 UCAgent Python 环境缺少插件依赖或版本不满足;requires command:外部分析工具不在当前进程的PATH;resource must remain inside plugin root:provider 声明了包外路径或逃逸符号链接;selector is ambiguous:多个 entry point、本地插件或工作流使用了冲突名称;错误会列出 候选 distribution 或清单路径,应卸载、移除搜索路径或显式使用唯一源码项目路径;Duplicate plugin Checker name:两个已激活插件声明了同名 Checker;conflicts with a core Checker:插件 Checker 类名占用了核心 Checker 短名;- 工具不在 Agent/MCP:确认已传
--plugin,再检查最终的tools.ignore_tools与tools.selected_tools。
运行工作流的开放契约¶
插件工作流必须把 LLM 实际需要遵守的规范文件列入当前阶段的 reference_files,不能 只依赖失败后的错误提示。例如使用行映射 Checker 时,阶段必须同时提供 Guide_Doc/dut_line_func_map.md 和当前生成的功能合同;任务提示还应明确单行物理范围也 使用完整的 start-end,例如 10-10,不能写成单个数字 10。规范文件缺失会让能力较弱 的模型反复试错,也会把本可避免的格式错误计入阶段失败。
阶段配置、模板上下文和能力依赖在 UCAgent 启动阶段一次性解析并复制到运行 workspace。 修改插件 YAML、Guide_Doc 或模板后,必须重新启动工作流并重新生成 workspace;运行中的 Agent 不会热加载这些文件。恢复或重试时要检查生成文件与当前解析配置的来源、哈希和 语言选择是否一致,不能把旧 workspace 的产物当作新配置的证据。
命令行 backend 可能自带 shell、文件浏览和外部目录读取能力,不能只靠系统提示要求模型 遵守 workspace 边界。工作流若要求测试、转换或分析只能由受信任 Tool/Checker 执行, backend 配置必须同时禁用原生 shell 并拒绝 workspace 外路径;读写当前 workspace 仍使用 backend 的受限文件工具,测试与外部命令使用公开 MCP Tool。应通过真实 backend 会话验证 被禁用能力确实返回拒绝,而不是仅验证配置文件包含对应字段。
批处理 Checker 的阶段文档会被模型反复编辑。每次精化或补充说明后,必须在完整文档上 检查 FG/FC/CK ID 全局唯一、父子路径和行映射引用闭合;不能把同一个 CK 的新描述追加到 另一个 FC 下,也不能只检查当前 batch 而忽略已完成批次。提交 refined 进度时只允许 使用当前 CurrentTips 给出的完整 CK 路径,完成后重新获取下一批。
批处理模板还必须区分“覆盖模型已声明 CK”和“测试函数已关联 CK”两类证据。覆盖组通常在 模板阶段之前一次性声明全部 CK,但这不代表全部模板已经生成。当前 Check 只要求历史已完成 项和 CurrentTips 当前批次存在真实测试关联;未来批次可以暂未关联,也不得提前关联并跳过 批次。源文档或测试关联变化时,应从当前文件和测试报告重新同步进度,而不能把覆盖声明或 旧 checkpoint 当成完成证据。
coverage predicate 本身也是独立证据,不能用 bin 名称存在来代替“条件已实现”。需要分批 实现 predicate 的工作流应在结构阶段为完整 CK 集写入唯一的显式 false 占位;实现阶段通过 AST 或等价源码证据区分占位与非恒定 predicate,只允许替换 CurrentTips 当前批次。恒真 callable、提前实现未来批次、已完成项回退为占位都必须拒绝。源码门禁只能证明条件已编写; predicate 是否可达以及是否与真实刺激匹配,仍要由随后隔离执行的 pytest coverage hit 证明。
复用核心批处理 Checker 时,先确认它的“报告通过”语义是否与插件工作流一致。验证工作流 可以保留由正确测试暴露的 DUT Bug,而设计生成工作流通常要求当前测试全部 Pass;两者不能 共用同一个最终报告判定。需要不同语义时,应继承 UnityChipCheckerBatchTestsImplementation,通过 _validate_current_batch_report(report) 只替换当前批次的报告门禁,并继续复用它的源码重同步、精确节点执行、checkpoint 和批次推进 状态机。若工作流不使用 Bug 文档,还应让 _cached_document_preflight(target_tests) 返回 None,不能让无关的 Bug 文档预检阻塞测试批次。报告门禁必须只检查本次精确节点的状态、 CK 关联和命中证据;完整覆盖模型中未由本批次执行的其他 CK 是局部报告中的正常未命中, 不能据此拒绝当前批次。门禁失败时不得调用批次完成或持久化进度,并应覆盖“拒绝后重建 Checker 仍从同一批开始”的回归测试。
批量实现 Python 测试时必须原位修改 CurrentTips 指定的已有模板函数,不能在文件前后追加 同名 def。每次写入后应对整个测试文件做 AST 级顶层函数名唯一性检查,并确认 mark_function 引用的正是该唯一函数;否则后定义会覆盖模块属性,pytest 收集、覆盖关联和 LLM 看到的实现可能指向不同函数,真实实现也可能被旧占位断言隐藏。
规范文档中的 fenced YAML 必须用真实 YAML 解析器预检。包含冒号、哈希、花括号模板或 其他 YAML 语法字符的自然语言值应显式使用引号;例如 packing: "element k occupies bits [8*k+7:8*k+0]",不能让冒号被解析成新的 mapping。 不要把“看起来像 YAML”的 Markdown 文本当作有效证据;Check 失败时应修复具体字段并 重新解析整个 fenced block。
外部工具依赖应声明真实的 console command、版本参数和所需子命令,并在缺失、版本不符或 子命令不可用时返回明确的下一步。只使用 Tool 时不应加载工作流专属依赖;只有选择对应 工作流才检查其能力。测试、转换和分析产生的临时文件应由受信任的 Check/Complete 子进程 管理,阶段 LLM 只接触公开源码语言、Python 测试和结果摘要。
插件提供的清理入口属于开发便利功能,不能依赖 Git 状态来决定删除范围。清理目标必须是 插件根目录内列举的输出、构建和缓存目录,并拒绝通过可覆盖的 workspace 或 output 参数 扩大范围;已跟踪源文件和用户对源文件的修改必须保持不变。发布前应在临时目录验证“目标 缓存被删除、无关文件保留、插件根外路径不会被触碰”这三个边界。