@alipay/alipay-aipay 1.6.0-beta.2 → 1.6.0

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.6.0-beta.2",
3
+ "version": "1.6.0",
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.0-beta.2
1
+ 1.6.0
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## 按步读取
9
9
 
10
- 禁止整份预读,只通过当前 Skill 绝对路径下的统一 runtime 按 marker 加载阶段,本 flow 仍是唯一执行依据:`entry`;项目与技术栈唯一后 `prepare`;非阻塞方案送达后用 `development --product-type "$PRODUCT_TYPE" --project-confirm-receipt "$PROJECT_CONFIRM_RECEIPT"` 校验同一项目事实;其后依次加载 `implementation`、`verification`、`acceptance --product-type "$PRODUCT_TYPE"` 和 `checklist --product-type "$PRODUCT_TYPE" --project-path "$PROJECT_PATH"`。统一单命令规则继承 `runtime-entry.md`;用户项目命令仍以已确认项目根为 workdir。未到阶段、无关产品/语言、维护说明和模块不得提前读取,原 flow 保留完整规则供校验。
10
+ 禁止整份预读,只通过当前 Skill 绝对路径下的统一 runtime 按 marker 加载阶段,本 flow 仍是唯一执行依据:`entry`;项目与技术栈唯一后 `prepare`;非阻塞方案送达后直接加载 `development --product-type "$PRODUCT_TYPE"`;其后依次加载 `implementation`、`verification`、`acceptance --product-type "$PRODUCT_TYPE"` 和 `checklist --product-type "$PRODUCT_TYPE" --project-path "$PROJECT_PATH"`。统一单命令规则继承 `runtime-entry.md`;用户项目命令仍以已确认项目根为 workdir。未到阶段、无关产品/语言、维护说明和模块不得提前读取,原 flow 保留完整规则供校验。
11
11
 
12
12
  步骤 1 只有 `CLI_ENV:NEEDS_SETUP` 才读 `../normal/alipay-cli-env.md`;步骤 2 只有产品无法唯一确定时才读 `modules/product-decision.md`;沙箱正常路径只执行已封装脚本,协议异常或用户要求解释时才读沙箱指南;步骤 4 只按 `integration_context_runner.mjs` 的当前产品/语言事实读取 SDK、本地契约和示例,不读取接口索引本身;步骤 6 仅按量付费读 A2M 沙箱模块;步骤 8 只读当前产品适用 checklist。
13
13
 
@@ -15,7 +15,7 @@
15
15
 
16
16
  ## ⛔ 强制执行要点
17
17
 
18
- 先确认唯一项目和服务端语言,再在产品确定前执行步骤 1;匿名沙箱不传 `PRODUCT`,缺失时创建、存在时复核,待配置只阻止沙箱依赖动作。步骤 2 的完整方案送达且同一次检查器 receipt 有效前不得改代码;`integration_only/full_process` 共用检查器事实和非阻塞 `integration.start.confirm`,一次只开发一个产品。网站支付/APP 支付必须实现下单、查询、退款、退款查询、关闭和异步通知;按量付费只实现 402、验付和履约确认。本流程不主动发起真实生产交易。
18
+ 先确认唯一项目和服务端语言,再在产品确定前执行步骤 1;匿名沙箱不传 `PRODUCT`,缺失时创建、存在时复核,待配置只阻止沙箱依赖动作。步骤 2 的完整方案可见送达前不得改代码;送达后直接按同一产品、项目和技术栈开工,不再执行方案 receipt 或项目快照二次校验。`integration_only/full_process` 共用检查器事实和非阻塞 `integration.start.confirm`,一次只开发一个产品。网站支付/APP 支付必须实现下单、查询、退款、退款查询、关闭和异步通知;按量付费只实现 402、验付和履约确认。本流程不主动发起真实生产交易。
19
19
 
20
20
  生产 `appId`、应用公钥、应用私钥和支付宝公钥必须属于同一生产应用,私钥格式必须匹配当前语言,格式转换只用支付宝官方密钥工具。网站支付/APP 支付本地无公网 `notify_url` 时仍实现通知代码,可暂不传地址并用查询验收;生产上线前必须恢复公网通知及验签、幂等、关键字段、`success` 回写和补偿查询,不得提前宣称生产就绪。
21
21
 
@@ -206,11 +206,11 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message win
206
206
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --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"
207
207
  ```
208
208
 
209
- runner 失败时不得展示手写方案或进入步骤 3。成功时必须同时取得唯一 `ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRM_RECEIPT=<receipt>` 和 `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" --project-confirm-receipt "$PROJECT_CONFIRM_RECEIPT"`,不得总结、询问或等待回复。loader 返回 `PROJECT_CONFIRMATION=VALID` 才能进入步骤 3;返回 `STALE` 时 stdout 已重新渲染当前标准方案并给出新 receipt,必须先原文可见送达,再使用新 receipt 立即重试一次;连续变化说明项目事实不稳定,停在步骤 2 核对,不要求用户输入确认口令。
209
+ 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"`,不得总结、询问、等待回复、解码内部值或再次渲染方案。
210
210
 
211
- - `full_process`:`../normal/full-process-routing.md` 已使用同一个 `integration.start.confirm`,在同一方案中绑定检查器产生的项目来源、代码状态和其他产品,以及产品、项目路径、语言/框架和服务声明;消息送达后已经直接通过 receipt 进入本步骤,禁止再次渲染或要求确认。该消息不展示步骤清单,也不缩减执行范围;后续仍必须按当前产品完成本 flow 的全部适用接口、完成条件和 checklist。任一方案字段变化时必须返回完整接入 router 重新扫描、渲染并自动校验新的单条方案。该方案仍禁止提前展示 MCC、授权范围、产品开通材料或 onboarding 待办。
211
+ - `full_process`:`../normal/full-process-routing.md` 已使用同一个 `integration.start.confirm`,在同一方案中绑定检查器产生的项目来源、代码状态和其他产品,以及产品、项目路径、语言/框架和服务声明;消息送达后已经直接进入本步骤,禁止再次渲染或要求确认。该消息不展示步骤清单,也不缩减执行范围;后续仍必须按当前产品完成本 flow 的全部适用接口、完成条件和 checklist。用户中断后若项目、产品、语言或框架发生变化,返回完整接入 router 重新澄清和扫描,再输出一条当前方案并继续。该方案仍禁止提前展示 MCC、授权范围、产品开通材料或 onboarding 待办。
212
212
 
213
- 方案与 receipt 校验通过后,只通过上述 development loader 进入步骤 3;loader 仍在原位置记录兼容 stage `integration.user_confirmed` 和 `integration.pre_dev_reading.start`。前者表示已基于完整确定事实自动进入执行,不表示收到额外确认回复;不得另行执行 telemetry 命令或伪造用户回复。
213
+ 方案送达后只通过上述 development loader 进入步骤 3;loader 仍在原位置记录兼容 stage `integration.user_confirmed` 和 `integration.pre_dev_reading.start`。前者表示已基于完整确定事实自动进入执行,不表示收到额外确认回复;不得另行执行 telemetry 命令或伪造用户回复。
214
214
 
215
215
  **方案后的上下文锁定**:已有项目保持步骤 1 前已经唯一解析的实际根目录和原有工程结构;新项目必须已经在步骤 1 前按用户明确选择的方式完成初始化并通过构建标识检查。此处不重复准备、初始化或探测项目。路径内容与步骤 1 成功时不一致则停止并重新澄清;只有目标项目或服务端语言变化时返回步骤 1,其他情况直接进入步骤 3。
216
216
 
@@ -227,7 +227,7 @@ runner 失败时不得展示手写方案或进入步骤 3。成功时必须同
227
227
 
228
228
  **任务**:步骤 1 已就绪时复核同一沙箱配置;步骤 1 已待配置时保持该状态并继续代码开发
229
229
 
230
- > 步骤 1 已完成 CLI、操作系统和首次配置校验。本步骤只复核方案生成和 receipt 校验期间配置是否仍然安全可用,不重新创建沙箱,也不重新执行环境探测。
230
+ > 步骤 1 已完成 CLI、操作系统和首次配置校验。本步骤只复核方案展示期间配置是否仍然安全可用,不重新创建沙箱,也不重新执行环境探测。
231
231
 
232
232
  **完成条件**:
233
233
  - [INT.SANDBOX.UNIX_TERMINAL] Unix/macOS/Linux:`READY` 时已用 `reverify` 复核同一配置;步骤 1 或本步骤得到 `CREATE_PENDING|VERIFY_PENDING` 时,未读取或使用无效配置,已保留待配置状态并继续步骤 4
@@ -447,7 +447,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message a2m
447
447
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message a2m-execution-guard --project-path "$PROJECT_PATH" --service-url "$SERVICE_URL" --http-method POST --request-body-file "$POST_BODY_FILE" [--prior-receipt "$A2M_EXECUTION_RECEIPT"]
448
448
  ```
449
449
 
450
- 只接受唯一 `ALIPAY_AIPAY_INTERNAL:A2M_EXECUTION=<json>`。`decision=RUN` 时保存新 receipt 并继续;`REUSE_PASSED` 复用同一项目和输入的本轮通过证据,不重复联调;`BLOCK_UNCHANGED` 表示失败后代码、配置和输入均未变化,禁止重跑,将本轮 A2M 联调记录为失败并继续步骤 7/8;`UNKNOWN_PREVIOUS_EXECUTION` 表示上次命令可能已发出但未登记终态,当前没有登记的结果查询入口,禁止自动重跑或临时探测,固定记录联调结果未知并继续步骤 7/8。项目、服务 URL、方法或 POST body 变化时 runner 才会产生新的 `RUN` receipt。receipt 只保留在当前会话,不写跨会话业务进度。
450
+ 只接受唯一 `ALIPAY_AIPAY_INTERNAL:A2M_EXECUTION=<json>`。`decision=RUN` 时保存新 receipt 并继续;`REUSE_PASSED` 复用同一项目和输入的本轮通过证据,不重复联调;`BLOCK_UNCHANGED` 表示失败后代码、配置和输入均未变化,禁止重跑,将本轮 A2M 联调记录为失败并继续步骤 7/8;`UNKNOWN_PREVIOUS_EXECUTION` 表示上次命令可能已发出但未登记终态,当前没有登记的结果查询入口,禁止自动重跑或临时探测,固定记录联调结果未知并继续步骤 7/8。项目代码或配置的实际内容、服务 URL、方法或 POST body 变化时 runner 才会产生新的 `RUN` receipt;仅文件时间戳变化或同内容重写不属于输入变化。receipt 只保留在当前会话,不写跨会话业务进度。
451
451
 
452
452
  4. 仅 `decision=RUN` 时执行下列固定 runner 命令,输出固定联调说明后立即继续,不等待用户确认;禁止另写开始话术。服务地址和 HTTP 方法只用于后续实际命令,不在本消息中展示:
453
453
 
@@ -106,7 +106,7 @@ Windows 使用 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" a2m`;
106
106
 
107
107
  **⚠️ 脚本的收银接口地址和付款链接前缀已硬编码在脚本中(`PAY_ENDPOINT`、`PAY_URL_PREFIX`),执行时无需额外指定。**
108
108
 
109
- 先按统一 runtime 的 `integration-message a2m-execution-guard` 当前会话 receipt 契约校验项目快照、服务 URL、HTTP 方法和可选 POST body。只有 `decision=RUN` 才使用 `../../../normal/json/customer-messages.json` 的 `a2m.test.start` 渲染固定联调说明并立即运行脚本;`REUSE_PASSED|BLOCK_UNCHANGED|UNKNOWN_PREVIOUS_EXECUTION` 均不得重复发起完整联调。服务地址和 HTTP 方法只用于实际命令,不在开始消息中展示。
109
+ 先按统一 runtime 的 `integration-message a2m-execution-guard` 当前会话 receipt 契约校验项目快照、服务 URL、HTTP 方法和可选 POST body。项目快照按代码和配置的实际内容计算,仅文件时间戳变化或同内容重写不产生新的执行机会;实际内容变化时才允许生成新的 `RUN` receipt。只有 `decision=RUN` 才使用 `../../../normal/json/customer-messages.json` 的 `a2m.test.start` 渲染固定联调说明并立即运行脚本;`REUSE_PASSED|BLOCK_UNCHANGED|UNKNOWN_PREVIOUS_EXECUTION` 均不得重复发起完整联调。服务地址和 HTTP 方法只用于实际命令,不在开始消息中展示。
110
110
 
111
111
  ```bash
112
112
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message a2m-test-start
@@ -66,21 +66,21 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message con
66
66
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message locate-projects --base-path "$USER_WORKSPACE_ROOT" --search-input "$SEARCH_INPUT" --format message
67
67
  ```
68
68
 
69
- 字段齐备后执行唯一 runner;禁止拆开执行项目扫描、`jq` 或 renderer,也不得附加解析。runner stdout 是本动作唯一对客消息;只有取得唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm` 才能继续。命令后的下一个动作必须把 stdout 作为可见进行中消息原文送达,不得作为最终答复结束当前回合,送达前禁止调用工具;送达后同一回合立即使用同一次 runner receipt 进入 development loader,不得总结、询问或等待回复。方案事实变化时重新扫描并输出,不使用确认口令;静态扫描只决定进入验证,不证明完成。
69
+ 字段齐备后执行唯一 runner;禁止拆开执行项目扫描、`jq` 或 renderer,也不得附加解析。runner stdout 是本动作唯一对客消息;只有取得唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm` 才能继续。命令后的下一个动作必须把 stdout 作为可见进行中消息原文送达,不得作为最终答复结束当前回合,送达前禁止调用工具;送达后同一回合立即进入 development loader,不得总结、询问、等待回复或再次校验项目快照。用户中断后若方案事实变化,重新澄清、扫描并输出当前方案;静态扫描只决定进入验证,不证明完成。
70
70
 
71
71
  ```bash
72
72
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message start-confirm --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"
73
73
  ```
74
74
 
75
- 上面命令失败时不得展示手写确认或进入子流程。成功时必须同时保存唯一 `ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRM_RECEIPT=<receipt>` 和 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失、重复或不可解析视为失败。参数必须是当前确定值,禁止直接拼用户输入。runner 校验产品 variant 并固定服务声明;实际范围仍取当前 Integration flow 和 checklist。
75
+ 上面命令失败时不得展示手写确认或进入子流程。成功时必须取得唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm`;缺失或重复视为失败。参数必须是当前确定值,禁止直接拼用户输入。runner 校验产品 variant 并固定服务声明;实际范围仍取当前 Integration flow 和 checklist。
76
76
 
77
- 分流、展示和交接事实必须来自 runner 内同一次 `scan` 对象;禁止用描述、Agent 自报或历史分类代替。`evidence` 仅内部校验,不进 renderer;Onboarding Step 1 前禁止传/猜 `mccCode`。只有方案 stdout 已按交付 marker 可见送达,才同时满足 `INT.START.PLAN_DELIVERED` 与 `INT.SERVICE_STATEMENT.DELIVERED`,随后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE" --project-confirm-receipt "$PROJECT_CONFIRM_RECEIPT"`。只有内部 `PROJECT_CONFIRMATION=VALID` 才进入步骤 3;`STALE` 时 loader stdout 已重新渲染当前标准方案,必须先原文可见送达,再用新 receipt 立即重试一次,连续变化则停止核对。loader 在原位置记录兼容 stage 和预开发阅读 stage,禁止手工执行 telemetry;receipt 有效时禁止再次渲染 `integration.start.confirm`。
77
+ 分流、展示和交接事实必须来自 runner 内同一次 `scan` 对象;禁止用描述、Agent 自报或历史分类代替。`evidence` 仅内部校验,不进 renderer;Onboarding Step 1 前禁止传/猜 `mccCode`。只有方案 stdout 已按交付 marker 可见送达,才同时满足 `INT.START.PLAN_DELIVERED` 与 `INT.SERVICE_STATEMENT.DELIVERED`,随后直接执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration development --product-type "$PRODUCT_TYPE"`。loader 在原位置记录兼容 stage 和预开发阅读 stage,禁止手工执行 telemetry;不得解码内部值、重复扫描或再次渲染 `integration.start.confirm`。
78
78
 
79
- 合法组合必须确定产品、路径/来源、代码状态、语言/框架、服务声明和顺序;发现其他产品时保留。零散信息、`新建` 选择、未选候选或新项目未准备均不能替代完整机器校验。方案送达并通过 receipt 校验后仍完整执行 Integration 和 checklist。
79
+ 合法组合必须确定产品、路径/来源、代码状态、语言/框架、服务声明和顺序;发现其他产品时保留。零散信息、`新建` 选择、未选候选或新项目未准备均不能替代完整机器校验。方案送达后仍完整执行 Integration 和 checklist。
80
80
 
81
81
  ## 子流程衔接规则
82
82
 
83
- - 启动方案送达并校验后直接进入 Integration 步骤 3;项目、产品、语言或框架变化时重新扫描并输出新方案。
83
+ - 启动方案送达后直接进入 Integration 步骤 3;用户中断后若项目、产品、语言或框架变化,重新澄清和扫描并输出当前方案。
84
84
  - Integration 先完整执行和校验。只有沙箱待配置,或 READY 且仅剩非阻塞人工待验证项时,保持“部分通过”进入 Onboarding;其他代码、安全或依据缺口停在 Integration,不提前登录或收集开通材料。
85
85
  - 阶段间只复用有效的产品、项目、代码产物和 CLI 检查,不再询问是否进入 Onboarding;Onboarding 只保留非阻塞方案展示。
86
86
  - 授权后分别查询签约、应用和适用服务;分支独立,单分支失败不回滚其他成功,认证/授权不匹配或主体变化全局阻断。一次只收集一个类别,提前材料直接校验且不重复索取。
@@ -5,10 +5,7 @@ import path from 'node:path';
5
5
  import process from 'node:process';
6
6
  import { fileURLToPath } from 'node:url';
7
7
 
8
- import {
9
- createChecklistScopeReceipt,
10
- validateStartConfirmationReceipt
11
- } from './integration_message_runner.mjs';
8
+ import { createChecklistScopeReceipt } from './integration_message_runner.mjs';
12
9
  import { emitStageMetricAsync } from './telemetry.mjs';
13
10
 
14
11
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
@@ -205,20 +202,6 @@ export function runFlowCli(argv = process.argv) {
205
202
  if (!flow || !phase) throw new Error('用法: flow_loader.mjs <integration|onboarding> <phase> [阶段参数]');
206
203
  const options = parseOptions(argv);
207
204
  const productType = options['product-type'];
208
- if (flow === 'integration' && phase === 'development') {
209
- const validation = validateStartConfirmationReceipt(options['project-confirm-receipt']);
210
- if (productType !== validation.productType) {
211
- throw new Error('integration development phase 的 --product-type 与项目确认回执不匹配');
212
- }
213
- if (!validation.valid) {
214
- process.stderr.write('ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRMATION=STALE\n');
215
- process.stderr.write(`ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRM_RECEIPT=${validation.receipt}\n`);
216
- process.stderr.write('ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm\n');
217
- process.stdout.write(`${validation.message}\n`);
218
- return;
219
- }
220
- process.stderr.write('ALIPAY_AIPAY_INTERNAL:PROJECT_CONFIRMATION=VALID\n');
221
- }
222
205
  if (flow === 'integration' && phase === 'checklist') {
223
206
  const projectPath = options['project-path'];
224
207
  if (!projectPath) throw new Error('integration checklist phase 缺少 --project-path');
@@ -76,14 +76,8 @@ const aipayPaymentValidationMarker = 'Payment-Validation';
76
76
  const aipayPaymentVerifyMarker = 'alipay\\.aipay\\.agent\\.payment\\.verify|AlipayAipayAgentPaymentVerify(Request|Model|Response)|alipay_aipay_agent_payment_verify_response';
77
77
  const aipayFulfillmentConfirmMarker = 'alipay\\.aipay\\.agent\\.fulfillment\\.confirm|AlipayAipayAgentFulfillmentConfirm(Request|Model|Response)|alipay_aipay_agent_fulfillment_confirm_response';
78
78
  const aipayMarker = `${aipayPaymentNeededMarker}|${aipayPaymentProofMarker}|${aipayPaymentVerifyMarker}|${aipayFulfillmentConfirmMarker}`;
79
- const aipayAmountComparisonPattern = [
80
- '(?:amounts?Equal|amounts?_equal|compareAmounts?|amounts?Match|amounts?_match)\\s*\\([^)]{0,320}amount[^)]{0,320},[^)]{0,320}amount[^)]{0,320}\\)',
81
- '(?:normalizeAmount|normalize_amount)\\s*\\([^)]{0,200}amount[^)]{0,200}\\)\\s*(?:===|==|\\.equals\\s*\\()[\\s\\S]{0,240}(?:normalizeAmount|normalize_amount)\\s*\\([^)]{0,200}amount[^)]{0,200}\\)',
82
- '(?:normalized|expected|order|stored|local)[\\w$]*amount\\s*(?:===|==|\\.equals\\s*\\()[\\s\\S]{0,200}(?:normalized|verified|verify|returned|actual|response)[\\w$]*amount'
83
- ].join('|');
84
79
  const internalPrefix = 'ALIPAY_AIPAY_INTERNAL:';
85
80
  const receiptKinds = Object.freeze({
86
- startConfirmation: 'integration-start-confirmation',
87
81
  checklist: 'integration-checklist-scope',
88
82
  a2mExecution: 'integration-a2m-execution',
89
83
  implementationAudit: 'integration-implementation-audit'
@@ -505,12 +499,8 @@ function projectSnapshotFingerprint(projectPath) {
505
499
  const stat = fs.statSync(file);
506
500
  const relative = path.relative(canonicalPath, file);
507
501
  hash.update(`${relative}\0${stat.size}\0`);
508
- if (path.basename(file) === '.alipay-sandbox.json') {
509
- hash.update(`${stat.mtimeMs}\n`);
510
- } else {
511
- hash.update(fs.readFileSync(file));
512
- hash.update('\n');
513
- }
502
+ hash.update(fs.readFileSync(file));
503
+ hash.update('\n');
514
504
  }
515
505
  return hash.digest('hex');
516
506
  }
@@ -598,20 +588,6 @@ function withoutCommentOnlyLines(content) {
598
588
  .join('\n');
599
589
  }
600
590
 
601
- function firstCodeContentPatternMatch(files, pattern) {
602
- for (const file of files) {
603
- let content;
604
- try {
605
- content = fs.readFileSync(file, 'utf8');
606
- } catch {
607
- continue;
608
- }
609
- const match = firstContentPatternMatch(file, withoutCommentOnlyLines(content), pattern);
610
- if (match) return match;
611
- }
612
- return null;
613
- }
614
-
615
591
  function auditFinding(projectPath, code, message, match = null) {
616
592
  const finding = { code, message };
617
593
  if (match) {
@@ -666,9 +642,6 @@ export function inspectImplementation(variant, projectPath) {
666
642
  findings.push(auditFinding(canonicalPath, code, message));
667
643
  }
668
644
  }
669
- if (variant === 'AIPAY' && !firstCodeContentPatternMatch(files, aipayAmountComparisonPattern)) {
670
- findings.push(auditFinding(canonicalPath, 'AIPAY_AMOUNT_CHECK_MISSING', '缺少验付金额与本地订单金额的实际比较'));
671
- }
672
645
 
673
646
  const commonTradeRelevance = [tradeQueryMarker, tradeRefundMarker, tradeRefundQueryMarker, tradeCloseMarker, tradeNotifyMarker].join('|');
674
647
  const targetRelevancePattern = variant === 'AIPAY'
@@ -1102,33 +1075,10 @@ function startConfirmationFacts(args) {
1102
1075
  language,
1103
1076
  framework,
1104
1077
  frameworkSource,
1105
- route,
1106
- projectFingerprint: projectSnapshotFingerprint(projectPath)
1078
+ route
1107
1079
  };
1108
1080
  }
1109
1081
 
1110
- function confirmationReceipt(facts) {
1111
- return encodeReceipt({
1112
- schema_ver: 1,
1113
- kind: receiptKinds.startConfirmation,
1114
- product_type: facts.productType,
1115
- product_name: facts.productName,
1116
- project_path: facts.projectPath,
1117
- project_selection: facts.projectSelection,
1118
- language: facts.language,
1119
- framework: facts.framework,
1120
- framework_source: facts.frameworkSource,
1121
- project_fingerprint: facts.projectFingerprint,
1122
- route: {
1123
- project_origin: facts.route.projectOrigin,
1124
- project_origin_label: facts.route.projectOriginLabel,
1125
- integration_status: facts.route.integrationStatus,
1126
- evidence: facts.route.evidence,
1127
- other_products: facts.route.otherProducts
1128
- }
1129
- });
1130
- }
1131
-
1132
1082
  function renderStartConfirmation(facts) {
1133
1083
  return renderMessage('integration.start.confirm', facts.variant, {
1134
1084
  productName: facts.productName,
@@ -1143,29 +1093,7 @@ function renderStartConfirmation(facts) {
1143
1093
  }
1144
1094
 
1145
1095
  export function createStartConfirmation(args) {
1146
- const facts = startConfirmationFacts(args);
1147
- return { message: renderStartConfirmation(facts), receipt: confirmationReceipt(facts) };
1148
- }
1149
-
1150
- export function validateStartConfirmationReceipt(receipt) {
1151
- const saved = decodeReceipt(receipt, receiptKinds.startConfirmation);
1152
- const args = {
1153
- 'product-type': saved.product_type,
1154
- 'product-name': saved.product_name,
1155
- 'project-path': saved.project_path,
1156
- 'project-selection': saved.project_selection,
1157
- language: saved.language
1158
- };
1159
- if (saved.framework_source === 'EXPLICIT') args.framework = saved.framework;
1160
- const facts = startConfirmationFacts(args);
1161
- const currentReceipt = confirmationReceipt(facts);
1162
- if (currentReceipt === receipt) return { valid: true, receipt, productType: saved.product_type };
1163
- return {
1164
- valid: false,
1165
- receipt: currentReceipt,
1166
- message: renderStartConfirmation(facts),
1167
- productType: saved.product_type
1168
- };
1096
+ return renderStartConfirmation(startConfirmationFacts(args));
1169
1097
  }
1170
1098
 
1171
1099
  export function createChecklistScopeReceipt(projectPath) {
@@ -1392,9 +1320,7 @@ export async function runIntegrationMessageCli(argv = process.argv) {
1392
1320
  return;
1393
1321
  }
1394
1322
  if (command === 'start-confirm') {
1395
- const result = createStartConfirmation(args);
1396
- console.log(result.message);
1397
- process.stderr.write(`${internalPrefix}PROJECT_CONFIRM_RECEIPT=${result.receipt}\n`);
1323
+ console.log(createStartConfirmation(args));
1398
1324
  process.stderr.write(`${internalPrefix}CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.start.confirm\n`);
1399
1325
  return;
1400
1326
  }
@@ -36,6 +36,7 @@ const nodeEntrypoints = Object.freeze({
36
36
 
37
37
  export const runtimeDomains = Object.freeze([
38
38
  'self-update',
39
+ 'integration-bootstrap',
39
40
  'onboarding-bootstrap',
40
41
  'onboarding-execute-ready',
41
42
  ...Object.keys(nodeEntrypoints),
@@ -125,15 +126,29 @@ function assertEnumOption(options, name, allowedValues, { required = true } = {}
125
126
  return value;
126
127
  }
127
128
 
129
+ async function startTelemetryRun(rootIntent, productType) {
130
+ const telemetryArgs = ['start-run', '--root-intent', rootIntent];
131
+ if (productType) telemetryArgs.push('--product-type', productType);
132
+ const { runTelemetryCli } = await import('./telemetry.mjs');
133
+ await runTelemetryCli(cliArgv(telemetryArgs));
134
+ }
135
+
136
+ async function runIntegrationBootstrap(args) {
137
+ const options = parseRuntimeArgs(args);
138
+ assertOnlyOptions(options, ['root-intent', 'product-type']);
139
+ const rootIntent = assertEnumOption(options, 'root-intent', ['integration_only']);
140
+ const productType = assertEnumOption(options, 'product-type', ['aipay', 'webpay', 'apppay'], { required: false });
141
+ await startTelemetryRun(rootIntent, productType);
142
+ const { runFlowCli } = await import('./flow_loader.mjs');
143
+ runFlowCli(cliArgv(['integration', 'entry']));
144
+ }
145
+
128
146
  async function runOnboardingBootstrap(args) {
129
147
  const options = parseRuntimeArgs(args);
130
148
  assertOnlyOptions(options, ['root-intent', 'product-type']);
131
149
  const rootIntent = assertEnumOption(options, 'root-intent', ['onboarding_only']);
132
150
  const productType = assertEnumOption(options, 'product-type', ['aipay', 'webpay', 'apppay'], { required: false });
133
- const telemetryArgs = ['start-run', '--root-intent', rootIntent];
134
- if (productType) telemetryArgs.push('--product-type', productType);
135
- const { runTelemetryCli } = await import('./telemetry.mjs');
136
- await runTelemetryCli(cliArgv(telemetryArgs));
151
+ await startTelemetryRun(rootIntent, productType);
137
152
  const { runOnboardingMessageCli } = await import('./onboarding_message_runner.mjs');
138
153
  await runOnboardingMessageCli(cliArgv(['platform-entry']));
139
154
  const { isWindowsPlatform } = await import('./platform_compat.mjs');
@@ -152,6 +167,7 @@ async function runOnboardingExecuteReady(args) {
152
167
  }
153
168
 
154
169
  async function dispatch(domain, args) {
170
+ if (domain === 'integration-bootstrap') return runIntegrationBootstrap(args);
155
171
  if (domain === 'onboarding-bootstrap') return runOnboardingBootstrap(args);
156
172
  if (domain === 'onboarding-execute-ready') return runOnboardingExecuteReady(args);
157
173
  if (domain === 'auth') {
@@ -40,13 +40,13 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" render <messageId> --va
40
40
 
41
41
  | 意图 | 判定 | 入口 | 后续按需加载 |
42
42
  |---|---|---|---|
43
- | `integration_only` | 只要求代码开发、支付集成或集成排障,未同时要求产品开通 | 执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration entry` | 当前阶段、产品和语言的契约、示例与脚本 |
43
+ | `integration_only` | 只要求代码开发、支付集成或集成排障,未同时要求产品开通 | 执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-bootstrap --root-intent integration_only` | 当前阶段、产品和语言的契约、示例与脚本 |
44
44
  | `onboarding_only` | 只要求签约、入驻或产品开通,未同时要求代码开发 | 执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-bootstrap --root-intent onboarding_only` | 当前阶段的授权、查询或写分支模块 |
45
45
  | `full_process` | 明确要求完整接入、一站式,或同一请求同时要求代码开发和产品开通 | `normal/full-process-routing.md` | 先 Integration,满足衔接条件后 Onboarding |
46
46
 
47
- `onboarding_only` 正常入口使用 `onboarding-bootstrap --root-intent onboarding_only`,该组合动作只串行执行 `telemetry start-run`、`onboarding-message platform-entry` 和 `flow onboarding entry` 三个既有无业务写入动作;Windows 只发送登记引导并停止 Skill 内产品开通,且引导 URL 的 `platform_id` 由 runner 读取本次已创建的同一 `run_id` 后编码生成,禁止 Agent 传入或拼接;非 Windows 继续返回 entry 执行契约。执行该组合动作后不得再单独重复执行这三条原子命令。`full_process` 衔接 Onboarding 时已存在同一根流程 run,不使用带 `start-run` 的 bootstrap;仍先执行 flow 登记的 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message platform-entry`,再按需加载 Onboarding entry,避免重复 `run.intent_detected`。
47
+ `integration_only` 的 `integration-bootstrap` 只在同一 Node 进程串行执行 `telemetry start-run` 与 `flow integration entry`。`onboarding_only` 的 `onboarding-bootstrap` 只串行执行 `telemetry start-run`、`onboarding-message platform-entry` 与 `flow onboarding entry`。两者均为既有无业务写入动作,执行后不得重复原子命令。Windows Onboarding 仅发送登记引导并停止,URL `platform_id` 取本次 `run_id`,禁止 Agent 传入或拼接;非 Windows 返回 entry 契约。`full_process` 不使用 `integration-bootstrap`;衔接 Onboarding 也不使用带 `start-run` 的 bootstrap,仍执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message platform-entry` 后按需加载 entry,避免重复 `run.intent_detected`。
48
48
 
49
- 识别根意图后立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry start-run --root-intent <integration_only|onboarding_only|full_process>`;产品已唯一确定时追加 `--product-type <aipay|webpay|apppay>`。唯一例外是 `onboarding_only` 已按上表执行 `onboarding-bootstrap --root-intent onboarding_only` 时,bootstrap 已包含同一次 `start-run`,不得重复执行本条 telemetry。命令创建/复用当前流程 `run_id`,并在遥测开启时记录 `run.intent_detected`:同一意图和产品继续复用,`UNKNOWN` 补全产品仍复用同一 `run_id`;明确换产品、换根意图或既有 run 已终态才重建。第三方平台项目 ID 仍优先固定为 `run_id`,不得被显式 run ID 或本地生成值覆盖。业务 stage 只由登记 runner/script 异步记录。
49
+ `full_process` 识别根意图后立即执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry start-run --root-intent full_process`;产品已唯一确定时追加 `--product-type <aipay|webpay|apppay>`。`integration_only` 和 `onboarding_only` 已由上表各自 bootstrap 包含同一次 `start-run`,不得重复执行本条 telemetry。命令创建/复用当前流程 `run_id`,并在遥测开启时记录 `run.intent_detected`:同一意图和产品继续复用,`UNKNOWN` 补全产品仍复用同一 `run_id`;明确换产品、换根意图或既有 run 已终态才重建。第三方平台项目 ID 仍优先固定为 `run_id`,不得被显式 run ID 或本地生成值覆盖。业务 stage 只由登记 runner/script 异步记录。
50
50
 
51
51
  遥测默认开启,`ALIPAY_AIPAY_TELEMETRY=0|false|off|no` 可关闭 `METRIC_EVENT`、outbox、上传和 flush;私有流程 run context 仍用于 `PLATFORM_ID` 和终态生命周期。落盘/网络/上传/flush 失败静默,不改变业务、消息或确认,stdout 为空且 stderr 内部行不对客。`integration_only` 由 checklist 终态结束 run,其他意图由 Onboarding closeout 结束。脚本始终以当前流程 `run_id` 为 `PLATFORM_ID`,Agent 不手写环境前缀或改 MCP payload;维护诊断、outbox、上传和 flush 细节只在 `normal/telemetry.md` 按需读取。
52
52
 
@@ -54,10 +54,10 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" render <messageId> --va
54
54
 
55
55
  代码开发或完整接入缺项目位置/服务端语言时,使用 `integration.context.required` 或 `integration.project_path.required` 标准消息;框架缺失不触发补问。先区分新建与复用并保留原始 `PROJECT_INPUT`。明确新建产物固定用 `resolve-project --intent new`;含名称或位置时由 Agent 解析 `TARGET_PROJECT_PATH` 并传 `--target-path`,runner 只校验路径和目录状态,不解析自然语言或把原话当目录名;纯默认新建才省略。现有项目未知时先定位候选;所有路径经 `resolve-project` 后再用 `framework-resolve`:新项目取语言默认框架,现有项目从依赖推导或沿用结构,用户明确框架优先。补齐前不初始化、装依赖或改文件。
56
56
 
57
- 每轮代码开发只渲染一次非阻塞 `integration.start.confirm`,两种意图复用同一次检查器事实并覆盖 Integration 步骤 1 至步骤8:代码开发校验;只有对应 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED` marker 唯一且 stdout 已作为可见消息送达,才算方案送达,随后以 receipt 进入步骤 3。`full_process` 在方案展示前已完成步骤 1。Onboarding 只保留一次非阻塞方案展示;同样只有 marker 唯一且 stdout 已可见送达,才允许在 MCC 唯一事实有效后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-execute-ready --product-type "$PRODUCT_TYPE"`。该组合动作只串行加载 `flow onboarding execute` 并执行既有 `env check`,不跨用户输入、授权页或任何写操作;执行后不得再重复单独加载 execute phase 或重复环境检查。两类方案送达后都自动继续,不等待回复。服务修改仍保留绑定当前摘要的阻塞确认。签约材料完整后直接提交,服务创建摘要后直接创建,新建应用公钥校验成功后直接提审。
57
+ 每轮代码开发只渲染一次非阻塞 `integration.start.confirm`,覆盖步骤 1 至步骤8:代码开发校验;对应 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED` marker 唯一且 stdout 可见送达后,直接进入步骤 3,不生成或复验方案 receipt。`full_process` 在方案展示前已完成步骤 1。Onboarding 只保留一次非阻塞方案展示;同样只有 marker 唯一且 stdout 已可见送达,才允许在 MCC 唯一事实有效后执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-execute-ready --product-type "$PRODUCT_TYPE"`。该组合动作只串行加载 `flow onboarding execute` 并执行既有 `env check`,不跨用户输入、授权页或任何写操作;执行后不得再重复单独加载 execute phase 或重复环境检查。两类方案送达后都自动继续,不等待回复。服务修改仍保留绑定当前摘要的阻塞确认。签约材料完整后直接提交,服务创建摘要后直接创建,新建应用公钥校验成功后直接提审。
58
58
 
59
59
  扫码页非阻塞:授权最多 12 次/间隔 5 秒,公钥最多 20 次/间隔 2 秒,成功即推进;耗尽后经统一回复判定只查一次,不重启轮询。
60
60
 
61
- `full_process` 代码开发方案送达前只准备项目、语言、系统分支环境和沙箱;Windows 未明确要求当前配置时记 `VERIFY_PENDING`,不收资料。方案送达且 receipt 有效后进入 Integration 步骤 3,满足条件自动进 Onboarding;仅沙箱待配置,或 READY 且只剩非阻塞人工验证时可部分通过,其他缺口停在 Integration;收口保留全部待办。
61
+ `full_process` 代码开发方案送达前只准备项目、语言、系统分支环境和沙箱;Windows 未明确要求当前配置时记 `VERIFY_PENDING`,不收资料。方案送达后直接进入 Integration 步骤 3,满足条件自动进 Onboarding;仅沙箱待配置,或 READY 且只剩非阻塞人工验证时可部分通过,其他缺口停在 Integration;收口保留全部待办。用户中断后重新确认当前项目和服务端语言,从实际项目扫描恢复,不恢复旧方案状态。
62
62
 
63
63
  仅代码开发结束时提醒仍需产品开通;仅产品开通结束时提醒仍需代码开发。机器规则、消息目录、fixture 和测试不作为默认必读内容。