fodda-mcp 1.46.31 → 1.46.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +14 -94
  2. package/dist/agents/fodda-researcher/skills.d.ts +1 -1
  3. package/dist/agents/fodda-researcher/skills.d.ts.map +1 -1
  4. package/dist/agents/fodda-researcher/skills.js +1 -1
  5. package/dist/brandTemplate.d.ts +1 -1
  6. package/dist/brandTemplate.d.ts.map +1 -1
  7. package/dist/brandTemplate.js +162 -74
  8. package/dist/brandTemplate.js.map +1 -1
  9. package/dist/catalogCache.d.ts +29 -1
  10. package/dist/catalogCache.d.ts.map +1 -1
  11. package/dist/catalogCache.js +267 -16
  12. package/dist/catalogCache.js.map +1 -1
  13. package/dist/coverageRelevance.d.ts +97 -2
  14. package/dist/coverageRelevance.d.ts.map +1 -1
  15. package/dist/coverageRelevance.js +959 -164
  16. package/dist/coverageRelevance.js.map +1 -1
  17. package/dist/editorialFill.d.ts +5 -0
  18. package/dist/editorialFill.d.ts.map +1 -1
  19. package/dist/editorialFill.js +1 -1
  20. package/dist/editorialFill.js.map +1 -1
  21. package/dist/enrichment.d.ts +26 -0
  22. package/dist/enrichment.d.ts.map +1 -1
  23. package/dist/enrichment.js +394 -31
  24. package/dist/enrichment.js.map +1 -1
  25. package/dist/errorHandling.d.ts +35 -7
  26. package/dist/errorHandling.d.ts.map +1 -1
  27. package/dist/errorHandling.js +225 -155
  28. package/dist/errorHandling.js.map +1 -1
  29. package/dist/index.d.ts +25 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +351 -143
  32. package/dist/index.js.map +1 -1
  33. package/dist/jobs/jlens_quarterly_sweep.d.ts +62 -0
  34. package/dist/jobs/jlens_quarterly_sweep.d.ts.map +1 -0
  35. package/dist/jobs/jlens_quarterly_sweep.js +160 -0
  36. package/dist/jobs/jlens_quarterly_sweep.js.map +1 -0
  37. package/dist/pricingCache.d.ts.map +1 -1
  38. package/dist/pricingCache.js +41 -1
  39. package/dist/pricingCache.js.map +1 -1
  40. package/dist/queryCache.d.ts.map +1 -1
  41. package/dist/queryCache.js +2 -0
  42. package/dist/queryCache.js.map +1 -1
  43. package/dist/reportBriefing.d.ts +89 -0
  44. package/dist/reportBriefing.d.ts.map +1 -0
  45. package/dist/reportBriefing.js +662 -0
  46. package/dist/reportBriefing.js.map +1 -0
  47. package/dist/searchTemplate.d.ts.map +1 -1
  48. package/dist/searchTemplate.js +65 -53
  49. package/dist/searchTemplate.js.map +1 -1
  50. package/dist/services/graphRouter.d.ts +7 -0
  51. package/dist/services/graphRouter.d.ts.map +1 -0
  52. package/dist/services/graphRouter.js +7 -0
  53. package/dist/services/graphRouter.js.map +1 -0
  54. package/dist/services/notifications.d.ts +49 -0
  55. package/dist/services/notifications.d.ts.map +1 -0
  56. package/dist/services/notifications.js +206 -0
  57. package/dist/services/notifications.js.map +1 -0
  58. package/dist/sessionTracker.d.ts +19 -2
  59. package/dist/sessionTracker.d.ts.map +1 -1
  60. package/dist/sessionTracker.js +69 -16
  61. package/dist/sessionTracker.js.map +1 -1
  62. package/dist/skillClient.d.ts.map +1 -1
  63. package/dist/skillClient.js +11 -6
  64. package/dist/skillClient.js.map +1 -1
  65. package/dist/svgVisuals.d.ts +17 -19
  66. package/dist/svgVisuals.d.ts.map +1 -1
  67. package/dist/svgVisuals.js +189 -233
  68. package/dist/svgVisuals.js.map +1 -1
  69. package/dist/systemPrompt.d.ts +7 -2
  70. package/dist/systemPrompt.d.ts.map +1 -1
  71. package/dist/systemPrompt.js +110 -68
  72. package/dist/systemPrompt.js.map +1 -1
  73. package/dist/telemetry.d.ts.map +1 -1
  74. package/dist/telemetry.js +15 -0
  75. package/dist/telemetry.js.map +1 -1
  76. package/dist/test_adjacent_trends_polymorphic.d.ts +2 -0
  77. package/dist/test_adjacent_trends_polymorphic.d.ts.map +1 -0
  78. package/dist/test_adjacent_trends_polymorphic.js +154 -0
  79. package/dist/test_adjacent_trends_polymorphic.js.map +1 -0
  80. package/dist/test_book_a_call_live.js +18 -5
  81. package/dist/test_book_a_call_live.js.map +1 -1
  82. package/dist/test_byo_mcp_submission_clarity.d.ts +2 -0
  83. package/dist/test_byo_mcp_submission_clarity.d.ts.map +1 -0
  84. package/dist/test_byo_mcp_submission_clarity.js +142 -0
  85. package/dist/test_byo_mcp_submission_clarity.js.map +1 -0
  86. package/dist/test_capabilities_guidance.d.ts +2 -0
  87. package/dist/test_capabilities_guidance.d.ts.map +1 -0
  88. package/dist/test_capabilities_guidance.js +372 -0
  89. package/dist/test_capabilities_guidance.js.map +1 -0
  90. package/dist/test_client_provenance.d.ts +2 -0
  91. package/dist/test_client_provenance.d.ts.map +1 -0
  92. package/dist/test_client_provenance.js +77 -0
  93. package/dist/test_client_provenance.js.map +1 -0
  94. package/dist/test_connection_surface_cleanup.d.ts +2 -0
  95. package/dist/test_connection_surface_cleanup.d.ts.map +1 -0
  96. package/dist/test_connection_surface_cleanup.js +203 -0
  97. package/dist/test_connection_surface_cleanup.js.map +1 -0
  98. package/dist/test_consult_routing.d.ts +2 -0
  99. package/dist/test_consult_routing.d.ts.map +1 -0
  100. package/dist/test_consult_routing.js +86 -0
  101. package/dist/test_consult_routing.js.map +1 -0
  102. package/dist/test_consult_split.d.ts +2 -0
  103. package/dist/test_consult_split.d.ts.map +1 -0
  104. package/dist/test_consult_split.js +30 -0
  105. package/dist/test_consult_split.js.map +1 -0
  106. package/dist/test_coverage_relevance.js +111 -70
  107. package/dist/test_coverage_relevance.js.map +1 -1
  108. package/dist/test_coverage_replay.d.ts +2 -0
  109. package/dist/test_coverage_replay.d.ts.map +1 -0
  110. package/dist/test_coverage_replay.js +170 -0
  111. package/dist/test_coverage_replay.js.map +1 -0
  112. package/dist/test_dcr_and_legacy_deprecation.js +45 -50
  113. package/dist/test_dcr_and_legacy_deprecation.js.map +1 -1
  114. package/dist/test_demand_signal_logging.d.ts +2 -0
  115. package/dist/test_demand_signal_logging.d.ts.map +1 -0
  116. package/dist/test_demand_signal_logging.js +92 -0
  117. package/dist/test_demand_signal_logging.js.map +1 -0
  118. package/dist/test_earnings_activity_scope.d.ts +5 -0
  119. package/dist/test_earnings_activity_scope.d.ts.map +1 -0
  120. package/dist/test_earnings_activity_scope.js +101 -0
  121. package/dist/test_earnings_activity_scope.js.map +1 -0
  122. package/dist/test_earnings_divergence_live.d.ts +5 -0
  123. package/dist/test_earnings_divergence_live.d.ts.map +1 -0
  124. package/dist/test_earnings_divergence_live.js +135 -0
  125. package/dist/test_earnings_divergence_live.js.map +1 -0
  126. package/dist/test_earnings_hygiene_and_binding.d.ts +5 -0
  127. package/dist/test_earnings_hygiene_and_binding.d.ts.map +1 -0
  128. package/dist/test_earnings_hygiene_and_binding.js +104 -0
  129. package/dist/test_earnings_hygiene_and_binding.js.map +1 -0
  130. package/dist/test_exec_quotes_render.d.ts +2 -0
  131. package/dist/test_exec_quotes_render.d.ts.map +1 -0
  132. package/dist/test_exec_quotes_render.js +86 -0
  133. package/dist/test_exec_quotes_render.js.map +1 -0
  134. package/dist/test_expert_intro.d.ts +2 -0
  135. package/dist/test_expert_intro.d.ts.map +1 -0
  136. package/dist/test_expert_intro.js +57 -0
  137. package/dist/test_expert_intro.js.map +1 -0
  138. package/dist/test_expert_layer.d.ts +11 -0
  139. package/dist/test_expert_layer.d.ts.map +1 -0
  140. package/dist/test_expert_layer.js +356 -0
  141. package/dist/test_expert_layer.js.map +1 -0
  142. package/dist/test_gap_alert.js +8 -0
  143. package/dist/test_gap_alert.js.map +1 -1
  144. package/dist/test_grok_offering_surfaces.d.ts +2 -0
  145. package/dist/test_grok_offering_surfaces.d.ts.map +1 -0
  146. package/dist/test_grok_offering_surfaces.js +155 -0
  147. package/dist/test_grok_offering_surfaces.js.map +1 -0
  148. package/dist/test_human_agent_live.d.ts +2 -0
  149. package/dist/test_human_agent_live.d.ts.map +1 -0
  150. package/dist/test_human_agent_live.js +48 -0
  151. package/dist/test_human_agent_live.js.map +1 -0
  152. package/dist/test_identity_gap.d.ts +2 -0
  153. package/dist/test_identity_gap.d.ts.map +1 -0
  154. package/dist/test_identity_gap.js +171 -0
  155. package/dist/test_identity_gap.js.map +1 -0
  156. package/dist/test_intelligence_and_verifier.d.ts +17 -0
  157. package/dist/test_intelligence_and_verifier.d.ts.map +1 -0
  158. package/dist/test_intelligence_and_verifier.js +162 -0
  159. package/dist/test_intelligence_and_verifier.js.map +1 -0
  160. package/dist/test_latency_mcp_brief5.d.ts +12 -0
  161. package/dist/test_latency_mcp_brief5.d.ts.map +1 -0
  162. package/dist/test_latency_mcp_brief5.js +200 -0
  163. package/dist/test_latency_mcp_brief5.js.map +1 -0
  164. package/dist/test_limit_and_credit_card_capture.d.ts +21 -0
  165. package/dist/test_limit_and_credit_card_capture.d.ts.map +1 -0
  166. package/dist/test_limit_and_credit_card_capture.js +216 -0
  167. package/dist/test_limit_and_credit_card_capture.js.map +1 -0
  168. package/dist/test_list_graphs_topics.js +1 -1
  169. package/dist/test_list_graphs_topics.js.map +1 -1
  170. package/dist/test_live_deployed_mcp_search.d.ts +2 -0
  171. package/dist/test_live_deployed_mcp_search.d.ts.map +1 -0
  172. package/dist/test_live_deployed_mcp_search.js +85 -0
  173. package/dist/test_live_deployed_mcp_search.js.map +1 -0
  174. package/dist/test_live_deployed_split.d.ts +2 -0
  175. package/dist/test_live_deployed_split.d.ts.map +1 -0
  176. package/dist/test_live_deployed_split.js +72 -0
  177. package/dist/test_live_deployed_split.js.map +1 -0
  178. package/dist/test_live_endpoint_runner.js +2 -2
  179. package/dist/test_live_endpoint_runner.js.map +1 -1
  180. package/dist/test_live_mcp.js +1 -1
  181. package/dist/test_live_mcp.js.map +1 -1
  182. package/dist/test_live_neil_widget.d.ts +2 -0
  183. package/dist/test_live_neil_widget.d.ts.map +1 -0
  184. package/dist/test_live_neil_widget.js +84 -0
  185. package/dist/test_live_neil_widget.js.map +1 -0
  186. package/dist/test_longpoll_status.d.ts +2 -0
  187. package/dist/test_longpoll_status.d.ts.map +1 -0
  188. package/dist/test_longpoll_status.js +117 -0
  189. package/dist/test_longpoll_status.js.map +1 -0
  190. package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts +2 -0
  191. package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts.map +1 -0
  192. package/dist/test_mcp_find_expert_and_vocabulary_routing.js +130 -0
  193. package/dist/test_mcp_find_expert_and_vocabulary_routing.js.map +1 -0
  194. package/dist/test_next_moves.js +644 -279
  195. package/dist/test_next_moves.js.map +1 -1
  196. package/dist/test_next_moves_transcripts.js +122 -40
  197. package/dist/test_next_moves_transcripts.js.map +1 -1
  198. package/dist/test_on_request_caller_identity.d.ts +13 -0
  199. package/dist/test_on_request_caller_identity.d.ts.map +1 -0
  200. package/dist/test_on_request_caller_identity.js +131 -0
  201. package/dist/test_on_request_caller_identity.js.map +1 -0
  202. package/dist/test_on_request_intercept.d.ts +10 -0
  203. package/dist/test_on_request_intercept.d.ts.map +1 -0
  204. package/dist/test_on_request_intercept.js +95 -0
  205. package/dist/test_on_request_intercept.js.map +1 -0
  206. package/dist/test_onboarding_consent_and_errors.d.ts +2 -0
  207. package/dist/test_onboarding_consent_and_errors.d.ts.map +1 -0
  208. package/dist/test_onboarding_consent_and_errors.js +110 -0
  209. package/dist/test_onboarding_consent_and_errors.js.map +1 -0
  210. package/dist/test_onboarding_live_scenarios.d.ts +2 -0
  211. package/dist/test_onboarding_live_scenarios.d.ts.map +1 -0
  212. package/dist/test_onboarding_live_scenarios.js +189 -0
  213. package/dist/test_onboarding_live_scenarios.js.map +1 -0
  214. package/dist/test_referral_live.d.ts +2 -0
  215. package/dist/test_referral_live.d.ts.map +1 -0
  216. package/dist/test_referral_live.js +33 -0
  217. package/dist/test_referral_live.js.map +1 -0
  218. package/dist/test_referral_piers.d.ts +2 -0
  219. package/dist/test_referral_piers.d.ts.map +1 -0
  220. package/dist/test_referral_piers.js +33 -0
  221. package/dist/test_referral_piers.js.map +1 -0
  222. package/dist/test_report_editorial_briefing.d.ts +21 -0
  223. package/dist/test_report_editorial_briefing.d.ts.map +1 -0
  224. package/dist/test_report_editorial_briefing.js +356 -0
  225. package/dist/test_report_editorial_briefing.js.map +1 -0
  226. package/dist/test_search_graph_quality.d.ts +2 -0
  227. package/dist/test_search_graph_quality.d.ts.map +1 -0
  228. package/dist/test_search_graph_quality.js +493 -0
  229. package/dist/test_search_graph_quality.js.map +1 -0
  230. package/dist/test_service_to_service_auth.d.ts +2 -0
  231. package/dist/test_service_to_service_auth.d.ts.map +1 -0
  232. package/dist/test_service_to_service_auth.js +199 -0
  233. package/dist/test_service_to_service_auth.js.map +1 -0
  234. package/dist/test_sources_live.d.ts +2 -0
  235. package/dist/test_sources_live.d.ts.map +1 -0
  236. package/dist/test_sources_live.js +30 -0
  237. package/dist/test_sources_live.js.map +1 -0
  238. package/dist/test_specialist_and_analyst_tiers.d.ts +2 -0
  239. package/dist/test_specialist_and_analyst_tiers.d.ts.map +1 -0
  240. package/dist/test_specialist_and_analyst_tiers.js +155 -0
  241. package/dist/test_specialist_and_analyst_tiers.js.map +1 -0
  242. package/dist/test_v2_2_visual_hardening.d.ts +5 -0
  243. package/dist/test_v2_2_visual_hardening.d.ts.map +1 -0
  244. package/dist/test_v2_2_visual_hardening.js +333 -0
  245. package/dist/test_v2_2_visual_hardening.js.map +1 -0
  246. package/dist/test_verify_deprecate_render_spec.d.ts +2 -0
  247. package/dist/test_verify_deprecate_render_spec.d.ts.map +1 -0
  248. package/dist/test_verify_deprecate_render_spec.js +217 -0
  249. package/dist/test_verify_deprecate_render_spec.js.map +1 -0
  250. package/dist/test_verify_neil_demo.d.ts +2 -0
  251. package/dist/test_verify_neil_demo.d.ts.map +1 -0
  252. package/dist/test_verify_neil_demo.js +149 -0
  253. package/dist/test_verify_neil_demo.js.map +1 -0
  254. package/dist/test_waitable_research_and_grounded_links.d.ts +2 -0
  255. package/dist/test_waitable_research_and_grounded_links.d.ts.map +1 -0
  256. package/dist/test_waitable_research_and_grounded_links.js +129 -0
  257. package/dist/test_waitable_research_and_grounded_links.js.map +1 -0
  258. package/dist/test_widget_guards.d.ts +2 -0
  259. package/dist/test_widget_guards.d.ts.map +1 -0
  260. package/dist/test_widget_guards.js +229 -0
  261. package/dist/test_widget_guards.js.map +1 -0
  262. package/dist/test_zero_retention_alerts.d.ts +14 -0
  263. package/dist/test_zero_retention_alerts.d.ts.map +1 -0
  264. package/dist/test_zero_retention_alerts.js +76 -0
  265. package/dist/test_zero_retention_alerts.js.map +1 -0
  266. package/dist/toolHandlers.d.ts +38 -1
  267. package/dist/toolHandlers.d.ts.map +1 -1
  268. package/dist/toolHandlers.js +3856 -938
  269. package/dist/toolHandlers.js.map +1 -1
  270. package/dist/tools.d.ts +20 -0
  271. package/dist/tools.d.ts.map +1 -1
  272. package/dist/tools.js +25 -4
  273. package/dist/tools.js.map +1 -1
  274. package/dist/verify_discoverability.d.ts +2 -0
  275. package/dist/verify_discoverability.d.ts.map +1 -0
  276. package/dist/verify_discoverability.js +53 -0
  277. package/dist/verify_discoverability.js.map +1 -0
  278. package/dist/verify_tools_endpoint.js +16 -3
  279. package/dist/verify_tools_endpoint.js.map +1 -1
  280. package/dist/widgetShell.d.ts +2 -2
  281. package/dist/widgetShell.d.ts.map +1 -1
  282. package/dist/widgetShell.js +1 -1
  283. package/dist/widgetShell.js.map +1 -1
  284. package/package.json +1 -1
  285. package/server.json +4 -32
  286. package/dist/oauthRegisterShim.d.ts +0 -13
  287. package/dist/oauthRegisterShim.d.ts.map +0 -1
  288. package/dist/oauthRegisterShim.js +0 -83
  289. package/dist/oauthRegisterShim.js.map +0 -1
@@ -0,0 +1,149 @@
1
+ import dotenv from 'dotenv';
2
+ dotenv.config();
3
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
5
+ import axios from 'axios';
6
+ const DEPLOYED_MCP_URL = process.env.TEST_URL || 'https://mcp.fodda.ai/mcp';
7
+ const FODDA_API_KEY = process.env.FODDA_INTERNAL_API_KEY || process.env.FODDA_API_KEY || 'sk_live_abcdef';
8
+ function extractJson(text) {
9
+ try {
10
+ return JSON.parse(text);
11
+ }
12
+ catch {
13
+ const rawMatch = text.match(/── RAW DATA[^\n]*\n([\s\S]*?)(?=\n──|$)/);
14
+ if (rawMatch && rawMatch[1]) {
15
+ try {
16
+ return JSON.parse(rawMatch[1]);
17
+ }
18
+ catch { }
19
+ }
20
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
21
+ if (jsonMatch) {
22
+ try {
23
+ return JSON.parse(jsonMatch[0]);
24
+ }
25
+ catch { }
26
+ }
27
+ return null;
28
+ }
29
+ }
30
+ async function runProbe() {
31
+ console.log(`=== Verification Probes against Deployed MCP Server (${DEPLOYED_MCP_URL}) ===\n`);
32
+ // Check health endpoint for version
33
+ const healthResp = await axios.get('https://mcp.fodda.ai/health');
34
+ console.log(`Health check: status=${healthResp.data.status}, version=${healthResp.data.version}\n`);
35
+ // Setup client with Bearer Authorization header
36
+ const transport = new StreamableHTTPClientTransport(new URL(DEPLOYED_MCP_URL), {
37
+ requestInit: {
38
+ headers: {
39
+ 'Authorization': `Bearer ${FODDA_API_KEY}`,
40
+ 'X-API-Key': FODDA_API_KEY,
41
+ 'X-Fodda-Session-Kind': 'internal-test'
42
+ }
43
+ }
44
+ });
45
+ const client = new Client({ name: 'neil-demo-verifier', version: '1.0.0' });
46
+ await client.connect(transport);
47
+ console.log('Connected to MCP server!\n');
48
+ // ── PROBE 1: Neil Carty Demo Query ──
49
+ console.log('--- PROBE 1: Neil Carty Collectibles Query ---');
50
+ const neilQuery = 'what are the trends in the collectible space, particularly trading cards, like baseball trading cards';
51
+ const res1 = await client.callTool({
52
+ name: 'search_graph',
53
+ arguments: { query: neilQuery, limit: 10 }
54
+ });
55
+ const parsed1 = extractJson(res1.content[0].text);
56
+ console.log('Results returned:', parsed1?.rows?.length || 0);
57
+ console.log('Top 3 rows:');
58
+ (parsed1?.rows || []).slice(0, 3).forEach((r, idx) => {
59
+ console.log(` #${idx + 1}: ${r.title || r.trendName || r.name} (signal: ${r.signal_score}, rel: ${r.relevance_score})`);
60
+ });
61
+ console.log('Coverage status:', parsed1?.coverage?.status);
62
+ console.log('Next moves:', JSON.stringify(parsed1?.next_moves, null, 2));
63
+ const textContent1 = res1.content.map((c) => c.text).join('\n');
64
+ const widgetMatch = textContent1.match(/── SEARCH WIDGET[\s\S]*?(?=\n\n──|$)/);
65
+ if (widgetMatch) {
66
+ console.log('\nWidget excerpt:');
67
+ console.log(widgetMatch[0].slice(0, 800));
68
+ }
69
+ const closingMatch1 = textContent1.match(/── NEXT MOVES CLOSING BLOCK[\s\S]*?(?=\n\n──|$)/);
70
+ if (closingMatch1) {
71
+ console.log('\nClosing Block:');
72
+ console.log(closingMatch1[0]);
73
+ }
74
+ // ── PROBE 2: "what does this cost?" follow-up ──
75
+ console.log('\n--- PROBE 2: "what does this cost?" follow-up (get_capabilities) ---');
76
+ const res2 = await client.callTool({
77
+ name: 'get_capabilities',
78
+ arguments: {}
79
+ });
80
+ const parsed2 = extractJson(res2.content[0].text);
81
+ console.log('get_capabilities pricing_url:', parsed2?.pricing_url);
82
+ // ── PROBE 3: "can I book Jeremy Bergstein?" ──
83
+ console.log('\n--- PROBE 3: "can I book Jeremy Bergstein?" (list_analysts) ---');
84
+ const res3 = await client.callTool({
85
+ name: 'list_analysts',
86
+ arguments: {}
87
+ });
88
+ const parsed3 = extractJson(res3.content[0].text);
89
+ const analysts = parsed3?.analysts || parsed3;
90
+ const jeremy = Array.isArray(analysts) ? analysts.find((a) => (a.name || '').toLowerCase().includes('jeremy')) : null;
91
+ console.log('Jeremy Bergstein book_a_call:', JSON.stringify(jeremy?.book_a_call, null, 2));
92
+ // ── PROBE 4: Patrick\'s Query (creative effectiveness, dentsu graph) ──
93
+ console.log('\n--- PROBE 4: Patrick\'s Query (creative effectiveness) ---');
94
+ const res4 = await client.callTool({
95
+ name: 'search_graph',
96
+ arguments: { query: 'creative effectiveness', graphs: ['dentsu-creative-marketing'], limit: 10 }
97
+ });
98
+ const parsed4 = extractJson(res4.content[0].text);
99
+ console.log('Patrick coverage status:', parsed4?.coverage?.status);
100
+ console.log('Patrick next moves:', JSON.stringify(parsed4?.next_moves, null, 2));
101
+ const textContent4 = res4.content.map((c) => c.text).join('\n');
102
+ const closingMatch4 = textContent4.match(/── NEXT MOVES CLOSING BLOCK[\s\S]*?(?=\n\n──|$)/);
103
+ if (closingMatch4) {
104
+ console.log('\nPatrick Closing Block:');
105
+ console.log(closingMatch4[0]);
106
+ }
107
+ // ── PROBE 5: 1.46.29 Regression Probes ──
108
+ console.log('\n--- PROBE 5A: Lululemon brand_tracker ---');
109
+ const res5a = await client.callTool({
110
+ name: 'brand_tracker',
111
+ arguments: { brand_name: 'Lululemon' }
112
+ });
113
+ const parsed5a = extractJson(res5a.content[0]?.text || '');
114
+ console.log('Lululemon next_moves:', JSON.stringify(parsed5a?.next_moves, null, 2));
115
+ const textContent5a = res5a.content.map((c) => c.text).join('\n');
116
+ const closingMatch5a = textContent5a.match(/── NEXT MOVES CLOSING BLOCK[\s\S]*?(?=\n\n──|$)/);
117
+ if (closingMatch5a) {
118
+ console.log('\nLululemon Closing Block:');
119
+ console.log(closingMatch5a[0]);
120
+ }
121
+ console.log('\n--- PROBE 5B: James Colistra consult ---');
122
+ const res5b_consult = await client.callTool({
123
+ name: 'consult_human_agent',
124
+ arguments: { analyst_id: 'james-colistra-earned-media-and-podcast', query: 'earned media strategy for luxury brands' }
125
+ });
126
+ const textContent5b_consult = res5b_consult.content.map((c) => c.text).join('\n');
127
+ const consultClosing = textContent5b_consult.match(/── NEXT MOVES CLOSING BLOCK[\s\S]*?(?=\n\n──|$)/);
128
+ if (consultClosing) {
129
+ console.log('\nJames Colistra Closing Block:');
130
+ console.log(consultClosing[0]);
131
+ }
132
+ console.log('\n--- PROBE 5C: Gen Z beverage search ---');
133
+ const res5c = await client.callTool({
134
+ name: 'search_graph',
135
+ arguments: { query: 'Gen Z functional beverage and soda alternatives', limit: 10 }
136
+ });
137
+ const parsed5c = extractJson(res5c.content[0].text);
138
+ console.log('Gen Z beverage next_moves:', JSON.stringify(parsed5c?.next_moves, null, 2));
139
+ const textContent5c = res5c.content.map((c) => c.text).join('\n');
140
+ const closingMatch5c = textContent5c.match(/── NEXT MOVES CLOSING BLOCK[\s\S]*?(?=\n\n──|$)/);
141
+ if (closingMatch5c) {
142
+ console.log('\nGen Z Beverage Closing Block:');
143
+ console.log(closingMatch5c[0]);
144
+ }
145
+ await client.close();
146
+ console.log('\n=== All Probes Complete ===');
147
+ }
148
+ runProbe().catch(console.error);
149
+ //# sourceMappingURL=test_verify_neil_demo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_verify_neil_demo.js","sourceRoot":"","sources":["../src/test_verify_neil_demo.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test_waitable_research_and_grounded_links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_waitable_research_and_grounded_links.d.ts","sourceRoot":"","sources":["../src/test_waitable_research_and_grounded_links.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ import assert from 'assert';
2
+ import { createServer } from './toolHandlers.js';
3
+ async function runTests() {
4
+ console.log('================================================================');
5
+ console.log(' Running Unit Tests: Waitable Deep Research & Grounded Source Links');
6
+ console.log('================================================================\n');
7
+ let lastRequestedPath = '';
8
+ let lastRequestBody = null;
9
+ let simulate409OnResearch = false;
10
+ let simulateRunningResearchOnThemes = false;
11
+ let simulateFindingsOnThemes = false;
12
+ const mockFoddaRequest = async (method, path, apiKey, userId, body) => {
13
+ lastRequestedPath = path;
14
+ lastRequestBody = body;
15
+ if (path === '/api/deep-research') {
16
+ if (simulate409OnResearch) {
17
+ const err = new Error('Basic info required');
18
+ err.response = {
19
+ status: 409,
20
+ data: { message: 'Basic profile information must be completed before deep research.' }
21
+ };
22
+ throw err;
23
+ }
24
+ return { success: true, message: 'Deep research started' };
25
+ }
26
+ if (path.startsWith('/api/onboarding-status')) {
27
+ return {
28
+ status: 'in_progress',
29
+ step: 'research',
30
+ research: {
31
+ state: path.includes('wait=research') ? 'completed' : 'running',
32
+ findings_count: 5
33
+ }
34
+ };
35
+ }
36
+ if (path === '/api/onboarding-themes') {
37
+ return {
38
+ research_state: simulateRunningResearchOnThemes ? 'running' : 'completed',
39
+ research_findings: simulateFindingsOnThemes ? [
40
+ {
41
+ id: 'find-1',
42
+ claim: 'Pioneered decentralized AI retail networks',
43
+ title: 'Retail Tech Review',
44
+ url: 'https://example.com/retail-ai'
45
+ },
46
+ {
47
+ id: 'find-2',
48
+ claim: 'Published 2026 Brand Strategy Framework',
49
+ sources: [
50
+ { title: 'Substack SIC', url: 'https://sic.substack.com' },
51
+ { title: 'Brandweek', url: 'https://brandweek.com/article' }
52
+ ]
53
+ }
54
+ ] : [],
55
+ themes: [
56
+ { name: 'Decentralized Retail Strategy', description: 'Next-gen autonomous retail agents' },
57
+ { name: 'Brand Gravity & Pricing Power', description: 'Resistance to algorithmic discounting' }
58
+ ]
59
+ };
60
+ }
61
+ if (path === '/api/generate-questions') {
62
+ return {
63
+ success: true,
64
+ questions: ['How do you protect margin against algorithmic price wars?']
65
+ };
66
+ }
67
+ return {};
68
+ };
69
+ const server = await createServer('test_key', 'test_user@example.com', mockFoddaRequest, async () => ({}), () => '', () => '');
70
+ const tools = server._registeredTools;
71
+ // ── Test 1: expert_onboarding_research result text & 409 mapping ──
72
+ console.log('Test 1: expert_onboarding_research returns waitable guidance text...');
73
+ simulate409OnResearch = false;
74
+ const res1 = await tools['expert_onboarding_research'].handler({});
75
+ assert.strictEqual(res1.isError, undefined);
76
+ assert.ok(res1.content[0].text.includes('get_onboarding_status'), 'Must mention get_onboarding_status');
77
+ assert.ok(res1.content[0].text.includes('waitForResearch: true'), 'Must mention waitForResearch: true');
78
+ assert.ok(res1.content[0].text.includes('25 seconds'), 'Must mention 25 seconds');
79
+ console.log('✅ Test 1A Passed: Guidance text contains waitable polling instruction.');
80
+ console.log('Test 1B: expert_onboarding_research maps 409 to research_needs_basic_info...');
81
+ simulate409OnResearch = true;
82
+ const res1B = await tools['expert_onboarding_research'].handler({});
83
+ assert.strictEqual(res1B.isError, true);
84
+ assert.ok(res1B.content[0].text.includes('research_needs_basic_info'), 'Must return research_needs_basic_info code');
85
+ assert.ok(res1B.content[0].text.includes('Basic profile information must be completed'), 'Must include upstream 409 message');
86
+ console.log('✅ Test 1B Passed: 409 correctly mapped to research_needs_basic_info.\n');
87
+ // ── Test 2: get_onboarding_status with waitForResearch ──
88
+ console.log('Test 2: get_onboarding_status appends ?wait=research when waitForResearch: true...');
89
+ await tools['get_onboarding_status'].handler({ waitForResearch: true });
90
+ assert.ok(lastRequestedPath.includes('wait=research'), `Path must include wait=research (got ${lastRequestedPath})`);
91
+ await tools['get_onboarding_status'].handler({ analystId: 'jane-doe', waitForResearch: true });
92
+ assert.ok(lastRequestedPath.includes('wait=research') && lastRequestedPath.includes('analystId=jane-doe'), `Path must include both params (got ${lastRequestedPath})`);
93
+ await tools['get_onboarding_status'].handler({ waitForResearch: false });
94
+ assert.ok(!lastRequestedPath.includes('wait=research'), 'Path must not include wait=research when false');
95
+ console.log('✅ Test 2 Passed: get_onboarding_status handles waitForResearch param.\n');
96
+ // ── Test 3: get_detected_themes shows research_state warning & findings before themes ──
97
+ console.log('Test 3: get_detected_themes renders findings before themes and running warning...');
98
+ simulateRunningResearchOnThemes = true;
99
+ simulateFindingsOnThemes = true;
100
+ const res3 = await tools['get_detected_themes'].handler({});
101
+ const prose3 = res3.content[0].text;
102
+ assert.ok(prose3.includes('Research is still running, so these themes may sharpen'), 'Must include running research warning');
103
+ assert.ok(prose3.includes('**What Fodda found about your work:**'), 'Must include findings header');
104
+ assert.ok(prose3.includes('Pioneered decentralized AI retail networks ([Retail Tech Review](https://example.com/retail-ai))'), 'Must format claim with link');
105
+ assert.ok(prose3.includes('[Substack SIC](https://sic.substack.com), [Brandweek](https://brandweek.com/article)'), 'Must format multi-source links');
106
+ assert.ok(prose3.includes("Anything here that's wrong or not yours? I'll leave it out."), 'Must include exclusion prompt');
107
+ assert.ok(prose3.indexOf('What Fodda found about your work') < prose3.indexOf('Detected Themes for Confirmation'), 'Findings must appear BEFORE themes');
108
+ console.log('✅ Test 3 Passed: get_detected_themes renders grounded findings before themes.\n');
109
+ // ── Test 4: confirm_themes passes flaggedFindingIds & flagNote ──
110
+ console.log('Test 4: confirm_themes passes flaggedFindingIds and flagNote to /api/generate-questions...');
111
+ await tools['confirm_themes'].handler({
112
+ themes: ['Decentralized Retail Strategy'],
113
+ flaggedFindingIds: ['find-1'],
114
+ flagNote: 'The AI retail network was a partner project, not my primary venture.'
115
+ });
116
+ assert.deepStrictEqual(lastRequestBody.confirmedThemes, ['Decentralized Retail Strategy']);
117
+ assert.deepStrictEqual(lastRequestBody.flaggedFindingIds, ['find-1']);
118
+ assert.strictEqual(lastRequestBody.flagNote, 'The AI retail network was a partner project, not my primary venture.');
119
+ console.log('✅ Test 4 Passed: confirm_themes forwards flagged findings and note.\n');
120
+ console.log('================================================================');
121
+ console.log(' All Waitable Deep Research & Grounded Source Links Tests Passed!');
122
+ console.log('================================================================\n');
123
+ process.exit(0);
124
+ }
125
+ runTests().catch((err) => {
126
+ console.error('Test Suite Failed:', err);
127
+ process.exit(1);
128
+ });
129
+ //# sourceMappingURL=test_waitable_research_and_grounded_links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_waitable_research_and_grounded_links.js","sourceRoot":"","sources":["../src/test_waitable_research_and_grounded_links.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test_widget_guards.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_widget_guards.d.ts","sourceRoot":"","sources":["../src/test_widget_guards.ts"],"names":[],"mappings":""}
@@ -0,0 +1,229 @@
1
+ import assert from 'node:assert';
2
+ import { isRowBrandEligible, buildPublisherExclusionSet, extractCleanRowBrands, rowHasDirectTokenMatch, specificQueryTokens, rowMatchesQueryTokens, rowScore, TIER_NOMINAL_SCORE, resolveRowTier } from './coverageRelevance.js';
3
+ import { renderSearchWidget } from './searchTemplate.js';
4
+ import { setCachedCatalogForTesting } from './catalogCache.js';
5
+ console.log('--- Running Widget Guards & Niche Ranking Unit Tests ---');
6
+ // Mock graphs
7
+ const mockGraphs = [
8
+ {
9
+ graph_id: 'retail',
10
+ name: 'Retail Strategy & Innovation',
11
+ graph_type: 'domain',
12
+ status: 'live',
13
+ curator: 'PSFK',
14
+ company: 'PSFK',
15
+ topics: ['retail', 'commerce', 'loyalty'],
16
+ trend_count: 150,
17
+ evidence_count: 600,
18
+ },
19
+ {
20
+ graph_id: 'culture',
21
+ name: 'Cultural Strategy',
22
+ graph_type: 'expert',
23
+ status: 'live',
24
+ curator: 'Ben Dietz',
25
+ company: '[SIC] Weekly',
26
+ topics: ['culture', 'marketing'],
27
+ trend_count: 80,
28
+ evidence_count: 300,
29
+ }
30
+ ];
31
+ setCachedCatalogForTesting({ version: '1.0', generated_at: new Date().toISOString(), graph_count: mockGraphs.length, graphs: mockGraphs }, []);
32
+ // ── Test 1: Brand Guard Helper (Shared Logic) ──
33
+ console.log('\n[Test 1] Brand Guard Helper (Mega-trend suppression & publisher filtering)');
34
+ {
35
+ // Mega-trend with brand_count > 30
36
+ const megaTrendRow = {
37
+ trendName: 'Experiential Loyalty',
38
+ brand_count: 734,
39
+ brandNames: ['PlayStation', 'Hermès', 'Louis Vuitton', 'Coach', 'Nike'],
40
+ };
41
+ assert.strictEqual(isRowBrandEligible(megaTrendRow), false, 'Row with brand_count > 30 should not be brand-eligible');
42
+ assert.deepStrictEqual(extractCleanRowBrands(megaTrendRow), [], 'Extracting brands from mega-trend should return empty array');
43
+ // Mega-trend with brandCount > 30
44
+ const megaTrendRowCamel = {
45
+ trendName: 'Experiential Loyalty',
46
+ brandCount: 50,
47
+ brandNames: ['PlayStation', 'Hermès'],
48
+ };
49
+ assert.strictEqual(isRowBrandEligible(megaTrendRowCamel), false, 'Row with brandCount > 30 should not be brand-eligible');
50
+ // Mega-trend with brandNames.length >= 10 when brand_count absent
51
+ const rosterRow = {
52
+ trendName: 'Broad Retail Trend',
53
+ brandNames: ['B1', 'B2', 'B3', 'B4', 'B5', 'B6', 'B7', 'B8', 'B9', 'B10'],
54
+ };
55
+ assert.strictEqual(isRowBrandEligible(rosterRow), false, 'Row with 10+ brandNames without brand_count should not be brand-eligible');
56
+ // Eligible niche row
57
+ const nicheRow = {
58
+ trendName: 'Collector Booster Packs',
59
+ brand_count: 3,
60
+ brandNames: ['Topps', 'Fanatics', 'Pokemon', 'PSFK'],
61
+ };
62
+ assert.strictEqual(isRowBrandEligible(nicheRow), true, 'Row with brand_count <= 30 should be brand-eligible');
63
+ const publisherTokens = buildPublisherExclusionSet(['retail'], mockGraphs, [nicheRow]);
64
+ const cleanBrands = extractCleanRowBrands(nicheRow, publisherTokens, 4);
65
+ assert.deepStrictEqual(cleanBrands, ['Topps', 'Fanatics', 'Pokemon'], 'Should extract clean brands and filter out publisher token PSFK');
66
+ console.log('✅ Test 1 Passed: Brand guard correctly suppresses mega-trend rosters and filters publisher tokens.');
67
+ }
68
+ // ── Test 2: Stat Card Zero-Value Clean Omission & Sources Reconciliation ──
69
+ console.log('\n[Test 2] Stat Card Emission Guard & Sources Reconciliation');
70
+ (async () => {
71
+ const testRows = [
72
+ { trendName: 'Signal A', signal_score: 80, graphName: 'Retail Strategy & Innovation', brand_count: 50, brandNames: ['PlayStation'] },
73
+ { trendName: 'Signal B', signal_score: 75, graphName: 'Retail Strategy & Innovation', brand_count: 60, brandNames: ['Hermès'] },
74
+ { trendName: 'Signal C', signal_score: 70, graphName: 'Retail Strategy & Innovation', brand_count: 70, brandNames: ['Gucci'] },
75
+ ];
76
+ // Case A: Zero-value Census data ("Gasoline Stations $0.0B")
77
+ const zeroCensus = {
78
+ snapshot: {
79
+ total_retail: { value: 0, mom_change: 0 },
80
+ subcategories: [
81
+ { name: 'Gasoline Stations', value: 0, mom_change: 0 }
82
+ ]
83
+ }
84
+ };
85
+ const resA = await renderSearchWidget({ rows: testRows, _routed_graphs: ['retail'] }, 'trading cards', 'Retail Strategy & Innovation', { census_retail: zeroCensus });
86
+ // Assert Market section is completely omitted
87
+ assert.ok(!resA.widget_html.includes('Gasoline Stations'), 'Widget HTML should not render zero-value Gasoline Stations card');
88
+ assert.ok(!resA.widget_html.includes('<div class="sec">Market</div>'), 'Market section should be clean-omitted when all values are 0');
89
+ assert.ok(!resA.widget_html.includes('Census Bureau'), 'Sources footer should NOT include Census Bureau when Market section is omitted');
90
+ // Assert Companies section is completely omitted because all rows failed the brand guard
91
+ assert.ok(!resA.widget_html.includes('<div class="sec">Companies</div>'), 'Companies section should be clean-omitted when no brands pass guard');
92
+ assert.ok(!resA.widget_html.includes('PlayStation'), 'No PlayStation brand chip should appear in widget cards or companies section');
93
+ // Case B: Valid non-zero Census data
94
+ const validCensus = {
95
+ snapshot: {
96
+ total_retail: { value: 700000000000, mom_change: 1.2 },
97
+ subcategories: [
98
+ { name: 'Hobby & Collectibles', value: 15000000000, mom_change: 3.4 }
99
+ ]
100
+ }
101
+ };
102
+ const resB = await renderSearchWidget({ rows: testRows, _routed_graphs: ['retail'] }, 'trading cards', 'Retail Strategy & Innovation', { census_retail: validCensus });
103
+ assert.ok(resB.widget_html.includes('US retail sales — Census Bureau'), 'Valid Census data should render Census card');
104
+ assert.ok(resB.widget_html.includes('$700.0B'), 'Valid Census total should render $700.0B');
105
+ assert.ok(resB.widget_html.includes('Census Bureau'), 'Sources footer SHOULD include Census Bureau when rendered');
106
+ console.log('✅ Test 2 Passed: Stat cards and Market section cleanly omit zero values and sources footer aligns.');
107
+ })();
108
+ // ── Test 3: Niche-Query Direct Token Match Reranking Tier ──
109
+ console.log('\n[Test 3] Niche-Query Direct Token Match Reranking Tier');
110
+ {
111
+ const query = 'collectible trading cards booster mechanics';
112
+ const tokens = specificQueryTokens(query);
113
+ const genericMegaTrend1 = {
114
+ trendName: 'Experiential Loyalty',
115
+ trendSlug: 'experiential-loyalty',
116
+ sectorNames: 'Retail|Customer Loyalty',
117
+ relevance_score: 1.364,
118
+ signal_score: 95,
119
+ brand_count: 734,
120
+ };
121
+ const genericMegaTrend2 = {
122
+ trendName: 'Retail as a Destination',
123
+ trendSlug: 'retail-as-destination',
124
+ sectorNames: 'Retail|Physical Stores',
125
+ relevance_score: 1.200,
126
+ signal_score: 90,
127
+ brand_count: 400,
128
+ };
129
+ const nicheTrend = {
130
+ trendName: 'Mass-Market Brands Ship Premium Collector Editions with Booster/Variation Mechanics',
131
+ trendSlug: 'mass-market-brands-collector-editions-booster-mechanics',
132
+ sectorNames: 'Collectibles|Toys & Hobby',
133
+ relevance_score: 0.644,
134
+ signal_score: 75,
135
+ brand_count: 2,
136
+ brandNames: ['Topps', 'Fanatics'],
137
+ };
138
+ assert.strictEqual(rowHasDirectTokenMatch(nicheTrend, tokens), true, 'Niche trend should direct-match query tokens (collector, booster, collectibles, cards)');
139
+ assert.strictEqual(rowHasDirectTokenMatch(genericMegaTrend1, tokens), false, 'Generic mega-trend 1 should NOT direct-match query tokens');
140
+ assert.strictEqual(rowHasDirectTokenMatch(genericMegaTrend2, tokens), false, 'Generic mega-trend 2 should NOT direct-match query tokens');
141
+ const rows = [genericMegaTrend1, genericMegaTrend2, nicheTrend];
142
+ const isRowDirectMatch = (row) => rowHasDirectTokenMatch(row, tokens);
143
+ const isRowOnTopic = (row) => rowMatchesQueryTokens(row, tokens, mockGraphs) ||
144
+ (rowScore(row) >= 0.75 * (TIER_NOMINAL_SCORE[resolveRowTier(row, mockGraphs, mockGraphs)] ?? 0.8));
145
+ rows.sort((a, b) => {
146
+ const directA = isRowDirectMatch(a) ? 1 : 0;
147
+ const directB = isRowDirectMatch(b) ? 1 : 0;
148
+ if (directA !== directB)
149
+ return directB - directA;
150
+ const onTopicA = isRowOnTopic(a) ? 1 : 0;
151
+ const onTopicB = isRowOnTopic(b) ? 1 : 0;
152
+ if (onTopicA !== onTopicB)
153
+ return onTopicB - onTopicA;
154
+ const relA = a.relevance_score || 0;
155
+ const relB = b.relevance_score || 0;
156
+ if (Math.abs(relB - relA) > 0.05)
157
+ return relB - relA;
158
+ return (b.signal_score || 0) - (a.signal_score || 0);
159
+ });
160
+ assert.strictEqual(rows[0]?.trendName, nicheTrend.trendName, 'Niche trend MUST rank #1 above high-scoring generic mega-trends');
161
+ // Also test Neil's exact verbatim phrasing: "what are the trends in the collectible space, particularly trading cards, like baseball trading cards"
162
+ const neilVerbatimQuery = 'what are the trends in the collectible space, particularly trading cards, like baseball trading cards';
163
+ const neilTokens = specificQueryTokens(neilVerbatimQuery);
164
+ assert.strictEqual(rowHasDirectTokenMatch(nicheTrend, neilTokens), true, 'Neil verbatim query (singular "collectible") must match sector "Collectibles" and "trading cards"');
165
+ assert.strictEqual(rowHasDirectTokenMatch(genericMegaTrend1, neilTokens), false, 'Experiential Loyalty must not match Neil verbatim tokens');
166
+ const neilRows = [genericMegaTrend1, genericMegaTrend2, nicheTrend];
167
+ const isNeilRowDirectMatch = (row) => rowHasDirectTokenMatch(row, neilTokens);
168
+ const isNeilRowOnTopic = (row) => rowMatchesQueryTokens(row, neilTokens, mockGraphs) ||
169
+ (rowScore(row) >= 0.75 * (TIER_NOMINAL_SCORE[resolveRowTier(row, mockGraphs, mockGraphs)] ?? 0.8));
170
+ neilRows.sort((a, b) => {
171
+ const directA = isNeilRowDirectMatch(a) ? 1 : 0;
172
+ const directB = isNeilRowDirectMatch(b) ? 1 : 0;
173
+ if (directA !== directB)
174
+ return directB - directA;
175
+ const onTopicA = isNeilRowOnTopic(a) ? 1 : 0;
176
+ const onTopicB = isNeilRowOnTopic(b) ? 1 : 0;
177
+ if (onTopicA !== onTopicB)
178
+ return onTopicB - onTopicA;
179
+ const relA = a.relevance_score || 0;
180
+ const relB = b.relevance_score || 0;
181
+ if (Math.abs(relB - relA) > 0.05)
182
+ return relB - relA;
183
+ return (b.signal_score || 0) - (a.signal_score || 0);
184
+ });
185
+ assert.strictEqual(neilRows[0]?.trendName, nicheTrend.trendName, 'Neil verbatim query must rank Booster/Variation collectibles trend at #1');
186
+ console.log('✅ Test 3 Passed: Direct token match tier with stemming places niche trend at rank #1 on Neil query.');
187
+ }
188
+ // ── Test 4: Generic Query Regression Check ──
189
+ console.log('\n[Test 4] Generic Query Regression Check (Broad query preserves existing order)');
190
+ {
191
+ const broadQuery = 'retail trends 2026';
192
+ const tokens = specificQueryTokens(broadQuery);
193
+ const trendA = {
194
+ trendName: 'Unified Commerce Orchestration',
195
+ trendSlug: 'unified-commerce-orchestration',
196
+ sectorNames: 'Retail|Technology',
197
+ relevance_score: 1.100,
198
+ signal_score: 85,
199
+ };
200
+ const trendB = {
201
+ trendName: 'Autonomous Checkout Solutions',
202
+ trendSlug: 'autonomous-checkout-solutions',
203
+ sectorNames: 'Retail|In-Store Tech',
204
+ relevance_score: 0.950,
205
+ signal_score: 80,
206
+ };
207
+ const rows = [trendB, trendA];
208
+ const isRowDirectMatch = (row) => rowHasDirectTokenMatch(row, tokens);
209
+ const isRowOnTopic = (row) => rowMatchesQueryTokens(row, tokens, mockGraphs) ||
210
+ (rowScore(row) >= 0.75 * (TIER_NOMINAL_SCORE[resolveRowTier(row, mockGraphs, mockGraphs)] ?? 0.8));
211
+ rows.sort((a, b) => {
212
+ const directA = isRowDirectMatch(a) ? 1 : 0;
213
+ const directB = isRowDirectMatch(b) ? 1 : 0;
214
+ if (directA !== directB)
215
+ return directB - directA;
216
+ const onTopicA = isRowOnTopic(a) ? 1 : 0;
217
+ const onTopicB = isRowOnTopic(b) ? 1 : 0;
218
+ if (onTopicA !== onTopicB)
219
+ return onTopicB - onTopicA;
220
+ const relA = a.relevance_score || 0;
221
+ const relB = b.relevance_score || 0;
222
+ if (Math.abs(relB - relA) > 0.05)
223
+ return relB - relA;
224
+ return (b.signal_score || 0) - (a.signal_score || 0);
225
+ });
226
+ assert.strictEqual(rows[0]?.trendName, trendA.trendName, 'Trend with higher relevance score must stay #1 for generic queries');
227
+ console.log('✅ Test 4 Passed: Broad query ranking behaves identically without regressions.');
228
+ }
229
+ //# sourceMappingURL=test_widget_guards.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_widget_guards.js","sourceRoot":"","sources":["../src/test_widget_guards.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Test suite for Zero Retention Alert Suppression and Query Privacy.
3
+ *
4
+ * Verifies:
5
+ * 1. buildGapAlertText redacts raw query to '[zero-retention contract]' when zeroQueryRetention is true.
6
+ * 2. buildFrustrationAlertText redacts queries to '[zero-retention contract]' when zeroQueryRetention is true.
7
+ * 3. Standard unflagged accounts continue to emit original query strings.
8
+ * 4. createSessionTracker tracks and updates zeroQueryRetention state correctly.
9
+ * 5. get_my_account status mapping logic surfaces queryRetention correctly.
10
+ *
11
+ * Run: node dist/test_zero_retention_alerts.js
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=test_zero_retention_alerts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_zero_retention_alerts.d.ts","sourceRoot":"","sources":["../src/test_zero_retention_alerts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}