gloomberb 0.16.3 → 0.16.5

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 (820) hide show
  1. package/README.md +14 -91
  2. package/package.json +7 -1
  3. package/src/{plugins/builtin/cloud → account}/auth-form.tsx +9 -9
  4. package/src/{plugins/builtin/cloud → account}/auth-model.ts +4 -4
  5. package/src/account/billing.ts +57 -0
  6. package/src/{plugins/builtin/cloud → account}/device-signin-dialog.tsx +18 -12
  7. package/src/{plugins/builtin/cloud → account}/device-signin.ts +2 -2
  8. package/src/{plugins/builtin/cloud → account}/email-auth-attempt.ts +2 -2
  9. package/src/account/session.ts +16 -0
  10. package/src/{plugins/builtin/cloud → account}/upgrade-dialog.tsx +42 -17
  11. package/src/account/upgrade-personalization.ts +57 -0
  12. package/src/account/upgrade-tickers.ts +124 -0
  13. package/src/{plugins/builtin/cloud → account}/verification-panel.tsx +6 -6
  14. package/src/api-client/askg.ts +43 -0
  15. package/src/api-client/auth.ts +15 -0
  16. package/src/api-client/beneficial-owners.ts +4 -0
  17. package/src/api-client/chat.ts +19 -0
  18. package/src/api-client/company-kpis.ts +14 -2
  19. package/src/api-client/data.ts +58 -18
  20. package/src/api-client/earnings.ts +6 -0
  21. package/src/api-client/futures-curve.ts +56 -0
  22. package/src/api-client/index.ts +16 -1
  23. package/src/api-client/market-discovery.ts +10 -1
  24. package/src/api-client/normalizers.ts +27 -0
  25. package/src/api-client/paths.ts +95 -23
  26. package/src/api-client/request.ts +2 -1
  27. package/src/api-client/research-activity.ts +46 -10
  28. package/src/api-client/socket.ts +39 -8
  29. package/src/api-client/types.ts +74 -2
  30. package/src/api-client/upgrade-experiment.ts +90 -0
  31. package/src/api-client/yield-curves.ts +8 -0
  32. package/src/app/global-shortcuts.ts +26 -2
  33. package/src/app/keybindings/actions.ts +10 -0
  34. package/src/app/pane-runtime/index.tsx +8 -0
  35. package/src/app/pane-runtime/pane-template-runtime.ts +5 -0
  36. package/src/app/pane-runtime/plugin-bindings.ts +65 -25
  37. package/src/app/pane-runtime/ticker-inspector-runtime.ts +12 -0
  38. package/src/app/pane-runtime/ticker-open-runtime.ts +25 -4
  39. package/src/app/runtime/desktop-deeplink.ts +5 -0
  40. package/src/app/star-prompt/model.ts +98 -0
  41. package/src/app/star-prompt/runtime.ts +41 -0
  42. package/src/app/star-prompt/status-line.tsx +190 -0
  43. package/src/app.tsx +13 -7
  44. package/src/architecture/core-builtin-allowlist.json +61 -0
  45. package/src/brokers/signed-in/adapter.ts +33 -2
  46. package/src/brokers/signed-in/client.ts +10 -0
  47. package/src/brokers/signed-in/sign-in-dialog.tsx +34 -14
  48. package/src/brokers/signed-in/sign-in.ts +62 -5
  49. package/src/capabilities/chart-series.ts +11 -1
  50. package/src/capabilities/registry.ts +8 -1
  51. package/src/capabilities/types.ts +2 -0
  52. package/src/cli/commands/crypto-hints.ts +19 -4
  53. package/src/cli/commands/fred-series.ts +61 -0
  54. package/src/cli/commands/market.ts +744 -181
  55. package/src/cli/commands/news-hints.ts +62 -0
  56. package/src/cli/commands/news-search.ts +53 -0
  57. package/src/cli/commands/options-chain.ts +172 -0
  58. package/src/cli/commands/options-leaps.ts +425 -0
  59. package/src/cli/commands/overview.ts +251 -40
  60. package/src/cli/commands/remote.ts +2 -1
  61. package/src/cli/commands/search.ts +109 -15
  62. package/src/cli/commands/system.ts +151 -24
  63. package/src/cli/commands/themes.ts +64 -0
  64. package/src/cli/commands/ticker.ts +149 -40
  65. package/src/cli/context.ts +45 -14
  66. package/src/cli/desktop-pane-shot.ts +150 -17
  67. package/src/cli/earnings-calendar.ts +71 -0
  68. package/src/cli/errors.ts +25 -2
  69. package/src/cli/freshness.ts +22 -8
  70. package/src/cli/fx-pair.ts +57 -0
  71. package/src/cli/glossary.ts +429 -0
  72. package/src/cli/help.ts +14 -1
  73. package/src/cli/history-rows.ts +48 -7
  74. package/src/cli/index-roots.ts +58 -0
  75. package/src/cli/index.ts +29 -12
  76. package/src/cli/known-gaps.ts +27 -0
  77. package/src/cli/listing-arg.ts +595 -26
  78. package/src/cli/not-a-ticker.ts +44 -0
  79. package/src/cli/options.ts +50 -6
  80. package/src/cli/pane-functions/access-gate.ts +5 -0
  81. package/src/cli/pane-functions/capabilities.ts +11 -4
  82. package/src/cli/pane-functions/catalog.ts +48 -7
  83. package/src/cli/pane-functions/data.ts +48 -13
  84. package/src/cli/pane-functions/discovery.ts +1 -0
  85. package/src/cli/pane-functions/dom.ts +41 -19
  86. package/src/cli/pane-functions/freshness.ts +531 -32
  87. package/src/cli/pane-functions/function-help.ts +77 -25
  88. package/src/cli/pane-functions/headless.ts +50 -21
  89. package/src/cli/pane-functions/index.ts +66 -10
  90. package/src/cli/pane-functions/market-session.ts +147 -0
  91. package/src/cli/pane-functions/options.ts +77 -25
  92. package/src/cli/pane-functions/report-notices.ts +81 -0
  93. package/src/cli/pane-functions/report.ts +19 -8
  94. package/src/cli/pane-functions/resolver.ts +53 -18
  95. package/src/cli/pane-functions/screenshot-evidence.ts +2 -0
  96. package/src/cli/pane-functions/screenshot.ts +199 -30
  97. package/src/cli/registry.ts +2 -1
  98. package/src/cli/report-tables.ts +3 -0
  99. package/src/cli/result.ts +53 -13
  100. package/src/cli/row-window.ts +76 -0
  101. package/src/cli/scroll-truncation.ts +34 -0
  102. package/src/cli/staged-tickers.ts +52 -0
  103. package/src/cli/symbol-args.ts +9 -0
  104. package/src/cli/symbol-list.ts +172 -0
  105. package/src/cli/ticker-resolution.ts +223 -30
  106. package/src/cli/types.ts +5 -0
  107. package/src/components/chart/composite/axis-overlays.tsx +6 -2
  108. package/src/components/chart/composite/composite-chart.tsx +83 -10
  109. package/src/components/chart/composite/legend.tsx +88 -8
  110. package/src/components/chart/composite/panel-surface.tsx +44 -17
  111. package/src/components/chart/composite/price-axis-labels.tsx +3 -1
  112. package/src/components/chart/composite/rasterizer.ts +64 -4
  113. package/src/components/chart/composite/series-cues.ts +71 -0
  114. package/src/components/chart/composite/text-renderer.ts +16 -8
  115. package/src/components/chart/composite/types.ts +3 -0
  116. package/src/components/command-bar/commands/direct/index.ts +9 -1
  117. package/src/components/command-bar/commands/plugin/items.ts +3 -1
  118. package/src/components/command-bar/commands/registry.ts +7 -0
  119. package/src/components/command-bar/layout-items/focused-pane.ts +38 -0
  120. package/src/components/command-bar/pane-templates/workflow.ts +5 -0
  121. package/src/components/command-bar/panel/index.tsx +11 -3
  122. package/src/components/command-bar/panel/runtime.ts +3 -0
  123. package/src/components/command-bar/panel/types.ts +2 -0
  124. package/src/components/command-bar/routes/root/command-items.ts +2 -0
  125. package/src/components/command-bar/routes/root/plugin-turn-on.ts +92 -0
  126. package/src/components/command-bar/routes/root/provider-search.ts +4 -3
  127. package/src/components/command-bar/routes/root/results.ts +40 -10
  128. package/src/components/command-bar/routes/root/runtime.ts +8 -0
  129. package/src/components/command-bar/routes/root/search-providers.ts +97 -14
  130. package/src/components/command-bar/routes/ticker-search/results.ts +12 -11
  131. package/src/components/command-bar/routes/ticker-search/route.ts +4 -3
  132. package/src/components/command-bar/surface/index.tsx +18 -4
  133. package/src/components/command-bar/theme-picker.tsx +48 -13
  134. package/src/components/command-bar/workflow/ops.ts +5 -3
  135. package/src/components/command-bar/workflow/tickers.ts +23 -4
  136. package/src/components/data-table/view.tsx +28 -9
  137. package/src/components/layout/detached-pane-shell.tsx +9 -0
  138. package/src/components/layout/floating-pane.tsx +9 -2
  139. package/src/components/layout/header.tsx +20 -5
  140. package/src/components/layout/market-summary.ts +23 -9
  141. package/src/components/layout/pane/content.tsx +40 -29
  142. package/src/components/layout/pane/cycle-order.ts +2 -11
  143. package/src/components/layout/pane/footer/index.tsx +6 -2
  144. package/src/components/layout/pane/footer/model.ts +35 -1
  145. package/src/components/layout/pane/header.tsx +26 -2
  146. package/src/components/layout/pane/index.tsx +12 -2
  147. package/src/components/layout/pane/sidebar.tsx +78 -10
  148. package/src/components/layout/pane/title.ts +1 -1
  149. package/src/components/layout/presentation.ts +22 -0
  150. package/src/components/layout/shell/active-drag.ts +21 -5
  151. package/src/components/layout/shell/drag/index.ts +43 -9
  152. package/src/components/layout/shell/drag/live.ts +87 -6
  153. package/src/components/layout/shell/drag/runtime.ts +62 -20
  154. package/src/components/layout/shell/index.tsx +71 -12
  155. package/src/components/layout/shell/layout-state.ts +5 -11
  156. package/src/components/layout/shell/menu.ts +33 -1
  157. package/src/components/layout/shell/native/pointer-runtime.ts +3 -1
  158. package/src/components/layout/shell/pane/actions.ts +2 -1
  159. package/src/components/layout/shell/pane/layers.tsx +216 -28
  160. package/src/components/layout/shell/pane/management-shortcuts.ts +5 -0
  161. package/src/components/layout/shell/pane/new-layout.ts +116 -0
  162. package/src/components/layout/shell/shortcuts.ts +5 -2
  163. package/src/components/layout/shell/terminal-pointer-runtime.ts +24 -0
  164. package/src/components/layout/shell/visible-layout.ts +44 -1
  165. package/src/components/layout/status-bar.tsx +4 -1
  166. package/src/components/markdown-text.tsx +69 -23
  167. package/src/components/metric-treemap/heat-surface.tsx +37 -9
  168. package/src/components/metric-treemap/heat-tiles.ts +48 -17
  169. package/src/components/onboarding/account-step/form-panel.tsx +1 -1
  170. package/src/components/onboarding/account-step/index.tsx +1 -1
  171. package/src/components/onboarding/account-step/qr-panel.tsx +1 -1
  172. package/src/components/onboarding/account-step/signed-in-panel.tsx +1 -1
  173. package/src/components/onboarding/onboarding-frame.tsx +33 -10
  174. package/src/components/onboarding/onboarding-keyboard.ts +1 -1
  175. package/src/components/onboarding/onboarding-wizard.tsx +50 -41
  176. package/src/components/onboarding/portfolio-step/positions-panel.tsx +5 -2
  177. package/src/components/onboarding/pro-step-layout.ts +86 -0
  178. package/src/components/onboarding/use-onboarding-upgrade.ts +8 -4
  179. package/src/components/onboarding/wizard-account.ts +2 -2
  180. package/src/components/pane-template-wizard.tsx +9 -1
  181. package/src/components/price-selector-dialog.tsx +11 -2
  182. package/src/components/sign-in-gate.tsx +3 -3
  183. package/src/components/ticker/list-table-view.tsx +24 -1
  184. package/src/components/ui/action-row.tsx +2 -1
  185. package/src/components/ui/button.tsx +17 -1
  186. package/src/components/ui/choice-dialog.tsx +6 -4
  187. package/src/components/ui/confirm-dialog.tsx +28 -18
  188. package/src/components/ui/data-table/index.tsx +49 -0
  189. package/src/components/ui/data-table/opentui/index.tsx +37 -6
  190. package/src/components/ui/data-table/types.ts +20 -1
  191. package/src/components/ui/data-table/visible-range.ts +2 -0
  192. package/src/components/ui/dialog-actions.tsx +64 -0
  193. package/src/components/ui/display.tsx +17 -3
  194. package/src/components/ui/frame.tsx +35 -2
  195. package/src/components/ui/icon.tsx +13 -2
  196. package/src/components/ui/index.ts +1 -1
  197. package/src/components/ui/text-prompt-dialog.tsx +11 -9
  198. package/src/core/connection-health.ts +1 -1
  199. package/src/core/state/app/layout-reducer.ts +89 -3
  200. package/src/core/state/app/state.ts +8 -5
  201. package/src/core/state/app/types.ts +13 -2
  202. package/src/data/cached-query.ts +2 -0
  203. package/src/data/config/layout.ts +55 -21
  204. package/src/data/config/store/fold-panes.ts +149 -0
  205. package/src/data/config/store/migrations.ts +7 -0
  206. package/src/data/config/store/node.ts +27 -6
  207. package/src/data/config/store/normalize.ts +44 -5
  208. package/src/data/ticker-repository.ts +5 -0
  209. package/src/data/ticker-store.ts +15 -0
  210. package/src/docs/content.ts +215 -0
  211. package/src/docs/load.ts +139 -0
  212. package/src/docs/requests.ts +39 -0
  213. package/src/docs/snapshot.chunk.ts +8 -0
  214. package/src/docs/snapshot.json +7416 -0
  215. package/src/docs/topics.ts +216 -0
  216. package/src/i18n/es.ts +75 -5
  217. package/src/i18n/ja.ts +75 -5
  218. package/src/i18n/ko.ts +75 -5
  219. package/src/i18n/zh-cn.ts +75 -5
  220. package/src/i18n/zh-tw.ts +75 -5
  221. package/src/layout/desks.ts +2 -3
  222. package/src/layout/pane-layout-move.ts +264 -0
  223. package/src/layout/pane-manager/dock-tree.ts +18 -0
  224. package/src/layout/pane-manager/hidden-panes.ts +160 -0
  225. package/src/layout/pane-manager/index.ts +2 -0
  226. package/src/market-data/coordinator/chart.ts +10 -4
  227. package/src/market-data/coordinator/entries.ts +7 -1
  228. package/src/market-data/coordinator/index.ts +6 -3
  229. package/src/market-data/coordinator/quotes.ts +2 -2
  230. package/src/{plugins/builtin/futures/contracts.ts → market-data/futures-board.ts} +81 -28
  231. package/src/market-data/futures-contract.ts +151 -0
  232. package/src/market-data/hooks.tsx +10 -2
  233. package/src/market-data/market/format.ts +39 -21
  234. package/src/market-data/market/freshness.ts +193 -30
  235. package/src/market-data/market/status.ts +59 -23
  236. package/src/market-data/options-alternatives.ts +69 -0
  237. package/src/market-data/published-apac-sessions.ts +23 -1
  238. package/src/market-data/quotes/contributions.ts +22 -2
  239. package/src/market-data/quotes/metadata.ts +8 -9
  240. package/src/market-data/quotes/resolution.ts +2 -0
  241. package/src/market-data/quotes/screener-live-quotes.ts +61 -9
  242. package/src/market-data/result-types.ts +2 -0
  243. package/src/plugins/builtin/account-management/keyboard.ts +3 -0
  244. package/src/plugins/builtin/account-management/model.ts +2 -56
  245. package/src/plugins/builtin/account-management/navigation.ts +1 -1
  246. package/src/plugins/builtin/account-management/pane.tsx +37 -8
  247. package/src/plugins/builtin/account-management/password-dialog.tsx +1 -1
  248. package/src/plugins/builtin/alerts/cli.ts +313 -47
  249. package/src/plugins/builtin/alerts/events-pane.tsx +45 -7
  250. package/src/plugins/builtin/alerts/events.ts +23 -2
  251. package/src/plugins/builtin/alerts/history-pane.tsx +7 -2
  252. package/src/plugins/builtin/alerts/history.ts +2 -0
  253. package/src/plugins/builtin/alerts/index.tsx +41 -9
  254. package/src/plugins/builtin/alerts/pane.tsx +8 -0
  255. package/src/plugins/builtin/alerts/quotes.ts +3 -0
  256. package/src/plugins/builtin/alerts/research-builder.ts +8 -3
  257. package/src/plugins/builtin/alerts/research-rules.ts +18 -2
  258. package/src/plugins/builtin/alerts/scheduled-check.ts +122 -0
  259. package/src/plugins/builtin/alerts/scheduled-sources.ts +25 -0
  260. package/src/plugins/builtin/alerts/scheduled.ts +254 -0
  261. package/src/plugins/builtin/alerts/targets.ts +92 -0
  262. package/src/plugins/builtin/analytics/index.tsx +4 -2
  263. package/src/plugins/builtin/analytics/risk-headless.ts +33 -13
  264. package/src/plugins/builtin/analytics/risk-math.ts +91 -27
  265. package/src/plugins/builtin/analytics/risk-model.ts +71 -12
  266. package/src/plugins/builtin/analytics/risk-pane.tsx +23 -12
  267. package/src/plugins/builtin/attention/index.tsx +2 -0
  268. package/src/plugins/builtin/attention/pane.tsx +3 -1
  269. package/src/plugins/builtin/attention/series.ts +26 -0
  270. package/src/plugins/builtin/awards/index.tsx +2 -0
  271. package/src/plugins/builtin/awards/pane.tsx +3 -1
  272. package/src/plugins/builtin/awards/series.ts +29 -0
  273. package/src/plugins/builtin/backtest/pane.tsx +1 -1
  274. package/src/plugins/builtin/bond-calculator/model.ts +2 -1
  275. package/src/plugins/builtin/broker-manager/detail.tsx +4 -0
  276. package/src/plugins/builtin/broker-manager/index.tsx +7 -3
  277. package/src/plugins/builtin/broker-manager/model.ts +8 -0
  278. package/src/plugins/builtin/broker-manager/pane-actions.tsx +8 -2
  279. package/src/plugins/builtin/broker-manager/sign-in-end.ts +82 -0
  280. package/src/plugins/builtin/broker-manager/table.ts +5 -0
  281. package/src/plugins/builtin/builtin-plugin-meta.ts +121 -11
  282. package/src/plugins/builtin/catalysts/pane.tsx +3 -1
  283. package/src/plugins/builtin/cds/client.ts +70 -13
  284. package/src/plugins/builtin/cds/headless.ts +116 -19
  285. package/src/plugins/builtin/cds/index.tsx +3 -1
  286. package/src/plugins/builtin/cds/model.ts +193 -31
  287. package/src/plugins/builtin/cds/pane.tsx +56 -14
  288. package/src/plugins/builtin/cds/series.ts +19 -0
  289. package/src/plugins/builtin/central-bank-rates/index.tsx +2 -0
  290. package/src/plugins/builtin/central-bank-rates/series.ts +42 -0
  291. package/src/plugins/builtin/chart-composer/catalog-inventory.ts +192 -255
  292. package/src/plugins/builtin/chart-composer/data-catalog-pane.tsx +84 -46
  293. package/src/plugins/builtin/chart-composer/editor.tsx +5 -4
  294. package/src/plugins/builtin/chart-composer/field-series.ts +40 -0
  295. package/src/plugins/builtin/chart-composer/headless.ts +8 -3
  296. package/src/plugins/builtin/chart-composer/index.tsx +9 -2
  297. package/src/plugins/builtin/chart-composer/pane.tsx +1 -1
  298. package/src/plugins/builtin/chart-composer/series-catalog.ts +58 -50
  299. package/src/plugins/builtin/chart-composer/series-expression.ts +18 -10
  300. package/src/plugins/builtin/chart-composer/use-series-catalog.ts +59 -3
  301. package/src/plugins/builtin/chart-composer/user-series.ts +84 -0
  302. package/src/plugins/builtin/chat/channels.ts +34 -36
  303. package/src/plugins/builtin/chat/command-bar.ts +138 -0
  304. package/src/plugins/builtin/chat/composer-commands.ts +21 -1
  305. package/src/plugins/builtin/chat/content/composer-runtime.ts +11 -1
  306. package/src/plugins/builtin/chat/content/footer.tsx +5 -3
  307. package/src/plugins/builtin/chat/content/index.tsx +21 -1
  308. package/src/plugins/builtin/chat/content/mentions.ts +2 -1
  309. package/src/plugins/builtin/chat/content/new-dm-dialog.tsx +10 -2
  310. package/src/plugins/builtin/chat/content/user-map.ts +3 -1
  311. package/src/plugins/builtin/chat/controller/index.ts +50 -0
  312. package/src/plugins/builtin/chat/conversations.ts +256 -0
  313. package/src/plugins/builtin/chat/discord-command.ts +91 -0
  314. package/src/plugins/builtin/chat/edit-window.ts +12 -6
  315. package/src/plugins/builtin/chat/ghost-user.ts +14 -0
  316. package/src/plugins/builtin/chat/index.tsx +40 -2
  317. package/src/plugins/builtin/chat/layout.ts +2 -0
  318. package/src/plugins/builtin/chat/message/desktop.tsx +2 -1
  319. package/src/plugins/builtin/chat/message/header.tsx +24 -15
  320. package/src/plugins/builtin/chat/message/profile-popover.tsx +2 -1
  321. package/src/plugins/builtin/chat/message/render-state.ts +3 -0
  322. package/src/plugins/builtin/chat/pane-requests.ts +60 -0
  323. package/src/plugins/builtin/chat/pane-state.ts +32 -2
  324. package/src/plugins/builtin/chat/pane.tsx +8 -0
  325. package/src/plugins/builtin/cloud/askg/controller.ts +223 -23
  326. package/src/plugins/builtin/cloud/askg/conversation-store.ts +21 -0
  327. package/src/plugins/builtin/cloud/askg/executor.ts +57 -3
  328. package/src/plugins/builtin/cloud/askg/manifest.ts +33 -7
  329. package/src/plugins/builtin/cloud/askg/model.ts +156 -78
  330. package/src/plugins/builtin/cloud/askg/pane.tsx +772 -377
  331. package/src/plugins/builtin/cloud/askg/protocol.ts +50 -3
  332. package/src/plugins/builtin/cloud/askg/tool-display.ts +440 -0
  333. package/src/plugins/builtin/cloud/askg/tool-timeline.tsx +403 -0
  334. package/src/plugins/builtin/cloud/askg/undo.ts +2 -0
  335. package/src/plugins/builtin/cloud/auth-actions.tsx +1 -1
  336. package/src/plugins/builtin/cloud/auth-commands.ts +1 -1
  337. package/src/plugins/builtin/cloud/auth-dialog.tsx +3 -3
  338. package/src/plugins/builtin/cloud/company-picker.tsx +1 -9
  339. package/src/plugins/builtin/cloud/mcp-connect/command.ts +24 -0
  340. package/src/plugins/builtin/cloud/mcp-connect/dialog.tsx +363 -0
  341. package/src/plugins/builtin/cloud/mcp-connect/model.ts +135 -0
  342. package/src/plugins/builtin/cloud/mcp-connect/sections.ts +62 -0
  343. package/src/plugins/builtin/cloud/plugin.tsx +36 -1
  344. package/src/plugins/builtin/cloud/terminal-relay/acm-tab.tsx +89 -0
  345. package/src/plugins/builtin/cloud/terminal-relay/client.ts +97 -0
  346. package/src/plugins/builtin/cloud/terminal-relay/connect-section.tsx +57 -0
  347. package/src/plugins/builtin/cloud/terminal-relay/engine.ts +734 -0
  348. package/src/plugins/builtin/cloud/terminal-relay/grants.ts +137 -0
  349. package/src/plugins/builtin/cloud/terminal-relay/host.tsx +81 -0
  350. package/src/plugins/builtin/cloud/terminal-relay/indicator.tsx +82 -0
  351. package/src/plugins/builtin/cloud/terminal-relay/manifest.ts +239 -0
  352. package/src/plugins/builtin/cloud/terminal-relay/policy.ts +162 -0
  353. package/src/plugins/builtin/cloud/terminal-relay/prompts.tsx +192 -0
  354. package/src/plugins/builtin/cloud/terminal-relay/redact.ts +73 -0
  355. package/src/plugins/builtin/cloud/terminal-relay/summary.ts +62 -0
  356. package/src/plugins/builtin/cloud/thesis/exposure.ts +1 -1
  357. package/src/plugins/builtin/cloud/thesis/prompts.tsx +2 -1
  358. package/src/plugins/builtin/comment-letters/client.ts +1 -3
  359. package/src/plugins/builtin/company-attention/app-rank.tsx +1 -1
  360. package/src/plugins/builtin/company-attention/headless.ts +19 -5
  361. package/src/plugins/builtin/company-attention/index.tsx +2 -0
  362. package/src/plugins/builtin/company-attention/model.ts +26 -7
  363. package/src/plugins/builtin/company-attention/pane.tsx +12 -9
  364. package/src/plugins/builtin/company-attention/series.ts +52 -0
  365. package/src/plugins/builtin/company-kpis/client.ts +23 -8
  366. package/src/plugins/builtin/company-kpis/headless.ts +3 -1
  367. package/src/plugins/builtin/company-kpis/pane.tsx +19 -9
  368. package/src/plugins/builtin/company-kpis/screenshot-evidence.ts +10 -3
  369. package/src/plugins/builtin/composite-plugins.ts +116 -67
  370. package/src/plugins/builtin/cot/index.tsx +3 -1
  371. package/src/plugins/builtin/cot/model.ts +40 -11
  372. package/src/plugins/builtin/cot/series.ts +27 -0
  373. package/src/plugins/builtin/credit-boards/cdx-pane.tsx +4 -4
  374. package/src/plugins/builtin/credit-boards/index.tsx +23 -21
  375. package/src/plugins/builtin/credit-boards/model.ts +0 -1
  376. package/src/plugins/builtin/credit-boards/pane.tsx +30 -0
  377. package/src/plugins/builtin/credit-boards/series.ts +66 -0
  378. package/src/plugins/builtin/credit-boards/sovr-pane.tsx +4 -4
  379. package/src/plugins/builtin/credit-conditions/index.tsx +2 -0
  380. package/src/plugins/builtin/credit-conditions/series.ts +26 -0
  381. package/src/plugins/builtin/credit-documents/headless.ts +31 -1
  382. package/src/plugins/builtin/credit-documents/pane.tsx +3 -1
  383. package/src/plugins/builtin/crypto-board/headless.ts +2 -3
  384. package/src/plugins/builtin/crypto-board/index.tsx +2 -0
  385. package/src/plugins/builtin/crypto-board/model.ts +12 -0
  386. package/src/plugins/builtin/crypto-board/pane.tsx +19 -12
  387. package/src/plugins/builtin/crypto-board/series.ts +48 -0
  388. package/src/plugins/builtin/custom-view/live-quotes.ts +2 -2
  389. package/src/plugins/builtin/debt-maturities/client.ts +37 -9
  390. package/src/plugins/builtin/debt-maturities/headless.ts +3 -1
  391. package/src/plugins/builtin/debt-maturities/index.tsx +2 -0
  392. package/src/plugins/builtin/debt-maturities/pane.tsx +5 -4
  393. package/src/plugins/builtin/debt-maturities/series.ts +45 -0
  394. package/src/plugins/builtin/dividend-yield/headless.ts +2 -2
  395. package/src/plugins/builtin/dividend-yield/index.tsx +3 -1
  396. package/src/plugins/builtin/dividend-yield/pane.tsx +1 -1
  397. package/src/plugins/builtin/dividend-yield/series.ts +20 -0
  398. package/src/plugins/builtin/docs/blocks.tsx +181 -0
  399. package/src/plugins/builtin/docs/index.tsx +68 -0
  400. package/src/plugins/builtin/docs/pane.tsx +426 -0
  401. package/src/plugins/builtin/docs/targets.ts +72 -0
  402. package/src/plugins/builtin/docs/use-docs.ts +60 -0
  403. package/src/plugins/builtin/doe/index.tsx +2 -0
  404. package/src/plugins/builtin/doe/series.ts +62 -0
  405. package/src/plugins/builtin/earnings/client.ts +3 -2
  406. package/src/plugins/builtin/earnings/format.ts +1 -5
  407. package/src/plugins/builtin/earnings/headless.ts +58 -6
  408. package/src/plugins/builtin/earnings/history-model.ts +15 -1
  409. package/src/plugins/builtin/earnings/history-table.ts +13 -2
  410. package/src/plugins/builtin/earnings/history.tsx +7 -3
  411. package/src/plugins/builtin/earnings-calls/data.ts +28 -7
  412. package/src/plugins/builtin/earnings-calls/headless.ts +3 -2
  413. package/src/plugins/builtin/earnings-calls/pane.tsx +10 -5
  414. package/src/plugins/builtin/econ/calendar-model.ts +42 -17
  415. package/src/plugins/builtin/econ/detail-view.tsx +2 -2
  416. package/src/plugins/builtin/econ/fred-catalog.ts +189 -0
  417. package/src/plugins/builtin/econ/fred-series-map.ts +0 -46
  418. package/src/plugins/builtin/econ/index.tsx +70 -22
  419. package/src/plugins/builtin/econ-statistics/defs.ts +5 -0
  420. package/src/plugins/builtin/econ-statistics/headless.ts +30 -5
  421. package/src/plugins/builtin/econ-statistics/pane.tsx +1 -1
  422. package/src/plugins/builtin/econ-statistics/stats.ts +1 -0
  423. package/src/plugins/builtin/econ-statistics/view.ts +17 -0
  424. package/src/plugins/builtin/equity-screener/pane.tsx +4 -11
  425. package/src/plugins/builtin/executives/data.ts +17 -6
  426. package/src/plugins/builtin/executives/pane.tsx +16 -7
  427. package/src/plugins/builtin/exposure/holdings.ts +1 -1
  428. package/src/plugins/builtin/exposure/pane.tsx +3 -1
  429. package/src/plugins/builtin/fear-greed/index.tsx +4 -0
  430. package/src/plugins/builtin/fear-greed/series.ts +52 -0
  431. package/src/plugins/builtin/filing-events/pane.tsx +22 -5
  432. package/src/plugins/builtin/futures/index.tsx +43 -3
  433. package/src/plugins/builtin/futures/model.ts +1 -1
  434. package/src/plugins/builtin/futures/returns.ts +1 -1
  435. package/src/plugins/builtin/futures/series.ts +13 -0
  436. package/src/plugins/builtin/futures/table.tsx +1 -1
  437. package/src/plugins/builtin/futures/use-front-returns.ts +1 -1
  438. package/src/plugins/builtin/futures-curve/client.ts +12 -3
  439. package/src/plugins/builtin/futures-curve/headless.ts +70 -9
  440. package/src/plugins/builtin/futures-curve/index.tsx +1 -1
  441. package/src/plugins/builtin/futures-curve/model.ts +66 -11
  442. package/src/plugins/builtin/futures-curve/pane.tsx +52 -18
  443. package/src/plugins/builtin/fx-matrix/index.tsx +22 -1
  444. package/src/plugins/builtin/fx-matrix/pairs.ts +1 -1
  445. package/src/plugins/builtin/fx-matrix/settings.ts +42 -2
  446. package/src/plugins/builtin/gpu/board.tsx +13 -10
  447. package/src/plugins/builtin/gpu/changes.tsx +4 -4
  448. package/src/plugins/builtin/gpu/client.ts +19 -1
  449. package/src/plugins/builtin/gpu/equities.tsx +14 -10
  450. package/src/plugins/builtin/gpu/headless.ts +64 -27
  451. package/src/plugins/builtin/gpu/history.tsx +3 -3
  452. package/src/plugins/builtin/gpu/index.tsx +2 -0
  453. package/src/plugins/builtin/gpu/model.ts +114 -20
  454. package/src/plugins/builtin/gpu/pane.tsx +28 -12
  455. package/src/plugins/builtin/gpu/series.ts +38 -0
  456. package/src/plugins/builtin/help/function-card.tsx +25 -6
  457. package/src/plugins/builtin/help/index.tsx +18 -8
  458. package/src/plugins/builtin/holders/beneficial-client.ts +29 -7
  459. package/src/plugins/builtin/holders/beneficial-model.ts +90 -3
  460. package/src/plugins/builtin/holders/beneficial-report.ts +57 -5
  461. package/src/plugins/builtin/holders/beneficial-view.tsx +62 -14
  462. package/src/plugins/builtin/holders/client.ts +22 -3
  463. package/src/plugins/builtin/holders/format.ts +18 -3
  464. package/src/plugins/builtin/holders/headless.ts +42 -134
  465. package/src/plugins/builtin/holders/pane.tsx +14 -4
  466. package/src/plugins/builtin/holders/report-header.ts +40 -5
  467. package/src/plugins/builtin/holders/report-rows.ts +240 -0
  468. package/src/plugins/builtin/insider/client.ts +35 -20
  469. package/src/plugins/builtin/insider/headless.ts +41 -11
  470. package/src/plugins/builtin/insider/index.tsx +27 -10
  471. package/src/plugins/builtin/insider/insider-data.ts +10 -0
  472. package/src/plugins/builtin/insider/issuer.ts +49 -0
  473. package/src/plugins/builtin/insider/model.ts +3 -0
  474. package/src/plugins/builtin/iv-history/charts.tsx +21 -7
  475. package/src/plugins/builtin/iv-history/client.ts +26 -6
  476. package/src/plugins/builtin/iv-history/format.ts +33 -2
  477. package/src/plugins/builtin/iv-history/headless.ts +27 -12
  478. package/src/plugins/builtin/iv-history/index.tsx +5 -3
  479. package/src/plugins/builtin/iv-history/model.ts +172 -20
  480. package/src/plugins/builtin/iv-history/pane.tsx +11 -3
  481. package/src/plugins/builtin/iv-history/screen-pane.tsx +45 -25
  482. package/src/plugins/builtin/iv-history/series.ts +29 -0
  483. package/src/plugins/builtin/jobs/headless.ts +28 -3
  484. package/src/plugins/builtin/jobs/index.tsx +3 -1
  485. package/src/plugins/builtin/jobs/pane.tsx +1 -1
  486. package/src/plugins/builtin/jobs/series.ts +19 -0
  487. package/src/plugins/builtin/kelly-sizer/headless.ts +149 -0
  488. package/src/plugins/builtin/kelly-sizer/history.ts +80 -0
  489. package/src/plugins/builtin/kelly-sizer/index.tsx +2 -0
  490. package/src/plugins/builtin/kelly-sizer/pane.tsx +111 -40
  491. package/src/plugins/builtin/kelly-sizer/portfolio.ts +0 -39
  492. package/src/plugins/builtin/kelly-sizer/sections.tsx +14 -0
  493. package/src/plugins/builtin/kelly-sizer/types.ts +9 -1
  494. package/src/plugins/builtin/layout-manager/index.tsx +9 -1
  495. package/src/plugins/builtin/macro-day/client.ts +68 -3
  496. package/src/plugins/builtin/macro-day/headless.ts +18 -12
  497. package/src/plugins/builtin/macro-day/index.tsx +3 -0
  498. package/src/plugins/builtin/macro-day/model.ts +66 -15
  499. package/src/plugins/builtin/macro-day/pane.tsx +34 -20
  500. package/src/plugins/builtin/macro-day/release-table.ts +40 -0
  501. package/src/plugins/builtin/macro-day/releases.ts +62 -44
  502. package/src/plugins/builtin/market-heatmap/data.ts +25 -5
  503. package/src/plugins/builtin/market-heatmap/evidence.ts +90 -0
  504. package/src/plugins/builtin/market-heatmap/index.tsx +144 -63
  505. package/src/plugins/builtin/market-heatmap/model.ts +102 -3
  506. package/src/plugins/builtin/market-heatmap/portfolio.ts +12 -2
  507. package/src/plugins/builtin/market-movers/client.ts +7 -5
  508. package/src/plugins/builtin/market-movers/headless.ts +31 -4
  509. package/src/plugins/builtin/market-movers/index.tsx +11 -3
  510. package/src/plugins/builtin/market-movers/model.ts +101 -17
  511. package/src/plugins/builtin/market-movers/screener.ts +31 -0
  512. package/src/plugins/builtin/market-movers/table.ts +50 -23
  513. package/src/plugins/builtin/market-valuation/chart-series.ts +29 -69
  514. package/src/plugins/builtin/market-valuation/index.tsx +3 -3
  515. package/src/plugins/builtin/market-valuation/indicators.ts +0 -5
  516. package/src/plugins/builtin/members/headless.ts +7 -2
  517. package/src/plugins/builtin/members/model.ts +31 -3
  518. package/src/plugins/builtin/members/pane.tsx +3 -6
  519. package/src/plugins/builtin/mna/headless.ts +15 -3
  520. package/src/plugins/builtin/money-markets/index.tsx +2 -0
  521. package/src/plugins/builtin/money-markets/series.ts +41 -0
  522. package/src/plugins/builtin/news/headless.ts +9 -2
  523. package/src/plugins/builtin/news/wire/news/footer.ts +10 -0
  524. package/src/plugins/builtin/notes/cli.ts +12 -7
  525. package/src/plugins/builtin/openfda/client.ts +1 -1
  526. package/src/plugins/builtin/options/carry.ts +95 -0
  527. package/src/plugins/builtin/options/index.tsx +58 -5
  528. package/src/plugins/builtin/options/strike-window.ts +183 -0
  529. package/src/plugins/builtin/options/table.ts +55 -3
  530. package/src/plugins/builtin/options/types.ts +8 -1
  531. package/src/plugins/builtin/options/view.tsx +162 -13
  532. package/src/plugins/builtin/options-calculator/inputs.ts +2 -1
  533. package/src/plugins/builtin/options-positioning/client.ts +7 -3
  534. package/src/plugins/builtin/options-positioning/headless.ts +5 -2
  535. package/src/plugins/builtin/options-positioning/pane.tsx +2 -2
  536. package/src/plugins/builtin/options-scenario/charts.tsx +2 -2
  537. package/src/plugins/builtin/options-scenario/client.ts +75 -18
  538. package/src/plugins/builtin/options-scenario/headless.ts +72 -24
  539. package/src/plugins/builtin/options-scenario/hedge.ts +285 -0
  540. package/src/plugins/builtin/options-scenario/index.tsx +9 -2
  541. package/src/plugins/builtin/options-scenario/model.ts +33 -0
  542. package/src/plugins/builtin/options-scenario/pane.tsx +40 -16
  543. package/src/plugins/builtin/pe-band/model.ts +2 -2
  544. package/src/plugins/builtin/pe-band/report-dates.ts +11 -7
  545. package/src/plugins/builtin/perps/client.ts +40 -6
  546. package/src/plugins/builtin/perps/equity-row.tsx +33 -8
  547. package/src/plugins/builtin/perps/freshness.ts +66 -0
  548. package/src/plugins/builtin/perps/headless.ts +45 -30
  549. package/src/plugins/builtin/perps/index.tsx +18 -1
  550. package/src/plugins/builtin/perps/model.ts +32 -6
  551. package/src/plugins/builtin/perps/pane.tsx +76 -20
  552. package/src/plugins/builtin/perps/series.ts +76 -0
  553. package/src/plugins/builtin/plugin-marketplace/model.ts +64 -21
  554. package/src/plugins/builtin/plugin-marketplace/packs.ts +118 -0
  555. package/src/plugins/builtin/plugin-marketplace/pane.tsx +357 -39
  556. package/src/plugins/builtin/plugin-marketplace/store.ts +7 -1
  557. package/src/plugins/builtin/plugin-module.ts +90 -4
  558. package/src/plugins/builtin/portfolio-list/account-metrics.ts +1 -1
  559. package/src/plugins/builtin/portfolio-list/cli/bulk-symbols.ts +273 -0
  560. package/src/plugins/builtin/portfolio-list/cli/import-13f.ts +109 -0
  561. package/src/plugins/builtin/portfolio-list/cli/portfolio-command.ts +400 -99
  562. package/src/plugins/builtin/portfolio-list/cli/render.ts +281 -43
  563. package/src/plugins/builtin/portfolio-list/cli/shared.ts +26 -16
  564. package/src/plugins/builtin/portfolio-list/cli/watchlist-command.ts +120 -47
  565. package/src/plugins/builtin/portfolio-list/column-values.ts +1 -1
  566. package/src/plugins/builtin/portfolio-list/grid.tsx +1 -1
  567. package/src/plugins/builtin/portfolio-list/headless.ts +70 -9
  568. package/src/plugins/builtin/portfolio-list/imported-from.ts +8 -0
  569. package/src/plugins/builtin/portfolio-list/live-valuation.ts +6 -2
  570. package/src/plugins/builtin/portfolio-list/pane/index.tsx +6 -1
  571. package/src/plugins/builtin/portfolio-list/quick-add/index.tsx +17 -1
  572. package/src/plugins/builtin/portfolio-list/summary/totals.ts +1 -1
  573. package/src/plugins/builtin/portfolio-list/table.tsx +7 -1
  574. package/src/plugins/builtin/power/client.ts +16 -0
  575. package/src/plugins/builtin/power/evidence.ts +6 -2
  576. package/src/plugins/builtin/power/headless.ts +71 -7
  577. package/src/plugins/builtin/power/index.tsx +4 -1
  578. package/src/plugins/builtin/power/model.ts +72 -1
  579. package/src/plugins/builtin/power/pane.tsx +32 -9
  580. package/src/plugins/builtin/rate-path/headless.ts +11 -3
  581. package/src/plugins/builtin/realized-vol/headless.ts +8 -0
  582. package/src/plugins/builtin/realized-vol/pane.tsx +1 -1
  583. package/src/plugins/builtin/research/corporate-actions-pane.tsx +7 -4
  584. package/src/plugins/builtin/research/equity-diagnostic-pane.tsx +1 -1
  585. package/src/plugins/builtin/research/event-model.ts +68 -24
  586. package/src/plugins/builtin/research/events-headless.ts +2 -1
  587. package/src/plugins/builtin/research/headless.ts +2 -1
  588. package/src/plugins/builtin/revenue-breakdown/client.ts +13 -6
  589. package/src/plugins/builtin/revenue-breakdown/headless.ts +4 -1
  590. package/src/plugins/builtin/revenue-breakdown/pane.tsx +7 -4
  591. package/src/plugins/builtin/reverse-dcf/headless.ts +5 -1
  592. package/src/plugins/builtin/reverse-dcf/pane.tsx +1 -1
  593. package/src/plugins/builtin/risk-factors/data.ts +23 -9
  594. package/src/plugins/builtin/risk-factors/headless.ts +5 -2
  595. package/src/plugins/builtin/risk-factors/pane.tsx +6 -5
  596. package/src/plugins/builtin/seasonality/client.ts +15 -7
  597. package/src/plugins/builtin/seasonality/headless.ts +36 -12
  598. package/src/plugins/builtin/seasonality/index.tsx +2 -2
  599. package/src/plugins/builtin/seasonality/model.ts +119 -0
  600. package/src/plugins/builtin/seasonality/pane.tsx +108 -37
  601. package/src/plugins/builtin/sec/index.tsx +5 -5
  602. package/src/plugins/builtin/sectors/client.ts +10 -2
  603. package/src/plugins/builtin/sectors/headless.ts +35 -6
  604. package/src/plugins/builtin/sectors/index.tsx +18 -1
  605. package/src/plugins/builtin/sectors/sector-model.ts +150 -41
  606. package/src/plugins/builtin/series-inventory.ts +91 -0
  607. package/src/plugins/builtin/shared/cloud-upgrade.ts +1 -1
  608. package/src/plugins/builtin/shared/command-tab.ts +69 -0
  609. package/src/plugins/builtin/shared/earnings-report.ts +55 -0
  610. package/src/plugins/builtin/shared/fred-points.ts +20 -0
  611. package/src/plugins/builtin/shared/fx-rate-freshness.ts +101 -0
  612. package/src/plugins/builtin/shared/headless-market-data.ts +33 -1
  613. package/src/plugins/builtin/shared/members-menu.tsx +4 -4
  614. package/src/plugins/builtin/shared/open-description.ts +29 -0
  615. package/src/plugins/builtin/shared/report-freshness.ts +59 -2
  616. package/src/plugins/builtin/shared/series-warning.ts +5 -0
  617. package/src/plugins/builtin/shared/ticker-request.ts +25 -1
  618. package/src/plugins/builtin/shared/use-quote-board.ts +25 -5
  619. package/src/plugins/builtin/shared/volatility/options.ts +1 -46
  620. package/src/plugins/builtin/short-interest/headless.ts +1 -0
  621. package/src/plugins/builtin/short-interest/index.tsx +21 -4
  622. package/src/plugins/builtin/short-interest/series.ts +36 -0
  623. package/src/plugins/builtin/short-interest/surface.tsx +4 -4
  624. package/src/plugins/builtin/short-interest/watch-headless.ts +1 -0
  625. package/src/plugins/builtin/short-interest/watch-model.ts +9 -5
  626. package/src/plugins/builtin/short-volume/headless.ts +1 -0
  627. package/src/plugins/builtin/short-volume/index.tsx +3 -10
  628. package/src/plugins/builtin/short-volume/series.ts +23 -0
  629. package/src/plugins/builtin/social-mentions/index.tsx +2 -0
  630. package/src/plugins/builtin/social-mentions/series.ts +23 -0
  631. package/src/plugins/builtin/supply-chain/graph-pane.tsx +3 -2
  632. package/src/plugins/builtin/supply-chain/model.ts +1 -1
  633. package/src/plugins/builtin/supply-chain/pane.tsx +3 -1
  634. package/src/plugins/builtin/thirteenf/api.ts +1 -0
  635. package/src/plugins/builtin/thirteenf/data.ts +6 -4
  636. package/src/plugins/builtin/thirteenf/headless.ts +217 -36
  637. package/src/plugins/builtin/thirteenf/model.ts +39 -1
  638. package/src/plugins/builtin/thirteenf/overlap.ts +75 -0
  639. package/src/plugins/builtin/thirteenf/pane.tsx +10 -1
  640. package/src/plugins/builtin/thirteenf/report-notes.ts +103 -1
  641. package/src/plugins/builtin/thirteenf/types.ts +2 -0
  642. package/src/plugins/builtin/ticker-detail/headless.ts +43 -21
  643. package/src/plugins/builtin/ticker-detail/index.tsx +3 -0
  644. package/src/plugins/builtin/ticker-detail/overview/components.tsx +1 -1
  645. package/src/plugins/builtin/ticker-detail/overview/futures-contract.ts +31 -0
  646. package/src/plugins/builtin/ticker-detail/overview/model.ts +3 -3
  647. package/src/plugins/builtin/ticker-detail/overview/pane.tsx +2 -1
  648. package/src/plugins/builtin/ticker-detail/overview-tab.tsx +48 -4
  649. package/src/plugins/builtin/ticker-detail/pane.tsx +4 -5
  650. package/src/plugins/builtin/ticker-detail/quote-monitor/card.tsx +94 -6
  651. package/src/plugins/builtin/ticker-detail/quote-monitor/index.tsx +13 -3
  652. package/src/plugins/builtin/time-sales/headless.ts +1 -0
  653. package/src/plugins/builtin/treasury-auctions/cache.ts +5 -2
  654. package/src/plugins/builtin/treasury-auctions/client.ts +22 -8
  655. package/src/plugins/builtin/treasury-auctions/headless.ts +56 -6
  656. package/src/plugins/builtin/treasury-auctions/index.tsx +12 -9
  657. package/src/plugins/builtin/treasury-auctions/model.ts +205 -30
  658. package/src/plugins/builtin/treasury-auctions/pane.tsx +35 -11
  659. package/src/plugins/builtin/treasury-auctions/types.ts +11 -1
  660. package/src/plugins/builtin/vol-surface/charts.tsx +1 -3
  661. package/src/plugins/builtin/vol-surface/client.ts +6 -2
  662. package/src/plugins/builtin/vol-surface/evidence.ts +11 -6
  663. package/src/plugins/builtin/vol-surface/headless.ts +125 -20
  664. package/src/plugins/builtin/vol-surface/model.ts +23 -11
  665. package/src/plugins/builtin/vol-surface/pane.tsx +38 -27
  666. package/src/plugins/builtin/vol-surface/tables.ts +124 -0
  667. package/src/plugins/builtin/volatility/index.tsx +2 -0
  668. package/src/plugins/builtin/volatility/series.ts +84 -0
  669. package/src/plugins/builtin/world-indices/client.ts +22 -4
  670. package/src/plugins/builtin/world-indices/headless.ts +54 -27
  671. package/src/plugins/builtin/world-indices/model.ts +4 -2
  672. package/src/plugins/builtin/world-indices/table.tsx +13 -2
  673. package/src/plugins/builtin/world-venue-map/geo-series.ts +27 -2
  674. package/src/plugins/builtin/world-venue-map/headless.ts +4 -1
  675. package/src/plugins/builtin/world-venue-map/index.ts +3 -2
  676. package/src/plugins/builtin/world-venue-map/layered-pane.tsx +8 -4
  677. package/src/plugins/builtin/world-venue-map/layers.ts +29 -0
  678. package/src/plugins/builtin/yield-curve/chart.ts +2 -2
  679. package/src/plugins/builtin/yield-curve/curves.ts +21 -8
  680. package/src/plugins/builtin/yield-curve/headless.ts +71 -18
  681. package/src/plugins/builtin/yield-curve/index.tsx +4 -2
  682. package/src/plugins/builtin/yield-curve/series.ts +86 -0
  683. package/src/plugins/builtin-editorial.ts +126 -0
  684. package/src/plugins/catalog-backend.ts +16 -9
  685. package/src/plugins/catalog-browser.ts +129 -64
  686. package/src/plugins/catalog-manifest.ts +73 -40
  687. package/src/plugins/catalog-ui.ts +26 -6
  688. package/src/plugins/extracted-plugins.ts +7 -1
  689. package/src/plugins/ownership.ts +150 -7
  690. package/src/plugins/plugin-functions.ts +54 -0
  691. package/src/plugins/plugin-off.ts +36 -0
  692. package/src/plugins/registry/host-actions.ts +16 -0
  693. package/src/plugins/registry/index.ts +173 -28
  694. package/src/plugins/registry/plugin-state.ts +25 -1
  695. package/src/plugins/runtime/context.tsx +29 -0
  696. package/src/{plugins/builtin/portfolio-list → portfolio}/position-metrics.ts +6 -6
  697. package/src/portfolio/position-value.ts +40 -0
  698. package/src/public/__snapshots__/public-api.test.ts.snap +7 -0
  699. package/src/public/time-series.ts +17 -0
  700. package/src/react/auto-refresh.ts +13 -3
  701. package/src/react/input.ts +48 -1
  702. package/src/remote/app-host.tsx +25 -4
  703. package/src/remote/confirm-change.tsx +85 -0
  704. package/src/remote/controller-utils.ts +8 -1
  705. package/src/remote/controller.ts +126 -59
  706. package/src/remote/matching.ts +69 -0
  707. package/src/remote/pane-screenshot.ts +47 -0
  708. package/src/remote/schema.ts +63 -1
  709. package/src/remote/semantic-tree.tsx +14 -0
  710. package/src/remote/types.ts +32 -0
  711. package/src/remote/watchlist.ts +306 -0
  712. package/src/renderers/browser/main.tsx +3 -2
  713. package/src/renderers/cloudflare/worker.ts +1 -1
  714. package/src/renderers/dom/data-table/frozen-column.ts +3 -1
  715. package/src/renderers/dom/data-table/index.tsx +33 -6
  716. package/src/renderers/dom/data-table/row.tsx +27 -1
  717. package/src/renderers/dom/desktop/control-styles.ts +63 -1
  718. package/src/renderers/dom/desktop/controls.tsx +30 -23
  719. package/src/renderers/dom/desktop/dialog-actions.tsx +170 -0
  720. package/src/renderers/dom/desktop/icons.tsx +21 -0
  721. package/src/renderers/dom/desktop/query-bar.tsx +59 -32
  722. package/src/renderers/dom/dom-ui-host.tsx +3 -0
  723. package/src/renderers/dom/host/box.tsx +4 -1
  724. package/src/renderers/dom/host/chart-surface.tsx +6 -2
  725. package/src/renderers/dom/host/drag-shield.ts +17 -6
  726. package/src/renderers/dom/host/live-frame.ts +14 -2
  727. package/src/renderers/dom/host/overflow-fade.ts +14 -1
  728. package/src/renderers/dom/host/size-observer.ts +26 -0
  729. package/src/renderers/dom/host/surface-3d.tsx +7 -2
  730. package/src/renderers/dom/host/text.tsx +1 -1
  731. package/src/renderers/dom/input-host.tsx +6 -1
  732. package/src/renderers/dom/styles.css +74 -0
  733. package/src/renderers/electrobun/bun/desktop/backend.ts +5 -1
  734. package/src/renderers/electrobun/bun/desktop/detached-windows.ts +12 -1
  735. package/src/renderers/electrobun/bun/desktop/initialization.ts +2 -1
  736. package/src/renderers/electrobun/shared/protocol.ts +2 -0
  737. package/src/renderers/electrobun/view/cli-pane-shot-entry.tsx +18 -3
  738. package/src/renderers/electrobun/view/cli-pane-shot-frame.tsx +109 -5
  739. package/src/renderers/electrobun/view/cli-pane-shot-health.ts +10 -26
  740. package/src/renderers/electrobun/view/main.tsx +6 -1
  741. package/src/renderers/opentui/input-host.tsx +6 -1
  742. package/src/renderers/opentui/start.tsx +9 -0
  743. package/src/series/capability.ts +75 -0
  744. package/src/series/csv.ts +160 -0
  745. package/src/series/files.ts +107 -0
  746. package/src/series/registry.ts +198 -0
  747. package/src/series/resolve.ts +107 -0
  748. package/src/series/standalone.ts +48 -0
  749. package/src/series/types.ts +145 -0
  750. package/src/series/validate.ts +171 -0
  751. package/src/shares/portable-layout.ts +16 -6
  752. package/src/sources/gloomberb-cloud/index.ts +26 -17
  753. package/src/sources/gloomberb-cloud/normalizers.ts +5 -1
  754. package/src/sources/history-result.ts +1 -0
  755. package/src/sources/listing-symbols.ts +14 -5
  756. package/src/sources/provider-errors.ts +88 -3
  757. package/src/sources/provider-router/batches.ts +4 -1
  758. package/src/sources/provider-router/cache.ts +4 -2
  759. package/src/sources/provider-router/cached-routes.ts +9 -5
  760. package/src/sources/provider-router/financial-routes.ts +12 -5
  761. package/src/sources/provider-router/financials.ts +55 -15
  762. package/src/sources/provider-router/history.ts +68 -34
  763. package/src/sources/provider-router/index.ts +1 -1
  764. package/src/sources/provider-router/primary.ts +23 -5
  765. package/src/sources/provider-router/search.ts +1 -0
  766. package/src/sources/sec-edgar.ts +68 -8
  767. package/src/sync/core-contributors.ts +5 -3
  768. package/src/test-support/cli-context.ts +2 -1
  769. package/src/test-support/data-provider.ts +34 -0
  770. package/src/test-support/shell-pane-keys.tsx +1 -0
  771. package/src/theme/series-colors.ts +46 -0
  772. package/src/theme/themes.ts +149 -0
  773. package/src/tickers/company-name.ts +75 -0
  774. package/src/tickers/instrument-kind.ts +25 -0
  775. package/src/tickers/open-target.ts +3 -2
  776. package/src/tickers/search/index.ts +67 -9
  777. package/src/tickers/search/ranking.ts +78 -18
  778. package/src/tickers/search/types.ts +10 -2
  779. package/src/tickers/starter-symbols.ts +8 -0
  780. package/src/tickers/us-listing.ts +34 -0
  781. package/src/time-series/hooks.ts +9 -0
  782. package/src/time-series/resolve.ts +96 -30
  783. package/src/time-series/types.ts +4 -2
  784. package/src/time-series/use-chart-resolution.ts +32 -0
  785. package/src/types/config.ts +67 -1
  786. package/src/types/data-provider.ts +5 -0
  787. package/src/types/financials.ts +52 -1
  788. package/src/types/headless.ts +72 -0
  789. package/src/types/instrument.ts +8 -0
  790. package/src/types/plugin.ts +68 -3
  791. package/src/types/price-history.ts +7 -0
  792. package/src/types/ticker.ts +14 -0
  793. package/src/ui/host.tsx +26 -4
  794. package/src/ui/index.tsx +2 -0
  795. package/src/ui/live-resize.ts +81 -0
  796. package/src/ui/live-stretch.ts +121 -0
  797. package/src/ui/measured-cells.ts +58 -0
  798. package/src/ui/pane-fill.ts +11 -0
  799. package/src/utils/basis-points.ts +17 -0
  800. package/src/utils/cli-output.ts +21 -2
  801. package/src/utils/concurrency.ts +25 -0
  802. package/src/utils/crypto-pair.ts +20 -0
  803. package/src/utils/currency-pair.ts +19 -0
  804. package/src/utils/decimal-comma.ts +19 -0
  805. package/src/utils/dom-screenshot-css.ts +265 -0
  806. package/src/utils/dom-screenshot-rasters.ts +276 -0
  807. package/src/utils/dom-screenshot.ts +437 -52
  808. package/src/utils/exchange-rate-snapshot.ts +6 -2
  809. package/src/utils/exchanges.ts +120 -1
  810. package/src/utils/format.ts +17 -3
  811. package/src/utils/fundamentals.ts +66 -0
  812. package/src/utils/futures-generic.ts +6 -12
  813. package/src/utils/fx-market-hours.ts +44 -0
  814. package/src/utils/option-expiry.ts +126 -0
  815. package/src/utils/price-history.ts +130 -40
  816. package/src/utils/rpc-timeout-error.ts +6 -2
  817. package/src/utils/sec-eps-basis.ts +178 -36
  818. package/src/utils/sec.ts +98 -40
  819. package/src/utils/throttled-fetch.ts +51 -22
  820. package/src/utils/utc-time.ts +51 -4
@@ -1,9 +1,7 @@
1
1
  import type { PaneInstanceConfig } from "../../../types/config";
2
2
  import type { PluginModule } from "../plugin-module";
3
- import { createTickerSurfacePaneTemplate } from "../shared/ticker-surface";
3
+ import { SHORT_VOLUME_SERIES } from "./series";
4
4
  import { shortVolumeCache } from "./client";
5
- import { shortVolumeHeadless } from "./headless";
6
- import { ShortVolumePane } from "./pane";
7
5
 
8
6
  export const shortVolumeSettings = [
9
7
  { key: "shortVolumeScope", label: "Reporting scope", type: "select" as const,
@@ -14,14 +12,9 @@ export const shortVolumeSettings = [
14
12
  export const followsWithoutFinraOverride = (pane: PaneInstanceConfig) => (
15
13
  typeof pane.settings?.finraSymbol !== "string" || !pane.settings.finraSymbol.trim()
16
14
  );
15
+ /** The daily-volume cache. `SIV` opens the short interest pane, so this module has no pane of its own. */
17
16
  export const shortVolumeModule: PluginModule = {
18
- panes: [{ id: "short-volume", name: "Daily Short Volume", icon: "S", component: ShortVolumePane,
19
- defaultPosition: "right", tickerFollower: followsWithoutFinraOverride, defaultMode: "floating", defaultFloatingSize: { width: 92, height: 28 },
20
- tableExport: true, headless: shortVolumeHeadless, settings: { title: "Daily Short Volume", fields: shortVolumeSettings } }],
21
- paneTemplates: [{ ...createTickerSurfacePaneTemplate({ id: "short-volume-pane", paneId: "short-volume", label: "Daily Short Volume",
22
- description: "FINRA daily off-exchange short-volume ratios, historical percentile and reported share quantities.",
23
- shortcut: "SIV", keywords: ["daily", "short", "volume", "finra", "siv"], publicShare: true,
24
- }), headless: shortVolumeHeadless }],
17
+ series: SHORT_VOLUME_SERIES,
25
18
  setup(ctx) { shortVolumeCache.attach(ctx.persistence); },
26
19
  dispose() { shortVolumeCache.reset(); },
27
20
  };
@@ -0,0 +1,23 @@
1
+ import type { SeriesDefinition } from "../../../series/types";
2
+ import { cachedSeriesWarning } from "../shared/series-warning";
3
+ import { loadShortVolume } from "./client";
4
+
5
+ /** The share of a ticker's daily on-exchange volume reported as short sales. */
6
+ export const SHORT_VOLUME_SERIES: readonly SeriesDefinition[] = [{
7
+ id: "short-volume:ratio",
8
+ name: "Daily short volume ratio",
9
+ unit: "%",
10
+ frequency: "daily",
11
+ group: "Positioning",
12
+ tags: ["short volume", "short sales", "shorts"],
13
+ publisher: "FINRA",
14
+ input: "ticker",
15
+ load: async ({ ticker }) => {
16
+ const resource = await loadShortVolume(ticker!, "nms");
17
+ const warning = cachedSeriesWarning(resource);
18
+ return {
19
+ points: resource.payload.history.map((point) => ({ date: point.date, value: point.ratioPercent })),
20
+ ...(warning ? { warning } : {}),
21
+ };
22
+ },
23
+ }];
@@ -1,4 +1,5 @@
1
1
  import type { PluginModule } from "../plugin-module";
2
+ import { SOCIAL_MENTION_SERIES } from "./series";
2
3
  import { createTickerSurfacePaneTemplate } from "../shared/ticker-surface";
3
4
  import { socialMentionPostsCache, socialMentionsCache } from "./client";
4
5
  import { socialMentionsHeadless } from "./headless";
@@ -9,6 +10,7 @@ const socialMentionsSettings = [
9
10
  options: [{ value: "1y", label: "1 year" }, { value: "5y", label: "5 years" }, { value: "max", label: "Since 2012" }] },
10
11
  ];
11
12
  export const socialMentionsModule: PluginModule = {
13
+ series: SOCIAL_MENTION_SERIES,
12
14
  panes: [{ id: "social-mentions", name: "Social Mentions", icon: "B", component: SocialMentionsPane,
13
15
  defaultPosition: "right", tickerFollower: true, defaultMode: "floating", defaultFloatingSize: { width: 96, height: 30 },
14
16
  tableExport: true, headless: socialMentionsHeadless, settings: { title: "Social Mentions", fields: socialMentionsSettings } }],
@@ -0,0 +1,23 @@
1
+ import type { SeriesDefinition } from "../../../series/types";
2
+ import { cachedSeriesWarning } from "../shared/series-warning";
3
+ import { loadSocialMentions } from "./client";
4
+
5
+ /** How often a ticker is posted about each day, over the last year. */
6
+ export const SOCIAL_MENTION_SERIES: readonly SeriesDefinition[] = [{
7
+ id: "social-mentions:posts",
8
+ name: "Social media mentions",
9
+ unit: "posts",
10
+ frequency: "daily",
11
+ group: "Alternative data",
12
+ tags: ["social", "mentions", "posts", "retail attention"],
13
+ input: "ticker",
14
+ style: "columns",
15
+ load: async ({ ticker }) => {
16
+ const resource = await loadSocialMentions(ticker!, "1y");
17
+ const warning = cachedSeriesWarning(resource);
18
+ return {
19
+ points: resource.payload.x.days.map((row) => ({ date: row.day, value: row.mentions })),
20
+ ...(warning ? { warning } : {}),
21
+ };
22
+ },
23
+ }];
@@ -11,6 +11,7 @@ import { useThemeColors } from "../../../theme/theme-context";
11
11
  import { Box, ScrollBox, Text, TextAttributes, useRendererHost, useUiCapabilities, type ScrollBoxRenderable } from "../../../ui";
12
12
  import { SignInWall } from "../cloud/auth-actions";
13
13
  import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
14
+ import { useOpenDescription } from "../shared/open-description";
14
15
  import { UpgradeLabel } from "../shared/locked-rows";
15
16
  import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
16
17
  import { cachedGraph, graphOptions, loadGraph, validateGraph } from "./graph-client";
@@ -138,7 +139,7 @@ export function SupplyGraphPane({ symbol, tab, width, height, focused }: { symbo
138
139
  const selectedPath = paths.find(path => path.id === selectedPathId) ?? paths.find(path => path.nodeIds.at(-1) === selectedId) ?? (target ? initialPath : null) ?? null;
139
140
  const selected = (tab === "path" ? null : data?.nodes.find(node => node.id === selectedId)) ?? (selectedPath ? data?.nodes.find(node => node.id === selectedPath.nodeIds.at(-1)) : null) ?? null;
140
141
  const openPath = paths.find(path => path.id === openId) ?? (instance?.settings?.evidence && openId !== "closed" ? initialPath : null) ?? null;
141
- const openUpgrade = useCloudUpgradeAction("splc"), { createPaneFromTemplate } = usePluginAppActions();
142
+ const openUpgrade = useCloudUpgradeAction("splc"), { createPaneFromTemplate } = usePluginAppActions(), openDescription = useOpenDescription();
142
143
  const recenter = (entity: SupplyEntity) => { setFocus(entityKey(entity)); setTarget(""); setTargetDraft(""); setSelected(null); setSelectedPath(null); setOpen(null); setCollapsed([]); };
143
144
  const applyTarget = (value: string) => { setTarget(value.trim()); setTargetDraft(value.trim()); setSelected(null); setSelectedPath(null); setOpen(null); setTargetActive(false); };
144
145
  const selectNode = (id: string) => { setSelected(id); setSelectedPath(null); };
@@ -149,7 +150,7 @@ export function SupplyGraphPane({ symbol, tab, width, height, focused }: { symbo
149
150
  ...(tab === "graph" && !openPath && selected && selected.id !== data?.entity?.id ? [{ id: "target", key: "p", label: "aths to target", onPress: () => applyTarget(entityKey(selected)) },
150
151
  { id: "collapse", key: "c", label: collapsed.includes(selected.id) ? "expand" : "ollapse", onPress: () => setCollapsed(old => old.includes(selected.id) ? old.filter(id => id !== selected.id) : [...old, selected.id]) }] : []),
151
152
  ...(!openPath && selected?.ticker ? [
152
- { id: "description", key: "d", label: "es", onPress: () => createPaneFromTemplate("new-ticker-detail-pane", { symbol: entityKey(selected) }) },
153
+ { id: "description", key: "d", label: "es", onPress: () => openDescription(entityKey(selected)) },
153
154
  { id: "financials", key: "f", label: "a", onPress: () => createPaneFromTemplate("financial-analysis-pane", { symbol: entityKey(selected) }) },
154
155
  { id: "chart", key: "g", label: "raph", onPress: () => createPaneFromTemplate("chart-composer-pane", { arg: entityKey(selected) }) },
155
156
  ] : []),
@@ -1,5 +1,5 @@
1
1
  import type { SupplyChainPayload, SupplyOptions, SupplyRole, SupplyRow } from "../../../api-client/supply-chain";
2
- import { SERIES_COLORS } from "../../../time-series/resolve";
2
+ import { SERIES_COLORS } from "../../../theme/series-colors";
3
3
  import { revenueAmount } from "../revenue-breakdown/model";
4
4
  import { activeRelationship, corroborationLabel, evidenceDate, evidenceLabel, isUnconfirmed, matchesSupplyOptions, trustTier } from "./trust";
5
5
 
@@ -19,6 +19,7 @@ import { Box, Text, TextAttributes, useRendererHost, useUiCapabilities } from ".
19
19
  import { displayWidth, truncateToDisplayWidth } from "../../../utils/format";
20
20
  import { SignInWall } from "../cloud/auth-actions";
21
21
  import { CLOUD_PLAN_KEY, useCloudUpgradeAction } from "../shared/cloud-upgrade";
22
+ import { useOpenDescription } from "../shared/open-description";
22
23
  import { Blurred, LockedOverlay, UpgradeLabel } from "../shared/locked-rows";
23
24
  import { isCloudSessionRequired, useResearchCloudSession } from "../shared/research-cloud-session";
24
25
  import { cachedSupplyChain, loadSupplyChain, SUPPLY_UNAVAILABLE, validateSupplyChain } from "./client";
@@ -143,6 +144,7 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
143
144
  const host = useRendererHost();
144
145
  const desktop = !!useUiCapabilities().nativePaneChrome;
145
146
  const { createPaneFromTemplate } = usePluginAppActions();
147
+ const openDescription = useOpenDescription();
146
148
  const session = useResearchCloudSession();
147
149
  const access = usePlanAccess();
148
150
  const accessKey = `${session.requestKey}:${access.hasProAccess ? "full" : "preview"}`;
@@ -200,7 +202,7 @@ function SupplyView({ symbol, width, height, focused }: Pick<PaneProps, "width"
200
202
  ...(current ? [{ id: "source", key: "o", label: "pen source", onPress: () => void host.openExternal(current.filingUrl) }] : []),
201
203
  ...(!openRow && selected ? [{ id: "evidence", key: "e", label: "vidence", onPress: evidence }] : []),
202
204
  ...(selected?.counterparty.ticker ? [
203
- { id: "description", key: "d", label: "es", onPress: () => navigate(selected, "new-ticker-detail-pane") },
205
+ { id: "description", key: "d", label: "es", onPress: () => openDescription(selected.counterparty.ticker!, selected.counterparty.exchange ?? undefined) },
204
206
  { id: "financials", key: "f", label: "a", onPress: () => navigate(selected, "financial-analysis-pane") },
205
207
  { id: "chart", key: "g", label: "raph", onPress: () => createPaneFromTemplate("chart-composer-pane", { arg: publicTickerKey(selected.counterparty.ticker!, selected.counterparty.exchange ?? undefined) }) },
206
208
  ...(getSharedRegistry()?.paneTemplates.has("buildout-pane") ? [{ id: "buildout", key: "t", label: "bo", onPress: () => createPaneFromTemplate("buildout-pane") }] : []),
@@ -179,6 +179,7 @@ export function mapForm(raw: any): ThirteenFFormSummary | null {
179
179
  tableEntryTotal: finiteOrNull(raw.table_entry_total),
180
180
  isAmendment: boolOrFalse(raw.is_amendment) || submissionType.includes("/A"),
181
181
  amendmentType: stringOrEmpty(raw.amendment_type) || undefined,
182
+ valueNote: stringOrEmpty(raw.value_note) || undefined,
182
183
  };
183
184
  }
184
185
 
@@ -14,6 +14,7 @@ import { isoDateDaysAgo, isoDateToday, isoDateYearsAgo } from "../../../utils/ca
14
14
  import {
15
15
  buildBrowserRows,
16
16
  latestLikely13FQuarter,
17
+ oneFundPerCik,
17
18
  buildPeriodReports,
18
19
  dedupeLatestForms,
19
20
  } from "./model";
@@ -192,7 +193,8 @@ async function loadBrowserPage(
192
193
  nextOffset: offset + 1,
193
194
  };
194
195
  }
195
- const funds = await searchThirteenFFunds(trimmed, browserLimit, signal, pageApiOptions);
196
+ const found = await searchThirteenFFunds(trimmed, browserLimit, signal, pageApiOptions);
197
+ const funds = oneFundPerCik(found);
196
198
  const [{ reports, warning }, topFunds] = await Promise.all([
197
199
  loadReportsForFunds(funds.slice(0, Math.min(browserLimit, FORM_ENRICHMENT_LIMIT)), { from, to, signal, ...apiOptions }),
198
200
  listTopThirteenFFunds(quarter, browserLimit, signal, apiOptions).catch(() => []),
@@ -203,15 +205,15 @@ async function loadBrowserPage(
203
205
  .filter((fund): fund is ThirteenFTopFund => !!fund);
204
206
  return {
205
207
  rows: buildBrowserRows({
206
- funds,
208
+ funds: oneFundPerCik(found, reports),
207
209
  topFunds: matchedTopFunds,
208
210
  reports,
209
211
  source: "funds",
210
212
  }),
211
213
  quarter,
212
214
  warning,
213
- hasMore: funds.length >= browserLimit,
214
- nextOffset: offset + funds.length,
215
+ hasMore: found.length >= browserLimit,
216
+ nextOffset: offset + found.length,
215
217
  };
216
218
  }
217
219
 
@@ -6,16 +6,30 @@ import type {
6
6
  } from "../../../types/plugin";
7
7
  import { formatShortDate } from "../../../utils/datetime-format";
8
8
  import { normalizeCik } from "./api";
9
- import { buildFundOverlap, overlapPeriod } from "./overlap";
9
+ import { buildFundOverlap, buildManagerEtfOverlap, overlapPeriod } from "./overlap";
10
+ import type { FundMembersPayload, MemberFundsPayload } from "../../../api-client/members";
11
+ import { fetchFunds, fetchMembers } from "../members/client";
12
+ import { coveredFund } from "../members/model";
10
13
  import { appendTickerHoldings, loadCrowding, loadTickerHoldings, type CrowdingRow, type TickerHoldings } from "./signals";
11
14
  import {
12
15
  AS_FILED_VALUE,
13
16
  compareCrowding,
14
17
  crowdingForTicker,
15
18
  cutText,
16
- periodText,
19
+ filedPeriodText,
20
+ filingDayText,
21
+ filingLagDays,
22
+ isOptionType,
23
+ isStaleFiling,
24
+ markedPositionType,
25
+ OPTION_ROWS_NOTE,
26
+ restatedValuesText,
27
+ staleFilingText,
28
+ staleFundsText,
17
29
  summarizeTickerHoldings,
30
+ THIRTEENF_LIMITS,
18
31
  THIRTEENF_MAX_LIMIT,
32
+ THIRTEENF_OPTIONS_NOTE,
19
33
  } from "./report-notes";
20
34
  import {
21
35
  loadBrowserRows,
@@ -31,9 +45,9 @@ import {
31
45
  buildTimelineRows,
32
46
  inferBrowserTabFromQuery,
33
47
  hasComparable13FQuarter,
34
- THIRTEENF_OPTIONS_NOTE,
35
48
  isCikQuery,
36
49
  positionType,
50
+ quartersBehindLatest,
37
51
  sortBrowserRows,
38
52
  sortHoldingRows,
39
53
  sortTimelineRows,
@@ -87,9 +101,16 @@ const BROWSER_COLUMNS: HeadlessPaneColumn[] = [
87
101
  },
88
102
  ];
89
103
 
104
+ /** What a 13F position report notes after its table: the filing's limits, and what the option marker means when option rows are shown. */
105
+ function positionNotes(rows: readonly { type?: unknown }[]): string[] {
106
+ return [THIRTEENF_LIMITS, ...(rows.some((row) => isOptionType(row.type)) ? [OPTION_ROWS_NOTE] : [])];
107
+ }
108
+
109
+ const TYPE_COLUMN: HeadlessPaneColumn = { key: "type", header: "Type", textFormat: markedPositionType };
110
+
90
111
  const HOLDING_COLUMNS: HeadlessPaneColumn[] = [
91
112
  { key: "ticker", header: "Ticker" },
92
- { key: "type", header: "Type" },
113
+ TYPE_COLUMN,
93
114
  { key: "issuer", header: "Issuer" },
94
115
  {
95
116
  key: "value",
@@ -175,9 +196,13 @@ export interface ThirteenFHeadlessDependencies {
175
196
  args: HeadlessPaneLoadArgs,
176
197
  ctx: HeadlessPaneContext,
177
198
  ): Promise<FundDetailData>;
199
+ /** The ETFs whose holdings files MEMB serves. */
200
+ loadEtfFunds?(ctx: HeadlessPaneContext): Promise<MemberFundsPayload["funds"]>;
201
+ /** One covered ETF's holdings file, as `fn MEMB` reads it. */
202
+ loadEtfHoldings?(ticker: string, ctx: HeadlessPaneContext): Promise<FundMembersPayload>;
178
203
  }
179
204
 
180
- const defaultDependencies: ThirteenFHeadlessDependencies = {
205
+ const defaultDependencies: Required<ThirteenFHeadlessDependencies> = {
181
206
  loadBrowser: (tab, query, limit, _args, ctx) => loadBrowserRows(
182
207
  tab,
183
208
  query,
@@ -185,6 +210,8 @@ const defaultDependencies: ThirteenFHeadlessDependencies = {
185
210
  { limit },
186
211
  ),
187
212
  loadDetail: (cik, name, _args, ctx) => loadFundDetail(cik, name, ctx.signal),
213
+ loadEtfFunds: async (ctx) => (await fetchFunds(ctx.apiClient)).funds,
214
+ loadEtfHoldings: (ticker, ctx) => fetchMembers(ticker, ctx.apiClient),
188
215
  };
189
216
 
190
217
  const VIEW_TITLES: Record<string, string> = {
@@ -217,18 +244,22 @@ function browserTab(view: HeadlessThirteenFView, query: string): ThirteenFBrowse
217
244
  return inferBrowserTabFromQuery(query);
218
245
  }
219
246
 
220
- async function resolveFund(
247
+ /**
248
+ * The manager a fund name or CIK names: a CIK as given, else the one fund
249
+ * whose name matches exactly, else the only match. `search` lists funds by
250
+ * name, as the 13F browser does.
251
+ */
252
+ async function findThirteenFFund(
221
253
  query: string,
222
- args: HeadlessPaneLoadArgs,
223
- ctx: HeadlessPaneContext,
224
- dependencies: ThirteenFHeadlessDependencies,
225
- ): Promise<{ cik: string; name: string }> {
226
- if (!query) throw new Error("13F holdings and filings require a fund name or CIK.");
254
+ search: (query: string, limit: number) => Promise<BrowserLoadResult>,
255
+ { exactOnly = false }: { exactOnly?: boolean } = {},
256
+ ): Promise<{ cik: string; name: string } | null> {
227
257
  if (isCikQuery(query)) return { cik: normalizeCik(query), name: query };
228
258
  // A small output limit must not hide other matching managers during lookup.
229
- const result = await dependencies.loadBrowser("funds", query, 25, args, ctx);
259
+ const result = await search(query, 25);
230
260
  const candidates = [...new Map(result.rows.map((row) => [row.cik, row])).values()];
231
261
  const exact = candidates.filter((row) => row.name.toLocaleLowerCase() === query.toLocaleLowerCase());
262
+ if (exactOnly) return exact.length === 1 ? { cik: exact[0]!.cik, name: exact[0]!.name } : null;
232
263
  const fund = exact.length === 1 ? exact[0]
233
264
  : candidates.length === 1 && !result.hasMore ? candidates[0] : undefined;
234
265
  if (candidates.length === 0) throw new Error(`No 13F fund found for "${query}".`);
@@ -239,12 +270,67 @@ async function resolveFund(
239
270
  return { cik: fund.cik, name: fund.name };
240
271
  }
241
272
 
273
+ async function resolveFund(
274
+ query: string,
275
+ args: HeadlessPaneLoadArgs,
276
+ ctx: HeadlessPaneContext,
277
+ dependencies: ThirteenFHeadlessDependencies,
278
+ ): Promise<{ cik: string; name: string }> {
279
+ if (!query) throw new Error("13F holdings and filings require a fund name or CIK.");
280
+ return (await findThirteenFFund(query, (text, limit) => dependencies.loadBrowser("funds", text, limit, args, ctx)))!;
281
+ }
282
+
283
+ /** A word that reads as a ticker (SPY, BRK.B), not a manager's name or a CIK. */
284
+ const TICKER_WORD = /^\$?[A-Za-z]{1,5}(?:[.-][A-Za-z])?$/;
285
+
286
+ type OverlapComparison =
287
+ | { kind: "fund"; cik: string; name: string }
288
+ | { kind: "etf"; symbol: string; ticker: string; name: string };
289
+
290
+ /** "IVV (also SPY, SPX), IJH": the covered funds and the aliases each answers to. */
291
+ const coveredEtfs = (funds: MemberFundsPayload["funds"]) => funds
292
+ .map((fund) => fund.aliases.length ? `${fund.ticker} (also ${fund.aliases.join(", ")})` : fund.ticker).join(", ");
293
+
294
+ /**
295
+ * What `--compare` names. A ticker-like word is an ETF when MEMB has its
296
+ * holdings file, else a 13F manager only by its exact name; it is never
297
+ * matched to a manager by a partial name (SPY is not Spyglass Capital).
298
+ * Anything else, a CIK or a longer name, is a 13F manager as before.
299
+ */
300
+ async function resolveComparison(
301
+ text: string,
302
+ args: HeadlessPaneLoadArgs,
303
+ ctx: HeadlessPaneContext,
304
+ dependencies: Required<ThirteenFHeadlessDependencies>,
305
+ ): Promise<OverlapComparison> {
306
+ if (isCikQuery(text) || !TICKER_WORD.test(text)) return { kind: "fund", ...await resolveFund(text, args, ctx, dependencies) };
307
+ const symbol = text.replace(/^\$/, "").toUpperCase();
308
+ let funds: MemberFundsPayload["funds"] | null = null;
309
+ let failure = "";
310
+ try {
311
+ funds = await dependencies.loadEtfFunds(ctx);
312
+ } catch (error) {
313
+ if (ctx.signal.aborted) throw error;
314
+ failure = error instanceof Error ? error.message : String(error);
315
+ }
316
+ const etf = funds ? coveredFund(funds, symbol) : undefined;
317
+ if (etf) return { kind: "etf", symbol, ticker: etf.ticker, name: etf.name };
318
+ const manager = await findThirteenFFund(text, (query, limit) => dependencies.loadBrowser("funds", query, limit, args, ctx), { exactOnly: true });
319
+ if (manager) return { kind: "fund", ...manager };
320
+ const etfs = funds ? `${symbol} is not an ETF MEMB covers (covered: ${coveredEtfs(funds)})` : `${symbol} could not be checked against MEMB's ETFs (${failure})`;
321
+ throw new Error(`${etfs}, and no 13F manager is named "${text}". For a manager, use its CIK or full name.`);
322
+ }
323
+
324
+ const percentText = (value: number) => `${(value * 100).toFixed(1)}%`;
325
+
242
326
  export function createThirteenFHeadless(
243
- dependencies: ThirteenFHeadlessDependencies = defaultDependencies,
327
+ overrides: ThirteenFHeadlessDependencies = defaultDependencies,
244
328
  ): HeadlessPaneDefinition<"rows"> {
329
+ const dependencies: Required<ThirteenFHeadlessDependencies> = { ...defaultDependencies, ...overrides };
245
330
  return {
246
331
  shape: "rows",
247
332
  freshness: { ...SEC_FILINGS, basis: "13F filings", observedKey: "filedAsOfDate" },
333
+ discovery: { limitations: [THIRTEENF_LIMITS] },
248
334
  argument: {
249
335
  kind: "free-text",
250
336
  placeholder: "fund, ticker, or CIK",
@@ -252,9 +338,10 @@ export function createThirteenFHeadless(
252
338
  optional: true,
253
339
  },
254
340
  options: [
255
- { key: "rank", description: "Crowding order.", type: "enum", values: [{ value: "new" }, { value: "exits" }, { value: "increases" }, { value: "decreases" }], defaultValue: "new" },
256
- { key: "compare", description: "Second fund name or CIK for overlap.", type: "string" },
257
- { key: "offset", description: "Fund offset for ticker-holdings.", type: "integer", defaultValue: 0, minimum: 0, maximum: 100000 },
341
+ // No defaults on view-specific options, so a flag the view does not use can be named as ignored.
342
+ { key: "rank", description: "Crowding order (crowding view; new when left out).", type: "enum", values: [{ value: "new" }, { value: "exits" }, { value: "increases" }, { value: "decreases" }] },
343
+ { key: "compare", description: "Second fund name or CIK, or an ETF ticker MEMB covers such as SPY; implies the overlap view.", type: "string" },
344
+ { key: "offset", description: "Fund offset for ticker-holdings (0 when left out).", type: "integer", minimum: 0, maximum: 100000 },
258
345
  {
259
346
  key: "view",
260
347
  description: "Fund browser mode or detail tab.",
@@ -287,20 +374,80 @@ export function createThirteenFHeadless(
287
374
  async load(args, ctx) {
288
375
  const query = typeof args.argument === "string" ? args.argument.trim() : "";
289
376
  const requestedView = String(args.options.view) as HeadlessThirteenFView;
377
+ const compare = typeof args.options.compare === "string" ? args.options.compare.trim() : "";
378
+ if (compare && requestedView !== "auto" && requestedView !== "overlap") {
379
+ throw new Error(`--compare is for the overlap view; --view ${requestedView} does not use it. Drop --view, or use --view overlap.`);
380
+ }
290
381
  // A ticker's holders with their positions, not the holders' whole books.
291
- const view = requestedView !== "auto" ? requestedView
292
- : isCikQuery(query) ? "holdings"
293
- : inferBrowserTabFromQuery(query) === "byTicker" ? "ticker-holdings"
294
- : requestedView;
382
+ const view = compare ? "overlap"
383
+ : requestedView !== "auto" ? requestedView
384
+ : isCikQuery(query) ? "holdings"
385
+ : inferBrowserTabFromQuery(query) === "byTicker" ? "ticker-holdings"
386
+ : requestedView;
387
+ // A flag the view does not use is named, never dropped without a word.
388
+ const flagNotices = [
389
+ compare && requestedView === "auto" ? "--compare implies --view overlap" : "",
390
+ args.options.rank != null && view !== "crowding" ? "--rank orders --view crowding only; ignored here" : "",
391
+ args.options.offset != null && view !== "ticker-holdings" ? "--offset pages a ticker's holders only; ignored here" : "",
392
+ query && (view === "latest" || view === "performance") ? `--view ${view} lists every manager; "${query}" is not used` : "",
393
+ ].filter(Boolean);
295
394
  const limit = Number(args.options.limit);
296
395
  if (view === "overlap") {
396
+ if (!compare) throw new Error(`13F overlap compares two holdings: add --compare <fund name, CIK or ETF ticker>, as in fn 13F ${query || "<fund or CIK>"} --compare SPY.`);
397
+ if (!query) throw new Error("13F overlap needs a fund name or CIK first: fn 13F <fund or CIK> --compare <fund, CIK or ETF ticker>.");
297
398
  const fund = await resolveFund(query, args, ctx, dependencies);
298
- const other = await resolveFund(String(args.options.compare ?? ""), args, ctx, dependencies);
399
+ const other = await resolveComparison(compare, args, ctx, dependencies);
400
+ if (other.kind === "etf") {
401
+ const [first, etf] = await Promise.all([dependencies.loadDetail(fund.cik, fund.name, args, ctx), dependencies.loadEtfHoldings(other.ticker, ctx)]);
402
+ const overlap = buildManagerEtfOverlap(first, etf.members);
403
+ const period = first.latestForm?.periodOfReport ?? null;
404
+ const filed = first.latestForm?.filedAsOfDate ?? null;
405
+ const rows = overlap?.rows ?? [];
406
+ const cut = cutText(rows.length, limit, "positions");
407
+ const missing = overlap?.missing ?? [];
408
+ const missingNames = missing.slice(0, 5).map((row) => `${row.ticker || row.issuer} ${weight(row.weight)}`).join(", ");
409
+ const leftOut = overlap ? [overlap.leftOut.options ? `${overlap.leftOut.options} option line${overlap.leftOut.options === 1 ? "" : "s"}` : "", overlap.leftOut.principal ? `${overlap.leftOut.principal} principal-amount line${overlap.leftOut.principal === 1 ? "" : "s"}` : ""].filter(Boolean) : [];
410
+ const etfWeight = (value: unknown, row: Record<string, unknown>) => row.etfWeight == null ? "no ticker" : value === 0 ? "not held" : weight(value);
411
+ return {
412
+ columns: [{ key: "ticker", header: "Ticker" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "13F weight", align: "right", format: weight }, { key: "etfWeight", header: `${other.symbol} weight`, align: "right", format: etfWeight }, { key: "shared", header: "Shared", align: "right", format: weight }],
413
+ rows: rows.slice(0, limit).map((row) => ({ ...row })),
414
+ errors: [
415
+ ...(first.warnings ?? []),
416
+ ...(first.latestReport?.complete === false ? [`The 13F for ${period} did not load completely; weights cover the lines that did.`] : []),
417
+ ...(etf.stale ? [`The ${other.ticker} holdings file is stale.`] : []),
418
+ ...(!overlap ? ["No share positions or ETF weights to compare."] : []),
419
+ ],
420
+ freshness: { source: "SEC EDGAR and Gloom Cloud", ...(period ? { asOf: period } : {}) },
421
+ metadata: {
422
+ view, comparedWith: "etf", firstFund: first.name, cik: first.cik, secondFund: other.symbol,
423
+ etf: { symbol: other.symbol, ticker: other.ticker, name: other.name, asOf: etf.asOf },
424
+ comparedPeriod: period, filed,
425
+ overlap: overlap?.overlap ?? null, activeShare: overlap?.activeShare ?? null,
426
+ missing: missing.map((row) => ({ ticker: row.ticker || null, issuer: row.issuer, weight: row.weight, reason: row.etfWeight == null ? "no ticker" : "not held" })),
427
+ missingWeight: overlap?.missingWeight ?? null,
428
+ leftOut: overlap?.leftOut ?? null,
429
+ shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit,
430
+ notices: [
431
+ ...flagNotices,
432
+ `${other.symbol} read as an ETF: ${other.name} holdings${other.ticker !== other.symbol ? ` (${other.ticker} file)` : ""}, as fn MEMB ${other.symbol} shows`,
433
+ ...(overlap ? [`Overlap ${percentText(overlap.overlap)} (sum of the smaller weight per name) | Active share ${percentText(overlap.activeShare)}`] : []),
434
+ [
435
+ period ? `Quarter compared: ${filingDayText(period)}${filed ? `, filed ${filingDayText(filed)}` : ""}` : "",
436
+ `${other.symbol} holdings as of ${filingDayText(etf.asOf.slice(0, 10))}`,
437
+ leftOut.length ? `13F weights leave out ${leftOut.join(" and ")}` : "",
438
+ ].filter(Boolean).join(" | "),
439
+ ...(overlap ? [missing.length ? `Not in ${other.symbol}: ${missing.length} of ${rows.length} positions, ${percentText(overlap.missingWeight)} of the 13F | ${missingNames}${missing.length > 5 ? ", ..." : ""}` : `${other.symbol} holds every position in the 13F`] : []),
440
+ ...(cut ? [`${cut[0]!.toUpperCase()}${cut.slice(1)}`] : []),
441
+ ].filter(Boolean),
442
+ },
443
+ };
444
+ }
299
445
  const [first, second] = await Promise.all([dependencies.loadDetail(fund.cik, fund.name, args, ctx), dependencies.loadDetail(other.cik, other.name, args, ctx)]);
300
446
  const comparedPeriod = overlapPeriod(first, second);
301
447
  const rows = buildFundOverlap(first, second);
302
448
  const cut = cutText(rows.length, limit, "positions");
303
- return { columns: [{ key: "ticker", header: "Ticker" }, { key: "type", header: "Type" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "First weight", align: "right", format: weight }, { key: "comparedWeight", header: "Second weight", align: "right", format: weight }], rows: rows.slice(0, limit).map(row => ({ ...row })), errors: [...(first.warnings ?? []), ...(second.warnings ?? []), ...(!comparedPeriod ? ["No reporting quarter is loaded for both funds."] : [])], metadata: { view, firstFund: first.name, secondFund: second.name, firstPeriod: first.latestForm?.periodOfReport ?? null, secondPeriod: second.latestForm?.periodOfReport ?? null, comparedPeriod, shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [[comparedPeriod ? `Quarter compared: ${comparedPeriod}` : "", cut].filter(Boolean).join(" | ")].filter(Boolean) } };
449
+ const read = `${compare} read as the 13F manager ${second.name} (CIK ${second.cik})`;
450
+ return { columns: [{ key: "ticker", header: "Ticker" }, { key: "type", header: "Type" }, { key: "issuer", header: "Issuer" }, { key: "weight", header: "First weight", align: "right", format: weight }, { key: "comparedWeight", header: "Second weight", align: "right", format: weight }], rows: rows.slice(0, limit).map(row => ({ ...row })), errors: [...(first.warnings ?? []), ...(second.warnings ?? []), ...(!comparedPeriod ? ["No reporting quarter is loaded for both funds."] : [])], metadata: { view, comparedWith: "fund", firstFund: first.name, secondFund: second.name, firstPeriod: first.latestForm?.periodOfReport ?? null, secondPeriod: second.latestForm?.periodOfReport ?? null, comparedPeriod, shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [...flagNotices, read, [comparedPeriod ? `Quarter compared: ${comparedPeriod}` : "", cut].filter(Boolean).join(" | ")].filter(Boolean) } };
304
451
  }
305
452
  if (view === "crowding") {
306
453
  const { rows: sourceRows, ...metadata } = await loadCrowding(ctx.signal);
@@ -314,7 +461,7 @@ export function createThirteenFHeadless(
314
461
  const columns: HeadlessPaneColumn[] = [{ key: "ticker", header: "Ticker" }, { key: "issuer", header: "Issuer" }, { key: "type", header: "Type" }, { key: "holderCount", header: "Funds", align: "right" }, { key: "newCount", header: "New", align: "right" }, { key: "exitCount", header: "Exits", align: "right" }, { key: "weightChange", header: "Weight change", align: "right", format: weightPoints }, { key: "comparedFunds", header: "Compared", align: "right" }, { key: "totalValue", header: "Value (USD)", align: "right", format: money }];
315
462
  const cut = cutText(rows.length, limit, "securities");
316
463
  return { columns: focus ? [{ key: "rank", header: "Rank", align: "right" }, ...columns] : columns, rows: rows.slice(0, limit).map(row => ({ ...row })),
317
- metadata: { ...metadata, view, rank, ...(ticker ? { ticker, found: rows.length > 0, rankedSecurities: ranked.length } : {}), shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [[sample, cut].filter(Boolean).join(" | "), ...(focus ? [focus.notice] : [])] },
464
+ metadata: { ...metadata, view, rank, ...(ticker ? { ticker, found: rows.length > 0, rankedSecurities: ranked.length } : {}), shown: Math.min(rows.length, limit), total: rows.length, truncated: rows.length > limit, notices: [...flagNotices, [sample, cut].filter(Boolean).join(" | "), ...(focus ? [focus.notice] : [])] },
318
465
  freshness: { asOf: metadata.period }, errors: metadata.warnings };
319
466
  }
320
467
  let holdings: TickerHoldings | null = null;
@@ -336,9 +483,11 @@ export function createThirteenFHeadless(
336
483
  const { rows, ...metadata } = holdings;
337
484
  const offset = Number(args.options.offset ?? 0);
338
485
  const summary = summarizeTickerHoldings({ ...metadata, offset, limit, loaded: rows });
486
+ const shown = rows.slice(0, limit).map(row => ({ ...row }));
339
487
  return {
340
- columns: [{ key: "fund", header: "Fund" }, { key: "cik", header: "CIK" }, { key: "type", header: "Type" }, { key: "value", header: "Value (USD)", align: "right", format: money }, { key: "shares", header: "Shares", align: "right", format: shares }, { key: "weight", header: "13F weight", align: "right", format: weight }, { key: "action", header: "Action" }],
341
- rows: rows.slice(0, limit).map(row => ({ ...row })),
488
+ columns: [{ key: "fund", header: "Fund" }, { key: "cik", header: "CIK" }, TYPE_COLUMN, { key: "value", header: "Value (USD)", align: "right", format: money }, { key: "shares", header: "Shares", align: "right", format: shares }, { key: "weight", header: "13F weight", align: "right", format: weight }, { key: "action", header: "Action" }],
489
+ rows: shown,
490
+ notes: positionNotes(shown),
342
491
  metadata: {
343
492
  ...metadata,
344
493
  view,
@@ -353,7 +502,7 @@ export function createThirteenFHeadless(
353
502
  totalValue: summary.shownValue,
354
503
  valueScope: "shown funds",
355
504
  valueBasis: "as reported at period end",
356
- notices: summary.notices,
505
+ notices: [...flagNotices, ...summary.notices],
357
506
  },
358
507
  freshness: { asOf: metadata.period },
359
508
  errors: metadata.warnings,
@@ -370,6 +519,8 @@ export function createThirteenFHeadless(
370
519
  .slice(0, limit)
371
520
  .map((row) => ({ ...row }));
372
521
  const cut = cutText(all.length, limit, "filings");
522
+ const shownFilings = new Set(rows.map((row) => row.accessionNumber));
523
+ const restated = restatedValuesText(detail.forms.filter((form) => shownFilings.has(form.accessionNumber)));
373
524
  return {
374
525
  columns: FILING_COLUMNS,
375
526
  rows,
@@ -382,7 +533,7 @@ export function createThirteenFHeadless(
382
533
  shown: rows.length,
383
534
  total: all.length,
384
535
  truncated: all.length > limit,
385
- notices: [[`CIK ${detail.cik}`, cut].filter(Boolean).join(" | ")],
536
+ notices: [...flagNotices, [`CIK ${detail.cik}`, cut].filter(Boolean).join(" | "), ...(restated ? [restated] : [])],
386
537
  },
387
538
  };
388
539
  }
@@ -391,7 +542,17 @@ export function createThirteenFHeadless(
391
542
  DEFAULT_HOLDING_SORT,
392
543
  );
393
544
  const previousPeriod = detail.previousForm?.periodOfReport ?? null;
545
+ const comparable = hasComparable13FQuarter(detail);
546
+ const filed = detail.latestForm?.filedAsOfDate || null;
547
+ const quartersBehind = quartersBehindLatest(latestPeriod);
394
548
  const cut = cutText(all.length, limit, "positions, exits included");
549
+ // Values, weights and Est P&L read both compared quarters' filings.
550
+ const reportForms = (report: typeof detail.latestReport, form: typeof detail.latestForm) =>
551
+ report?.filings ?? (form ? [form] : []);
552
+ const restated = restatedValuesText([
553
+ ...reportForms(detail.latestReport, detail.latestForm),
554
+ ...(comparable ? reportForms(detail.previousReport, detail.previousForm) : []),
555
+ ]);
395
556
  const rows = all
396
557
  .slice(0, limit)
397
558
  .map((row) => ({
@@ -403,22 +564,33 @@ export function createThirteenFHeadless(
403
564
  columns: HOLDING_COLUMNS,
404
565
  rows,
405
566
  ...(detail.warnings?.length ? { errors: detail.warnings } : {}),
406
- // Positions as of the quarter they report; the rows carry no filing date.
407
- ...(latestPeriod ? { freshness: { asOf: latestPeriod } } : {}),
567
+ notes: positionNotes(rows),
568
+ // Dated by the filing that made the positions public, with the quarter they report beside it.
569
+ ...(latestPeriod ? { freshness: {
570
+ asOf: filed ?? latestPeriod,
571
+ basis: `13F filing for the quarter ended ${filingDayText(latestPeriod)}`,
572
+ } } : {}),
408
573
  metadata: {
409
574
  view,
410
575
  cik: detail.cik,
411
576
  fund: detail.name,
412
577
  latestPeriod,
578
+ latestFiled: filed,
579
+ filingLagDays: filingLagDays(latestPeriod, filed),
580
+ quartersBehind,
413
581
  previousPeriod,
414
582
  shown: rows.length,
415
583
  total: all.length,
416
584
  truncated: all.length > limit,
417
585
  notices: [
418
- [`CIK ${detail.cik}`, periodText(latestPeriod, hasComparable13FQuarter(detail) ? previousPeriod : null), AS_FILED_VALUE].filter(Boolean).join(" | "),
586
+ ...flagNotices,
587
+ [`CIK ${detail.cik}`, filedPeriodText(latestPeriod, filed, comparable ? previousPeriod : null)].filter(Boolean).join(" | "),
588
+ AS_FILED_VALUE,
589
+ ...(restated ? [restated] : []),
590
+ ...(isStaleFiling(quartersBehind) ? [staleFilingText(quartersBehind)] : []),
419
591
  ...(cut ? [`${cut[0]!.toUpperCase()}${cut.slice(1)}`] : []),
420
592
  ],
421
- comparisonAvailable: hasComparable13FQuarter(detail),
593
+ comparisonAvailable: comparable,
422
594
  currentFilings: detail.latestReport?.filings.map((form) => form.accessionNumber) ?? [],
423
595
  previousFilings: detail.previousReport?.filings.map((form) => form.accessionNumber) ?? [],
424
596
  currentReportedValue: detail.latestReport?.complete ? detail.latestReport.tableValueTotal : null,
@@ -432,11 +604,18 @@ export function createThirteenFHeadless(
432
604
  const tab = browserTab(view === "ticker-holdings" ? requestedView : view, query);
433
605
  const result = await dependencies.loadBrowser(tab, query, limit, args, ctx);
434
606
  const more = result.hasMore || result.rows.length > limit;
607
+ const browserRows = sortBrowserRows(result.rows, browserSortFor(DEFAULT_BROWSER_SORT, tab)).slice(0, limit);
608
+ // A search finds managers that stopped filing; say which, since the Period column alone reads like any other.
609
+ const stale = tab === "funds"
610
+ ? browserRows.flatMap((row) => {
611
+ const quarters = quartersBehindLatest(row.periodOfReport);
612
+ return isStaleFiling(quarters) ? [{ name: row.name, quarters }] : [];
613
+ })
614
+ : [];
435
615
  return {
436
616
  columns: result.rows[0]?.priorReturns?.length ? [...BROWSER_COLUMNS.filter(column => !["filedAsOfDate", "tableEntryTotal"].includes(column.key)), ...result.rows[0].priorReturns.map((point, index) => ({ key: `return${index + 1}`, header: point.quarter, align: "right" as const, format: (value: unknown) => formatRawPercentMaybe(typeof value === "number" ? value : null) }))]
437
617
  : tab === "performance" ? BROWSER_COLUMNS : BROWSER_COLUMNS.filter(column => column.key !== "estQuarterReturn"),
438
- rows: sortBrowserRows(result.rows, browserSortFor(DEFAULT_BROWSER_SORT, tab))
439
- .slice(0, limit)
618
+ rows: browserRows
440
619
  .map((row) => ({ ...row, ...Object.fromEntries((row.priorReturns ?? []).map((point, index) => [`return${index + 1}`, point.value])) })),
441
620
  ...(result.warning ? { errors: [result.warning] } : {}),
442
621
  metadata: {
@@ -447,9 +626,11 @@ export function createThirteenFHeadless(
447
626
  hasMore: result.hasMore ?? false,
448
627
  shown: Math.min(result.rows.length, limit),
449
628
  truncated: more,
450
- notices: more
451
- ? [[`Showing the first ${Math.min(result.rows.length, limit)}`, limit < THIRTEENF_MAX_LIMIT ? `more: --limit ${THIRTEENF_MAX_LIMIT}` : ""].filter(Boolean).join(" | ")]
452
- : [],
629
+ notices: [
630
+ ...flagNotices,
631
+ ...(more ? [[`Showing the first ${Math.min(result.rows.length, limit)}`, limit < THIRTEENF_MAX_LIMIT ? `more: --limit ${THIRTEENF_MAX_LIMIT}` : ""].filter(Boolean).join(" | ")] : []),
632
+ ...(stale.length ? [staleFundsText(stale)] : []),
633
+ ],
453
634
  },
454
635
  };
455
636
  },