@alipay/alipay-aipay 1.6.7-beta1 → 1.6.7-beta2
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 +1 -1
- package/skill/VERSION +1 -1
- package/skill/references/integration/flow.md +7 -7
- package/skill/references/integration/modules/scripts/sandbox_config.sh +2 -0
- package/skill/references/normal/integration-worker.md +1 -1
- package/skill/references/normal/scripts/integration_message_runner.mjs +17 -5
- package/skill/references/normal/scripts/onboarding_discovery_runner.mjs +8 -1
- package/skill/references/normal/scripts/onboarding_message_runner.mjs +17 -6
- package/skill/references/normal/scripts/render_customer_message.mjs +3 -3
- package/skill/references/onboarding/flow.md +7 -3
- package/skill/references/onboarding/modules/app-release.md +2 -0
- package/skill/references/onboarding/modules/scripts/mcc.sh +17 -5
- package/skill/references/runtime-entry.md +2 -2
package/package.json
CHANGED
package/skill/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.6.7-
|
|
1
|
+
1.6.7-beta2
|
|
@@ -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`
|
|
170
|
-
- `VERIFY_PENDING`:退出码为 0;脚本 stdout 已渲染唯一 `sandbox.configuration.pending/VERIFY`
|
|
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
|
|
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
|
|
|
@@ -332,7 +332,7 @@ curl -sL "<当前契约 sourceUrl 中的官方页面>"
|
|
|
332
332
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" sandbox summary "<productType>" "<规范化项目路径>" "<已确认服务端语言>"
|
|
333
333
|
```
|
|
334
334
|
|
|
335
|
-
该命令 stdout 只渲染 `sandbox.environment.summary` 与 `sandbox.environment.reminder
|
|
335
|
+
该命令 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
336
|
|
|
337
337
|
Windows 从项目实际读取的同一本机配置构造不含密码和密钥原文的 `ENVIRONMENT_ROWS`,再从本 flow 所在目录执行以下固定命令;不得重新索取或复述步骤 1 已提供的敏感值,也不得改用 Unix 快速沙箱脚本:
|
|
338
338
|
|
|
@@ -500,7 +500,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message ser
|
|
|
500
500
|
**完成条件**:
|
|
501
501
|
- [INT.CLOSEOUT.SAFETY_AND_NEXT_STEPS_PRINTED] 已向用户明文输出安全红线和完整上线指引
|
|
502
502
|
|
|
503
|
-
**安全与上线提醒(必须明文打印给用户)**:使用 `../normal/json/customer-messages.json` 的 `integration.safety.closeout`,按 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY` 映射产品并传入实际验收口径。模板覆盖私钥保护、支付结果依据、异常恢复、异步通知或 `Payment-Proof`/履约确认、生产配置、真实 `serviceId` 和私钥格式;不重复沙箱摘要、账号密码、Android 下载或步骤 6
|
|
503
|
+
**安全与上线提醒(必须明文打印给用户)**:使用 `../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
504
|
|
|
505
505
|
```bash
|
|
506
506
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message safety-closeout --variant "$PRODUCT_VARIANT" --acceptance-summary "$ACCEPTANCE_SUMMARY"
|
|
@@ -528,7 +528,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
|
|
|
528
528
|
|
|
529
529
|
**执行边界**:默认禁止安装依赖或浏览器、切换运行时版本、启动长期服务、申请网络/端口权限、执行截图或 UI 自动化,也不得重复步骤 6 已完成的端到端测试。遇到 `EPERM`、网络受限、缺少浏览器等环境限制时,将对应项标记为“人工待验证”并停止扩展排查;不得据此推断代码或运行时兼容问题。只有用户明确要求继续扩展验证时,才展示拟执行动作并按原确认规则处理。
|
|
530
530
|
|
|
531
|
-
步骤 3 至步骤 7 的必要依据、配置摘要、代码修复、网站回跳或按量付费联调在本轮无法继续时,跳过所有依赖该失败事实的后续动作,但仍进入本步骤:把未满足条件和被跳过动作按实际证据标记为失败或人工待验证,并使用同一 `integration.checklist.result`
|
|
531
|
+
步骤 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
532
|
|
|
533
533
|
校验项包括:
|
|
534
534
|
- 签名验签
|
|
@@ -545,7 +545,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" integration-message saf
|
|
|
545
545
|
|
|
546
546
|
若审计发现问题且命令未传 `--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
547
|
|
|
548
|
-
对客结论统一使用 `integration.checklist.result`;整体结论、失败/部分通过项和人工待验证项必须来自最终一轮 checklist
|
|
548
|
+
对客结论统一使用 `integration.checklist.result`;整体结论、失败/部分通过项和人工待验证项必须来自最终一轮 checklist 实际证据。最终渲染成功时必须产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=integration.checklist.result`;命令返回后的下一动作先将 stdout 原文独立送达,不得以工具面板或自写总结替代。首次调用前先按以下完整契约确定参数,禁止改枚举:
|
|
549
549
|
|
|
550
550
|
- `variant` 映射 `aipay=AIPAY`、`webpay=WEBPAY`、`apppay=APPPAY`;`overallResult` 只允许“通过、部分通过、未通过”。
|
|
551
551
|
- `failedItems`/`manualItems` 必须是含下一步的受控单行值,无项目传“无”。`sandboxConfigState` 只允许 `READY|CREATE_PENDING|VERIFY_PENDING`;除沙箱配置及其直接依赖外存在代码、安全或必要依据缺口时 `blockingDefectState=PRESENT`,否则 `NONE`。待配置时 `failedItems` 必须列出沙箱配置及依赖动作未完成;恢复口令只由步骤 1/3 已发送的 `sandbox.configuration.pending` 正文提供。
|
|
@@ -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
|
}
|
|
@@ -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
|
|
@@ -49,7 +49,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" flow integration develo
|
|
|
49
49
|
|
|
50
50
|
Integration Worker 不执行 Onboarding、self-update、`telemetry start-run`、产品/项目重新决策或原 flow 之外的沙箱调用和诊断。不得用 Worker 自报代替原 flow 要求的实际脚本终态和校验证据。
|
|
51
51
|
|
|
52
|
-
原 flow 要求对客送达的登记 runner/script stdout
|
|
52
|
+
原 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
53
|
|
|
54
54
|
## 返回协议
|
|
55
55
|
|
|
@@ -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, emitStageMetricAsync, recordTelemetryUserInput, 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');
|
|
@@ -130,6 +130,11 @@ function countUserInput(args) {
|
|
|
130
130
|
if (inputId) recordTelemetryUserInput(inputId);
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
function requireCustomerMessageDelivery(messageId, message) {
|
|
134
|
+
process.stderr.write(`${internalPrefix}CUSTOMER_MESSAGE_DELIVERY_REQUIRED=${messageId}\n`);
|
|
135
|
+
return message;
|
|
136
|
+
}
|
|
137
|
+
|
|
133
138
|
function stripWrappingQuotes(value) {
|
|
134
139
|
const trimmed = value.trim();
|
|
135
140
|
if (
|
|
@@ -1256,9 +1261,9 @@ function runServiceNotReady(args) {
|
|
|
1256
1261
|
function runSafetyCloseout(args) {
|
|
1257
1262
|
const variant = required(args, 'variant');
|
|
1258
1263
|
if (!['AIPAY', 'WEBPAY', 'APPPAY'].includes(variant)) throw new Error('variant 非法,仅支持 AIPAY、WEBPAY、APPPAY');
|
|
1259
|
-
return renderMessage('integration.safety.closeout', variant, {
|
|
1264
|
+
return requireCustomerMessageDelivery('integration.safety.closeout', renderMessage('integration.safety.closeout', variant, {
|
|
1260
1265
|
acceptanceSummary: required(args, 'acceptance-summary')
|
|
1261
|
-
});
|
|
1266
|
+
}));
|
|
1262
1267
|
}
|
|
1263
1268
|
|
|
1264
1269
|
function runWindowsSandboxSummary(args) {
|
|
@@ -1268,7 +1273,7 @@ function runWindowsSandboxSummary(args) {
|
|
|
1268
1273
|
environmentRows: required(args, 'environment-rows')
|
|
1269
1274
|
});
|
|
1270
1275
|
const reminder = renderMessage('sandbox.environment.reminder', 'WINDOWS', {});
|
|
1271
|
-
return `${summary}\n\n${reminder}
|
|
1276
|
+
return requireCustomerMessageDelivery('sandbox.environment.summary', `${summary}\n\n${reminder}`);
|
|
1272
1277
|
}
|
|
1273
1278
|
|
|
1274
1279
|
async function readStdin() {
|
|
@@ -1313,6 +1318,13 @@ function checklistInputFromArgs(args) {
|
|
|
1313
1318
|
async function runChecklistResult(args) {
|
|
1314
1319
|
const variant = required(args, 'variant');
|
|
1315
1320
|
if (!['AIPAY', 'WEBPAY', 'APPPAY'].includes(variant)) throw new Error('variant 非法,仅支持 AIPAY、WEBPAY、APPPAY');
|
|
1321
|
+
if (telemetryEnabled()) {
|
|
1322
|
+
const run = currentRunContext();
|
|
1323
|
+
if (!run?.run_id || run.terminal || run.product_type !== variant.toUpperCase()
|
|
1324
|
+
|| !['integration_only', 'full_process'].includes(run.root_intent)) {
|
|
1325
|
+
throw new Error('checklist 必须在当前产品匹配的 active integration run 内执行');
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1316
1328
|
if (Object.prototype.hasOwnProperty.call(args, 'implementation-audit-receipt')) {
|
|
1317
1329
|
throw new Error('implementation-audit-receipt 已废弃');
|
|
1318
1330
|
}
|
|
@@ -1354,7 +1366,7 @@ async function runChecklistResult(args) {
|
|
|
1354
1366
|
}
|
|
1355
1367
|
emitStageMetricAsync('integration.complete_coding', { productType: variant.toLowerCase() });
|
|
1356
1368
|
const rendered = renderMessage('integration.checklist.result', variant, input);
|
|
1357
|
-
return rendered;
|
|
1369
|
+
return requireCustomerMessageDelivery('integration.checklist.result', rendered);
|
|
1358
1370
|
}
|
|
1359
1371
|
|
|
1360
1372
|
export async function runIntegrationMessageCli(argv = process.argv) {
|
|
@@ -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, emitStageMetricAsync, 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);
|
|
@@ -218,6 +218,11 @@ function runEnterpriseUnsupported(args) {
|
|
|
218
218
|
async function runMccClarify(args) {
|
|
219
219
|
const productType = required(args, 'product-type');
|
|
220
220
|
const product = productFor({ ...args, 'product-type': productType });
|
|
221
|
+
const rootIntent = required(args, 'root-intent');
|
|
222
|
+
if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
223
|
+
throw new Error('root-intent 仅支持 onboarding_only、full_process');
|
|
224
|
+
}
|
|
225
|
+
await startTelemetryRun(rootIntent, productType);
|
|
221
226
|
return renderMessage('onboarding.mcc.clarify', 'DEFAULT', {
|
|
222
227
|
productName: product.productName
|
|
223
228
|
}, { productType });
|
|
@@ -733,10 +738,11 @@ async function runPlanConfirm(args) {
|
|
|
733
738
|
async function runMccResolvePlan(args) {
|
|
734
739
|
const productType = required(args, 'product-type');
|
|
735
740
|
productFor({ ...args, 'product-type': productType });
|
|
736
|
-
const rootIntent =
|
|
737
|
-
if (['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
738
|
-
|
|
741
|
+
const rootIntent = required(args, 'root-intent');
|
|
742
|
+
if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
743
|
+
throw new Error('root-intent 仅支持 onboarding_only、full_process');
|
|
739
744
|
}
|
|
745
|
+
await startTelemetryRun(rootIntent, productType);
|
|
740
746
|
const mccRunContext = captureMccRunContext();
|
|
741
747
|
const query = required(args, 'query');
|
|
742
748
|
const selected = optional(args, 'select');
|
|
@@ -789,6 +795,11 @@ async function runMccResolvePlan(args) {
|
|
|
789
795
|
async function runMccMatchCodes(args) {
|
|
790
796
|
const productType = required(args, 'product-type');
|
|
791
797
|
productFor({ ...args, 'product-type': productType });
|
|
798
|
+
const rootIntent = required(args, 'root-intent');
|
|
799
|
+
if (!['onboarding_only', 'full_process'].includes(rootIntent)) {
|
|
800
|
+
throw new Error('root-intent 仅支持 onboarding_only、full_process');
|
|
801
|
+
}
|
|
802
|
+
await startTelemetryRun(rootIntent, productType);
|
|
792
803
|
const query = required(args, 'query');
|
|
793
804
|
const semanticTerms = parseMccSemanticTerms(args);
|
|
794
805
|
if (args['agent-mcc-status'] !== undefined || args['agent-mcc-codes'] !== undefined) {
|
|
@@ -1206,10 +1217,10 @@ function runApplicationResult(args) {
|
|
|
1206
1217
|
if (actualStatus === '需人工配置') {
|
|
1207
1218
|
if (optional(args, 'next-action') !== undefined) throw new Error('需人工配置的下一步由消息目录固定,不接收 --next-action');
|
|
1208
1219
|
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', {
|
|
1220
|
+
return requireCustomerMessageDelivery('application.operation.result', renderMessage('application.operation.result', 'ALIPAY_PUBLIC_KEY_MANUAL_CONFIGURATION', {
|
|
1210
1221
|
appId: required(args, 'app-id'),
|
|
1211
1222
|
actualStatus
|
|
1212
|
-
});
|
|
1223
|
+
}));
|
|
1213
1224
|
}
|
|
1214
1225
|
const variables = {
|
|
1215
1226
|
appId: required(args, 'app-id'),
|
|
@@ -1218,7 +1229,7 @@ function runApplicationResult(args) {
|
|
|
1218
1229
|
};
|
|
1219
1230
|
const appKeySavePath = optional(args, 'app-key-save-path');
|
|
1220
1231
|
if (appKeySavePath !== undefined) variables.appKeySavePath = appKeySavePath;
|
|
1221
|
-
return renderMessage('application.operation.result', 'DEFAULT', variables);
|
|
1232
|
+
return requireCustomerMessageDelivery('application.operation.result', renderMessage('application.operation.result', 'DEFAULT', variables));
|
|
1222
1233
|
}
|
|
1223
1234
|
|
|
1224
1235
|
export async function runOnboardingMessageCli(argv = process.argv) {
|
|
@@ -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': {
|
|
@@ -101,14 +101,14 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message ente
|
|
|
101
101
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message product-clarify
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
产品明确但无经营描述/MCC:执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-clarify --product-type "$PRODUCT_TYPE"`
|
|
104
|
+
产品明确但无经营描述/MCC:执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message mcc-clarify --product-type "$PRODUCT_TYPE" --root-intent "$ROOT_INTENT"`。该命令必须先创建或复用正式 telemetry run 并记录 `clarify_intent`;缺少或非法 `ROOT_INTENT` 时停止,不得继续 MCC 或授权。
|
|
105
105
|
|
|
106
106
|
已有经营描述、二级类目名称或编码时,以原话作为 `MCC_SEARCH_QUERY` 进入唯一 MCC 解析/方案入口。非精确编码时,Agent 应先理解原话;遇到行业俗称、场景表达或目录不一定直接出现的用词时,在首次调用中一并传入 0 到 12 个有原话依据的行业概念、经营对象或同义表达,形成 `MCC_SEMANTIC_TERMS_JSON`;只传概念、不传 MCC 编码,不补原话无依据的行业。没有可靠扩展时省略,不追加用户确认。runner 在完整动态类目内做 NFKC、泛词剥离、标点边界内二/三元词组召回和动态稀有度排序;原始精确编码/完整名称决定性优先,其余原话与 Agent 辅助概念联合评分,语义项按 `0.7` 权重参与,名称证据高于描述,其他候选最多 8 项。评分只用于真实目录召回排序;禁止业务词到 MCC 的硬编码点映射、Agent 全表判断、远程语义或额外网络调用。
|
|
107
107
|
|
|
108
108
|
`queryMcc` 树和多候选快照使用默认 1800 秒、本轮 run 私有缓存;无有效 run 不缓存。快照绑定产品、salesCode、原查询、规范化语义词、选择回执、候选树事实及按需取得的资格详情;有效命中原样复用,失效才重查。runner 只接受最多 12 项、单项 2 到 40 字符、总计不超过 240 字符的 JSON 字符串数组并拒绝 MCC 编码;Agent 参数错误时基于原话更正或省略,不要求用户重述。两种 MCP 请求体不变;`batchQueryMcc` 最多一次,只传树内命中且 `needSpecialQual=true` 的候选编码。
|
|
109
109
|
|
|
110
110
|
```bash
|
|
111
|
-
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" [--semantic-terms-json "$MCC_SEMANTIC_TERMS_JSON"] --input-id "$USER_INPUT_ID"
|
|
111
|
+
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" --root-intent "$ROOT_INTENT" [--semantic-terms-json "$MCC_SEMANTIC_TERMS_JSON"] --input-id "$USER_INPUT_ID"
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
只收唯一 `ALIPAY_AIPAY_INTERNAL:MCC_QUERY_RESULT=SUCCESS` 与 `ALIPAY_AIPAY_INTERNAL:MCC_RESOLUTION=<json>`。`UNIQUE` 恰一项,并有唯一 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=onboarding.plan.confirm`、`MCC_CONTEXT_RECEIPT`;先把 stdout 作为可见进行中消息原文送达,随后同一回合进入 `execute`,不等待回复。`MULTIPLE|NONE` 送候选/无匹配后等待。禁止旧 `mcc-search`/`mcc-candidates`、手写候选或近似追问。
|
|
@@ -117,7 +117,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --quer
|
|
|
117
117
|
|
|
118
118
|
`ALIPAY_AIPAY_INTERNAL:MCC_QUERY_RESULT=FAILED` 且无 `MCC_FLOW:RETRY_WITH_NETWORK`:送stdout,停MCC;非无匹配,禁候选/方案/授权/签约。
|
|
119
119
|
|
|
120
|
-
`MULTIPLE` 还须取得唯一 `MCC_SELECTION_RECEIPT`。用户回复序号、当前候选完整名称或编码时,以原始 `MCC_SEARCH_QUERY` 和首次检索使用的同一 `MCC_SEMANTIC_TERMS_JSON` 重跑同一入口:`node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" [--semantic-terms-json "$MCC_SEMANTIC_TERMS_JSON"] --select "$SELECTED_MCC_CODE" --selection-receipt "$MCC_SELECTION_RECEIPT" --input-id "$USER_INPUT_ID"`。有效详情快照直接生成方案,不再调用 `queryMcc` 或 `batchQueryMcc`;runner 仍校验当前 run、产品、原话、规范化语义词、候选和事实哈希。receipt 或快照失效时不得沿用或自动套用旧选择,必须基于完整当前产品目录重新召回并至少重新展示一次当前候选。
|
|
120
|
+
`MULTIPLE` 还须取得唯一 `MCC_SELECTION_RECEIPT`。用户回复序号、当前候选完整名称或编码时,以原始 `MCC_SEARCH_QUERY` 和首次检索使用的同一 `MCC_SEMANTIC_TERMS_JSON` 重跑同一入口:`node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" --root-intent "$ROOT_INTENT" [--semantic-terms-json "$MCC_SEMANTIC_TERMS_JSON"] --select "$SELECTED_MCC_CODE" --selection-receipt "$MCC_SELECTION_RECEIPT" --input-id "$USER_INPUT_ID"`。有效详情快照直接生成方案,不再调用 `queryMcc` 或 `batchQueryMcc`;runner 仍校验当前 run、产品、原话、规范化语义词、候选和事实哈希。receipt 或快照失效时不得沿用或自动套用旧选择,必须基于完整当前产品目录重新召回并至少重新展示一次当前候选。
|
|
121
121
|
|
|
122
122
|
`salesCode`、`scope` 和基础材料只取“产品映射”。方案只由 `mcc resolve-plan` 或已有唯一 MCC 事实时的 `onboarding-message plan-confirm --root-intent "$ROOT_INTENT" --mcc-context-receipt` 生成,展示产品/scope、MCC、特殊资质、企业账号边界及商家平台链接。`ROOT_INTENT` 取当前路线根意图,只能是 `onboarding_only` 或 `full_process`。特殊资质只来自 `qualificationGroups`:多个 group 是 OR 关系;同一 group 内多个 qualifications 是 AND 关系;`attaType` 为空或 null 的 qualification 只展示 `qualName`,不生成上传项。禁止补充模板外资格或审核规则。
|
|
123
123
|
|
|
@@ -224,6 +224,8 @@ Step 1 的产品/MCC 唯一事实校验和方案送达、Step 2 的环境 READY
|
|
|
224
224
|
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"]
|
|
225
225
|
```
|
|
226
226
|
|
|
227
|
+
该查询只能在当前产品匹配且未收口的 `onboarding_only|full_process` active run 内执行;telemetry 开启时缺少或不匹配 run 会直接停止,禁止完成查询后静默丢失 `onboarding.confirm_signing`。
|
|
228
|
+
|
|
227
229
|
只接受唯一 `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` 或结构异常不得触发二者。
|
|
228
230
|
|
|
229
231
|
命中 `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`、本地权限、网络权限,禁止同时进入两个恢复分支。
|
|
@@ -506,6 +508,8 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message appl
|
|
|
506
508
|
|
|
507
509
|
`SIGNING_RESULT`、`SERVICE_RESULT`、`APPLICATION_RESULT` 和 `INTEGRATION_RESULT` 必须使用消息目录允许的状态枚举原文,禁止拼接 `appId`、公钥文件路径、错误码、截图证据或其他自由文本;本轮 `ALIPAY_PUBLIC_KEY_EXPORT_STATUS=EXPORTED` 时,`APP_KEY_SAVE_PATH` 或 `APPLICATION_OPERATION_APP_KEY_SAVE_PATH` 必须同时传入结果 runner。这些证据不能污染分支结果枚举。
|
|
508
510
|
|
|
511
|
+
应用分支单独输出 `application.operation.result` 时,runner 必须输出唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=application.operation.result`。命令后的下一个 Agent 动作必须先将该次 stdout 原文作为独立用户可见消息送达,送达前禁止 closeout、合并或继续工具调用;总收口不能替代这条应用结果消息。该约束只强化消息交付编排,不新增用户确认点;marker 缺失或不唯一时停止并重跑同一登记命令。
|
|
512
|
+
|
|
509
513
|
```bash
|
|
510
514
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message closeout --product-type "$PRODUCT_TYPE" --root-intent "$ROOT_INTENT" --signing-result "$SIGNING_RESULT" --application-result "$APPLICATION_RESULT" --remaining-actions "$REMAINING_ACTIONS" [--integration-result "$INTEGRATION_RESULT"] [--service-result "$SERVICE_RESULT"] [--sandbox-config-state "$SANDBOX_CONFIG_STATE"] [--manual-verification-items "$MANUAL_VERIFICATION_ITEMS"] [--application-operation-app-id "$APPLICATION_OPERATION_APP_ID" [--application-operation-next-action "$APPLICATION_OPERATION_NEXT_ACTION"] [--application-operation-app-key-save-path "$APPLICATION_OPERATION_APP_KEY_SAVE_PATH"]]
|
|
511
515
|
```
|
|
@@ -83,4 +83,6 @@ RSA2 状态只看应用公钥字段,支付宝公钥不能反证。`verify-key|
|
|
|
83
83
|
node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message application-result --app-id "$APP_ID" --actual-status "$ACTUAL_STATUS" [--next-action "$NEXT_ACTION"] [--app-key-save-path "$APP_KEY_SAVE_PATH"]
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
单独执行该命令时,只要 stdout 非空,必须同时取得唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=application.operation.result`,并在下一步先将 stdout 原文作为独立用户可见消息送达;送达前禁止执行 closeout 或把应用结果并入总收口。该交付屏障不增加用户确认点。`需人工配置` 分支同样必须交付,但禁止传公钥保存路径。
|
|
87
|
+
|
|
86
88
|
输出实际 appId、状态和下一步;若本轮 `ALIPAY_PUBLIC_KEY_EXPORT_STATUS=EXPORTED`,必须把该路径原样作为 `APP_KEY_SAVE_PATH` 传入,runner 会对客展示“当前 appId: xxx 对应的支付宝公钥保存在:xxx”。只展示路径,禁止复述支付宝公钥内容。待审核、待设钥、需人工配置、失败或未知不得称发布完成。`APP_FLOW:RETRY_WITH_LOCAL_CONFIG_PERMISSION` 不渲染结果;`MANUAL_CONFIGURATION_REQUIRED` 固定传“需人工配置”且省略 `--next-action` 和 `--app-key-save-path`,由目录派生。写操作仅 `NOT_SENT` 自动重试;`MAYBE_SENT` 查询核验,无法确认进入 `UNKNOWN`,禁止同名猜测或重复创建/提审。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# 功能描述: 查询当前产品支持的 MCC 经营类目并托管 MCC 匹配与方案展示
|
|
5
5
|
# 调用位置: Step 1 方案规划
|
|
6
6
|
# 用法:
|
|
7
|
-
# bash mcc.sh resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay> [--semantic-terms-json <JSON数组>] [--select <MCC编码> --selection-receipt <receipt>] [--input-id <USER_INPUT_ID>]
|
|
7
|
+
# bash mcc.sh resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay> --root-intent <onboarding_only|full_process> [--semantic-terms-json <JSON数组>] [--select <MCC编码> --selection-receipt <receipt>] [--input-id <USER_INPUT_ID>]
|
|
8
8
|
#=============================================================================
|
|
9
9
|
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -514,12 +514,13 @@ normalize_mcc_catalog() {
|
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
run_mcc_match_codes() {
|
|
517
|
-
local query="$1" product_type="$2"
|
|
517
|
+
local query="$1" product_type="$2" root_intent="$3" catalog="$4" semantic_terms_json="$5" runner_out runner_err runner_rc line resolution=""
|
|
518
518
|
runner_out=$(mktemp "${TMPDIR:-/tmp}/mcc_match_out.XXXXXX") || { echo "❌ 创建临时文件失败"; exit 1; }
|
|
519
519
|
runner_err=$(mktemp "${TMPDIR:-/tmp}/mcc_match_err.XXXXXX") || { rm -f "$runner_out"; echo "❌ 创建临时文件失败"; exit 1; }
|
|
520
520
|
"${NODE_BINARY:-node}" "$ONBOARDING_RUNNER" mcc-match-codes \
|
|
521
521
|
--query "$query" \
|
|
522
522
|
--product-type "$product_type" \
|
|
523
|
+
--root-intent "$root_intent" \
|
|
523
524
|
--mcc-catalog-json "$catalog" \
|
|
524
525
|
--semantic-terms-json "$semantic_terms_json" >"$runner_out" 2>"$runner_err"
|
|
525
526
|
runner_rc=$?
|
|
@@ -549,7 +550,7 @@ validate_mcc_selection_cache() {
|
|
|
549
550
|
}
|
|
550
551
|
|
|
551
552
|
run_resolve_plan() {
|
|
552
|
-
local query="" product_type="" semantic_terms_json='[]' select_value="" selection_receipt="" input_id="" sales_code tree rows tree_catalog resolution match_type full_codes candidate_rows qualification_rows details catalog selection_cache="" used_selection_cache=false stale_selection=false resolved_semantic_terms='[]'
|
|
553
|
+
local query="" product_type="" root_intent="" semantic_terms_json='[]' select_value="" selection_receipt="" input_id="" sales_code tree rows tree_catalog resolution match_type full_codes candidate_rows qualification_rows details catalog selection_cache="" used_selection_cache=false stale_selection=false resolved_semantic_terms='[]'
|
|
553
554
|
shift
|
|
554
555
|
while [[ $# -gt 0 ]]; do
|
|
555
556
|
case "$1" in
|
|
@@ -559,6 +560,9 @@ run_resolve_plan() {
|
|
|
559
560
|
--product-type)
|
|
560
561
|
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
561
562
|
product_type="$2"; shift 2 ;;
|
|
563
|
+
--root-intent)
|
|
564
|
+
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
565
|
+
root_intent="$2"; shift 2 ;;
|
|
562
566
|
--semantic-terms-json)
|
|
563
567
|
[ $# -ge 2 ] || { echo "❌ 缺少参数值: $1"; exit 1; }
|
|
564
568
|
semantic_terms_json="$2"; shift 2 ;;
|
|
@@ -579,6 +583,13 @@ run_resolve_plan() {
|
|
|
579
583
|
echo "❌ 缺少 --query 或 --product-type"
|
|
580
584
|
exit 1
|
|
581
585
|
fi
|
|
586
|
+
case "$root_intent" in
|
|
587
|
+
onboarding_only|full_process) ;;
|
|
588
|
+
*)
|
|
589
|
+
echo "❌ 缺少或非法 --root-intent,仅支持 onboarding_only、full_process"
|
|
590
|
+
exit 1
|
|
591
|
+
;;
|
|
592
|
+
esac
|
|
582
593
|
semantic_terms_json=$(printf '%s' "$semantic_terms_json" | jq -ce '
|
|
583
594
|
select(type == "array" and length <= 12 and all(.[]; type == "string"))
|
|
584
595
|
' 2>/dev/null) || {
|
|
@@ -617,7 +628,7 @@ run_resolve_plan() {
|
|
|
617
628
|
tree_catalog=$(normalize_mcc_tree_catalog "$rows") || {
|
|
618
629
|
mcc_query_failed
|
|
619
630
|
}
|
|
620
|
-
capture_or_exit resolution run_mcc_match_codes "$query" "$product_type" "$tree_catalog" "$semantic_terms_json"
|
|
631
|
+
capture_or_exit resolution run_mcc_match_codes "$query" "$product_type" "$root_intent" "$tree_catalog" "$semantic_terms_json"
|
|
621
632
|
match_type=$(printf '%s' "$resolution" | jq -r '.matchType // ""' 2>/dev/null) || mcc_query_failed
|
|
622
633
|
resolved_semantic_terms=$(printf '%s' "$resolution" | jq -c '.semanticTerms // []' 2>/dev/null) || mcc_query_failed
|
|
623
634
|
if [ "$match_type" = "NONE" ]; then
|
|
@@ -649,6 +660,7 @@ run_resolve_plan() {
|
|
|
649
660
|
"$ONBOARDING_RUNNER" mcc-resolve-plan
|
|
650
661
|
--query "$query"
|
|
651
662
|
--product-type "$product_type"
|
|
663
|
+
--root-intent "$root_intent"
|
|
652
664
|
--mcc-catalog-json "$catalog"
|
|
653
665
|
--semantic-terms-json "$semantic_terms_json"
|
|
654
666
|
)
|
|
@@ -692,7 +704,7 @@ case "${1:-}" in
|
|
|
692
704
|
run_resolve_plan "$@"
|
|
693
705
|
;;
|
|
694
706
|
*)
|
|
695
|
-
echo "用法: bash mcc.sh resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay> [--semantic-terms-json <JSON数组>] [--select <MCC编码> --selection-receipt <receipt>] [--input-id <USER_INPUT_ID>]"
|
|
707
|
+
echo "用法: bash mcc.sh resolve-plan --query <经营描述|MCC编码> --product-type <aipay|webpay|apppay> --root-intent <onboarding_only|full_process> [--semantic-terms-json <JSON数组>] [--select <MCC编码> --selection-receipt <receipt>] [--input-id <USER_INPUT_ID>]"
|
|
696
708
|
exit 1
|
|
697
709
|
;;
|
|
698
710
|
esac
|
|
@@ -16,7 +16,7 @@ AI 网页应用收款覆盖 PC 网页和手机浏览器/H5,接口固定 `alipa
|
|
|
16
16
|
7. **沙箱结论**:真实快速沙箱配置不得用占位值,唯一例外是 AI 按量付费沙箱 `service_id=api_mock_service_id`,且生产禁用。`CREATE_PENDING|VERIFY_PENDING` 只允许继续代码实现,阻止字段使用、摘要、后置校验、联调和付款体验。字段校验不等于支付测试;仅完整 402 链路满足 flow 才可称沙箱测试通过。
|
|
17
17
|
8. **异步通知**:AI 网页应用收款/AI 移动应用收款必须实现通知。本地无公网 HTTPS `notify_url` 时可不传并以交易查询验收,公网通知联调列为人工待验证;生产上线前须恢复通知并完成验签、幂等、关键字段校验、`success` 回写和补偿查询,否则不宣称生产就绪。
|
|
18
18
|
9. **受控页面**:授权链接仅由 `auth.sh` 按固定产品/MCC 生成,只允许 `https://aipay.alipay.com/cli-auth` 及登记参数,禁用 CLI `verification_url`;公钥页和系统 opener 只走登记脚本。失败后宿主内置浏览器只可打开已交付的同一 URL 一次;仍失败才提示手动打开,再有限轮询。禁止搜索、改写或自动操作;opener/config 写失败不算业务失败。
|
|
19
|
-
10. **对客输出**:指定 runner/renderer/脚本时,stdout 是唯一对客正文,须原文回复且不加旁白;工具输出记录、折叠面板或日志不等于已对客发送。展示命令只执行登记单条命令,禁 `2>&1`、管道、`grep/sed/awk/tee`、临时包装或拆回 `jq/printf/renderer`。除 `self_update.mjs` 的 `SELF_UPDATE:*` stderr 终态外,内部事实行均以 `ALIPAY_AIPAY_INTERNAL:` 开头;宿主合并输出时仍整行剔除,严禁对客。`integration.start.confirm` 和 `
|
|
19
|
+
10. **对客输出**:指定 runner/renderer/脚本时,stdout 是唯一对客正文,须原文回复且不加旁白;工具输出记录、折叠面板或日志不等于已对客发送。展示命令只执行登记单条命令,禁 `2>&1`、管道、`grep/sed/awk/tee`、临时包装或拆回 `jq/printf/renderer`。除 `self_update.mjs` 的 `SELF_UPDATE:*` stderr 终态外,内部事实行均以 `ALIPAY_AIPAY_INTERNAL:` 开头;宿主合并输出时仍整行剔除,严禁对客。`integration.start.confirm`、`onboarding.plan.confirm`、`sandbox.configuration.pending`、`sandbox.environment.summary`、`integration.safety.closeout` 和 `integration.checklist.result` 成功渲染时必须各自产生唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=<messageId>`;下一动作先将剔除内部行后的 stdout 原文作为独立可见消息送达,不得以工具面板、折叠输出、进度话术或最终答复代替,也不得在送达前继续调用工具。送达后同回合按 flow 继续,不等待回复。成功沙箱准备 `READY` 时 stdout 仍按 flow 静默,不构成交付消息;只有待配置正文和后置摘要需要交付。所有 `postRenderHintType=scanReturn` 的页面消息都是交付屏障(当前为 `auth.page`、`application.key.page`):先独立送达页面 stdout,再执行受控 opener 和有限轮询,不合并 pending/收口;不要求确认。阻塞正文后等待;剔除内部行后正文为空则直接转移。
|
|
20
20
|
11. **确定性转移**:固定脚本终态后立即转移;只执行动作处登记命令,禁止追加 `jq/cat/grep/curl` 或临时脚本重复解析。失败只走登记恢复;项目自检不绕过 Skill 脚本或打印敏感配置。
|
|
21
21
|
|
|
22
22
|
## 标准消息
|
|
@@ -58,7 +58,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" render <messageId> --va
|
|
|
58
58
|
|
|
59
59
|
`start-run` 只在 `root_intent + product_type` 都唯一确定后创建或复用 `run_id`,并把 `clarify_intent` 作为新 run 的第一条事件上报;产品尚未唯一确定时不创建 `run_id`。后续用户输入只按当前 active run 的 `user_input_after_clarify_intent` 计数,确认回复、补材料、候选选择和中途插话都按一次输入计,`summary` 收口后不再计入当前 run。阻塞确认统一通过 `reply confirm --reply "$USER_REPLY" --input-id "$USER_INPUT_ID"`,该 runner 只登记一次用户输入,不再使用旧 phase 计数。Agent 每收到一条聊天框用户消息,都必须先分配不含消息内容的 `USER_INPUT_ID`,执行一次 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry count-user-input --input-id "$USER_INPUT_ID"`,再解释、分类、路由、调用 runner 或回复;不论消息是否与 Skill 相关,文字、图片/文件、空白、确认和中途插话都执行。重复同一 `USER_INPUT_ID` 不加计;登记 runner 携带的同一 `--input-id` 只是兼容兜底,不是另一条计数。由于宿主聊天总入口不在本仓库,Skill 无法从未交给 Agent 的宿主消息中自行恢复计数,Agent 收到消息后的这条前置命令是完整统计所必需的唯一动作。`c4` 只承载 `user_input_after_clarify_intent`、`root_intent` 和 `progress_pct`。不新增业务确认点或独立上报;当前实现将事件先同步写入本地 outbox,再启动 detached worker 异步上传,失败保留 outbox 并不影响业务收口;维护诊断/outbox/上传/flush 见 `normal/telemetry.md`。
|
|
60
60
|
|
|
61
|
-
三种入口均只在无法确定产品时执行 `product-clarify` runner;产品明确但缺 MCC 用 `mcc-clarify
|
|
61
|
+
三种入口均只在无法确定产品时执行 `product-clarify` runner;产品明确但缺 MCC 用 `mcc-clarify`,且必须携带当前 `ROOT_INTENT`,由 runner 先创建或复用正式 telemetry run。已有经营描述、名称或编码时只执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" mcc resolve-plan --query "$MCC_SEARCH_QUERY" --product-type "$PRODUCT_TYPE" --root-intent "$ROOT_INTENT" [--semantic-terms-json "$MCC_SEMANTIC_TERMS_JSON"] --input-id "$USER_INPUT_ID"`。`ROOT_INTENT` 缺失或非法时 runner 必须停止,禁止依赖跨进程环境变量静默推断或在没有正式 run 的情况下继续 MCC 查询。非精确编码时,Agent 在首次调用中最多补充 12 个有原话依据的行业概念、经营对象或同义表达,只传概念、不传 MCC 编码且不新增确认;禁止硬编码映射、全表判断、远程语义或手拼候选。runner 按 Onboarding entry 严格校验当前产品 `queryMcc` 目录、联合排序原话与语义证据,只为命中且 `needSpecialQual=true` 的候选调用一次 `batchQueryMcc`,并复用有效的同 run/产品候选快照。
|
|
62
62
|
|
|
63
63
|
代码开发或完整接入缺项目位置/服务端语言时,使用 `integration.context.required` 或 `integration.project_path.required` 标准消息;框架缺失不触发补问。先区分新建/复用,`PROJECT_INPUT` 保留原话。Agent 确定两类项目的真实 `PROJECT_PATH`,以 `resolve-project --project-path "$PROJECT_PATH" --intent <existing|new>` 交 runner 校验;`PROJECT_INPUT` 不得代替路径。默认新建也先选安全路径并显式传入。现有项目位置未知时先定位候选;路径经 `resolve-project` 后再用 `framework-resolve`。补齐前不初始化、装依赖或改文件。
|
|
64
64
|
|