@alipay/alipay-aipay 1.6.7-beta1 → 1.6.7-beta3

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.
Files changed (25) hide show
  1. package/package.json +1 -1
  2. package/skill/VERSION +1 -1
  3. package/skill/references/integration/flow.md +17 -15
  4. package/skill/references/integration/modules/sandbox/alipay-sandbox-tool.md +1 -1
  5. package/skill/references/integration/modules/scripts/sandbox_config.sh +4 -2
  6. package/skill/references/normal/full-process-routing.md +3 -1
  7. package/skill/references/normal/integration-worker.md +12 -6
  8. package/skill/references/normal/scripts/common.sh +12 -14
  9. package/skill/references/normal/scripts/integration_message_runner.mjs +17 -10
  10. package/skill/references/normal/scripts/interaction_reply.mjs +1 -2
  11. package/skill/references/normal/scripts/onboarding_discovery_runner.mjs +9 -2
  12. package/skill/references/normal/scripts/onboarding_message_runner.mjs +25 -16
  13. package/skill/references/normal/scripts/onboarding_recovery_runner.mjs +1 -2
  14. package/skill/references/normal/scripts/render_customer_message.mjs +3 -3
  15. package/skill/references/normal/scripts/runtime.mjs +40 -6
  16. package/skill/references/normal/scripts/telemetry.mjs +306 -493
  17. package/skill/references/normal/telemetry.md +60 -4
  18. package/skill/references/onboarding/flow.md +32 -26
  19. package/skill/references/onboarding/modules/app-release.md +2 -0
  20. package/skill/references/onboarding/modules/scripts/app.sh +1 -1
  21. package/skill/references/onboarding/modules/scripts/ar_sign_apply.sh +2 -2
  22. package/skill/references/onboarding/modules/scripts/auth.sh +4 -4
  23. package/skill/references/onboarding/modules/scripts/mcc.sh +17 -5
  24. package/skill/references/onboarding/modules/scripts/service.sh +2 -2
  25. package/skill/references/runtime-entry.md +10 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alipay/alipay-aipay",
3
- "version": "1.6.7-beta1",
3
+ "version": "1.6.7-beta3",
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.6.7-beta1
1
+ 1.6.7-beta3
@@ -25,7 +25,7 @@
25
25
 
26
26
  ### 耗时事件规则
27
27
 
28
- `start-run` 已确定 `run_id`;stage 由登记动作异步记录,Agent 不手工上报。遥测失败不改变业务;诊断只按需读 `../normal/telemetry.md`。
28
+ `start-run` 已确定 `RUN_ID`;stage 由登记动作在前台固定 event/c4 并执行最长 3 秒的同步上传,Agent 不重复手工上报。每个会生成 stage 的命令前回顾当前可见用户消息得到 `HISTORY_COUNT`,并传入下文登记的两个 gateway 内部参数;无法可靠回顾时用 `null`。遥测失败不改变业务、卡点或对客交付;诊断只按需读 `../normal/telemetry.md`。
29
29
 
30
30
  ### 服务声明执行护栏
31
31
 
@@ -151,7 +151,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message loc
151
151
  3. Unix/macOS/Linux 从本 flow 所在的 `references/integration/` 目录执行唯一准备入口:
152
152
 
153
153
  ```bash
154
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox ensure "<规范化项目路径>" "<已确认服务端语言>"
154
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox ensure "<规范化项目路径>" "<已确认服务端语言>" [--telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"]
155
155
  ```
156
156
 
157
157
  4. Windows 不调用快速沙箱脚本。普通代码开发或完整接入请求没有明确要求当前配置沙箱时,不展示申领消息、不补问,直接记录 `sandboxConfigState=VERIFY_PENDING` 并继续步骤 2。只有用户明确要求现在配置/恢复 Windows 沙箱时,才执行下列既有标准消息 `sandbox.windows.manual_setup`;该消息使用自由资料回复,不要求用户输入 `1` 或自行执行脚本。随后只处理用户针对本轮该消息提供的资料:完整有效时写入目标项目的受保护本机配置并记录 `READY`,部分或错误时使用既有受控失败分支补问实际缺失/错误字段:
@@ -166,10 +166,10 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
166
166
  6. 只有 Unix/macOS/Linux 创建分支会调用冻结的 `alipay-anonymous-sandbox.createAnonymousSandbox`、`{"request":{"appType":"PUBLICAPP"}}`、`PLATFORM`、`PLATFORM_ID`、`ALIPAYCLI_BIZ_INFO` 环境变量和 `result.content[0].text -> success -> data` 解包逻辑;`ALIPAYCLI_BIZ_INFO` 固定标识当前调用方 Skill、当前生效版本和匿名 `skill_user_id`,禁止传入 `PRODUCT`。Windows 不调用该方法或 `sandbox_config.sh`。
167
167
  7. Unix/macOS/Linux 只接受以下互斥最终结果和一个临时恢复结果;待配置不算成功:
168
168
  - `READY`:退出码为 0;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_ENSURE_ACTION=CREATED|VERIFIED`、`SANDBOX_CONFIG_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_READY` 内部事实。
169
- - `CREATE_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/CREATE` 正文;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_CREATE` 内部事实;不得出现 READY 标记。
170
- - `VERIFY_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/VERIFY` 正文;唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_VERIFY` 内部事实;不得出现 READY 标记。
169
+ - `CREATE_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/CREATE` 正文,并产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.configuration.pending`;另有唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_CREATE` 内部事实;不得出现 READY 标记。
170
+ - `VERIFY_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/VERIFY` 正文,并产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.configuration.pending`;另有唯一带 `ALIPAY_AIPAY_INTERNAL:` 前缀的 `SANDBOX_PENDING_PATH=<同一目标项目绝对路径>/.alipay-sandbox.json` 和 `FLOW:SANDBOX_CONFIG_PENDING_VERIFY` 内部事实;不得出现 READY 标记。
171
171
  - `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 事实。不得再次申请、新增消息或确认。
172
- 8. 所有 `ALIPAY_AIPAY_INTERNAL:` 行只用于转移;宿主合并输出时也先整行剔除。`READY` 的 stdout 为空,静默记录 `READY` 并直接进入步骤 2;普通 pending 或按上项降级时只原文发送最终选定的一份 stdout,记录 `CREATE_PENDING|VERIFY_PENDING` 并直接进入步骤 2。禁止追加 `jq|cat|grep|ls|stat` 或临时脚本;待配置时禁止读取、引用或复制无效/不存在配置的字段。
172
+ 8. 所有 `ALIPAY_AIPAY_INTERNAL:` 行只用于转移;宿主合并输出时也先整行剔除。`READY` 的 stdout 为空,静默记录 `READY` 并直接进入步骤 2;普通 pending 或按上项降级时,必须校验唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.configuration.pending`,下一动作将剔除内部行后的 stdout 原文独立送达,再记录 `CREATE_PENDING|VERIFY_PENDING` 并直接进入步骤 2。禁止追加 `jq|cat|grep|ls|stat` 或临时脚本;待配置时禁止读取、引用或复制无效/不存在配置的字段。
173
173
  9. 除上项精确的 `LOCAL_FS_RECOVERY` 外,命令非 0、终态标记缺失/重复/冲突、路径不一致或输出含 `SANDBOX_ERROR` 时属于脚本执行协议失败,仍停留在步骤 1;不得把这种执行异常降级为待配置,也不得临场改写 jq、重放原始 MCP 命令或自行检查敏感配置。CLI 已执行后才出现本地状态权限证据时,创建请求属于 `MAYBE_SENT`,脚本不得返回恢复 marker 或重放,`ensure` 直接使用既有 `CREATE_PENDING` 正文和终态继续代码开发。Windows 配置检查未通过仍按 Windows 登记分支处理。项目内自建 JSON、Agent 自报或补充诊断结果都不能替代上述终态。
174
174
  10. 准备阶段不得渲染 `sandbox.environment.summary` 或 `sandbox.environment.reminder`,不得展示沙箱买家密码,也不得输出“沙箱测试通过”。只有 `sandboxConfigState=READY` 且代码开发完成并通过配置后置校验后,才按步骤 5 的摘要展示规则对客展示沙箱环境配置。
175
175
 
@@ -201,6 +201,8 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
201
201
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --root-intent "$ROOT_INTENT" --product-type "$PRODUCT_TYPE" --product-name "$PRODUCT_NAME" --project-path "$PROJECT_PATH" --project-selection "$PROJECT_SELECTION" --language "$SERVER_LANGUAGE" --framework "$FRAMEWORK" --framework-source "$FRAMEWORK_SOURCE"
202
202
  ```
203
203
 
204
+ 若 bootstrap 尚未创建正式 run,本命令在任何 Integration 业务 stage 前原子创建 run 和 `clarify_intent`,并输出后续唯一使用的 `RUN_ID` marker;触发本命令的首条消息不计入新 run。已有同组合 active run 时只复用 marker。步骤 3 之后所有能生成 stage 的登记命令都必须携带当前 telemetry context;runner 已生成 stage 后 Agent 禁止重复调用 `telemetry stage`。
205
+
204
206
  runner 失败时不得展示手写方案或进入步骤 3。成功时必须取得唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失或重复都视为失败。stdout 是步骤 2 唯一对客消息;命令后的下一个动作必须把 stdout 作为可见进行中消息原文送达,不得作为最终答复结束当前回合,送达前禁止调用工具。命令面板、折叠输出、内部思考或“已渲染/已展示”说明都不能替代交付;禁止添加 `<...>` 标签、“已输出完整方案”“服务声明已打印”、重复摘要或任何前后缀。送达后同一回合立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE"`,不得总结、询问、等待回复、解码内部值或再次渲染方案。
205
207
 
206
208
  - `full_process`:`../normal/full-process-routing.md` 已用同一方案绑定检查器事实、产品、项目、语言/框架和服务声明;送达后按该路由选择唯一 Integration Worker 或当前 Agent 执行,禁止重显或确认。两者都须完成本 flow 全部适用接口、条件和 checklist。用户中断后事实变化则返回 router 重新澄清、扫描和展示。方案仍禁止提前展示 MCC、授权范围、开通材料或 onboarding 待办。
@@ -237,7 +239,7 @@ runner 失败时不得展示手写方案或进入步骤 3。成功时必须取
237
239
  4. Unix/macOS/Linux 仅在 `sandboxConfigState=READY` 时执行以下唯一复核命令,不先检查文件、不读取字段、不运行其他诊断:
238
240
 
239
241
  ```bash
240
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox reverify "<规范化项目路径>" "<已确认服务端语言>"
242
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox reverify "<规范化项目路径>" "<已确认服务端语言>" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"
241
243
  ```
242
244
 
243
245
  5. `reverify` 只接受与步骤 1 相同的三个互斥终态。`READY` 更新 `sandboxConfigState=READY` 并立即进入步骤 4;`VERIFY_PENDING` 已由脚本输出唯一待配置正文,更新状态后立即进入步骤 4。`reverify` 不允许创建分支,若异常出现 `CREATED|CREATE_PENDING` 标记必须按协议失败停止。所有终态之后禁止追加任何 `jq`、`cat`、`grep`、`ls`、`stat` 或临时脚本。
@@ -332,12 +334,12 @@ curl -sL "<当前契约 sourceUrl 中的官方页面>"
332
334
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox summary "<productType>" "<规范化项目路径>" "<已确认服务端语言>"
333
335
  ```
334
336
 
335
- 该命令 stdout 只渲染 `sandbox.environment.summary` 与 `sandbox.environment.reminder`;带 `ALIPAY_AIPAY_INTERNAL:` 前缀的配置路径和 `FLOW:SANDBOX_CONFIGURED` 只用于流程转移,严禁对客。命令不重新创建沙箱,不调用 `createAnonymousSandbox`。`productType` 只能来自步骤 2 已确认的 `aipay|webpay|apppay`;配置路径和语言必须与步骤 1/3 一致。摘要展示失败时不得进入沙箱测试或付款体验,也不得改用 Agent 自写表格。
337
+ 该命令 stdout 只渲染 `sandbox.environment.summary` 与 `sandbox.environment.reminder`;命令必须产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.environment.summary`,带 `ALIPAY_AIPAY_INTERNAL:` 前缀的配置路径和 `FLOW:SANDBOX_CONFIGURED` 只用于流程转移,严禁对客。命令返回后下一动作必须将剔除内部行后的 stdout 原文独立送达,再进入后续沙箱测试或付款体验;不得把工具面板输出或自写摘要当作已送达。命令不重新创建沙箱,不调用 `createAnonymousSandbox`。`productType` 只能来自步骤 2 已确认的 `aipay|webpay|apppay`;配置路径和语言必须与步骤 1/3 一致。摘要展示失败时不得进入沙箱测试或付款体验,也不得改用 Agent 自写表格。
336
338
 
337
339
  Windows 从项目实际读取的同一本机配置构造不含密码和密钥原文的 `ENVIRONMENT_ROWS`,再从本 flow 所在目录执行以下固定命令;不得重新索取或复述步骤 1 已提供的敏感值,也不得改用 Unix 快速沙箱脚本:
338
340
 
339
341
  ```powershell
340
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message windows-sandbox-summary --product-name "$PRODUCT_NAME" --config-path "$CONFIG_PATH" --environment-rows "$ENVIRONMENT_ROWS"
342
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message windows-sandbox-summary --product-name "$PRODUCT_NAME" --config-path "$CONFIG_PATH" --environment-rows "$ENVIRONMENT_ROWS" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"
341
343
  ```
342
344
 
343
345
  Windows 的 `CONFIG_PATH` 必须是步骤 1/3 已校验的实际本机配置绝对路径;`ENVIRONMENT_ROWS` 只包含实际取得的非敏感应用、商家、买家和沙箱标识,缺失可选项直接省略。两个 renderer 任一失败都按摘要展示失败处理,禁止手写补齐。
@@ -500,7 +502,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message ser
500
502
  **完成条件**:
501
503
  - [INT.CLOSEOUT.SAFETY_AND_NEXT_STEPS_PRINTED] 已向用户明文输出安全红线和完整上线指引
502
504
 
503
- **安全与上线提醒(必须明文打印给用户)**:使用 `../normal/json/customer-messages.json` 的 `integration.safety.closeout`,按 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY` 映射产品并传入实际验收口径。模板覆盖私钥保护、支付结果依据、异常恢复、异步通知或 `Payment-Proof`/履约确认、生产配置、真实 `serviceId` 和私钥格式;不重复沙箱摘要、账号密码、Android 下载或步骤 6 体验。不得临场删减、拆分或维护近似话术。必须执行:
505
+ **安全与上线提醒(必须明文打印给用户)**:使用 `../normal/json/customer-messages.json` 的 `integration.safety.closeout`,按 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY` 映射产品并传入实际验收口径。模板覆盖私钥保护、支付结果依据、异常恢复、异步通知或 `Payment-Proof`/履约确认、生产配置、真实 `serviceId` 和私钥格式;不重复沙箱摘要、账号密码、Android 下载或步骤 6 体验。不得临场删减、拆分或维护近似话术。命令必须产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.safety.closeout`;返回后的下一动作先将 stdout 原文独立送达,再进入步骤 8。必须执行:
504
506
 
505
507
  ```bash
506
508
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message safety-closeout --variant "$PRODUCT_VARIANT" --acceptance-summary "$ACCEPTANCE_SUMMARY"
@@ -528,7 +530,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
528
530
 
529
531
  **执行边界**:默认禁止安装依赖或浏览器、切换运行时版本、启动长期服务、申请网络/端口权限、执行截图或 UI 自动化,也不得重复步骤 6 已完成的端到端测试。遇到 `EPERM`、网络受限、缺少浏览器等环境限制时,将对应项标记为“人工待验证”并停止扩展排查;不得据此推断代码或运行时兼容问题。只有用户明确要求继续扩展验证时,才展示拟执行动作并按原确认规则处理。
530
532
 
531
- 步骤 3 至步骤 7 的必要依据、配置摘要、代码修复、网站回跳或按量付费联调在本轮无法继续时,跳过所有依赖该失败事实的后续动作,但仍进入本步骤:把未满足条件和被跳过动作按实际证据标记为失败或人工待验证,并使用同一 `integration.checklist.result` 收口。不得为了生成结果重新执行已阻断的外部动作。`full_process` 中,只有沙箱为 `CREATE_PENDING|VERIFY_PENDING` 且代码实现与不依赖沙箱的安全检查均通过、或沙箱为 `READY` 且仅剩非阻塞人工待验证项时,才在输出标准“部分通过”结果后继续 onboarding;存在其他代码、安全或必要依据失败时仍停在代码开发。
533
+ 步骤 3 至步骤 7 的必要依据、配置摘要、代码修复、网站回跳或按量付费联调在本轮无法继续时,跳过所有依赖该失败事实的后续动作,但仍进入本步骤:把未满足条件和被跳过动作按实际证据标记为失败或人工待验证,并使用同一 `integration.checklist.result` 收口。不得为了生成结果重新执行已阻断的外部动作。该 runner 只能在当前产品匹配且未收口的 `integration_only|full_process` active run 内执行;telemetry 开启时缺少或不匹配 run 会直接停止,禁止完成 checklist 后静默丢失 `integration.complete_coding`。`full_process` 中,只有沙箱为 `CREATE_PENDING|VERIFY_PENDING` 且代码实现与不依赖沙箱的安全检查均通过、或沙箱为 `READY` 且仅剩非阻塞人工待验证项时,才在输出标准“部分通过”结果后继续 onboarding;存在其他代码、安全或必要依据失败时仍停在代码开发。
532
534
 
533
535
  校验项包括:
534
536
  - 签名验签
@@ -545,7 +547,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
545
547
 
546
548
  若审计发现问题且命令未传 `--finalize-audit-findings true`,stdout 为空,stderr 只接受唯一 `ALIPAY_AIPAY_INTERNAL:CHECKLIST_AUDIT={state:"REPAIR_REQUIRED",findings:[...]}`。本轮可修复时先修复,重新加载 checklist 阶段取得新 scope,再用更新后的实际证据重跑同一结论命令,禁止渲染中间结果。无法修复时向同一命令追加 `--finalize-audit-findings true`,runner 将 findings 合入“未通过”并收口;该内部重跑不新增用户操作点。`full_process` 必须停在 Integration。
547
549
 
548
- 对客结论统一使用 `integration.checklist.result`;整体结论、失败/部分通过项和人工待验证项必须来自最终一轮 checklist 实际证据。首次调用前先按以下完整契约确定参数,禁止改枚举:
550
+ 对客结论统一使用 `integration.checklist.result`;整体结论、失败/部分通过项和人工待验证项必须来自最终一轮 checklist 实际证据。最终渲染成功时必须产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.checklist.result`;命令返回后的下一动作先将 stdout 原文独立送达,不得以工具面板或自写总结替代。首次调用前先按以下完整契约确定参数,禁止改枚举:
549
551
 
550
552
  - `variant` 映射 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY`;`overallResult` 只允许“通过、部分通过、未通过”。
551
553
  - `failedItems`/`manualItems` 必须是含下一步的受控单行值,无项目传“无”。`sandboxConfigState` 只允许 `READY|CREATE_PENDING|VERIFY_PENDING`;除沙箱配置及其直接依赖外存在代码、安全或必要依据缺口时 `blockingDefectState=PRESENT`,否则 `NONE`。待配置时 `failedItems` 必须列出沙箱配置及依赖动作未完成;恢复口令只由步骤 1/3 已发送的 `sandbox.configuration.pending` 正文提供。
@@ -556,21 +558,21 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
556
558
 
557
559
  <!-- ALIPAY_AIPAY_PRODUCT:aipay:START -->
558
560
  ```bash
559
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant AIPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --sandbox-result "$SANDBOX_RESULT" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER"
561
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant AIPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --sandbox-result "$SANDBOX_RESULT" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"
560
562
  ```
561
563
  <!-- ALIPAY_AIPAY_PRODUCT:END -->
562
564
  <!-- ALIPAY_AIPAY_PRODUCT:webpay:START -->
563
565
  ```bash
564
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant WEBPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --webpay-experience-result "$WEBPAY_EXPERIENCE_RESULT" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER"
566
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant WEBPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --webpay-experience-result "$WEBPAY_EXPERIENCE_RESULT" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"
565
567
  ```
566
568
  <!-- ALIPAY_AIPAY_PRODUCT:END -->
567
569
  <!-- ALIPAY_AIPAY_PRODUCT:apppay:START -->
568
570
  ```bash
569
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant APPPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER"
571
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message checklist-result --variant APPPAY --project-path "$PROJECT_PATH" --scope-receipt "$CHECKLIST_SCOPE_RECEIPT" --overall-result "$OVERALL_RESULT" --failed-items "$FAILED_ITEMS" --manual-items "$MANUAL_ITEMS" --sandbox-config-state "$SANDBOX_CONFIG_STATE" --blocking-defect-state "$BLOCKING_DEFECT_STATE" --execution-mode "$EXECUTION_MODE" --next-flow-reminder "$NEXT_FLOW_REMINDER" --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"
570
572
  ```
571
573
  <!-- ALIPAY_AIPAY_PRODUCT:END -->
572
574
 
573
- 用户输入计数只统计 `clarify_intent` 之后、当前 active run 内 Agent 收到的每条聊天框用户消息,不按是否与 Skill 相关筛选。Agent 必须在任何解释、分类、路由、runner 或回复前执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry count-user-input --input-id "$USER_INPUT_ID"`;登记 runner 的输入参数只作同一消息的幂等兜底。只有本地计数状态不可用且已重新核对时,才在 checklist 命令末尾追加 `--user-input-after-clarify-intent <count>`;runner 会拒绝明显不合理计数。
575
+ 用户输入计数严格继承 `runtime-entry.md`:active run 内每条聊天框用户消息先执行唯一 `count-user-input --run-id "$RUN_ID" --input-id "$USER_INPUT_ID"`,不按 Skill 相关性筛选;runner、renderer 和 checklist 不做隐式计数。checklist 生成 `integration.complete_coding` 和 `integration_summary` 前使用同一个 `HISTORY_COUNT` 快照,正式值始终由 runtime counter 写入,禁止传入或覆盖 `user_input_after_clarify_intent`。
574
576
 
575
577
  同一次代码开发流程只渲染一次最终 checklist 结果;renderer stdout 是本次默认收口的唯一对客正文,禁止在前后追加风险说明、通过项摘要、执行说明、衔接提醒或第二份待办。
576
578
 
@@ -40,7 +40,7 @@ alipay-cli mcp call alipay-anonymous-sandbox.createAnonymousSandbox \
40
40
  | 变量 | 来源 | 取值规则 |
41
41
  |------|------|----------|
42
42
  | `PLATFORM` | AI 编程工具识别结果 | 参考通用脚本 `../../../normal/scripts/detect_dev_tool.sh` 识别当前工具后使用其输出值;缺失时使用 `unknown`。例如 Codex 环境检测结果为 `codex` |
43
- | `PLATFORM_ID` | 当前流程 `run_id` | 由 `sandbox_config.sh` 通过 `common.sh` 从当前流程 run context 读取,遥测开启或关闭都不影响该值;若宿主提供 `COZE_PROJECT_ID`、`MEOO_PROJECT_ID`,或 `MIAODA` 环境下的 `VITE_APP_ID`/`PLATFORM_ID`,新建 run 时优先以该项目 ID 为 `run_id`;缺失时不阻断沙箱创建 |
43
+ | `PLATFORM_ID` | 第三方项目 ID;缺失时为当前逻辑 `run_id` | 由 `sandbox_config.sh` 通过 `common.sh` 读取,遥测开启或关闭都不影响该值;第三方项目 ID 只用于项目维度,不能生成逻辑 `run_id`,缺失时才保持 `PLATFORM_ID <- run_id` fallback,且不阻断沙箱创建 |
44
44
  | `ALIPAYCLI_BIZ_INFO` | 当前生效 Skill 的 `VERSION` 与匿名机器哈希 | 由 `common.sh` 动态生成 JSON:`{"skill":"alipay-aipay","skill_version":"v<当前 VERSION>","skill_user_id":"machine_<32位匿名机器哈希>"}`;`skill` 固定,版本统一带 `v` 前缀,`skill_user_id` 复用 telemetry 的 `machineUserID`,极端环境无法取得合法 `machine_` 标识时省略该字段;禁止由 Agent 手写或沿用外部同名值 |
45
45
  | `PRODUCT` | 不再传入 | 该 MCP 方法当前不需要产品上下文;不得把产品名写入 `--data` 或 CLI 环境变量 |
46
46
 
@@ -67,6 +67,7 @@ render_pending() {
67
67
  echo "SANDBOX_ERROR:沙箱待配置消息渲染失败" >&2
68
68
  return 1
69
69
  }
70
+ emit_control "CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.configuration.pending" || return 1
70
71
  emit_control_field "SANDBOX_PENDING_PATH" "$CONFIG_PATH" || return 1
71
72
  emit_control "$PENDING_MARKER"
72
73
  }
@@ -120,7 +121,7 @@ if [ "$MODE" = "ensure" ] || [ "$MODE" = "reverify" ]; then
120
121
  emit_control_field "SANDBOX_ENSURE_ACTION" "$ENSURE_ACTION" || exit 1
121
122
  emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
122
123
  emit_control "FLOW:SANDBOX_CONFIG_READY"
123
- emit_stage_metric_async "integration.create_sandbox"
124
+ emit_stage_metric "integration.create_sandbox"
124
125
  exit 0
125
126
  fi
126
127
 
@@ -319,6 +320,7 @@ fi
319
320
 
320
321
  if [ "$MODE" = "summary" ]; then
321
322
  render_summary "$data" || exit 1
323
+ emit_control "CUSTOMER_MESSAGE_DELIVERY_REQUIRED=sandbox.environment.summary" || exit 1
322
324
  emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
323
325
  emit_control "FLOW:SANDBOX_CONFIGURED"
324
326
  exit 0
@@ -326,4 +328,4 @@ fi
326
328
 
327
329
  emit_control_field "SANDBOX_CONFIG_PATH" "$CONFIG_PATH" || exit 1
328
330
  emit_control "FLOW:SANDBOX_CONFIG_READY"
329
- emit_stage_metric_async "integration.create_sandbox"
331
+ emit_stage_metric "integration.create_sandbox"
@@ -6,6 +6,8 @@
6
6
 
7
7
  其他 Skill 相对命令以 `references/normal/` 为 workdir。`PROJECT_INPUT` 保留原话;Agent 确定两类项目的真实 `PROJECT_PATH`,以 `--project-path` 交 runner 校验。复用须选定项目根,位置未知先定位候选;“当前目录”仅在 runner 识别为项目根时接受。后续只用规范化绝对路径。
8
8
 
9
+ `full_process` 的 `RUN_ID` 只取 `runtime-entry.md` 中 `start-run` 的唯一 marker。active run 期间每条聊天框用户消息都先执行统一 `count-user-input --run-id "$RUN_ID"`,与 Skill 无关的插话和中断后输入也不例外。每个登记 stage 动作前回顾当前可见用户历史得到 `HISTORY_COUNT`,无法可靠回顾时为 `null`;能生成 stage 的 runtime 命令按对应 flow 追加 `--telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT"`。Integration Worker 只接收这两个低敏 telemetry 上下文字段并透传给原 flow;正式计数仍由 runtime state 读取。`integration_summary` 不关闭 full-process run,只有 `all_summary` 关闭;telemetry 不改变本文件的业务衔接和卡点。
10
+
9
11
  ## 边界
10
12
 
11
13
  - 只编排 Integration 与 Onboarding,不复制其状态、完成条件和红线。完整接入复用 Integration 步骤 2 的唯一非阻塞 `integration.start.confirm`、同一检查器事实和模板,本轮只渲染一次。
@@ -76,7 +78,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message sta
76
78
 
77
79
  上面命令失败时不得展示手写确认或进入子流程。成功时必须取得唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失或重复视为失败。参数必须是当前确定值,禁止直接拼用户输入。runner 校验产品 variant 并固定服务声明;实际范围仍取当前 Integration flow 和 checklist。
78
80
 
79
- 交接事实必须来自 runner 内同一次 `scan`,不得用描述、自报或历史分类代替;`evidence` 不进 renderer,Onboarding 前不传/猜 `mccCode`。方案 stdout 按 marker 送达后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE"`;支持 Worker 的宿主由唯一 Worker 完成步骤 3 至步骤 8,不支持 Worker 的宿主仍由当前 Agent 串行完成步骤 3 至步骤 8。loader 仍记录兼容 stage 和预开发阅读 stage;禁止手工 telemetry、解码内部值、重复扫描或重显方案。
81
+ 交接事实必须来自 runner 内同一次 `scan`,不得用描述、自报或历史分类代替;`evidence` 不进 renderer,Onboarding 前不传/猜 `mccCode`。方案 stdout 按 marker 送达后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE"`;支持 Worker 的宿主由唯一 Worker 完成步骤 3 至步骤 8,不支持 Worker 的宿主仍由当前 Agent 串行完成步骤 3 至步骤 8。loader 只加载当前分支规则;业务完成后由登记入口记录完成态 stage。禁止手工 telemetry、解码内部值、重复扫描或重显方案。
80
82
 
81
83
  合法组合必须确定产品、路径/来源、代码状态、语言/框架、服务声明和顺序;发现其他产品时保留。零散信息、`新建` 选择、未选候选或新项目未准备均不能替代完整机器校验。方案送达后仍完整执行 Integration 和 checklist。
82
84
 
@@ -29,11 +29,13 @@ Agent 发给 Integration Worker 的任务正文只允许由下列一句固定说
29
29
  "project_path": "<规范化绝对路径>",
30
30
  "server_language": "<Java|Python|Node.js|C#|PHP>",
31
31
  "framework": "<已确定框架>",
32
- "sandbox_config_state": "<READY|CREATE_PENDING|VERIFY_PENDING>"
32
+ "sandbox_config_state": "<READY|CREATE_PENDING|VERIFY_PENDING>",
33
+ "telemetry_run_id": "<RUN_ID marker 中的当前 run_id>",
34
+ "telemetry_history_count": "<非负整数|null>"
33
35
  }
34
36
  ```
35
37
 
36
- Agent 不得复制、摘录或改写本文件的执行协议,不得在请求中手写任何 `runtime.mjs`、sandbox、verification、acceptance、audit 或 checklist 命令。禁止把完整对话、`integration.start.confirm` stdout、runner evidence、Agent 分析、源码或补丁、完整命令日志、沙箱文件内容、私钥、密码、临时 URL 或此前工具输出复制到 Worker 请求。`skill_dir` 必须是启动器确定的当前 Skill 规范化绝对路径;`sandbox_config_state` 必须是步骤 1 实际取得并在步骤 2 保持有效的终态枚举,不得包含配置内容。
38
+ Agent 不得复制、摘录或改写本文件的执行协议,不得在请求中手写任何 `runtime.mjs`、sandbox、verification、acceptance、audit 或 checklist 命令。禁止把完整对话、`integration.start.confirm` stdout、runner evidence、Agent 分析、源码或补丁、完整命令日志、沙箱文件内容、私钥、密码、临时 URL 或此前工具输出复制到 Worker 请求。`skill_dir` 必须是启动器确定的当前 Skill 规范化绝对路径;`sandbox_config_state` 必须是步骤 1 实际取得并在步骤 2 保持有效的终态枚举,不得包含配置内容。`telemetry_run_id` 只取主 Agent 已解析的当前 `RUN_ID` marker;`telemetry_history_count` 是 Worker 创建前主 Agent 对当前可见历史的诊断快照,无法可靠回顾时为 JSON `null`。两者只供原 flow 登记 stage 使用,不改变 Worker 的业务范围。
37
39
 
38
40
  调用提交成功后,Integration 执行权立即且不可逆地转移给该 Worker。Agent 不得因等待、返回格式或 Worker 失败重新取回本轮 Integration 执行权。
39
41
 
@@ -42,14 +44,16 @@ Agent 不得复制、摘录或改写本文件的执行协议,不得在请求
42
44
  Integration Worker 使用输入事实执行下列原 flow 入口:
43
45
 
44
46
  ```bash
45
- node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE"
47
+ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE" --telemetry-run-id "$TELEMETRY_RUN_ID" --telemetry-history-count "$TELEMETRY_HISTORY_COUNT"
46
48
  ```
47
49
 
48
- 随后严格按照该入口加载的原 `integration/flow.md`,从步骤 3 对步骤 1 的实际沙箱终态进行复核或保持待配置状态,再完整执行步骤 4 至步骤 8。阶段读取、命令、沙箱状态、代码实现、verification、acceptance、checklist 和失败转移都只以原 flow 为准;本文件不另行定义或覆盖业务流程。
50
+ 随后严格按照该入口加载的原 `integration/flow.md`,从步骤 3 对步骤 1 的实际沙箱终态进行复核或保持待配置状态,再完整执行步骤 4 至步骤 8。阶段读取、命令、沙箱状态、代码实现、verification、acceptance、checklist 和失败转移都只以原 flow 为准;本文件不另行定义或覆盖业务流程。Worker 期间主 Agent 不处理新业务消息,因此各 stage 沿用该诊断 history 快照;正式 `user_input_after_clarify_intent` 仍由每个 event 生成时读取 runtime counter,不从 Worker 输入计算。原 flow 中能生成 stage 的 runtime 命令必须继续携带同一对 `--telemetry-run-id/--telemetry-history-count` 参数。
49
51
 
50
52
  Integration Worker 不执行 Onboarding、self-update、`telemetry start-run`、产品/项目重新决策或原 flow 之外的沙箱调用和诊断。不得用 Worker 自报代替原 flow 要求的实际脚本终态和校验证据。
51
53
 
52
- 原 flow 要求对客送达的登记 runner/script stdout 都要进入交接对象。Worker 以 flow、消息目录和 runner 契约为准收集这些对客 stdout:既包括带有 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED` marker 的交付屏障,也包括未带 marker 但被定义为唯一对客正文的消息;按发生顺序剔除 `ALIPAY_AIPAY_INTERNAL:` 行后保存到 `customer_messages`。过程 stdout、分析、命令和日志不得进入交接对象。登记正文不改写、不总结;空正文不加入。沙箱账号只允许存在于原始登记正文中,不得拆出、复述或进入其他字段。返回结果只依据最终 checklist 的实际证据;只有原 flow 允许衔接时 `next_phase=ONBOARDING`,其他情况为 `STOP`。
54
+ 遇到阻塞时,先判断是否能在当前授权和工具范围内自行解决;能解决就继续处理并验证,不能解决才返回 STOP。不得将单次失败或尚未定位原因视为无法继续。恢复仍遵守原 flow 的权限、失败分支和重试边界;有新证据或可验证的修复方向时继续,无新进展时停止重复尝试并如实说明,不伪造通过。STOP 的 `remaining_actions` 须简短列明实际错误、已尝试的恢复及所需外部条件;尚未确认的原因明确标为未知,不返回源码、完整日志或敏感值。
55
+
56
+ 原 flow 要求对客送达的登记 runner/script stdout 都要进入交接对象。`integration.start.confirm` 已由主 Agent 在 Worker 转移前按唯一 marker 独立交付;Worker 从步骤 3 开始,以 flow、消息目录和 runner 契约为准收集后续对客 stdout,其中 `sandbox.configuration.pending`、`sandbox.environment.summary`、`integration.safety.closeout` 和 `integration.checklist.result` 必须各自带唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=<messageId>` marker,缺失、重复或对应正文为空时按交接失败处理;按发生顺序剔除 `ALIPAY_AIPAY_INTERNAL:` 行后保存到 `customer_messages`。过程 stdout、分析、命令和日志不得进入交接对象。登记正文不改写、不总结;空正文不加入。沙箱账号只允许存在于原始登记正文中,不得拆出、复述或进入其他字段。返回结果只依据最终 checklist 的实际证据;只有原 flow 允许衔接时 `next_phase=ONBOARDING`,其他情况为 `STOP`。
53
57
 
54
58
  ## 返回协议
55
59
 
@@ -74,6 +78,8 @@ Integration Worker 不执行 Onboarding、self-update、`telemetry start-run`、
74
78
  - 沙箱 `READY` 且只剩原 flow 允许的非阻塞人工项:`部分完成,人工待验证`、`ONBOARDING`;
75
79
  - 其他代码、安全、必要依据或协议缺口:`未通过`、`STOP`。
76
80
 
77
- 上述七个字段都由 Integration Worker 根据原 flow 的实际结果生成。`protocol` 必须精确为 `INTEGRATION_WORKER_V1`,返回对象只允许包含这七个字段。`sandbox_config_state` 必须复用输入后按步骤 3 实际复核得到的终态,不接受 `null` 或字符串 `"null"`。`manual_verification_items` 和 `remaining_actions` 只保留最终 checklist 已证实的短项;没有时传空数组。禁止返回项目路径、语言、框架、changed files、依赖列表、源码、收据、绝对路径、配置字段或 Worker 分析。Agent 只做一次结构校验,不解释、修复、补充、改写或追问 Worker 返回。校验通过后,按数组顺序把 `customer_messages` 每一项原文作为可见消息送达,不加旁白;然后丢弃该数组。`next_phase=ONBOARDING` 时只把产品、`integration_result`、`sandbox_config_state`、`manual_verification_items` 和 `remaining_actions` 带入独立 Onboarding;不读取项目、不复查 Worker、不重跑 Integration。`protocol`、`customer_messages` 和 `next_phase` 不带入 Onboarding。`next_phase=STOP` 时在送达登记正文后停止,不进入 Onboarding。
81
+ 上述七个字段都由 Integration Worker 根据原 flow 的实际结果生成。`protocol` 必须精确为 `INTEGRATION_WORKER_V1`,返回对象只允许包含这七个字段;telemetry 输入不得回传。`sandbox_config_state` 必须复用输入后按步骤 3 实际复核得到的终态,不接受 `null` 或字符串 `"null"`。`manual_verification_items` 和 `remaining_actions` 只保留最终 checklist 已证实的短项;STOP 时 `remaining_actions` 另保留上文要求的脱敏阻塞事实,没有时传空数组。禁止返回项目路径、语言、框架、changed files、依赖列表、源码、收据、绝对路径、配置字段或 Worker 分析。Agent 对每次返回做结构校验,不自行解释、修复、补充或改写结果;仅允许下文规定的同 Worker 核实。结构合法的 STOP 若缺少阻塞依据,或仍存在授权范围内未尝试的恢复方向,在对客送达前最多要求同一 Worker 核实并继续一次;只指出返回中的证据缺口,不读取项目、不创建新 Worker、不接手 Integration。Worker 从当前实际状态继续,不重做已成功动作,仍按原 flow 修复、重检并返回同一七字段对象。宿主不支持继续同一 Worker,或再次返回 STOP 时,不循环追问,如实保留未解决项。最终结果校验通过后,按数组顺序把 `customer_messages` 每一项原文作为可见消息送达,不加旁白;然后丢弃该数组。`next_phase=ONBOARDING` 时只把产品、`integration_result`、`sandbox_config_state`、`manual_verification_items` 和 `remaining_actions` 带入独立 Onboarding;不读取项目、不复查 Worker、不重跑 Integration。`protocol`、`customer_messages` 和 `next_phase` 不带入 Onboarding。最终 `next_phase=STOP` 时在送达登记正文后停止,不进入 Onboarding。
82
+
83
+ `next_phase=ONBOARDING` 时,送达登记正文后立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow onboarding entry` 并继续流程,不得仅宣布下一步就结束当前轮。
78
84
 
79
85
  Worker 明确失败、超时、返回非单一 JSON、字段非法或门禁矛盾时,本轮 Integration 立即停止。Agent 只报告“Integration Worker 交接失败,本轮已停止以避免重复执行”,不创建第二个 Agent,不追问 Worker,不读取项目,不执行任何 `flow integration`、`sandbox`、`a2m`、verification、acceptance、audit 或 checklist 命令,不进入 Onboarding。即使 Worker 文本中包含可猜测的沙箱状态,也不得由 Agent 补跑或重新展示 `integration.start.confirm`。
@@ -341,26 +341,24 @@ init_alipay_cli_product_from_sales_code() {
341
341
  init_alipay_cli_product "$product_type"
342
342
  }
343
343
 
344
- emit_stage_metric_async() {
344
+ emit_stage_metric() {
345
345
  local stage="${1:-}"
346
- local product_name="${2:-}"
347
- local common_dir telemetry_script
346
+ local run_id="${ALIPAY_AIPAY_TELEMETRY_RUN_ID:-}"
347
+ local history_count="${ALIPAY_AIPAY_TELEMETRY_HISTORY_COUNT:-null}"
348
+ local common_dir telemetry_script telemetry_switch
348
349
  [ -n "$stage" ] || return 0
350
+ [ -n "$run_id" ] || return 0
351
+ telemetry_switch="$(printf '%s' "${ALIPAY_AIPAY_TELEMETRY:-}" | tr '[:upper:]' '[:lower:]')"
352
+ case "$telemetry_switch" in
353
+ 0|false|off|no) return 0 ;;
354
+ esac
349
355
  common_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
350
356
  telemetry_script="${common_dir}/telemetry.mjs"
351
357
  [ -f "$telemetry_script" ] && command -v node >/dev/null 2>&1 || return 0
352
- if [ -n "$product_name" ]; then
353
- if [ "${ALIPAY_AIPAY_TEST_MODE:-0}" = "1" ]; then
354
- node "$telemetry_script" stage-async "$stage" --product-name "$product_name"
355
- else
356
- node "$telemetry_script" stage-async "$stage" --product-name "$product_name" >/dev/null 2>&1
357
- fi
358
+ if [ "${ALIPAY_AIPAY_TEST_MODE:-0}" = "1" ]; then
359
+ node "$telemetry_script" stage "$stage" --run-id "$run_id" --history-count "$history_count"
358
360
  else
359
- if [ "${ALIPAY_AIPAY_TEST_MODE:-0}" = "1" ]; then
360
- node "$telemetry_script" stage-async "$stage"
361
- else
362
- node "$telemetry_script" stage-async "$stage" >/dev/null 2>&1
363
- fi
361
+ node "$telemetry_script" stage "$stage" --run-id "$run_id" --history-count "$history_count" >/dev/null 2>&1
364
362
  fi
365
363
  return 0
366
364
  }
@@ -10,7 +10,7 @@ import { fileURLToPath } from 'node:url';
10
10
 
11
11
  import { isWindowsPlatform } from './platform_compat.mjs';
12
12
  import { renderMessage } from './render_customer_message.mjs';
13
- import { emitStageMetricAsync, recordTelemetryUserInput, startTelemetryRun } from './telemetry.mjs';
13
+ import { currentRunContext, emitStageMetric, startTelemetryRun, telemetryEnabled } from './telemetry.mjs';
14
14
 
15
15
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
16
16
  const inspectorPath = path.join(scriptDir, 'project_route_inspector.sh');
@@ -125,9 +125,9 @@ function optional(args, name) {
125
125
  return typeof args[name] === 'string' && args[name].length > 0 ? args[name] : undefined;
126
126
  }
127
127
 
128
- function countUserInput(args) {
129
- const inputId = optional(args, 'input-id');
130
- if (inputId) recordTelemetryUserInput(inputId);
128
+ function requireCustomerMessageDelivery(messageId, message) {
129
+ process.stderr.write(`${internalPrefix}CUSTOMER_MESSAGE_DELIVERY_REQUIRED=${messageId}\n`);
130
+ return message;
131
131
  }
132
132
 
133
133
  function stripWrappingQuotes(value) {
@@ -1256,9 +1256,9 @@ function runServiceNotReady(args) {
1256
1256
  function runSafetyCloseout(args) {
1257
1257
  const variant = required(args, 'variant');
1258
1258
  if (!['AIPAY', 'WEBPAY', 'APPPAY'].includes(variant)) throw new Error('variant 非法,仅支持 AIPAY、WEBPAY、APPPAY');
1259
- return renderMessage('integration.safety.closeout', variant, {
1259
+ return requireCustomerMessageDelivery('integration.safety.closeout', renderMessage('integration.safety.closeout', variant, {
1260
1260
  acceptanceSummary: required(args, 'acceptance-summary')
1261
- });
1261
+ }));
1262
1262
  }
1263
1263
 
1264
1264
  function runWindowsSandboxSummary(args) {
@@ -1268,7 +1268,8 @@ function runWindowsSandboxSummary(args) {
1268
1268
  environmentRows: required(args, 'environment-rows')
1269
1269
  });
1270
1270
  const reminder = renderMessage('sandbox.environment.reminder', 'WINDOWS', {});
1271
- return `${summary}\n\n${reminder}`;
1271
+ emitStageMetric('integration.create_sandbox');
1272
+ return requireCustomerMessageDelivery('sandbox.environment.summary', `${summary}\n\n${reminder}`);
1272
1273
  }
1273
1274
 
1274
1275
  async function readStdin() {
@@ -1313,6 +1314,13 @@ function checklistInputFromArgs(args) {
1313
1314
  async function runChecklistResult(args) {
1314
1315
  const variant = required(args, 'variant');
1315
1316
  if (!['AIPAY', 'WEBPAY', 'APPPAY'].includes(variant)) throw new Error('variant 非法,仅支持 AIPAY、WEBPAY、APPPAY');
1317
+ if (telemetryEnabled()) {
1318
+ const run = currentRunContext();
1319
+ if (!run?.run_id || run.terminal || run.product_type !== variant.toUpperCase()
1320
+ || !['integration_only', 'full_process'].includes(run.root_intent)) {
1321
+ throw new Error('checklist 必须在当前产品匹配的 active integration run 内执行');
1322
+ }
1323
+ }
1316
1324
  if (Object.prototype.hasOwnProperty.call(args, 'implementation-audit-receipt')) {
1317
1325
  throw new Error('implementation-audit-receipt 已废弃');
1318
1326
  }
@@ -1352,14 +1360,13 @@ async function runChecklistResult(args) {
1352
1360
  input.nextFlowReminder = '代码开发校验通过后将自动进入支付产品-产品开通;未通过时停留在代码开发。';
1353
1361
  }
1354
1362
  }
1355
- emitStageMetricAsync('integration.complete_coding', { productType: variant.toLowerCase() });
1363
+ emitStageMetric('integration.complete_coding');
1356
1364
  const rendered = renderMessage('integration.checklist.result', variant, input);
1357
- return rendered;
1365
+ return requireCustomerMessageDelivery('integration.checklist.result', rendered);
1358
1366
  }
1359
1367
 
1360
1368
  export async function runIntegrationMessageCli(argv = process.argv) {
1361
1369
  const { command, args } = parseArgs(argv);
1362
- countUserInput(args);
1363
1370
  if (command === 'resolve-project') {
1364
1371
  console.log(runResolveProject(args));
1365
1372
  return;
@@ -4,7 +4,6 @@ import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import process from 'node:process';
6
6
  import { fileURLToPath } from 'node:url';
7
- import { recordTelemetryUserInput } from './telemetry.mjs';
8
7
 
9
8
  const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
10
9
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
@@ -125,7 +124,7 @@ export function runInteractionReplyCli(argv = process.argv) {
125
124
  if (command !== 'confirm' || typeof args.reply !== 'string' || !args.reply) {
126
125
  throw new Error('用法: interaction_reply.mjs confirm --reply <用户原始回复> --input-id <本地用户输入幂等键>');
127
126
  }
128
- recordTelemetryUserInput(required(args, 'input-id'));
127
+ required(args, 'input-id');
129
128
  const decision = isAffirmativeReply(args.reply) ? 'CONFIRMED' : 'REJECTED';
130
129
  process.stderr.write(`${internalPrefix}REPLY_DECISION=${decision}\n`);
131
130
  if (decision === 'REJECTED') process.exitCode = 2;
@@ -6,7 +6,7 @@ import process from 'node:process';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
8
  import { renderDiscoverySummary } from './onboarding_message_runner.mjs';
9
- import { emitStageMetricAsync } from './telemetry.mjs';
9
+ import { currentRunContext, emitStageMetric, telemetryEnabled } from './telemetry.mjs';
10
10
 
11
11
  const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
12
12
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
@@ -290,6 +290,13 @@ function emitEnvelope(envelope) {
290
290
  async function runDiscovery(args) {
291
291
  const productType = required(args, 'product-type');
292
292
  if (!productSalesCodes[productType]) throw new Error('product-type 非法,仅支持 aipay、webpay、apppay');
293
+ if (telemetryEnabled()) {
294
+ const run = currentRunContext();
295
+ if (!run?.run_id || run.terminal || run.product_type !== productType.toUpperCase()
296
+ || !['onboarding_only', 'full_process'].includes(run.root_intent)) {
297
+ throw new Error('discovery 必须在当前产品匹配的 active onboarding run 内执行');
298
+ }
299
+ }
293
300
  const salesCode = required(args, 'sales-code');
294
301
  if (salesCode !== productSalesCodes[productType]) throw new Error('sales-code 与 product-type 不匹配');
295
302
  const reusedSigning = reusedSigningBranch(args, productType);
@@ -325,7 +332,7 @@ async function runDiscovery(args) {
325
332
  };
326
333
  if (envelope.signing.query_status === 'SUCCESS'
327
334
  && (envelope.signing.sign_status === 'SIGNED_EFFECTIVE' || envelope.signing.sign_status === 'SIGN_SUBMITTED')) {
328
- emitStageMetricAsync('onboarding.confirm_signing', { productType });
335
+ emitStageMetric('onboarding.confirm_signing');
329
336
  }
330
337
  if (globalBlocker) {
331
338
  envelope.global_blocker = globalBlocker;
@@ -13,8 +13,8 @@ import {
13
13
  } from './render_customer_message.mjs';
14
14
  import {
15
15
  currentRunContext,
16
- startTelemetryRun,
17
- recordTelemetryUserInput,
16
+ emitStageMetric,
17
+ startTelemetryRun
18
18
  } from './telemetry.mjs';
19
19
 
20
20
  const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
@@ -135,11 +135,6 @@ function optional(args, name) {
135
135
  return typeof args[name] === 'string' && args[name].length > 0 ? args[name] : undefined;
136
136
  }
137
137
 
138
- function countUserInput(args) {
139
- const inputId = optional(args, 'input-id');
140
- if (inputId) recordTelemetryUserInput(inputId);
141
- }
142
-
143
138
  function productFor(args) {
144
139
  const productType = required(args, 'product-type');
145
140
  const mapping = productTypes[productType];
@@ -170,8 +165,8 @@ function runPlatformEntry(args = {}) {
170
165
  if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
171
166
  throw new Error('Windows 产品开通引导缺少有效的当前 Onboarding run context');
172
167
  }
173
- const platformId = runContext?.run_id
174
- || platformIdFromEnv(process.env)
168
+ const platformId = platformIdFromEnv(process.env)
169
+ || runContext?.run_id
175
170
  || '';
176
171
  if (!platformId) {
177
172
  throw new Error('Windows 产品开通引导缺少有效的当前 Onboarding run context');
@@ -218,6 +213,11 @@ function runEnterpriseUnsupported(args) {
218
213
  async function runMccClarify(args) {
219
214
  const productType = required(args, 'product-type');
220
215
  const product = productFor({ ...args, 'product-type': productType });
216
+ const rootIntent = required(args, 'root-intent');
217
+ if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
218
+ throw new Error('root-intent 仅支持 onboarding_only、full_process');
219
+ }
220
+ await startTelemetryRun(rootIntent, productType);
221
221
  return renderMessage('onboarding.mcc.clarify', 'DEFAULT', {
222
222
  productName: product.productName
223
223
  }, { productType });
@@ -733,10 +733,11 @@ async function runPlanConfirm(args) {
733
733
  async function runMccResolvePlan(args) {
734
734
  const productType = required(args, 'product-type');
735
735
  productFor({ ...args, 'product-type': productType });
736
- const rootIntent = currentRunContext(process.env)?.root_intent || process.env.ALIPAY_AIPAY_ROOT_INTENT || process.env.ROOT_INTENT || '';
737
- if (['onboarding_only', 'full_process'].includes(rootIntent)) {
738
- await startTelemetryRun(rootIntent, productType);
736
+ const rootIntent = required(args, 'root-intent');
737
+ if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
738
+ throw new Error('root-intent 仅支持 onboarding_only、full_process');
739
739
  }
740
+ await startTelemetryRun(rootIntent, productType);
740
741
  const mccRunContext = captureMccRunContext();
741
742
  const query = required(args, 'query');
742
743
  const selected = optional(args, 'select');
@@ -789,6 +790,11 @@ async function runMccResolvePlan(args) {
789
790
  async function runMccMatchCodes(args) {
790
791
  const productType = required(args, 'product-type');
791
792
  productFor({ ...args, 'product-type': productType });
793
+ const rootIntent = required(args, 'root-intent');
794
+ if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
795
+ throw new Error('root-intent 仅支持 onboarding_only、full_process');
796
+ }
797
+ await startTelemetryRun(rootIntent, productType);
792
798
  const query = required(args, 'query');
793
799
  const semanticTerms = parseMccSemanticTerms(args);
794
800
  if (args['agent-mcc-status'] !== undefined || args['agent-mcc-codes'] !== undefined) {
@@ -1145,6 +1151,10 @@ function closeoutInputFromArgs(args) {
1145
1151
 
1146
1152
  async function runCloseout(args) {
1147
1153
  const variables = closeoutInputFromArgs(args);
1154
+ if (args['product-type'] === 'aipay'
1155
+ && ['已复用', '创建成功,状态未取得', '修改成功,状态未取得', '已完成'].includes(args['service-result'])) {
1156
+ emitStageMetric('onboarding.confirm_service');
1157
+ }
1148
1158
  const rendered = renderMessage('process.partial_result', 'DEFAULT', variables);
1149
1159
  return rendered;
1150
1160
  }
@@ -1206,10 +1216,10 @@ function runApplicationResult(args) {
1206
1216
  if (actualStatus === '需人工配置') {
1207
1217
  if (optional(args, 'next-action') !== undefined) throw new Error('需人工配置的下一步由消息目录固定,不接收 --next-action');
1208
1218
  if (optional(args, 'app-key-save-path') !== undefined) throw new Error('需人工配置表示支付宝公钥未本地保存,禁止传入 --app-key-save-path');
1209
- return renderMessage('application.operation.result', 'ALIPAY_PUBLIC_KEY_MANUAL_CONFIGURATION', {
1219
+ return requireCustomerMessageDelivery('application.operation.result', renderMessage('application.operation.result', 'ALIPAY_PUBLIC_KEY_MANUAL_CONFIGURATION', {
1210
1220
  appId: required(args, 'app-id'),
1211
1221
  actualStatus
1212
- });
1222
+ }));
1213
1223
  }
1214
1224
  const variables = {
1215
1225
  appId: required(args, 'app-id'),
@@ -1218,12 +1228,11 @@ function runApplicationResult(args) {
1218
1228
  };
1219
1229
  const appKeySavePath = optional(args, 'app-key-save-path');
1220
1230
  if (appKeySavePath !== undefined) variables.appKeySavePath = appKeySavePath;
1221
- return renderMessage('application.operation.result', 'DEFAULT', variables);
1231
+ return requireCustomerMessageDelivery('application.operation.result', renderMessage('application.operation.result', 'DEFAULT', variables));
1222
1232
  }
1223
1233
 
1224
1234
  export async function runOnboardingMessageCli(argv = process.argv) {
1225
1235
  const { command, args } = parseArgs(argv);
1226
- countUserInput(args);
1227
1236
  if (command === 'platform-entry') {
1228
1237
  const message = runPlatformEntry(args);
1229
1238
  if (message) console.log(message);
@@ -5,7 +5,6 @@ import path from 'node:path';
5
5
  import process from 'node:process';
6
6
  import { fileURLToPath } from 'node:url';
7
7
  import { isAffirmativeReply } from './interaction_reply.mjs';
8
- import { recordTelemetryUserInput } from './telemetry.mjs';
9
8
 
10
9
  const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
11
10
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
@@ -34,7 +33,7 @@ function required(args, name) {
34
33
  }
35
34
 
36
35
  function assertRegisteredReply(args, kind) {
37
- recordTelemetryUserInput(required(args, 'input-id'));
36
+ required(args, 'input-id');
38
37
  if (!isAffirmativeReply(required(args, 'reply'))) {
39
38
  process.stderr.write(`${internalPrefix}RECOVERY_INPUT_REJECTED=${kind}\n`);
40
39
  process.exitCode = 2;
@@ -916,15 +916,15 @@ const managedEntrypoints = {
916
916
  reason: 'runner 轻量定位候选。'
917
917
  },
918
918
  'onboarding.mcc.clarify': {
919
- command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-clarify --product-type <aipay|webpay|apppay>',
919
+ command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-clarify --product-type <aipay|webpay|apppay> --root-intent <onboarding_only|full_process>',
920
920
  reason: 'runner 绑定产品。'
921
921
  },
922
922
  'onboarding.mcc.no_match': {
923
- command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <business-description> --product-type <aipay|webpay|apppay>',
923
+ command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <business-description> --product-type <aipay|webpay|apppay> --root-intent <onboarding_only|full_process>',
924
924
  reason: 'mcc.sh 查询当前产品支持的 MCC 树和详情后托管输出无匹配恢复。'
925
925
  },
926
926
  'onboarding.mcc.candidates': {
927
- command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <business-description> --product-type <aipay|webpay|apppay>',
927
+ command: 'node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query <business-description> --product-type <aipay|webpay|apppay> --root-intent <onboarding_only|full_process>',
928
928
  reason: 'mcc.sh 绑定当前产品支持类目、详情、候选快照和特殊资质。'
929
929
  },
930
930
  'onboarding.discovery.summary': {