product-spec-mcp 0.3.21 → 0.3.26

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/dist/index.cjs CHANGED
@@ -22982,15 +22982,21 @@ ${formatInterrogateResult(readiness, clarification)}`;
22982
22982
  }
22983
22983
  if (!spec) return "# \u9519\u8BEF\uFF1A\u65E0\u6CD5\u751F\u6210\u89C4\u683C";
22984
22984
  if (mode === "draft") {
22985
- let md2 = `# \u4EA7\u54C1\u89C4\u683C\u8349\u6848
22985
+ const localFirstDraft = spec.technicalProfile?.frontendOnly === true && spec.technicalProfile?.needsBackend === false;
22986
+ let md2 = localFirstDraft ? `# MVP \u4EA7\u54C1\u89C4\u683C\u8349\u6848
22987
+
22988
+ > \u4EE5\u4E0B\u5185\u5BB9\u5DF2\u6309\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u9ED8\u8BA4\u503C\u751F\u6210\uFF0C\u53EF\u4F5C\u4E3A MVP \u5F00\u5DE5\u8349\u6848\uFF1B\u5982\u7528\u6237\u6CA1\u6709\u8865\u5145\u591A\u4EBA\u540C\u6B65\u3001\u767B\u5F55\u3001\u652F\u4ED8\u3001AI Key \u7B49\u5F3A\u4FE1\u53F7\uFF0C\u4E0D\u8981\u5347\u7EA7\u5230\u91CD\u540E\u7AEF\u67B6\u6784\u3002
22989
+ ` : `# \u4EA7\u54C1\u89C4\u683C\u8349\u6848
22986
22990
 
22987
22991
  > \u26A0\uFE0F **\u6CE8\u610F\uFF1A** \u4EE5\u4E0B\u5185\u5BB9\u57FA\u4E8E\u9ED8\u8BA4\u5047\u8BBE\u751F\u6210\uFF0C**\u4E0D\u53EF\u76F4\u63A5\u7528\u4E8E\u5F00\u53D1**\uFF0C\u9700\u8981\u7528\u6237\u786E\u8BA4\u3002
22992
+ `;
22993
+ md2 += `
22988
22994
 
22989
22995
  ## \u9700\u6C42\u5B8C\u6574\u5EA6
22990
22996
 
22991
22997
  - **Score:** ${readiness.score} / 100
22992
22998
  - **\u72B6\u6001:** ${readiness.status}
22993
- - **\u662F\u5426\u53EF\u6267\u884C:** \u5426\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\u5047\u8BBE\uFF09
22999
+ - **\u662F\u5426\u53EF\u6267\u884C:** ${localFirstDraft ? "MVP \u8349\u6848\u53EF\u6267\u884C\uFF08\u9ED8\u8BA4\u5047\u8BBE\u9700\u786E\u8BA4\uFF09" : "\u5426\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\u5047\u8BBE\uFF09"}
22994
23000
 
22995
23001
  ## \u9700\u6C42\u6458\u8981
22996
23002
 
@@ -23003,6 +23009,20 @@ ${formatTechnicalProfileSection(spec.technicalProfile)}
23003
23009
 
23004
23010
  ${spec.coreFeatures.map((f) => `- ${f}`).join("\n")}
23005
23011
 
23012
+ ## \u67B6\u6784\u5EFA\u8BAE
23013
+
23014
+ ${spec.architecture}
23015
+
23016
+ ## \u6570\u636E\u65B9\u6848
23017
+
23018
+ ${spec.dataModel}
23019
+
23020
+ ## API \u8BBE\u8BA1
23021
+
23022
+ \`\`\`
23023
+ ${spec.apiDesign}
23024
+ \`\`\`
23025
+
23006
23026
  ## \u9ED8\u8BA4\u5047\u8BBE\uFF08\u9700\u8981\u7528\u6237\u786E\u8BA4\uFF09
23007
23027
 
23008
23028
  ${spec.assumptions.length > 0 ? spec.assumptions.map((a) => `- \u26A0\uFE0F ${a}`).join("\n") : "- \u65E0\u9ED8\u8BA4\u5047\u8BBE"}
@@ -23011,9 +23031,17 @@ ${spec.assumptions.length > 0 ? spec.assumptions.map((a) => `- \u26A0\uFE0F ${a}
23011
23031
 
23012
23032
  ${spec.riskBoundaries.length > 0 ? spec.riskBoundaries.map((r) => `- \u26A0\uFE0F ${r}`).join("\n") : "- \u65E0\u7279\u6B8A\u98CE\u9669"}
23013
23033
 
23034
+ ## \u6682\u4E0D\u5305\u542B
23035
+
23036
+ ${spec.nonGoals.map((g) => `- ${g}`).join("\n")}
23037
+
23038
+ ## \u9A8C\u6536\u6807\u51C6
23039
+
23040
+ ${spec.successCriteria.map((c) => `- ${c}`).join("\n")}
23041
+
23014
23042
  ## \u4E0B\u4E00\u6B65
23015
23043
 
23016
- \u8BF7\u5148\u8865\u5145\u4E0A\u8FF0\u7F3A\u5931\u4FE1\u606F\uFF0C\u6216\u660E\u786E\u63A5\u53D7\u9ED8\u8BA4\u5047\u8BBE\u540E\u518D\u751F\u6210\u6B63\u5F0F\u5F00\u53D1 Prompt\u3002
23044
+ ${localFirstDraft ? "\u786E\u8BA4\u9ED8\u8BA4\u5047\u8BBE\u540E\u5373\u53EF\u6309\u8BE5 MVP \u8349\u6848\u5B9E\u73B0\uFF1B\u5982\u679C\u7528\u6237\u63D0\u51FA\u591A\u4EBA\u591A\u8BBE\u5907\u540C\u6B65\u3001\u90AE\u4EF6\u901A\u77E5\u3001\u767B\u5F55\u6743\u9650\u7B49\uFF0C\u518D\u91CD\u65B0\u8BC4\u4F30\u6280\u672F\u5F62\u6001\u3002" : "\u8BF7\u5148\u8865\u5145\u4E0A\u8FF0\u7F3A\u5931\u4FE1\u606F\uFF0C\u6216\u660E\u786E\u63A5\u53D7\u9ED8\u8BA4\u5047\u8BBE\u540E\u518D\u751F\u6210\u6B63\u5F0F\u5F00\u53D1 Prompt\u3002"}
23017
23045
 
23018
23046
  `;
23019
23047
  if (confirmation) {
@@ -23319,6 +23347,7 @@ function buildCompileStructuredOutput(mode, readiness, spec, confirmation, clari
23319
23347
  },
23320
23348
  inputConsumption: spec?.inputConsumption,
23321
23349
  technicalProfile: spec?.technicalProfile,
23350
+ pmIntentDecision: spec?.pmIntentDecision,
23322
23351
  spec: spec ? {
23323
23352
  productGoal: spec.productGoal,
23324
23353
  targetUser: spec.targetUser,
@@ -23332,6 +23361,7 @@ function buildCompileStructuredOutput(mode, readiness, spec, confirmation, clari
23332
23361
  successCriteria: spec.successCriteria,
23333
23362
  assumptions: spec.assumptions,
23334
23363
  technicalProfile: spec.technicalProfile,
23364
+ pmIntentDecision: spec.pmIntentDecision,
23335
23365
  inputConsumption: spec.inputConsumption
23336
23366
  } : void 0,
23337
23367
  confirmation: confirmation ? { items: confirmation.items } : void 0,
@@ -23371,6 +23401,7 @@ function buildAcceptanceStructuredOutput(acceptance) {
23371
23401
  productType: acceptance.productType,
23372
23402
  platform: acceptance.platform,
23373
23403
  technicalProfile: acceptance.technicalProfile,
23404
+ pmIntentDecision: acceptance.pmIntentDecision,
23374
23405
  categories: acceptance.categories,
23375
23406
  definitionOfDone: acceptance.definitionOfDone,
23376
23407
  checklist
@@ -23414,7 +23445,8 @@ function buildArchitectureStructuredOutput(decision) {
23414
23445
  domain: decision.domain,
23415
23446
  mvpSuggestion: decision.mvpSuggestion,
23416
23447
  productionSuggestion: decision.productionSuggestion,
23417
- reasoning: decision.reasoning
23448
+ reasoning: decision.reasoning,
23449
+ pmIntentDecision: decision.pmIntentDecision
23418
23450
  },
23419
23451
  technicalProfile: decision.technicalProfile,
23420
23452
  riskLevel,
@@ -23490,6 +23522,60 @@ var SpecCompileInputSchema = external_exports.object({
23490
23522
  min_readiness_score: external_exports.number().optional().default(70).describe("\u6700\u4F4E\u53EF\u63A5\u53D7\u7684 readiness \u5206\u6570")
23491
23523
  });
23492
23524
 
23525
+ // src/schemas/pmIntentDecision.schema.ts
23526
+ var PmIntentDecisionSchema = external_exports.object({
23527
+ needType: external_exports.enum([
23528
+ "static_display",
23529
+ "personal_local_tool",
23530
+ "multi_user_collaboration",
23531
+ "content_marketing_site",
23532
+ "data_visualization_site",
23533
+ "transaction_workflow",
23534
+ "content_knowledge",
23535
+ "ai_automation",
23536
+ "unknown"
23537
+ ]),
23538
+ usageScope: external_exports.enum(["self", "fixed_group", "public_audience", "unknown"]),
23539
+ maintenanceMode: external_exports.enum([
23540
+ "agent_assisted",
23541
+ "manual_files",
23542
+ "web_admin",
23543
+ "visitor_submission",
23544
+ "runtime_collaboration",
23545
+ "unknown"
23546
+ ]),
23547
+ accessTopology: external_exports.enum(["single_device", "lan_only", "internet_ip", "public_domain", "unknown"]),
23548
+ technicalShape: external_exports.enum([
23549
+ "static_page",
23550
+ "local_storage_tool",
23551
+ "local_json_import_export",
23552
+ "static_json_data_page",
23553
+ "light_backend_json_sqlite",
23554
+ "full_backend_saas",
23555
+ "unknown"
23556
+ ]),
23557
+ recommendedDeployment: external_exports.enum([
23558
+ "static_only",
23559
+ "local_browser_only",
23560
+ "static_hosting_with_agent_updates",
23561
+ "local_lan_server_sqlite",
23562
+ "cheap_vps_sqlite_by_ip",
23563
+ "vps_domain_https",
23564
+ "unknown"
23565
+ ]),
23566
+ route: external_exports.enum(["spec_compile", "spec_interrogate", "architecture_decide"]),
23567
+ confidence: external_exports.enum(["high", "medium", "low"]),
23568
+ strongSignals: external_exports.array(external_exports.string()),
23569
+ weakSignals: external_exports.array(external_exports.string()),
23570
+ coreObjects: external_exports.array(external_exports.string()),
23571
+ states: external_exports.array(external_exports.string()),
23572
+ actions: external_exports.array(external_exports.string()),
23573
+ mustNotUse: external_exports.array(external_exports.string()),
23574
+ boundaryQuestionIds: external_exports.array(external_exports.string()),
23575
+ defaultAssumptions: external_exports.array(external_exports.string()),
23576
+ source: external_exports.enum(["local_rule", "online_llm", "merged"])
23577
+ });
23578
+
23493
23579
  // src/schemas/outputs/specCompile.output.ts
23494
23580
  var SpecCompileOutputSchema = external_exports.object({
23495
23581
  mode: external_exports.enum(["not_ready", "draft", "formal"]),
@@ -23504,6 +23590,7 @@ var SpecCompileOutputSchema = external_exports.object({
23504
23590
  confidence: external_exports.enum(["high", "medium", "low"])
23505
23591
  }).optional(),
23506
23592
  technicalProfile: TechnicalProfileSchema.optional(),
23593
+ pmIntentDecision: PmIntentDecisionSchema.optional(),
23507
23594
  spec: external_exports.object({
23508
23595
  productGoal: external_exports.string(),
23509
23596
  targetUser: external_exports.string(),
@@ -23517,6 +23604,7 @@ var SpecCompileOutputSchema = external_exports.object({
23517
23604
  successCriteria: external_exports.array(external_exports.string()),
23518
23605
  assumptions: external_exports.array(external_exports.string()),
23519
23606
  technicalProfile: TechnicalProfileSchema.optional(),
23607
+ pmIntentDecision: PmIntentDecisionSchema.optional(),
23520
23608
  inputConsumption: external_exports.object({
23521
23609
  consumedAnswers: external_exports.array(external_exports.string()),
23522
23610
  unusedAnswers: external_exports.array(external_exports.string()),
@@ -23570,10 +23658,11 @@ function cleanObjectLabel(value) {
23570
23658
  }
23571
23659
  function buildFieldLabels(text, recordObject) {
23572
23660
  const labels = [`${recordObject}\u540D`];
23573
- addIf(labels, "\u6570\u91CF/\u5E93\u5B58", /数量|库存|余量|剩余|补货/.test(text));
23661
+ const physicalInventory = /家里有哪些|有哪些|库存|余量|剩余|补货|存放|放在/.test(text);
23662
+ addIf(labels, "\u6570\u91CF/\u5E93\u5B58", physicalInventory || /数量|库存|余量|剩余|补货/.test(text));
23574
23663
  addIf(labels, "\u6709\u6548\u671F/\u5230\u671F\u65E5", /有效期|过期|临期|到期|截止|保质期|续费|提醒/.test(text));
23575
- addIf(labels, "\u5206\u7C7B", /分类|类别|标签|类型/.test(text));
23576
- addIf(labels, "\u5B58\u653E\u4F4D\u7F6E", /位置|存放|放在|地点|地址/.test(text));
23664
+ addIf(labels, "\u5206\u7C7B", physicalInventory || /分类|类别|标签|类型/.test(text));
23665
+ addIf(labels, "\u5B58\u653E\u4F4D\u7F6E", physicalInventory || /位置|存放|放在|地点|地址/.test(text));
23577
23666
  addIf(labels, "\u72B6\u6001", /状态|进度|已完成|未完成|正常|异常/.test(text));
23578
23667
  addIf(labels, "\u91D1\u989D/\u4EF7\u683C", /金额|价格|费用|预算|保费/.test(text));
23579
23668
  addIf(labels, "\u94FE\u63A5", /链接|网址|URL/i.test(text));
@@ -23583,10 +23672,11 @@ function buildFieldLabels(text, recordObject) {
23583
23672
  function buildFeatureHints(text, recordObject) {
23584
23673
  const hints = [];
23585
23674
  if (/记录|管理|保存|清单|列表/.test(text)) hints.push(`${recordObject}\u8BB0\u5F55\u7BA1\u7406`);
23675
+ if (/记录|管理|保存|清单|列表/.test(text)) hints.push("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664");
23586
23676
  if (/新增|添加|编辑|删除|增删改查|CRUD/i.test(text)) hints.push("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664");
23587
- if (/搜索|筛选|分类|标签|查询/.test(text)) hints.push("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B");
23677
+ if (/搜索|筛选|分类|标签|查询|家里有哪些|有哪些|清单|列表/.test(text)) hints.push("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B");
23588
23678
  if (/提醒|到期|过期|临期|快过期|截止|倒计时|保质期|续费/.test(text)) hints.push("\u5230\u671F/\u8FC7\u671F\u63D0\u9192");
23589
- if (/数量|库存|余量|剩余|补货/.test(text)) hints.push("\u6570\u91CF/\u5E93\u5B58\u7BA1\u7406");
23679
+ if (/数量|库存|余量|剩余|补货|家里有哪些|有哪些/.test(text)) hints.push("\u6570\u91CF/\u5E93\u5B58\u7BA1\u7406");
23590
23680
  if (/高级|好看|美观|视觉|界面|页面|UI|ui|响应式/.test(text)) hints.push("\u9AD8\u7EA7\u754C\u9762\u4E0E\u54CD\u5E94\u5F0F\u5E03\u5C40");
23591
23681
  return Array.from(new Set(hints));
23592
23682
  }
@@ -23611,11 +23701,234 @@ function addIf(items, label, condition) {
23611
23701
  if (condition) items.push(label);
23612
23702
  }
23613
23703
 
23704
+ // src/core/pmIntentGate.ts
23705
+ function decidePmIntent(rawText, context = {}) {
23706
+ const text = `${rawText} ${JSON.stringify(context)}`;
23707
+ const strongSignals = collectSignals(text, strongSignalMap);
23708
+ const weakSignals = collectSignals(text, weakSignalMap);
23709
+ const usageScope = decideUsageScope(text);
23710
+ const preliminaryNeedType = decideNeedType(text, strongSignals);
23711
+ const maintenanceMode = decideMaintenanceMode(text, preliminaryNeedType);
23712
+ const accessTopology = decideAccessTopology(text, usageScope, maintenanceMode);
23713
+ const needType = preliminaryNeedType;
23714
+ const technicalShape = decideTechnicalShape(text, needType, maintenanceMode);
23715
+ const recommendedDeployment = decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology);
23716
+ const route = decideRoute(needType, technicalShape, maintenanceMode);
23717
+ const confidence = decideConfidence(needType, strongSignals, weakSignals);
23718
+ return enforceHardRules({
23719
+ needType,
23720
+ usageScope,
23721
+ maintenanceMode,
23722
+ accessTopology,
23723
+ technicalShape,
23724
+ recommendedDeployment,
23725
+ route,
23726
+ confidence,
23727
+ strongSignals,
23728
+ weakSignals,
23729
+ coreObjects: extractCoreObjects(text, needType),
23730
+ states: extractStates(text, needType),
23731
+ actions: extractActions(text, needType),
23732
+ mustNotUse: buildMustNotUse(needType, maintenanceMode),
23733
+ boundaryQuestionIds: buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology),
23734
+ defaultAssumptions: buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, recommendedDeployment),
23735
+ source: "local_rule"
23736
+ });
23737
+ }
23738
+ function decideNeedType(text, strongSignals) {
23739
+ if (hasAny2(text, ["AI", "ai", "LLM", "llm", "GPT", "gpt", "\u5927\u6A21\u578B", "\u6A21\u578B\u63A5\u53E3", "API Key", "DeepSeek", "OpenAI"]) && !isNegated(text, ["AI", "\u6A21\u578B"])) {
23740
+ return "ai_automation";
23741
+ }
23742
+ if (hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6", "\u6536\u6B3E", "\u5BFC\u51FA Excel", "\u5BFC\u51FA"])) {
23743
+ return "transaction_workflow";
23744
+ }
23745
+ if (hasAny2(text, ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA\u5171\u7528", "\u5171\u7528", "\u5171\u4EAB", "\u534F\u4F5C", "\u76F8\u4E92\u5B89\u6392", "\u8BA4\u9886", "\u5206\u914D\u4EFB\u52A1", "\u56E2\u961F\u5F85\u529E"])) {
23746
+ return "multi_user_collaboration";
23747
+ }
23748
+ if (hasAny2(text, ["xlsx", "XLSX", "Excel", "csv", "CSV", "\u56FE\u8868", "\u6570\u636E\u6E32\u67D3", "\u53EF\u89C6\u5316", "\u4EEA\u8868\u76D8"]) && hasAny2(text, ["\u6587\u4EF6", "\u6570\u636E", "\u6E32\u67D3", "\u56FE\u8868", "\u4E0A\u4F20", "\u63D0\u4F9B"])) {
23749
+ return "data_visualization_site";
23750
+ }
23751
+ if (hasAny2(text, ["\u5065\u8EAB\u623F", "\u9910\u5385", "\u5496\u5561\u5E97", "\u5DE5\u4F5C\u5BA4", "\u95E8\u5E97", "\u672C\u5730\u670D\u52A1", "GEO", "geo", "SEO", "seo", "\u4FC3\u9500", "\u6559\u7EC3", "Q&A", "FAQ", "\u7167\u7247", "\u7528\u6237\u53CD\u9988"])) {
23752
+ return "content_marketing_site";
23753
+ }
23754
+ if (hasAny2(text, ["\u77E5\u8BC6\u5E93", "\u6587\u6863\u7BA1\u7406", "\u8D44\u6599\u5E93", "\u56E2\u961F\u6587\u6863"])) {
23755
+ return "content_knowledge";
23756
+ }
23757
+ if (hasAny2(text, ["\u836F\u54C1", "\u98DF\u6750", "\u8BFB\u4E66", "\u8BA2\u9605", "\u690D\u7269", "\u88C5\u5907", "\u6E05\u5355", "\u8BB0\u5F55", "\u63D0\u9192", "\u5E93\u5B58", "\u4FDD\u8D28\u671F"]) && !strongSignals.includes("\u591A\u4EBA")) {
23758
+ return "personal_local_tool";
23759
+ }
23760
+ if (hasAny2(text, ["\u4F5C\u54C1\u96C6", "\u4E2A\u4EBA\u4E3B\u9875", "\u5B98\u7F51", "\u4ECB\u7ECD\u9875", "\u516C\u53F8\u4ECB\u7ECD", "\u8054\u7CFB\u65B9\u5F0F"]) && !hasAny2(text, ["\u63D0\u4EA4", "\u4E0A\u4F20", "\u7F16\u8F91", "\u7EF4\u62A4", "\u6570\u636E", "\u4EFB\u52A1", "\u8BA4\u9886"])) {
23761
+ return "static_display";
23762
+ }
23763
+ return "unknown";
23764
+ }
23765
+ function decideUsageScope(text) {
23766
+ if (hasAny2(text, ["\u516C\u5F00", "\u8BBF\u5BA2", "\u5BA2\u6237", "\u7528\u6237", "\u4F1A\u5458", "\u5B98\u7F51", "\u7F51\u7AD9", "\u95E8\u5E97", "\u5065\u8EAB\u623F", "\u9910\u5385", "\u5DE5\u4F5C\u5BA4"])) return "public_audience";
23767
+ if (hasAny2(text, ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA", "\u5BB6\u5EAD", "\u540C\u4E8B", "\u56E2\u961F", "\u5171\u7528", "\u5171\u4EAB"])) return "fixed_group";
23768
+ if (hasAny2(text, ["\u81EA\u5DF1", "\u81EA\u7528", "\u4E2A\u4EBA", "\u6211\u7528", "\u6211\u81EA\u5DF1"])) return "self";
23769
+ return "unknown";
23770
+ }
23771
+ function decideMaintenanceMode(text, needType) {
23772
+ if (hasAny2(text, ["\u8BBF\u5BA2\u63D0\u4EA4", "\u7528\u6237\u63D0\u4EA4", "\u5728\u7EBF\u63D0\u4EA4", "\u63D0\u4EA4\u53CD\u9988", "\u63D0\u4EA4\u8BC4\u8BBA", "\u9884\u7EA6\u4F53\u9A8C", "\u62A5\u540D"])) return "visitor_submission";
23773
+ if (hasAny2(text, ["\u8BA4\u9886", "\u76F8\u4E92\u5B89\u6392", "\u534F\u4F5C", "\u5206\u914D\u4EFB\u52A1", "\u591A\u4EBA\u4EFB\u52A1", "\u5171\u4EAB\u4EFB\u52A1"])) return "runtime_collaboration";
23774
+ if (hasAny2(text, ["\u540E\u53F0", "\u7BA1\u7406\u540E\u53F0", "\u7F51\u9875\u91CC\u7F16\u8F91", "\u7F51\u9875\u4E0A\u4F20", "\u4E0A\u4F20\u6309\u94AE", "\u767B\u5F55\u540E\u7F16\u8F91", "CMS", "cms"])) return "web_admin";
23775
+ if (hasAny2(text, ["data.json", "markdown", "Markdown", "md \u6587\u4EF6", "\u624B\u52A8\u6539\u6587\u4EF6"])) return "manual_files";
23776
+ if (hasAny2(text, ["Agent", "agent", "\u6BCF\u6B21\u6211\u63D0\u4F9B", "\u6211\u63D0\u4F9B\u65B0\u7684", "\u4F20\u5F88\u591A", "\u4E0D\u5B9A\u671F\u7EF4\u62A4", "\u91CD\u65B0\u90E8\u7F72"])) return "agent_assisted";
23777
+ if (needType === "content_marketing_site" || needType === "data_visualization_site" || needType === "static_display") return "agent_assisted";
23778
+ return "unknown";
23779
+ }
23780
+ function decideAccessTopology(text, usageScope, maintenanceMode) {
23781
+ if (hasAny2(text, ["\u540C\u4E00 Wi-Fi", "\u540C\u4E00\u4E2A Wi-Fi", "\u5C40\u57DF\u7F51", "\u5185\u7F51", "\u5BB6\u91CC\u7F51\u7EDC"])) return "lan_only";
23782
+ if (hasAny2(text, ["\u5916\u51FA", "\u516C\u7F51 IP", "\u516C\u7F51ip", "IP \u5730\u5740", "\u670D\u52A1\u5668", "VPS", "vps"])) return "internet_ip";
23783
+ if (hasAny2(text, ["\u57DF\u540D", "HTTPS", "https", "\u5907\u6848", "\u516C\u5F00\u7F51\u7AD9", "\u5B98\u7F51"])) return "public_domain";
23784
+ if (usageScope === "self" && maintenanceMode !== "runtime_collaboration") return "single_device";
23785
+ if (usageScope === "public_audience") return "public_domain";
23786
+ return "unknown";
23787
+ }
23788
+ function decideTechnicalShape(text, needType, maintenanceMode) {
23789
+ if (needType === "ai_automation") return "full_backend_saas";
23790
+ if (needType === "transaction_workflow") return hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u6536\u8D39"]) ? "full_backend_saas" : "light_backend_json_sqlite";
23791
+ if (needType === "multi_user_collaboration") return "light_backend_json_sqlite";
23792
+ if (needType === "content_marketing_site") {
23793
+ return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
23794
+ }
23795
+ if (needType === "data_visualization_site") {
23796
+ return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
23797
+ }
23798
+ if (needType === "content_knowledge") {
23799
+ return maintenanceMode === "agent_assisted" || maintenanceMode === "manual_files" ? "static_json_data_page" : "light_backend_json_sqlite";
23800
+ }
23801
+ if (needType === "personal_local_tool") return "local_storage_tool";
23802
+ if (needType === "static_display") return "static_page";
23803
+ return "unknown";
23804
+ }
23805
+ function decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology) {
23806
+ if (technicalShape === "static_page") return "static_only";
23807
+ if (technicalShape === "local_storage_tool" || technicalShape === "local_json_import_export") return "local_browser_only";
23808
+ if (maintenanceMode === "agent_assisted" && ["content_marketing_site", "data_visualization_site", "content_knowledge"].includes(needType)) {
23809
+ return "static_hosting_with_agent_updates";
23810
+ }
23811
+ if (accessTopology === "lan_only") return "local_lan_server_sqlite";
23812
+ if (accessTopology === "internet_ip") return "cheap_vps_sqlite_by_ip";
23813
+ if (accessTopology === "public_domain") return "vps_domain_https";
23814
+ if (technicalShape === "light_backend_json_sqlite") return "cheap_vps_sqlite_by_ip";
23815
+ return "unknown";
23816
+ }
23817
+ function decideRoute(needType, technicalShape, maintenanceMode) {
23818
+ if (needType === "personal_local_tool") return "spec_compile";
23819
+ if (["static_page", "static_json_data_page"].includes(technicalShape) && maintenanceMode === "agent_assisted") return "spec_compile";
23820
+ return "spec_interrogate";
23821
+ }
23822
+ function decideConfidence(needType, strongSignals, weakSignals) {
23823
+ if (needType === "unknown") return "low";
23824
+ if (strongSignals.length >= 2) return "high";
23825
+ if (strongSignals.length === 1 || weakSignals.length >= 2) return "medium";
23826
+ return "medium";
23827
+ }
23828
+ function enforceHardRules(decision) {
23829
+ const hasRuntimeCollaboration = decision.needType === "multi_user_collaboration" || decision.maintenanceMode === "runtime_collaboration" || decision.strongSignals.some((signal) => ["\u591A\u4EBA", "\u5171\u4EAB", "\u534F\u4F5C", "\u8BA4\u9886", "\u76F8\u4E92\u5B89\u6392"].includes(signal));
23830
+ if (hasRuntimeCollaboration && decision.technicalShape !== "light_backend_json_sqlite") {
23831
+ return {
23832
+ ...decision,
23833
+ needType: "multi_user_collaboration",
23834
+ maintenanceMode: "runtime_collaboration",
23835
+ technicalShape: "light_backend_json_sqlite",
23836
+ recommendedDeployment: decision.accessTopology === "lan_only" ? "local_lan_server_sqlite" : "cheap_vps_sqlite_by_ip",
23837
+ route: "spec_interrogate",
23838
+ mustNotUse: Array.from(/* @__PURE__ */ new Set([...decision.mustNotUse, "static_display", "local_storage_only"]))
23839
+ };
23840
+ }
23841
+ return decision;
23842
+ }
23843
+ function buildMustNotUse(needType, maintenanceMode) {
23844
+ const items = [];
23845
+ if (needType === "multi_user_collaboration") items.push("static_display", "local_storage_only");
23846
+ if (needType === "content_marketing_site" || needType === "data_visualization_site") items.push("admin_backend_by_default", "database_by_default");
23847
+ if (maintenanceMode === "agent_assisted") items.push("web_admin_cms_by_default");
23848
+ if (needType === "transaction_workflow") items.push("local_storage_only");
23849
+ if (needType === "ai_automation") items.push("frontend_api_key");
23850
+ return Array.from(new Set(items));
23851
+ }
23852
+ function buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology) {
23853
+ if (needType === "multi_user_collaboration") {
23854
+ return ["access_topology", "public_ip_acceptance", "claim_rule", "time_conflict_rule"];
23855
+ }
23856
+ if (needType === "content_marketing_site") {
23857
+ return ["maintenance_mode", "geo_goal", "visitor_submission", "image_volume"];
23858
+ }
23859
+ if (needType === "data_visualization_site") {
23860
+ return ["data_update_mode", "audience_scope", "history_versions"];
23861
+ }
23862
+ if (needType === "content_knowledge") {
23863
+ return maintenanceMode === "agent_assisted" ? ["maintenance_mode", "visibility_scope"] : ["editor_roles", "permission_rule", "version_history"];
23864
+ }
23865
+ if (needType === "unknown") return ["usage_scope", "maintenance_mode", "data_flow"];
23866
+ if (accessTopology === "unknown" && needType !== "personal_local_tool") return ["access_topology"];
23867
+ return [];
23868
+ }
23869
+ function buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, deployment) {
23870
+ const items = [`\u4F7F\u7528\u8303\u56F4\uFF1A${usageScope}`, `\u7EF4\u62A4\u65B9\u5F0F\uFF1A${maintenanceMode}`, `\u8BBF\u95EE\u65B9\u5F0F\uFF1A${accessTopology}`, `\u63A8\u8350\u90E8\u7F72\uFF1A${deployment}`];
23871
+ if (needType === "content_marketing_site" || needType === "data_visualization_site") {
23872
+ items.push("\u5185\u5BB9\u6216\u6570\u636E\u7ECF\u5E38\u66F4\u65B0\u65F6\uFF0CMVP \u9ED8\u8BA4\u4F18\u5148\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\uFF0C\u4E0D\u9ED8\u8BA4\u5EFA\u8BBE\u7F51\u9875\u540E\u53F0\u3002");
23873
+ }
23874
+ if (needType === "multi_user_collaboration") {
23875
+ items.push("\u591A\u4EBA\u534F\u4F5C\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F\uFF1B\u4E0D\u76F4\u63A5\u9ED8\u8BA4\u516C\u7F51\u670D\u52A1\u5668\u3001\u57DF\u540D\u6216\u5907\u6848\u3002");
23876
+ }
23877
+ return items;
23878
+ }
23879
+ function extractCoreObjects(text, needType) {
23880
+ if (needType === "multi_user_collaboration") return ["\u7528\u6237", "\u4EFB\u52A1", "\u65E5\u7A0B\u9879"];
23881
+ if (needType === "content_marketing_site") return ["Q&A", "\u7167\u7247", "\u7528\u6237\u53CD\u9988", "\u4FC3\u9500\u6D3B\u52A8", "\u6559\u7EC3\u4FE1\u606F"].filter((item) => text.includes(item.replace("\u4FE1\u606F", "")) || item === "Q&A");
23882
+ if (needType === "data_visualization_site") return ["xlsx \u6587\u4EF6", "\u6570\u636E\u8868", "\u56FE\u8868\u914D\u7F6E", "\u6E32\u67D3\u7ED3\u679C"];
23883
+ if (needType === "personal_local_tool") {
23884
+ if (text.includes("\u836F")) return ["\u836F\u54C1"];
23885
+ if (text.includes("\u98DF\u6750")) return ["\u98DF\u6750"];
23886
+ return ["\u8BB0\u5F55"];
23887
+ }
23888
+ return [];
23889
+ }
23890
+ function extractStates(text, needType) {
23891
+ const states = [];
23892
+ if (needType === "multi_user_collaboration") states.push("\u5F85\u8BA4\u9886", "\u5DF2\u8BA4\u9886", "\u5DF2\u5B8C\u6210", "\u53D6\u6D88");
23893
+ if (hasAny2(text, ["\u8FC7\u671F", "\u4E34\u671F", "\u5230\u671F"])) states.push("\u6B63\u5E38", "\u4E34\u671F", "\u5DF2\u8FC7\u671F");
23894
+ return Array.from(new Set(states));
23895
+ }
23896
+ function extractActions(text, needType) {
23897
+ if (needType === "multi_user_collaboration") return ["\u5B89\u6392\u4EFB\u52A1", "\u8BA4\u9886\u4EFB\u52A1", "\u67E5\u770B\u65E5\u7A0B\u51B2\u7A81"];
23898
+ if (needType === "content_marketing_site") return ["\u66F4\u65B0\u5185\u5BB9", "\u53D1\u5E03\u4FC3\u9500", "\u7EF4\u62A4\u56FE\u7247\u548C FAQ"];
23899
+ if (needType === "data_visualization_site") return ["\u89E3\u6790 xlsx", "\u66F4\u65B0\u56FE\u8868\u6570\u636E", "\u6E32\u67D3\u7ED3\u679C"];
23900
+ return [];
23901
+ }
23902
+ var strongSignalMap = {
23903
+ \u591A\u4EBA: ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA\u5171\u7528", "\u5171\u7528", "\u5171\u4EAB"],
23904
+ \u534F\u4F5C: ["\u534F\u4F5C", "\u76F8\u4E92\u5B89\u6392", "\u8BA4\u9886", "\u5206\u914D\u4EFB\u52A1"],
23905
+ \u6743\u9650: ["\u6743\u9650", "\u767B\u5F55", "\u540E\u53F0", "\u7BA1\u7406\u5458", "\u5BA1\u6279", "\u5BA1\u6838"],
23906
+ \u516C\u5F00\u63D0\u4EA4: ["\u8BBF\u5BA2\u63D0\u4EA4", "\u7528\u6237\u63D0\u4EA4", "\u5728\u7EBF\u63D0\u4EA4", "\u63D0\u4EA4\u53CD\u9988"],
23907
+ \u4EA4\u6613: ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6"],
23908
+ AI: ["AI", "ai", "API Key", "\u6A21\u578B\u63A5\u53E3", "\u5927\u6A21\u578B"]
23909
+ };
23910
+ var weakSignalMap = {
23911
+ \u5C55\u793A: ["\u5C55\u793A", "\u7F51\u7AD9", "\u9875\u9762"],
23912
+ \u89C6\u89C9: ["\u9875\u9762\u9AD8\u7EA7", "\u597D\u770B", "\u7F8E\u89C2"],
23913
+ \u7BA1\u7406: ["\u7BA1\u7406", "\u7EF4\u62A4", "\u5185\u5BB9\u591A"],
23914
+ \u5217\u8868: ["\u5217\u8868", "\u67E5\u770B", "\u7B5B\u9009", "\u65E5\u7A0B", "\u72B6\u6001"]
23915
+ };
23916
+ function collectSignals(text, map) {
23917
+ return Object.entries(map).filter(([, signals]) => hasAny2(text, signals)).map(([label]) => label);
23918
+ }
23919
+ function hasAny2(text, signals) {
23920
+ return signals.some((signal) => text.includes(signal));
23921
+ }
23922
+ function isNegated(text, signals) {
23923
+ return signals.some((signal) => new RegExp(`(\u4E0D\u63A5|\u4E0D\u505A|\u4E0D\u7528|\u65E0\u9700|\u4E0D\u9700\u8981|\u6682\u4E0D|\u5148\u4E0D).{0,8}${signal}`, "i").test(text));
23924
+ }
23925
+
23614
23926
  // src/core/promptBuilder.ts
23615
23927
  function buildSpec(rawIdea, context, readiness) {
23616
23928
  const assumptions = [];
23617
23929
  const normalizedContext = normalizeContext(context);
23618
23930
  const technicalProfile = buildTechnicalProfile(rawIdea, normalizedContext);
23931
+ const pmIntentDecision = decidePmIntent(rawIdea, normalizedContext);
23619
23932
  const classification = classifyProductDomain(rawIdea, normalizedContext);
23620
23933
  const shouldUseDomainPack = classification.domain !== "generic" && !(isLocalFirstProfile(technicalProfile) && ["knowledge_base", "ticket_workflow"].includes(classification.domain));
23621
23934
  if (shouldUseDomainPack && classification.domain === "crm") {
@@ -23642,16 +23955,21 @@ function buildSpec(rawIdea, context, readiness) {
23642
23955
  if (shouldUseDomainPack && classification.domain === "registration") {
23643
23956
  return withTechnicalProfile(buildRegistrationSpec(rawIdea, normalizedContext, readiness), technicalProfile);
23644
23957
  }
23958
+ if (classification.domain === "generic" && shouldUsePmGateSpec(pmIntentDecision)) {
23959
+ return withTechnicalProfile(buildPmGateSpec(rawIdea, normalizedContext, readiness, pmIntentDecision), technicalProfile);
23960
+ }
23645
23961
  const hasStructuredAnswers = hasUnsupportedStructuredAnswers(normalizedContext);
23646
23962
  const personalLocalTool = isLocalFirstProfile(technicalProfile) || isPersonalLocalFrontendToolContext(rawIdea, normalizedContext);
23647
- const genericReadinessScore = hasStructuredAnswers ? Math.min(Math.max(readiness.score, 60), 79) : readiness.score;
23963
+ const localSignalProfile = personalLocalTool ? buildLocalToolSignalProfile(rawIdea) : void 0;
23964
+ const hasLocalSignals = Boolean(localSignalProfile && (localSignalProfile.featureHints.length > 0 || localSignalProfile.recordObject !== "\u8BB0\u5F55"));
23965
+ const genericReadinessScore = hasStructuredAnswers ? Math.min(Math.max(readiness.score, 60), 79) : hasLocalSignals ? Math.max(readiness.score, 60) : readiness.score;
23648
23966
  const genericReadinessStatus = readinessStatusFromScore(genericReadinessScore);
23649
23967
  const isActionable = !hasStructuredAnswers && genericReadinessScore >= 70;
23650
- const productGoal = normalizedContext.product_goal || extractGoal(rawIdea);
23968
+ const productGoal = normalizedContext.product_goal || extractGoal(rawIdea) || (hasLocalSignals && localSignalProfile ? `${localSignalProfile.recordObject}\u7BA1\u7406\u5DE5\u5177` : "");
23651
23969
  if (!productGoal) {
23652
23970
  assumptions.push("\u4EA7\u54C1\u76EE\u6807\uFF1A\u672A\u660E\u786E\uFF0C\u9700\u8981\u7528\u6237\u786E\u8BA4");
23653
23971
  }
23654
- const targetUser = normalizedContext.target_user || extractTargetUser(rawIdea);
23972
+ const targetUser = normalizedContext.target_user || (hasLocalSignals ? inferLocalFirstTargetUser(rawIdea) : extractTargetUser(rawIdea));
23655
23973
  if (!targetUser) {
23656
23974
  assumptions.push("\u76EE\u6807\u7528\u6237\uFF1A\u9ED8\u8BA4\u4E3A\u4E2A\u4EBA\u7528\u6237");
23657
23975
  }
@@ -23666,7 +23984,9 @@ function buildSpec(rawIdea, context, readiness) {
23666
23984
  assumptions.push("\u5F53\u524D\u8F93\u5165\u5305\u542B\u591A\u4E2A\u7ED3\u6784\u5316\u7B54\u6848\uFF0C\u4F46\u672A\u5339\u914D\u5230\u7A33\u5B9A domain pack\uFF1B\u4E0D\u8981\u628A\u5B83\u5957\u5165\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u6216\u77E5\u8BC6\u5E93\u6A21\u677F\u3002");
23667
23985
  }
23668
23986
  const needsBackend = technicalProfile.needsBackend || normalizedContext.need_backend === true || normalizedContext.data_persistence === true || normalizedContext.user_roles === true || normalizedContext.backend_need === true;
23669
- const dataModel = buildDataModel(normalizedContext, needsBackend, technicalProfile);
23987
+ const dataModel = buildDataModel(normalizedContext, needsBackend, technicalProfile, rawIdea);
23988
+ const successCriteria = personalLocalTool ? buildLocalFirstSuccessCriteria(rawIdea) : ["\u6838\u5FC3\u529F\u80FD\u53EF\u7528", "\u65E0\u660E\u663E Bug", "\u7528\u6237\u4F53\u9A8C\u6D41\u7545"];
23989
+ const nonGoals = personalLocalTool ? ["\u6682\u4E0D\u5305\u542B\u767B\u5F55/\u6CE8\u518C", "\u6682\u4E0D\u5305\u542B\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF", "\u6682\u4E0D\u5305\u542B\u591A\u4EBA\u591A\u8BBE\u5907\u540C\u6B65"] : ["\u6682\u4E0D\u5305\u542B\u9AD8\u7EA7\u529F\u80FD", "\u6682\u4E0D\u5305\u542B\u79FB\u52A8\u7AEF App"];
23670
23990
  return {
23671
23991
  readinessScore: genericReadinessScore,
23672
23992
  readinessStatus: genericReadinessStatus,
@@ -23679,16 +23999,191 @@ function buildSpec(rawIdea, context, readiness) {
23679
23999
  architecture: buildArchitectureRecommendation(normalizedContext, needsBackend, technicalProfile),
23680
24000
  apiDesign: personalLocalTool ? buildLocalFirstApiDesign(technicalProfile) : hasStructuredAnswers ? "\u672A\u5339\u914D\u5230\u7A33\u5B9A domain\uFF0C\u6682\u4E0D\u751F\u6210\u6B63\u5F0F API\uFF1B\u8BF7\u5148\u8865\u5145\u6838\u5FC3\u4E1A\u52A1\u5BF9\u8C61\u3001\u72B6\u6001\u6D41\u8F6C\u3001\u6743\u9650\u8FB9\u754C\u540E\u518D\u7F16\u8BD1\u3002" : needsBackend ? buildApiDesign(normalizedContext, coreFeatures) : "\u7EAF\u524D\u7AEF\u9879\u76EE\uFF0C\u65E0\u9700 API",
23681
24001
  riskBoundaries: hasStructuredAnswers ? ["\u672A\u547D\u4E2D\u7A33\u5B9A domain pack\uFF0C\u5F53\u524D\u89C4\u683C\u4EC5\u53EF\u4F5C\u4E3A\u8349\u6848\uFF1B\u7981\u6B62\u9759\u9ED8\u590D\u7528\u5176\u5B83\u4E1A\u52A1\u6A21\u677F\u3002"] : buildRiskBoundaries(normalizedContext),
23682
- nonGoals: toArray(normalizedContext.non_goals, ["\u6682\u4E0D\u5305\u542B\u9AD8\u7EA7\u529F\u80FD", "\u6682\u4E0D\u5305\u542B\u79FB\u52A8\u7AEF App"]),
23683
- successCriteria: toArray(normalizedContext.success_criteria, ["\u6838\u5FC3\u529F\u80FD\u53EF\u7528", "\u65E0\u660E\u663E Bug", "\u7528\u6237\u4F53\u9A8C\u6D41\u7545"]),
24002
+ nonGoals: toArray(normalizedContext.non_goals, nonGoals),
24003
+ successCriteria: toArray(normalizedContext.success_criteria, successCriteria),
23684
24004
  assumptions,
23685
24005
  technicalProfile,
24006
+ pmIntentDecision,
23686
24007
  inputConsumption: buildInputConsumption(normalizedContext, Object.keys(normalizedContext), "generic", "low")
23687
24008
  };
23688
24009
  }
23689
24010
  function withTechnicalProfile(spec, technicalProfile) {
23690
24011
  return { ...spec, technicalProfile };
23691
24012
  }
24013
+ function shouldUsePmGateSpec(decision) {
24014
+ return [
24015
+ "multi_user_collaboration",
24016
+ "content_marketing_site",
24017
+ "data_visualization_site"
24018
+ ].includes(decision.needType);
24019
+ }
24020
+ function buildPmGateSpec(rawIdea, context, readiness, decision) {
24021
+ const score = Math.min(Math.max(readiness.score, 60), 79);
24022
+ const productGoal = context.product_goal || pmGateProductGoal(decision);
24023
+ const targetUser = context.target_user || pmGateTargetUser(decision);
24024
+ const assumptions = [...decision.defaultAssumptions];
24025
+ return {
24026
+ readinessScore: score,
24027
+ readinessStatus: readinessStatusFromScore(score),
24028
+ isActionable: false,
24029
+ productGoal,
24030
+ targetUser,
24031
+ platform: context.platform || "web",
24032
+ coreFeatures: pmGateCoreFeatures(decision),
24033
+ dataModel: pmGateDataModel(decision),
24034
+ architecture: pmGateArchitecture(decision),
24035
+ apiDesign: pmGateApiDesign(decision),
24036
+ riskBoundaries: pmGateRiskBoundaries(decision),
24037
+ nonGoals: pmGateNonGoals(decision),
24038
+ successCriteria: pmGateSuccessCriteria(decision),
24039
+ assumptions,
24040
+ pmIntentDecision: decision,
24041
+ inputConsumption: buildInputConsumption(context, Object.keys(context), "generic", decision.confidence)
24042
+ };
24043
+ }
24044
+ function pmGateProductGoal(decision) {
24045
+ if (decision.needType === "multi_user_collaboration") return "\u591A\u4EBA\u5171\u4EAB\u4EFB\u52A1\u65E5\u7A0B\u5DE5\u5177";
24046
+ if (decision.needType === "content_marketing_site") return "\u5185\u5BB9\u8425\u9500\u7F51\u7AD9";
24047
+ if (decision.needType === "data_visualization_site") return "\u6570\u636E\u56FE\u8868\u5C55\u793A\u7F51\u7AD9";
24048
+ return "\u4EA7\u54C1 MVP";
24049
+ }
24050
+ function pmGateTargetUser(decision) {
24051
+ if (decision.usageScope === "fixed_group") return "\u56FA\u5B9A\u5C0F\u8303\u56F4\u6210\u5458";
24052
+ if (decision.usageScope === "public_audience") return "\u516C\u5F00\u8BBF\u95EE\u7528\u6237\u548C\u7AD9\u70B9\u7EF4\u62A4\u8005";
24053
+ if (decision.usageScope === "self") return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
24054
+ return "\u5F85\u7528\u6237\u786E\u8BA4";
24055
+ }
24056
+ function pmGateCoreFeatures(decision) {
24057
+ if (decision.needType === "multi_user_collaboration") {
24058
+ return [
24059
+ "\u6210\u5458\u4EFB\u52A1\u65E5\u7A0B\u5C55\u793A",
24060
+ "\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u4EFB\u52A1\u76F4\u63A5\u751F\u6548",
24061
+ "\u7ED9\u522B\u4EBA\u5B89\u6392\u4EFB\u52A1\u8FDB\u5165\u5F85\u8BA4\u9886",
24062
+ "\u4EFB\u52A1\u8BA4\u9886\u548C\u5B8C\u6210\u72B6\u6001\u6D41\u8F6C",
24063
+ "\u540C\u4E00\u65F6\u95F4\u4EFB\u52A1\u5E76\u6392\u5C55\u793A\u6216\u9AD8\u4EAE\u51B2\u7A81"
24064
+ ];
24065
+ }
24066
+ if (decision.needType === "content_marketing_site") {
24067
+ return [
24068
+ "\u5065\u8EAB\u623F\u57FA\u7840\u4FE1\u606F\u5C55\u793A",
24069
+ "Q&A/FAQ \u5185\u5BB9\u9875",
24070
+ "\u7167\u7247\u548C\u7528\u6237\u53CD\u9988\u5C55\u793A",
24071
+ "\u8FD1\u671F\u4FC3\u9500\u6D3B\u52A8\u5C55\u793A",
24072
+ "\u6559\u7EC3\u4FE1\u606F\u5C55\u793A",
24073
+ "GEO/SEO \u7ED3\u6784\u5316\u5185\u5BB9"
24074
+ ];
24075
+ }
24076
+ if (decision.needType === "data_visualization_site") {
24077
+ return [
24078
+ "xlsx \u6570\u636E\u89E3\u6790\u6D41\u7A0B",
24079
+ "\u56FE\u8868\u6570\u636E JSON \u751F\u6210",
24080
+ "\u56FE\u8868\u9875\u9762\u6E32\u67D3",
24081
+ "\u6700\u65B0\u6570\u636E\u7ED3\u679C\u5C55\u793A"
24082
+ ];
24083
+ }
24084
+ return ["\u6838\u5FC3\u529F\u80FD\u5F85\u786E\u8BA4"];
24085
+ }
24086
+ function pmGateDataModel(decision) {
24087
+ if (decision.needType === "multi_user_collaboration") {
24088
+ return [
24089
+ "SQLite\uFF08MVP\uFF09",
24090
+ "users(id, name, access_code, created_at)",
24091
+ "tasks(id, title, description, start_at, end_at, creator_id, assignee_id, status, created_at, updated_at)",
24092
+ "task_events(id, task_id, actor_id, action, note, created_at)",
24093
+ "status \u5EFA\u8BAE\uFF1Aself_active / pending_claim / claimed / done / cancelled"
24094
+ ].join("\n");
24095
+ }
24096
+ if (decision.needType === "content_marketing_site") {
24097
+ return [
24098
+ "\u9759\u6001\u5185\u5BB9\u6587\u4EF6\uFF1Adata/site.json + markdown \u5185\u5BB9 + assets \u56FE\u7247\u76EE\u5F55",
24099
+ "site_profile(name, address, hours, phone, geo_keywords)",
24100
+ "faqs(question, answer, category)",
24101
+ "coaches(name, title, specialties, bio, photo)",
24102
+ "promotions(title, description, start_date, end_date, status)",
24103
+ "testimonials(author_label, content, source, status)",
24104
+ "\u9ED8\u8BA4\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\uFF0C\u4E0D\u9ED8\u8BA4\u5EFA\u8BBE CMS \u540E\u53F0\u3002"
24105
+ ].join("\n");
24106
+ }
24107
+ if (decision.needType === "data_visualization_site") {
24108
+ return [
24109
+ "\u9759\u6001\u6570\u636E\u6587\u4EF6\uFF1Adata/chart-data.json",
24110
+ "Agent \u4ECE xlsx \u89E3\u6790\u51FA rows\u3001columns\u3001metrics\u3001chart_config",
24111
+ "\u9875\u9762\u8BFB\u53D6 chart-data.json \u6E32\u67D3\u56FE\u8868\uFF1B\u9ED8\u8BA4\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C\u3002",
24112
+ "\u5982\u6539\u4E3A\u7F51\u9875\u4E0A\u4F20\u4E14\u6240\u6709\u8BBF\u5BA2\u770B\u6700\u65B0\u7ED3\u679C\uFF0C\u518D\u5347\u7EA7\u4E0A\u4F20\u63A5\u53E3\u548C\u670D\u52A1\u5668\u5B58\u50A8\u3002"
24113
+ ].join("\n");
24114
+ }
24115
+ return "\u5F85\u786E\u8BA4\u6570\u636E\u6A21\u578B";
24116
+ }
24117
+ function pmGateArchitecture(decision) {
24118
+ if (decision.needType === "multi_user_collaboration") {
24119
+ return decision.accessTopology === "lan_only" ? "\u5C40\u57DF\u7F51\u8F7B\u540E\u7AEF\uFF1A\u4E00\u53F0\u672C\u673A/NAS \u8FD0\u884C Node + SQLite\uFF0C\u6210\u5458\u901A\u8FC7\u5C40\u57DF\u7F51 IP \u8BBF\u95EE\u3002" : "\u8F7B\u540E\u7AEF MVP\uFF1ANode + SQLite\uFF1B\u56FA\u5B9A\u51E0\u4EBA\u5916\u51FA\u8BBF\u95EE\u65F6\u53EF\u7528\u4F4E\u4EF7\u516C\u7F51 VPS + IP \u5730\u5740\u5148\u8DD1\u901A\u3002";
24120
+ }
24121
+ if (decision.needType === "content_marketing_site") {
24122
+ return "\u9759\u6001\u5185\u5BB9\u8425\u9500\u7AD9\uFF1AHTML/CSS/JS + \u9759\u6001\u5185\u5BB9\u6587\u4EF6 + \u56FE\u7247\u8D44\u6E90\uFF1B\u7531 Agent \u7EF4\u62A4\u5185\u5BB9\u5E76\u91CD\u65B0\u90E8\u7F72\u3002";
24123
+ }
24124
+ if (decision.needType === "data_visualization_site") {
24125
+ return "\u9759\u6001\u6570\u636E\u56FE\u8868\u7AD9\uFF1AAgent \u89E3\u6790 xlsx \u751F\u6210 JSON\uFF0C\u524D\u7AEF\u8BFB\u53D6 JSON \u5E76\u6E32\u67D3\u56FE\u8868\uFF1B\u4E0D\u9ED8\u8BA4\u540E\u53F0\u6216\u6570\u636E\u5E93\u3002";
24126
+ }
24127
+ return "\u5F85\u786E\u8BA4\u67B6\u6784";
24128
+ }
24129
+ function pmGateApiDesign(decision) {
24130
+ if (decision.needType === "multi_user_collaboration") {
24131
+ return [
24132
+ "GET /api/schedule?date=YYYY-MM-DD",
24133
+ "POST /api/tasks",
24134
+ "POST /api/tasks/:id/claim",
24135
+ "POST /api/tasks/:id/complete",
24136
+ "PATCH /api/tasks/:id"
24137
+ ].join("\n");
24138
+ }
24139
+ return "\u65E0\u9700 REST API\uFF1B\u7531 Agent \u66F4\u65B0\u9759\u6001\u5185\u5BB9/\u6570\u636E\u6587\u4EF6\u540E\u91CD\u65B0\u90E8\u7F72\u3002";
24140
+ }
24141
+ function pmGateRiskBoundaries(decision) {
24142
+ if (decision.needType === "multi_user_collaboration") {
24143
+ return ["\u591A\u4EBA\u8FD0\u884C\u65F6\u6570\u636E\u9700\u8981\u7EDF\u4E00\u6570\u636E\u6E90\uFF0C\u4E0D\u80FD\u7528\u6BCF\u4EBA\u5404\u81EA localStorage \u89E3\u51B3\u3002", "\u516C\u7F51\u8BBF\u95EE\u65F6\u8981\u786E\u8BA4\u662F\u5426\u63A5\u53D7 IP \u8BBF\u95EE\uFF0C\u57DF\u540D\u548C HTTPS \u53EF\u4F5C\u4E3A\u6B63\u5F0F\u5316\u9636\u6BB5\u3002"];
24144
+ }
24145
+ if (decision.needType === "content_marketing_site") {
24146
+ return ["\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u7B49\u4E8E\u5FC5\u987B\u5EFA\u8BBE\u540E\u53F0\uFF1B\u53EA\u6709\u7F51\u9875\u7F16\u8F91\u3001\u591A\u4EBA\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u624D\u5347\u7EA7\u540E\u7AEF\u3002"];
24147
+ }
24148
+ if (decision.needType === "data_visualization_site") {
24149
+ return ["\u6BCF\u6B21\u63D0\u4F9B xlsx \u53EF\u7531 Agent \u66F4\u65B0\u9759\u6001\u6570\u636E\uFF1B\u53EA\u6709\u7F51\u9875\u4E0A\u4F20\u3001\u7EDF\u4E00\u6700\u65B0\u6570\u636E\u6216\u5386\u53F2\u7248\u672C\u624D\u5347\u7EA7\u540E\u7AEF\u3002"];
24150
+ }
24151
+ return [];
24152
+ }
24153
+ function pmGateNonGoals(decision) {
24154
+ if (decision.needType === "multi_user_collaboration") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A\u57DF\u540D/\u5907\u6848/\u5B8C\u6574\u516C\u7F51\u8FD0\u7EF4", "\u6682\u4E0D\u505A\u590D\u6742 RBAC"];
24155
+ if (decision.needType === "content_marketing_site") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A CMS \u540E\u53F0", "\u6682\u4E0D\u9ED8\u8BA4\u5F00\u653E\u8BBF\u5BA2\u63D0\u4EA4"];
24156
+ if (decision.needType === "data_visualization_site") return ["\u6682\u4E0D\u9ED8\u8BA4\u505A\u7F51\u9875\u4E0A\u4F20\u540E\u53F0", "\u6682\u4E0D\u9ED8\u8BA4\u4FDD\u5B58\u5386\u53F2\u7248\u672C"];
24157
+ return ["\u6682\u4E0D\u5305\u542B\u9AD8\u7EA7\u529F\u80FD"];
24158
+ }
24159
+ function pmGateSuccessCriteria(decision) {
24160
+ if (decision.needType === "multi_user_collaboration") {
24161
+ return [
24162
+ "\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u7684\u4EFB\u52A1\u4FDD\u5B58\u540E\u7ACB\u5373\u51FA\u73B0\u5728\u81EA\u5DF1\u7684\u65E5\u7A0B\u4E2D",
24163
+ "\u5B89\u6392\u7ED9\u522B\u4EBA\u65F6\u4EFB\u52A1\u8FDB\u5165\u5F85\u8BA4\u9886\u72B6\u6001",
24164
+ "\u5BF9\u65B9\u8BA4\u9886\u540E\u4EFB\u52A1\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B",
24165
+ "\u540C\u4E00\u65F6\u95F4\u4EFB\u52A1\u80FD\u5E76\u6392\u5C55\u793A\u6216\u9AD8\u4EAE\u51B2\u7A81",
24166
+ "\u5237\u65B0\u540E\u4EFB\u52A1\u72B6\u6001\u4FDD\u6301\u4E00\u81F4"
24167
+ ];
24168
+ }
24169
+ if (decision.needType === "content_marketing_site") {
24170
+ return [
24171
+ "FAQ\u3001\u7167\u7247\u3001\u4FC3\u9500\u6D3B\u52A8\u3001\u6559\u7EC3\u4FE1\u606F\u80FD\u4ECE\u5185\u5BB9\u6587\u4EF6\u6E32\u67D3",
24172
+ "Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u9875\u9762\u5C55\u793A\u6700\u65B0\u5185\u5BB9",
24173
+ "\u9875\u9762\u5305\u542B\u57FA\u7840 GEO/SEO \u7ED3\u6784\u5316\u4FE1\u606F\u3001sitemap \u6216\u53EF\u7D22\u5F15\u5185\u5BB9",
24174
+ "\u4E0D\u51FA\u73B0\u9700\u8981\u540E\u53F0\u767B\u5F55\u624D\u80FD\u7EF4\u62A4\u7684\u9ED8\u8BA4\u6D41\u7A0B"
24175
+ ];
24176
+ }
24177
+ if (decision.needType === "data_visualization_site") {
24178
+ return [
24179
+ "Agent \u80FD\u4ECE\u65B0\u7684 xlsx \u751F\u6210\u56FE\u8868\u6570\u636E\u6587\u4EF6",
24180
+ "\u9875\u9762\u8BFB\u53D6\u6700\u65B0\u6570\u636E\u6587\u4EF6\u5E76\u6E32\u67D3\u56FE\u8868",
24181
+ "\u66FF\u6362\u6570\u636E\u540E\u91CD\u65B0\u90E8\u7F72\u80FD\u770B\u5230\u6700\u65B0\u7ED3\u679C",
24182
+ "\u4E0D\u9ED8\u8BA4\u8981\u6C42\u540E\u53F0\u4E0A\u4F20\u6216\u6570\u636E\u5E93"
24183
+ ];
24184
+ }
24185
+ return ["\u6838\u5FC3\u529F\u80FD\u6309\u786E\u8BA4\u8FB9\u754C\u5B9E\u73B0"];
24186
+ }
23692
24187
  function buildRegistrationSpec(rawIdea, context, readiness) {
23693
24188
  const formFields = parseListLike(context.form_fields, ["\u59D3\u540D", "\u624B\u673A\u53F7", "\u62A5\u540D\u4EBA\u6570", "\u5907\u6CE8"]);
23694
24189
  const hasPhone = formFields.some((field) => field.includes("\u624B\u673A") || field.includes("\u7535\u8BDD"));
@@ -24752,6 +25247,11 @@ function extractTargetUser(text) {
24752
25247
  }
24753
25248
  return "";
24754
25249
  }
25250
+ function inferLocalFirstTargetUser(text) {
25251
+ if (/家庭|家里|父母|老人|孩子|家人/.test(text)) return "\u5BB6\u5EAD\u81EA\u7528\u7528\u6237";
25252
+ if (/个人|自己用|自用|我的/.test(text)) return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
25253
+ return "\u4E2A\u4EBA\u4F7F\u7528\u8005";
25254
+ }
24755
25255
  function extractPlatform(text) {
24756
25256
  if (text.includes("\u5C0F\u7A0B\u5E8F")) return "mini_program";
24757
25257
  if (text.includes("app") || text.includes("App")) return "app";
@@ -24821,7 +25321,7 @@ function extractFeatures(text) {
24821
25321
  return features.length > 0 ? features : ["\u6838\u5FC3\u529F\u80FD"];
24822
25322
  }
24823
25323
  function buildLocalFirstExtractedFeatures(text) {
24824
- const genericFeatures = extractFeatures(text).filter((feature) => feature !== "\u6838\u5FC3\u529F\u80FD");
25324
+ const genericFeatures = extractFeatures(text).filter((feature) => feature !== "\u6838\u5FC3\u529F\u80FD" && feature !== "\u7BA1\u7406");
24825
25325
  const signalProfile = buildLocalToolSignalProfile(text);
24826
25326
  const features = [...genericFeatures, ...signalProfile.featureHints];
24827
25327
  return features.length > 0 ? Array.from(new Set(features)) : ["\u6838\u5FC3\u529F\u80FD"];
@@ -24830,7 +25330,7 @@ function isNegatedKeyword(text, keyword) {
24830
25330
  const escaped = keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
24831
25331
  return new RegExp(`(\u4E0D\u63A5|\u4E0D\u505A|\u4E0D\u7528|\u65E0\u9700|\u4E0D\u9700\u8981|\u6682\u4E0D|\u5148\u4E0D|\u4E0D\u8981|\u6CA1\u6709).{0,8}${escaped}`, "i").test(text);
24832
25332
  }
24833
- function buildDataModel(context, needsBackend = true, technicalProfile) {
25333
+ function buildDataModel(context, needsBackend = true, technicalProfile, rawIdea = "") {
24834
25334
  if (technicalProfile?.shape === "static_page") return "\u65E0\u9700\u6570\u636E\u6301\u4E45\u5316\uFF1B\u7EAF HTML/CSS/JS \u9759\u6001\u5C55\u793A\u3002";
24835
25335
  if (technicalProfile?.shape === "static_json_data_page") {
24836
25336
  return [
@@ -24840,17 +25340,21 @@ function buildDataModel(context, needsBackend = true, technicalProfile) {
24840
25340
  ].join("\n");
24841
25341
  }
24842
25342
  if (technicalProfile?.shape === "local_json_import_export") {
25343
+ const signalProfile = buildLocalToolSignalProfile(rawIdea);
24843
25344
  return [
24844
25345
  "\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8 + JSON \u6587\u4EF6\u5BFC\u5165\u5BFC\u51FA",
24845
25346
  "localStorage key \u793A\u4F8B\uFF1Alocal_tool_records",
24846
- 'JSON \u793A\u4F8B\uFF1A[{ "id": "item-1", "name": "\u793A\u4F8B\u8BB0\u5F55", "date": "2026-06-22", "status": "active", "note": "\u5907\u6CE8" }]'
25347
+ `\u5B57\u6BB5\u5EFA\u8BAE\uFF1A${signalProfile.fieldExample}`,
25348
+ `JSON \u793A\u4F8B\uFF1A${buildLocalRecordJsonExample(signalProfile.recordObject, signalProfile.fieldExample)}`
24847
25349
  ].join("\n");
24848
25350
  }
24849
25351
  if (technicalProfile?.shape === "local_storage_tool") {
25352
+ const signalProfile = buildLocalToolSignalProfile(rawIdea);
24850
25353
  return [
24851
25354
  "\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8\uFF1AlocalStorage",
24852
25355
  "localStorage key \u793A\u4F8B\uFF1Apersonal_tool_records",
24853
- '\u8BB0\u5F55\u793A\u4F8B\uFF1A{ "id": "item-1", "name": "\u793A\u4F8B\u8BB0\u5F55", "date": "2026-06-22", "status": "active", "note": "\u5907\u6CE8" }',
25356
+ `\u5B57\u6BB5\u5EFA\u8BAE\uFF1A${signalProfile.fieldExample}`,
25357
+ `\u8BB0\u5F55\u793A\u4F8B\uFF1A${buildLocalRecordJsonExample(signalProfile.recordObject, signalProfile.fieldExample)}`,
24854
25358
  "\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u540E\u7EED\u5982\u6570\u636E\u91CF\u8F83\u5927\u53EF\u5347\u7EA7 IndexedDB\u3002"
24855
25359
  ].join("\n");
24856
25360
  }
@@ -24861,6 +25365,37 @@ function buildDataModel(context, needsBackend = true, technicalProfile) {
24861
25365
  if (!needsBackend) return "\u6D4F\u89C8\u5668\u672C\u5730\u5B58\u50A8\uFF1AlocalStorage \u6216\u5355\u4E2A JSON \u6587\u4EF6\uFF1B\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93";
24862
25366
  return "\u5F85\u786E\u8BA4\uFF1A\u5EFA\u8BAE SQLite\uFF08MVP\uFF09\u6216 PostgreSQL\uFF08\u751F\u4EA7\uFF09";
24863
25367
  }
25368
+ function buildLocalRecordJsonExample(recordObject, fieldExample) {
25369
+ const labels = fieldExample.split("\u3001").map((item) => item.trim()).filter(Boolean);
25370
+ const record2 = {
25371
+ id: "item-1"
25372
+ };
25373
+ for (const label of labels) {
25374
+ if (label.includes("\u540D")) record2.name = `\u793A\u4F8B${recordObject}`;
25375
+ else if (label.includes("\u6570\u91CF") || label.includes("\u5E93\u5B58")) record2.quantity = 1;
25376
+ else if (label.includes("\u6709\u6548\u671F") || label.includes("\u5230\u671F")) record2.expireDate = "2026-12-31";
25377
+ else if (label.includes("\u5206\u7C7B")) record2.category = "\u9ED8\u8BA4\u5206\u7C7B";
25378
+ else if (label.includes("\u4F4D\u7F6E") || label.includes("\u5730\u70B9") || label.includes("\u5730\u5740")) record2.location = "\u9ED8\u8BA4\u4F4D\u7F6E";
25379
+ else if (label.includes("\u72B6\u6001")) record2.status = "normal";
25380
+ else if (label.includes("\u91D1\u989D") || label.includes("\u4EF7\u683C")) record2.amount = 0;
25381
+ else if (label.includes("\u94FE\u63A5")) record2.url = "";
25382
+ else if (label.includes("\u5907\u6CE8")) record2.note = "\u5907\u6CE8";
25383
+ }
25384
+ record2.updatedAt = "2026-06-23T00:00:00.000Z";
25385
+ return JSON.stringify(record2);
25386
+ }
25387
+ function buildLocalFirstSuccessCriteria(text) {
25388
+ const signalProfile = buildLocalToolSignalProfile(text);
25389
+ const items = [...signalProfile.acceptanceItems];
25390
+ if (signalProfile.featureHints.includes("\u65B0\u589E/\u7F16\u8F91/\u5220\u9664")) {
25391
+ items.push(`${signalProfile.recordObject}\u8BB0\u5F55\u652F\u6301\u65B0\u589E\u3001\u7F16\u8F91\u3001\u5220\u9664\uFF0C\u64CD\u4F5C\u540E\u5217\u8868\u7ACB\u5373\u66F4\u65B0`);
25392
+ }
25393
+ if (signalProfile.featureHints.includes("\u641C\u7D22/\u7B5B\u9009/\u5206\u7C7B")) {
25394
+ items.push("\u641C\u7D22\u3001\u5206\u7C7B\u6216\u72B6\u6001\u7B5B\u9009\u80FD\u51C6\u786E\u7F29\u5C0F\u5217\u8868\uFF0C\u6E05\u7A7A\u7B5B\u9009\u540E\u6062\u590D\u5168\u90E8\u8BB0\u5F55");
25395
+ }
25396
+ items.push("\u5237\u65B0\u9875\u9762\u540E\uFF0C\u5DF2\u4FDD\u5B58\u8BB0\u5F55\u4ECD\u80FD\u4ECE localStorage \u6062\u590D");
25397
+ return Array.from(new Set(items));
25398
+ }
24864
25399
  function buildArchitectureRecommendation(context, needsBackend, technicalProfile) {
24865
25400
  if (technicalProfile?.shape === "static_page") return "\u7EAF\u524D\u7AEF\u67B6\u6784";
24866
25401
  if (technicalProfile?.shape === "local_storage_tool") return "\u7EAF\u524D\u7AEF\u672C\u5730\u5DE5\u5177\uFF1AHTML/CSS/JS + localStorage\uFF1B\u9002\u5408\u4E2A\u4EBA\u8BB0\u5F55\u3001\u6E05\u5355\u3001\u63D0\u9192\u548C\u53F0\u8D26\u3002";
@@ -25035,7 +25570,8 @@ var ArchitectureDecideOutputSchema = external_exports.object({
25035
25570
  domain: external_exports.string().optional(),
25036
25571
  mvpSuggestion: external_exports.string(),
25037
25572
  productionSuggestion: external_exports.string(),
25038
- reasoning: external_exports.array(external_exports.string())
25573
+ reasoning: external_exports.array(external_exports.string()),
25574
+ pmIntentDecision: PmIntentDecisionSchema.optional()
25039
25575
  }),
25040
25576
  technicalProfile: TechnicalProfileSchema.optional(),
25041
25577
  riskLevel: external_exports.enum(["low", "medium", "high"]),
@@ -25170,6 +25706,74 @@ var architectureRules_default = {
25170
25706
  };
25171
25707
 
25172
25708
  // src/core/architectureEngine.ts
25709
+ function buildPmGateArchitectureDecision(decision, technicalProfile) {
25710
+ if (decision.needType === "multi_user_collaboration") {
25711
+ return {
25712
+ canBeFrontendOnly: false,
25713
+ needBackend: true,
25714
+ needSeparation: false,
25715
+ recommendedDatabase: "SQLite\uFF08MVP\uFF09",
25716
+ needAuth: true,
25717
+ needAdmin: false,
25718
+ needLogging: true,
25719
+ paymentRisk: false,
25720
+ aiKeyRisk: false,
25721
+ capacityRisk: false,
25722
+ domain: "generic",
25723
+ mvpSuggestion: decision.accessTopology === "lan_only" ? "\u5C40\u57DF\u7F51 Node + SQLite\uFF1A\u4E00\u53F0\u7535\u8111/NAS \u8FD0\u884C\u670D\u52A1\uFF0C\u6210\u5458\u901A\u8FC7\u5C40\u57DF\u7F51 IP \u8BBF\u95EE" : "Node + SQLite\uFF1A\u56FA\u5B9A\u51E0\u4EBA\u5916\u51FA\u8BBF\u95EE\u65F6\u53EF\u5148\u7528\u4F4E\u4EF7\u516C\u7F51 VPS + IP \u5730\u5740\u8DD1\u901A",
25724
+ productionSuggestion: "\u540E\u7EED\u518D\u8865\u57DF\u540D\u3001HTTPS\u3001\u5907\u4EFD\u548C\u66F4\u5B8C\u6574\u8D26\u53F7\u6743\u9650\uFF1B\u56FD\u5185\u516C\u5F00\u57DF\u540D\u6309\u5B9E\u9645\u60C5\u51B5\u8003\u8651\u5907\u6848",
25725
+ reasoning: [
25726
+ "\u591A\u4EBA\u3001\u534F\u4F5C\u3001\u8BA4\u9886\u548C\u8DE8\u7528\u6237\u65E5\u7A0B\u662F\u8FD0\u884C\u65F6\u5171\u4EAB\u6570\u636E\uFF0C\u4E0D\u80FD\u7528\u6BCF\u4EBA\u672C\u5730 localStorage \u89E3\u51B3\u3002",
25727
+ "\u591A\u4EBA\u534F\u4F5C\u4E0D\u76F4\u63A5\u7B49\u4E8E\u6B63\u5F0F\u516C\u7F51 SaaS\uFF1B\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F\u3002"
25728
+ ],
25729
+ technicalProfile,
25730
+ pmIntentDecision: decision
25731
+ };
25732
+ }
25733
+ if (decision.needType === "content_marketing_site") {
25734
+ const needsBackend = decision.maintenanceMode === "web_admin" || decision.maintenanceMode === "visitor_submission";
25735
+ return {
25736
+ canBeFrontendOnly: !needsBackend,
25737
+ needBackend: needsBackend,
25738
+ needSeparation: false,
25739
+ recommendedDatabase: needsBackend ? "SQLite\uFF08MVP\uFF09" : "\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u4F7F\u7528\u9759\u6001\u5185\u5BB9\u6587\u4EF6",
25740
+ needAuth: decision.maintenanceMode === "web_admin",
25741
+ needAdmin: decision.maintenanceMode === "web_admin",
25742
+ needLogging: needsBackend,
25743
+ paymentRisk: false,
25744
+ aiKeyRisk: false,
25745
+ capacityRisk: false,
25746
+ domain: "generic",
25747
+ mvpSuggestion: needsBackend ? "\u8F7B\u540E\u53F0 CMS + SQLite\uFF0C\u7528\u4E8E\u7F51\u9875\u91CC\u7F16\u8F91\u5185\u5BB9\u548C\u4E0A\u4F20\u56FE\u7247" : "\u9759\u6001\u5185\u5BB9\u8425\u9500\u7AD9 + data.json/markdown/assets\uFF0C\u7531 Agent \u66F4\u65B0\u5185\u5BB9\u5E76\u91CD\u65B0\u90E8\u7F72",
25748
+ productionSuggestion: "\u9700\u8981\u591A\u4EBA\u7F51\u9875\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u65F6\u518D\u5347\u7EA7\u540E\u53F0\u3001\u5BA1\u6838\u3001\u9632\u5783\u573E\u548C\u901A\u77E5",
25749
+ reasoning: ["\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u76F4\u63A5\u89E6\u53D1\u540E\u53F0\uFF1B\u5148\u770B\u7EF4\u62A4\u65B9\u5F0F\u662F\u4E0D\u662F Agent-assisted\u3002"],
25750
+ technicalProfile,
25751
+ pmIntentDecision: decision
25752
+ };
25753
+ }
25754
+ if (decision.needType === "data_visualization_site") {
25755
+ const needsBackend = decision.maintenanceMode === "web_admin" || decision.maintenanceMode === "visitor_submission";
25756
+ return {
25757
+ canBeFrontendOnly: !needsBackend,
25758
+ needBackend: needsBackend,
25759
+ needSeparation: false,
25760
+ recommendedDatabase: needsBackend ? "SQLite\uFF08MVP\uFF09" : "\u65E0\u9700\u670D\u52A1\u5668\u6570\u636E\u5E93\uFF1B\u4F7F\u7528\u9759\u6001 chart-data.json",
25761
+ needAuth: needsBackend,
25762
+ needAdmin: needsBackend,
25763
+ needLogging: needsBackend,
25764
+ paymentRisk: false,
25765
+ aiKeyRisk: false,
25766
+ capacityRisk: false,
25767
+ domain: "generic",
25768
+ mvpSuggestion: needsBackend ? "\u4E0A\u4F20\u63A5\u53E3 + xlsx \u89E3\u6790 + SQLite/\u6587\u4EF6\u5B58\u50A8\uFF0C\u6240\u6709\u8BBF\u5BA2\u8BFB\u53D6\u6700\u65B0\u56FE\u8868\u6570\u636E" : "Agent \u89E3\u6790 xlsx \u751F\u6210 JSON\uFF0C\u9759\u6001\u56FE\u8868\u7AD9\u8BFB\u53D6 JSON \u6E32\u67D3",
25769
+ productionSuggestion: "\u9700\u8981\u5386\u53F2\u7248\u672C\u3001\u591A\u4EBA\u4E0A\u4F20\u6216\u6743\u9650\u65F6\u518D\u8865\u540E\u7AEF\u548C\u6570\u636E\u5E93",
25770
+ reasoning: ["\u5B9A\u671F\u63D0\u4F9B xlsx \u4E0D\u7B49\u4E8E\u5FC5\u987B\u540E\u53F0\uFF1BAgent-assisted \u66F4\u65B0\u53EF\u5148\u9759\u6001\u5316\u3002"],
25771
+ technicalProfile,
25772
+ pmIntentDecision: decision
25773
+ };
25774
+ }
25775
+ return null;
25776
+ }
25173
25777
  function decideArchitecture(productType, platform, features, commercialIntent, expectedUsers) {
25174
25778
  const featureText = features.join(" ");
25175
25779
  const allText = `${productType} ${featureText}`;
@@ -25199,6 +25803,12 @@ function decideArchitecture(productType, platform, features, commercialIntent, e
25199
25803
  expected_users: expectedUsers,
25200
25804
  commercial_intent: commercialIntent
25201
25805
  });
25806
+ const pmIntentDecision = decidePmIntent(allText, {
25807
+ expected_users: expectedUsers,
25808
+ commercial_intent: commercialIntent
25809
+ });
25810
+ const pmGateArchitecture2 = domain === "generic" ? buildPmGateArchitectureDecision(pmIntentDecision, technicalProfile) : null;
25811
+ if (pmGateArchitecture2) return pmGateArchitecture2;
25202
25812
  const contentCommunityDomain = domain === "content_community";
25203
25813
  const singleUserCrm = domain === "crm" && isSingleUserCrmContext(allText, { expected_users: expectedUsers });
25204
25814
  const personalLocalSignal = domain === "generic" && expectedUsers !== "enterprise" && expectedUsers !== "massive" && !commercialIntent && isLocalFirstProfile(technicalProfile);
@@ -26027,6 +26637,7 @@ var AcceptanceGenerateOutputSchema = external_exports.object({
26027
26637
  productType: external_exports.string(),
26028
26638
  platform: external_exports.string(),
26029
26639
  technicalProfile: TechnicalProfileSchema.optional(),
26640
+ pmIntentDecision: PmIntentDecisionSchema.optional(),
26030
26641
  categories: external_exports.array(
26031
26642
  external_exports.object({
26032
26643
  category: external_exports.string(),
@@ -26151,15 +26762,36 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
26151
26762
  has_auth: hasAuth
26152
26763
  });
26153
26764
  const featureText = buildFeatureText(productType, features);
26765
+ const pmIntentDecision = decidePmIntent(featureText, {
26766
+ has_backend: hasBackend,
26767
+ has_payment: hasPayment,
26768
+ has_auth: hasAuth
26769
+ });
26154
26770
  const domain = classifyProductDomain(productType, { features }).domain;
26155
26771
  const inferredBackend = hasBackend || technicalProfile.needsBackend;
26156
26772
  const inferredAuth = hasAuth || technicalProfile.needsAuth;
26157
26773
  const inferredPayment = hasPayment || technicalProfile.blockers.some((blocker) => blocker.includes("\u652F\u4ED8"));
26774
+ if (domain === "generic" && ["multi_user_collaboration", "content_marketing_site", "data_visualization_site"].includes(pmIntentDecision.needType)) {
26775
+ return {
26776
+ productType,
26777
+ platform,
26778
+ technicalProfile,
26779
+ pmIntentDecision,
26780
+ categories: buildPmGateAcceptanceCategories(pmIntentDecision),
26781
+ definitionOfDone: [
26782
+ "\u6838\u5FC3\u8FB9\u754C\u5DF2\u6309 PM Gate \u786E\u8BA4",
26783
+ "\u684C\u9762\u7AEF\u548C\u79FB\u52A8\u7AEF\u9A8C\u6536\u901A\u8FC7",
26784
+ "\u63A7\u5236\u53F0\u65E0\u660E\u663E\u62A5\u9519",
26785
+ "\u65E0 P0/P1 Bug"
26786
+ ]
26787
+ };
26788
+ }
26158
26789
  if (isStaticDisplaySite(productType, features, platform, inferredBackend, inferredPayment, inferredAuth)) {
26159
26790
  return {
26160
26791
  productType,
26161
26792
  platform,
26162
26793
  technicalProfile,
26794
+ pmIntentDecision,
26163
26795
  categories: buildStaticDisplayAcceptanceCategories(),
26164
26796
  definitionOfDone: [
26165
26797
  "\u6240\u6709\u5360\u4F4D\u5185\u5BB9\u5DF2\u66FF\u6362\u4E3A\u771F\u5B9E\u5185\u5BB9",
@@ -26184,6 +26816,7 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
26184
26816
  productType,
26185
26817
  platform,
26186
26818
  technicalProfile,
26819
+ pmIntentDecision,
26187
26820
  categories: buildLocalFirstAcceptanceCategories(technicalProfile, productType, features),
26188
26821
  definitionOfDone: [
26189
26822
  "\u6838\u5FC3\u529F\u80FD\u6309\u9700\u6C42\u5B9E\u73B0",
@@ -26566,10 +27199,86 @@ function generateAcceptance(productType, features, platform, hasBackend, hasPaym
26566
27199
  productType,
26567
27200
  platform,
26568
27201
  technicalProfile,
27202
+ pmIntentDecision,
26569
27203
  categories,
26570
27204
  definitionOfDone: [...acceptanceRules_default.definition_of_done]
26571
27205
  };
26572
27206
  }
27207
+ function buildPmGateAcceptanceCategories(decision) {
27208
+ if (decision.needType === "multi_user_collaboration") {
27209
+ return [
27210
+ {
27211
+ category: "\u591A\u4EBA\u534F\u4F5C\u6D41\u7A0B\u9A8C\u6536",
27212
+ items: [
27213
+ "\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u5B89\u6392\u7684\u4EFB\u52A1\u4FDD\u5B58\u540E\u7ACB\u5373\u8FDB\u5165\u81EA\u5DF1\u7684\u65E5\u7A0B",
27214
+ "\u7ED9\u5BA4\u53CB\u6216\u6210\u5458\u5B89\u6392\u7684\u4EFB\u52A1\u5148\u8FDB\u5165\u5F85\u8BA4\u9886\u72B6\u6001\uFF0C\u4E0D\u80FD\u76F4\u63A5\u53D8\u6210\u5BF9\u65B9\u5DF2\u786E\u8BA4\u65E5\u7A0B",
27215
+ "\u5BF9\u65B9\u8BA4\u9886\u4EFB\u52A1\u540E\uFF0C\u4EFB\u52A1\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\u5E76\u4FDD\u7559\u8BA4\u9886\u65F6\u95F4",
27216
+ "\u4EFB\u52A1\u5B8C\u6210\u3001\u53D6\u6D88\u6216\u91CD\u65B0\u5206\u914D\u540E\uFF0C\u6240\u6709\u6210\u5458\u5237\u65B0\u9875\u9762\u770B\u5230\u4E00\u81F4\u72B6\u6001"
27217
+ ]
27218
+ },
27219
+ {
27220
+ category: "\u65E5\u7A0B\u4E0E\u8BBF\u95EE\u8FB9\u754C\u9A8C\u6536",
27221
+ items: [
27222
+ "\u540C\u4E00\u65F6\u95F4\u6BB5\u7684\u4EFB\u52A1\u6309\u5DF2\u786E\u8BA4\u89C4\u5219\u5E76\u6392\u5C55\u793A\u3001\u9AD8\u4EAE\u51B2\u7A81\u6216\u963B\u6B62\u5B89\u6392",
27223
+ "\u8BBF\u95EE\u65B9\u5F0F\u5FC5\u987B\u5728\u5C40\u57DF\u7F51\u3001\u672C\u673A\u516C\u7F51 IP \u6216\u57DF\u540D HTTPS \u4E2D\u660E\u786E\u4E00\u79CD",
27224
+ "\u591A\u4EBA\u8FD0\u884C\u65F6\u534F\u4F5C\u6570\u636E\u4E0D\u5F97\u5206\u522B\u4FDD\u5B58\u5728\u5404\u81EA\u6D4F\u89C8\u5668 localStorage \u91CC",
27225
+ "SQLite \u6570\u636E\u6587\u4EF6\u6216\u7B49\u4EF7\u6301\u4E45\u5316\u6587\u4EF6\u91CD\u542F\u670D\u52A1\u540E\u4ECD\u80FD\u6062\u590D\u4EFB\u52A1\u548C\u6210\u5458\u6570\u636E"
27226
+ ]
27227
+ }
27228
+ ];
27229
+ }
27230
+ if (decision.needType === "content_marketing_site") {
27231
+ return [
27232
+ {
27233
+ category: "\u5185\u5BB9\u8425\u9500\u7AD9\u9A8C\u6536",
27234
+ items: [
27235
+ "FAQ\u3001\u7167\u7247\u3001\u4FC3\u9500\u6D3B\u52A8\u3001\u6559\u7EC3\u6216\u56E2\u961F\u4FE1\u606F\u80FD\u4ECE\u5185\u5BB9\u6587\u4EF6\u6E32\u67D3\u5230\u9875\u9762",
27236
+ "Agent \u66F4\u65B0\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u7EBF\u4E0A\u9875\u9762\u5C55\u793A\u6700\u65B0\u5185\u5BB9",
27237
+ "\u9875\u9762\u5305\u542B\u9762\u5411\u672C\u5730\u66DD\u5149\u7684\u6807\u9898\u3001\u63CF\u8FF0\u3001\u7ED3\u6784\u5316 FAQ \u548C sitemap \u57FA\u7840\u4FE1\u606F",
27238
+ "\u79FB\u52A8\u7AEF\u9996\u5C4F\u3001\u56FE\u7247\u5217\u8868\u3001\u6D3B\u52A8\u4FE1\u606F\u548C\u8054\u7CFB\u65B9\u5F0F\u5747\u6B63\u5E38\u5C55\u793A"
27239
+ ]
27240
+ },
27241
+ {
27242
+ category: "\u7EF4\u62A4\u8FB9\u754C\u9A8C\u6536",
27243
+ items: [
27244
+ "\u5185\u5BB9\u7ECF\u5E38\u4FEE\u6539\u65F6\u9ED8\u8BA4\u6309 Agent-assisted \u5185\u5BB9\u6587\u4EF6\u7EF4\u62A4\uFF0C\u4E0D\u5F3A\u5236\u751F\u6210 CMS \u540E\u53F0",
27245
+ "\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u7F51\u9875\u7F16\u8F91\u3001\u56FE\u7247\u4E0A\u4F20\u3001\u591A\u4EBA\u7EF4\u62A4\u6216\u8BBF\u5BA2\u63D0\u4EA4\u65F6\u624D\u5F15\u5165\u540E\u7AEF",
27246
+ "\u8BBF\u5BA2\u53CD\u9988\u6216\u9884\u7EA6\u63D0\u4EA4\u5982\u679C\u8FDB\u5165 MVP\uFF0C\u5FC5\u987B\u6709\u540E\u7AEF\u4FDD\u5B58\u3001\u5BA1\u6838\u6216\u9632\u5783\u573E\u7B56\u7565"
27247
+ ]
27248
+ }
27249
+ ];
27250
+ }
27251
+ if (decision.needType === "data_visualization_site") {
27252
+ return [
27253
+ {
27254
+ category: "\u6570\u636E\u56FE\u8868\u7AD9\u9A8C\u6536",
27255
+ items: [
27256
+ "Agent \u80FD\u4ECE\u65B0 xlsx \u6216 CSV \u751F\u6210\u9875\u9762\u8BFB\u53D6\u7684\u56FE\u8868\u6570\u636E\u6587\u4EF6",
27257
+ "\u9875\u9762\u8BFB\u53D6\u6700\u65B0\u6570\u636E\u6587\u4EF6\u540E\uFF0C\u56FE\u8868\u3001\u6307\u6807\u5361\u548C\u8868\u683C\u7ED3\u679C\u4E00\u81F4",
27258
+ "\u66FF\u6362\u6570\u636E\u5E76\u91CD\u65B0\u90E8\u7F72\u540E\uFF0C\u7EBF\u4E0A\u9875\u9762\u5C55\u793A\u6700\u65B0\u7ED3\u679C",
27259
+ "\u6570\u636E\u4E3A\u7A7A\u3001\u5B57\u6BB5\u7F3A\u5931\u6216\u683C\u5F0F\u9519\u8BEF\u65F6\u9875\u9762\u6709\u660E\u786E\u63D0\u793A\uFF0C\u4E0D\u663E\u793A\u65E7\u7ED3\u679C"
27260
+ ]
27261
+ },
27262
+ {
27263
+ category: "\u6570\u636E\u66F4\u65B0\u8FB9\u754C\u9A8C\u6536",
27264
+ items: [
27265
+ "\u9ED8\u8BA4\u4E0D\u8981\u6C42\u540E\u53F0\u4E0A\u4F20\u3001\u6570\u636E\u5E93\u6216\u767B\u5F55\u6743\u9650",
27266
+ "\u53EA\u6709\u7528\u6237\u660E\u786E\u8981\u6C42\u7F51\u9875\u4E0A\u4F20\u3001\u591A\u4EBA\u4E0A\u4F20\u3001\u5386\u53F2\u7248\u672C\u6216\u6743\u9650\u63A7\u5236\u65F6\u624D\u5347\u7EA7\u540E\u7AEF",
27267
+ "\u5982\u679C\u516C\u5F00\u5C55\u793A\uFF0C\u90E8\u7F72\u5730\u5740\u548C\u6570\u636E\u8131\u654F\u8FB9\u754C\u5FC5\u987B\u660E\u786E"
27268
+ ]
27269
+ }
27270
+ ];
27271
+ }
27272
+ return [
27273
+ {
27274
+ category: "PM Gate \u9A8C\u6536",
27275
+ items: [
27276
+ "\u4F7F\u7528\u8005\u3001\u7EF4\u62A4\u65B9\u5F0F\u548C\u8BBF\u95EE\u65B9\u5F0F\u5DF2\u786E\u8BA4",
27277
+ "MVP \u6280\u672F\u65B9\u6848\u6CA1\u6709\u8D85\u51FA\u5DF2\u786E\u8BA4\u8FB9\u754C"
27278
+ ]
27279
+ }
27280
+ ];
27281
+ }
26573
27282
  function hasFeatureSignal(productType, features, signals) {
26574
27283
  const text = buildFeatureText(productType, features).toLowerCase();
26575
27284
  return signals.some((signal) => text.includes(signal.toLowerCase()));
@@ -26895,6 +27604,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
26895
27604
  executed: external_exports.boolean(),
26896
27605
  result: external_exports.union([
26897
27606
  SpecInterrogateOutputSchema,
27607
+ SpecCompileOutputSchema,
26898
27608
  UiTranslateOutputSchema,
26899
27609
  DebugGuideOutputSchema,
26900
27610
  ArchitectureDecideOutputSchema
@@ -26903,6 +27613,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
26903
27613
  type: external_exports.enum([
26904
27614
  "answer_questions",
26905
27615
  "compile_spec",
27616
+ "confirm_spec",
26906
27617
  "translate_ui",
26907
27618
  "provide_debug_info",
26908
27619
  "review_launch_readiness",
@@ -26912,6 +27623,7 @@ var ProductSpecAssistOutputSchema = external_exports.object({
26912
27623
  suggestedTool: external_exports.string().optional()
26913
27624
  }),
26914
27625
  technicalProfile: TechnicalProfileSchema.optional(),
27626
+ pmIntentDecision: PmIntentDecisionSchema.optional(),
26915
27627
  quickQuestions: external_exports.array(QuickQuestionSchema),
26916
27628
  agentGuidance: external_exports.array(external_exports.string())
26917
27629
  });
@@ -26977,6 +27689,276 @@ function isExplicitLaunchInquiry(text) {
26977
27689
  return launchSignals.some((kw) => text.includes(kw)) && inquirySignals.some((kw) => text.includes(kw)) && !debugSignals.some((kw) => text.includes(kw));
26978
27690
  }
26979
27691
 
27692
+ // src/core/remotePmIntentGate.ts
27693
+ var import_node_crypto = require("node:crypto");
27694
+ function shouldUseRemoteGate(local, mode = process.env.PRODUCT_SPEC_REMOTE_GATE_MODE || "auto") {
27695
+ if (mode === "off") return false;
27696
+ if (!process.env.PRODUCT_SPEC_REMOTE_GATE_URL) return false;
27697
+ if (mode === "force") return true;
27698
+ return local.confidence === "low" || local.needType === "unknown" || local.technicalShape === "unknown" || hasRouteShapeConflict(local);
27699
+ }
27700
+ async function callRemotePmIntentGate(message, context, localDecision) {
27701
+ if (!shouldUseRemoteGate(localDecision)) return null;
27702
+ const url = process.env.PRODUCT_SPEC_REMOTE_GATE_URL;
27703
+ if (!url) return null;
27704
+ const controller = new AbortController();
27705
+ const timeout = Number(process.env.PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS || 2500);
27706
+ const timer = setTimeout(() => controller.abort(), timeout);
27707
+ try {
27708
+ const response = await fetch(url, {
27709
+ method: "POST",
27710
+ headers: {
27711
+ "content-type": "application/json",
27712
+ ...process.env.PRODUCT_SPEC_REMOTE_GATE_TOKEN ? { authorization: `Bearer ${process.env.PRODUCT_SPEC_REMOTE_GATE_TOKEN}` } : {},
27713
+ "x-product-spec-telemetry": process.env.PRODUCT_SPEC_TELEMETRY || "off"
27714
+ },
27715
+ body: JSON.stringify({
27716
+ message: truncateForRemote(message),
27717
+ context,
27718
+ packageVersion: process.env.npm_package_version,
27719
+ client: "product-spec-mcp",
27720
+ messageHash: hashMessage(message),
27721
+ ruleDecision: summarizeDecision(localDecision),
27722
+ choices: {
27723
+ needType: [
27724
+ "static_display",
27725
+ "personal_local_tool",
27726
+ "multi_user_collaboration",
27727
+ "content_marketing_site",
27728
+ "data_visualization_site",
27729
+ "transaction_workflow",
27730
+ "content_knowledge",
27731
+ "ai_automation",
27732
+ "unknown"
27733
+ ],
27734
+ usageScope: ["self", "fixed_group", "public_audience", "unknown"],
27735
+ maintenanceMode: [
27736
+ "agent_assisted",
27737
+ "manual_files",
27738
+ "web_admin",
27739
+ "visitor_submission",
27740
+ "runtime_collaboration",
27741
+ "unknown"
27742
+ ],
27743
+ accessTopology: ["single_device", "lan_only", "internet_ip", "public_domain", "unknown"]
27744
+ }
27745
+ }),
27746
+ signal: controller.signal
27747
+ });
27748
+ if (!response.ok) {
27749
+ return {
27750
+ decision: localDecision,
27751
+ meta: { used: false, fallbackReason: `remote_http_${response.status}` }
27752
+ };
27753
+ }
27754
+ const payload = await response.json();
27755
+ if (!payload.decision) {
27756
+ return {
27757
+ decision: localDecision,
27758
+ meta: { used: false, fallbackReason: "remote_missing_decision" }
27759
+ };
27760
+ }
27761
+ const sanitized = sanitizeRemoteDecision(payload.decision);
27762
+ if (!sanitized) {
27763
+ return {
27764
+ decision: localDecision,
27765
+ meta: { used: false, fallbackReason: "remote_invalid_schema" }
27766
+ };
27767
+ }
27768
+ const merged = mergeRemoteDecision(localDecision, sanitized);
27769
+ return {
27770
+ decision: merged,
27771
+ meta: {
27772
+ used: payload.llmGate?.used ?? true,
27773
+ provider: payload.llmGate?.provider,
27774
+ model: payload.llmGate?.model,
27775
+ cacheHit: payload.llmGate?.cacheHit,
27776
+ promptTokensApprox: payload.llmGate?.promptTokensApprox,
27777
+ completionTokensApprox: payload.llmGate?.completionTokensApprox,
27778
+ rateLimit: payload.rateLimit
27779
+ }
27780
+ };
27781
+ } catch (error2) {
27782
+ return {
27783
+ decision: localDecision,
27784
+ meta: {
27785
+ used: false,
27786
+ fallbackReason: error2 instanceof Error ? error2.name : "remote_error"
27787
+ }
27788
+ };
27789
+ } finally {
27790
+ clearTimeout(timer);
27791
+ }
27792
+ }
27793
+ function mergeRemoteDecision(local, remote) {
27794
+ const needType = remote.bestGate || remote.needType || local.needType;
27795
+ const draft = {
27796
+ ...local,
27797
+ ...remote,
27798
+ needType,
27799
+ source: "merged",
27800
+ strongSignals: mergeStrings(local.strongSignals, remote.strongSignals),
27801
+ weakSignals: mergeStrings(local.weakSignals, remote.weakSignals),
27802
+ coreObjects: mergeStrings(local.coreObjects, remote.coreObjects),
27803
+ states: mergeStrings(local.states, remote.states),
27804
+ actions: mergeStrings(local.actions, remote.actions),
27805
+ mustNotUse: mergeStrings(local.mustNotUse, remote.mustNotUse),
27806
+ boundaryQuestionIds: mergeStrings(local.boundaryQuestionIds, remote.boundaryQuestionIds),
27807
+ defaultAssumptions: mergeStrings(local.defaultAssumptions, remote.defaultAssumptions)
27808
+ };
27809
+ return enforceRemoteHardRules(draft, local);
27810
+ }
27811
+ function sanitizeRemoteDecision(remote) {
27812
+ const sanitized = {};
27813
+ if (remote.bestGate !== void 0) {
27814
+ if (!needTypes.includes(remote.bestGate)) return null;
27815
+ sanitized.bestGate = remote.bestGate;
27816
+ }
27817
+ if (remote.needType !== void 0) {
27818
+ if (!needTypes.includes(remote.needType)) return null;
27819
+ sanitized.needType = remote.needType;
27820
+ }
27821
+ if (remote.usageScope !== void 0) {
27822
+ if (!usageScopes.includes(remote.usageScope)) return null;
27823
+ sanitized.usageScope = remote.usageScope;
27824
+ }
27825
+ if (remote.maintenanceMode !== void 0) {
27826
+ if (!maintenanceModes.includes(remote.maintenanceMode)) return null;
27827
+ sanitized.maintenanceMode = remote.maintenanceMode;
27828
+ }
27829
+ if (remote.accessTopology !== void 0) {
27830
+ if (!accessTopologies.includes(remote.accessTopology)) return null;
27831
+ sanitized.accessTopology = remote.accessTopology;
27832
+ }
27833
+ if (remote.technicalShape !== void 0) {
27834
+ if (!technicalShapes.includes(remote.technicalShape)) return null;
27835
+ sanitized.technicalShape = remote.technicalShape;
27836
+ }
27837
+ if (remote.recommendedDeployment !== void 0) {
27838
+ if (!recommendedDeployments.includes(remote.recommendedDeployment)) return null;
27839
+ sanitized.recommendedDeployment = remote.recommendedDeployment;
27840
+ }
27841
+ if (remote.route !== void 0) {
27842
+ if (!routes.includes(remote.route)) return null;
27843
+ sanitized.route = remote.route;
27844
+ }
27845
+ if (remote.confidence !== void 0) {
27846
+ if (!confidences.includes(remote.confidence)) return null;
27847
+ sanitized.confidence = remote.confidence;
27848
+ }
27849
+ copyStringArray(remote, sanitized, "strongSignals");
27850
+ copyStringArray(remote, sanitized, "weakSignals");
27851
+ copyStringArray(remote, sanitized, "coreObjects");
27852
+ copyStringArray(remote, sanitized, "states");
27853
+ copyStringArray(remote, sanitized, "actions");
27854
+ copyStringArray(remote, sanitized, "mustNotUse");
27855
+ copyStringArray(remote, sanitized, "boundaryQuestionIds");
27856
+ copyStringArray(remote, sanitized, "defaultAssumptions");
27857
+ if (remote.source !== void 0) {
27858
+ if (!sources.includes(remote.source)) return null;
27859
+ sanitized.source = remote.source;
27860
+ }
27861
+ return sanitized;
27862
+ }
27863
+ function copyStringArray(remote, sanitized, key) {
27864
+ const value = remote[key];
27865
+ if (value === void 0) return;
27866
+ if (!Array.isArray(value) || !value.every((item) => typeof item === "string")) return;
27867
+ sanitized[key] = value;
27868
+ }
27869
+ function enforceRemoteHardRules(remote, local) {
27870
+ const hasCollaboration = local.needType === "multi_user_collaboration" || remote.needType === "multi_user_collaboration" || mergeStrings(local.strongSignals, remote.strongSignals).some((signal) => /多人|共享|协作|认领|相互安排/.test(signal));
27871
+ if (hasCollaboration) {
27872
+ return {
27873
+ ...remote,
27874
+ needType: "multi_user_collaboration",
27875
+ maintenanceMode: "runtime_collaboration",
27876
+ technicalShape: "light_backend_json_sqlite",
27877
+ route: "spec_interrogate",
27878
+ mustNotUse: mergeStrings(remote.mustNotUse, ["static_display", "local_storage_only"])
27879
+ };
27880
+ }
27881
+ const hasSensitiveBackendSignal = mergeStrings(local.strongSignals, remote.strongSignals).some(
27882
+ (signal) => /支付|订单|AI|公开提交|访客提交/.test(signal)
27883
+ );
27884
+ if (hasSensitiveBackendSignal && ["static_page", "local_storage_tool", "local_json_import_export"].includes(remote.technicalShape)) {
27885
+ return {
27886
+ ...remote,
27887
+ technicalShape: "full_backend_saas",
27888
+ route: "spec_interrogate",
27889
+ mustNotUse: mergeStrings(remote.mustNotUse, ["frontend_only"])
27890
+ };
27891
+ }
27892
+ return remote;
27893
+ }
27894
+ function hasRouteShapeConflict(decision) {
27895
+ return decision.route === "architecture_decide" && decision.technicalShape !== "static_page";
27896
+ }
27897
+ function summarizeDecision(decision) {
27898
+ return {
27899
+ needType: decision.needType,
27900
+ usageScope: decision.usageScope,
27901
+ maintenanceMode: decision.maintenanceMode,
27902
+ accessTopology: decision.accessTopology,
27903
+ technicalShape: decision.technicalShape,
27904
+ confidence: decision.confidence,
27905
+ strongSignals: decision.strongSignals,
27906
+ weakSignals: decision.weakSignals,
27907
+ conflict: hasRouteShapeConflict(decision)
27908
+ };
27909
+ }
27910
+ function truncateForRemote(message) {
27911
+ return message.length <= 500 ? message : `${message.slice(0, 500)}\u2026`;
27912
+ }
27913
+ function hashMessage(message) {
27914
+ return (0, import_node_crypto.createHash)("sha256").update(message.trim().replace(/\s+/g, " ")).digest("hex");
27915
+ }
27916
+ function mergeStrings(a = [], b = []) {
27917
+ return Array.from(new Set([...a, ...b].filter(Boolean)));
27918
+ }
27919
+ var needTypes = [
27920
+ "static_display",
27921
+ "personal_local_tool",
27922
+ "multi_user_collaboration",
27923
+ "content_marketing_site",
27924
+ "data_visualization_site",
27925
+ "transaction_workflow",
27926
+ "content_knowledge",
27927
+ "ai_automation",
27928
+ "unknown"
27929
+ ];
27930
+ var usageScopes = ["self", "fixed_group", "public_audience", "unknown"];
27931
+ var maintenanceModes = [
27932
+ "agent_assisted",
27933
+ "manual_files",
27934
+ "web_admin",
27935
+ "visitor_submission",
27936
+ "runtime_collaboration",
27937
+ "unknown"
27938
+ ];
27939
+ var accessTopologies = ["single_device", "lan_only", "internet_ip", "public_domain", "unknown"];
27940
+ var technicalShapes = [
27941
+ "static_page",
27942
+ "local_storage_tool",
27943
+ "local_json_import_export",
27944
+ "static_json_data_page",
27945
+ "light_backend_json_sqlite",
27946
+ "full_backend_saas",
27947
+ "unknown"
27948
+ ];
27949
+ var recommendedDeployments = [
27950
+ "static_only",
27951
+ "local_browser_only",
27952
+ "static_hosting_with_agent_updates",
27953
+ "local_lan_server_sqlite",
27954
+ "cheap_vps_sqlite_by_ip",
27955
+ "vps_domain_https",
27956
+ "unknown"
27957
+ ];
27958
+ var routes = ["spec_compile", "spec_interrogate", "architecture_decide"];
27959
+ var confidences = ["high", "medium", "low"];
27960
+ var sources = ["local_rule", "online_llm", "merged"];
27961
+
26980
27962
  // src/core/assistEngine.ts
26981
27963
  function executeAssist(message, knownContext, preferredPlatform = "unknown", strictness = "normal", autoExecute = true) {
26982
27964
  const routed = routeIntent(message);
@@ -26994,6 +27976,28 @@ function executeAssist(message, knownContext, preferredPlatform = "unknown", str
26994
27976
  return handleUnknown(routed);
26995
27977
  }
26996
27978
  }
27979
+ async function executeAssistWithRemoteGate(message, knownContext, preferredPlatform = "unknown", strictness = "normal", autoExecute = true) {
27980
+ const result = executeAssist(message, knownContext, preferredPlatform, strictness, autoExecute);
27981
+ if (result.routedIntent.scenario !== "build_product" || !result.pmIntentDecision) return result;
27982
+ const remote = await callRemotePmIntentGate(message, knownContext || {}, result.pmIntentDecision);
27983
+ if (!remote) return result;
27984
+ const merged = remote.decision;
27985
+ if (merged.needType !== result.pmIntentDecision.needType && ["multi_user_collaboration", "content_marketing_site", "data_visualization_site"].includes(merged.needType)) {
27986
+ const technicalProfile = buildTechnicalProfile(message, knownContext || {});
27987
+ const questions = merged.needType === "multi_user_collaboration" ? buildMultiUserCollaborationQuickQuestions() : merged.needType === "content_marketing_site" ? buildContentMarketingQuickQuestions() : buildDataVisualizationQuickQuestions();
27988
+ return appendRemoteGateMeta(
27989
+ buildPmGateInterrogateResult(
27990
+ message,
27991
+ result.routedIntent,
27992
+ technicalProfile,
27993
+ merged,
27994
+ questions
27995
+ ),
27996
+ remote.meta.fallbackReason
27997
+ );
27998
+ }
27999
+ return appendRemoteGateMeta({ ...result, pmIntentDecision: merged }, remote.meta.fallbackReason);
28000
+ }
26997
28001
  function detectPlatform(message, preferred) {
26998
28002
  if (preferred !== "unknown") return preferred;
26999
28003
  if (message.includes("\u5C0F\u7A0B\u5E8F")) return "mini_program";
@@ -27003,8 +28007,18 @@ function detectPlatform(message, preferred) {
27003
28007
  }
27004
28008
  function handleBuildProduct(message, knownContext, strictness, autoExecute, routed) {
27005
28009
  const technicalProfile = buildTechnicalProfile(message, knownContext || {});
27006
- if (isStaticDisplaySite2(message)) {
27007
- return handleStaticDisplaySite(message, autoExecute, routed);
28010
+ const pmIntentDecision = decidePmIntent(message, knownContext || {});
28011
+ if (pmIntentDecision.needType === "static_display" && isStaticDisplaySite2(message)) {
28012
+ return withPmDecision(handleStaticDisplaySite(message, autoExecute, routed), pmIntentDecision);
28013
+ }
28014
+ if (pmIntentDecision.needType === "multi_user_collaboration") {
28015
+ return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildMultiUserCollaborationQuickQuestions());
28016
+ }
28017
+ if (pmIntentDecision.needType === "content_marketing_site") {
28018
+ return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildContentMarketingQuickQuestions());
28019
+ }
28020
+ if (pmIntentDecision.needType === "data_visualization_site") {
28021
+ return buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, buildDataVisualizationQuickQuestions());
27008
28022
  }
27009
28023
  if (!autoExecute) {
27010
28024
  const quickQuestions2 = buildProductQuickQuestions(message, knownContext);
@@ -27018,6 +28032,7 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
27018
28032
  suggestedTool: "spec_interrogate"
27019
28033
  },
27020
28034
  technicalProfile,
28035
+ pmIntentDecision,
27021
28036
  quickQuestions: quickQuestions2,
27022
28037
  agentGuidance: [
27023
28038
  "\u53EA\u5C55\u793A quickQuestions \u4E2D\u7684\u9009\u9879\uFF0C\u4E0D\u8981\u81EA\u884C\u5408\u5E76\u6216\u5220\u6539\u95EE\u9898\u3002",
@@ -27043,21 +28058,69 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
27043
28058
  const structured = buildInterrogateStructuredOutput(readiness, clarification, technicalProfile);
27044
28059
  const domainClassification = classifyProductDomain(message, knownContext || {});
27045
28060
  const quickQuestions = buildProductQuickQuestions(message, knownContext);
28061
+ const localFirstGeneric = domainClassification.domain === "generic" && isLocalFirstProfile(technicalProfile);
27046
28062
  const domainPackWarning = domainClassification.domain === "generic" ? "\n\n> \u26A0\uFE0F \u5F53\u524D\u53EA\u8BC6\u522B\u4E3A\u4EA7\u54C1\u5F00\u53D1\u610F\u56FE\uFF0C\u4F46\u672A\u547D\u4E2D\u7A33\u5B9A domain pack\u3002\u540E\u7EED `spec_compile` \u5E94\u4F5C\u4E3A\u8349\u6848\u5904\u7406\uFF0C\u4E0D\u8981\u9759\u9ED8\u5957\u7528\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u3001\u77E5\u8BC6\u5E93\u6216 CRM \u6A21\u677F\u3002" : "";
28063
+ const localFirstDefaultNote = localFirstGeneric ? `
28064
+
28065
+ ## \u5C0F\u767D\u9ED8\u8BA4\u8DEF\u5F84
28066
+
28067
+ \u8FD9\u662F\u4E2A\u4EBA\u672C\u5730\u5C0F\u5DE5\u5177\u3002\u4E0D\u8981\u8981\u6C42\u7528\u6237\u9010\u9879\u56DE\u7B54\u5168\u90E8 quickQuestions\uFF1B\u53EF\u4EE5\u5148\u91C7\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u8FDB\u5165 \`spec_compile\`\uFF0C\u751F\u6210 Draft \u89C4\u683C\u3002
28068
+
28069
+ \u201C\u9875\u9762\u9AD8\u7EA7\u4E00\u70B9\u201D\u53EA\u5F71\u54CD UI \u98CE\u683C\u3001\u5E03\u5C40\u548C\u9A8C\u6536\u6807\u51C6\uFF0C\u4E0D\u662F\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u4FE1\u53F7\uFF1B\u9AD8\u7EA7\u9875\u9762\u53EF\u4EE5\u4ECD\u7136\u4F7F\u7528 localStorage\u3002
28070
+
28071
+ \u5982\u9700\u786E\u8BA4\uFF0C\u53EA\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u95EE\u9898\uFF1A\u662F\u5426\u6309\u201C\u6D4F\u89C8\u5668\u672C\u5730\u4FDD\u5B58\u3001\u4E0D\u767B\u5F55\u4E0D\u505A\u540E\u53F0\u3001\u652F\u6301\u65B0\u589E\u7F16\u8F91\u5220\u9664\u548C\u641C\u7D22\u7B5B\u9009\u3001\u63D0\u9192\u5728\u9875\u9762\u5185\u7528\u72B6\u6001\u548C\u5217\u8868\u5C55\u793A\u201D\u7EE7\u7EED\uFF1F` : "";
28072
+ if (localFirstGeneric) {
28073
+ const spec = buildSpec(message, knownContext || {}, readiness);
28074
+ const effectiveReadiness = {
28075
+ ...readiness,
28076
+ score: spec.readinessScore,
28077
+ status: spec.readinessStatus
28078
+ };
28079
+ const confirmation = buildConfirmation(spec);
28080
+ const compileMarkdown = formatCompileResult("draft", effectiveReadiness, void 0, spec, confirmation);
28081
+ const compileStructured = buildCompileStructuredOutput("draft", effectiveReadiness, spec, confirmation);
28082
+ return {
28083
+ routedIntent: routed,
28084
+ selectedTool: "spec_compile",
28085
+ executed: true,
28086
+ result: compileStructured,
28087
+ nextAction: {
28088
+ type: "confirm_spec",
28089
+ message: "\u5DF2\u6309\u672C\u5730\u5C0F\u5DE5\u5177\u9ED8\u8BA4\u503C\u751F\u6210 MVP \u8349\u6848\uFF1B\u8BF7\u786E\u8BA4\u9ED8\u8BA4\u5047\u8BBE\u5373\u53EF\uFF0C\u4E0D\u8981\u8BA9\u5C0F\u767D\u7528\u6237\u9010\u9879\u586B\u5199\u7ED3\u6784\u5316\u95EE\u9898\u3002",
28090
+ suggestedTool: "spec_compile"
28091
+ },
28092
+ technicalProfile,
28093
+ pmIntentDecision,
28094
+ quickQuestions,
28095
+ agentGuidance: [
28096
+ "\u9762\u5411\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u65F6\uFF0C\u4E0D\u8981\u628A quickQuestions \u539F\u6837\u629B\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u8981\u8981\u6C42\u7528\u6237\u56DE\u7B54\u7C7B\u4F3C\u201CB + a\u201D\u7684\u7ED3\u6784\u5316\u9009\u9879\uFF1B\u5DF2\u751F\u6210 MVP \u8349\u6848\uFF0C\u6700\u591A\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u786E\u8BA4\u3002\u9875\u9762\u9AD8\u7EA7\u611F\u53EA\u5F71\u54CD UI\uFF0C\u4E0D\u8981\u56E0\u6B64\u7EA0\u504F\u6210\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u3002",
28097
+ "\u4E0D\u8981\u628A\u7528\u6237\u7AEF\u767B\u5F55\u548C\u540E\u53F0\u7BA1\u7406\u5458\u767B\u5F55\u5408\u5E76\u6210\u540C\u4E00\u4E2A\u5B57\u6BB5\u3002",
28098
+ "\u5982\u679C\u7528\u6237\u53EA\u9700\u8981\u5BFC\u51FA\uFF0C\u4E0D\u8981\u64C5\u81EA\u6269\u5C55\u6210\u5B8C\u6574\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF\u3002",
28099
+ "\u672A\u547D\u4E2D\u7A33\u5B9A domain pack \u65F6\uFF0C\u5E94\u4F7F\u7528 generic MVP \u8349\u6848\uFF0C\u4E0D\u8981\u5957\u7528\u62A5\u540D\u3001\u7535\u5546\u3001\u9884\u7EA6\u3001\u5185\u5BB9\u793E\u533A\u3001\u5DE5\u5355\u3001\u77E5\u8BC6\u5E93\u6216 CRM \u6A21\u677F\u3002"
28100
+ ],
28101
+ markdown: `# \u8BC6\u522B\u5230\u573A\u666F\uFF1A\u4EA7\u54C1\u5F00\u53D1
28102
+
28103
+ **\u7F6E\u4FE1\u5EA6\uFF1A** ${Math.round(routed.confidence * 100)}%
28104
+ ${domainPackWarning}
28105
+ ${localFirstDefaultNote}
28106
+
28107
+ ${compileMarkdown}`
28108
+ };
28109
+ }
27047
28110
  return {
27048
28111
  routedIntent: routed,
27049
28112
  selectedTool: "spec_interrogate",
27050
28113
  executed: true,
27051
28114
  result: structured,
27052
28115
  nextAction: {
27053
- type: structured.recommendation.canProceed ? "compile_spec" : "answer_questions",
27054
- message: structured.recommendation.reason,
27055
- suggestedTool: structured.recommendation.suggestedNextTool
28116
+ type: structured.recommendation.canProceed || localFirstGeneric ? "compile_spec" : "answer_questions",
28117
+ message: localFirstGeneric ? "\u672C\u5730\u5C0F\u5DE5\u5177\u53EF\u5148\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u751F\u6210 Draft \u89C4\u683C\uFF1B\u4E0D\u8981\u8981\u6C42\u5C0F\u767D\u7528\u6237\u9010\u9879\u586B\u5199\u7ED3\u6784\u5316\u7B54\u6848\u3002" : structured.recommendation.reason,
28118
+ suggestedTool: localFirstGeneric ? "spec_compile" : structured.recommendation.suggestedNextTool
27056
28119
  },
27057
28120
  technicalProfile,
27058
28121
  quickQuestions,
27059
28122
  agentGuidance: [
27060
- "\u4F18\u5148\u76F4\u63A5\u5C55\u793A quickQuestions\uFF0C\u907F\u514D\u4E8C\u6B21\u6539\u5199\u5BFC\u81F4\u9009\u9879\u8BED\u4E49\u53D8\u5316\u3002",
28123
+ localFirstGeneric ? "\u9762\u5411\u5C0F\u767D\u672C\u5730\u5DE5\u5177\u65F6\uFF0C\u4E0D\u8981\u628A quickQuestions \u539F\u6837\u629B\u7ED9\u7528\u6237\uFF0C\u4E5F\u4E0D\u8981\u8981\u6C42\u7528\u6237\u56DE\u7B54\u7C7B\u4F3C\u201CB + a\u201D\u7684\u7ED3\u6784\u5316\u9009\u9879\uFF1B\u7528\u63A8\u8350\u9ED8\u8BA4\u503C\u7EE7\u7EED spec_compile\uFF0C\u6700\u591A\u95EE\u4E00\u53E5\u81EA\u7136\u8BED\u8A00\u786E\u8BA4\u3002\u9875\u9762\u9AD8\u7EA7\u611F\u53EA\u5F71\u54CD UI\uFF0C\u4E0D\u8981\u56E0\u6B64\u7EA0\u504F\u6210\u540E\u7AEF\u3001\u767B\u5F55\u3001\u591A\u7AEF\u540C\u6B65\u6216\u670D\u52A1\u5668\u6570\u636E\u5E93\u3002" : "\u4F18\u5148\u76F4\u63A5\u5C55\u793A quickQuestions\uFF0C\u907F\u514D\u4E8C\u6B21\u6539\u5199\u5BFC\u81F4\u9009\u9879\u8BED\u4E49\u53D8\u5316\u3002",
27061
28124
  "\u4E0D\u8981\u628A\u7528\u6237\u7AEF\u767B\u5F55\u548C\u540E\u53F0\u7BA1\u7406\u5458\u767B\u5F55\u5408\u5E76\u6210\u540C\u4E00\u4E2A\u5B57\u6BB5\u3002",
27062
28125
  "\u5982\u679C\u7528\u6237\u53EA\u9700\u8981\u5BFC\u51FA\uFF0C\u4E0D\u8981\u64C5\u81EA\u6269\u5C55\u6210\u5B8C\u6574\u540E\u53F0\u7BA1\u7406\u7CFB\u7EDF\u3002",
27063
28126
  ...domainClassification.domain === "generic" ? ["\u672A\u547D\u4E2D\u7A33\u5B9A domain pack \u65F6\uFF0C\u5E94\u5148\u6F84\u6E05\u6838\u5FC3\u4E1A\u52A1\u5BF9\u8C61\u3001\u72B6\u6001\u6D41\u8F6C\u548C\u6743\u9650\u8FB9\u754C\uFF0C\u4E0D\u8981\u5957\u7528\u5176\u5B83 domain \u6A21\u677F\u3002"] : []
@@ -27066,13 +28129,90 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
27066
28129
 
27067
28130
  **\u7F6E\u4FE1\u5EA6\uFF1A** ${Math.round(routed.confidence * 100)}%
27068
28131
  ${domainPackWarning}
28132
+ ${localFirstDefaultNote}
27069
28133
 
27070
28134
  ## \u5FEB\u901F\u786E\u8BA4\u95EE\u9898
27071
28135
 
27072
28136
  ${formatQuickQuestions(quickQuestions)}
27073
28137
 
27074
- ${markdown}`
28138
+ ${markdown}`,
28139
+ pmIntentDecision
28140
+ };
28141
+ }
28142
+ function withPmDecision(result, pmIntentDecision) {
28143
+ return { ...result, pmIntentDecision };
28144
+ }
28145
+ function appendRemoteGateMeta(result, fallbackReason) {
28146
+ if (!fallbackReason) return result;
28147
+ return {
28148
+ ...result,
28149
+ agentGuidance: [
28150
+ ...result.agentGuidance,
28151
+ `\u8FDC\u7A0B PM Gate \u672A\u4F7F\u7528\u6216\u5DF2\u964D\u7EA7\uFF1A${fallbackReason}\u3002\u5F53\u524D\u7ED3\u679C\u6765\u81EA\u672C\u5730\u89C4\u5219\u3002`
28152
+ ]
28153
+ };
28154
+ }
28155
+ function buildPmGateInterrogateResult(message, routed, technicalProfile, pmIntentDecision, quickQuestions) {
28156
+ const title = formatNeedTypeTitle(pmIntentDecision.needType);
28157
+ return {
28158
+ routedIntent: routed,
28159
+ selectedTool: "spec_interrogate",
28160
+ executed: true,
28161
+ nextAction: {
28162
+ type: "answer_questions",
28163
+ message: "\u5DF2\u8BC6\u522B\u9700\u6C42\u95E8\uFF0C\u8BF7\u5148\u786E\u8BA4\u4F1A\u6539\u53D8\u67B6\u6784\u548C\u8FB9\u754C\u7684\u5173\u952E\u95EE\u9898\u3002",
28164
+ suggestedTool: "spec_compile"
28165
+ },
28166
+ technicalProfile,
28167
+ pmIntentDecision,
28168
+ quickQuestions,
28169
+ agentGuidance: [
28170
+ `PM Gate \u5DF2\u5224\u5B9A\u4E3A ${pmIntentDecision.needType}\uFF0C\u4E0D\u8981\u5957\u7528\u65E0\u5173 domain \u6A21\u677F\u3002`,
28171
+ "\u4F18\u5148\u786E\u8BA4\u4F7F\u7528\u8303\u56F4\u3001\u7EF4\u62A4\u65B9\u5F0F\u548C\u8BBF\u95EE\u65B9\u5F0F\uFF0C\u518D\u8C08\u5177\u4F53\u6280\u672F\u6808\u3002",
28172
+ ...pmIntentDecision.mustNotUse.map((item) => `\u7981\u6B62\u9ED8\u8BA4\u4F7F\u7528\uFF1A${item}`)
28173
+ ],
28174
+ markdown: `# \u8BC6\u522B\u5230\u573A\u666F\uFF1A${title}
28175
+
28176
+ **\u7F6E\u4FE1\u5EA6\uFF1A** ${pmIntentDecision.confidence}
28177
+
28178
+ ## PM Gate \u5224\u65AD
28179
+
28180
+ - **\u9700\u6C42\u95E8:** ${pmIntentDecision.needType}
28181
+ - **\u4F7F\u7528\u8303\u56F4:** ${pmIntentDecision.usageScope}
28182
+ - **\u7EF4\u62A4\u65B9\u5F0F:** ${pmIntentDecision.maintenanceMode}
28183
+ - **\u8BBF\u95EE\u65B9\u5F0F:** ${pmIntentDecision.accessTopology}
28184
+ - **\u6280\u672F\u5F62\u6001:** ${pmIntentDecision.technicalShape}
28185
+ - **\u63A8\u8350\u90E8\u7F72:** ${pmIntentDecision.recommendedDeployment}
28186
+ - **\u5F3A\u4FE1\u53F7:** ${pmIntentDecision.strongSignals.join("\u3001") || "\u65E0"}
28187
+ - **\u5F31\u4FE1\u53F7:** ${pmIntentDecision.weakSignals.join("\u3001") || "\u65E0"}
28188
+ - **\u4E0D\u8981\u9ED8\u8BA4\u4F7F\u7528:** ${pmIntentDecision.mustNotUse.join("\u3001") || "\u65E0"}
28189
+
28190
+ ## \u9ED8\u8BA4\u7406\u89E3
28191
+
28192
+ ${pmIntentDecision.defaultAssumptions.map((item) => `- ${item}`).join("\n")}
28193
+
28194
+ ## \u5FEB\u901F\u786E\u8BA4\u95EE\u9898
28195
+
28196
+ ${formatQuickQuestions(quickQuestions)}
28197
+
28198
+ ## \u4E0B\u4E00\u6B65
28199
+
28200
+ \u8BF7\u5148\u786E\u8BA4\u4EE5\u4E0A\u8FB9\u754C\uFF0C\u518D\u8C03\u7528 \`spec_compile\` \u56FA\u5316 MVP \u89C4\u683C\u3002`
28201
+ };
28202
+ }
28203
+ function formatNeedTypeTitle(needType) {
28204
+ const titles = {
28205
+ static_display: "\u9759\u6001\u5C55\u793A\u7F51\u7AD9",
28206
+ personal_local_tool: "\u4E2A\u4EBA\u672C\u5730\u5DE5\u5177",
28207
+ multi_user_collaboration: "\u591A\u4EBA\u534F\u4F5C\u5DE5\u5177",
28208
+ content_marketing_site: "\u5185\u5BB9\u8425\u9500\u7F51\u7AD9",
28209
+ data_visualization_site: "\u6570\u636E\u56FE\u8868\u7F51\u7AD9",
28210
+ transaction_workflow: "\u4EA4\u6613/\u5C65\u7EA6\u6D41\u7A0B",
28211
+ content_knowledge: "\u5185\u5BB9/\u77E5\u8BC6\u7BA1\u7406",
28212
+ ai_automation: "AI \u81EA\u52A8\u5316\u4EA7\u54C1",
28213
+ unknown: "\u4EA7\u54C1\u5F00\u53D1"
27075
28214
  };
28215
+ return titles[needType];
27076
28216
  }
27077
28217
  function handleStaticDisplaySite(message, autoExecute, routed) {
27078
28218
  const technicalProfile = buildTechnicalProfile(message, {});
@@ -27656,6 +28796,161 @@ function buildLocalFirstQuickQuestions(technicalProfile, message = "") {
27656
28796
  }
27657
28797
  return questions;
27658
28798
  }
28799
+ function buildMultiUserCollaborationQuickQuestions() {
28800
+ return withQuestionExamples([
28801
+ {
28802
+ id: "access_topology",
28803
+ question: "\u4F60\u4EEC\u53EA\u9700\u8981\u5728\u540C\u4E00\u4E2A Wi-Fi/\u5C40\u57DF\u7F51\u91CC\u4F7F\u7528\uFF0C\u8FD8\u662F\u5916\u51FA\u65F6\u4E5F\u8981\u8BBF\u95EE\uFF1F",
28804
+ whyImportant: "\u51B3\u5B9A\u662F\u5C40\u57DF\u7F51\u5C0F\u670D\u52A1\uFF0C\u8FD8\u662F\u9700\u8981\u516C\u7F51\u670D\u52A1\u5668\u3001\u57DF\u540D\u548C HTTPS\u3002",
28805
+ priority: "P0",
28806
+ defaultValue: "ask_first",
28807
+ mapsTo: ["access_topology", "deployment"],
28808
+ options: [
28809
+ { label: "\u5148\u786E\u8BA4\u5C40\u57DF\u7F51\u662F\u5426\u8DB3\u591F", value: "ask_first", recommended: true },
28810
+ { label: "\u53EA\u5728\u540C\u4E00 Wi-Fi/\u5C40\u57DF\u7F51\u4F7F\u7528", value: "lan_only" },
28811
+ { label: "\u5916\u51FA\u4E5F\u8981\u80FD\u8BBF\u95EE", value: "internet_ip" }
28812
+ ]
28813
+ },
28814
+ {
28815
+ id: "public_ip_acceptance",
28816
+ question: "\u5982\u679C\u5916\u51FA\u4E5F\u8981\u8BBF\u95EE\uFF0C\u80FD\u5426\u63A5\u53D7\u7B2C\u4E00\u7248\u7528\u51E0\u5341\u5143/\u5E74\u7684\u516C\u7F51\u670D\u52A1\u5668\u548C IP \u5730\u5740\u8BBF\u95EE\uFF1F",
28817
+ whyImportant: "\u51B3\u5B9A MVP \u662F\u5426\u5148\u8DF3\u8FC7\u57DF\u540D\u3001\u5907\u6848\u548C\u5B8C\u6574 HTTPS \u8FD0\u7EF4\u3002",
28818
+ priority: "P0",
28819
+ defaultValue: "cheap_vps_ip_ok",
28820
+ mapsTo: ["deployment", "non_goals"],
28821
+ options: [
28822
+ { label: "\u53EF\u4EE5\uFF0C\u5148\u7528\u516C\u7F51 IP \u8DD1\u901A", value: "cheap_vps_ip_ok", recommended: true },
28823
+ { label: "\u5FC5\u987B\u6709\u57DF\u540D\u548C HTTPS", value: "domain_https" },
28824
+ { label: "\u5148\u53EA\u505A\u5C40\u57DF\u7F51\u7248", value: "lan_first" }
28825
+ ]
28826
+ },
28827
+ {
28828
+ id: "claim_rule",
28829
+ question: "\u7ED9\u522B\u4EBA\u5B89\u6392\u4EFB\u52A1\u65F6\uFF0C\u662F\u5426\u5FC5\u987B\u5BF9\u65B9\u8BA4\u9886\u540E\u624D\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\uFF1F",
28830
+ whyImportant: "\u51B3\u5B9A\u4EFB\u52A1\u72B6\u6001\u673A\u548C\u6743\u9650\u8FB9\u754C\u3002",
28831
+ priority: "P0",
28832
+ defaultValue: "claim_required",
28833
+ mapsTo: ["workflow", "task_status"],
28834
+ options: [
28835
+ { label: "\u5FC5\u987B\u8BA4\u9886\u540E\u624D\u751F\u6548", value: "claim_required", recommended: true },
28836
+ { label: "\u76F4\u63A5\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\u4F46\u6807\u8BB0\u5F85\u786E\u8BA4", value: "pending_confirm" },
28837
+ { label: "\u521B\u5EFA\u8005\u53EF\u4EE5\u76F4\u63A5\u5B89\u6392", value: "direct_assign" }
28838
+ ]
28839
+ },
28840
+ {
28841
+ id: "time_conflict_rule",
28842
+ question: "\u540C\u4E00\u65F6\u95F4\u6709\u591A\u4E2A\u4EFB\u52A1\u65F6\uFF0C\u5E94\u8BE5\u5E76\u6392\u5C55\u793A/\u9AD8\u4EAE\u51B2\u7A81\uFF0C\u8FD8\u662F\u963B\u6B62\u5B89\u6392\uFF1F",
28843
+ whyImportant: "\u51B3\u5B9A\u65E5\u7A0B\u89C6\u56FE\u548C\u51B2\u7A81\u89C4\u5219\u3002",
28844
+ priority: "P0",
28845
+ defaultValue: "show_conflict",
28846
+ mapsTo: ["workflow", "success_criteria"],
28847
+ options: [
28848
+ { label: "\u5141\u8BB8\u5E76\u6392\u5C55\u793A\u5E76\u9AD8\u4EAE\u51B2\u7A81", value: "show_conflict", recommended: true },
28849
+ { label: "\u963B\u6B62\u5B89\u6392\u51B2\u7A81\u4EFB\u52A1", value: "block_conflict" },
28850
+ { label: "\u53EA\u63D0\u793A\u4E0D\u963B\u6B62", value: "warn_only" }
28851
+ ]
28852
+ }
28853
+ ]);
28854
+ }
28855
+ function buildContentMarketingQuickQuestions() {
28856
+ return withQuestionExamples([
28857
+ {
28858
+ id: "maintenance_mode",
28859
+ question: "\u540E\u7EED\u7EF4\u62A4\u5185\u5BB9\u65F6\uFF0C\u662F\u7EE7\u7EED\u8BA9 Agent \u5E2E\u4F60\u6539\u548C\u53D1\u5E03\uFF0C\u8FD8\u662F\u9700\u8981\u7F51\u9875\u540E\u53F0\u81EA\u5DF1\u7F16\u8F91\uFF1F",
28860
+ whyImportant: "\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u7B49\u4E8E\u5FC5\u987B\u505A\u540E\u53F0\uFF0C\u7EF4\u62A4\u65B9\u5F0F\u51B3\u5B9A\u67B6\u6784\u590D\u6742\u5EA6\u3002",
28861
+ priority: "P0",
28862
+ defaultValue: "agent_assisted",
28863
+ mapsTo: ["maintenance_mode", "backend_need"],
28864
+ options: [
28865
+ { label: "\u7EE7\u7EED\u8BA9 Agent \u5E2E\u6211\u66F4\u65B0\u548C\u53D1\u5E03", value: "agent_assisted", recommended: true },
28866
+ { label: "\u6211\u80FD\u63A5\u53D7\u6539 data.json/markdown \u6587\u4EF6", value: "manual_files" },
28867
+ { label: "\u6211\u8981\u7F51\u9875\u540E\u53F0\u4E0A\u4F20\u56FE\u7247\u548C\u7F16\u8F91\u5185\u5BB9", value: "web_admin" }
28868
+ ]
28869
+ },
28870
+ {
28871
+ id: "geo_goal",
28872
+ question: "\u4F60\u8BF4\u7684 GEO \u670D\u52A1\u4E3B\u8981\u662F AI/\u751F\u6210\u5F0F\u641C\u7D22\u53EF\u89C1\u6027\uFF0C\u8FD8\u662F\u5730\u56FE/\u9644\u8FD1\u95E8\u5E97\u66DD\u5149\uFF1F",
28873
+ whyImportant: "\u51B3\u5B9A FAQ\u3001\u7ED3\u6784\u5316\u6570\u636E\u3001\u95E8\u5E97\u4FE1\u606F\u3001\u5730\u56FE\u548C sitemap \u7684\u4F18\u5148\u7EA7\u3002",
28874
+ priority: "P0",
28875
+ defaultValue: "geo_seo_content",
28876
+ mapsTo: ["seo_geo", "content_sections"],
28877
+ options: [
28878
+ { label: "AI/\u751F\u6210\u5F0F\u641C\u7D22\u548C SEO \u53EF\u89C1\u6027", value: "geo_seo_content", recommended: true },
28879
+ { label: "\u5730\u56FE\u5B9A\u4F4D/\u9644\u8FD1\u95E8\u5E97\u66DD\u5149", value: "map_local_discovery" },
28880
+ { label: "\u4E24\u8005\u90FD\u8981", value: "both" }
28881
+ ]
28882
+ },
28883
+ {
28884
+ id: "visitor_submission",
28885
+ question: "\u7528\u6237\u53CD\u9988\u662F\u4F60\u624B\u52A8\u6574\u7406\u540E\u5C55\u793A\uFF0C\u8FD8\u662F\u8BBF\u5BA2\u53EF\u4EE5\u5728\u7EBF\u63D0\u4EA4\uFF1F",
28886
+ whyImportant: "\u8BBF\u5BA2\u63D0\u4EA4\u4F1A\u89E6\u53D1\u540E\u7AEF\u3001\u5BA1\u6838\u548C\u9632\u5783\u573E\u5185\u5BB9\u3002",
28887
+ priority: "P0",
28888
+ defaultValue: "owner_curated",
28889
+ mapsTo: ["maintenance_mode", "risk_boundaries"],
28890
+ options: [
28891
+ { label: "\u6211\u624B\u52A8\u6574\u7406\u540E\u5C55\u793A", value: "owner_curated", recommended: true },
28892
+ { label: "\u8BBF\u5BA2\u53EF\u4EE5\u5728\u7EBF\u63D0\u4EA4", value: "visitor_submission" },
28893
+ { label: "\u5148\u5C55\u793A\u56FA\u5B9A\u6848\u4F8B", value: "static_examples" }
28894
+ ]
28895
+ },
28896
+ {
28897
+ id: "image_volume",
28898
+ question: "\u7167\u7247\u662F\u5C11\u91CF\u7CBE\u9009\u56FE\uFF0C\u8FD8\u662F\u4F1A\u7ECF\u5E38\u4E0A\u4F20\u5F88\u591A\u56FE\uFF1F",
28899
+ whyImportant: "\u51B3\u5B9A\u56FE\u7247\u538B\u7F29\u3001\u5206\u7C7B\u3001\u5C01\u9762\u548C\u8D44\u6E90\u7BA1\u7406\u65B9\u5F0F\u3002",
28900
+ priority: "P1",
28901
+ defaultValue: "curated_gallery",
28902
+ mapsTo: ["content_sections", "asset_strategy"],
28903
+ options: [
28904
+ { label: "\u5C11\u91CF\u7CBE\u9009\u56FE", value: "curated_gallery", recommended: true },
28905
+ { label: "\u7ECF\u5E38\u4E0A\u4F20\u5F88\u591A\u56FE", value: "large_gallery" },
28906
+ { label: "\u5148\u4E0D\u505A\u56FE\u5E93", value: "no_gallery_first" }
28907
+ ]
28908
+ }
28909
+ ]);
28910
+ }
28911
+ function buildDataVisualizationQuickQuestions() {
28912
+ return withQuestionExamples([
28913
+ {
28914
+ id: "data_update_mode",
28915
+ question: "\u65B0\u7684 xlsx \u662F\u4EA4\u7ED9 Agent \u66F4\u65B0\u7F51\u7AD9\uFF0C\u8FD8\u662F\u7F51\u7AD9\u91CC\u8981\u6709\u4E0A\u4F20\u6309\u94AE\uFF1F",
28916
+ whyImportant: "\u51B3\u5B9A\u662F\u5426\u9700\u8981\u540E\u53F0\u4E0A\u4F20\u63A5\u53E3\u548C\u670D\u52A1\u5668\u89E3\u6790\u3002",
28917
+ priority: "P0",
28918
+ defaultValue: "agent_assisted",
28919
+ mapsTo: ["maintenance_mode", "data_flow"],
28920
+ options: [
28921
+ { label: "\u4EA4\u7ED9 Agent \u89E3\u6790\u5E76\u66F4\u65B0\u7F51\u7AD9", value: "agent_assisted", recommended: true },
28922
+ { label: "\u7F51\u9875\u91CC\u4E0A\u4F20\uFF0C\u4F46\u53EA\u5728\u6D4F\u89C8\u5668\u672C\u5730\u6E32\u67D3", value: "browser_upload" },
28923
+ { label: "\u7F51\u9875\u4E0A\u4F20\u540E\u6240\u6709\u8BBF\u5BA2\u770B\u5230\u6700\u65B0\u6570\u636E", value: "server_upload" }
28924
+ ]
28925
+ },
28926
+ {
28927
+ id: "audience_scope",
28928
+ question: "\u56FE\u8868\u662F\u53EA\u7ED9\u4F60\u81EA\u5DF1\u770B\uFF0C\u8FD8\u662F\u516C\u5F00\u7ED9\u522B\u4EBA\u770B\uFF1F",
28929
+ whyImportant: "\u51B3\u5B9A\u8BBF\u95EE\u65B9\u5F0F\u3001\u90E8\u7F72\u65B9\u5F0F\u548C\u662F\u5426\u9700\u8981\u6743\u9650\u3002",
28930
+ priority: "P0",
28931
+ defaultValue: "public_view",
28932
+ mapsTo: ["usage_scope", "access_topology"],
28933
+ options: [
28934
+ { label: "\u516C\u5F00\u5C55\u793A", value: "public_view", recommended: true },
28935
+ { label: "\u53EA\u7ED9\u81EA\u5DF1\u770B", value: "self_view" },
28936
+ { label: "\u56FA\u5B9A\u51E0\u4E2A\u4EBA\u770B", value: "fixed_group" }
28937
+ ]
28938
+ },
28939
+ {
28940
+ id: "history_versions",
28941
+ question: "\u662F\u5426\u9700\u8981\u4FDD\u7559\u5386\u53F2\u7248\u672C\uFF0C\u8FD8\u662F\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C\uFF1F",
28942
+ whyImportant: "\u51B3\u5B9A\u662F\u5426\u9700\u8981\u7248\u672C\u5B58\u50A8\u548C\u5386\u53F2\u5207\u6362\u3002",
28943
+ priority: "P1",
28944
+ defaultValue: "latest_only",
28945
+ mapsTo: ["data_model", "success_criteria"],
28946
+ options: [
28947
+ { label: "\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C", value: "latest_only", recommended: true },
28948
+ { label: "\u4FDD\u7559\u5386\u53F2\u7248\u672C", value: "keep_history" },
28949
+ { label: "\u4EE5\u540E\u518D\u8BF4", value: "later" }
28950
+ ]
28951
+ }
28952
+ ]);
28953
+ }
27659
28954
  function buildAppointmentQuickQuestions() {
27660
28955
  return [
27661
28956
  {
@@ -28349,7 +29644,7 @@ function quickQuestionExample(id, question) {
28349
29644
  // src/tools/productSpecAssist.ts
28350
29645
  function registerProductSpecAssist(server) {
28351
29646
  const handler = async (input) => {
28352
- const result = executeAssist(
29647
+ const result = await executeAssistWithRemoteGate(
28353
29648
  input.message,
28354
29649
  input.known_context,
28355
29650
  input.preferred_platform,
@@ -28365,6 +29660,7 @@ function registerProductSpecAssist(server) {
28365
29660
  result: result.result ?? null,
28366
29661
  nextAction: result.nextAction,
28367
29662
  technicalProfile: result.technicalProfile,
29663
+ pmIntentDecision: result.pmIntentDecision,
28368
29664
  quickQuestions: result.quickQuestions,
28369
29665
  agentGuidance: result.agentGuidance
28370
29666
  }
@@ -28386,7 +29682,7 @@ function registerProductSpecAssist(server) {
28386
29682
  function createServer() {
28387
29683
  const server = new McpServer({
28388
29684
  name: "product-spec-mcp",
28389
- version: "0.3.21"
29685
+ version: "0.3.26"
28390
29686
  });
28391
29687
  registerSpecInterrogate(server);
28392
29688
  registerSpecCompile(server);