关于 debug-extension
面向调试已构建 `.ppmplugin` 控件的工程师,采用先调查再修复的流程。它沿 PCF、分发契约、原生模块和构建配置追踪症状,并基于证据提出修复方案。
主要功能
- 01将症状映射到候选故障层
- 02追踪 PCF 到原生模块的分发路径
- 03比较平台实现和响应格式
- 04诊断并确认后应用修复
适用场景
- 01排查 PCF 错误代码或无响应
- 02调查平台间行为差异
- 03查找原生模块未加载的原因
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill debug-extension安装后在 Claude Code 中输入/debug-extension确认已加载。
详细介绍
/debug-extension
调查用户在测试已构建的 .ppmplugin 控件时遇到的故障,找出根本原因并修复。封装二进制文件在客户的 shell 中运行,无法访问 logcat / Xcode 控制台 / 原生调试器,因此证据通常只有 PCF 的 ErrorCode / ErrorMessage、原始的 <name>Json 诊断输出、主机日志行,或用户对所见情况的描述。此技能会将这些有限的证据转化为已定位的根本原因和修复方案。
先调查,再通过修复解决。 与单纯的“应用此更改”流程不同,/debug-extension 从症状入手,反向追查原因,然后才修改代码。找到原因后,它会提出修复方案,并按照谨慎编辑的同一套规范应用修复(诊断规范与偏差、保持契约一致、精准修改、设置门禁)。
这是一种入口,但不是唯一入口。 根据 shared/shared-instructions.md §7.5,可从任何技能或普通对话轮次应用修复——用户不会被阻止,也不会被迫使用此技能。此技能为已报告的问题提供的是结构化流程:症状→层级分类、调用路径追踪,以及编辑前基于已定位证据进行诊断。当设备上出现故障且你还不知道原因时,使用此技能;对于已知要修改内容的计划内功能变更,直接编辑即可。
适用场景:
- “我点了按钮,但什么也没发生——没有错误,也没有界面变化。”(静默无操作)
- “PCF 显示
ErrorCode: PARSE/ErrorMessage: ...。”(需要追踪的代码) - “屏幕一加载,应用就崩溃。”(启动时崩溃)
- “主机日志显示
Loaded 0 plugin package(s)。”(原生加载特征) - “iOS 上能用,但 Android 上毫无反应。”(兼容性 / 传输错误)
- “Done 按钮返回了错误的数据。”(行为偏差)
不适用场景:
- 还没有仓库 →
/generate-native-extension。 - 全新的操作 →
/design-native-extension-feature,然后生成。 - 已知要修改什么、且未报告故障的计划内变更 → 直接编辑(使用任何技能或聊天)。
- 构建从未生成二进制文件 → 这是构建故障;先运行
/generate-ppmplugin并查看其阶段输出。
与 generate- 解耦。* 如果未检测到扩展仓库,此技能会拒绝运行。它不会搭建项目骨架、安装依赖项、构建二进制文件或组装包。它只负责诊断,然后编辑文件。
步骤 0 — 确认这是扩展仓库
按以下顺序检测仓库。如果缺少任何必需信号,则停止并报告 BLOCKED: not an extension repo (no <X> found)。
| 信号 | 必需? | 检查方式 |
|---|---|---|
仓库根目录存在 PRD.md | 是 | 规范是用于比对观测行为的基准。 |
仓库根目录存在 package.json | 是 | 确认这是生成的扩展仓库,而不是随意的目录。 |
仓库根目录存在 ARCHITECTURE.md | 否 | 强烈建议存在——其中包含追踪所依据的调用契约及各操作的实现。请将其缺失记为一项隐患。 |
仓库根目录存在 .extension-state.md | 否 | 提供参考信息——此前的编辑 / 偏差记录可作为调试线索。如果不存在,则在步骤 9 创建。 |
存在 pcf/ 文件夹,且其中包含 ControlManifest.Input.xml | 否 | 用于检测 PCF。使用 Glob 在 pcf/ 下定位清单,并记录 `has_pcf: true |
存在 ppmplugin/ 构建输出 / .ppmplugin 工件 | 否 | 提供参考信息——确认已构建二进制文件(此技能用于调试已构建的控件)。如果不存在,故障可能发生在构建前;请注明。 |
如果缺少 PRD.md 或 package.json,请建议使用 /generate-native-extension,然后停止。
步骤 1 — 阅读共享文档、PRD、ARCHITECTURE、清单和状态
按以下顺序阅读:
shared/shared-instructions.md— 常量、返回状态码(DONE/DONE_WITH_CONCERNS/BLOCKED/NEEDS_CONTEXT)和安全规则。shared/error-codes.md— 权威目录,以及症状 → 可能原因 → 查看位置映射。这是分类诊断(步骤 3)的核心输入。请完整阅读。shared/naming-conventions.md— 将 PRD 标识映射到用于追踪的文件路径。shared/repo-layout.md— 预期的文件树。shared/ppmplugin-format.md— 分发契约、封装sendAsync传输、{ isUpdate, message }响应容器,以及原生加载模型(§2、§5、§5b)。追踪传输/加载故障时必不可少。./PRD.md— 完整阅读(标识、操作、预期行为)。./ARCHITECTURE.md— 完整阅读(SDK 固定版本、逐操作实现说明、消息契约、§5 错误码、清单实现)。追踪过程将依据此文档。./manifest.json— 已提交的分发契约(name、receivers[].method、receivers[].nativeModule)。./.extension-state.md— 先前的## Edits/## Debug条目,以及记录的任何偏差 — 通常是最快的线索。
跳过 shared/prereq-check.md。 调试不会安装或验证身份验证。如果后续修复需要 PCF npm run build,步骤 8 会指出缺少的工具链。
根据 shared-instructions.md §9.2,在步骤 1 开始时打印一行前置条件提示:
Prereq check — /debug-extension: skipped (skill does no installs / auth / network — investigation only until a fix's smoke check).
步骤 2 — 收集错误报告
收集症状。如果用户调用此技能时未提供任何细节,请询问他们能提供以下哪些信息(合并成一次询问,而不是分五次):
- 实际发生的情况与预期情况(可观察到的行为)。
- PCF 上显示的
ErrorCode/ErrorMessage(或通过 Power Fx 中的Self.ErrorCode/Self.ErrorMessage获取)。 - 原始
<name>Json诊断输出(传输内容字节 — 传输层取证信息)。 - 任何宿主日志行(例如
Loaded 0 plugin package(s)、native module '<x>' not loaded、method '<m>' not found、堆栈跟踪)。 - 平台(iOS / Android / 两者)以及发生时机(启动时/点击时/操作后)。
- 复现步骤(如有)。
在追踪过程中保留原始报告,切勿概述而丢失细节,因为精确的代码或消息是信号最强的输入。不要原样保存。
.extension-state.md 会提交到仓库,而粘贴的报告通常包含原始响应、堆栈跟踪、宿主日志行、文件路径、URL、令牌或客户数据。步骤 9 会写入经过脱敏的一行摘要 — 详见该步骤中的脱敏规则。
步骤 3 — 分诊:将症状映射到候选层
使用 shared/error-codes.md(§2 模块代码、§3 传输代码、§4 无代码特征),将症状归类到一个或多个候选层,并按可能性从高到低排列:
| 层 | 出现以下症状时可归入此层…… |
|---|---|
PCF / 传输(pcf/<Pascal>PCF/index.ts) | PARSE、UNEXPECTED_PAYLOAD、BRIDGE_FAILED、NOT_IN_WRAP;点击后无响应;每次调用都以相同方式失败。 |
分发契约(./manifest.json ↔ 原生名称 ↔ PCF 键) | method '<m>' not found、native module '<x>' not loaded、带路由消息的 BRIDGE_FAILED;仅在一个平台上正常工作。 |
原生模块 — Android(android/.../<Pascal>Module.kt) | Android 上出现 INTERNAL_ERROR / PERMISSION_DENIED / NO_ACTIVITY;仅 Android 崩溃;Loaded 0 plugin package(s)。 |
原生模块 — iOS(ios/RCT<Pascal>Module.m) | iOS 上出现 INTERNAL_ERROR / PERMISSION_DENIED;仅 iOS 崩溃 / 无响应;+moduleName / requiresMainQueueSetup 加载问题。 |
| 原生加载 / 生命周期(构造函数、包类) | 在任何 UI 出现之前启动时崩溃;模块从未加载。 |
构建配置 / RN 固定版本(package.json、android/build.gradle、.podspec) | React 头文件 / 未定义符号错误;行为与 SDK 级别相关;固定版本与宿主 RN 不一致。 |
| 行为 / 规范(原生操作主体与 PRD/ARCHITECTURE 对照) | 结果错误、缺少控件、负载不正确——没有错误代码,只是输出错误。 |
单个报告可能涉及多个层(例如,UNEXPECTED_PAYLOAD 通常属于 PCF,但也可能是原生响应不符合规范)。列出所有合理的候选层;步骤 4 会确认或排除。
如果报告信息不足以进行分诊,请提出一个有针对性的澄清问题(例如:“两个平台都会失败,还是只有一个?”)。如果仍不清楚,请停止并给出
NEEDS_CONTEXT: <不清楚的内容>。
第 4 步 — 调查:追踪路径并收集证据
对于每个候选层,阅读相关文件,并用具体证据确认或排除假设。 不要猜测——打开文件并引用行号。
根据约定推导的文件(通过
shared/naming-conventions.md 中的 PRD 标识替换 <Pascal> / <lower>):
- PCF / 传输 →
pcf/<Pascal>PCF/index.ts(invokeBridge、extractResponse、onTrigger结果分支、args: [request]、复合键)、pcf/<Pascal>PCF/ControlManifest.Input.xml。 - 分发契约 →
./manifest.json中的receivers[];原生端的getName()(Android)/+moduleName(iOS);PCF 复合键<name>/<receiver>+method。交叉核对三者是否一致。 - Android 原生端 →
android/src/main/java/com/powerapps/<lower>/<Pascal>Module.kt(+<Pascal>CaptureActivity.kt)、ReactPackage类(公共无参构造函数)、android/src/main/AndroidManifest.xml。 - iOS 原生端 →
ios/RCT<Pascal>Module.{h,m}(+moduleName、+requiresMainQueueSetup、无参初始化)、被呈现的 VC。 - 构建 / 固定版本 →
package.json(RN 固定版本0.79.7)、android/build.gradle、ios/<Pascal>Extension.podspec。
追踪技巧:
- 端到端跟踪分发路径:PCF 键 →
sendAsync信封({ method, args: [request] })→ manifestreceivers[]→ 原生方法 → 响应 JSON →extractResponse→ PCF 输出。任何一处中断都可能是 bug。 - 在
ios/、android/、pcf/中搜索报告里的特定符号(错误代码、字段名、方法名),找出所有生成或使用该符号的位置。 - 当症状与平台有关时,比较 iOS 和 Android——差异就是线索。
- 对照
{ status, result?/error?, message? }约定和{ isUpdate, message }容器,检查原始<name>Json——形状不匹配表明问题出在extractResponse与直接解析之间。 - 对照
error-codes.md §4 signatures:Loaded 0 plugin package(s)→ Android package 缺少无参构造函数;PCF 中出现cordova.exec→ 禁止使用(会静默空操作);React 头文件错误 → RN 固定版本不一致。
如果追踪涉及单个操作的实现,请阅读 shared/self-critique-protocol.md——其中的检查项(状态覆盖、跨平台一致性、生命周期)有助于进一步明确假设。
第 5 步 — 根因诊断 + 检查关卡
按可能性排序给出诊断。每个假设都必须以证据为依据,而非直觉:
Diagnosis for: "<verbatim symptom>"
1. [HIGH confidence] <one-line root cause>
Evidence: <file>:<line> — <what the code does / doesn't do>
Why it produces this symptom: <one sentence tied to error-codes.md>
Layer: PCF | dispatch contract | native-android | native-ios | native-load | build/pin | behavior
2. [MEDIUM confidence] <alternative cause>
Evidence: ...
Ruled out: <hypothesis> — <why the evidence eliminates it>
Recommended fix (for #1): <what would change, in which file(s)>
检查关卡:Proceed with the fix for #1? (yes / investigate #2 instead / show me <file> / stop)。
- 选择
stop→BLOCKED: user stopped after diagnosis(未编辑任何内容;诊断记录在第 9 步)。 - 选择
investigate #2→ 深入调查该假设,并重新呈现。 - 如果追踪后仍没有假设达到至少 MEDIUM 置信度 → 停止并给出
NEEDS_CONTEXT: <what additional evidence is needed>(例如:“请粘贴原始<name>Json输出”或“崩溃时的一行宿主日志”)。绝不要为未经确认的原因编造修复方案。
第 6 步 — 修复计划 + 规格与偏差核查 + 把关
现在推导修复方案。首先像谨慎编辑一样对问题分类,因为修复可能不只是代码补丁:
| 情况 | 修复内容 | 操作 |
|---|---|---|
| B — 代码偏差(最常见) | 代码偏离了已有的正确规格(例如缺少 extractResponse、复合键错误、异常被吞掉)。 | 只修复代码。打印 <doc> §<n> already specifies the correct behavior — fixing code only. |
| A — 规格错误 | 实际观察到的行为符合 PRD/ARCHITECTURE 当前的描述,但该规格有误。 | 先提出 PRD/ARCHITECTURE 修改(单独设一个小关卡),应用修改,然后再推导代码修复。 |
| C — 两者都有问题 | 规格含糊或不完整,代码也不完整。 | 更新文档细节,然后修复代码。 |
然后给出代码修复计划:
Fix plan:
<path/to/file>
- Replace: <specific symbol / region> → <replacement> (rationale tied to the diagnosis)
- Add: <specific addition>
Contract impact: <"none" | "method set / receiver / nativeModule moves — ./manifest.json + PCF key updated in this same change, re-staged via /generate-ppmplugin-manifest">
Total: N files changed.
Apply? (yes / no / show me <file>)
契约衔接点。 如果修复会改变方法集合、接收器/路由名称或原生模块名称(Android getName() / iOS +moduleName = <Pascal>Module),那么此修复中的三个产物必须同步变更:原生源代码、已提交的 ./manifest.json(对 receivers[] / methods 进行精确编辑),以及 PCF 复合键 <name>/<receiver>。然后运行 /generate-ppmplugin-manifest 重新验证并重新暂存清单。若纯行为修复不改变这些内容,则无需修改清单。
如果修复需要编辑 PCF,但 has_pcf: false,则停止并提示 BLOCKED: this fix requires PCF edits but pcf/ is not scaffolded — run /generate-pcf-companion first。
关卡:等待明确的 yes。用户回答 no → BLOCKED: user declined fix plan(仍记录诊断)。用户回答 show me <file> → 打印拟议内容并再次询问。
第 7 步 — 应用修复
使用 Edit 工具应用计划中的修改。规则:
- 精确修改,不要整体重写。 修改诊断中指出的行;不要重写函数或文件。仅在确实需要新建文件时(调试中很少见)才使用
Write。 - 每个文件内保持原子性。 依次应用对同一文件的所有修改;绝不让文件处于只修改了一半的状态。
- 跨文件保持原子性(尽力而为)。 如果多文件批次在中途失败,停止操作,报告哪些文件已写入、哪些尚未写入,并告知用户对写入了一半的文件运行
git diff/git checkout。不要自动还原(这具有破坏性,不在安全操作范围内)。 - 不做附带修改。 只修改计划中列出的文件。在摘要中指出无关问题;本轮不要修复。
第 7.5 步 — 按主动协议进行自我审查
应用修改后,重新读取每个修改过的文件,并按照 shared/self-critique-protocol.md 逐项检查。修复虽然解决了报告的问题,却可能引入新问题(例如,通过延迟初始化修复 Android 崩溃,可能留下首次调用竞态;修正复合键可能导致输出孤立)。
- 重新读取从磁盘重新读取每个已编辑文件(不要依赖记忆)。
- 逐项检查关卡——PRD 覆盖情况、用户旅程、布局、状态、跨平台一致性、可逆性、生命周期、规格偏差,以及 3P 的第 10 项关卡(可构建性 / 包体适配)和第 11 项关卡(PCF↔原生往返)。特别关注第 11 项关卡——大多数调试修复都会涉及出问题的往返链路。
- 按协议的严重程度和自动修复节奏报告并应用修复:机械性修复合并为一个批次(一次
yes);结构性修复各自单独把关;需要判断的事项作为关注点提出。最多循环 3 轮。
对返回状态的影响:所有关卡均通过 → 继续。暂缓处理阻塞项 → BLOCKED: self-critique blockers — <list>(保留已应用的修复;用户决定后重新运行)。仍有关注点 → 继续并返回 DONE_WITH_CONCERNS。
步骤 8 — 验证修复
验证修复确实解决了问题,并将验证范围限定为已编辑的内容:
插值前先验证。 <Pascal> 来自 PRD 标识,而不是常量——精心构造或格式错误的值会使下面的命令变成任意 shell 命令,或逃逸出项目目录。运行前:要求 <Pascal> 匹配 ^[A-Za-z][A-Za-z0-9]*$(不含分隔符、点或路径段),解析 pcf/<Pascal>PCF 并确认真实路径仍位于 pcf/ 内,然后将其作为单个带引号的参数传入,而不是拼接进 shell 语法。失败时,使用 BLOCKED: refusing to run a build command with an invalid <Pascal> value — <value> 停止。
| 编辑的文件 | 验证 | 原因 |
|---|---|---|
任意 pcf/<Pascal>PCF/ 下的 .ts / ControlManifest.Input.xml | npm run build --prefix "$PCF_DIR" | 这是仓库中唯一的 TS 构建,可立即捕获类型和清单错误。 |
仅 .kt / .m / XML | 打印:已修复原生文件 — 独立编译和设备端验证留待 /build-android-binary // /build-ios-binary(通过 /generate-ppmplugin)以及 /test-native-extension 第 5 层处理。在设备上重新构建并复测,以确认问题已消失。 | 在此处进行原生代码独立编译并不可靠;实际编译由构建技能完成。 |
契约已移动(./manifest.json / 名称) | 重新运行 /generate-ppmplugin-manifest(重新验证并暂存),然后说明还需要运行 /generate-ppmplugin(重新构建并运行 /audit-ppmplugin)。 | 必须重新生成已暂存的清单和二进制文件,修复才能作用于设备。 |
现场问题的最终验证方式是重新构建并在设备上复测——冒烟检查通过只能确认修复可以编译,不能确认问题已消失。请在摘要中明确说明这一点。冒烟检查失败时:报告失败的命令和最相关的错误行,不要自动还原,使用 BLOCKED: smoke check failed — <one-line cause> 停止(仍须在步骤 9 记录)。
步骤 9 — 状态日志和摘要
9.1 更新 .extension-state.md
在 ## Debug 部分末尾追加(不要覆盖;如果不存在则创建):
## Debug
- <ISO timestamp> — <one-line summary of the bug + fix>
- Symptom: "<redacted one-line summary — see the redaction rule below>"
- Root cause: <located cause> (<file>:<line>)
- Diagnosis case: A | B | C
- Docs changed: <sections, or "none">
- Code changed: <file paths>
- Contract moved: <"none" | "receiver/method/nativeModule changed — ./manifest.json updated; re-staged via /generate-ppmplugin-manifest">
- Verification: <PCF npm run build → PASS | native — rebuild + device retest required | etc.>
- Status: DONE | DONE_WITH_CONCERNS: <reasons> | BLOCKED — <reason>
写入前先脱敏。 .extension-state.md 会提交到仓库,因此应将每个字段都视为已公开内容。Symptom 行应是简短的转述——包括错误代码、受影响的操作和可观察到的行为——绝不要直接粘贴报告。对每个字段删除:机密信息和令牌;PII 和客户数据;请求/响应载荷及其片段;绝对路径或内部文件系统路径;内部 URL 和主机名;以及超出定位原因所需单个堆栈帧的堆栈跟踪。Root cause 只保留已纳入源代码控制的、相对于仓库的 <file>:<line>。如果某个细节是说明修复合理性所必需的,但无法安全脱敏,就不要写入文件,保留在聊天中。
9.2 最终摘要和下一步
用一段话说明定位到的根本原因、修复内容和验证结果——并明确指出,只有重新构建后在设备上复测,才能确认问题已解决。然后通过 AskUserQuestion(shared-instructions §9.1)提供下一步,并选择适合此次修复的选项:
- 运行 /generate-ppmplugin — 重新构建
.ppmplugin并再次审计(先重新验证并暂存./manifest.json)。原生代码或契约修复的推荐下一步。 - 运行 /test-native-extension — 重新验证契约(第 0 层交叉检查;第 4 层 PCF 编译)。适用于完整重建前的 PCF 或契约修复。
- 运行 /generate-pcf-companion — 仅当修复需要编辑 PCF,但尚未搭建
pcf/时使用。 - 暂不操作 — 我会先在设备上复测。
根据 执行,而非描述 的 HARD RULE(§9.1),用户选择 Run /… 选项时,必须在同一轮中通过 Skill 工具调用该技能。不要自行自动串联后续步骤。
严格规则
- 没有找到原因,绝不修复。 每项修复都必须追溯到 Step 4/5 的文件:行证据。没有确认原因 →
NEEDS_CONTEXT,不得猜测性地打补丁。 - 两道关卡:先诊断,再制定修复计划。 绝不悄悄编辑代码。对于 case-A/C 规范修复,文档编辑必须先经过单独的小关卡。
- 绝不清除无关文件。 只修改 Step 6 计划中的文件——不得顺手重构。
- 失败时绝不自动还原。 明确指出问题并停止;由用户检查
git diff。 - 文件编辑策略——分为三类(与生成/编辑规范一致):
- 工具管理——绝不编辑:
.git/、锁文件(pnpm-lock.yaml、package-lock.json、Podfile.lock)、生成的 bundle 及其暂存文件(ppmplugin/staging/manifest.json、ppmplugin/输出文件、任何.ppmplugin)、PCF 生成的构件(pcf/<Pascal>PCF/generated/)、构建输出(lib/、dist/、build/、pcf/<Pascal>PCF/out/)、*.bak.*、.claude/。(仓库根目录下已提交的./manifest.json则相反——它是使用方位置,契约变更时必须编辑。) - 技能管理——仅通过规范的状态步骤更新:
.extension-state.md(此技能的 Step 9)。流程中途不得直接编辑。 - 按请求可编辑:
.gitignore、CHANGELOG.md、LICENSE、README.md、PCF 的eslint.config.js/tsconfig.json,以及所有源文件(ios/**、android/**、pcf/<Pascal>PCF/{index.ts,ControlManifest.Input.xml})。
- 工具管理——绝不编辑:
- 单个文件内原子化,跨文件尽力而为。
- 保持契约一致。 如果修复变更了方法集 / 接收方 / nativeModule,则
./manifest.json、原生端和 PCF 必须一起变更,然后通过/generate-ppmplugin-manifest重新暂存。使用/test-native-extension的 Layer 0 进行验证。 - 规范与代码保持同步。 case-A/C 修复先更新 PRD/ARCHITECTURE;case-B 修复则记录这种偏差。绝不悄悄更新规范以迁就 bug。
- PCF 自动检测,绝不假定存在。 如果没有
pcf/<Pascal>PCF/ControlManifest.Input.xml,就不要写入pcf/;如果修复需要 PCF,则转到/generate-pcf-companion。 - 不要自动串联后续步骤;但在 Step 9.2 明确选择时应予以执行。
- 冒烟检查不等于已在设备上确认。 始终告知用户,必须重新构建并在设备上重新测试,确认字段问题已消失。
场景——流程演示
场景 1——Android 上静默无操作(PCF 传输 bug)
Step 2: Symptom = "tap does nothing, no error, only on Android."
Step 3: Triage → PCF/transport (error-codes.md §4 top row) + dispatch contract.
Step 4: Read pcf/.../index.ts — invokeBridge calls cordova.exec directly, no sendAsync.
Evidence: index.ts:NN. Matches the §4 signature (cordova undefined in PCF sandbox).
Step 5: [HIGH] cordova.exec used instead of the host-injected sendAsync → silent no-op,
worst on Android. Gate: proceed.
Step 6: Case B (ppmplugin-format §2 already specifies sendAsync). Fix plan: replace
cordova.exec with window.PowerApps.NativeExtension.sendAsync + args:[request].
Step 7: Apply. 7.5: self-critique Gate 11 (round-trip) clean.
Step 8: cd pcf && npm run build → PASS. Note: rebuild PCF + retest on device.
Step 9: Log case B; suggest /test-native-extension then /generate-pcf-companion publish path.
场景 2——启动时崩溃(原生加载)
Step 2: Symptom = "app crashes the moment the control's screen opens", host log
"Loaded 0 plugin package(s)".
Step 3: Triage → native-load + native-android.
Step 4: Read the ReactPackage class — constructor takes an argument (no public no-arg
ctor). Matches error-codes.md §4 "Loaded 0 plugin package(s)".
Step 5: [HIGH] ReactPackage has no public no-arg constructor → runtime instantiation fails
fails → 0 packages loaded. Gate: proceed.
Step 6: Case B. Fix: add the public no-arg constructor.
Step 7: Apply. 7.5: Gate 10 buildability clean.
Step 8: Native-only → defer to /build-android-binary; rebuild + device retest required.
Step 9: Log; recommend /generate-ppmplugin (rebuild + audit).
场景 3——输出错误(行为偏差,规范正确)
Step 2: Symptom = "Done returns the image without the drawing layer."
Step 3: Triage → behavior/spec + native (both platforms).
Step 4: Read both native op bodies vs ARCHITECTURE §3.n export step. Android composites
only the base bitmap; iOS composites both. Evidence: <Pascal>Module.kt:NN.
Step 5: [HIGH] Android export omits the ink layer; ARCHITECTURE §3.1 says composite both.
Gate: proceed.
Step 6: Case B (spec already correct). Fix Android export to match. Cross-platform parity.
Step 7: Apply. 7.5: Gate 5 parity now holds.
Step 8: Native-only → rebuild + device retest. Step 9: log; suggest /generate-ppmplugin.
失败模式
| 发生的情况 | 技能的处理方式 |
|---|---|
缺少 PRD / package.json | 以 BLOCKED: not an extension repo 停止;建议使用 /generate-native-extension。 |
| 提出一个澄清问题后,症状仍不足以进行分类 | 以 NEEDS_CONTEXT: <what's needed> 停止(例如,粘贴 <name>Json / 一行主机日志)。 |
| 没有假设达到 ≥ MEDIUM 的置信度 | 以 NEEDS_CONTEXT 停止——绝不编造修复方案。 |
| 用户在诊断后停止 | BLOCKED: user stopped after diagnosis;记录诊断结果。 |
| 用户拒绝修复计划 | BLOCKED: user declined fix plan;记录诊断结果(以及已应用的任何文档编辑)。 |
修复需要编辑 PCF,但不存在 pcf/ | 停止;转到 /generate-pcf-companion。 |
| 冒烟检查失败 | BLOCKED: smoke check failed — <cause>;保留编辑内容;记录失败情况。 |
编辑工具失败(例如 old_string 不唯一) | 明确指出具体错误;不得盲目重试;报告已应用修改的文件。 |
返回状态
每次运行都以以下状态之一结束:
DONE— 已找到根本原因、已应用修复,并且冒烟检查已通过(或仅涉及原生代码,且已打印重建和重新测试提醒)。DONE_WITH_CONCERNS: <list>— 已应用修复,但仍有注意事项(自我审查发现的问题、缺少预期文件、未经确认的次要假设)。BLOCKED: <reason>— 用户已停止或拒绝、冒烟检查失败、缺少 PRD,或需要 PCF 但未提供。NEEDS_CONTEXT: <what's unclear>— 症状描述过于简略,或尚未以足够的置信度找到原因。