SuperAPI AI Directory

wxa-skills-validate

General & other

View repository

Updated 10-16 01:32

About this skill

wxa-skills-validate

Perform on mini program AI SKILLs artifacts "Static validation → Atomic interface execution → Atomic component rendering → Delivery document" closed-loop validation, and at each step when it fails, repair the skill source files in place by error type classification.

Dependencies

  • Node.js ≥ 18(scripts/*.mjs Uses node:crypto / native fetch)
  • WeChat DevTools (latest Nightly Electron Build) is installed, CLI executable:<DEVTOOLS_APP_PATH>/Contents/MacOS/cli -h(macOS default <DEVTOOLS_APP_PATH>=/Applications/wechatwebdevtools.app)
  • The DevTools service port must be enabled: manually open the tool → Settings → Security Settings → enable "Service Port". If not enabled, the CLI cannot connect, and execute / render all fail
  • Debug base library ≥ 3.16.2; the project AppID has already applied for and passed "development mode" in "WeChat Official Platform - Basic Features - AI Capabilities"
  • Project project.config.json contains appid;app.json contains agent.skills; each skill directory contains mcp.json + SKILL.md

During runtime, DevTools may pop up an authorization window, which requires manual authorization; failure to authorize will cause atomic interface execution to fail.

Trigger Conditions

Start this skill when any of the following situations occurs:

  • Explicitly request any one of "validation / successful run-through / rendering / delivery document output" for the skills directory
  • Existing skills artifacts (regardless of source) need to enter the verification phase
  • Validation errors from running skills need to be fixed

Required Information

Item Description Action when missing
<project-path> Mini program project root directory (containing project.config.json + app.json;app.json 's agent.skills[].path pointing to the skill subpackage) Ask the user
<DEVTOOLS_APP_PATH> WeChat DevTools application path macOS default /Applications/wechatwebdevtools.app, user-overridable
<AUTO_PORT> auto WebSocket port Default 9420

Note:<skills-path> hasno longer serves as an input parameter, the script automatically discovers the subpackage from app.json .

Reference Materials (loaded as needed)

When entering "Step 4: On-device closed loop"mustfirst read references/CLI_AGENT_REFERENCE.md, which contains script usage, artifact structure, next actions after reading artifacts, the 5-item checklist comparison table, and the failure backtracking process.

File Purpose Loading Timing
references/CLI_AGENT_REFERENCE.md CLI agent command reference Before Step 4 execution
references/VALIDATE_RULES.md Detailed explanation of the V001~V021 rules built into validate.mjs When a validation error occurs and the id needs to be located
references/DELIVERY_TEMPLATE.md DELIVERY.md delivery template At final delivery

Acceptance Goals (cannot be downgraded)

  • <project-path> under app.json For each skill subpackage discovered, all atomic interfaces declared by its mcp.json must successfully run execute (status === "ok" and invokeResult.isError !== true)。Exception: sensitive interfaces are not actually executed——interfaces hitting sensitive keywords are written to disk by V019 cli-agent-run/destructive-manifest.json, and execute.mjs reads this manifest to intercept (--confirm-destructive allowed through) — static validation only; at acceptance it is treated as "execution skipped" rather than failed, and must be noted in the report skipped_destructive。
  • All atomic interfaces with _meta.ui.componentPath must run render successfully and pass the 5 checks (see references/CLI_AGENT_REFERENCE.md Section 2.3).
  • A single interface is allowed to be suspended only after 3 consecutive rounds of fixes still fail. No item may be skipped (except execution skipping for sensitive interfaces).
  • Static/compilation pass ≠ acceptance pass: real-device execute + render 5 checks are required; if execute has not run successfully, it must not be judged as passed, and no DELIVERY.md(see "Unfixable Category" and "Termination Condition 4").

Execution Checklist (copy and check off, complete item by item)

阶段 1 — 静态校验 + 编译校验
- [ ] 运行 `node validate.mjs <project-path>`(单参数,脚本自动发现 skill 分包并决定是否跑 preview)
- [ ] summary.errors === 0(含 V001~V021),否则按 T1~T9 分类修复后重跑
- [ ] summary.buildStatus === "pass"(静态 0 error 时 preview 会自动运行;
      若为 "skipped" 说明静态未过,先按上一项修复)
- [ ] 阅读 Build 行:若 stage=compile + FAIL,说明有语法/编译错误,必须修复

阶段 2 — 准备
- [ ] 确认 CLI 可执行:<DEVTOOLS_APP_PATH>/Contents/MacOS/cli -h
- [ ] (可选)显式启动 cli auto

阶段 3 — 构建执行计划
- [ ] 解析每个 <skill>/mcp.json 的 apis[],按书写顺序 + 参数依赖做拓扑排序
- [ ] 建立"已知数据池"(空)

阶段 4 — execute 与 render(可独立执行)
对每个 {name}:
- [ ] execute 成功(status=ok 且 !isError)
- [ ] 若 mcp.json 有 _meta.ui.componentPath,render 可在任何时间点执行(不要求紧跟 execute)
- [ ] render 通过 --from-execute 复用最新的 execute 产物(args 取自 invokeResult.structuredContent);
      structuredContent 缺失时必须先重跑 execute
- [ ] 5 项核对全部通过(主要依据:`consoleMessages.snapshotCard` 中的生命周期日志 + `[ai-mode] ... overflow monitor=on` 基线日志 + 不出现 `overflowed=true`;仅在具备图像读取能力时再辅助读截图)

阶段 5 — 交付
- [ ] 写 ./cli-agent-run/report.md
- [ ] 若全部通过,按 references/DELIVERY_TEMPLATE.md 写 ./DELIVERY.md 并回贴内容

Working Directory

In <project-path> create at the same level ./cli-agent-run/ for unified storage of artifacts:

cli-agent-run/
├── validate-report.json                   # 阶段 1 产物
├── execute-result.<apiName>.json          # 阶段 4 execute 产物(含 invokeResult.structuredContent 供 render 继承)
├── render-result.<apiName>.json           # 阶段 4 render 产物(snapshot 摘要 + consoleMessages + elementTree)
├── render-result.<apiName>.snapshot.png   # 阶段 4 render 截图
├── execute-trace.json                     # 每次尝试的回溯日志
└── report.md                              # 阶段 5 执行报告

项目根目录/
└── DELIVERY.md                            # 全部通过时的最终交付文档

When rerunning the same interface, you must reuse --output(the file will be overwritten); different interfaces must use different file names.


Phase 1 — Static validation + Compilation validation (merged into one run)

Run:

node <skill-dir>/scripts/validate.mjs <miniprogram-project-path>

Only one input parameter is needed — the mini program project root directory(including project.config.json + app.json). The script automatically:

  1. Read app.json 's agent.skills[].path to discover skill subpackages (when not configured, fall back to top-level metaServicePkg/ or skills/)
  2. Static rules are executed only within the skill subpackage directory , without touching main package code
  3. Write the validation artifact directory cli-agent-run/ into project.config.json 's packOptions.ignore(packaging ignore) and watchOptions.ignore(watch ignore), to prevent the developer tools from continuously watching artifact changes and triggering circular compilation (existing entries will not be appended again; synchronization is completed before artifacts are written to disk, and the result is attached to the report ignoreSync field)
  4. After static validation passes (errors === 0) automatically call cli preview for compilation validation; if there is an error, skip preview
  5. Report is written to disk at <project>/cli-agent-run/validate-report.json(can be overridden with --output )

Optional parameters:--rules <自定义规则 json> / --cli-path <CLI 路径> / --build-timeout <ms> / --output <path>。

Exit codes:0 passed;1 error exists or build failed;2 runtime exception.

Pass Criteria:

  • summary.errors === 0(warnings are allowed to proceed into Phase 2)
  • summary.buildStatus === "pass"(after 0 static errors, build is automatically triggered;"skipped" means static validation did not pass, first fix according to the fix decision table)
  • Build line stage=compile + FAIL indicates syntax/compilation errors, which must be fixed

When Build compilation errors occur: prioritize checking the integration configuration, then modify the source code. Cross-check wxa-skills-generate SKILL.md 's "Phase 6 — Configuration Integration" and references/CODE_TEMPLATES.md 's "VI. app.json + project.config.json Configuration" against app.json(agent.skills / subPackages) and project.config.json(appid / packOptions.include). Only after the integration is correct should you modify source code according to logs,Do not bypass integration issues by commenting out/deleting source code。

Handling when CLI is not found: if it outputs Build: SKIPPED - 跳过:未找到微信开发者工具 CLI, it means the script could not automatically locate cli. The automatic detection order is:--cli-path > environment variable WECHAT_DEVTOOLS_CLI / WXA_CLI > macOS /Applications/wechatwebdevtools.app/Contents/MacOS/cli > user directory variants at the same path > Windows C:\Program Files (x86)\Tencent\微信web开发者工具\cli.bat. At this point, proactively ask the user for the installation path of WeChat DevTools, then:

  • Rerun:node validate.mjs <project-path> --cli-path <用户提供的绝对 cli 路径>
  • Or suggest the user set an environment variable:export WECHAT_DEVTOOLS_CLI=<绝对路径> then rerun

A missing CLI does not affect the output of static rules; it only causes the build phase to be skipped.

Execution order(closed loop within the script):

  1. Sync project.config.json of packOptions.ignore + watchOptions.ignore(append cli-agent-run/)
  2. Detected skill subpackage → run V001~V021 only within the subpackage
  3. error → build=skipped(saves preview cost); 0 errors → call cli preview
  4. Reaching the upload stage is considered compilation passed; even if the upload fails (server-side validation, network, etc.), build is not marked as failed

Repair decision table on failure(after reading validate-report.json in results[].id / message / fix then match):

Error type Identifying feature Repair scope Action
T1 Naming spelling Field case/spelling error Single file, single line Fix directly
T2 Schema inconsistency structuredContent and outputSchema.properties fields do not match (V009) apis/{name}.js + mcp.json Align fields
T3 Component binding inconsistency WXML {{}} and setData fields do not match (V011) components/{x}/index.{js,wxml} Align binding
T4 Incorrect component value path result.structuredContent.xxx does not match the field returned by the API (V010) components/{x}/index.js Fix access path
T5 Compliance violation Non-whitelist WXML tags / events / image formats / CSS properties (V003/V005/V006) Single-file rewrite Replace with a whitelist implementation:collapsible-view is allowed;transition / animation / overflow / -webkit-line-clamp delete all (change to -wx-line-clamp); delete non-tap events
T6 Missing registration mcp.json 's name in index.js not registerAPI, or vice versa (V007/V008) index.js Add/remove registration
T7 Dependency chain issue storage key writer/reader mismatch Cross-API + utils/util.js cross-file adjustment
T8 Incorrect atomic API granularity Overlapping API responsibilities mcp.json + index.js + apis/*.js Split/merge apis[]
T-mcp-size mcp.json exceeds 24000 characters after removing outputSchema (V013; the backend will also reject it) mcp.json 's description/title/inputSchema; or redivide skill subpackages Compress the description text; when there are too many APIs to trim easily, split them into multiple skill subpackages by responsibility,do not cram examples/enums into outputSchema
T-auth Missing authentication 401 / unauthorized / token 无效 etc. (in the static phase usually triggered indirectly by V007/V008) utils/util.js / apis/{name}.js Read the main packageRestore the login flow
T-wx-jsapi non-whitelist At runtime wx.<xxx> is not a function / wx.<ns> is undefined apis/{name}.js / components/{x}/index.js Refer to wxa-skills-generate SKILL.md D.1/D.2 whitelist (full listsee wxa-skills-generate/references/JSAPI_WHITELIST.md),replace per D.7 or change the network request; if there is no replacement, mark T9 (see stage 4 category C for details)
T-build Compilation failure The Build line shows FAIL and stage=compile Project integration / .js / .wxml / .wxss First check against wxa-skills-generate SKILL.md Stage 6 "Configuration Integration" to verify app.json / project.config.json, and after integration is correct, fix the source code according to the logs
T-skill-description app.json 's agent.skills[].description is missing or empty (V016) app.json In that entry, add a non-empty description field
T-handoff Handoff page _meta.ui.pagePath format error/page does not exist/has query, or pagePath was declared but not returned handoff(V017) mcp.json + apis/{name}.js pagePath starts with / , contains no query, and the page actually exists; add at the top level of the return value handoff: { query, payload? }(see wxa-skills-generate SKILL.md D.6)
T-handoff-query handoff.query 's parameter name and handoff page onLoad 's read parameter name do not match (V018) apis/{name}.js Read handoff page <pagePath>.js 's onLoad(param) to confirm the param.xxx name it reads, and change handoff.query 's parameter name to the name actually read by the page
T-destructive API hit sensitive keywords, V019 pending model judgment (V019,destructive:null) cli-agent-run/destructive-manifest.json Edit manifest to fill in destructive=true+destructiveReason(truly sensitive) or false+destructiveReason(false positive such as read-only query)
T-relatedPage Component not declared in components[] , or relatedPage missing / missing leading / / page does not exist (V015) mcp.json + components/{x}/index.js In components[] add { path, relatedPage }(path strictly equal to API _meta.ui.componentPath ,relatedPage starts with / and the page actually exists; if there is no corresponding business page, fill in the home page); at runtime after receiving Result call setRelatedPage({ query })
T-limits SKILL.md / AGENTS.md / page-meta.json exceeds byte limit, or SKILL count exceeds 30 (V020) Corresponding file / app.json streamline content (SKILL.md keep only the 5-section structure, return API contract to mcp.json); when there are too many SKILLs, merge those with similar responsibilities
T-dynamic Static atomic component or its relative JavaScript dependency uses wx.login / wx.checkSession / wx.request / setTimeout / setInterval, or any component code path uses cloud development (V021) <componentPath>.js, its relative JavaScript dependency, or mcp.json static component truly has real-time requirements, only then in components[] add to that entry permissions["scope.dynamic"]; cloud development must always be moved to atomic APIs and data delivered via NotificationType.Result Deliver data
T9 capability cannot be implemented All candidates violate hard constraints — ⛔ Terminate, inform the user

For details of rules V001~V021, see references/VALIDATE_RULES.md。

Decision mnemonic: if it can be fully fixed within the file → T1~T6; if the storage manifest or API division needs to be changed → T7/T8; if even the fix plan violates the rules → T9.

Iteration rules:

Situation Action
summary.errors === 0 ✅ Enter Stage 2
errors count decreased compared with the previous round Continue fixing, rerun
Same finding id for 3 consecutive rounds Escalate to T7/T8 cross-file adjustment
Still not passed after 5 cumulative rounds ⛔ Terminate, request manual intervention

Stage 2 — Prepare CLI agent command

Confirm CLI is executable:

<DEVTOOLS_APP_PATH>/Contents/MacOS/cli -h

If it fails, tell the user "Confirm that WeChat DevTools is installed" and stop; do not force a workaround.

(Recommended) open to warm up first, then auto(about 10s; can be extended for large projects), to reduce websocket timeouts:

<DEVTOOLS_APP_PATH>/Contents/MacOS/cli open --project <PROJECT_PATH>
<DEVTOOLS_APP_PATH>/Contents/MacOS/cli auto \
  --project <PROJECT_PATH> --auto-port <AUTO_PORT> --trust-project

If this step is skipped, the script will automatically start auto; if a timeout occurs or agent compile mode is disabled occurs, handle it as "unfixable / tool unstable".


Phase 3 — Build execution plan

Read <project-path> under app.json each skill subpackage discovered in mcp.json(validate-report.json in skillDirs field gives the specific subpackage path):

  1. Initial screening of sensitive interfaces + model judgment (V019, required before execute): In Phase 1 static validation, the V019 script initially screens all mcp.json files and writes interfaces whose name/description match sensitive keywords into cli-agent-run/destructive-manifest.json(destructive:null pending judgment), reports error and blocks build. After the model judges each one, edit the manifest to fill in destructive:true(truly sensitive, skipped by execute) or false(false positive, allowed by execute) + destructiveReason, rerun validate until V019 passes. execute.mjs reads the manifest:true block / false allow / null block (pending judgment) / not in manifest allow. On the generation side, Phase 2 already specifies that sensitive interfaces are not collected by default; V019 is a fallback to catch sensitive interface names that slip through.
  2. Summarize apis[] of name / description / inputSchema / outputSchema / _meta.ui.componentPath。
  3. sort by input parameter dependency(topological order):
    • Interfaces with no parameters (inputSchema.properties is empty or has no required)→ execute first
    • Interfaces with parameters → placed after the interfaces that are the source of their parameters
    • description or inputSchema contains wording such as "need to call X first", place X before it
  4. Maintain a "known data pool": after each interface succeeds, store structuredContent into the pool for downstream parameter references.
  5. Parameter filling priority for interfaces with parameters: first check the known data pool (synonymous fields from upstream interface structuredContent ); only if it is not in the pool consider user-specified or default values——It is forbidden to directly use default values to test interfaces with parameters when a data pool is available。

Phase 4 — execute and render

Terminology clarification: execute is thevalidation phase name(this phase), using CLI agent tool to call the registered interfaces of the skills subpackage;do not confuse it with probe——probe is used in generate Phase 3.7 with automator to capture requests and responses on the source project. The two differ in tool (CLI agent vs automator), object (skills subpackage vs source project), and phase (validation vs generation).

execute and render aretwo independent reentrantcommands:

  • execute calls atomic interfaces and produces business data (invokeResult.structuredContent)。
  • render passes execute's --from-execute through invokeResult.structuredContent as the rendering data source to the component; you can also --name + --args specify independently. Internally, the CLI automatically generates a one-time toolCallId / sessionId for each render, without depending on execute's runtime context.

Execution flexibility:

  • You can execute all atomic interfaces at once, then batch render uniformly
  • You can also alternate "single-interface execute → render"
  • render data source priority:--args explicitly specified > --from-execute read from invokeResult.structuredContent

hard constraints(keep only what is truly necessary):

  • sensitive interfaces are not executed by default—interfaces that produce irreversible side effectsare denied execution by default. Determination source: read first cli-agent-run/destructive-manifest.json(V019 initial screening + model judgment),destructive=true block / false allow / null block (pending determination, safety first) / interfaces not in the manifest are allowed; when the manifest does not exist, fall back to keyword determination.execute.mjs without --confirm-destructive directly denies the determined sensitive interfaces (exit code 3, not written to disk). During full execute / loop troubleshootingmust skipthese interfaces (only perform phase 1 static validation), and the report marks skipped_destructive。strictly prohibitedbatch allowing. Only when the user explicitly requests execution of a specific sensitive interface, carry --confirm-destructive to execute it separately, and explain the consequences to the user before execution.
  • Execution order: parameterless first, then parameterized—parameterless interfaces are first batch-executed successfully, and their structuredContent after entering the data pool, parameterized interfaces then retrieve parameter values from the pool to execute. It is prohibited to directly use default values to test parameterized interfaces when a data pool is available
  • prepare input parameters according to the apis[] order dependency relationships (if the args of a downstream interface depend on an upstream structuredContent, the upstream still needs to be executed first)
  • every interface with componentPath must ultimately pass render; the criterion for complete passing remains "execute success + render 5-item verification passed"
  • within the same CLI invocation,render.mjs cannot be executed concurrently (CLI background auto is serial)
  • --from-execute 's execute output must contain invokeResult.structuredContent; if missing,render.mjs will directly report an error, and it is necessary to first re-execute successfully before render

4.1 execute

Run:

node <skill-dir>/scripts/execute.mjs \
  --project <PROJECT_PATH> \
  --name <name> \
  [--args '{"query":"..."}'] \
  [--auto-port <AUTO_PORT>] \
  [--skill <skill-name-or-path>] \
  [--timeout <ms>] \
  --output ./cli-agent-run/execute-result.<name>.json

execute.mjs only accepts the above parameters; toolCallId / sessionId / auto related tickets are handled automatically internally by the CLI, and are no longer exposed by the script.

Input parameter source priority:

  1. user-specified
  2. known data pool(synonymous fields of the upstream interface structuredContent )—parameterized interfaces must first attempt to extract parameter values from the structuredContent of successfully executed parameterless/upstream interfaces, rather than directly using default values. Example:getOrderDetail requires orderId → first run listOrders(parameterless), and from its structuredContent.orders[0].id take orderId
  3. inputSchema allowed to be empty → omit --args
  4. type default value (string ""、number 0、array []、object {}), and the log marks "using default value"—only use it when the data pool has no corresponding field and the user has not specified it

Success criteria:status === "ok" and invokeResult.isError !== true and invokeResult.structuredContent is a non-empty object (the latter is the precondition for render --from-execute ).

Empty result troubleshooting (success but structuredContent business data is empty):isError !== true but the returned structuredContent is an empty list / empty object / total: 0 / only has the error field,cannot be directly judged as passed—this is usually a symptom of incorrect request parameters, authentication not taking effect, a misspelled URL, or an incorrect response unpacking path, rather than there truly being no data in the business. Troubleshoot in the following order:

  1. read consoleMessages' [ai-mode] Logs: Confirm whether the URL / parameters / headers actually sent in the request are correct (entry log → pre-request log → post-request log)
  2. Read the main package source code to locate the real request: Find the page/request wrapper corresponding to this API in the main package, and confirm the real URL / method / parameter names / auth headers / response unwrapping path
  3. Compare the main package's real request with the request actually sent by apis/<name>.js Actual request sent: Are the URL / method / parameter names / auth headers consistent? If not → go back to apis/<name>.js or utils/request.js to fix
  4. Auth troubleshooting: The login state/token required by the main package's request wrapper, whether theapis/<name>.js entry has completed await ensureLogin() etc. → missing auth will cause the backend to return empty instead of an error
  5. After troubleshooting, fix → rerun execute; if still empty and the request is confirmed to be completely consistent with the main package's real request → it may be a backend environment difference (test account has no data), record in trace "request verified correct after troubleshooting, suspected no data in environment", and allow passing with a declaration

execute failed: First check whether the artifact _meta.diagnosis is of the unrecoverable type (if so, stop immediately), otherwise handle it according to categories A/B/C/D in "Stage 4 Failure Classification" below.

4.2 render (executed only when this api in mcp.json has _meta.ui.componentPath )

As long as the correct name + args(rendering data source) is provided, it can render. The CLI's render will not re-execute the atomic API, but instead feeds --args as structuredContent directly to the component for rendering;--from-execute is just syntactic sugar, used to feed the invokeResult.structuredContent in the execute artifact directly to render.

Recommended run method(inherit name / argsfrom the execute artifact, with args sourced from invokeResult.structuredContent):

node <skill-dir>/scripts/render.mjs \
  --project <PROJECT_PATH> \
  --from-execute ./cli-agent-run/execute-result.<name>.json \
  [--timeout 90000] \
  --output ./cli-agent-run/render-result.<name>.json

If the execute artifact is missing invokeResult.structuredContent, the script will directly exit 2 with an error— in this case you must first rerun execute and confirm that status=ok + invokeResult.isError!==true + structuredContent is a non-empty object.

Independently specify context(no execute artifact, or args need to be specified manually):

node <skill-dir>/scripts/render.mjs \
  --project <PROJECT_PATH> \
  --name <tool-name> \
  --args '{"<字段>":"..."}' \
  [--timeout 90000] \
  --output ./cli-agent-run/render-result.<name>.json

render.mjs automatically inherits --from-execute from name / args; when any field is provided by --name / --args or other explicit parameters, the explicit value takes precedence. The parameters issued by the CLI are limited to --project / --name / --args / --output / --trust-project (and --timeoutwhen necessary); other context is automatically generated internally by the CLI and cannot and need not be explicitly passed in from the script.

render cold start is usually slower than execute (it needs to create a container + render components); for the first call or in a CI environment, it is recommended to --timeout 90000. For detailed parameters, artifact structure, and the next action after reading the artifact, see references/CLI_AGENT_REFERENCE.md Section 2.

Artifacts that must be read(relying only on render.mjs exit code 0 is not enough to determine pass):

  • console logs (main basis):render-result.<name>.json 's consoleMessages.snapshotCard. Must check:
    • [ai-mode] ... created → [ai-mode] ... 收到接口返回 → [ai-mode] ... setData three lifecycle logs (missing any one → there is a problem with component initialization or Result listening)
    • [ai-mode] <component> overflow monitor=on(baseline log, must exist): the component has bound NotificationType.Overflow listening. If missing → treat as not integrated with listening, go back to the component JS skeleton of wxa-skill-generate to complete it
    • [ai-mode] <component> overflow overflowed=true data=<JSON>(or data.overflowHeight > 0): there is clipping, check ③ fails. A single occurrence is enough to fail; only monitor=on, without overflowed=true record is considered passed as not clipped
    • Any ERROR -level log basically means the business component failed to initialize, and the screenshot will be blank
  • Component tree elementTree(auxiliary check, passed through as-is):render-result.<name>.json 's elementTree is entirely returned by CLI render, and is an indented-formatstring(not a JSON object), serializing the card's shadow tree, in the form of <view:view class="addr-row">...、<text:default-component class="temp">... 28°、 <(virtual):wx:if> and other nodes.render.mjs / lib.mjs does not perform any processing or placeholder backfilling—if the CLI did not deliver it, the field does not exist. Itdoes not participate in pass/fail determination, and serves only as an auxiliary signal: used to check whether field text hits the binding, the number of list nodes, wx:if whether the empty state takes effect, etc. (perform grep on the string)
  • Screenshot (auxiliary):render-result.<name>.snapshot.png。Only when the current runtime environment has image reading capability, read it in as an image via read_file , to assist in checking style restoration fidelity (check ④). If the current environment does not have image reading capability,skipscreenshot reading, and do not treat it as a failure; check ③ (clipping) is entirely based on the overflow log, and does not fall back to visual judgment based on screenshots

5 checksSee references/CLI_AGENT_REFERENCE.md Section 2.3. If any one fails → stay on this interface and continue fixing.

4.3 Closed-loop self-check (hard gate before overall pass)

Every interface with componentPath must satisfy all of the following before it may be marked as passed:

  • there exists execute-result.<name>.json, whose status === "ok" and invokeResult.isError !== true
  • there exists render-result.<name>.json
  • all 5 checks pass (including consoleMessages.snapshotCard there exists in [ai-mode] ... overflow monitor=on baseline log, and overflowed=truedoes not appear; screenshots serve only as an auxiliary signal when image reading capability is available)

Stage 4 Failure Classification and Repair Process

Unrepairable category: environment / permission issues (not code errors)

First check _meta.diagnosis: if non-null, it is an environment/permission issue; stop changing code, and relay hint to the user as-is (do not broadly assert "no permission"). In this case, do not mark as passed and do not produce DELIVERY.md。

Handle separately according to _meta.diagnosis.type :

miniprogram_not_runnable(CLI returns agent compile mode is disabled): indicates that the mini program main package/subpackage failed to compile and run normally—agent capabilities are automatically ready only when the mini program can run normally (cli preview reaching upload's "compilation passed" only means it can be packaged, not that there will be no white screen at runtime). Check item by item according to hint :

  1. Open the project in the developer tools, confirm it can run normally with no white screen, and no app.js / hack.js runtime errors in the console (e.g., Cannot set properties of undefined、appServiceSDKScriptError)
  2. regeneratorRuntime -type errors usually originate from project.config.json 's es6 / enhance compilation settings being inconsistent with production; align with a configuration that can run normally.
  3. appid missing / cloud init error indicates project.config.json is missing appid or cloud development is not initialized; complete it and retry
  4. Confirm app.json 's agent.skills / subPackages configuration is correct, and the skill directory contains mcp.json
  5. First open may not be ready yet; reopen the project once to warm it up, then retry

agent_env_unreachable: CLI stdout contains timeout waiting for auto websocket and stderr contains Fetching AppID (wx...) detailed information ✖. There are multiple possibilities;it cannot be directly attributed to lack of permission, and the possibilities in hint must be relayed to the user one by one. Troubleshooting order:

  1. Developer Tools / base library agent runtime exception or version too old → switch to the online base library, use --debug to retry
  2. Automation channel not connected / port mismatch → confirm the service port is enabled; if necessary, specify --auto-port
  3. Tool not logged in or the account is not a member of this AppID → log in again and confirm account permissions
  4. Network cannot access WeChat backend → check proxy / VPN / firewall
  5. If all of the above are normal and it still fails, only then consider that the AppID has not enabled AI development mode permission

Tool unstable(_meta.diagnosis is null but execute times out/disconnects/Adapter wait timeout/runtime not attached): not a code bug; modifying code to make it pass is prohibited. Handling:cli open warm up → --timeout 120000+ → keep the tool in the foreground, restart if necessary; if it still fails, stop and do not produce DELIVERY.md。

diagnosis === null ≠ all are "tool unstable"——execute.mjs/render.mjs only when a deterministic environment signal is recognized (agent compile mode is disabled / Fetching AppID ✖ etc.) write diagnosis; otherwise always leave null.diagnosis === null when error / consoleMessages according tospecific error characteristicsdetermine the classification:

  • timeout / disconnect / Adapter wait timeout / runtime not attached → Tool unstable(this section)
  • missing required parameter / xxx is undefined → Category A(below)
  • no data / getStorageSync 返回 null → Category B(below)
  • network / 500 / unauthorized / wx.<xxx> is not a function / JS throws an exception → Category C(below)
  • status: ok + isError: false + empty data → Category E(below)

Prohibitedto disguise Category A/B/C/E business errors as "tool unstable" to evade fixing.


Repair paradigm (after confirming it is not an unfixable category, follow this order for each failure)

- [ ] 步骤 1:读运行时产物(execute-result / render-result 的 `error` / `consoleMessages`;
      `elementTree` 由 CLI 返回时可辅助定位字段/绑定问题,缺失时跳过;
      `snapshot.png` 仅当环境具备图像读取能力时再辅助核对,否则跳过)
   - 先检查 `_meta.diagnosis` —— 若非 null → 不可修复类,立即停止
   - **若报错形如 `wx.<xxx> is not a function` / `Cannot read property '<xxx>' of undefined`
     → 直接跳到 C.1 子类按白名单比对处理**
- [ ] 步骤 2:回到主包源码定位真实逻辑(页面 .js / utils/request.js / app.js / cloudfunctions/*)
- [ ] 步骤 3:对比分包实现,列出差异点再改(`apis/<name>.js` / `utils/util.js` / `components/<name>/*`)
- [ ] 步骤 4:若涉及接口划分 / storage 链路,改 mcp.json 的 apis[] 并同步 index.js 注册
- [ ] 步骤 5:重跑 execute 验证数据正确;涉及 UI/WXML/WXSS 改动时单独跑 render 验证渲染
      (render 可通过 --from-execute 复用之前的 execute 产物,前提是该产物仍含 invokeResult.structuredContent)
- [ ] 步骤 6:仍失败重复步骤 1~5,单接口上限 5 次

Core principle:the truth is only in the main package. Subpackages are independently running copies; for logic differences, the main package prevails. It is prohibited to speculate and modify without reading the main package source code.


Category A: execute parameter failure

Characteristics:missing required parameter / xxx is undefined / 参数格式错误。

  1. Find the upstream interface from the dependency graph; if it has not been run, run the upstream first, extract the fields, then reassemble --args(limit 3 times)
  2. Field name mismatch → perform field mapping and retry
  3. Cannot find the upstream source → read the main package to confirm the real dependency → modify apis/<name>.js input parameter assembly → rerun
  4. Still fails after 3 times → switch to Category C

Category B: execute fails to read storage

Characteristics:no data / getStorageSync 返回 null。

  1. In the storage list of <skill>/SKILL.md , find the writer interface, run it once first, then rerun the current interface (limit 2 times)
  2. If the key should be initialized by the main package app.js → read the main package → in utils/util.js 's ensureStorageInit() , add initialization logic → rerun
  3. Still fails after 2 times → switch to Category C

Category C: execute code/network failure

Characteristics:network / timeout / 500 / unauthorized / not registered / JS throws an exception / returned fields do not match outputSchema Inconsistent.

  1. Read execute-result.<name>.json of invokeResult.error + consoleMessages([ai-mode] prefixed logs) to pin down the failing step
  2. Read main packageMust-read checklist:
    • Source page .js: assemble request params (headers / token / signature / query string)
    • utils/request.js / utils/http.js / api/*.js:baseUrl / auth header / error code / response structure (whether it wraps data/code/msg)
    • app.js:wx.cloud.init({ env }) / global token / globalData
    • Cloud development project:cloudfunctions/<fn>/index.js real field names
  3. After listing the differences, only change apis/<name>.js / utils/util.js, do not rewrite the whole file
  4. If the returned fields changed → also update components/<name>/index.js access path and index.wxml binding
  5. Re-run execute; if it still fails, repeat 1~4, up to 5 times
  6. Still failing after 5 times:
    • Involves API splitting / storage dependency → change mcp.json 's apis[] structure + ensureStorageInit, re-run phase 1
    • Source has no corresponding capability or the dependency is not whitelisted → mark T9, in report.md record and terminate this API

C.1 Subclass: wx JSAPI undefined (not whitelisted)

Feature: at runtime it reports wx.<xxx> is not a function / Cannot read property '<xxx>' of undefined(wx.<ns> is undefined).

First assume it is not a code error, but that this JSAPI is not in the skill subpackage whitelist. Handle in the following order:

  1. Extract the API name from the error, and compare it against wxa-skills-generate SKILL.md 's D.1 (API side) / D.2 (component side) whitelist (Full checklistsee wxa-skills-generate/references/JSAPI_WHITELIST.md)
  2. If it is in the whitelist → check whether the call context is misplaced (component/API side exclusive),wx.request whether the component side is missing the declaration permissions["scope.dynamic"]
  3. If not in the whitelist → replace per D.7 (e.g. chooseImage → chooseMedia) or change the network request implementation
  4. No equivalent replacement → mark T9 and terminate.Do not use if (wx.x) / try/catch to swallow exceptions and call it fixed

C.2 Subclass: Skill module load failure (subpackage not registered)

Feature: at runtime it reports Skill code loading failed: module 'skills/<skill>/index.js' is not defined, require args is 'skills/<skill>/index.js'(or similar module ... is not defined / require args is ... module resolution error).

First assume it is not a JS code error, but that the subpackage integration is not wired up correctly. Check in the following order (Do not touch apis/ or components/):

  1. app.json 's subPackages whether skills is declared as an independent subpackage(missing this is the most common cause):
    "subPackages": [
      { "root": "skills", "name": "skills", "pages": [], "independent": true }
    ]
    
    • root must be the relative path of the skills directory;independent must be true;pages can be []
  2. app.json 's agent.skills[].path whether it points to skills/<skill>(consistent with subPackages.root )
  3. project.config.json 's packOptions.include whether it includes { "type": "folder", "value": "skills" }(otherwise the CLI will not package this directory when building)
  4. The directory itself:skills/<skill>/index.js actually exists, and within it wx.modelContext.registerAPI('<name>', fn) registers the error-corresponding <name>
  5. Only when the above four items are complete and correct → read according to the C-class main flow apis/<name>.js 's code

Compare against wxa-skills-generate SKILL.md phase 6 and references/CODE_TEMPLATES.md section 6 configuration snippets for verification; do not write randomly.

Class E: execute success but business data is empty

Feature:status === "ok" and invokeResult.isError !== true, but structuredContent is an empty list / empty object / total: 0 / only error fields.cannot be directly judged as passed—this is usually a symptom of wrong request parameters, authentication not taking effect, a misspelled URL, or an incorrect response unpacking path.

Troubleshoot in the following order (see references/CLI_AGENT_REFERENCE.md Category E troubleshooting process):

  1. Read the [ai-mode] log of consoleMessages to confirm the URL / parameters / headers actually sent in the request
  2. Read the main package source code to locate the interface's real request structure (URL / method / parameter names / auth header / response unpacking path)
  3. Compare the main package's real request with the request actually sent by apis/<name>.js : whether the URL / method / parameter names / auth header are consistent
  4. Authentication troubleshooting: the login state/token required by the main package request wrapper,apis/<name>.js whether the entry has completed await ensureLogin() etc.
  5. After troubleshooting, fix → rerun execute; if still empty and the request is confirmed to be completely consistent with the main package's real request → it may be a backend environment difference, record in trace "request verified correct after troubleshooting, suspected no data in environment", allow passing with a declaration

Upper limit 3 rounds; if after troubleshooting it is confirmed to be a code issue → switch to Category C to fix apis/<name>.js / utils/request.js。

Category D: render verification failed (including "clipped" / "style restoration below standard")

  1. Read the artifact to locate:consoleMessages.snapshotCard(main basis, especially [ai-mode] ... overflow logs) + elementTree(if issued by the CLI, auxiliary verification of field binding / list length / empty-state copy); only when the environment has image reading capability, additionally use the image method read_file read snapshot.png as an auxiliary signal for style restoration
  2. Modify according to the problem type (only modify components/<name>/, do not touch mcp.json / apis/*):
    • clipped ([ai-mode] ... overflow overflowed=true or data.overflowHeight > 0):index.wxss compress item height, use -wx-line-clamp:1~2 to truncate long text; root nodedo not write overflow / max-height / min-height / height(outer size and clipping are both imposed by the host; if the component sets its own height it will make the NotificationType.Overflow callback ineffective); when it is purely a list data overflow, you can use the half-screen atomic component collapsible-view to let the card expand itself, do not mistakenly change it to opening another half-screen page; only use an independent half-screen page when detail outside the card or user-supplied information is needed. Otherwise in index.js calculate visibleItems + omittedCount = total - visibleItems.length, and have WXML render "{{omittedCount}} more items not displayed"
    • overflow monitoring not integrated (consoleMessages.snapshotCard cannot find [ai-mode] ... overflow monitor=on baseline log): go back to the component JS skeleton of wxa-skill-generate, in created bind the listener via wx.modelContext.getViewContext(this).on(NotificationType.Overflow, ...) and synchronously after binding console.info('[ai-mode] {componentName} overflow monitor=on') output the baseline log
    • style inconsistent with the source page (restoration below standard): go back to the main package and read .wxml / .wxss + app.wxss, re-extract visual tokens (primary color, font size, border radius, spacing, dividers, image ratio) to override index.wxss. Unit recommended vw(1vw ≈ 7.5rpx)
    • images not displayed (soft optimization): in index.js the NotificationType.Result branch perform field normalization (e.g. imageUrl: item.imageUrl || item.cover || item.pic || item.thumb || item.image)
    • component uplink protocol violation(clicking the "active" button but the mini program AI cannot get the next hop, or the component calls the business interface itself): there are two legal uplink forms: ① single text(natural-language followUp); ② text + api/call Combination (structured toolCall)—— wx.modelContext.getContext(this).sendFollowUpMessage({ content: [{ type: 'text', text }, { type: 'api/call', data: { name, arguments } }] }), text is a short Chinese phrase from the user's perspective (≤ 12 characters),name must exist in the current skill mcp.json.apis[].name exists in,arguments fields are aligned with the target interface inputSchema.properties values are taken from e.currentTarget.dataset / this.data Violating forms include:content contains only api/call does not contain the leading text(missing user context, so the Mini Program AI cannot get the intent description), missing content array directly { type: 'api/call', ... }、name does not exist in mcp.json,arguments field names are wrong or contain placeholder values, or the component directly calls wx.request business interfaces.setRelatedPage using the created saved in this._viewCtx is a legal form and should not be reported as a cache reference error. Only change components/<name>/index.js 's tap handler,do not change apis/ or mcp.json; before each uplink, add a line of console.info('[ai-mode] {componentName} send api/call name=... args=...') so that the next render can be verified in consoleMessages.snapshotCard after the change
  3. after changing components/<name>/ rerun render (UI-type changes do not require re-execute; the existing artifacts can be reused via --from-execute ) → read render-result.<name>.json 's consoleMessages.snapshotCard: the baseline overflow monitor=on log must exist, and overflowed=truemust not appear (if image reading capability is available, screenshots may additionally be read as an auxiliary signal of style fidelity); do not pass solely based on exit code 0
  4. upper limit is 5 rounds; if still not passing, handle according to the C-class exit condition

Forbidden actions

  • It is forbidden to use curl / fetch / HTTP tools to directly verify network interfaces. Reasons: ① the Mini Program sandbox's authentication context (session / cookie / signature / wx.login code) cannot be reproduced in the terminal; ② the verification result has no reference value for skill subpackages. Network request changes can only be verified through execute.mjs verification.
  • It is forbidden to speculate and modify subpackage code without reading the main package source code.
  • render can be done via --from-execute reuse existing execute artifacts (args are taken from invokeResult.structuredContent); but render cares about UI rendering correctness, so if the change affects the data returned by the interface (changing apis/ / outputSchema), you need to re-execute first and then render; do not use old artifacts; when only changing UI (wxml/wxss/components/index.js), they can be reused.
  • It is forbidden to execute CLI commands for multiple interfaces concurrently.
  • It is forbidden to change the overall directory structure of the skill (<skill>/apis/ / <skill>/components/ / mcp.json / SKILL.md); only make minimal repairs at the file content level.

Backtracking records

Each execute / render appends to ./cli-agent-run/execute-trace.json:

{
  "skill": "<skill-dir>",
  "api": "<name>",
  "attempt": 1,
  "argumentsUsed": { },
  "argumentsSource": "user | upstream:<apiName> | default | empty",
  "executeStatus": "ok | error",
  "executeError": null,
  "renderChecks": { "rendered": true, "fieldsComplete": true, "overflow": false, "style": true, "ellipsis": true },
  "renderFailReason": null,
  "recovery": null
}

Termination conditions

Terminate if any one is satisfied:

  1. Stage 1 passes + every declared api execute succeeds + the interface with componentPath passes all 5 checks
  2. Stage 1 fails to pass for 5 consecutive rounds → stop and output a failure report
  3. Stage 4 still has interfaces failing after 5 cumulative rounds → stop and output a failure report
  4. Unrepairable type (_meta.diagnosis is non-null) or the tool remains unstable after warm-up/increased timeout/restart → stop and relay hint, do not produce DELIVERY.md
  5. T9-type problem → terminate immediately and inform the user

Phase 5 — Delivery Artifacts

1. Execution Report ./cli-agent-run/report.md(output on every termination)

# CLI `agent` 命令校验报告

- 执行时间:<ISO>
- project-path:<abs-path>
- skill 分包:<metaServicePkg, ...>(validate-report.json 中 skillDirs 字段)
- devtools:<DEVTOOLS_APP_PATH>

## 接口结果

| skill | api | componentPath | execute | render 5 项 | 产物 |
|-------|-----|---------------|---------|------------|------|
| business | searchItems | components/item-list/index | ✔ | ✔✔✔✔✔ | execute-result.searchItems.json / render-result.searchItems.snapshot.png |

## 未通过接口

- <apiName>:<原因简述>,详见 <产物路径>

## 修复摘要

- `skills/<skill>/apis/<name>.js`:<一行摘要>

2. Delivery Document ./DELIVERY.md(produced only when termination condition 1 holds)

Must be produced when termination condition 1 holds:

  • Write path:./DELIVERY.md(project root; if the user specifies another path, the user's path prevails, but it must be .md)
  • Template: strictly apply references/DELIVERY_TEMPLATE.md, all {占位符} must be replaced with actual values
  • execute-trace.json when it exists, reference it in the "Known Limitations" section
  • After writing,must also paste the complete MD content in the conversation, and must not merely say "the file has been generated"
  • Cannot write (permissions) → output the MD content directly in the conversation as a substitute

Outputting only report.md does not count as task completion;DELIVERY.md is the final deliverable.

3. Fix suggestions when not passed (append to the end of report.md)

  • Phase 4 non-fixable category / tool instability → do not modify code, relay according to diagnosis.hint ; prompt the user to rerun execute after the tool recovers, and do not produce DELIVERY.md
  • Phase 1 T1~T6 → directly fix the corresponding files, rerun validate
  • Phase 1 T7/T8 → adjust mcp.json of apis[] / utils/util.js the storage logic of index.js of registerAPI, rerun validate
  • Phase 4 Category A/B → fix apis/<name>.js argument assembly or utils/util.js of ensureStorageInit, rerun execute
  • Phase 4 Category C → fix against the main package source apis/<name>.js / utils/util.js, adjust if necessary mcp.json of outputSchema and the component value retrieval path, rerun execute
  • Phase 4 Category D → fix components/<name>/ the wxml/wxss/js, rerun render
  • T9 → terminate, inform the user that the feature is unsupported or suggest changing the implementation approach

Key constraints (emphasized again)

  • Acceptance goals cannot be downgraded: all atomic APIs and atomic components with componentPath must pass; suspension is limited to the hard cap of "5 consecutive rounds still not passed"
  • render must read consoleMessages.snapshotCard to make judgments, and must not only look at execute-result; when image reading capability is available, read screenshots as an auxiliary aid
  • "Not cropped + style restoration" is a hard criterion:not croppedis based on consoleMessages.snapshotCard existing in [ai-mode] ... overflow monitor=on baseline logs and overflowed=true not appearing (missing monitor=on = monitoring not integrated, treated as not passed);style restoration degreewhen image reading capability is available, read snapshot.png as an auxiliary signal; otherwise use elementTree field completeness as a fallback
  • Fixes must link the main package + subpackages; the truth is only in the main package
  • According to mcp.json the apis[] dependency relationships, arrange the execute order; when upstream dependencies exist, upstream execute must precede downstream. render has no such order constraint
  • Do not add new dependencies, do not rewrite the entire file