@alipay/alipay-aipay 1.8.0 → 1.8.2

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 (72) hide show
  1. package/package.json +3 -3
  2. package/skill/VERSION +1 -1
  3. package/skill/references/integration/flow.md +21 -15
  4. package/skill/references/integration/modules/checklist.md +10 -8
  5. package/skill/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  6. package/skill/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  7. package/skill/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
  8. package/skill/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  9. package/skill/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  10. package/skill/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +3 -1
  11. package/skill/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  12. package/skill/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  13. package/skill/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +6 -2
  14. package/skill/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  15. package/skill/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  16. package/skill/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
  17. package/skill/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  18. package/skill/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  19. package/skill/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +8 -3
  20. package/skill/references/integration/modules/interface-contract/aipay-interface-contract.md +3 -1
  21. package/skill/references/integration/modules/interface-contract/apppay-interface-contract.md +4 -4
  22. package/skill/references/integration/modules/interface-contract/common-trade-contract.md +8 -8
  23. package/skill/references/integration/modules/interface-contract/notify-url-contract.md +12 -11
  24. package/skill/references/integration/modules/interface-contract/webpay-interface-contract.md +3 -3
  25. package/skill/references/integration/modules/interface-guide.md +1 -1
  26. package/skill/references/integration/modules/sandbox/a2m-sandbox-test.md +4 -4
  27. package/skill/references/integration/modules/sandbox/sandbox-setup-guide.md +10 -8
  28. package/skill/references/normal/conversation-telemetry.md +1 -1
  29. package/skill/references/normal/integration-worker.md +2 -2
  30. package/skill/references/normal/json/customer-messages.json +1 -1
  31. package/skill/references/normal/json/policy-rules.json +1 -1
  32. package/skill/references/normal/scripts/integration_message_runner.mjs +7 -2
  33. package/skill/references/normal/scripts/onboarding_message_runner.mjs +9 -5
  34. package/skill/references/normal/scripts/render_customer_message.mjs +145 -48
  35. package/skill/references/onboarding/flow.md +12 -6
  36. package/skill/references/runtime-entry.md +3 -1
  37. package/skill-pre/VERSION +1 -1
  38. package/skill-pre/references/integration/flow.md +28 -19
  39. package/skill-pre/references/integration/modules/checklist.md +12 -8
  40. package/skill-pre/references/integration/modules/code-examples/csharp/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  41. package/skill-pre/references/integration/modules/code-examples/csharp/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  42. package/skill-pre/references/integration/modules/code-examples/csharp/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
  43. package/skill-pre/references/integration/modules/code-examples/java/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  44. package/skill-pre/references/integration/modules/code-examples/java/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  45. package/skill-pre/references/integration/modules/code-examples/java/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemoController.md +3 -1
  46. package/skill-pre/references/integration/modules/code-examples/nodejs/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  47. package/skill-pre/references/integration/modules/code-examples/nodejs/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  48. package/skill-pre/references/integration/modules/code-examples/nodejs/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +6 -2
  49. package/skill-pre/references/integration/modules/code-examples/php/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  50. package/skill-pre/references/integration/modules/code-examples/php/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  51. package/skill-pre/references/integration/modules/code-examples/php/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +3 -1
  52. package/skill-pre/references/integration/modules/code-examples/python/2-/347/275/221/347/253/231/346/224/257/344/273/230//347/273/237/344/270/200/346/224/266/345/215/225/344/270/213/345/215/225/345/271/266/346/224/257/344/273/230/351/241/265/351/235/242/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  53. package/skill-pre/references/integration/modules/code-examples/python/3-APP/346/224/257/344/273/230/APP/346/224/257/344/273/230/346/216/245/345/217/243/344/273/243/347/240/201/347/244/272/344/276/213.md +1 -1
  54. package/skill-pre/references/integration/modules/code-examples/python/4-/346/214/211/351/207/217/344/273/230/350/264/271/A2MPaymentDemo.md +8 -3
  55. package/skill-pre/references/integration/modules/interface-contract/aipay-interface-contract.md +3 -1
  56. package/skill-pre/references/integration/modules/interface-contract/apppay-interface-contract.md +4 -4
  57. package/skill-pre/references/integration/modules/interface-contract/common-trade-contract.md +8 -8
  58. package/skill-pre/references/integration/modules/interface-contract/notify-url-contract.md +12 -11
  59. package/skill-pre/references/integration/modules/interface-contract/webpay-interface-contract.md +3 -3
  60. package/skill-pre/references/integration/modules/interface-guide.md +1 -1
  61. package/skill-pre/references/integration/modules/sandbox/a2m-sandbox-test.md +4 -4
  62. package/skill-pre/references/integration/modules/sandbox/sandbox-setup-guide.md +11 -9
  63. package/skill-pre/references/normal/full-process-routing.md +2 -2
  64. package/skill-pre/references/normal/integration-worker.md +2 -2
  65. package/skill-pre/references/normal/json/customer-messages.json +1 -1
  66. package/skill-pre/references/normal/json/policy-rules.json +1 -1
  67. package/skill-pre/references/normal/scripts/integration_message_runner.mjs +7 -2
  68. package/skill-pre/references/normal/scripts/onboarding_message_runner.mjs +9 -5
  69. package/skill-pre/references/normal/scripts/render_customer_message.mjs +150 -48
  70. package/skill-pre/references/normal/windows-environment.md +4 -4
  71. package/skill-pre/references/onboarding/flow.md +12 -6
  72. package/skill-pre/references/runtime-entry.md +5 -3
@@ -1084,14 +1084,17 @@ async function runMaterialCollect(args) {
1084
1084
  }, { productType });
1085
1085
  }
1086
1086
 
1087
- function renderApplicationCandidates(applicationType, applicationCandidates, selectionState = 'initial') {
1087
+ function renderApplicationCandidates(applicationType, applicationCandidates, selectionState = 'initial', includeIntro = selectionState === 'initial') {
1088
1088
  const onlineCount = applicationCandidates.filter((candidate) => candidate?.status === 'ON_LINE').length;
1089
1089
  const variant = applicationCandidates.length === 0
1090
1090
  ? 'EMPTY'
1091
1091
  : onlineCount === 0
1092
1092
  ? 'PENDING_ONLY'
1093
1093
  : 'ONLINE_WITH_OPTIONAL_PENDING';
1094
- const facts = renderMessage('application.candidates.facts', variant, { applicationType, applicationCandidates });
1094
+ const candidateFacts = renderMessage('application.candidates.facts', variant, { applicationType, applicationCandidates });
1095
+ const facts = includeIntro
1096
+ ? `${renderMessage('application.configuration.intro', 'DEFAULT', {})}\n\n${candidateFacts}`
1097
+ : candidateFacts;
1095
1098
  if (applicationCandidates.length === 0) return facts;
1096
1099
  const selectionVariant = `${onlineCount === 0 ? 'PENDING' : 'ONLINE'}_${applicationType === 'WEBAPP' ? 'WEB' : 'MOBILE'}_OR_NEW`;
1097
1100
  const selection = renderMessage('application.candidate.select', selectionVariant, {});
@@ -1187,8 +1190,8 @@ async function runApplicationRecheck(args) {
1187
1190
  const previousCanonical = canonicalCandidates(input.previousCandidates);
1188
1191
  const currentCanonical = canonicalCandidates(input.currentCandidates);
1189
1192
  // Rendering both snapshots applies the same content and sensitivity checks even on the silent path.
1190
- renderApplicationCandidates(applicationType, input.previousCandidates);
1191
- const output = renderApplicationCandidates(applicationType, input.currentCandidates);
1193
+ renderApplicationCandidates(applicationType, input.previousCandidates, 'initial', false);
1194
+ const output = renderApplicationCandidates(applicationType, input.currentCandidates, 'initial', false);
1192
1195
  if (previousCanonical === currentCanonical) {
1193
1196
  process.stderr.write(`${internalPrefix}APPLICATION_RECHECK_RESULT=UNCHANGED\n`);
1194
1197
  return '';
@@ -1256,10 +1259,11 @@ function closeoutInputFromArgs(args) {
1256
1259
  };
1257
1260
  const optionalMapping = {
1258
1261
  'sandbox-config-state': 'sandboxConfigState',
1262
+ 'sandbox-summary': 'sandboxSummary',
1259
1263
  'manual-verification-items': 'manualVerificationItems'
1260
1264
  };
1261
1265
  for (const [argName, fieldName] of Object.entries(optionalMapping)) {
1262
- if (Object.prototype.hasOwnProperty.call(args, argName)) input[fieldName] = required(args, argName);
1266
+ if (Object.prototype.hasOwnProperty.call(args, argName)) input[fieldName] = argName === 'sandbox-summary' ? optional(args, argName) : required(args, argName);
1263
1267
  }
1264
1268
  return input;
1265
1269
  }
@@ -6,6 +6,7 @@ import path from 'node:path';
6
6
  import process from 'node:process';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  import { currentRunContext, emitMessageMetric } from './telemetry.mjs';
9
+ import { isWindowsPlatform } from './platform_compat.mjs';
9
10
 
10
11
  const scriptDir = path.dirname(fileURLToPath(import.meta.url));
11
12
  const normalDir = path.resolve(scriptDir, '..');
@@ -18,7 +19,7 @@ const placeholderPattern = /\{\{([A-Za-z][A-Za-z0-9_]*)\}\}/g;
18
19
  const allowedVariableTypes = new Set([
19
20
  'applicationCandidates',
20
21
  'command', 'customerErrorDetails', 'customerErrorText', 'enum', 'enumList', 'existingPath', 'mccCode', 'officialTemporaryUrl', 'path',
21
- 'runtimeUrl', 'sandboxCredential', 'sandboxTableRows', 'serviceCandidates', 'mccCandidates', 'singleLine', 'string'
22
+ 'runtimeUrl', 'sandboxCredential', 'sandboxTableRows', 'sandboxSummary', 'serviceCandidates', 'mccCandidates', 'singleLine', 'string'
22
23
  ]);
23
24
 
24
25
  function allowedVariableNames(definitions) {
@@ -547,6 +548,9 @@ function validateValue(definition, value, policy) {
547
548
  case 'sandboxCredential':
548
549
  if (value.length > 256 || /[\r\n]/.test(value)) throw new Error(`变量 ${definition.name} 不是合法沙箱凭据`);
549
550
  break;
551
+ case 'sandboxSummary':
552
+ if (value.length > 12000 || /[\u0000-\u0009\u000b-\u001f\u007f]/u.test(value)) throw new Error('沙箱摘要包含非法内容');
553
+ break;
550
554
  case 'sandboxTableRows':
551
555
  if (value.length > 4096 || !value.split('\n').every((line) => /^\| [^|]+ \| [^|]+ \|$/.test(line))) {
552
556
  throw new Error(`变量 ${definition.name} 不是合法沙箱摘要行`);
@@ -806,70 +810,137 @@ function validateWriteConfirmation(variantName, variables, normalized) {
806
810
  validateServicePayload(variables, normalized);
807
811
  }
808
812
 
813
+ // Replay only the registered sandbox summary already delivered in this conversation.
814
+ // No config contents, keys, commands or free-form Markdown are accepted here.
815
+ function sandboxReplayBlock(original, productName, sandboxConfigState) {
816
+ // This optional display must never prevent delivery of the actual branch results.
817
+ try {
818
+ if (typeof original !== 'string' || !original || productName !== 'AI 网页应用收款') return '';
819
+ if (sandboxConfigState !== 'READY') return '';
820
+ const lines = original.trim().split('\n');
821
+ const configPath = lines[5]?.match(/^\| 配置文件目录 \| `([^`]+)` \|$/u)?.[1];
822
+ const environmentRows = lines.slice(6, 10).join('\n');
823
+ if (!configPath) throw new Error('必须复用本轮登记的完整沙箱摘要');
824
+ const input = { productName, configPath, environmentRows };
825
+ const summary = renderMessage('sandbox.environment.summary', 'DEFAULT', input);
826
+ const normalize = (text) => text.trim().replace(/\n{2,}/gu, '\n\n');
827
+ const valid = ['DEFAULT', 'WINDOWS'].some((variant) => {
828
+ const reminder = renderMessage('sandbox.environment.reminder', variant, {});
829
+ return normalize(original) === normalize(`${summary}\n\n${reminder}`)
830
+ || normalize(original) === normalize(`${summary}\n${reminder}`);
831
+ });
832
+ if (!valid) throw new Error('沙箱摘要不匹配登记正文,禁止改写或追加内容');
833
+ return renderMessage('sandbox.environment.summary', 'FINAL', input);
834
+ } catch {
835
+ return '';
836
+ }
837
+ }
838
+
839
+ function productionConfigSourceLines() {
840
+ return [
841
+ '1、确认上线条件:',
842
+ '- 前往支付宝 AI 付站点(https://aipay.alipay.com/?from=alipay-aipay-skill)→ 一站式接入,查看产品开通情况。',
843
+ '- 如本次流程新建支付宝应用,进入一站式接入 → 选择产品 → 密钥配置,确认新建的支付宝应用“已上线”;使用其他生产应用时,也需确认该应用已上线。',
844
+ '',
845
+ '2、生产环境的支付宝应用配置替换到项目中:',
846
+ '- 修改项目中的支付宝网关为 https://openapi.alipay.com/gateway.do。',
847
+ '- 把生产环境支付宝应用配置写入业务系统生产环境变量、受保护配置文件或密钥管理系统。',
848
+ '- appId、支付宝公钥、应用私钥需要配到项目中。应用私钥不要泄露、不要暴露给 Agent;应用公钥用于在支付宝侧配置,无需额外配到项目中。',
849
+ '- 确保应用公钥与应用私钥配对,appId、该应用公钥及对应的支付宝公钥与目标生产应用配置一致,不混用沙箱或其他应用的配置。',
850
+ ];
851
+ }
852
+
809
853
  function productionSpecificLines(productName) {
810
854
  if (productName === 'AI 按量付费') {
811
855
  return [
812
- '4. AI 按量付费 `serviceId`:把沙箱 `api_mock_service_id` 替换为真实 `serviceId`,`serviceId` 获取方式是:登录支付宝 AI 付站点(https://aipay.alipay.com/?from=alipay-aipay-skill) → 控制台 → 服务管理 → 复制审核已通过的目标服务 ID。',
813
- '5. AI 按量付费商户标识:`seller_id`/`seller_unique_id` 填收款商户 PID/2088,PID 获取方式是:登录支付宝商家平台(https://b.alipay.com/page/portal/home) → 点击头像 → 复制账户名下方 2088 开头的商家 ID;`seller_app_id` 填生产 `appId`。',
814
- '6. AI 按量付费验收:A2M 不使用 `notify_url`;上线前用生产应用私钥重新签名 402 账单,并验证 `Payment-Proof`、金额/订单/资源一致、`trade_no` 防重复履约和 `alipay.aipay.agent.fulfillment.confirm` 异步回执。'
815
- ];
816
- }
817
- if (productName === 'AI 移动应用收款') {
818
- return [
819
- '4. AI 移动应用收款 `notify_url`:生成生产 `orderStr` 时传入商家已部署的公网 HTTPS `notify_url`;未传不会触发异步通知。',
820
- '5. AI 移动应用收款验收:`notify_url` 完成验签,校验 `app_id`/`out_trade_no`/`total_amount`/`trade_status`,幂等处理并返回 `success`;支付结果以异步通知或 `alipay.trade.query` 补偿查询为准。客户端 SDK 使用服务端 `orderStr` 调起支付,客户端结果只做展示,不能作为付款成功依据。'
856
+ '', '3、AI 按量付费服务配置:',
857
+ '- 把沙箱 `api_mock_service_id` 替换为真实 `serviceId`。获取方式:登录支付宝 AI 付站点(https://aipay.alipay.com/?from=alipay-aipay-skill)→ 控制台 → 服务管理 → 复制审核已通过的目标服务 ID。',
858
+ '- `seller_id`/`seller_unique_id` 填收款商户 PID/2088,`seller_app_id` 填生产 `appId`。PID 获取方式:登录支付宝商家平台(https://b.alipay.com/page/portal/home)→ 点击头像 → 复制账户名下方 2088 开头的商家 ID。',
821
859
  ];
822
860
  }
861
+ const mobile = productName === 'AI 移动应用收款';
823
862
  return [
824
- '4. AI 网页应用收款 `notify_url`:生产下单时传入商家已部署的公网 HTTPS `notify_url`;该地址是商家后端通知地址,不是支付宝生成的 URL。',
825
- '5. AI 网页应用收款验收:`notify_url` 完成验签,校验 `app_id`/`out_trade_no`/`total_amount`/`trade_status`,幂等处理并返回 `success`;支付结果以异步通知或 `alipay.trade.query` 补偿查询为准,同步回跳或前台页面不能作为付款成功依据。',
826
- '6. AI 网页应用收款限制:如需解除 AI 网页应用收款的收款限制,请前往 支付宝商家平台 - 签约管理 补全收款信息:https://b.alipay.com/page/ar-center/ar-manage'
863
+ '', `3、${productName}支付结果确认:`,
864
+ '- `notify_url` 用于商家服务端接收支付宝发来的支付结果异步通知,不是前端页面或支付宝生成的 URL。',
865
+ '- 如使用异步通知,下单时传入 `notify_url`;它应是商家已部署、支付宝服务端可通过公网访问的 HTTPS 通知接口地址。',
866
+ '- 如不配置 `notify_url`,不会触发该地址的异步通知;商家服务端需通过 `alipay.trade.query` 主动查单。',
867
+ mobile
868
+ ? '- 支付结果以验签通过的异步通知或服务端交易查询结果为准;APP 客户端支付结果不能单独作为付款成功依据。'
869
+ : '- 支付结果以验签通过的异步通知或 `alipay.trade.query` 查询结果为准;同步回跳或前台页面不能作为付款成功依据。',
870
+ '- 项目正式对客前,请完成生产环境支付验证。',
871
+ ...(mobile ? [] : ['', '4、AI 网页应用收款限制:', '- 如需解除 AI 网页应用收款的收款限制,请前往支付宝商家平台 → 签约管理补全收款信息:https://b.alipay.com/page/ar-center/ar-manage'])
827
872
  ];
828
873
  }
829
874
 
830
- function productionConfigSourceLines() {
831
- return [
832
- '1. 产品开通确认:前往支付宝 AI 付站点查看产品开通情况(https://aipay.alipay.com/?from=alipay-aipay-skill)。',
833
- '2. 应用上线确认:前往支付宝 AI 付站点“一站式接入 → 选择产品 → 密钥配置”,确认目标支付宝应用“已上线”。',
834
- '3. 替换项目中支付宝应用配置为生产:把生产环境的支付宝应用配置写入业务系统环境变量、受保护配置文件或密钥管理系统。确保 appId、应用私钥、支付宝公钥同属一套生产环境支付宝应用,同时修改项目中的支付宝网关为生产网关:https://openapi.alipay.com/gateway.do。'
835
- ];
875
+ function summaryItems(value) {
876
+ if (!value || value === '无') return [];
877
+ let items = [value];
878
+ if (value.trim().startsWith('[')) {
879
+ try {
880
+ const parsed = JSON.parse(value);
881
+ if (Array.isArray(parsed) && parsed.every((item) => typeof item === 'string')) items = parsed;
882
+ } catch { /* Preserve validated plain text. */ }
883
+ }
884
+ return [...new Set(items.flatMap((item) => item.split(';')).map((item) => item.trim()).filter(Boolean))];
885
+ }
886
+
887
+ // Completion inputs contain actual gaps only; reminders are delivered elsewhere.
888
+ function validateChecklistItemClassification(variables, fields) {
889
+ const notifyReminders = new Set([
890
+ '公网 HTTPS notify_url 联调人工待验证:上线前配置公网通知地址并完成验签联调',
891
+ '公网 HTTPS notify_url 联调待部署后验证'
892
+ ]);
893
+ for (const field of fields) {
894
+ const value = variables[field];
895
+ const items = summaryItems(value);
896
+ if (value && value !== '无' && items.length === 0) {
897
+ throw new Error(`${field} 没有实际缺口时必须传“无”,不能使用空列表影响完成判定`);
898
+ }
899
+ for (const item of items) {
900
+ if (notifyReminders.has(item) || /^沙箱付款待用户体验(?::.*)?$/u.test(item)) {
901
+ throw new Error(`${field} 只能包含实际缺口;通用通知地址提醒和可选沙箱付款体验不计入完成判定。请重新分类并按实际证据填写结果,不重跑已完成检查`);
902
+ }
903
+ }
904
+ }
836
905
  }
837
906
 
838
907
  function productionReadinessBlock(productName, context) {
839
908
  const statusLines = [];
840
- if (!context.productBranchesComplete) {
909
+ if (context.integrationOnly) {
910
+ statusLines.push('- 本轮仅进行代码开发;上线前请确认生产配置并完成验证。');
911
+ } else if (!context.productBranchesComplete) {
841
912
  statusLines.push('- 还不能正式收款,产品签约、服务市场或应用发布仍有上表待办。');
842
913
  }
843
914
  if (context.integrationResult === '不在本轮执行范围') {
844
915
  statusLines.push('- 本轮只完成产品开通流程收口,不代表业务系统已经具备收款代码;先完成支付产品-代码开发、项目部署和生产参数验收。');
845
916
  } else if (context.integrationResult === '部分完成,沙箱配置待完成') {
846
- statusLines.push('- 代码开发仍有沙箱配置缺口;可继续产品开通流程,但不能进入真实生产收款。');
917
+ statusLines.push('- 沙箱配置尚未完成,相关测试未执行;后续上线条件按生产配置和实际验证结果另行确认。');
847
918
  } else if (context.integrationResult === '部分完成,人工待验证') {
848
919
  statusLines.push('- 代码开发还有人工待验证项;完成后才能判断是否可进入真实生产上线。');
920
+ } else if (context.integrationResult === '未通过' && !(context.integrationOnly && context.failedItems && context.failedItems !== '无')) {
921
+ statusLines.push('- 代码开发仍有未完成项,请先按本轮校验结果修复。');
849
922
  }
850
- if (statusLines.length > 0) {
851
- return [
852
- '【当前状态】',
853
- ...statusLines,
854
- '',
855
- '【上线前有以下关键点】',
856
- ...productionConfigSourceLines(),
857
- ...productionSpecificLines(productName),
858
- '',
859
- '【提示】',
860
- '- 如找不到配置替换位置,可以试试对 Agent 说:“我要上线了,帮我找一下项目里支付宝生产配置应该改哪些地方”。让 Agent 定位文件/变量名,但不要把生产应用私钥、账号密码、支付凭证或未脱敏通知内容直接发给 Agent。'
861
- ].join('\n');
923
+ if (context.integrationOnly && context.failedItems && context.failedItems !== '无') {
924
+ statusLines.push(`- ${context.failedItems}`);
862
925
  }
926
+ const integrationGapAlreadyShown = context.productBranchesComplete && ['部分完成,人工待验证', '部分完成,沙箱配置待完成'].includes(context.integrationResult);
927
+ if (context.remainingActions && context.remainingActions !== '无' && !integrationGapAlreadyShown) {
928
+ statusLines.push(...summaryItems(context.remainingActions).map((item) => `- 下一步:${item}`));
929
+ }
930
+ if (statusLines.length === 0) {
931
+ statusLines.push('- 代码开发和产品开通流程已完成,但当前 Agent 没有替你切生产配置,也不会默认发起真实生产交易。');
932
+ }
933
+ const manualItems = summaryItems(context.manualVerificationItems);
934
+ const manualLines = manualItems.length
935
+ ? ['', '上线前请完成本轮尚未验证的项目:', ...manualItems.map((item) => `- ${item}`)]
936
+ : [];
863
937
  return [
864
- '【当前状态】',
865
- '- 代码开发和产品开通流程已完成,但当前 Agent 没有替你切生产配置,也不会默认发起真实生产交易。',
866
- '',
867
- '【上线前有以下关键点】',
868
- ...productionConfigSourceLines(),
869
- ...productionSpecificLines(productName),
870
- '',
938
+ '【当前状态】', ...statusLines, '',
939
+ ...(context.sandboxBlock ? [context.sandboxBlock, ''] : []),
940
+ '【上线前有以下关键点】', '',
941
+ ...productionConfigSourceLines(), ...productionSpecificLines(productName), ...manualLines, '',
871
942
  '【提示】',
872
- '- 如找不到配置替换位置,可以试试对 Agent 说:“我要上线了,帮我找一下项目里支付宝生产配置应该改哪些地方”。让 Agent 定位文件/变量名,但不要把生产应用私钥、账号密码、支付凭证或未脱敏通知内容直接发给 Agent。'
943
+ '- 如找不到项目上线前生产配置的替换位置,可以试试对 Agent 说:“我要上线了,帮我找一下项目里支付宝生产配置要改哪些地方”。让 Agent 帮助您定位文件/变量名,但不要把生产应用私钥、账号密码、支付凭证或未脱敏通知内容直接发给 Agent。'
873
944
  ].join('\n');
874
945
  }
875
946
 
@@ -1358,7 +1429,12 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1358
1429
  }
1359
1430
  validateVariantInputShape(messageId, variantName, variables);
1360
1431
  for (const definition of message.variables) {
1361
- normalized[definition.name] = definition.derived ? '' : validateValue(definition, variables[definition.name], policy);
1432
+ if (definition.name === 'sandboxSummary') {
1433
+ try { normalized.sandboxSummary = validateValue(definition, variables.sandboxSummary, policy); }
1434
+ catch { normalized.sandboxSummary = ''; }
1435
+ } else {
1436
+ normalized[definition.name] = definition.derived ? '' : validateValue(definition, variables[definition.name], policy);
1437
+ }
1362
1438
  }
1363
1439
  } catch (error) {
1364
1440
  throw addManagedEntrypointHint(messageId, error);
@@ -1377,6 +1453,14 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1377
1453
  if (messageId === 'onboarding.mcc.candidates') {
1378
1454
  normalized.candidateTable = mccCandidateTable(variantName, variables.mccCandidates, telemetryContext.productType);
1379
1455
  }
1456
+ if (messageId === 'sandbox.environment.summary' && variantName === 'FINAL') {
1457
+ if (variables.productName !== 'AI 网页应用收款') throw new Error('最终沙箱测试配置仅适用于 AI 网页应用收款');
1458
+ const buyerRows = variables.environmentRows.split('\n').slice(1);
1459
+ if (buyerRows.some((row) => row.includes('已写入本地配置文件,默认不在对话中展开'))) {
1460
+ throw new Error('网页收款最终沙箱测试配置必须展示已校验的买家密码明文');
1461
+ }
1462
+ normalized.sandboxBuyerRows = buyerRows.join('\n');
1463
+ }
1380
1464
  if (messageId === 'application.operation.result') {
1381
1465
  if (variantName === 'ALIPAY_PUBLIC_KEY_MANUAL_CONFIGURATION') {
1382
1466
  if (variables.actualStatus !== '需人工配置') {
@@ -1472,6 +1556,7 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1472
1556
  }[variables.integrationStatus];
1473
1557
  }
1474
1558
  if (messageId === 'integration.checklist.result') {
1559
+ validateChecklistItemClassification(variables, ['failedItems', 'manualItems']);
1475
1560
  const sandboxPending = variables.sandboxConfigState !== 'READY';
1476
1561
  const hasBlockingDefect = variables.blockingDefectState === 'PRESENT';
1477
1562
  if (variantName === 'AIPAY' && !variables.sandboxResult) throw new Error('AI 按量付费 checklist 缺少沙箱联调结果');
@@ -1489,6 +1574,10 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1489
1574
  ? '代码开发自动校验已完成,仍有人工待验证项;本轮继续产品开通。'
1490
1575
  : '代码开发校验通过后将自动进入支付产品-产品开通;未通过时停留在代码开发。';
1491
1576
  if (variables.nextFlowReminder !== expectedReminder) throw new Error('代码开发执行模式与后续衔接不一致');
1577
+ if (variables.executionMode === '完整接入' && isWindowsPlatform()
1578
+ && process.env.ALIPAY_AIPAY_WINDOWS_ROUTE === 'CODE_ONLY') {
1579
+ normalized.nextFlowReminder = derivedCatalogText(definitions, 'windowsCodeOnlyReminder');
1580
+ }
1492
1581
  if (variables.overallResult === '通过' && (hasFailedItems || hasManualItems)) {
1493
1582
  throw new Error('代码开发结果为通过时不得存在未通过项或人工待验证项');
1494
1583
  }
@@ -1528,6 +1617,19 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1528
1617
  if (manualOnly) {
1529
1618
  normalized.failedItems = `人工待验证项未完成:${normalized.manualItems}`;
1530
1619
  }
1620
+ normalized.checklistDetails = variables.executionMode === '仅代码开发'
1621
+ ? ''
1622
+ : `未完成项:${normalized.failedItems}\n人工待验证:${normalized.manualItems}`;
1623
+ const productName = { AIPAY: 'AI 按量付费', WEBPAY: 'AI 网页应用收款', APPPAY: 'AI 移动应用收款' }[variantName];
1624
+ normalized.launchGuidance = variables.executionMode === '仅代码开发'
1625
+ ? productionReadinessBlock(productName, {
1626
+ productBranchesComplete: false,
1627
+ integrationOnly: true,
1628
+ failedItems: variables.failedItems,
1629
+ integrationResult: variables.overallResult === '通过' ? '已完成' : sandboxPending ? '部分完成,沙箱配置待完成' : hasBlockingDefect ? '未通过' : '部分完成,人工待验证',
1630
+ manualVerificationItems: variables.manualItems,
1631
+ sandboxBlock: sandboxReplayBlock(normalized.sandboxSummary, productName, variables.sandboxConfigState)
1632
+ }) : '';
1531
1633
  }
1532
1634
  if (messageId === 'materials.category.collect') {
1533
1635
  const expectedStatus = {
@@ -1579,6 +1681,7 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1579
1681
  normalized.specialQualificationHint = variables.specialQualificationHint || '';
1580
1682
  }
1581
1683
  if (messageId === 'process.partial_result') {
1684
+ validateChecklistItemClassification(variables, ['remainingActions', 'manualVerificationItems']);
1582
1685
  const statusQueryHintDefinition = definitions.get('statusQueryHint');
1583
1686
  const statusQueryHint = statusQueryHintDefinition?.values?.[0];
1584
1687
  if (!statusQueryHintDefinition?.derived || !statusQueryHint) {
@@ -1601,12 +1704,10 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1601
1704
  if (onboardingOnly) {
1602
1705
  if (variables.sandboxConfigState !== undefined) throw new Error('onboarding_only 禁止传入代码开发沙箱状态');
1603
1706
  if (hasManualVerificationItems) throw new Error('onboarding_only 禁止传入代码开发人工待验证项');
1604
- normalized.manualVerificationLine = '';
1605
1707
  normalized.sandboxRecoveryHint = '';
1606
1708
  } else if (variables.integrationResult === '已完成') {
1607
1709
  if (variables.sandboxConfigState !== 'READY') throw new Error('完整代码开发结果必须绑定 READY 沙箱状态');
1608
1710
  if (hasManualVerificationItems) throw new Error('代码开发已完成时禁止传入人工待验证项');
1609
- normalized.manualVerificationLine = '';
1610
1711
  normalized.sandboxRecoveryHint = '';
1611
1712
  } else if (variables.integrationResult === '部分完成,沙箱配置待完成') {
1612
1713
  if (hasManualVerificationItems) throw new Error('沙箱待配置结果不通过人工待验证项表达');
@@ -1616,11 +1717,9 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1616
1717
  }[variables.sandboxConfigState];
1617
1718
  if (!normalized.sandboxRecoveryHint) throw new Error('沙箱待配置结果必须绑定 CREATE_PENDING 或 VERIFY_PENDING');
1618
1719
  if (variables.remainingActions === '无') throw new Error('沙箱待配置时必须保留剩余待办');
1619
- normalized.manualVerificationLine = '';
1620
1720
  } else if (variables.integrationResult === '部分完成,人工待验证') {
1621
1721
  if (variables.sandboxConfigState !== 'READY') throw new Error('人工待验证结果必须绑定 READY 沙箱状态');
1622
1722
  if (!hasManualVerificationItems) throw new Error('人工待验证结果必须列出人工待验证项');
1623
- normalized.manualVerificationLine = `人工待验证:${normalized.manualVerificationItems}`;
1624
1723
  normalized.sandboxRecoveryHint = '';
1625
1724
  } else {
1626
1725
  throw new Error('full_process 进入产品开通收口时只允许已完成、沙箱待配置或人工待验证');
@@ -1644,7 +1743,10 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1644
1743
  !hasManualVerificationItems;
1645
1744
  normalized.productionReadinessBlock = productionReadinessBlock(variables.productName, {
1646
1745
  productBranchesComplete,
1647
- integrationResult: variables.integrationResult
1746
+ remainingActions: normalized.remainingActions,
1747
+ integrationResult: variables.integrationResult,
1748
+ manualVerificationItems: variables.manualVerificationItems,
1749
+ sandboxBlock: sandboxReplayBlock(onboardingOnly ? '' : normalized.sandboxSummary, variables.productName, variables.sandboxConfigState)
1648
1750
  });
1649
1751
  const declaresComplete = variables.processResultTitle === '支付产品-产品开通已完成';
1650
1752
  if (branchesComplete !== declaresComplete) {
@@ -1657,7 +1759,7 @@ export function renderMessage(messageId, variantName, variables, telemetryContex
1657
1759
  if (messageId === 'service.create.summary') validateServiceCreateSummary(variantName, variables, normalized);
1658
1760
  if (messageId === 'onboarding.write.confirm') validateWriteConfirmation(variantName, variables, normalized);
1659
1761
  let rendered = variant.templateLines.join('\n').replace(placeholderPattern, (_, name) => normalized[name]);
1660
- if (messageId === 'application.operation.result' || messageId === 'process.partial_result' || messageId === 'error.backend' || messageId === 'error.cli') {
1762
+ if (messageId === 'application.operation.result' || messageId === 'process.partial_result' || messageId === 'integration.checklist.result' || messageId === 'sandbox.environment.summary' || messageId === 'error.backend' || messageId === 'error.cli') {
1661
1763
  rendered = normalizeProcessPartialResultSpacing(rendered);
1662
1764
  }
1663
1765
  if (message.blocking && allowedRepliesFor(catalog, message).length > 0) {
@@ -18,7 +18,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" windows-entry --root-in
18
18
 
19
19
  退出 0 只表示分流完成。必须取得唯一 `ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=<JSON>`,校验 schemaVersion=1、rootIntent 等于当前根意图、route 为 READY、BLOCKED、LEGACY 或 CODE_ONLY;非零、超时、缺失或冲突均按 BLOCKED 停止。READY 才执行本地快速沙箱和签约;BLOCKED 说明内部 `WINDOWS_ENV_RESULT` 的实际 reason/dependency 及恢复动作,等待环境修复,不能输出站点引导;LEGACY 仅用于不支持的执行映射或用户明确选择站点。后续 Windows runtime 命令附加当前 `--windows-route`;BLOCKED 不进入 bootstrap、业务 flow 或项目写入。CODE_ONLY 只放行独立代码开发,根意图和诊断原因沿用本次入口事实。修复可选工具后重新只读复检,取得唯一 READY 才恢复快速沙箱和开通动作。环境故障不关闭遥测,也不改变 SESSION_ID、run_id、计数或会话采集选择。
20
20
 
21
- `integration_only/full_process` 遇到已识别的 Git Bash、jq、CLI 或安装辅助工具缺失/运行失败,以及这些工具的有限安装、下载、哈希/签名校验或预算耗尽失败时,返回 `CODE_ONLY`。失败工具不得继续执行,校验失败的安装包不得运行。以唯一 WINDOWS_ROUTE 的 route 决定是否进入开发;WINDOWS_ENV_RESULT 的失败诊断保留实际原因,不能将其误读为业务能力可用。该分流只允许 Integration 的原生 Node 路径,默认 `VERIFY_PENDING`,跳过快速沙箱和依赖沙箱的测试,最终如实列出未完成项,不自动引导站点开通。完整接入在代码部分检查后停在 Onboarding 前,待工具恢复且复检 READY 才恢复。Node 版本不足、实际存储故障、状态损坏、回滚失败或未知错误仍为 BLOCKED;项目路径和生产配置保护要求不变。下文“失败保持 BLOCKED”对上述可选工具例外按 CODE_ONLY 处理。
21
+ `integration_only/full_process` 遇到已识别的 Git Bash、jq、CLI 或安装辅助工具缺失/运行失败,以及这些工具的有限安装、下载、哈希/签名校验或预算耗尽失败时,返回 `CODE_ONLY`。失败工具不得继续执行,校验失败的安装包不得运行。以唯一 WINDOWS_ROUTE 的 route 决定是否进入开发;WINDOWS_ENV_RESULT 的失败诊断保留实际原因,不能将其误读为业务能力可用。该分流沿用 Integration 的原生 Node 路径,沙箱默认 `VERIFY_PENDING`,跳过快速沙箱;用户主动提供完整有效手工资料并写入、校验项目配置后,可记沙箱 `READY`,无需先将环境分流恢复为 READY。各测试按自身实际依赖执行:缺失工具所依赖的动作仍不能运行;原生 Python 402 联调不依赖 Git Bash,但仍须 Python、curl、服务可访问、沙箱配置等前置就绪。最终如实列出未完成项,不自动引导站点开通。完整接入在代码部分检查后停在 Onboarding 前,待工具恢复且复检 READY 才恢复。Node 版本不足、实际存储故障、状态损坏、回滚失败或未知错误仍为 BLOCKED;项目路径和生产配置保护要求不变。下文“失败保持 BLOCKED”对上述可选工具例外按 CODE_ONLY 处理。
22
22
 
23
23
  CODE_ONLY 后用户已自行修好环境时,按原根意图执行上述 `windows-entry` 只读复检;明确授权准备时附加 `--prepare-authorized true`,只有明确修复后重试才再附加 `--repair-confirmed true`,沿用原有分阶段预算。唯一 READY 才恢复快速沙箱和开通能力;仍为 CODE_ONLY 时只继续独立代码开发,不反复安装。根意图变化必须按新根意图重新执行入口,不把 CODE_ONLY 当成 LEGACY 的站点选择,也不沿用旧能力事实。
24
24
 
@@ -36,9 +36,9 @@ CLI 刷新策略与非 Windows 保持同一会话预算,不锁定 0.1.7 或其
36
36
 
37
37
  初次缺 Git Bash、jq 或本机 CLI 无法启动且当前任务授权准备时,按 Git Bash → jq → 必要的 CLI 修复 → 完整复检执行。CLI 已可用时不重复安装。Git 优先复用已有可运行的 Git for Windows;缺失时优先调用用户级 winget,无法运行或未通过复检时使用 `scripts/windows/policy.json` 固定的 Git for Windows 官方 x64 安装包(当前 2.56.0.2)。官方包下载后先校验固定 SHA-256,再由系统 PowerShell 验证 Authenticode 有效,之后安装到 `%LOCALAPPDATA%/Programs/Git-Aipay-<version>`,并实测 git、bash、cygpath。下载或校验失败不运行安装包。两种来源均不可用时按根意图返回 CODE_ONLY 或 BLOCKED,展示原因及官方手工安装路径,不静默跳站点。
38
38
 
39
- jq 使用固定 1.7.1 官方资产和 SHA-256,已有健康版本直接复用;CLI 仍使用正式 PowerShell 安装器选择当前版本。每个依赖和 Git 的两种安装来源分别记录实际开始的安装尝试,确认来源前的只读探测不消耗预算;Git 的 winget 失败可在同次准备中尝试官方固定包。初次每个来源最多一次,用户明确修复后每个来源最多再一次;失败阶段可续跑,已健康的阶段不重装。状态记录不含业务材料;复检始终只读且不消耗安装预算。可选工具的网络、签名或完整性失败按第 21 行分流;实际存储故障仍为 BLOCKED。不轮换未经验证的镜像、使用 WSL、提权或修改执行策略。
39
+ jq 使用固定 1.7.1 官方资产和 SHA-256,已有健康版本直接复用;CLI 仍使用正式 PowerShell 安装器选择当前版本。每个依赖和 Git 的两种安装来源分别记录实际开始的安装尝试,确认来源前的只读探测不消耗预算;Git 的 winget 失败可在同次准备中尝试官方固定包。初次每个来源最多一次,用户明确修复后每个来源最多再一次;失败阶段可续跑,已健康的阶段不重装。状态记录不含业务材料;复检始终只读且不消耗安装预算。可选工具的网络、签名或完整性失败按[启动与分流](#启动与分流)中的 CODE_ONLY 规则分流;实际存储故障仍为 BLOCKED。不轮换未经验证的镜像、使用 WSL、提权或修改执行策略。
40
40
 
41
- 环境诊断和次数保存在 `%LOCALAPPDATA%/alipay-aipay-pre/windows/environment.json`;旧版全局次数无法归属具体安装阶段,迁移时保留阻断原因并从新版本的有限分阶段预算重新计数。锁短时占用或状态损坏时,完整工具检查通过仍可 READY;自动安装保持阻断,不删除锁或状态绕过预算。CODE_ONLY 的恢复使用第 23 行 `windows-entry`;以下仅适用于 BLOCKED。用户修好依赖后,只读复检可再次执行,无论此前安装预算是否用尽:
41
+ 环境诊断和次数保存在 `%LOCALAPPDATA%/alipay-aipay-pre/windows/environment.json`;旧版全局次数无法归属具体安装阶段,迁移时保留阻断原因并从新版本的有限分阶段预算重新计数。锁短时占用或状态损坏时,完整工具检查通过仍可 READY;自动安装保持阻断,不删除锁或状态绕过预算。CODE_ONLY 的恢复使用[启动与分流](#启动与分流)中的 `windows-entry` 只读复检;以下仅适用于 BLOCKED。用户修好依赖后,只读复检可再次执行,无论此前安装预算是否用尽:
42
42
 
43
43
  ```text
44
44
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env retry --repair-confirmed true --root-intent "<ROOT_INTENT>" --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>" --windows-route BLOCKED
@@ -52,7 +52,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" env prepare --authorize
52
52
 
53
53
  如果之前只是缺少授权或没有找到安装来源,尚未实际尝试该阶段,则使用同一命令但省略 `--repair-confirmed true`,继续首次准备;不能把新授权当成已消耗预算后的额外重试许可。
54
54
 
55
- 仅退出 0、唯一 `CLI_ENV:READY` 和唯一根意图匹配的 `WINDOWS_ROUTE=READY` 可恢复沙箱及开通能力。BLOCKED 恢复命令的其他结果保持 BLOCKED,说明具体失败原因;不重建会话、重复计数或重放业务操作。CODE_ONLY 按第 23 行重新取得入口分流。用户明确选择站点或平台执行映射不支持时,可走原 LEGACY 分支;可恢复的依赖失败不能自动转站点。
55
+ 仅退出 0、唯一 `CLI_ENV:READY` 和唯一根意图匹配的 `WINDOWS_ROUTE=READY` 可恢复沙箱及开通能力。BLOCKED 恢复命令的其他结果保持 BLOCKED,说明具体失败原因;不重建会话、重复计数或重放业务操作。CODE_ONLY 按[启动与分流](#启动与分流)重新执行 `windows-entry` 取得入口分流。用户明确选择站点或平台执行映射不支持时,可走原 LEGACY 分支;可恢复的依赖失败不能自动转站点。
56
56
 
57
57
  ## 路径、权限与进程
58
58
 
@@ -285,6 +285,8 @@ Step 3.1 通常已在同一次 stdout 展示三分支摘要;网站支付和 AP
285
285
 
286
286
  **直接输入材料或 appId**:选择获取方式不是必经步骤。用户直接提供应用公钥时,按当前应用材料处理,不要求先回复编号,也不打开生成页面。空候选新建、已有明确新建意图或已选复用缺钥应用时,沿用当前目标并只补缺项;候选非空且尚未选定目标时保留已提供公钥,只补问完整 appId 或新建意图,不将公钥当无效 appId,也不要求重交公钥。用户直接提供完整 appId 时,按当前成功查询所得的同类型已上线候选校验并进入复用;不得按开头数字拆成方式编号,候选外或未上线 appId 仍走既有无效选择分支。
287
287
 
288
+ 应用配置首次展示时,`application-candidates` 的默认 `initial` 输出先包含 `application.configuration.intro` 科普,再展示同一次查询的应用事实及适用选择提示;无应用、仅未上线和含已上线候选均适用。不得单独手写或重复渲染科普;无效选择的 `invalid` 输出及 `application-recheck` 的候选变化提示不重复科普,补资料、获取公钥和后续写操作也不重复展示。
289
+
288
290
  轮到服务或应用时,只有 `query_status=SUCCESS` 且 `candidates` 为数组,才用以下 runner 基于同一快照生成候选事实和选择提示;stdout 是唯一正文,禁止提前展示、手工拼表、压缩、拆分或改写。应用候选存在上线或未上线记录时,runner 必须产生且仅产生一个 `CUSTOMER_MESSAGE_DELIVERY_REQUIRED=application.candidate.select`;命令后的下一动作先将 stdout 原文送达,不得添加标题、提示、风险说明、前后缀或改写,然后立即等待用户选择:
289
291
 
290
292
  ```bash
@@ -566,25 +568,29 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message appl
566
568
 
567
569
  **完成条件**:当前登录、scope 和 MCC 必须有效;签约必须由实际查询确认为已生效;仅按量付费适用的服务分支必须复用或保存成功并取得实际 `serviceId`;应用必须达到 `ON_LINE`、应用公钥已生效且支付宝公钥已实际导出。存在失败、未知、待生效、待审核或人工配置时不得宣称产品开通完成。不维护人工完成条件数量。
568
570
 
569
- 使用 `../normal/json/customer-messages.json` 的 `process.partial_result` 逐分支收口,必须通过 `onboarding_message_runner.mjs closeout` 托管输出并原文发送 stdout。禁止 Agent 手写短摘要、删减 `productionReadinessBlock`、删减 AI 网页应用收款限制引导或改写后续衔接;AI 网页应用收款收口缺少“【上线前有以下关键点】”和“AI 网页应用收款限制”时视为标准收口未送达,必须重发同一次 stdout。自动重试耗尽、业务错误或查询失败且仍未恢复的动作,统一写入分支结果和 `remainingActions`,只说明一次,不在收口后追问是否重试。必须执行:
571
+ 使用 `../normal/json/customer-messages.json` 的 `process.partial_result` 逐分支收口,必须通过 `onboarding_message_runner.mjs closeout` 托管输出并原文发送 stdout。禁止 Agent 手写短摘要、删减 `productionReadinessBlock`、删减 AI 网页应用收款限制引导或改写后续衔接;AI 网页应用收款收口缺少“【上线前有以下关键点】”和“AI 网页应用收款限制”时视为标准收口未送达,必须重发同一次 stdout。自动重试耗尽、业务错误或查询失败且仍未恢复的动作,保留在分支结果及内部 `remainingActions`,未解决业务分支的必要恢复动作由 `remainingActions` 放入【当前状态】的“下一步”,不能只依赖前序消息;产品开通各分支已完成且仅剩代码人工验证或沙箱待配置时,分别沿用上线关键点或独立恢复口令,不重复内部汇总待办;仅保留本轮尚未解决分支的具体恢复指引,不重复通用上线提醒或已在上线关键点列出的人工验证项。UNKNOWN 仍先核对事实,禁止自动重放写操作,不在收口后追问是否重试。必须执行:
570
572
 
571
573
  `SIGNING_RESULT`、`SERVICE_RESULT`、`APPLICATION_RESULT` 和 `INTEGRATION_RESULT` 必须使用消息目录允许的状态枚举原文,禁止拼接 `appId`、公钥文件路径、错误码、截图证据或其他自由文本;本轮 `ALIPAY_PUBLIC_KEY_EXPORT_STATUS=EXPORTED` 时,`APP_KEY_SAVE_PATH` 必须传入前一步独立应用结果 runner。这些证据不能污染分支结果枚举。
572
574
 
573
575
  进入本步骤前,应用分支已按前一步的交付规则独立输出 `application.operation.result`(无实际 appId 的例外沿用前一步),runner 必须输出唯一 `ALIPAY_AIPAY_INTERNAL:CUSTOMER_MESSAGE_DELIVERY_REQUIRED=application.operation.result`。命令后的下一个 Agent 动作必须先将该次 stdout 原文作为独立用户可见消息送达,送达前禁止 closeout、合并或继续工具调用;总收口不能替代这条应用结果消息。该约束只强化消息交付编排,不新增用户确认点;marker 缺失或不唯一时停止并重跑同一登记命令。
574
576
 
575
577
  ```bash
576
- 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"] --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT" --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"
578
+ 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"] [--sandbox-summary "$SANDBOX_SUMMARY"] --telemetry-run-id "$RUN_ID" --telemetry-history-count "$HISTORY_COUNT" --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"
577
579
  ```
578
580
 
579
581
  用户输入计数严格继承 `runtime-entry.md`:active run 内每条聊天框用户消息先执行唯一 `count-user-input --run-id "$RUN_ID" --input-id "$USER_INPUT_ID"`,不按 Skill 相关性筛选;runner、recovery、renderer 和 closeout 不做隐式计数。closeout 生成最终 summary 前使用当前 `HISTORY_COUNT` 快照,正式值始终由 runtime counter 写入,禁止传入或覆盖 `user_input_after_clarify_intent`。
580
582
 
581
- runner 从 `PRODUCT_TYPE` 派生产品名,网站支付/APP 支付派生服务结果“无需处理”,从 `ROOT_INTENT` 派生代码开发栏和后续衔接;标题只按完成条件派生。`onboarding_only` 省略 `--integration-result`、`--sandbox-config-state` 和 `--manual-verification-items`。`full_process`:代码开发通过填“已完成”并传 `READY`;仅沙箱待配置且其余代码与安全检查通过填“部分完成,沙箱配置待完成”并传 `CREATE_PENDING|VERIFY_PENDING`;沙箱 `READY` 且只剩非阻塞人工待验证项时填“部分完成,人工待验证”,传 `READY`,把 checklist `manualItems` 原样作为 `MANUAL_VERIFICATION_ITEMS`,并在 `REMAINING_ACTIONS` 写明实际待办,禁止传“无”。runner 拒绝旧完整参数、stdin JSON、`--input-json`、可派生字段和空字符串伪值。renderer 校验结果与沙箱状态/人工待验证项一致,并派生恢复口令或人工待验证展示;不增加确认点。不得在 stdout 前后追加衔接提醒,不伪造本轮代码修改、沙箱创建或测试结果,也不重复进入 integration。
583
+ runner 从 `PRODUCT_TYPE` 派生产品名,网站支付/APP 支付派生服务结果“无需处理”,从 `ROOT_INTENT` 派生代码开发栏和后续衔接;标题只按完成条件派生。`onboarding_only` 省略 `--integration-result`、`--sandbox-config-state` 和 `--manual-verification-items`。`full_process`:代码开发通过填“已完成”并传 `READY`;仅沙箱待配置且其余代码与安全检查通过填“部分完成,沙箱配置待完成”并传 `CREATE_PENDING|VERIFY_PENDING`;沙箱 `READY` 且只剩非阻塞人工待验证项时填“部分完成,人工待验证”,传 `READY`,把 checklist 已分类的实际 `manualItems` 原样作为 `MANUAL_VERIFICATION_ITEMS`,并在 `REMAINING_ACTIONS` 写明实际待办,禁止传“无”。runner 拒绝旧完整参数、stdin JSON、`--input-json`、可派生字段和空字符串伪值。renderer 校验结果与沙箱状态/人工待验证项一致,并派生恢复口令;`remainingActions` 和 `manualVerificationItems` 仍用于完成条件校验,最终总收口不再单列“本轮流程仍需处理”和“人工待验证”,保留分支状态表、【当前状态】及沙箱恢复提示,不增加确认点。不得在 stdout 前后追加衔接提醒,不伪造本轮代码修改、沙箱创建或测试结果,也不重复进入 integration。
584
+
585
+ 三个产品的总收口只保留分支状态表中的应用发布结果,不再重复输出应用结果详情、appId、支付宝公钥保存路径或应用结果专属下一步。应用详情仅由前一步 `application.operation.result` 独立交付;`closeout` 拒绝旧 `--application-operation-*` 参数,禁止把详情改塞入 `remainingActions` 或其他字段。应用创建、提审、复用和人工配置的事实判据保持不变。
586
+
587
+ 当且仅当签约结果为“已提交,等待生效”且应用结果为“已提交审核,等待上线”时,renderer 从消息目录自动在分支状态表后独立展示状态查询提示;该提示不是 flow 入参,Agent 禁止自行传入、拼接或在模板外重复输出。其他结果组合不展示该提示。
582
588
 
583
- 三个产品的总收口只保留分支状态表中的应用发布结果和实际待办,不再重复输出应用结果详情、appId、支付宝公钥保存路径或应用结果专属下一步。应用详情仅由前一步 `application.operation.result` 独立交付;`closeout` 拒绝旧 `--application-operation-*` 参数,禁止把详情改塞入 `remainingActions` 或其他字段。应用创建、提审、复用和人工配置的事实判据保持不变。
589
+ renderer 按产品和实际结果自动派生【当前状态】、可选【沙箱测试配置】、【上线前有以下关键点】和【提示】。`onboarding_only` 禁止传 `--sandbox-summary`,不展示沙箱信息;`full_process` 仅 AI 网页应用收款在沙箱 READY、代码配置后置校验通过且原摘要有效时,传 Integration 本轮已交付的完整 `SANDBOX_SUMMARY`,包括 Worker 返回的原登记正文。不得重读配置、重建沙箱、摘出凭据或手写表格;无有效原摘要时省略,不展示占位信息。原摘要缺失、过期、格式异常或回放校验失败时,renderer 只省略该可选区块,严禁因此阻塞整个 summary;不输出未校验凭据,也不因省略展示改变或证明业务状态。区块只保留沙箱买家测试账号、沙箱买家登录密码、沙箱买家支付密码,两个密码明文展示(含 Windows);不展示配置路径、appId、产品或密钥行。按量付费与 APP 支付禁止传该参数,最终 summary 不展示沙箱配置。沙箱区块用于用户后续测试,不宣称测试通过。
584
590
 
585
- 当且仅当签约结果为“已提交,等待生效”且应用结果为“已提交审核,等待上线”时,renderer 从消息目录自动在 `remainingActions` 后追加状态查询提示;该提示不是 flow 入参,Agent 禁止自行传入、拼接或在模板外重复输出。其他结果组合不展示该提示。
591
+ 上线关键点按“确认上线条件 → 生产配置替换 → 产品专属支付结果确认/服务配置 → 适用收款限制”组织。生产配置包括 appId、应用私钥、对应支付宝公钥及生产网关;应用公钥与应用私钥必须配对,在支付宝侧配置,无需额外配到项目中。应用上线提醒覆盖本轮新建和用户自行准备的其他生产应用。网页/移动收款必须同时实现通知处理和交易查询;缺少 `notify_url` 时省略该字段并由服务端查单兜底,不会仅因缺少该地址而报错。允许省略 `notify_url`,但商家服务端必须可靠主动查单并完成响应验签、订单/金额/状态/归属校验、持久化幂等、后台重试及未决订单恢复;使用通知时需公网 HTTPS、验签、关键字段校验、幂等、`success` 回写和补偿查询。仅没有公网通知地址不应判为不能上线。按量付费 summary 仅保留真实 serviceId、商户 PID/2088 等生产服务配置,不再单列 402 验付和履约回执验证提醒。最终 summary 不重复私钥格式,也不逐字段解释通知校验;这些实现和检查要求仍由原契约、代码开发 flow 及 checklist 执行,不改变自动测试脚本。
586
592
 
587
- renderer 还会按 `productName` 和分支完成条件自动派生上线前检查块。Agent 不传入、不改写该字段,也不得在模板外补第二份生产上线清单。该检查使用“【当前状态】/【上线前有以下关键点】/【提示】”结构,不单列“相关站点”,也不在模板尾部追加第二个查询入口;必要 URL 只放在具体操作步骤中。完成态只能表述为代码开发和产品开通流程已完成,不得替用户确认生产配置已替换、产品真实可收款或应用页面状态;通用上线提醒固定分为三点:前往支付宝 AI 付站点查看产品开通情况;进入一站式接入 → 选择产品 → 密钥配置确认目标支付宝应用已上线;将项目中的支付宝应用配置替换为生产配置,确保 appId、应用私钥、支付宝公钥同属一套生产环境支付宝应用并使用生产网关。三个产品的专属提醒从第 4 点开始;AI 网页应用收款和 AI 移动应用收款必须完成公网 HTTPS `notify_url` 的验签、关键字段校验、幂等、`success` 回写和补偿查询;AI 按量付费必须把沙箱 `api_mock_service_id` 替换为服务市场真实 `serviceId`,A2M 示例中的 `sellerId` 来自商户 PID/2088,由商家自行在支付宝平台确认,不由 Agent 猜测、生成或代填。生产环境应用私钥、账号密码、支付凭证和未脱敏通知内容仍禁止提供给 Agent。分支未完成时,该派生块必须明确上表待办完成前不能正式收款。该提示只在消息目录维护,不增加用户确认点,Agent 不得在模板外重复输出或改写。
593
+ 通用通知地址提醒和用户可选沙箱付款体验不属于缺口,不得写入 `remainingActions`/`manualVerificationItems` 影响完成判定;仅剩这些提醒时按其余适用检查实际证据确定代码结果。实际待验证项必须与部分完成状态对应,不能在 renderer 中隐藏;上游分类有误时只纠正参数,不重测项目。本轮实际尚未验证的项目在上线关键点中列出,不单列“人工待验证”段落,不把尚未验证改成已通过。应用结果与支付宝公钥保存路径仍在前一步独立交付。禁止 Agent 在模板外补第二份生产上线清单或删掉网页收款限制;生产应用私钥、账号密码、支付凭证和未脱敏通知内容不得提供给 Agent。完成态不代表已切生产配置或已可真实收款,不新增确认点。
588
594
 
589
595
  签约、服务和应用分别按本轮脚本实际结果表达:签约提交成功但未生效时,`signingResult` 固定使用“已提交,等待生效”;服务创建或修改成功且取得 `serviceId`、但未取得服务状态时,`serviceResult` 分别固定使用“创建成功,状态未取得”或“修改成功,状态未取得”。任一分支失败或结果未知不清除其他分支成功,也不能概括为“全部失败”。`APPLICATION_RESULT` 沿用应用阶段上述唯一状态映射和本轮实际 marker,字面值必须与消息目录逐字一致。
590
596
 
@@ -14,7 +14,7 @@ AI 网页应用收款覆盖 PC 网页和手机浏览器/H5,接口固定 `alipa
14
14
  5. **用户文件**:只改已确认项目和范围,不清空或删除既有项目;“新建/重做/换一个”不是删除授权。具体删除仍遵守 Integration flow 的清单、二次确认和禁删边界。
15
15
  6. **敏感信息**:应用公钥仅由用户生成并明确提供;禁止 Agent 请求/处理生产私钥、代为生成密钥对、补全/改写公钥或添加 PEM 头尾。预发版仅允许用户明确选择方案3后,按 Onboarding flow 打开随包的本地离线页面,由用户在浏览器内自行生成并保存密钥;禁止 Agent 点击生成、读取页面密钥、读取下载文件或把页面接入联网服务。敏感值、临时 URL 和沙箱资料遵守对应 flow/script 的白名单、权限和输出边界。
16
16
  7. **沙箱结论**:真实快速沙箱配置不得用占位值,唯一例外是 AI 按量付费沙箱 `service_id=api_mock_service_id`,且生产禁用。`CREATE_PENDING|VERIFY_PENDING` 只允许继续代码实现,阻止字段使用、摘要、后置校验、联调和付款体验。字段校验不等于支付测试;仅完整 402 链路满足 flow 才可称沙箱测试通过。
17
- 8. **异步通知**:AI 网页应用收款/AI 移动应用收款必须实现通知。本地无公网 HTTPS `notify_url` 时可不传并以交易查询验收,公网通知联调列为人工待验证;生产上线前须恢复通知并完成验签、幂等、关键字段校验、`success` 回写和补偿查询,否则不宣称生产就绪。
17
+ 8. **异步通知**:AI 网页应用收款/AI 移动应用收款必须实现通知处理和交易查询。`notify_url` 是可选参数;生产也允许省略。未配置时不触发该地址的异步通知,必须由商家服务端通过 `alipay.trade.query` 主动确认支付结果,校验订单、金额、支付状态及归属,幂等更新订单;即使用户关闭页面,仍须继续处理查询重试和未决订单。如使用异步通知,配置商家已部署、支付宝服务端可公网访问的 HTTPS 地址并完成验签、关键字段校验、幂等、`success` 回写和补偿查询。不能只因没有公网通知地址阻止流程或判定不能上线;通知处理代码仍须实现,实际代码或支付结果确认链路缺陷仍是阻断项。
18
18
  9. **受控页面**:授权链接仅由 `auth.sh` 按固定产品/MCC 生成,只允许 `https://aipay.alipay.com/cli-auth` 及登记参数,禁用 CLI `verification_url`;公钥页和系统 opener 只走登记脚本。失败后宿主内置浏览器只可打开已交付的同一 URL 一次;仍失败才提示手动打开,再有限轮询。禁止搜索、改写或自动操作;opener/config 写失败不算业务失败。
19
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 脚本或打印敏感配置。
@@ -70,7 +70,7 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" telemetry resolve-sessi
70
70
  node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" windows-entry --root-intent "<ROOT_INTENT>" --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"
71
71
  ```
72
72
 
73
- 用户明确要求安装并通过 Skill 完成签约/开通或完整接入时(包括正式版保留的原任务与用户随后明确同意安装内测版的选择),当前任务已授权准备所需用户级依赖,附加 `--prepare-authorized true`;仅代码开发且未授权准备依赖时先只读检查。用户明确选择站点时才附加 `--site-selected true`。这不构成登录、签约或应用写入授权。只接受退出 0、唯一 `ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=<JSON>` 且 rootIntent 匹配、route 为 `READY|BLOCKED|LEGACY|CODE_ONLY`。非零、缺失或冲突按 `BLOCKED` 停止,不推定站点分支。`BLOCKED` 须说明内部结果给出的实际缺项/失败原因和有限恢复动作;用户修好依赖后先只读复检,必要且获授权时才按环境文档继续准备。只有不支持的执行映射或用户明确选择站点才进入 `LEGACY`。`integration_only/full_process` 因 Git Bash、jq、CLI 等可选工具缺失、不可运行或有限准备失败时可返回 `CODE_ONLY`,继续原生 Node 代码开发,沙箱记 `VERIFY_PENDING`;完整接入的代码部分完成后停在开通前,不宣称完整接入完成。Windows 沙箱项目配置不要求精确 ACL 白名单;CLI 登录凭据目录仅在依赖登录的动作前检查实际可写性,失败只阻断该动作。Node 不足、实际存储故障、状态异常及未知错误仍阻断,不由 Agent 自行降级。所有后续 Windows runtime 命令追加 `--windows-route "<READY|BLOCKED|LEGACY|CODE_ONLY>"`;`BLOCKED` 不进入业务 bootstrap/flow。修复后只有唯一、根意图匹配的 `WINDOWS_ROUTE=READY` 才恢复快速沙箱与本地开通;`LEGACY` 保留原独立开发/手工沙箱及站点开通分支。`CODE_ONLY` 绑定本次根意图;根意图变化必须重新执行 `windows-entry`,不得继承旧分流。用户修好依赖或明确授权准备后,按 Windows 环境文档重新检查;未取得 READY 时继续独立开发,不循环安装。实际业务执行前仍复检能力。环境、沙箱准备或业务失败不修改采集选择、SESSION_ID、run_id、用户输入计数或阶段责任方。
73
+ 用户明确要求安装并通过 Skill 完成签约/开通或完整接入时(包括正式版保留的原任务与用户随后明确同意安装内测版的选择),当前任务已授权准备所需用户级依赖,附加 `--prepare-authorized true`;仅代码开发且未授权准备依赖时先只读检查。用户明确选择站点时才附加 `--site-selected true`。这不构成登录、签约或应用写入授权。只接受退出 0、唯一 `ALIPAY_AIPAY_INTERNAL:WINDOWS_ROUTE=<JSON>` 且 rootIntent 匹配、route 为 `READY|BLOCKED|LEGACY|CODE_ONLY`。非零、缺失或冲突按 `BLOCKED` 停止,不推定站点分支。`BLOCKED` 须说明内部结果给出的实际缺项/失败原因和有限恢复动作;用户修好依赖后先只读复检,必要且获授权时才按环境文档继续准备。只有不支持的执行映射或用户明确选择站点才进入 `LEGACY`。`integration_only/full_process` 因 Git Bash、jq、CLI 等可选工具缺失、不可运行或有限准备失败时可返回 `CODE_ONLY`,继续原生 Node 代码开发,沙箱默认记 `VERIFY_PENDING`;用户主动提供完整有效手工资料并完成项目配置校验后可记沙箱 `READY`,但环境分流仍为 `CODE_ONLY`,测试按实际依赖执行,不因缺少 Git Bash 单独跳过原生 Python 402 联调;完整接入的代码部分完成后停在开通前,不宣称完整接入完成。Windows 沙箱项目配置不要求精确 ACL 白名单;CLI 登录凭据目录仅在依赖登录的动作前检查实际可写性,失败只阻断该动作。Node 不足、实际存储故障、状态异常及未知错误仍阻断,不由 Agent 自行降级。所有后续 Windows runtime 命令追加 `--windows-route "<READY|BLOCKED|LEGACY|CODE_ONLY>"`;`BLOCKED` 不进入业务 bootstrap/flow。修复后只有唯一、根意图匹配的 `WINDOWS_ROUTE=READY` 才恢复快速沙箱与本地开通;`LEGACY` 保留原独立开发/手工沙箱及站点开通分支。`CODE_ONLY` 绑定本次根意图;根意图变化必须重新执行 `windows-entry`,不得继承旧分流。用户修好依赖或明确授权准备后,按 Windows 环境文档重新检查;未取得 READY 时继续独立开发,不循环安装。实际业务执行前仍复检能力。环境、沙箱准备或业务失败不修改采集选择、SESSION_ID、run_id、用户输入计数或阶段责任方。
74
74
 
75
75
 
76
76
  `integration_only` 的 `integration-bootstrap` 在产品已唯一确定时必须携带 `--product-type`,并串行执行 `telemetry start-run` 与 `flow integration entry`;产品尚未唯一确定时省略产品且不创建正式 run,后续由 `integration-message start-confirm` 首次开 run并生成 `clarify_intent`。`onboarding_only` 的 `onboarding-bootstrap` 同理:产品已唯一时携带产品并先启动 run,尚未唯一时由 `mcc resolve-plan` 或 `onboarding-message plan-confirm` 首次启动。两者均为既有无业务写入动作,执行后不得重复原子命令。Windows READY 返回本地 entry 契约;Windows LEGACY 引导渲染依次使用现有平台项目 ID、正式 run_id;两者均不存在时使用已绑定 `SESSION_ID` 的稳定匿名哈希,不提前创建 run。非 Windows 返回 entry 契约。`full_process` 不使用 `integration-bootstrap`;衔接 Onboarding 也不使用带 `start-run` 的 bootstrap,仍执行 `node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" onboarding-message platform-entry --agent-platform "<AGENT_PLATFORM>" --session-id "<SESSION_ID>"` 后按需加载 entry,避免重复 `clarify_intent`。
@@ -103,6 +103,8 @@ node "<SKILL_DIR>/references/normal/scripts/runtime.mjs" windows-entry --root-in
103
103
 
104
104
  扫码页非阻塞:授权最多 12 次/间隔 5 秒,公钥最多 20 次/间隔 2 秒,成功即推进;耗尽后经统一回复判定只查一次,不重启轮询。
105
105
 
106
- `full_process` 代码开发方案送达前只准备项目、语言、系统分支环境和沙箱;Windows LEGACY 未明确要求当前配置时记 `VERIFY_PENDING`,不收资料。方案送达后直接进入 Integration 步骤 3,满足条件自动进 Onboarding;仅沙箱待配置,或 READY 且只剩非阻塞人工验证时可部分通过,其他缺口停在 Integration;收口保留全部待办。用户中断后重新确认当前项目和服务端语言,从实际项目扫描恢复,不恢复旧方案状态。
106
+ `full_process` 代码开发方案送达前只准备项目、语言、系统分支环境和沙箱;Windows LEGACY/CODE_ONLY 未明确要求当前配置且未主动提供资料时记 `VERIFY_PENDING`,不收资料;本轮有效手工配置可记 `READY`,`CODE_ONLY` 仍在开通前停止。方案送达后直接进入 Integration 步骤 3,满足条件自动进 Onboarding;仅沙箱待配置,或 READY 且只剩非阻塞人工验证时可部分通过,其他缺口停在 Integration;收口保留全部待办。用户中断后重新确认当前项目和服务端语言,从实际项目扫描恢复,不恢复旧方案状态。
107
+
108
+ checklist 的有限修复、禁止循环检测及局部修复后的定向复检只按 Integration flow 步骤 8 执行,不能因阶段重入重新运行全部测试。
107
109
 
108
110
  仅代码开发结束时提醒仍需产品开通;仅产品开通结束时提醒仍需代码开发。机器规则、消息目录、fixture 和测试不作为默认必读内容。