product-spec-mcp 0.3.28 → 0.3.30

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/README.md CHANGED
@@ -61,7 +61,7 @@ npm run dev
61
61
  ```bash
62
62
  PRODUCT_SPEC_REMOTE_GATE_URL=https://gate.example.com/v1/pm-intent
63
63
  PRODUCT_SPEC_REMOTE_GATE_TOKEN=replace-with-token
64
- PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS=2500
64
+ PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS=10000
65
65
  PRODUCT_SPEC_REMOTE_GATE_MODE=auto
66
66
  PRODUCT_SPEC_TELEMETRY=off
67
67
  ```
package/dist/index.cjs CHANGED
@@ -21147,6 +21147,60 @@ var TechnicalProfileSchema = external_exports.object({
21147
21147
  )
21148
21148
  });
21149
21149
 
21150
+ // src/schemas/pmIntentDecision.schema.ts
21151
+ var PmIntentDecisionSchema = external_exports.object({
21152
+ needType: external_exports.enum([
21153
+ "static_display",
21154
+ "personal_local_tool",
21155
+ "multi_user_collaboration",
21156
+ "content_marketing_site",
21157
+ "data_visualization_site",
21158
+ "transaction_workflow",
21159
+ "content_knowledge",
21160
+ "ai_automation",
21161
+ "unknown"
21162
+ ]),
21163
+ usageScope: external_exports.enum(["self", "fixed_group", "public_audience", "unknown"]),
21164
+ maintenanceMode: external_exports.enum([
21165
+ "agent_assisted",
21166
+ "manual_files",
21167
+ "web_admin",
21168
+ "visitor_submission",
21169
+ "runtime_collaboration",
21170
+ "unknown"
21171
+ ]),
21172
+ accessTopology: external_exports.enum(["single_device", "lan_only", "internet_ip", "public_domain", "unknown"]),
21173
+ technicalShape: external_exports.enum([
21174
+ "static_page",
21175
+ "local_storage_tool",
21176
+ "local_json_import_export",
21177
+ "static_json_data_page",
21178
+ "light_backend_json_sqlite",
21179
+ "full_backend_saas",
21180
+ "unknown"
21181
+ ]),
21182
+ recommendedDeployment: external_exports.enum([
21183
+ "static_only",
21184
+ "local_browser_only",
21185
+ "static_hosting_with_agent_updates",
21186
+ "local_lan_server_sqlite",
21187
+ "cheap_vps_sqlite_by_ip",
21188
+ "vps_domain_https",
21189
+ "unknown"
21190
+ ]),
21191
+ route: external_exports.enum(["spec_compile", "spec_interrogate", "architecture_decide"]),
21192
+ confidence: external_exports.enum(["high", "medium", "low"]),
21193
+ strongSignals: external_exports.array(external_exports.string()),
21194
+ weakSignals: external_exports.array(external_exports.string()),
21195
+ coreObjects: external_exports.array(external_exports.string()),
21196
+ states: external_exports.array(external_exports.string()),
21197
+ actions: external_exports.array(external_exports.string()),
21198
+ mustNotUse: external_exports.array(external_exports.string()),
21199
+ boundaryQuestionIds: external_exports.array(external_exports.string()),
21200
+ defaultAssumptions: external_exports.array(external_exports.string()),
21201
+ source: external_exports.enum(["local_rule", "online_llm", "merged"])
21202
+ });
21203
+
21150
21204
  // src/schemas/outputs/specInterrogate.output.ts
21151
21205
  var SpecInterrogateOutputSchema = external_exports.object({
21152
21206
  readiness: external_exports.object({
@@ -21180,7 +21234,8 @@ var SpecInterrogateOutputSchema = external_exports.object({
21180
21234
  suggestedNextTool: external_exports.enum(["spec_compile", "spec_interrogate"]),
21181
21235
  reason: external_exports.string()
21182
21236
  }),
21183
- technicalProfile: TechnicalProfileSchema.optional()
21237
+ technicalProfile: TechnicalProfileSchema.optional(),
21238
+ pmIntentDecision: PmIntentDecisionSchema.optional()
21184
21239
  });
21185
21240
 
21186
21241
  // src/core/contextSignals.ts
@@ -23315,7 +23370,7 @@ ${acceptance.platform}
23315
23370
  }
23316
23371
 
23317
23372
  // src/core/structuredResultBuilder.ts
23318
- function buildInterrogateStructuredOutput(readiness, clarification, technicalProfile) {
23373
+ function buildInterrogateStructuredOutput(readiness, clarification, technicalProfile, pmIntentDecision) {
23319
23374
  const canProceed = readiness.status !== "Not Ready";
23320
23375
  return {
23321
23376
  readiness: {
@@ -23333,7 +23388,8 @@ function buildInterrogateStructuredOutput(readiness, clarification, technicalPro
23333
23388
  suggestedNextTool: canProceed ? "spec_compile" : "spec_interrogate",
23334
23389
  reason: canProceed ? readiness.status === "Build Ready" ? "\u4FE1\u606F\u5145\u8DB3\uFF0C\u53EF\u4EE5\u751F\u6210\u6B63\u5F0F\u89C4\u683C" : "\u4FE1\u606F\u90E8\u5206\u5B8C\u6574\uFF0C\u53EF\u4EE5\u751F\u6210\u8349\u6848" : "\u4FE1\u606F\u4E0D\u8DB3\uFF0C\u9700\u8981\u5148\u56DE\u7B54\u8FFD\u95EE"
23335
23390
  },
23336
- technicalProfile
23391
+ technicalProfile,
23392
+ pmIntentDecision
23337
23393
  };
23338
23394
  }
23339
23395
  function buildCompileStructuredOutput(mode, readiness, spec, confirmation, clarification) {
@@ -23483,97 +23539,512 @@ function buildDebugGuideStructuredOutput(guide) {
23483
23539
  };
23484
23540
  }
23485
23541
 
23542
+ // src/core/pmIntentGate.ts
23543
+ function decidePmIntent(rawText, context = {}) {
23544
+ const text = `${rawText} ${JSON.stringify(context)}`;
23545
+ const strongSignals = collectSignals(text, strongSignalMap);
23546
+ const weakSignals = collectSignals(text, weakSignalMap);
23547
+ const usageScope = decideUsageScope(text);
23548
+ const preliminaryNeedType = decideNeedType(text, strongSignals);
23549
+ const maintenanceMode = decideMaintenanceMode(text, preliminaryNeedType);
23550
+ const accessTopology = decideAccessTopology(text, usageScope, maintenanceMode);
23551
+ const needType = preliminaryNeedType;
23552
+ const technicalShape = decideTechnicalShape(text, needType, maintenanceMode);
23553
+ const recommendedDeployment = decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology);
23554
+ const route = decideRoute(needType, technicalShape, maintenanceMode);
23555
+ const confidence = decideConfidence(needType, strongSignals, weakSignals);
23556
+ return enforceHardRules({
23557
+ needType,
23558
+ usageScope,
23559
+ maintenanceMode,
23560
+ accessTopology,
23561
+ technicalShape,
23562
+ recommendedDeployment,
23563
+ route,
23564
+ confidence,
23565
+ strongSignals,
23566
+ weakSignals,
23567
+ coreObjects: extractCoreObjects(text, needType),
23568
+ states: extractStates(text, needType),
23569
+ actions: extractActions(text, needType),
23570
+ mustNotUse: buildMustNotUse(needType, maintenanceMode),
23571
+ boundaryQuestionIds: buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology),
23572
+ defaultAssumptions: buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, recommendedDeployment),
23573
+ source: "local_rule"
23574
+ });
23575
+ }
23576
+ function decideNeedType(text, strongSignals) {
23577
+ 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"])) {
23578
+ return "ai_automation";
23579
+ }
23580
+ if (hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6", "\u6536\u6B3E", "\u5BFC\u51FA Excel", "\u5BFC\u51FA"])) {
23581
+ return "transaction_workflow";
23582
+ }
23583
+ 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"])) {
23584
+ return "multi_user_collaboration";
23585
+ }
23586
+ 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"])) {
23587
+ return "data_visualization_site";
23588
+ }
23589
+ 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"])) {
23590
+ return "content_marketing_site";
23591
+ }
23592
+ if (hasAny2(text, ["\u77E5\u8BC6\u5E93", "\u6587\u6863\u7BA1\u7406", "\u8D44\u6599\u5E93", "\u56E2\u961F\u6587\u6863"])) {
23593
+ return "content_knowledge";
23594
+ }
23595
+ 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")) {
23596
+ return "personal_local_tool";
23597
+ }
23598
+ 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"])) {
23599
+ return "static_display";
23600
+ }
23601
+ return "unknown";
23602
+ }
23603
+ function decideUsageScope(text) {
23604
+ 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";
23605
+ if (hasAny2(text, ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA", "\u5BB6\u5EAD", "\u540C\u4E8B", "\u56E2\u961F", "\u5171\u7528", "\u5171\u4EAB"])) return "fixed_group";
23606
+ if (hasAny2(text, ["\u81EA\u5DF1", "\u81EA\u7528", "\u4E2A\u4EBA", "\u6211\u7528", "\u6211\u81EA\u5DF1"])) return "self";
23607
+ return "unknown";
23608
+ }
23609
+ function decideMaintenanceMode(text, needType) {
23610
+ 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";
23611
+ 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";
23612
+ 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";
23613
+ if (hasAny2(text, ["data.json", "markdown", "Markdown", "md \u6587\u4EF6", "\u624B\u52A8\u6539\u6587\u4EF6"])) return "manual_files";
23614
+ 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";
23615
+ if (needType === "content_marketing_site" || needType === "data_visualization_site" || needType === "static_display") return "agent_assisted";
23616
+ return "unknown";
23617
+ }
23618
+ function decideAccessTopology(text, usageScope, maintenanceMode) {
23619
+ if (hasAny2(text, ["\u540C\u4E00 Wi-Fi", "\u540C\u4E00\u4E2A Wi-Fi", "\u5C40\u57DF\u7F51", "\u5185\u7F51", "\u5BB6\u91CC\u7F51\u7EDC"])) return "lan_only";
23620
+ if (hasAny2(text, ["\u5916\u51FA", "\u516C\u7F51 IP", "\u516C\u7F51ip", "IP \u5730\u5740", "\u670D\u52A1\u5668", "VPS", "vps"])) return "internet_ip";
23621
+ if (hasAny2(text, ["\u57DF\u540D", "HTTPS", "https", "\u5907\u6848", "\u516C\u5F00\u7F51\u7AD9", "\u5B98\u7F51"])) return "public_domain";
23622
+ if (usageScope === "self" && maintenanceMode !== "runtime_collaboration") return "single_device";
23623
+ if (usageScope === "public_audience") return "public_domain";
23624
+ return "unknown";
23625
+ }
23626
+ function decideTechnicalShape(text, needType, maintenanceMode) {
23627
+ if (needType === "ai_automation") return "full_backend_saas";
23628
+ if (needType === "transaction_workflow") return hasAny2(text, ["\u652F\u4ED8", "\u8BA2\u5355", "\u6536\u8D39"]) ? "full_backend_saas" : "light_backend_json_sqlite";
23629
+ if (needType === "multi_user_collaboration") return "light_backend_json_sqlite";
23630
+ if (needType === "content_marketing_site") {
23631
+ return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
23632
+ }
23633
+ if (needType === "data_visualization_site") {
23634
+ return maintenanceMode === "web_admin" || maintenanceMode === "visitor_submission" ? "light_backend_json_sqlite" : "static_json_data_page";
23635
+ }
23636
+ if (needType === "content_knowledge") {
23637
+ return maintenanceMode === "agent_assisted" || maintenanceMode === "manual_files" ? "static_json_data_page" : "light_backend_json_sqlite";
23638
+ }
23639
+ if (needType === "personal_local_tool") return "local_storage_tool";
23640
+ if (needType === "static_display") return "static_page";
23641
+ return "unknown";
23642
+ }
23643
+ function decideRecommendedDeployment(needType, technicalShape, maintenanceMode, accessTopology) {
23644
+ if (technicalShape === "static_page") return "static_only";
23645
+ if (technicalShape === "local_storage_tool" || technicalShape === "local_json_import_export") return "local_browser_only";
23646
+ if (maintenanceMode === "agent_assisted" && ["content_marketing_site", "data_visualization_site", "content_knowledge"].includes(needType)) {
23647
+ return "static_hosting_with_agent_updates";
23648
+ }
23649
+ if (accessTopology === "lan_only") return "local_lan_server_sqlite";
23650
+ if (accessTopology === "internet_ip") return "cheap_vps_sqlite_by_ip";
23651
+ if (accessTopology === "public_domain") return "vps_domain_https";
23652
+ if (technicalShape === "light_backend_json_sqlite") return "unknown";
23653
+ return "unknown";
23654
+ }
23655
+ function decideRoute(needType, technicalShape, maintenanceMode) {
23656
+ if (needType === "personal_local_tool") return "spec_compile";
23657
+ if (["static_page", "static_json_data_page"].includes(technicalShape) && maintenanceMode === "agent_assisted") return "spec_compile";
23658
+ return "spec_interrogate";
23659
+ }
23660
+ function decideConfidence(needType, strongSignals, weakSignals) {
23661
+ if (needType === "unknown") return "low";
23662
+ if (strongSignals.length >= 2) return "high";
23663
+ if (strongSignals.length === 1 || weakSignals.length >= 2) return "medium";
23664
+ return "medium";
23665
+ }
23666
+ function enforceHardRules(decision) {
23667
+ 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));
23668
+ if (hasRuntimeCollaboration && decision.technicalShape !== "light_backend_json_sqlite") {
23669
+ return {
23670
+ ...decision,
23671
+ needType: "multi_user_collaboration",
23672
+ maintenanceMode: "runtime_collaboration",
23673
+ technicalShape: "light_backend_json_sqlite",
23674
+ recommendedDeployment: recommendedDeploymentForCollaboration(decision.accessTopology),
23675
+ route: "spec_interrogate",
23676
+ mustNotUse: Array.from(/* @__PURE__ */ new Set([...decision.mustNotUse, "static_display", "local_storage_only"]))
23677
+ };
23678
+ }
23679
+ return decision;
23680
+ }
23681
+ function recommendedDeploymentForCollaboration(accessTopology) {
23682
+ if (accessTopology === "lan_only") return "local_lan_server_sqlite";
23683
+ if (accessTopology === "internet_ip") return "cheap_vps_sqlite_by_ip";
23684
+ if (accessTopology === "public_domain") return "vps_domain_https";
23685
+ return "unknown";
23686
+ }
23687
+ function buildMustNotUse(needType, maintenanceMode) {
23688
+ const items = [];
23689
+ if (needType === "multi_user_collaboration") items.push("static_display", "local_storage_only");
23690
+ if (needType === "content_marketing_site" || needType === "data_visualization_site") items.push("admin_backend_by_default", "database_by_default");
23691
+ if (maintenanceMode === "agent_assisted") items.push("web_admin_cms_by_default");
23692
+ if (needType === "transaction_workflow") items.push("local_storage_only");
23693
+ if (needType === "ai_automation") items.push("frontend_api_key");
23694
+ return Array.from(new Set(items));
23695
+ }
23696
+ function buildBoundaryQuestionIds(needType, maintenanceMode, accessTopology) {
23697
+ if (needType === "multi_user_collaboration") {
23698
+ return ["access_topology", "public_ip_acceptance", "claim_rule", "time_conflict_rule"];
23699
+ }
23700
+ if (needType === "content_marketing_site") {
23701
+ return ["maintenance_mode", "geo_goal", "visitor_submission", "image_volume"];
23702
+ }
23703
+ if (needType === "data_visualization_site") {
23704
+ return ["data_update_mode", "audience_scope", "history_versions"];
23705
+ }
23706
+ if (needType === "content_knowledge") {
23707
+ return maintenanceMode === "agent_assisted" ? ["maintenance_mode", "visibility_scope"] : ["editor_roles", "permission_rule", "version_history"];
23708
+ }
23709
+ if (needType === "unknown") return ["usage_scope", "maintenance_mode", "data_flow"];
23710
+ if (accessTopology === "unknown" && needType !== "personal_local_tool") return ["access_topology"];
23711
+ return [];
23712
+ }
23713
+ function buildDefaultAssumptions(needType, usageScope, maintenanceMode, accessTopology, deployment) {
23714
+ 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}`];
23715
+ if (needType === "content_marketing_site" || needType === "data_visualization_site") {
23716
+ 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");
23717
+ }
23718
+ if (needType === "multi_user_collaboration") {
23719
+ 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");
23720
+ }
23721
+ return items;
23722
+ }
23723
+ function extractCoreObjects(text, needType) {
23724
+ if (needType === "multi_user_collaboration") return ["\u7528\u6237", "\u4EFB\u52A1", "\u65E5\u7A0B\u9879"];
23725
+ 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");
23726
+ if (needType === "data_visualization_site") return ["xlsx \u6587\u4EF6", "\u6570\u636E\u8868", "\u56FE\u8868\u914D\u7F6E", "\u6E32\u67D3\u7ED3\u679C"];
23727
+ if (needType === "personal_local_tool") {
23728
+ if (text.includes("\u836F")) return ["\u836F\u54C1"];
23729
+ if (text.includes("\u98DF\u6750")) return ["\u98DF\u6750"];
23730
+ return ["\u8BB0\u5F55"];
23731
+ }
23732
+ return [];
23733
+ }
23734
+ function extractStates(text, needType) {
23735
+ const states = [];
23736
+ if (needType === "multi_user_collaboration") states.push("\u5F85\u8BA4\u9886", "\u5DF2\u8BA4\u9886", "\u5DF2\u5B8C\u6210", "\u53D6\u6D88");
23737
+ if (hasAny2(text, ["\u8FC7\u671F", "\u4E34\u671F", "\u5230\u671F"])) states.push("\u6B63\u5E38", "\u4E34\u671F", "\u5DF2\u8FC7\u671F");
23738
+ return Array.from(new Set(states));
23739
+ }
23740
+ function extractActions(text, needType) {
23741
+ if (needType === "multi_user_collaboration") return ["\u5B89\u6392\u4EFB\u52A1", "\u8BA4\u9886\u4EFB\u52A1", "\u67E5\u770B\u65E5\u7A0B\u51B2\u7A81"];
23742
+ if (needType === "content_marketing_site") return ["\u66F4\u65B0\u5185\u5BB9", "\u53D1\u5E03\u4FC3\u9500", "\u7EF4\u62A4\u56FE\u7247\u548C FAQ"];
23743
+ if (needType === "data_visualization_site") return ["\u89E3\u6790 xlsx", "\u66F4\u65B0\u56FE\u8868\u6570\u636E", "\u6E32\u67D3\u7ED3\u679C"];
23744
+ return [];
23745
+ }
23746
+ var strongSignalMap = {
23747
+ \u591A\u4EBA: ["\u591A\u4EBA", "\u5BA4\u53CB", "\u5BB6\u4EBA\u5171\u7528", "\u5171\u7528", "\u5171\u4EAB"],
23748
+ \u534F\u4F5C: ["\u534F\u4F5C", "\u76F8\u4E92\u5B89\u6392", "\u8BA4\u9886", "\u5206\u914D\u4EFB\u52A1"],
23749
+ \u6743\u9650: ["\u6743\u9650", "\u767B\u5F55", "\u540E\u53F0", "\u7BA1\u7406\u5458", "\u5BA1\u6279", "\u5BA1\u6838"],
23750
+ \u516C\u5F00\u63D0\u4EA4: ["\u8BBF\u5BA2\u63D0\u4EA4", "\u7528\u6237\u63D0\u4EA4", "\u5728\u7EBF\u63D0\u4EA4", "\u63D0\u4EA4\u53CD\u9988"],
23751
+ \u4EA4\u6613: ["\u652F\u4ED8", "\u8BA2\u5355", "\u552E\u5356", "\u8D2D\u4E70", "\u62A5\u540D", "\u9884\u7EA6"],
23752
+ AI: ["AI", "ai", "API Key", "\u6A21\u578B\u63A5\u53E3", "\u5927\u6A21\u578B"]
23753
+ };
23754
+ var weakSignalMap = {
23755
+ \u5C55\u793A: ["\u5C55\u793A", "\u7F51\u7AD9", "\u9875\u9762"],
23756
+ \u89C6\u89C9: ["\u9875\u9762\u9AD8\u7EA7", "\u597D\u770B", "\u7F8E\u89C2"],
23757
+ \u7BA1\u7406: ["\u7BA1\u7406", "\u7EF4\u62A4", "\u5185\u5BB9\u591A"],
23758
+ \u5217\u8868: ["\u5217\u8868", "\u67E5\u770B", "\u7B5B\u9009", "\u65E5\u7A0B", "\u72B6\u6001"]
23759
+ };
23760
+ function collectSignals(text, map) {
23761
+ return Object.entries(map).filter(([, signals]) => hasAny2(text, signals)).map(([label]) => label);
23762
+ }
23763
+ function hasAny2(text, signals) {
23764
+ return signals.some((signal) => text.includes(signal));
23765
+ }
23766
+ function isNegated(text, signals) {
23767
+ 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));
23768
+ }
23769
+
23770
+ // src/core/pmGateClarification.ts
23771
+ function shouldUsePmGateClarification(decision) {
23772
+ return [
23773
+ "personal_local_tool",
23774
+ "multi_user_collaboration",
23775
+ "content_marketing_site",
23776
+ "data_visualization_site"
23777
+ ].includes(decision.needType);
23778
+ }
23779
+ function buildPmGateClarification(decision) {
23780
+ const questions = questionsForDecision(decision);
23781
+ return {
23782
+ missingFields: questions.map((question) => question.field),
23783
+ questions,
23784
+ defaultAssumptions: Object.fromEntries(questions.map((question) => [question.field, question.defaultAssumption]))
23785
+ };
23786
+ }
23787
+ function formatPmGateInterrogatePrelude(decision) {
23788
+ return `# PM Gate \u5224\u65AD\uFF1A${needTypeTitle(decision.needType)}
23789
+
23790
+ - **\u9700\u6C42\u95E8:** ${decision.needType}
23791
+ - **\u4F7F\u7528\u8303\u56F4:** ${decision.usageScope}
23792
+ - **\u7EF4\u62A4\u65B9\u5F0F:** ${decision.maintenanceMode}
23793
+ - **\u8BBF\u95EE\u65B9\u5F0F:** ${decision.accessTopology}
23794
+ - **\u6280\u672F\u5F62\u6001:** ${decision.technicalShape}
23795
+ - **\u63A8\u8350\u90E8\u7F72:** ${decision.recommendedDeployment}
23796
+ - **\u5F3A\u4FE1\u53F7:** ${decision.strongSignals.join("\u3001") || "\u65E0"}
23797
+ - **\u5F31\u4FE1\u53F7:** ${decision.weakSignals.join("\u3001") || "\u65E0"}
23798
+ - **\u4E0D\u8981\u9ED8\u8BA4\u4F7F\u7528:** ${decision.mustNotUse.join("\u3001") || "\u65E0"}
23799
+
23800
+ ${decision.defaultAssumptions.map((item) => `- ${item}`).join("\n")}
23801
+
23802
+ > \u5148\u786E\u8BA4\u4F7F\u7528\u8303\u56F4\u3001\u7EF4\u62A4\u65B9\u5F0F\u548C\u8BBF\u95EE\u8FB9\u754C\uFF1B\u4E0D\u8981\u5957\u7528\u65E0\u5173 domain \u6A21\u677F\u3002
23803
+ `;
23804
+ }
23805
+ function questionsForDecision(decision) {
23806
+ switch (decision.needType) {
23807
+ case "personal_local_tool":
23808
+ return personalLocalToolQuestions();
23809
+ case "multi_user_collaboration":
23810
+ return multiUserCollaborationQuestions();
23811
+ case "content_marketing_site":
23812
+ return contentMarketingQuestions();
23813
+ case "data_visualization_site":
23814
+ return dataVisualizationQuestions();
23815
+ default:
23816
+ return [];
23817
+ }
23818
+ }
23819
+ function personalLocalToolQuestions() {
23820
+ return [
23821
+ {
23822
+ field: "record_fields",
23823
+ question: "\u6BCF\u6761\u8BB0\u5F55\u8981\u4FDD\u5B58\u54EA\u4E9B\u4FE1\u606F\uFF1F",
23824
+ example: "\u6BD4\u5982\u836F\u54C1\u540D\u3001\u5206\u7C7B\u3001\u6570\u91CF\u3001\u5355\u4F4D\u3001\u6709\u6548\u671F\u3001\u5B58\u653E\u4F4D\u7F6E\u3001\u72B6\u6001\u3001\u5907\u6CE8\u3002",
23825
+ whyImportant: "\u51B3\u5B9A\u8868\u5355\u5B57\u6BB5\u3001\u5217\u8868\u5217\u548C\u63D0\u9192\u8BA1\u7B97\uFF0C\u4E0D\u9700\u8981\u56E0\u6B64\u5347\u7EA7\u5230\u540E\u53F0\u3002",
23826
+ options: ["\u540D\u79F0 + \u65E5\u671F + \u72B6\u6001 + \u5907\u6CE8", "\u518D\u52A0\u6570\u91CF/\u5355\u4F4D/\u5206\u7C7B/\u4F4D\u7F6E", "\u6211\u4F1A\u81EA\u5B9A\u4E49\u5B57\u6BB5"],
23827
+ defaultAssumption: "\u540D\u79F0\u3001\u65E5\u671F\u3001\u72B6\u6001\u3001\u5907\u6CE8\uFF1B\u836F\u54C1\u7C7B\u9ED8\u8BA4\u518D\u52A0\u6570\u91CF\u3001\u5206\u7C7B\u548C\u5B58\u653E\u4F4D\u7F6E",
23828
+ priority: "P0"
23829
+ },
23830
+ {
23831
+ field: "data_storage",
23832
+ question: "\u6570\u636E\u4FDD\u5B58\u5728\u54EA\u91CC\uFF1F",
23833
+ example: "\u6BD4\u5982\u6D4F\u89C8\u5668 localStorage\uFF0C\u672C\u673A JSON \u5907\u4EFD\uFF0C\u6216\u4EE5\u540E\u518D\u8003\u8651\u591A\u4EBA\u540C\u6B65\u3002",
23834
+ whyImportant: "\u4E2A\u4EBA\u6216\u5BB6\u5EAD\u81EA\u7528\u5DE5\u5177\u9ED8\u8BA4\u4E0D\u9700\u8981\u670D\u52A1\u5668\u6570\u636E\u5E93\u3002",
23835
+ options: ["\u6D4F\u89C8\u5668 localStorage", "JSON/CSV \u5BFC\u5165\u5BFC\u51FA\u5907\u4EFD", "\u4EE5\u540E\u518D\u8003\u8651\u591A\u4EBA\u540C\u6B65"],
23836
+ defaultAssumption: "\u6D4F\u89C8\u5668 localStorage\uFF0C\u652F\u6301 JSON \u5BFC\u5165\u5BFC\u51FA\u5907\u4EFD",
23837
+ priority: "P0"
23838
+ },
23839
+ {
23840
+ field: "operations",
23841
+ question: "\u7B2C\u4E00\u7248\u9700\u8981\u54EA\u4E9B\u64CD\u4F5C\uFF1F",
23842
+ example: "\u6BD4\u5982\u65B0\u589E\u3001\u7F16\u8F91\u3001\u5220\u9664\u3001\u641C\u7D22\u7B5B\u9009\u3001\u4E34\u671F/\u8FC7\u671F\u72B6\u6001\u5217\u8868\u3002",
23843
+ whyImportant: "\u9501\u5B9A MVP\uFF0C\u4E0D\u628A\u6E05\u5355\u5DE5\u5177\u6269\u6210\u540E\u53F0\u7CFB\u7EDF\u3002",
23844
+ options: ["\u65B0\u589E/\u7F16\u8F91/\u5220\u9664 + \u641C\u7D22\u7B5B\u9009", "\u518D\u52A0\u4E34\u671F/\u8FC7\u671F\u63D0\u9192", "\u518D\u52A0\u7EDF\u8BA1\u548C\u5BFC\u5165\u5BFC\u51FA"],
23845
+ defaultAssumption: "\u65B0\u589E/\u7F16\u8F91/\u5220\u9664 + \u641C\u7D22\u7B5B\u9009 + \u9875\u9762\u5185\u4E34\u671F/\u8FC7\u671F\u63D0\u9192",
23846
+ priority: "P0"
23847
+ },
23848
+ {
23849
+ field: "account_scope",
23850
+ question: "\u9700\u8981\u767B\u5F55\u3001\u540E\u53F0\u6216\u7BA1\u7406\u5458\u5417\uFF1F",
23851
+ example: "\u6BD4\u5982\u5B8C\u5168\u4E0D\u7528\u767B\u5F55\uFF0C\u5BB6\u5EAD\u7535\u8111\u672C\u5730\u7528\uFF1B\u6216\u4EE5\u540E\u518D\u505A\u591A\u4EBA\u8D26\u53F7\u3002",
23852
+ whyImportant: "\u51B3\u5B9A\u662F\u5426\u5F15\u5165\u540E\u7AEF\u3001\u9274\u6743\u548C\u670D\u52A1\u5668\u6210\u672C\u3002",
23853
+ options: ["\u4E0D\u9700\u8981\uFF0C\u6D4F\u89C8\u5668\u672C\u5730\u7528", "\u53EA\u52A0\u672C\u5730\u8BBF\u95EE\u5BC6\u7801", "\u9700\u8981\u591A\u4EBA\u8D26\u53F7/\u540E\u53F0"],
23854
+ defaultAssumption: "\u4E0D\u9700\u8981\u767B\u5F55\u3001\u540E\u53F0\u6216\u7BA1\u7406\u5458",
23855
+ priority: "P0"
23856
+ }
23857
+ ];
23858
+ }
23859
+ function multiUserCollaborationQuestions() {
23860
+ return [
23861
+ {
23862
+ field: "access_topology",
23863
+ question: "\u4F60\u4EEC\u53EA\u5728\u540C\u4E00 Wi-Fi/\u5C40\u57DF\u7F51\u4F7F\u7528\uFF0C\u8FD8\u662F\u5916\u51FA\u4E5F\u8981\u8BBF\u95EE\uFF1F",
23864
+ example: "\u6BD4\u5982\u5BBF\u820D\u540C\u4E00 Wi-Fi \u5185\u7528\uFF0C\u6216\u4EBA\u5728\u5916\u9762\u4E5F\u8981\u7528\u624B\u673A\u6253\u5F00\u3002",
23865
+ whyImportant: "\u5148\u51B3\u5B9A\u672C\u5730\u5C40\u57DF\u7F51\u670D\u52A1\u3001\u4F4E\u4EF7 VPS\uFF0C\u8FD8\u662F\u57DF\u540D + HTTPS\u3002",
23866
+ options: ["\u53EA\u5728\u540C\u4E00 Wi-Fi/\u5C40\u57DF\u7F51", "\u5916\u51FA\u4E5F\u8981\u8BBF\u95EE", "\u8981\u6B63\u5F0F\u57DF\u540D + HTTPS"],
23867
+ defaultAssumption: "\u5148\u786E\u8BA4\u8BBF\u95EE\u8303\u56F4\uFF0C\u4E0D\u76F4\u63A5\u9ED8\u8BA4\u516C\u7F51\u670D\u52A1\u5668",
23868
+ priority: "P0"
23869
+ },
23870
+ {
23871
+ field: "public_ip_acceptance",
23872
+ question: "\u5982\u679C\u5916\u51FA\u4E5F\u8981\u8BBF\u95EE\uFF0C\u80FD\u5426\u63A5\u53D7\u5148\u7528\u51E0\u5341\u5143/\u5E74\u7684\u516C\u7F51 VPS + IP \u5730\u5740\uFF1F",
23873
+ example: "\u6BD4\u5982\u5148\u901A\u8FC7 http://\u670D\u52A1\u5668IP \u6253\u5F00\uFF0C\u8DD1\u901A\u540E\u518D\u8003\u8651\u57DF\u540D\u548C\u5907\u6848\u3002",
23874
+ whyImportant: "\u56FA\u5B9A\u5C0F\u56E2\u961F MVP \u53EF\u4EE5\u5148\u907F\u5F00\u57DF\u540D\u3001\u8BC1\u4E66\u3001\u5907\u6848\u548C\u590D\u6742\u8FD0\u7EF4\u3002",
23875
+ options: ["\u80FD\u63A5\u53D7 IP \u8BBF\u95EE", "\u5FC5\u987B\u57DF\u540D + HTTPS", "\u5148\u53EA\u505A\u5C40\u57DF\u7F51"],
23876
+ defaultAssumption: "\u56FA\u5B9A\u5C0F\u7EC4\u5916\u51FA\u8BBF\u95EE\u65F6\uFF0C\u9ED8\u8BA4\u4F4E\u4EF7 VPS + SQLite + IP \u5730\u5740",
23877
+ priority: "P0"
23878
+ },
23879
+ {
23880
+ field: "claim_rule",
23881
+ question: "\u522B\u4EBA\u5B89\u6392\u7ED9\u6211\u7684\u4EFB\u52A1\uFF0C\u5FC5\u987B\u6211\u8BA4\u9886\u540E\u624D\u8FDB\u5165\u65E5\u7A0B\u5417\uFF1F",
23882
+ example: "\u6BD4\u5982\u5BA4\u53CB\u5B89\u6392\u540E\u5148\u663E\u793A\u5F85\u8BA4\u9886\uFF0C\u81EA\u5DF1\u7ED9\u81EA\u5DF1\u7684\u4EFB\u52A1\u76F4\u63A5\u751F\u6548\u3002",
23883
+ whyImportant: "\u51B3\u5B9A\u4EFB\u52A1\u72B6\u6001\u673A\u548C\u901A\u77E5/\u63D0\u9192\u903B\u8F91\u3002",
23884
+ options: ["\u5FC5\u987B\u8BA4\u9886\u540E\u751F\u6548", "\u521B\u5EFA\u540E\u8FDB\u5165\u5BF9\u65B9\u65E5\u7A0B\u4F46\u6807\u5F85\u786E\u8BA4", "\u521B\u5EFA\u540E\u76F4\u63A5\u751F\u6548"],
23885
+ defaultAssumption: "\u522B\u4EBA\u5B89\u6392\u7684\u4EFB\u52A1\u9700\u8981\u8BA4\u9886\uFF1B\u81EA\u5DF1\u5B89\u6392\u7ED9\u81EA\u5DF1\u7684\u4EFB\u52A1\u76F4\u63A5\u751F\u6548",
23886
+ priority: "P0"
23887
+ },
23888
+ {
23889
+ field: "time_conflict_rule",
23890
+ question: "\u540C\u4E00\u65F6\u95F4\u591A\u4E2A\u4EFB\u52A1\u51B2\u7A81\u65F6\uFF0C\u662F\u5E76\u6392\u5C55\u793A\u9AD8\u4EAE\uFF0C\u8FD8\u662F\u76F4\u63A5\u963B\u6B62\u5B89\u6392\uFF1F",
23891
+ example: "\u6BD4\u5982\u540C\u4E00\u5C0F\u65F6\u4E24\u4E2A\u4EFB\u52A1\u90FD\u663E\u793A\u5728\u65E5\u7A0B\u683C\u5B50\u91CC\uFF0C\u5E76\u7528\u7EA2\u8272\u63D0\u793A\u51B2\u7A81\u3002",
23892
+ whyImportant: "\u51B3\u5B9A\u65E5\u7A0B\u89C6\u56FE\u4EA4\u4E92\uFF0C\u662F\u63D0\u9192\u578B\u8FD8\u662F\u62E6\u622A\u578B\u3002",
23893
+ options: ["\u5E76\u6392\u5C55\u793A + \u9AD8\u4EAE\u51B2\u7A81", "\u963B\u6B62\u5B89\u6392", "\u53EA\u63D0\u793A\u4F46\u5141\u8BB8\u4FDD\u5B58"],
23894
+ defaultAssumption: "\u5E76\u6392\u5C55\u793A\u5E76\u9AD8\u4EAE\u51B2\u7A81\uFF0C\u4E0D\u9ED8\u8BA4\u963B\u6B62\u5B89\u6392",
23895
+ priority: "P1"
23896
+ }
23897
+ ];
23898
+ }
23899
+ function contentMarketingQuestions() {
23900
+ return [
23901
+ {
23902
+ field: "maintenance_mode",
23903
+ question: "\u5185\u5BB9\u66F4\u65B0\u662F\u4EA4\u7ED9 Agent \u6539\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72\uFF0C\u8FD8\u662F\u9700\u8981\u4F60\u5728\u7F51\u9875\u540E\u53F0\u81EA\u5DF1\u7F16\u8F91\uFF1F",
23904
+ example: "\u6BD4\u5982\u4F60\u628A\u65B0\u7167\u7247\u548C\u4FC3\u9500\u6587\u6848\u53D1\u7ED9 Agent\uFF1B\u6216\u7F51\u9875\u91CC\u767B\u5F55\u540E\u4E0A\u4F20\u56FE\u7247\u3002",
23905
+ whyImportant: "\u5185\u5BB9\u7ECF\u5E38\u6539\u4E0D\u7B49\u4E8E\u5FC5\u987B\u505A\u540E\u53F0\u3002",
23906
+ options: ["Agent \u4EE3\u7EF4\u62A4\u5E76\u91CD\u65B0\u90E8\u7F72", "\u6211\u624B\u52A8\u6539 Markdown/data.json", "\u7F51\u9875\u540E\u53F0\u7F16\u8F91\u548C\u4E0A\u4F20"],
23907
+ defaultAssumption: "\u5148\u6309 Agent \u4EE3\u7EF4\u62A4\u5185\u5BB9\u6587\u4EF6\u5E76\u91CD\u65B0\u90E8\u7F72",
23908
+ priority: "P0"
23909
+ },
23910
+ {
23911
+ field: "visitor_submission",
23912
+ question: "\u8BBF\u5BA2\u9700\u8981\u5728\u7F51\u7AD9\u4E0A\u63D0\u4EA4\u53CD\u9988\u3001\u9884\u7EA6\u6216\u62A5\u540D\u5417\uFF1F",
23913
+ example: "\u6BD4\u5982\u7528\u6237\u8BC4\u4EF7\u53EA\u662F\u4F60\u6574\u7406\u540E\u5C55\u793A\uFF0C\u8FD8\u662F\u8BBF\u5BA2\u80FD\u76F4\u63A5\u63D0\u4EA4\u8868\u5355\u3002",
23914
+ whyImportant: "\u8BBF\u5BA2\u63D0\u4EA4\u4F1A\u89E6\u53D1\u540E\u7AEF\u3001\u5BA1\u6838\u3001\u9632\u5783\u573E\u548C\u901A\u77E5\u3002",
23915
+ options: ["\u4E0D\u9700\u8981\u8BBF\u5BA2\u63D0\u4EA4", "\u53EA\u5C55\u793A\u4F60\u6574\u7406\u7684\u53CD\u9988", "\u9700\u8981\u8BBF\u5BA2\u5728\u7EBF\u63D0\u4EA4"],
23916
+ defaultAssumption: "\u4E0D\u505A\u8BBF\u5BA2\u63D0\u4EA4\uFF0C\u53EA\u5C55\u793A\u7EF4\u62A4\u540E\u7684\u5185\u5BB9",
23917
+ priority: "P0"
23918
+ },
23919
+ {
23920
+ field: "geo_goal",
23921
+ question: "GEO/SEO \u91CD\u70B9\u670D\u52A1\u54EA\u4E2A\u672C\u5730\u66DD\u5149\u76EE\u6807\uFF1F",
23922
+ example: "\u6BD4\u5982\u9644\u8FD1\u5065\u8EAB\u623F\u641C\u7D22\u3001\u79C1\u6559\u5173\u952E\u8BCD\u3001\u56E2\u8BFE\u4FC3\u9500\u3001\u54C1\u724C\u95EE\u7B54\u3002",
23923
+ whyImportant: "\u51B3\u5B9A\u9875\u9762\u7ED3\u6784\u3001FAQ\u3001schema \u548C\u5185\u5BB9\u680F\u76EE\u4F18\u5148\u7EA7\u3002",
23924
+ options: ["\u672C\u5730\u641C\u7D22\u66DD\u5149", "\u95EE\u7B54\u5185\u5BB9\u8986\u76D6", "\u4FC3\u9500\u6D3B\u52A8\u8F6C\u5316"],
23925
+ defaultAssumption: "\u672C\u5730\u670D\u52A1\u5B98\u7F51 + FAQ + \u6559\u7EC3/\u8BFE\u7A0B/\u4FC3\u9500\u7ED3\u6784\u5316\u5185\u5BB9",
23926
+ priority: "P1"
23927
+ }
23928
+ ];
23929
+ }
23930
+ function dataVisualizationQuestions() {
23931
+ return [
23932
+ {
23933
+ field: "data_update_mode",
23934
+ question: "\u65B0 xlsx \u662F\u4EA4\u7ED9 Agent \u66F4\u65B0\u7F51\u7AD9\uFF0C\u8FD8\u662F\u7F51\u7AD9\u91CC\u8981\u6709\u4E0A\u4F20\u6309\u94AE\uFF1F",
23935
+ example: "\u6BD4\u5982\u6BCF\u6B21\u628A Excel \u53D1\u7ED9 Agent \u91CD\u65B0\u751F\u6210 data.json\uFF0C\u6216\u7528\u6237\u5728\u7F51\u9875\u91CC\u4E0A\u4F20\u3002",
23936
+ whyImportant: "Agent \u66F4\u65B0\u53EF\u4EE5\u4FDD\u6301\u9759\u6001\u7AD9\uFF1B\u7F51\u9875\u4E0A\u4F20\u624D\u9700\u8981\u66F4\u591A\u8FD0\u884C\u65F6\u903B\u8F91\u3002",
23937
+ options: ["\u4EA4\u7ED9 Agent \u66F4\u65B0\u5E76\u91CD\u65B0\u90E8\u7F72", "\u6D4F\u89C8\u5668\u5185\u4E0A\u4F20\u89E3\u6790", "\u540E\u7AEF\u7EDF\u4E00\u4E0A\u4F20\u4FDD\u5B58"],
23938
+ defaultAssumption: "Agent \u89E3\u6790 xlsx \u751F\u6210 data.json/chart config\uFF0C\u518D\u91CD\u65B0\u90E8\u7F72\u9759\u6001\u56FE\u8868\u7AD9",
23939
+ priority: "P0"
23940
+ },
23941
+ {
23942
+ field: "audience_scope",
23943
+ question: "\u56FE\u8868\u53EA\u7ED9\u81EA\u5DF1\u770B\uFF0C\u8FD8\u662F\u516C\u5F00\u7ED9\u522B\u4EBA\u770B\uFF1F",
23944
+ example: "\u6BD4\u5982\u672C\u5730\u6253\u5F00\u67E5\u770B\uFF0C\u6216\u90E8\u7F72\u5230\u516C\u5F00\u7F51\u5740\u7ED9\u5BA2\u6237/\u56E2\u961F\u770B\u3002",
23945
+ whyImportant: "\u51B3\u5B9A\u90E8\u7F72\u3001\u6743\u9650\u548C\u662F\u5426\u9700\u8981\u7EDF\u4E00\u5728\u7EBF\u6570\u636E\u6E90\u3002",
23946
+ options: ["\u53EA\u7ED9\u81EA\u5DF1\u770B", "\u516C\u5F00\u53EA\u8BFB\u5C55\u793A", "\u56FA\u5B9A\u56E2\u961F\u53EF\u8BBF\u95EE"],
23947
+ defaultAssumption: "\u9ED8\u8BA4\u9759\u6001\u53EA\u8BFB\u5C55\u793A\uFF0C\u4E0D\u9ED8\u8BA4\u767B\u5F55\u548C\u540E\u53F0",
23948
+ priority: "P0"
23949
+ },
23950
+ {
23951
+ field: "history_versions",
23952
+ question: "\u9700\u8981\u4FDD\u7559\u5386\u53F2\u7248\u672C\uFF0C\u8FD8\u662F\u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C\uFF1F",
23953
+ example: "\u6BD4\u5982\u53EA\u66FF\u6362\u6700\u65B0\u6570\u636E\uFF0C\u6216\u4FDD\u7559\u6BCF\u6708 Excel \u5BF9\u6BD4\u8D8B\u52BF\u3002",
23954
+ whyImportant: "\u51B3\u5B9A\u6570\u636E\u6587\u4EF6\u7ED3\u6784\u548C\u662F\u5426\u9700\u8981\u7248\u672C\u7BA1\u7406\u3002",
23955
+ options: ["\u53EA\u5C55\u793A\u6700\u65B0", "\u4FDD\u7559\u5386\u53F2\u7248\u672C", "\u540E\u7EED\u518D\u52A0"],
23956
+ defaultAssumption: "MVP \u53EA\u5C55\u793A\u6700\u65B0\u7ED3\u679C",
23957
+ priority: "P1"
23958
+ }
23959
+ ];
23960
+ }
23961
+ function needTypeTitle(needType) {
23962
+ const titles = {
23963
+ static_display: "\u9759\u6001\u5C55\u793A\u7F51\u7AD9",
23964
+ personal_local_tool: "\u4E2A\u4EBA\u672C\u5730\u5DE5\u5177",
23965
+ multi_user_collaboration: "\u591A\u4EBA\u534F\u4F5C\u5DE5\u5177",
23966
+ content_marketing_site: "\u5185\u5BB9\u8425\u9500\u7F51\u7AD9",
23967
+ data_visualization_site: "\u6570\u636E\u56FE\u8868\u7F51\u7AD9",
23968
+ transaction_workflow: "\u4EA4\u6613/\u5C65\u7EA6\u6D41\u7A0B",
23969
+ content_knowledge: "\u5185\u5BB9/\u77E5\u8BC6\u7BA1\u7406",
23970
+ ai_automation: "AI \u81EA\u52A8\u5316\u4EA7\u54C1",
23971
+ unknown: "\u4EA7\u54C1\u5F00\u53D1"
23972
+ };
23973
+ return titles[needType];
23974
+ }
23975
+
23486
23976
  // src/tools/specInterrogate.ts
23487
23977
  function registerSpecInterrogate(server) {
23488
23978
  const handler = async (input) => {
23489
23979
  const readiness = calculateReadiness(input.raw_idea, input.known_context);
23490
- const clarification = generateClarification(
23980
+ const technicalProfile = buildTechnicalProfile(input.raw_idea, input.known_context || {});
23981
+ const pmIntentDecision = decidePmIntent(input.raw_idea, input.known_context || {});
23982
+ const usePmGate = input.scenario !== "modify_ui" && shouldUsePmGateClarification(pmIntentDecision);
23983
+ const clarification = usePmGate ? buildPmGateClarification(pmIntentDecision) : generateClarification(
23491
23984
  input.raw_idea,
23492
23985
  readiness,
23493
23986
  input.scenario,
23494
23987
  input.target_platform,
23495
23988
  input.strictness,
23496
- input.known_context
23497
- );
23498
- const markdown = formatInterrogateResult(readiness, clarification);
23499
- const structuredContent = buildInterrogateStructuredOutput(readiness, clarification);
23500
- return {
23501
- content: [{ type: "text", text: markdown }],
23502
- structuredContent
23503
- };
23504
- };
23505
- server.registerTool(
23506
- "spec_interrogate",
23507
- {
23508
- title: "\u9700\u6C42\u8FFD\u95EE",
23509
- description: "\u5206\u6790\u7528\u6237\u7684\u539F\u59CB idea \u6216\u9875\u9762\u4FEE\u6539\u9700\u6C42\uFF0C\u5224\u65AD\u4FE1\u606F\u662F\u5426\u8DB3\u591F\u8FDB\u5165\u5F00\u53D1\u9636\u6BB5\u3002\u5F53\u4FE1\u606F\u7F3A\u5931\u8F83\u591A\u65F6\uFF0C\u8F93\u51FA\u8FFD\u95EE\u95EE\u9898\u6E05\u5355\u3002",
23510
- inputSchema: SpecInterrogateInputSchema.shape,
23511
- outputSchema: SpecInterrogateOutputSchema.shape
23512
- },
23513
- handler
23514
- );
23515
- }
23516
-
23517
- // src/schemas/specCompile.schema.ts
23518
- var SpecCompileInputSchema = external_exports.object({
23519
- raw_idea: external_exports.string().describe("\u7528\u6237\u539F\u59CB\u60F3\u6CD5"),
23520
- answers: external_exports.record(external_exports.string(), external_exports.any()).optional().describe("\u7528\u6237\u5BF9\u8FFD\u95EE\u7684\u56DE\u7B54"),
23521
- allow_assumptions: external_exports.boolean().optional().default(true).describe("\u662F\u5426\u5141\u8BB8\u4F7F\u7528\u9ED8\u8BA4\u5047\u8BBE"),
23522
- min_readiness_score: external_exports.number().optional().default(70).describe("\u6700\u4F4E\u53EF\u63A5\u53D7\u7684 readiness \u5206\u6570")
23523
- });
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"])
23989
+ input.known_context
23990
+ );
23991
+ const baseMarkdown = formatInterrogateResult(readiness, clarification);
23992
+ const markdown = usePmGate ? `${formatPmGateInterrogatePrelude(pmIntentDecision)}
23993
+ ${baseMarkdown}` : baseMarkdown;
23994
+ const structuredContent = buildInterrogateStructuredOutput(
23995
+ readiness,
23996
+ clarification,
23997
+ technicalProfile,
23998
+ usePmGate ? pmIntentDecision : void 0
23999
+ );
24000
+ return {
24001
+ content: [{ type: "text", text: markdown }],
24002
+ structuredContent
24003
+ };
24004
+ };
24005
+ server.registerTool(
24006
+ "spec_interrogate",
24007
+ {
24008
+ title: "\u9700\u6C42\u8FFD\u95EE",
24009
+ description: "\u5206\u6790\u7528\u6237\u7684\u539F\u59CB idea \u6216\u9875\u9762\u4FEE\u6539\u9700\u6C42\uFF0C\u5224\u65AD\u4FE1\u606F\u662F\u5426\u8DB3\u591F\u8FDB\u5165\u5F00\u53D1\u9636\u6BB5\u3002\u5F53\u4FE1\u606F\u7F3A\u5931\u8F83\u591A\u65F6\uFF0C\u8F93\u51FA\u8FFD\u95EE\u95EE\u9898\u6E05\u5355\u3002",
24010
+ inputSchema: SpecInterrogateInputSchema.shape,
24011
+ outputSchema: SpecInterrogateOutputSchema.shape
24012
+ },
24013
+ handler
24014
+ );
24015
+ }
24016
+
24017
+ // src/schemas/coercion.ts
24018
+ var looseBoolean = external_exports.preprocess((value) => {
24019
+ if (typeof value !== "string") return value;
24020
+ const normalized = value.trim().toLowerCase();
24021
+ if (normalized === "true") return true;
24022
+ if (normalized === "false") return false;
24023
+ return value;
24024
+ }, external_exports.boolean());
24025
+ var looseNumber = external_exports.preprocess((value) => {
24026
+ if (typeof value !== "string") return value;
24027
+ const normalized = value.trim();
24028
+ if (normalized === "") return value;
24029
+ const parsed = Number(normalized);
24030
+ return Number.isFinite(parsed) ? parsed : value;
24031
+ }, external_exports.number());
24032
+ function looseStringArray(description) {
24033
+ return external_exports.preprocess((value) => {
24034
+ if (Array.isArray(value)) return value;
24035
+ if (value && typeof value === "object" && "item" in value && Array.isArray(value.item)) {
24036
+ return value.item;
24037
+ }
24038
+ return value;
24039
+ }, external_exports.array(external_exports.string())).describe(description);
24040
+ }
24041
+
24042
+ // src/schemas/specCompile.schema.ts
24043
+ var SpecCompileInputSchema = external_exports.object({
24044
+ raw_idea: external_exports.string().describe("\u7528\u6237\u539F\u59CB\u60F3\u6CD5"),
24045
+ answers: external_exports.record(external_exports.string(), external_exports.any()).optional().describe("\u7528\u6237\u5BF9\u8FFD\u95EE\u7684\u56DE\u7B54"),
24046
+ allow_assumptions: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(true).describe("\u662F\u5426\u5141\u8BB8\u4F7F\u7528\u9ED8\u8BA4\u5047\u8BBE"),
24047
+ min_readiness_score: external_exports.union([external_exports.number(), looseNumber]).optional().default(70).describe("\u6700\u4F4E\u53EF\u63A5\u53D7\u7684 readiness \u5206\u6570")
23577
24048
  });
23578
24049
 
23579
24050
  // src/schemas/outputs/specCompile.output.ts
@@ -23701,228 +24172,6 @@ function addIf(items, label, condition) {
23701
24172
  if (condition) items.push(label);
23702
24173
  }
23703
24174
 
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
-
23926
24175
  // src/core/promptBuilder.ts
23927
24176
  function buildSpec(rawIdea, context, readiness) {
23928
24177
  const assumptions = [];
@@ -25549,8 +25798,8 @@ function registerSpecCompile(server) {
25549
25798
  var ArchitectureDecideInputSchema = external_exports.object({
25550
25799
  product_type: external_exports.string().describe("\u4EA7\u54C1\u7C7B\u578B\u63CF\u8FF0"),
25551
25800
  platform: external_exports.enum(["web", "mini_program", "app", "backend"]).describe("\u76EE\u6807\u5E73\u53F0"),
25552
- features: external_exports.array(external_exports.string()).describe("\u529F\u80FD\u5217\u8868"),
25553
- commercial_intent: external_exports.boolean().optional().default(false).describe("\u662F\u5426\u6709\u5546\u4E1A\u5316\u610F\u56FE"),
25801
+ features: looseStringArray("\u529F\u80FD\u5217\u8868"),
25802
+ commercial_intent: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(false).describe("\u662F\u5426\u6709\u5546\u4E1A\u5316\u610F\u56FE"),
25554
25803
  expected_users: external_exports.enum(["individual", "small_team", "enterprise", "massive"]).optional().default("individual").describe("\u9884\u671F\u7528\u6237\u89C4\u6A21")
25555
25804
  });
25556
25805
 
@@ -26625,11 +26874,11 @@ function registerDebugGuide(server) {
26625
26874
  // src/schemas/acceptanceGenerate.schema.ts
26626
26875
  var AcceptanceGenerateInputSchema = external_exports.object({
26627
26876
  product_type: external_exports.string().describe("\u4EA7\u54C1\u7C7B\u578B"),
26628
- features: external_exports.array(external_exports.string()).describe("\u529F\u80FD\u5217\u8868"),
26877
+ features: looseStringArray("\u529F\u80FD\u5217\u8868"),
26629
26878
  platform: external_exports.enum(["web", "mini_program", "app", "backend"]).describe("\u76EE\u6807\u5E73\u53F0"),
26630
- has_backend: external_exports.boolean().optional().default(false).describe("\u662F\u5426\u6709\u540E\u7AEF"),
26631
- has_payment: external_exports.boolean().optional().default(false).describe("\u662F\u5426\u6D89\u53CA\u652F\u4ED8"),
26632
- has_auth: external_exports.boolean().optional().default(false).describe("\u662F\u5426\u6D89\u53CA\u9274\u6743")
26879
+ has_backend: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(false).describe("\u662F\u5426\u6709\u540E\u7AEF"),
26880
+ has_payment: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(false).describe("\u662F\u5426\u6D89\u53CA\u652F\u4ED8"),
26881
+ has_auth: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(false).describe("\u662F\u5426\u6D89\u53CA\u9274\u6743")
26633
26882
  });
26634
26883
 
26635
26884
  // src/schemas/outputs/acceptanceGenerate.output.ts
@@ -27573,7 +27822,7 @@ var ProductSpecAssistInputSchema = external_exports.object({
27573
27822
  known_context: external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe("\u5DF2\u6709\u4E0A\u4E0B\u6587"),
27574
27823
  preferred_platform: external_exports.enum(["web", "mini_program", "app", "backend", "unknown"]).optional().default("unknown").describe("\u7528\u6237\u5DF2\u77E5\u5E73\u53F0"),
27575
27824
  strictness: external_exports.enum(["light", "normal", "grill"]).optional().default("normal").describe("\u8FFD\u95EE\u5F3A\u5EA6"),
27576
- auto_execute: external_exports.boolean().optional().default(true).describe("\u662F\u5426\u5141\u8BB8\u81EA\u52A8\u8C03\u7528\u5BF9\u5E94 engine")
27825
+ auto_execute: external_exports.union([external_exports.boolean(), looseBoolean]).optional().default(true).describe("\u662F\u5426\u5141\u8BB8\u81EA\u52A8\u8C03\u7528\u5BF9\u5E94 engine")
27577
27826
  });
27578
27827
 
27579
27828
  // src/schemas/outputs/productSpecAssist.output.ts
@@ -27702,7 +27951,7 @@ async function callRemotePmIntentGate(message, context, localDecision) {
27702
27951
  const url = process.env.PRODUCT_SPEC_REMOTE_GATE_URL;
27703
27952
  if (!url) return null;
27704
27953
  const controller = new AbortController();
27705
- const timeout = Number(process.env.PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS || 2500);
27954
+ const timeout = Number(process.env.PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS || 1e4);
27706
27955
  const timer = setTimeout(() => controller.abort(), timeout);
27707
27956
  try {
27708
27957
  const response = await fetch(url, {
@@ -27874,6 +28123,7 @@ function enforceRemoteHardRules(remote, local) {
27874
28123
  needType: "multi_user_collaboration",
27875
28124
  maintenanceMode: "runtime_collaboration",
27876
28125
  technicalShape: "light_backend_json_sqlite",
28126
+ recommendedDeployment: recommendedDeploymentForCollaboration2(remote.accessTopology),
27877
28127
  route: "spec_interrogate",
27878
28128
  mustNotUse: mergeStrings(remote.mustNotUse, ["static_display", "local_storage_only"])
27879
28129
  };
@@ -27891,6 +28141,12 @@ function enforceRemoteHardRules(remote, local) {
27891
28141
  }
27892
28142
  return remote;
27893
28143
  }
28144
+ function recommendedDeploymentForCollaboration2(accessTopology) {
28145
+ if (accessTopology === "lan_only") return "local_lan_server_sqlite";
28146
+ if (accessTopology === "internet_ip") return "cheap_vps_sqlite_by_ip";
28147
+ if (accessTopology === "public_domain") return "vps_domain_https";
28148
+ return "unknown";
28149
+ }
27894
28150
  function hasRouteShapeConflict(decision) {
27895
28151
  return decision.route === "architecture_decide" && decision.technicalShape !== "static_page";
27896
28152
  }
@@ -28094,6 +28350,7 @@ function handleBuildProduct(message, knownContext, strictness, autoExecute, rout
28094
28350
  quickQuestions,
28095
28351
  agentGuidance: [
28096
28352
  "\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",
28353
+ "\u5F53\u524D nextAction \u662F confirm_spec\uFF0C\u8868\u793A\u8349\u6848\u5DF2\u7ECF\u751F\u6210\uFF1B\u4E0D\u8981\u518D\u8C03\u7528 spec_interrogate\u3001spec_compile \u6216 architecture_decide \u6765\u91CD\u590D\u8FFD\u95EE\uFF0C\u9664\u975E\u7528\u6237\u660E\u786E\u8981\u6C42\u4FEE\u6539\u89C4\u683C\u3002",
28097
28354
  "\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
28355
  "\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
28356
  "\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"
@@ -29682,7 +29939,7 @@ function registerProductSpecAssist(server) {
29682
29939
  function createServer() {
29683
29940
  const server = new McpServer({
29684
29941
  name: "product-spec-mcp",
29685
- version: "0.3.28"
29942
+ version: "0.3.30"
29686
29943
  });
29687
29944
  registerSpecInterrogate(server);
29688
29945
  registerSpecCompile(server);
@@ -7,7 +7,7 @@ P0 online gate is an HTTP classifier for low-confidence or conflicting local PM
7
7
  ```bash
8
8
  PRODUCT_SPEC_REMOTE_GATE_URL=https://gate.example.com/v1/pm-intent
9
9
  PRODUCT_SPEC_REMOTE_GATE_TOKEN=replace-with-token
10
- PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS=2500
10
+ PRODUCT_SPEC_REMOTE_GATE_TIMEOUT_MS=10000
11
11
  PRODUCT_SPEC_REMOTE_GATE_MODE=auto
12
12
  PRODUCT_SPEC_TELEMETRY=off
13
13
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "product-spec-mcp",
3
- "version": "0.3.28",
3
+ "version": "0.3.30",
4
4
  "description": "MCP Server for product specification - requirement interrogation, architecture decision, UI translation, debug guidance, and acceptance generation",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.cjs",