@alipay/alipay-aipay 1.5.8-beta4 → 1.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alipay/alipay-aipay",
3
- "version": "1.5.8-beta4",
3
+ "version": "1.5.8",
4
4
  "description": "支付宝 AI 付 Skill 安装包 - 优先安装 Agent Skill,并在 macOS/Linux 后台准备用户级 CLI 工具",
5
5
  "type": "module",
6
6
  "bin": {
package/skill/VERSION CHANGED
@@ -1 +1 @@
1
- 1.5.8-beta4
1
+ 1.5.8
@@ -163,12 +163,12 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
163
163
 
164
164
  5. Unix/macOS/Linux 的 `ensure` 只依据同一目标项目的 `.alipay-sandbox.json` 当前事实分流:文件不存在时执行既有 `create`;文件存在或为符号链接时执行既有 `verify` 安全路径。已存在配置不得再次调用 `createAnonymousSandbox`、不得覆盖,也不得因为中断重来要求用户删除配置;无效、不安全或被 Git 跟踪时不得使用,脚本按待配置终态统一输出后继续代码开发。
165
165
  6. 只有 Unix/macOS/Linux 创建分支会调用冻结的 `alipay-anonymous-sandbox.createAnonymousSandbox`、`{"request":{"appType":"PUBLICAPP"}}`、`PLATFORM` 环境变量和 `result.content[0].text -> success -> data` 解包逻辑;禁止传入 `PRODUCT`。Windows 不调用该方法或 `sandbox_config.sh`。
166
- 7. Unix/macOS/Linux 只接受以下互斥终态,不能把待配置标记当作成功:
166
+ 7. Unix/macOS/Linux 只接受以下互斥最终结果和一个临时恢复结果;待配置不算成功:
167
167
  - `READY`:退出码为 0;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_ENSURE_ACTION=CREATED|VERIFIED`、`SANDBOX_CONFIG_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_READY` 内部事实。
168
168
  - `CREATE_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/CREATE` 正文;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_CREATE` 内部事实;不得出现 READY 标记。
169
169
  - `VERIFY_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/VERIFY` 正文;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_VERIFY` 内部事实;不得出现 READY 标记。
170
- - `LOCAL_FS_RECOVERY`:仅创建分支、退出码 `77`、stdout 为空,且唯一包含 `SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE` 与 `CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`。这证明 `createAnonymousSandbox` 调用次数为 0;宿主支持时允许同一 `sandbox ensure` 命令访问两个 CLI 私有状态目录后原样重试一次。拒绝、不支持或再次命中时不再申请、不执行原始 MCP,直接记录 `sandboxConfigState=CREATE_PENDING` 并继续步骤 2,不新增第二份对客消息或用户确认。
171
- 8. 所有 `ALIPAY_AIPAY_INTERNAL:` 行只用于流程转移;即使宿主合并 stdout/stderr,也必须整行剔除后再判断对客正文。命中 `READY` 时剔除后 stdout 为空,不发送“环境检查完成”“沙箱已创建/已复核”等消息,记录 `sandboxConfigState=READY` 并直接进入步骤 2;命中待配置终态时,脚本 stdout 已包含唯一对客正文,Agent 原文发送且不得转述,分别记录 `sandboxConfigState=CREATE_PENDING|VERIFY_PENDING` 后直接进入步骤 2。两类终态都禁止追加 `jq`、`cat`、`grep`、`ls`、`stat` 或临时脚本;待配置状态还禁止读取、引用或复制当前无效/不存在配置中的任何字段。
170
+ - `LOCAL_FS_RECOVERY`:仅创建分支、退出码 `77`,唯一包含上述 CREATE pending 两个事实及 `SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE`、`CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`;stdout 是现有 pending 正文,先暂存且不得发送,CLI 调用次数为 0。允许权限升级后原样重试一次:`READY` 时丢弃暂存正文;普通 `CREATE_PENDING` 或再次命中本结果时只发送重试 stdout 并接受其 pending 事实;拒绝或宿主不支持时发送首次 stdout 并接受首次 pending 事实。不得再次申请、新增消息或确认。
171
+ 8. 所有 `ALIPAY_AIPAY_INTERNAL:` 行只用于转移;宿主合并输出时也先整行剔除。`READY` 的 stdout 为空,静默记录 `READY` 并直接进入步骤 2;普通 pending 或按上项降级时只原文发送最终选定的一份 stdout,记录 `CREATE_PENDING|VERIFY_PENDING` 并直接进入步骤 2。禁止追加 `jq|cat|grep|ls|stat` 或临时脚本;待配置时禁止读取、引用或复制无效/不存在配置的字段。
172
172
  9. 除上项精确的 `LOCAL_FS_RECOVERY` 外,命令非 0、终态标记缺失/重复/冲突、路径不一致或输出含 `SANDBOX_ERROR` 时属于脚本执行协议失败,仍停留在步骤 1;不得把这种执行异常降级为待配置,也不得临场改写 jq、重放原始 MCP 命令或自行检查敏感配置。CLI 已执行后才出现本地状态权限证据时,创建请求属于 `MAYBE_SENT`,脚本不得返回恢复 marker 或重放,`ensure` 直接使用既有 `CREATE_PENDING` 正文和终态继续代码开发。Windows 配置检查未通过仍按 Windows 登记分支处理。项目内自建 JSON、Agent 自报或补充诊断结果都不能替代上述终态。
173
173
  10. 准备阶段不得渲染 `sandbox.environment.summary` 或 `sandbox.environment.reminder`,不得展示沙箱买家密码,也不得输出“沙箱测试通过”。只有 `sandboxConfigState=READY` 且代码开发完成并通过配置后置校验后,才按步骤 5 的摘要展示规则对客展示沙箱环境配置。
174
174
 
@@ -556,7 +556,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message che
556
556
  ```
557
557
  <!-- ALIPAY_AIPAY_PRODUCT:END -->
558
558
 
559
- `failedItems` 与 `manualItems` 必须在各自受控单行值中包含对应的确定下一步;没有对应项目时明确传入“无”。`sandboxConfigState` 必须直接复用本轮脚本终态,只允许 `READY|CREATE_PENDING|VERIFY_PENDING`。`blockingDefectState` 来自同一最终 checklist:除沙箱配置及其直接依赖动作外,存在任一代码、安全或必要依据缺口时必须为 `PRESENT`,否则为 `NONE`。待配置时 `failedItems` 必须包含沙箱配置及其依赖动作未完成;恢复口令已经由步骤 1/3 的 `sandbox.configuration.pending` 输出,本结果不再重复。
559
+ `failedItems` 与 `manualItems` 必须在各自受控单行值中包含对应的确定下一步;没有对应项目时明确传入“无”。`sandboxConfigState` 必须直接复用本轮脚本终态,只允许 `READY|CREATE_PENDING|VERIFY_PENDING`。`blockingDefectState` 来自同一最终 checklist:除沙箱配置及其直接依赖动作外,存在任一代码、安全或必要依据缺口时必须为 `PRESENT`,否则为 `NONE`。待配置时 `failedItems` 必须包含沙箱配置及其依赖动作未完成;恢复口令已由步骤 1/3 选定并发送的唯一 `sandbox.configuration.pending` 正文输出,checklist runner 不生成也不重复该消息。
560
560
 
561
561
  同一次代码开发流程只渲染一次最终 checklist 结果;renderer stdout 是本次默认收口的唯一对客正文,禁止在前后追加风险说明、通过项摘要、执行说明、衔接提醒或第二份待办。
562
562
 
@@ -160,7 +160,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message che
160
160
 
161
161
  未完成公网 HTTPS `notify_url` 联调时,禁止把第一种表述写成第二种。
162
162
 
163
- `failedItems` 与 `manualItems` 必须在各自受控单行值中包含对应的确定下一步;没有对应项目时明确传入“无”。`overallResult=通过` 时两者必须都是“无”、`sandboxConfigState=READY` 且 `blockingDefectState=NONE`;“部分通过”必须至少存在一类缺口;“未通过”必须列出未通过项。`blockingDefectState` 只表示除沙箱配置及其直接依赖动作之外,是否存在代码、安全或必要依据缺口;当前环境无法自动取得 UI、浏览器或公网联调证据但代码与安全依据已完成时,只登记 `manualItems`,不把该人工待验证项自动计为 `PRESENT`。待配置时恢复口令由 renderer 固定生成。`full_process` 在待配置且无其他阻塞缺口,或 `READY` 且仅剩非阻塞人工待验证项时,输出“部分通过”并继续产品开通;其他未通过组合保持停留提醒。
163
+ `failedItems` 与 `manualItems` 必须在各自受控单行值中包含对应的确定下一步;没有对应项目时明确传入“无”。`overallResult=通过` 时两者必须都是“无”、`sandboxConfigState=READY` 且 `blockingDefectState=NONE`;“部分通过”必须至少存在一类缺口;“未通过”必须列出未通过项。`blockingDefectState` 只表示除沙箱配置及其直接依赖动作之外,是否存在代码、安全或必要依据缺口;当前环境无法自动取得 UI、浏览器或公网联调证据但代码与安全依据已完成时,只登记 `manualItems`,不把该人工待验证项自动计为 `PRESENT`。待配置恢复口令来自步骤 1/3 已选定并发送的唯一 `sandbox.configuration.pending` 正文,checklist runner 不生成或重复该消息。`full_process` 在待配置且无其他阻塞缺口,或 `READY` 且仅剩非阻塞人工待验证项时,输出“部分通过”并继续产品开通;其他未通过组合保持停留提醒。
164
164
 
165
165
  同一次代码开发只渲染一次最终结果;renderer stdout 是默认收口的唯一对客正文,禁止在前后追加通过摘要、风险说明、产品开通提醒或第二份待办。
166
166
 
@@ -62,6 +62,15 @@ LANGUAGE="$(normalize_language "$LANGUAGE")" || {
62
62
  CONFIG_PATH="${PROJECT_PATH}/.alipay-sandbox.json"
63
63
  GITIGNORE_PATH="${PROJECT_PATH}/.gitignore"
64
64
 
65
+ render_pending() {
66
+ printf '%s' '{}' | node "$RENDERER" sandbox.configuration.pending --variant "$PENDING_VARIANT" || {
67
+ echo "SANDBOX_ERROR:沙箱待配置消息渲染失败" >&2
68
+ return 1
69
+ }
70
+ emit_control_field "SANDBOX_PENDING_PATH" "$CONFIG_PATH" || return 1
71
+ emit_control "$PENDING_MARKER"
72
+ }
73
+
65
74
  if [ "$MODE" = "summary" ]; then
66
75
  case "$PRODUCT_TYPE" in aipay) PRODUCT_NAME="AI 按量付费" ;; webpay) PRODUCT_NAME="AI 网页应用收款" ;; apppay) PRODUCT_NAME="AI 移动应用收款" ;; *) echo "SANDBOX_ERROR:产品非法,仅支持 aipay|webpay|apppay" >&2; exit 2 ;; esac
67
76
  fi
@@ -99,6 +108,7 @@ if [ "$MODE" = "ensure" ] || [ "$MODE" = "reverify" ]; then
99
108
  if [ "$ensure_rc" -eq "$ALIPAY_CLI_LOCAL_STATE_PERMISSION_EXIT_CODE" ] &&
100
109
  [ "$(printf '%s\n' "$ensure_output" | grep -Fxc 'ALIPAY_AIPAY_INTERNAL:SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE')" -eq 1 ] &&
101
110
  [ "$(printf '%s\n' "$ensure_output" | grep -Fxc 'ALIPAY_AIPAY_INTERNAL:CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION')" -eq 1 ]; then
111
+ render_pending || exit 1
102
112
  emit_control "SANDBOX_LOCAL_FS_PERMISSION_MODE=CREATE"
103
113
  emit_control "CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION"
104
114
  exit "$ALIPAY_CLI_LOCAL_STATE_PERMISSION_EXIT_CODE"
@@ -122,12 +132,7 @@ if [ "$MODE" = "ensure" ] || [ "$MODE" = "reverify" ]; then
122
132
  break
123
133
  done
124
134
 
125
- printf '%s' '{}' | node "$RENDERER" sandbox.configuration.pending --variant "$PENDING_VARIANT" || {
126
- echo "SANDBOX_ERROR:沙箱待配置消息渲染失败" >&2
127
- exit 1
128
- }
129
- emit_control_field "SANDBOX_PENDING_PATH" "$CONFIG_PATH" || exit 1
130
- emit_control "$PENDING_MARKER"
135
+ render_pending || exit 1
131
136
  exit 0
132
137
  fi
133
138
 
@@ -255,14 +255,25 @@ function applicationBranch(result) {
255
255
  return { query_status: 'SUCCESS', application_type: applicationType, flow, candidates };
256
256
  }
257
257
 
258
- function hasAuthBlocker(result) {
259
- return internalLines(result.stderr).some((line) => [
258
+ function authBlockerFlows(result) {
259
+ return internalLines(result.stderr).filter((line) => [
260
260
  'AUTH_FLOW:AUTH_REQUIRED',
261
261
  'AUTH_FLOW:SCOPE_MISMATCH',
262
262
  'AUTH_FLOW:MCC_MISMATCH'
263
263
  ].includes(line));
264
264
  }
265
265
 
266
+ function hasAuthBlocker(result) {
267
+ return authBlockerFlows(result).length > 0;
268
+ }
269
+
270
+ function authRecoveryAction(results) {
271
+ const flows = new Set(results.flatMap(authBlockerFlows));
272
+ if (flows.has('AUTH_FLOW:SCOPE_MISMATCH') || flows.has('AUTH_FLOW:MCC_MISMATCH')) return 'MISMATCH';
273
+ if (flows.has('AUTH_FLOW:AUTH_REQUIRED')) return 'INIT';
274
+ return '';
275
+ }
276
+
266
277
  function hasLocalFsRecovery(result) {
267
278
  return internalLines(result.stderr).includes('CLI_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION');
268
279
  }
@@ -300,7 +311,8 @@ async function runDiscovery(args) {
300
311
  ]);
301
312
 
302
313
  const executedResults = [signingResult, serviceResult, applicationResult].filter(Boolean);
303
- const globalBlocker = executedResults.some(hasAuthBlocker) ? 'AUTHORIZATION_INVALID' : '';
314
+ const recoveryAction = authRecoveryAction(executedResults);
315
+ const globalBlocker = recoveryAction ? 'AUTHORIZATION_INVALID' : '';
304
316
  const retryWithLocalFs = !globalBlocker && executedResults.some(hasLocalFsRecovery);
305
317
  const retryWithNetwork = !globalBlocker && !retryWithLocalFs && executedResults.some(hasNetworkRecovery);
306
318
  const envelope = {
@@ -312,7 +324,10 @@ async function runDiscovery(args) {
312
324
  : { query_status: 'NOT_APPLICABLE', applicable: false },
313
325
  application: applicationBranch(applicationResult)
314
326
  };
315
- if (globalBlocker) envelope.global_blocker = globalBlocker;
327
+ if (globalBlocker) {
328
+ envelope.global_blocker = globalBlocker;
329
+ envelope.auth_recovery_action = recoveryAction;
330
+ }
316
331
  emitEnvelope(envelope);
317
332
  if (retryWithLocalFs) {
318
333
  process.stderr.write(`${internalPrefix}DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION\n`);
@@ -6,7 +6,7 @@
6
6
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" self-update check --skill-dir "<SKILL_DIR>"
7
7
  ```
8
8
 
9
- `<SKILL_DIR>` 必须是包含当前 updater 的本份 Skill 规范化绝对路径,不得换成启动目录、项目目录、Home、npm 源码根或其他副本。命令不得改成变量赋值、命令替换、相对路径或特定 shell 语法;`VERSION` 或 `references/runtime-entry.md` 缺失不改变该绑定,由检查器进入精确修复。
9
+ `<SKILL_DIR>` 必须是当前这份包含 updater 的 Skill 规范化绝对路径,不得换成启动目录、项目目录、Home、npm 源码根或其他副本。命令不得改成变量赋值、命令替换、相对路径或特定 shell 语法;`VERSION` 或 `references/runtime-entry.md` 缺失不改变该绑定,由检查器进入精确修复。
10
10
 
11
11
  stderr 必须恰有一个下列 `SELF_UPDATE:*` 内部终态;不对客,不透传 npm/npx 原始输出。
12
12
 
@@ -54,7 +54,7 @@
54
54
 
55
55
  ---
56
56
 
57
- ## 二、主流程
57
+ ## 主流程概览
58
58
 
59
59
  ```
60
60
  Step 1: 方案规划 → Step 2: 环境检查 → Step 3: 登录授权
@@ -94,7 +94,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message ente
94
94
 
95
95
  `onboarding_only` 固定使用 `ONBOARDING_ONLY`;`full_process` 只会在代码开发已通过后进入本 flow,固定使用 `FULL_PROCESS`。runner stdout 是该意图的最终产品开通消息,必须把 stdout 原文作为当前回复正文发给用户;命令面板、折叠输出或“已渲染/已展示”说明不能替代对客消息。发出 stdout 原文后直接停止本 flow,不再执行 Step 6 或追加第二份收口。
96
96
 
97
- ## 一、产品映射
97
+ ## 产品映射
98
98
 
99
99
  > 术语说明:本 Skill 对客统一使用“AI 网页应用收款”,覆盖电脑网页和手机浏览器网页/H5 场景;“网站支付”“电脑网站支付”“PC网站支付”“手机网站支付”“H5支付”均作为输入别名映射到同一产品。签约 payload 中的 `appType=PC_WEB` 是接口字段名,不代表只能用于 PC 端网页。
100
100
 
@@ -104,7 +104,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message ente
104
104
  | AI 网页应用收款 | webpay | WEBPAY | I1080300001000041203 | app:all,fast_instant_trade_pay:write | 需要3张网站截图 |
105
105
  | AI 移动应用收款 | apppay | APPPAY | I1080300001000041313 | app:all,auth_alipay_apppay:write | 未签约时需要 APP 名称和 3 张 APP 界面截图,签约状态固定按 `OFFLINE` 提交;选择新建应用时在 Step 4 前置采集移动平台信息,Step 5.3 才用于创建 |
106
106
 
107
- ## 三、Step 详解
107
+ ## Step 详解
108
108
 
109
109
  ### Step 1: 方案规划
110
110
 
@@ -140,7 +140,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-
140
140
 
141
141
  `MULTIPLE` 同时只接受唯一 `ALIPAY_AIPAY_INTERNAL:MCC_SELECTION_RECEIPT=<opaque>`。用户回复序号、当前候选表中的完整 MCC 名称或编码时,只能映射到该 receipt 绑定候选快照的对应行,并执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" --select "$SELECTED_MCC_CODE" --selection-receipt "$MCC_SELECTION_RECEIPT"`;`MCC_SEARCH_QUERY` 仍使用产生该候选快照的原始经营描述,runner 必须校验产品、原始描述摘要、候选成员和当前 MCC 表摘要均未变化后生成唯一方案,不重新运行 Agent 泛化或扩大候选。候选、MCC 表摘要、产品或原始经营描述变化后旧 receipt 失效。用户提供新的经营描述时才开始新一轮双路召回。`UNIQUE` 直接输出非阻塞方案;`MULTIPLE|NONE` 继续使用 runner 本次真实 stdout。无需固定重试口令,不得猜测或追加近似候选。
142
142
 
143
- 产品确定后,`salesCode`、`scope` 和材料要求统一取自“一、产品映射”,禁止在本步骤另建映射或改写固定值。
143
+ 产品确定后,`salesCode`、`scope` 和材料要求统一取自“产品映射”,禁止在本步骤另建映射或改写固定值。
144
144
 
145
145
  **MCC类目**:
146
146
  - 用户直接提供当前表内完整 MCC 编码时,由 runner 精确校验并使用表内原值,不读取 `modules/mcc-reference.md` 做 Agent 泛化;其余经营描述无论确定性召回结果为唯一、多候选或无匹配,都必须先按上文只读取一次该文件完成 Agent 语义判断
@@ -238,7 +238,7 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
238
238
 
239
239
  `auth.page` 非阻塞并追加“扫码完成后请回到 Agent 对话页面”;`auth.pending` 仅由 wait 耗尽或单次 confirm 的 PENDING 渲染,其他对客终态由脚本渲染对应消息。自动轮询期间即使 `login --complete` 已返回可复核状态,只要 `whoami` 尚未取得有效本机登录态,也继续按 PENDING 处理并消耗本次 wait 预算,不输出断头失败文案。剔除 `ALIPAY_AIPAY_INTERNAL:` 内部行后的 stdout 是当前动作唯一对客正文;禁止再次调用 renderer、另写近似话术、输出 stderr 或内部行、重复转述。授权脚本明确返回链接过期时必须重建,旧回复失效。
240
240
 
241
- 授权 `scope` 统一使用“一、产品映射”中当前产品的固定值,禁止自行修改。
241
+ 授权 `scope` 统一使用“产品映射”中当前产品的固定值,禁止自行修改。
242
242
 
243
243
  必须原样展示 init stdout,并在 login 前完成固定产品/MCC 上下文和 URL 逐项校验。禁止 CLI `verification_url`、非登记 URL 或要求用户输入确认码;这些正常路径约束均由本节命令和 `auth.sh` 托管,不为重复确认而读取模块。
244
244
 
@@ -255,7 +255,7 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
255
255
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-discovery run --product-type "$PRODUCT_TYPE" --sales-code "$SALES_CODE" [--reuse-sign-receipt "$AUTH_SIGN_REUSE_RECEIPT"]
256
256
  ```
257
257
 
258
- 只接受唯一 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_RESULT=<json>`。runner stdout 保留底层脚本已有的受控错误正文,并在没有全局授权阻断或本地权限恢复时追加原 `onboarding.discovery.summary` 标准正文;必须原文送达,不得手写、压缩或再次调用 `discovery-summary`。envelope 中每个分支只允许 `SUCCESS|QUERY_FAILED|NOT_APPLICABLE`:成功分支携带原脚本的确定状态和候选,失败不得伪装为空列表;存在 `global_blocker=AUTHORIZATION_INVALID` 时停止查询组,按 Step 3 重新授权,不进入 Step 4。不存在授权阻断且任一只读子查询命中 CLI 私有状态 preflight/调用后权限证据时,runner 只输出一个 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`,不输出摘要或网络恢复 marker;否则底层重试耗尽具有 DNS、连接、timeout、socket/TLS、`fetch failed`、`network_error`、`网络连接失败` 或连接前沙箱禁网强证据时,runner 额外且至多输出一个 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_FLOW:RETRY_WITH_NETWORK`。支付宝侧明确服务异常、业务错误、裸 `permission denied` 或结构异常不得触发这两个恢复 marker。
258
+ 只接受唯一 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_RESULT=<json>`。runner stdout 保留底层受控错误,并在无全局授权阻断或本地权限恢复时追加原 `onboarding.discovery.summary`;必须原文送达,不得手写、压缩或重放摘要。envelope 中每个分支只允许 `SUCCESS|QUERY_FAILED|NOT_APPLICABLE`;服务/应用成功时 `candidates` 必须是数组,应用还须有合法 `application_type`,否则不得当空列表。`global_blocker=AUTHORIZATION_INVALID` 必须唯一携带 `auth_recovery_action=INIT|MISMATCH`:任一子查询为 `SCOPE_MISMATCH|MCC_MISMATCH` 时固定 `MISMATCH` 并执行 Step 3 第 4 项,否则 `AUTH_REQUIRED` 固定 `INIT` 并执行第 1 项;随后停止查询且不进入 Step 4。字段非法、缺失或与该优先级矛盾时停止核对,禁止猜测。无授权阻断且任一子查询命中 CLI 私有状态权限证据时,runner 只输出一个 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION`,不输出摘要或网络 marker;否则仅在 DNS、连接、timeout、socket/TLS、`fetch failed`、`network_error`、`网络连接失败` 或连接前沙箱禁网强证据下至多输出一个 `ALIPAY_AIPAY_INTERNAL:DISCOVERY_FLOW:RETRY_WITH_NETWORK`。支付宝侧服务异常、业务错误、裸 `permission denied` 或结构异常不得触发二者。
259
259
 
260
260
  命中 `DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION` 时 stdout 必须为空;宿主支持时只允许当前同一 discovery 命令访问两个 CLI 私有状态目录并原样重试一次。拒绝、不支持或再次命中时停止申请,按最新 envelope 保留失败分支,不渲染额外恢复文案。命中 `DISCOVERY_FLOW:RETRY_WITH_NETWORK` 时先暂存本次 stdout,不对客发送;宿主支持时申请联网权限,并以完全相同的产品、salesCode 和签约复用回执原样重试同一条 discovery 命令一次。重试成功只送达重试后的 stdout 并继续;权限被拒绝、宿主不支持时送达首次 stdout 一次;重试仍返回同一 marker 时只送达重试后的 stdout 一次并停止再次申请。两类恢复都不新增对客文案、确认点或 closeout 枚举。优先级固定为 `AUTHORIZATION_INVALID`、本地权限、网络权限,禁止同时进入两个恢复分支。
261
261
 
@@ -273,7 +273,7 @@ Step 5 直接使用对应 phase 的完整命令;仅出现脚本异常、需要
273
273
 
274
274
  所有内部事实行都必须以 `ALIPAY_AIPAY_INTERNAL:` 开头;宿主合并 stdout/stderr 时也逐行剔除。无前缀的相似文本不得作为流程事实;唯一字段缺失、重复或冲突时按结构异常处理。
275
275
 
276
- - MCP 认证失败或产品/scope/MCC 授权不匹配:discovery runner 子查询只上报认证失效事实,不在并发子进程内 logout;立即停止查询组,不再处理剩余查询结果。授权不匹配时调用 Step 3 的 `auth.sh mismatch`,由该命令统一 logout 并重新授权。重新授权后仅恢复尚未执行的查询,保留重新授权前已经成功取得且主体未变化的结果。若无法确认仍为同一账号主体,则重新执行全部适用查询。
276
+ - MCP 认证失败或产品/scope/MCC 不匹配:子查询只报事实、不 logout,并停止查询组;只按 `auth_recovery_action` 执行 Step 3 第 1 或第 4 项,禁止凭 stdout 猜测。重新授权后保留主体未变化的成功结果并恢复其余查询;主体无法确认时重查全部。
277
277
  - 强网络证据且无授权阻断:只按上文 `DISCOVERY_FLOW:RETRY_WITH_NETWORK` 契约申请权限并原样重试 discovery 一次;连接前沙箱明确禁网不在子脚本内浪费两次固定间隔重试。远端服务异常仍使用既有分支失败和收口,不误报为本地联网权限。
278
278
  - CLI 私有状态权限且无授权阻断:只按上文 `DISCOVERY_FLOW:RETRY_WITH_LOCAL_FS_PERMISSION` 契约恢复同一只读查询组一次;不得改走 auth mismatch、不得解释为网络或支付宝侧查询失败。
279
279
  - 单个业务失败、响应结构错误或 MCP 服务失败,但当前会话仍有效:把该分支标记为查询失败,继续其他不依赖该结果的只读查询,最后一次性输出“已取得结果 + 失败分支”摘要。不得把失败视为空列表;应用查询失败时禁止应用复用/创建,服务查询失败时禁止服务复用/新建/修改。
@@ -288,9 +288,9 @@ Step 5 直接使用对应 phase 的完整命令;仅出现脚本异常、需要
288
288
  <!-- ALIPAY_AIPAY_FLOW:ONBOARDING_BRANCH_SUMMARY:START -->
289
289
  ### Step 4: 分支摘要与分类材料
290
290
 
291
- Step 3.1 的 discovery runner 已在同一次 stdout 中展示签约、服务市场和应用发布摘要;网站支付和 APP 支付的服务市场固定为“无需处理”,查询失败显示“查询失败”。进入本阶段后只消费同一 `DISCOVERY_RESULT` envelope,禁止再次调用 `discovery-summary`、手写状态枚举或重复输出摘要。
291
+ Step 3.1 通常已在同一次 stdout 展示三分支摘要;网站支付和 APP 支付的服务市场固定为“无需处理”,查询失败显示“查询失败”。本地权限未恢复时没有摘要,只消费最新失败 envelope,禁止补写或重放。进入本阶段后只消费同一 `DISCOVERY_RESULT`,不得再次调用 `discovery-summary`、手写或重复输出摘要。
292
292
 
293
- 轮到服务或应用时,以下 runner 用同一 discovery 快照一次生成候选事实和适用选择提示;stdout 是唯一对客正文,禁止提前展示、手工拼表、压缩为 ID、拆开或改写:
293
+ 轮到服务或应用时,只有 `query_status=SUCCESS` 且 `candidates` 为数组,才用以下 runner 基于同一快照生成候选事实和选择提示;stdout 是唯一正文,禁止提前展示、手工拼表、压缩、拆分或改写:
294
294
 
295
295
  ```bash
296
296
  # 仅按量付费,轮到服务类别时
@@ -300,7 +300,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message serv
300
300
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-candidates --application-type "$APPLICATION_TYPE" --candidates-json "$APP_CANDIDATES_JSON"
301
301
  ```
302
302
 
303
- 空候选时直接进入新建资料分支;非空时发出 runner stdout 后等待当前候选允许的选择。
303
+ 只有成功分支的实际 `candidates.length === 0` 才进入新建;非空时发送 runner stdout 并等待选择。`QUERY_FAILED`、候选缺失或类型非法均阻断该分支,禁止候选 runner、创建资料和写动作,不影响其他成功分支。
304
304
 
305
305
  每次只展示一个类别,同类一次收齐且只补问缺失或错误字段。`MATERIAL_CATEGORY` 固定为 `signing|service|application`;`INITIAL` 对应“待补充”,`PARTIAL` 对应“部分已提供,待补充”,`INVALID` 对应“校验失败,需更正”,其他状态停止核对。字段别名只交给 runner 归一化;禁止使用 `签约资料` 等同义词,正常路径禁止调用 `render --schema`、`jq` 或读取消息目录。只执行:
306
306
 
@@ -359,7 +359,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sign --product apppay -
359
359
  <!-- ALIPAY_AIPAY_STAGE:onboarding.service.start products=aipay -->
360
360
  #### 5.2 服务市场注册(仅按量付费)
361
361
 
362
- 列表为空进入新建;存在候选只接受当前完整 `serviceId`、`新建` 或 `修改:<当前serviceId>`,不接受序号、候选外/历史 ID 或自由格式修改。创建/修改必须用服务名称、描述、地址、单价、请求示例 JSON 五项资料通过 `validate`。单价可输入纯数字或带 `元`/`元/次` 后缀(可空格),后续只复用脚本 `SERVICE_PRICING=<纯数字>` 内部事实。复用不写;创建由 `save` 内部重查完整列表,只有当前服务数量小于固定上限 `10` 才调用保存方法;达到 `10` 个时禁止调用保存方法,调用次数必须为 0。校验通过先输出非阻塞摘要后直接创建。只有修改必须取得 `SERVICE_UPDATE_ONLY` 当前摘要确认;会话、主体、产品、目标或参数变化即失效。成功实际 `serviceId` 记为 `productionServiceId`;状态未返回只能写“状态未取得”,不得推断或重复 `save`。
362
+ 仅 Step 3.1 服务查询成功且候选数组为空时新建;查询失败、缺失或非法时阻断。存在候选只接受当前完整 `serviceId`、`新建` 或 `修改:<当前serviceId>`,不接受序号、候选外/历史 ID 或自由格式修改。创建/修改必须用服务名称、描述、地址、单价、请求示例 JSON 五项资料通过 `validate`。单价可输入纯数字或带 `元`/`元/次` 后缀(可空格),后续只复用脚本 `SERVICE_PRICING=<纯数字>` 内部事实。复用不写;创建由 `save` 内部重查完整列表,只有当前服务数量小于固定上限 `10` 才调用保存方法;达到 `10` 个时禁止调用保存方法,调用次数必须为 0。校验通过先输出非阻塞摘要后直接创建。只有修改必须取得 `SERVICE_UPDATE_ONLY` 当前摘要确认;会话、主体、产品、目标或参数变化即失效。成功实际 `serviceId` 记为 `productionServiceId`;状态未返回只能写“状态未取得”,不得推断或重复 `save`。
363
363
 
364
364
  ```bash
365
365
  # 创建摘要后不等待回复
@@ -388,7 +388,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" service save --service-
388
388
  <!-- ALIPAY_AIPAY_STAGE:onboarding.application.start -->
389
389
  #### 5.3 应用发布
390
390
 
391
- **应用分支**:按量付费/网站支付使用 `WEBAPP`,APP 支付使用 `MOBILEAPP`。复用 Step 3.1 候选和 Step 4 条件资料,按本节固定命令执行复用或新建、设置/校验应用公钥和提审;产品上下文、平台字段、`appSign` 边界、MCP 参数和返回处理由 `app.sh` 托管,只有异常诊断或业务解释时读取 `modules/app-release.md`。
391
+ **应用分支**:按量付费/网站支付使用 `WEBAPP`,APP 支付使用 `MOBILEAPP`。仅 Step 3.1 查询成功、类型合法且候选为数组时继续;失败、缺失或非法时阻断。复用候选和 Step 4 资料后按固定命令执行复用/新建、设钥/验钥和提审;上下文、平台字段、`appSign`、MCP 参数和返回由 `app.sh` 托管,仅异常诊断或业务解释时读取 `modules/app-release.md`。
392
392
 
393
393
  候选正文只由 Step 4 的同快照 runner 输出:存在 `ON_LINE` 时只接受当前完整 `appId` 或 `新建`;仅非上线候选时只接受 `新建|暂不新建`;禁止序号、历史/自报 ID。`新建` 已构成创建确认,候选复查不变且资料齐备时不追加确认。按量付费/网站支付新建时说明应用公钥要求;APP 支付首次资料只执行下列固定消息,一次收集 `IOS` 的 `bundleId`、`ANDROID` 的 `appPackage+appSign` 或 `ALL` 的三项组合,补问只用消息中的中文字段名:
394
394
 
@@ -515,13 +515,13 @@ renderer 还会按 `productName` 和分支完成条件自动派生上线前检
515
515
 
516
516
  ---
517
517
 
518
- ## 四、错误处理(全局规则)
518
+ ## 错误处理(全局规则)
519
519
 
520
520
  所有 CLI/MCP 操作立即使用脚本内置错误检测,失败后禁止解析业务结果;分类与恢复以 `modules/scripts/error_handler.sh` 和按需读取的 `modules/error-handling.md` 为准。Step 3.1 查询失败仍按分支隔离。
521
521
 
522
522
  ---
523
523
 
524
- ## 五、当前会话事实
524
+ ## 当前会话事实
525
525
 
526
526
  只保留当前已确认产品/MCC、已验证材料、候选和脚本结果;重入时重新校验授权并查询全部适用分支。可验证的提前材料直接复用,否则重收。
527
527