fodda-mcp 1.38.0 → 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 (346) hide show
  1. package/README.md +14 -91
  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 +278 -83
  8. package/dist/brandTemplate.js.map +1 -1
  9. package/dist/catalogCache.d.ts +39 -0
  10. package/dist/catalogCache.d.ts.map +1 -1
  11. package/dist/catalogCache.js +293 -22
  12. package/dist/catalogCache.js.map +1 -1
  13. package/dist/coverageRelevance.d.ts +251 -0
  14. package/dist/coverageRelevance.d.ts.map +1 -0
  15. package/dist/coverageRelevance.js +1857 -0
  16. package/dist/coverageRelevance.js.map +1 -0
  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 +442 -29
  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 +411 -106
  32. package/dist/index.js.map +1 -1
  33. package/dist/pricingCache.d.ts.map +1 -1
  34. package/dist/pricingCache.js +55 -3
  35. package/dist/pricingCache.js.map +1 -1
  36. package/dist/queryCache.d.ts.map +1 -1
  37. package/dist/queryCache.js +2 -0
  38. package/dist/queryCache.js.map +1 -1
  39. package/dist/reportBriefing.d.ts +89 -0
  40. package/dist/reportBriefing.d.ts.map +1 -0
  41. package/dist/reportBriefing.js +662 -0
  42. package/dist/reportBriefing.js.map +1 -0
  43. package/dist/searchTemplate.d.ts.map +1 -1
  44. package/dist/searchTemplate.js +65 -53
  45. package/dist/searchTemplate.js.map +1 -1
  46. package/dist/services/graphRouter.d.ts +7 -0
  47. package/dist/services/graphRouter.d.ts.map +1 -0
  48. package/dist/services/graphRouter.js +7 -0
  49. package/dist/services/graphRouter.js.map +1 -0
  50. package/dist/services/notifications.d.ts +2 -2
  51. package/dist/services/notifications.js +3 -3
  52. package/dist/services/notifications.js.map +1 -1
  53. package/dist/sessionTracker.d.ts +42 -3
  54. package/dist/sessionTracker.d.ts.map +1 -1
  55. package/dist/sessionTracker.js +261 -14
  56. package/dist/sessionTracker.js.map +1 -1
  57. package/dist/skillClient.d.ts.map +1 -1
  58. package/dist/skillClient.js +11 -6
  59. package/dist/skillClient.js.map +1 -1
  60. package/dist/svgVisuals.d.ts +17 -19
  61. package/dist/svgVisuals.d.ts.map +1 -1
  62. package/dist/svgVisuals.js +189 -233
  63. package/dist/svgVisuals.js.map +1 -1
  64. package/dist/systemPrompt.d.ts +7 -2
  65. package/dist/systemPrompt.d.ts.map +1 -1
  66. package/dist/systemPrompt.js +153 -81
  67. package/dist/systemPrompt.js.map +1 -1
  68. package/dist/telemetry.d.ts.map +1 -1
  69. package/dist/telemetry.js +15 -0
  70. package/dist/telemetry.js.map +1 -1
  71. package/dist/test_adjacent_trends_polymorphic.d.ts +2 -0
  72. package/dist/test_adjacent_trends_polymorphic.d.ts.map +1 -0
  73. package/dist/test_adjacent_trends_polymorphic.js +154 -0
  74. package/dist/test_adjacent_trends_polymorphic.js.map +1 -0
  75. package/dist/test_book_a_call_live.d.ts +2 -0
  76. package/dist/test_book_a_call_live.d.ts.map +1 -0
  77. package/dist/test_book_a_call_live.js +161 -0
  78. package/dist/test_book_a_call_live.js.map +1 -0
  79. package/dist/test_brand_intelligence_endpoint.js +2 -2
  80. package/dist/test_byo_mcp_submission_clarity.d.ts +2 -0
  81. package/dist/test_byo_mcp_submission_clarity.d.ts.map +1 -0
  82. package/dist/test_byo_mcp_submission_clarity.js +142 -0
  83. package/dist/test_byo_mcp_submission_clarity.js.map +1 -0
  84. package/dist/test_capabilities_guidance.d.ts +2 -0
  85. package/dist/test_capabilities_guidance.d.ts.map +1 -0
  86. package/dist/test_capabilities_guidance.js +372 -0
  87. package/dist/test_capabilities_guidance.js.map +1 -0
  88. package/dist/test_client_provenance.d.ts +2 -0
  89. package/dist/test_client_provenance.d.ts.map +1 -0
  90. package/dist/test_client_provenance.js +77 -0
  91. package/dist/test_client_provenance.js.map +1 -0
  92. package/dist/test_connection_surface_cleanup.d.ts +2 -0
  93. package/dist/test_connection_surface_cleanup.d.ts.map +1 -0
  94. package/dist/test_connection_surface_cleanup.js +203 -0
  95. package/dist/test_connection_surface_cleanup.js.map +1 -0
  96. package/dist/test_consult_routing.d.ts +2 -0
  97. package/dist/test_consult_routing.d.ts.map +1 -0
  98. package/dist/test_consult_routing.js +86 -0
  99. package/dist/test_consult_routing.js.map +1 -0
  100. package/dist/test_consult_split.d.ts +2 -0
  101. package/dist/test_consult_split.d.ts.map +1 -0
  102. package/dist/test_consult_split.js +30 -0
  103. package/dist/test_consult_split.js.map +1 -0
  104. package/dist/test_coverage_relevance.d.ts +12 -0
  105. package/dist/test_coverage_relevance.d.ts.map +1 -0
  106. package/dist/test_coverage_relevance.js +162 -0
  107. package/dist/test_coverage_relevance.js.map +1 -0
  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.d.ts +2 -0
  113. package/dist/test_dcr_and_legacy_deprecation.d.ts.map +1 -0
  114. package/dist/test_dcr_and_legacy_deprecation.js +143 -0
  115. package/dist/test_dcr_and_legacy_deprecation.js.map +1 -0
  116. package/dist/test_demand_signal_logging.d.ts +2 -0
  117. package/dist/test_demand_signal_logging.d.ts.map +1 -0
  118. package/dist/test_demand_signal_logging.js +92 -0
  119. package/dist/test_demand_signal_logging.js.map +1 -0
  120. package/dist/test_earnings_activity_scope.d.ts +5 -0
  121. package/dist/test_earnings_activity_scope.d.ts.map +1 -0
  122. package/dist/test_earnings_activity_scope.js +101 -0
  123. package/dist/test_earnings_activity_scope.js.map +1 -0
  124. package/dist/test_earnings_divergence_live.d.ts +5 -0
  125. package/dist/test_earnings_divergence_live.d.ts.map +1 -0
  126. package/dist/test_earnings_divergence_live.js +135 -0
  127. package/dist/test_earnings_divergence_live.js.map +1 -0
  128. package/dist/test_earnings_hygiene_and_binding.d.ts +5 -0
  129. package/dist/test_earnings_hygiene_and_binding.d.ts.map +1 -0
  130. package/dist/test_earnings_hygiene_and_binding.js +104 -0
  131. package/dist/test_earnings_hygiene_and_binding.js.map +1 -0
  132. package/dist/test_exec_quotes_render.d.ts +2 -0
  133. package/dist/test_exec_quotes_render.d.ts.map +1 -0
  134. package/dist/test_exec_quotes_render.js +86 -0
  135. package/dist/test_exec_quotes_render.js.map +1 -0
  136. package/dist/test_expert_intro.d.ts +2 -0
  137. package/dist/test_expert_intro.d.ts.map +1 -0
  138. package/dist/test_expert_intro.js +57 -0
  139. package/dist/test_expert_intro.js.map +1 -0
  140. package/dist/test_expert_layer.d.ts +11 -0
  141. package/dist/test_expert_layer.d.ts.map +1 -0
  142. package/dist/test_expert_layer.js +356 -0
  143. package/dist/test_expert_layer.js.map +1 -0
  144. package/dist/test_financial_snapshot_render.d.ts +2 -0
  145. package/dist/test_financial_snapshot_render.d.ts.map +1 -0
  146. package/dist/test_financial_snapshot_render.js +167 -0
  147. package/dist/test_financial_snapshot_render.js.map +1 -0
  148. package/dist/test_gap_alert.d.ts +12 -0
  149. package/dist/test_gap_alert.d.ts.map +1 -0
  150. package/dist/test_gap_alert.js +51 -0
  151. package/dist/test_gap_alert.js.map +1 -0
  152. package/dist/test_grok_offering_surfaces.d.ts +2 -0
  153. package/dist/test_grok_offering_surfaces.d.ts.map +1 -0
  154. package/dist/test_grok_offering_surfaces.js +155 -0
  155. package/dist/test_grok_offering_surfaces.js.map +1 -0
  156. package/dist/test_human_agent_live.d.ts +2 -0
  157. package/dist/test_human_agent_live.d.ts.map +1 -0
  158. package/dist/test_human_agent_live.js +48 -0
  159. package/dist/test_human_agent_live.js.map +1 -0
  160. package/dist/test_identity_gap.d.ts +2 -0
  161. package/dist/test_identity_gap.d.ts.map +1 -0
  162. package/dist/test_identity_gap.js +171 -0
  163. package/dist/test_identity_gap.js.map +1 -0
  164. package/dist/test_intelligence_and_verifier.d.ts +17 -0
  165. package/dist/test_intelligence_and_verifier.d.ts.map +1 -0
  166. package/dist/test_intelligence_and_verifier.js +162 -0
  167. package/dist/test_intelligence_and_verifier.js.map +1 -0
  168. package/dist/test_latency_mcp_brief5.d.ts +12 -0
  169. package/dist/test_latency_mcp_brief5.d.ts.map +1 -0
  170. package/dist/test_latency_mcp_brief5.js +200 -0
  171. package/dist/test_latency_mcp_brief5.js.map +1 -0
  172. package/dist/test_limit_and_credit_card_capture.d.ts +21 -0
  173. package/dist/test_limit_and_credit_card_capture.d.ts.map +1 -0
  174. package/dist/test_limit_and_credit_card_capture.js +216 -0
  175. package/dist/test_limit_and_credit_card_capture.js.map +1 -0
  176. package/dist/test_list_graphs_topics.js +1 -1
  177. package/dist/test_list_graphs_topics.js.map +1 -1
  178. package/dist/test_live_deployed_mcp_search.d.ts +2 -0
  179. package/dist/test_live_deployed_mcp_search.d.ts.map +1 -0
  180. package/dist/test_live_deployed_mcp_search.js +85 -0
  181. package/dist/test_live_deployed_mcp_search.js.map +1 -0
  182. package/dist/test_live_deployed_split.d.ts +2 -0
  183. package/dist/test_live_deployed_split.d.ts.map +1 -0
  184. package/dist/test_live_deployed_split.js +72 -0
  185. package/dist/test_live_deployed_split.js.map +1 -0
  186. package/dist/test_live_endpoint_runner.js +2 -2
  187. package/dist/test_live_endpoint_runner.js.map +1 -1
  188. package/dist/test_live_mcp.js +1 -1
  189. package/dist/test_live_mcp.js.map +1 -1
  190. package/dist/test_live_neil_widget.d.ts +2 -0
  191. package/dist/test_live_neil_widget.d.ts.map +1 -0
  192. package/dist/test_live_neil_widget.js +84 -0
  193. package/dist/test_live_neil_widget.js.map +1 -0
  194. package/dist/test_longpoll_status.d.ts +2 -0
  195. package/dist/test_longpoll_status.d.ts.map +1 -0
  196. package/dist/test_longpoll_status.js +117 -0
  197. package/dist/test_longpoll_status.js.map +1 -0
  198. package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts +2 -0
  199. package/dist/test_mcp_find_expert_and_vocabulary_routing.d.ts.map +1 -0
  200. package/dist/test_mcp_find_expert_and_vocabulary_routing.js +130 -0
  201. package/dist/test_mcp_find_expert_and_vocabulary_routing.js.map +1 -0
  202. package/dist/test_next_moves.d.ts +2 -0
  203. package/dist/test_next_moves.d.ts.map +1 -0
  204. package/dist/test_next_moves.js +714 -0
  205. package/dist/test_next_moves.js.map +1 -0
  206. package/dist/test_next_moves_transcripts.d.ts +2 -0
  207. package/dist/test_next_moves_transcripts.d.ts.map +1 -0
  208. package/dist/test_next_moves_transcripts.js +495 -0
  209. package/dist/test_next_moves_transcripts.js.map +1 -0
  210. package/dist/test_on_request_caller_identity.d.ts +13 -0
  211. package/dist/test_on_request_caller_identity.d.ts.map +1 -0
  212. package/dist/test_on_request_caller_identity.js +131 -0
  213. package/dist/test_on_request_caller_identity.js.map +1 -0
  214. package/dist/test_on_request_intercept.d.ts +10 -0
  215. package/dist/test_on_request_intercept.d.ts.map +1 -0
  216. package/dist/test_on_request_intercept.js +95 -0
  217. package/dist/test_on_request_intercept.js.map +1 -0
  218. package/dist/test_onboarding_consent_and_errors.d.ts +2 -0
  219. package/dist/test_onboarding_consent_and_errors.d.ts.map +1 -0
  220. package/dist/test_onboarding_consent_and_errors.js +110 -0
  221. package/dist/test_onboarding_consent_and_errors.js.map +1 -0
  222. package/dist/test_onboarding_live_scenarios.d.ts +2 -0
  223. package/dist/test_onboarding_live_scenarios.d.ts.map +1 -0
  224. package/dist/test_onboarding_live_scenarios.js +189 -0
  225. package/dist/test_onboarding_live_scenarios.js.map +1 -0
  226. package/dist/test_referral_live.d.ts +2 -0
  227. package/dist/test_referral_live.d.ts.map +1 -0
  228. package/dist/test_referral_live.js +33 -0
  229. package/dist/test_referral_live.js.map +1 -0
  230. package/dist/test_referral_piers.d.ts +2 -0
  231. package/dist/test_referral_piers.d.ts.map +1 -0
  232. package/dist/test_referral_piers.js +33 -0
  233. package/dist/test_referral_piers.js.map +1 -0
  234. package/dist/test_report_editorial_briefing.d.ts +21 -0
  235. package/dist/test_report_editorial_briefing.d.ts.map +1 -0
  236. package/dist/test_report_editorial_briefing.js +356 -0
  237. package/dist/test_report_editorial_briefing.js.map +1 -0
  238. package/dist/test_search_graph_quality.d.ts +2 -0
  239. package/dist/test_search_graph_quality.d.ts.map +1 -0
  240. package/dist/test_search_graph_quality.js +493 -0
  241. package/dist/test_search_graph_quality.js.map +1 -0
  242. package/dist/test_service_to_service_auth.d.ts +2 -0
  243. package/dist/test_service_to_service_auth.d.ts.map +1 -0
  244. package/dist/test_service_to_service_auth.js +199 -0
  245. package/dist/test_service_to_service_auth.js.map +1 -0
  246. package/dist/test_session_next_moves_telemetry.d.ts +2 -0
  247. package/dist/test_session_next_moves_telemetry.d.ts.map +1 -0
  248. package/dist/test_session_next_moves_telemetry.js +100 -0
  249. package/dist/test_session_next_moves_telemetry.js.map +1 -0
  250. package/dist/test_sources_live.d.ts +2 -0
  251. package/dist/test_sources_live.d.ts.map +1 -0
  252. package/dist/test_sources_live.js +30 -0
  253. package/dist/test_sources_live.js.map +1 -0
  254. package/dist/test_specialist_and_analyst_tiers.d.ts +2 -0
  255. package/dist/test_specialist_and_analyst_tiers.d.ts.map +1 -0
  256. package/dist/test_specialist_and_analyst_tiers.js +155 -0
  257. package/dist/test_specialist_and_analyst_tiers.js.map +1 -0
  258. package/dist/test_v2_2_visual_hardening.d.ts +5 -0
  259. package/dist/test_v2_2_visual_hardening.d.ts.map +1 -0
  260. package/dist/test_v2_2_visual_hardening.js +333 -0
  261. package/dist/test_v2_2_visual_hardening.js.map +1 -0
  262. package/dist/test_verify_deprecate_render_spec.d.ts +2 -0
  263. package/dist/test_verify_deprecate_render_spec.d.ts.map +1 -0
  264. package/dist/test_verify_deprecate_render_spec.js +217 -0
  265. package/dist/test_verify_deprecate_render_spec.js.map +1 -0
  266. package/dist/test_verify_neil_demo.d.ts +2 -0
  267. package/dist/test_verify_neil_demo.d.ts.map +1 -0
  268. package/dist/test_verify_neil_demo.js +149 -0
  269. package/dist/test_verify_neil_demo.js.map +1 -0
  270. package/dist/test_waitable_research_and_grounded_links.d.ts +2 -0
  271. package/dist/test_waitable_research_and_grounded_links.d.ts.map +1 -0
  272. package/dist/test_waitable_research_and_grounded_links.js +129 -0
  273. package/dist/test_waitable_research_and_grounded_links.js.map +1 -0
  274. package/dist/test_widget_guards.d.ts +2 -0
  275. package/dist/test_widget_guards.d.ts.map +1 -0
  276. package/dist/test_widget_guards.js +229 -0
  277. package/dist/test_widget_guards.js.map +1 -0
  278. package/dist/test_zero_retention_alerts.d.ts +14 -0
  279. package/dist/test_zero_retention_alerts.d.ts.map +1 -0
  280. package/dist/test_zero_retention_alerts.js +76 -0
  281. package/dist/test_zero_retention_alerts.js.map +1 -0
  282. package/dist/toolHandlers.d.ts +38 -1
  283. package/dist/toolHandlers.d.ts.map +1 -1
  284. package/dist/toolHandlers.js +4290 -711
  285. package/dist/toolHandlers.js.map +1 -1
  286. package/dist/tools.d.ts +22 -1
  287. package/dist/tools.d.ts.map +1 -1
  288. package/dist/tools.js +29 -4
  289. package/dist/tools.js.map +1 -1
  290. package/dist/verify_tools_endpoint.js +19 -5
  291. package/dist/verify_tools_endpoint.js.map +1 -1
  292. package/dist/widgetShell.d.ts +2 -2
  293. package/dist/widgetShell.d.ts.map +1 -1
  294. package/dist/widgetShell.js +1 -1
  295. package/dist/widgetShell.js.map +1 -1
  296. package/package.json +1 -1
  297. package/server.json +3 -31
  298. package/dist/debug_tools.d.ts +0 -2
  299. package/dist/debug_tools.d.ts.map +0 -1
  300. package/dist/debug_tools.js +0 -19
  301. package/dist/debug_tools.js.map +0 -1
  302. package/dist/inspect_list_graphs.d.ts +0 -2
  303. package/dist/inspect_list_graphs.d.ts.map +0 -1
  304. package/dist/inspect_list_graphs.js +0 -25
  305. package/dist/inspect_list_graphs.js.map +0 -1
  306. package/dist/scratch_test.d.ts.map +0 -1
  307. package/dist/scripts/simulate_gemini.d.ts +0 -2
  308. package/dist/scripts/simulate_gemini.d.ts.map +0 -1
  309. package/dist/scripts/simulate_gemini.js +0 -100
  310. package/dist/scripts/simulate_gemini.js.map +0 -1
  311. package/dist/scripts/verify_registry.d.ts +0 -2
  312. package/dist/scripts/verify_registry.d.ts.map +0 -1
  313. package/dist/scripts/verify_registry.js +0 -77
  314. package/dist/scripts/verify_registry.js.map +0 -1
  315. package/dist/src/index.d.ts +0 -2
  316. package/dist/src/index.d.ts.map +0 -1
  317. package/dist/src/index.js +0 -332
  318. package/dist/src/index.js.map +0 -1
  319. package/dist/src/tools.d.ts +0 -12
  320. package/dist/src/tools.d.ts.map +0 -1
  321. package/dist/src/tools.js +0 -104
  322. package/dist/src/tools.js.map +0 -1
  323. package/dist/src/types.d.ts +0 -44
  324. package/dist/src/types.d.ts.map +0 -1
  325. package/dist/src/types.js +0 -2
  326. package/dist/src/types.js.map +0 -1
  327. package/dist/src/verify.d.ts +0 -2
  328. package/dist/src/verify.d.ts.map +0 -1
  329. package/dist/src/verify.js +0 -47
  330. package/dist/src/verify.js.map +0 -1
  331. package/dist/src/verify_hmac.d.ts +0 -2
  332. package/dist/src/verify_hmac.d.ts.map +0 -1
  333. package/dist/src/verify_hmac.js +0 -106
  334. package/dist/src/verify_hmac.js.map +0 -1
  335. package/dist/src/verify_tools_endpoint.d.ts +0 -2
  336. package/dist/src/verify_tools_endpoint.d.ts.map +0 -1
  337. package/dist/src/verify_tools_endpoint.js +0 -40
  338. package/dist/src/verify_tools_endpoint.js.map +0 -1
  339. package/dist/test-waverunner-response.d.ts +0 -2
  340. package/dist/test-waverunner-response.d.ts.map +0 -1
  341. package/dist/test-waverunner-response.js +0 -20
  342. package/dist/test-waverunner-response.js.map +0 -1
  343. package/dist/test_coverage_r2.d.ts +0 -2
  344. package/dist/test_coverage_r2.d.ts.map +0 -1
  345. package/dist/test_coverage_scratch.d.ts +0 -2
  346. package/dist/test_coverage_scratch.d.ts.map +0 -1
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Comprehensive verification for the Expert Layer updates:
3
+ * 1. cleanDisplayName sanitization (retiring '(Classic Digital Twin)', '(Digital Twin)', etc.)
4
+ * 2. findCandidateExperts domain vs modifier overlap, blind spots, self-rec guards, honest empty
5
+ * 3. find_expert MCP tool registration, responses, and candidate formatting
6
+ * 4. consult_analyst & consult_human_agent deep parameter acceptance and forwarding
7
+ *
8
+ * Run: npm run build && node dist/test_expert_layer.js
9
+ */
10
+ import assert from 'assert';
11
+ import { cleanDisplayName, normalizeAnalyst } from './catalogCache.js';
12
+ import { findCandidateExperts } from './coverageRelevance.js';
13
+ import { createServer } from './toolHandlers.js';
14
+ async function runTests() {
15
+ console.log('================================================================');
16
+ console.log(' Running Unit Tests: Expert Layer & find_expert Verification');
17
+ console.log('================================================================\n');
18
+ // ─────────────────────────────────────────────────────────────
19
+ // 1. cleanDisplayName Tests
20
+ // ─────────────────────────────────────────────────────────────
21
+ console.log('--- 1. Testing cleanDisplayName ---');
22
+ assert.strictEqual(cleanDisplayName('Thorstein Veblen (Classic Digital Twin)'), 'Thorstein Veblen');
23
+ assert.strictEqual(cleanDisplayName('Jane Austen (Digital Twin)'), 'Jane Austen');
24
+ assert.strictEqual(cleanDisplayName('Ben Dietz (Human Twin)'), 'Ben Dietz');
25
+ assert.strictEqual(cleanDisplayName('John Ruskin (Classic Agent)'), 'John Ruskin');
26
+ assert.strictEqual(cleanDisplayName('Piers Fawkes'), 'Piers Fawkes');
27
+ assert.strictEqual(cleanDisplayName(' Alexis De Tocqueville (Digital Twin) '), 'Alexis De Tocqueville');
28
+ assert.strictEqual(cleanDisplayName('Adam Smith [Classic Digital Twin]'), 'Adam Smith');
29
+ console.log('✅ cleanDisplayName tests passed.\n');
30
+ // ─────────────────────────────────────────────────────────────
31
+ // 2. findCandidateExperts Matching Tests
32
+ // ─────────────────────────────────────────────────────────────
33
+ console.log('--- 2. Testing findCandidateExperts ---');
34
+ const mockAnalysts = [
35
+ {
36
+ analyst_id: 'lauren-goode-beauty',
37
+ name: 'Lauren Goode (Digital Twin)',
38
+ role: 'Beauty & Skincare Specialist',
39
+ description: 'Beauty and skincare specialist focusing on formulations and prestige cosmetics.',
40
+ category: 'human_agent',
41
+ category_label: 'Human Agent',
42
+ is_verified_real_person: true,
43
+ consult_tool: 'consult_human_agent',
44
+ expert_in: ['beauty', 'skincare', 'cosmetics', 'wellness', 'clean beauty'],
45
+ topics: ['prestige beauty', 'dermatology', 'retail'],
46
+ outside_their_lane: ['cryptocurrency', 'b2b saas', 'cycling'],
47
+ blind_spots: ['automotive supply chain'],
48
+ },
49
+ {
50
+ analyst_id: 'peter-abraham-cycling',
51
+ name: 'Peter Abraham',
52
+ role: 'Cycling & Outdoor Culture Expert',
53
+ description: 'Cycling industry strategist and outdoor culture voice.',
54
+ category: 'human_agent',
55
+ category_label: 'Human Agent',
56
+ is_verified_real_person: true,
57
+ consult_tool: 'consult_human_agent',
58
+ expert_in: ['cycling', 'bicycles', 'gravel racing', 'outdoor apparel'],
59
+ what_they_offer: 'Ask Peter^[HA] to innovate your cycling product strategy',
60
+ topics: ['endurance sports', 'brand strategy'],
61
+ outside_their_lane: ['beauty', 'skincare'],
62
+ blind_spots: ['fast fashion'],
63
+ },
64
+ {
65
+ analyst_id: 'piers-fawkes',
66
+ name: 'Piers Fawkes',
67
+ role: 'Retail & Consumer Trends Strategist',
68
+ description: 'Founder of PSFK and retail innovation strategist.',
69
+ category: 'human_agent',
70
+ category_label: 'Human Agent',
71
+ is_verified_real_person: true,
72
+ consult_tool: 'consult_human_agent',
73
+ // Note: Piers has cross-cutting modifiers like 'ai', 'strategy', 'trends', 'retail', 'innovation'
74
+ expert_in: ['retail innovation', 'consumer trends', 'strategy', 'ai agents', 'future of shopping'],
75
+ topics: ['omnichannel', 'experiential retail', 'technology strategy'],
76
+ outside_their_lane: ['biotech', 'heavy industrial machinery'],
77
+ blind_spots: [],
78
+ },
79
+ {
80
+ analyst_id: 'thorstein-veblen',
81
+ name: 'Thorstein Veblen (Classic Digital Twin)',
82
+ role: 'Sociologist & Institutional Economist',
83
+ description: 'Author of Theory of the Leisure Class; institutional critique of consumption.',
84
+ category: 'classic_agent',
85
+ category_label: 'Classic Agent',
86
+ is_verified_real_person: false,
87
+ consult_tool: 'consult_analyst',
88
+ expert_in: ['conspicuous consumption', 'leisure class', 'economic theory', 'status display'],
89
+ topics: ['luxury goods', 'sociology of wealth'],
90
+ outside_their_lane: ['modern digital marketing', 'tiktok algorithms'],
91
+ blind_spots: [],
92
+ },
93
+ ];
94
+ // Test 2a: Beauty query - Lauren Goode must match; Piers Fawkes must NOT match despite having 'trends'/'strategy'
95
+ const beautyCandidates = findCandidateExperts('prestige clean beauty and skincare formulation trends', {
96
+ analysts: mockAnalysts,
97
+ limit: 3,
98
+ });
99
+ console.log('Beauty query candidates:', beautyCandidates.map(c => `${c.display_name} (${c.analyst_id})`));
100
+ assert.ok(beautyCandidates.length >= 1, 'Should find at least 1 candidate for beauty');
101
+ assert.strictEqual(beautyCandidates[0]?.analyst_id, 'lauren-goode-beauty', 'Lauren Goode must be top candidate');
102
+ assert.strictEqual(beautyCandidates[0]?.display_name, 'Lauren Goode', 'Candidate display_name must be sanitized');
103
+ assert.ok(!beautyCandidates.some(c => c.analyst_id === 'piers-fawkes'), 'Piers Fawkes must NOT match beauty query solely on "trends" modifier');
104
+ // Test 2b: Cycling query - Peter Abraham must match
105
+ const cyclingCandidates = findCandidateExperts('gravel cycling race culture and gear', {
106
+ analysts: mockAnalysts,
107
+ limit: 3,
108
+ });
109
+ console.log('Cycling query candidates:', cyclingCandidates.map(c => `${c.display_name} (${c.analyst_id})`));
110
+ assert.strictEqual(cyclingCandidates.length, 1);
111
+ assert.strictEqual(cyclingCandidates[0]?.analyst_id, 'peter-abraham-cycling');
112
+ assert.ok(cyclingCandidates[0]?.reason.includes('cycling'), 'Reason should cite cycling domain');
113
+ assert.ok(!cyclingCandidates[0]?.reason.includes('Ask Peter'), 'Reason should not contain what_they_offer askLine imperative');
114
+ console.log('Peter Abraham candidate reason:', cyclingCandidates[0]?.reason);
115
+ // Test 2c: Self-recommendation protection - Peter Abraham excluded when consulting Peter Abraham
116
+ const cyclingSelfExclusion = findCandidateExperts('gravel cycling race culture and gear', {
117
+ analysts: mockAnalysts,
118
+ excludeAnalystId: 'peter-abraham-cycling',
119
+ limit: 3,
120
+ });
121
+ assert.strictEqual(cyclingSelfExclusion.length, 0, 'Must exclude candidate matching excludeAnalystId');
122
+ // Test 2d: Blind spot / outside_their_lane exclusion
123
+ // Peter Abraham has 'beauty' in outside_their_lane
124
+ const peterBeautyCheck = findCandidateExperts('beauty product innovation', {
125
+ analysts: [mockAnalysts[1]], // only Peter
126
+ });
127
+ assert.strictEqual(peterBeautyCheck.length, 0, 'Peter must be excluded from beauty query due to outside_their_lane');
128
+ // Test 2e: Honest Empty Failure
129
+ // Query completely out of scope for all mock analysts
130
+ const outOfDomainCandidates = findCandidateExperts('deep seabed geothermal subsea mining robotic drilling', {
131
+ analysts: mockAnalysts,
132
+ });
133
+ console.log('Out of domain candidates count:', outOfDomainCandidates.length);
134
+ assert.strictEqual(outOfDomainCandidates.length, 0, 'Must return empty array honestly when no expert matches');
135
+ // Test 2f: Classic Agent vs Living Practitioner ranking
136
+ // For luxury consumption: Thorstein Veblen matches
137
+ const luxuryCandidates = findCandidateExperts('conspicuous consumption and luxury status display', {
138
+ analysts: mockAnalysts,
139
+ });
140
+ assert.ok(luxuryCandidates.length >= 1);
141
+ assert.strictEqual(luxuryCandidates[0]?.analyst_id, 'thorstein-veblen');
142
+ assert.strictEqual(luxuryCandidates[0]?.display_name, 'Thorstein Veblen');
143
+ assert.strictEqual(luxuryCandidates[0]?.category, 'classic_agent');
144
+ console.log('✅ findCandidateExperts tests passed.\n');
145
+ // ─────────────────────────────────────────────────────────────
146
+ // 3. find_expert MCP Tool Registration & Execution Tests
147
+ // ─────────────────────────────────────────────────────────────
148
+ console.log('--- 3. Testing find_expert Tool Handler ---');
149
+ const server = await createServer('test_api_key', 'test_user', (async (method, path) => {
150
+ if (path.includes('/v1/analysts')) {
151
+ return { analysts: mockAnalysts };
152
+ }
153
+ return {};
154
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
155
+ const tools = server._registeredTools;
156
+ const findExpertTool = tools['find_expert'];
157
+ assert.ok(findExpertTool, 'find_expert tool must be registered in server tools');
158
+ // Execute with empty/unmatched query
159
+ const emptyResult = await findExpertTool.handler({ query: 'cryogenic orbital propulsion mechanics' });
160
+ const emptyParsed = JSON.parse(emptyResult.content[0].text);
161
+ assert.strictEqual(emptyParsed.total_matches, 0);
162
+ assert.deepStrictEqual(emptyParsed.candidates, []);
163
+ assert.ok(emptyParsed.note && emptyParsed.note.includes('No active expert directly covers this domain'));
164
+ console.log('Empty find_expert result note:', emptyParsed.note);
165
+ // Execute with general matching query (will run against cached analysts)
166
+ const beautyResult = await findExpertTool.handler({ query: 'beauty, cosmetics, and skincare' });
167
+ const beautyParsed = JSON.parse(beautyResult.content[0].text);
168
+ console.log('find_expert beauty query result total_matches:', beautyParsed.total_matches);
169
+ if (beautyParsed.candidates.length > 0) {
170
+ const first = beautyParsed.candidates[0];
171
+ assert.ok(first.analyst_id, 'Candidate must have analyst_id');
172
+ assert.ok(first.display_name, 'Candidate must have display_name');
173
+ assert.ok(!first.display_name.includes('(Classic Digital Twin)'), 'display_name must not contain legacy twin suffix');
174
+ assert.ok(!first.display_name.includes('(Digital Twin)'), 'display_name must not contain legacy twin suffix');
175
+ assert.ok(first.category, 'Candidate must have category');
176
+ assert.ok(first.reason, 'Candidate must have reason explanation');
177
+ assert.ok(first.consult_tool, 'Candidate must have consult_tool');
178
+ }
179
+ console.log('✅ find_expert local fallback tests passed.\n');
180
+ // ─────────────────────────────────────────────────────────────
181
+ // 3b. find_expert API Integration Tests (On-Request, Active, Related Graphs, Timeout Fallback)
182
+ // ─────────────────────────────────────────────────────────────
183
+ console.log('--- 3b. Testing find_expert API Integration & Differentiated Routing ---');
184
+ // Test 3b.1: On-Request Specialist via API
185
+ const serverWithOnRequestApi = await createServer('test_api_key', 'test_user', (async (method, path) => {
186
+ if (path.includes('/v1/experts/search')) {
187
+ return {
188
+ ok: true,
189
+ query: 'nicotine pouches',
190
+ total_matches: 1,
191
+ timing_ms: 15.2,
192
+ results: [
193
+ {
194
+ id: 'adam-specialist',
195
+ slug: 'adam-specialist',
196
+ name: 'Adam Specialist',
197
+ status: 'Unclaimed',
198
+ agent_class: 'human_agent',
199
+ role_title: 'Regulatory & Market Entry Director',
200
+ search_ask_line: 'Ask Adam about market entry and compliance for nicotine pouches and vaping products.',
201
+ why_matched: ['Nicotine pouches', 'Vaping products'],
202
+ topics: ['harm reduction', 'oral nicotine'],
203
+ score: 25
204
+ }
205
+ ],
206
+ related_knowledge_graphs: []
207
+ };
208
+ }
209
+ return {};
210
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
211
+ const findExpertOnRequest = serverWithOnRequestApi._registeredTools['find_expert'];
212
+ const onRequestRes = await findExpertOnRequest.handler({ query: 'nicotine pouches' });
213
+ const onRequestParsed = JSON.parse(onRequestRes.content[0].text);
214
+ assert.strictEqual(onRequestParsed.total_matches, 1);
215
+ const onReqCandidate = onRequestParsed.candidates[0];
216
+ assert.strictEqual(onReqCandidate.analyst_id, 'adam-specialist');
217
+ assert.strictEqual(onReqCandidate.status, 'on_request');
218
+ assert.strictEqual(onReqCandidate.search_ask_line, 'Ask Adam about market entry and compliance for nicotine pouches and vaping products.');
219
+ assert.deepStrictEqual(onReqCandidate.why_matched, ['Nicotine pouches', 'Vaping products']);
220
+ assert.ok(onReqCandidate.next_step.includes('request_expert_intro(analyst_id: \'adam-specialist\')'));
221
+ assert.ok(onReqCandidate.next_step.includes('consult_human_agent(analyst_id: \'adam-specialist\')'));
222
+ console.log('✅ find_expert On-Request candidate routing verified.');
223
+ // Test 3b.2: Active Human Agent via API
224
+ const serverWithActiveApi = await createServer('test_api_key', 'test_user', (async (method, path) => {
225
+ if (path.includes('/v1/experts/search')) {
226
+ return {
227
+ ok: true,
228
+ query: 'clean beauty',
229
+ total_matches: 1,
230
+ timing_ms: 12.0,
231
+ results: [
232
+ {
233
+ id: 'tara-james-taylor',
234
+ slug: 'tara-james-taylor',
235
+ name: 'Tara James Taylor',
236
+ status: 'Active',
237
+ agent_class: 'human_agent',
238
+ role_title: 'Global Head of Beauty & Personal Care',
239
+ search_ask_line: 'Ask Tara about clean beauty formulation trends and retail distribution.',
240
+ why_matched: ['Clean beauty', 'Cosmetics'],
241
+ topics: ['clean beauty', 'skincare'],
242
+ score: 28
243
+ }
244
+ ],
245
+ related_knowledge_graphs: []
246
+ };
247
+ }
248
+ return {};
249
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
250
+ const findExpertActive = serverWithActiveApi._registeredTools['find_expert'];
251
+ const activeRes = await findExpertActive.handler({ query: 'clean beauty' });
252
+ const activeParsed = JSON.parse(activeRes.content[0].text);
253
+ assert.strictEqual(activeParsed.total_matches, 1);
254
+ const activeCandidate = activeParsed.candidates[0];
255
+ assert.strictEqual(activeCandidate.status, 'active');
256
+ assert.strictEqual(activeCandidate.consult_tool, 'consult_human_agent');
257
+ assert.strictEqual(activeCandidate.next_step, "Call consult_human_agent with analyst_id: 'tara-james-taylor'.");
258
+ console.log('✅ find_expert Active Human Agent routing verified.');
259
+ // Test 3b.3: Zero Matches with Related Knowledge Graphs
260
+ const serverWithGraphsApi = await createServer('test_api_key', 'test_user', (async (method, path) => {
261
+ if (path.includes('/v1/experts/search')) {
262
+ return {
263
+ ok: true,
264
+ query: 'sub-orbital hypersonic space travel',
265
+ total_matches: 0,
266
+ timing_ms: 8.5,
267
+ results: [],
268
+ related_knowledge_graphs: [
269
+ { id: 'tech', name: 'PSFK Technology & Enterprise', description: 'Tech insights' },
270
+ { id: 'transport', name: 'Mobility & Aerospace Trends', description: 'Transport insights' }
271
+ ]
272
+ };
273
+ }
274
+ return {};
275
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
276
+ const findExpertGraphs = serverWithGraphsApi._registeredTools['find_expert'];
277
+ const graphsRes = await findExpertGraphs.handler({ query: 'sub-orbital hypersonic space travel' });
278
+ const graphsParsed = JSON.parse(graphsRes.content[0].text);
279
+ assert.strictEqual(graphsParsed.total_matches, 0);
280
+ assert.deepStrictEqual(graphsParsed.candidates, []);
281
+ assert.ok(graphsParsed.note.includes('No dedicated Human Agent covers this domain yet'));
282
+ assert.ok(graphsParsed.note.includes('PSFK Technology & Enterprise, Mobility & Aerospace Trends'));
283
+ assert.ok(graphsParsed.note.includes("search_graph(graphId: 'tech', query: 'sub-orbital hypersonic space travel')"));
284
+ assert.strictEqual(graphsParsed.related_knowledge_graphs.length, 2);
285
+ console.log('✅ find_expert Related Knowledge Graphs recommendation verified.');
286
+ // Test 3b.4: Network Error Fallback to Local Matching
287
+ const serverWithErrorApi = await createServer('test_api_key', 'test_user', (async (method, path) => {
288
+ if (path.includes('/v1/experts/search')) {
289
+ throw new Error('Connection refused to Fodda API');
290
+ }
291
+ if (path.includes('/v1/analysts')) {
292
+ return { analysts: mockAnalysts };
293
+ }
294
+ return {};
295
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
296
+ const findExpertError = serverWithErrorApi._registeredTools['find_expert'];
297
+ const errorFallbackRes = await findExpertError.handler({ query: 'beauty, cosmetics, and skincare' });
298
+ assert.strictEqual(errorFallbackRes.isError, undefined);
299
+ const errorFallbackParsed = JSON.parse(errorFallbackRes.content[0].text);
300
+ assert.ok(errorFallbackParsed.total_matches >= 1, 'Local fallback must find candidate despite API error');
301
+ assert.strictEqual(errorFallbackParsed.candidates[0].analyst_id, 'lauren-goode-beauty');
302
+ console.log('✅ find_expert Network Error graceful local fallback verified.');
303
+ // Test 3b.5: Timeout Fallback (>3s) to Local Matching
304
+ const serverWithTimeoutApi = await createServer('test_api_key', 'test_user', (async (method, path) => {
305
+ if (path.includes('/v1/experts/search')) {
306
+ // Simulate slow upstream hang (> 3s)
307
+ await new Promise(resolve => setTimeout(resolve, 3500));
308
+ return { ok: true, results: [] };
309
+ }
310
+ if (path.includes('/v1/analysts')) {
311
+ return { analysts: mockAnalysts };
312
+ }
313
+ return {};
314
+ }), (async () => ({})), () => 'widget_1', () => 'http://localhost');
315
+ const findExpertTimeout = serverWithTimeoutApi._registeredTools['find_expert'];
316
+ const timeoutStart = Date.now();
317
+ const timeoutRes = await findExpertTimeout.handler({ query: 'beauty, cosmetics, and skincare' });
318
+ const elapsed = Date.now() - timeoutStart;
319
+ assert.strictEqual(timeoutRes.isError, undefined);
320
+ assert.ok(elapsed >= 2900 && elapsed < 4500, `Timeout must trigger around 3000ms, took ${elapsed}ms`);
321
+ const timeoutParsed = JSON.parse(timeoutRes.content[0].text);
322
+ assert.ok(timeoutParsed.total_matches >= 1, 'Local fallback must find candidate when API times out');
323
+ assert.strictEqual(timeoutParsed.candidates[0].analyst_id, 'lauren-goode-beauty');
324
+ console.log('✅ find_expert >3s Timeout graceful local fallback verified.\n');
325
+ // ─────────────────────────────────────────────────────────────
326
+ // 4. consult_analyst deep Parameter Tests
327
+ // ─────────────────────────────────────────────────────────────
328
+ console.log('--- 4. Testing consult_analyst deep Parameter ---');
329
+ const consultTool = tools['consult_analyst'];
330
+ assert.ok(consultTool, 'consult_analyst must be registered');
331
+ const shape = typeof consultTool.inputSchema?.def?.shape === 'function'
332
+ ? consultTool.inputSchema.def.shape()
333
+ : consultTool.inputSchema?.def?.shape;
334
+ assert.ok(shape && shape.deep, 'consult_analyst schema must accept deep parameter');
335
+ // ─────────────────────────────────────────────────────────────
336
+ // 5. get_capabilities find_expert Inclusion Tests
337
+ // ─────────────────────────────────────────────────────────────
338
+ console.log('--- 5. Testing get_capabilities find_expert Inclusion ---');
339
+ const getCapabilitiesTool = tools['get_capabilities'];
340
+ assert.ok(getCapabilitiesTool, 'get_capabilities must be registered');
341
+ const capRes = await getCapabilitiesTool.handler({});
342
+ const capParsed = JSON.parse(capRes.content[0].text);
343
+ const expertCap = capParsed.capabilities.find((c) => c.id === 'expert_consult');
344
+ assert.ok(expertCap, 'expert_consult capability must exist');
345
+ assert.ok(expertCap.tools.includes('find_expert'), 'find_expert must be listed in expert_consult tools');
346
+ console.log('expert_consult tools:', expertCap.tools);
347
+ console.log('✅ get_capabilities find_expert inclusion verified.\n');
348
+ console.log('================================================================');
349
+ console.log(' ALL EXPERT LAYER TESTS PASSED SUCCESSFULLY!');
350
+ console.log('================================================================');
351
+ }
352
+ runTests().catch((err) => {
353
+ console.error('❌ Test failed:', err);
354
+ process.exit(1);
355
+ });
356
+ //# sourceMappingURL=test_expert_layer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_expert_layer.js","sourceRoot":"","sources":["../src/test_expert_layer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test_financial_snapshot_render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_financial_snapshot_render.d.ts","sourceRoot":"","sources":["../src/test_financial_snapshot_render.ts"],"names":[],"mappings":""}
@@ -0,0 +1,167 @@
1
+ import assert from 'assert';
2
+ import { renderBrandWidget } from './brandTemplate.js';
3
+ async function runTests() {
4
+ console.log('=== Test 1: Public Company (Microchip Technology / NASDAQ:MCHP) with full market_data ===');
5
+ const publicProfile = {
6
+ brand: 'Microchip Technology',
7
+ trend_footprint: [
8
+ {
9
+ trend_name: 'Edge AI Microcontrollers',
10
+ trend_description: 'Low-power microcontrollers optimized for on-device machine learning inference.',
11
+ graphName: 'Semiconductors 2026',
12
+ evidence_count: 5,
13
+ signal_score: 82,
14
+ lifecycle: 'building',
15
+ }
16
+ ],
17
+ evidence_items: [
18
+ {
19
+ title: 'Microchip Announces Next-Gen MCU',
20
+ excerpt: 'Microchip Technology unveiled its latest 32-bit microcontroller line.',
21
+ published_at: '2026-07-15T00:00:00.000Z',
22
+ category: 'Case Study',
23
+ graphName: 'Semiconductors 2026'
24
+ }
25
+ ],
26
+ competitive_context: {
27
+ co_occurring_brands: [{ brand: 'STMicroelectronics', co_occurrences: 4 }]
28
+ },
29
+ cross_graph_presence: [{ graphName: 'Semiconductors 2026', graphId: 'semiconductors-2026', evidenceCount: 5 }],
30
+ market_data: {
31
+ source: 'roic_market',
32
+ ticker: 'MCHP',
33
+ primary_symbol: 'NASDAQ:MCHP',
34
+ company_profile: {
35
+ primary_symbol: 'NASDAQ:MCHP',
36
+ ticker: 'MCHP',
37
+ company_name: 'Microchip Technology Incorporated',
38
+ sector: 'Technology',
39
+ industry: 'Semiconductors',
40
+ exchange: 'NASDAQ',
41
+ currency: 'USD'
42
+ },
43
+ quarterly_financials: [
44
+ {
45
+ period: 'Q1 FY2027 (2026-06-30)',
46
+ period_end_date: '2026-06-30',
47
+ fiscal_year: 2027,
48
+ period_label: 'Q1',
49
+ revenue: 1484700000,
50
+ operating_income: 292400000,
51
+ net_income: 182300000,
52
+ eps: 0.34,
53
+ diluted_eps: 0.33
54
+ },
55
+ {
56
+ period: 'Q4 FY2026 (2026-03-31)',
57
+ period_end_date: '2026-03-31',
58
+ fiscal_year: 2026,
59
+ period_label: 'Q4',
60
+ revenue: 1325000000,
61
+ operating_income: 260000000,
62
+ net_income: 155000000,
63
+ eps: 0.29,
64
+ diluted_eps: 0.28
65
+ }
66
+ ],
67
+ price_window: {
68
+ current_price: 78.42,
69
+ as_of_date: '2026-08-21'
70
+ },
71
+ data_status: 'ok'
72
+ }
73
+ };
74
+ const resPublic = await renderBrandWidget(publicProfile);
75
+ const htmlPublic = resPublic.widget_html;
76
+ // Assertions for Public Company
77
+ assert.ok(htmlPublic.includes('Institutional Financial Snapshot'), 'Must contain Institutional Financial Snapshot heading');
78
+ assert.ok(htmlPublic.includes('Microchip Technology Incorporated'), 'Must contain company name');
79
+ assert.ok(htmlPublic.includes('NASDAQ:MCHP'), 'Must contain symbol');
80
+ assert.ok(htmlPublic.includes('Sector: Technology'), 'Must contain sector');
81
+ assert.ok(htmlPublic.includes('Industry: Semiconductors'), 'Must contain industry');
82
+ assert.ok(htmlPublic.includes('$78.42 (as of 2026-08-21)'), 'Must contain stock price with as_of date');
83
+ assert.ok(htmlPublic.includes('Q1 FY2027 (2026-06-30)'), 'Must contain Q1 period');
84
+ assert.ok(htmlPublic.includes('$1.48B'), 'Must format revenue as $1.48B');
85
+ assert.ok(htmlPublic.includes('$292.4M'), 'Must format operating income as $292.4M');
86
+ assert.ok(htmlPublic.includes('$182.3M'), 'Must format net income as $182.3M');
87
+ assert.ok(htmlPublic.includes('$0.34 (Diluted $0.33)'), 'Must format EPS / Diluted EPS');
88
+ assert.ok(htmlPublic.includes('Q4 FY2026 (2026-03-31)'), 'Must contain Q4 period');
89
+ assert.ok(htmlPublic.includes('$1.33B') || htmlPublic.includes('$1.32B'), 'Must format Q4 revenue');
90
+ assert.ok(htmlPublic.includes('Source: Institutional SEC & Market Financial Filings.'), 'Must cite standard institutional filings note');
91
+ // Strict Privacy Invariant: NEVER contain "ROIC"
92
+ assert.strictEqual(htmlPublic.includes('ROIC'), false, 'Strict Privacy Invariant: "ROIC" must never appear in rendered widget HTML');
93
+ assert.strictEqual(htmlPublic.includes('roic'), false, 'Strict Privacy Invariant: "roic" must never appear in rendered widget HTML');
94
+ console.log('✅ PASS: Public company snapshot rendered with accurate formatting and 0 ROIC mentions.');
95
+ console.log('\n=== Test 2: Private Company (Chobani) with no market_data / no_signal ===');
96
+ const privateProfile = {
97
+ brand: 'Chobani',
98
+ trend_footprint: [
99
+ {
100
+ trend_name: 'High-Protein Dairy',
101
+ trend_description: 'Consumer shift toward high protein dairy formats.',
102
+ graphName: 'Food & Beverage',
103
+ evidence_count: 4,
104
+ signal_score: 75,
105
+ lifecycle: 'mature'
106
+ }
107
+ ],
108
+ evidence_items: [],
109
+ competitive_context: { co_occurring_brands: [] },
110
+ cross_graph_presence: [{ graphName: 'Food & Beverage', graphId: 'food-beverage', evidenceCount: 4 }],
111
+ market_data: {
112
+ data_status: 'no_signal'
113
+ }
114
+ };
115
+ const resPrivate = await renderBrandWidget(privateProfile);
116
+ const htmlPrivate = resPrivate.widget_html;
117
+ assert.strictEqual(htmlPrivate.includes('Institutional Financial Snapshot'), false, 'Private company must NOT render Financial Snapshot header');
118
+ assert.strictEqual(htmlPrivate.includes('{{FINANCIAL_SNAPSHOT_SECTION_HTML}}'), false, 'Template placeholder must be cleanly removed');
119
+ assert.strictEqual(htmlPrivate.includes('ROIC') || htmlPrivate.includes('roic'), false, 'No ROIC mentions');
120
+ console.log('✅ PASS: Private company omitted Financial Snapshot cleanly without empty headers or broken placeholders.');
121
+ console.log('\n=== Test 3: Edge Case Formatting (Negative Net Income, Single Quarter, Scaling) ===');
122
+ const edgeProfile = {
123
+ brand: 'Rivian',
124
+ trend_footprint: [],
125
+ evidence_items: [],
126
+ cross_graph_presence: [],
127
+ market_data: {
128
+ ticker: 'RIVN',
129
+ primary_symbol: 'NASDAQ:RIVN',
130
+ company_profile: {
131
+ company_name: 'Rivian Automotive, Inc.',
132
+ sector: 'Consumer Cyclical',
133
+ industry: 'Auto Manufacturers',
134
+ exchange: 'NASDAQ'
135
+ },
136
+ quarterly_financials: [
137
+ {
138
+ period: 'Q2 2026',
139
+ revenue: 850000000,
140
+ operating_income: -1200000000,
141
+ net_income: -1450000000,
142
+ eps: -1.45,
143
+ diluted_eps: -1.45
144
+ }
145
+ ],
146
+ price_window: {
147
+ current_price: 14.25
148
+ },
149
+ data_status: 'ok'
150
+ }
151
+ };
152
+ const resEdge = await renderBrandWidget(edgeProfile);
153
+ const htmlEdge = resEdge.widget_html;
154
+ assert.ok(htmlEdge.includes('Rivian Automotive, Inc. (NASDAQ:RIVN)'), 'Must render header with symbol');
155
+ assert.ok(htmlEdge.includes('$850.0M'), 'Must format $850M revenue');
156
+ assert.ok(htmlEdge.includes('-$1.20B'), 'Must format negative operating income as -$1.20B');
157
+ assert.ok(htmlEdge.includes('-$1.45B'), 'Must format negative net income as -$1.45B');
158
+ assert.ok(htmlEdge.includes('-$1.45 (Diluted -$1.45)'), 'Must format negative EPS');
159
+ assert.ok(htmlEdge.includes('Stock Price: <span style="font-family:var(--font-mono);font-weight:600;">$14.25</span>'), 'Must format price without date gracefully');
160
+ console.log('✅ PASS: Edge cases formatted correctly (negatives, scaling, single quarter).');
161
+ console.log('\n🎉 All Financial Snapshot rendering tests passed successfully!');
162
+ }
163
+ runTests().catch(err => {
164
+ console.error('❌ Test failed:', err);
165
+ process.exit(1);
166
+ });
167
+ //# sourceMappingURL=test_financial_snapshot_render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_financial_snapshot_render.js","sourceRoot":"","sources":["../src/test_financial_snapshot_render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Verification for data-gap Slack alerts (v1.42.0).
3
+ *
4
+ * postGapToSlack fires a #fodda-research alert when coverage is thin/empty,
5
+ * deduped per query topic per session. Runs without SLACK_BOT_TOKEN — the
6
+ * poster logs a skip instead of hitting the network, so this exercises the
7
+ * gating/dedupe/message logic only.
8
+ *
9
+ * Run: npx tsx src/test_gap_alert.ts
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=test_gap_alert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test_gap_alert.d.ts","sourceRoot":"","sources":["../src/test_gap_alert.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}