alphacouncil-agent 0.9.2 → 1.0.0

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 (493) hide show
  1. package/.claude/commands/alpha.md +22 -3
  2. package/.claude-plugin/marketplace.json +3 -3
  3. package/.claude-plugin/plugin.json +2 -2
  4. package/.codex-plugin/plugin.json +4 -4
  5. package/.grok/commands/alpha.md +22 -3
  6. package/.opencode/command/alpha.md +22 -3
  7. package/AGENTS.md +42 -4
  8. package/CHANGELOG.md +164 -0
  9. package/CLAUDE.md +59 -7
  10. package/README.ja.md +25 -11
  11. package/README.md +44 -12
  12. package/README.zh-CN.md +37 -12
  13. package/commands/alpha.md +22 -3
  14. package/data/authored/core-seats.mjs +808 -0
  15. package/data/authored/growth-seats.mjs +581 -0
  16. package/data/authored/index.mjs +114 -0
  17. package/data/authored/quant-seats.mjs +564 -0
  18. package/data/authored/value-seats.mjs +663 -0
  19. package/data/build-profile.v1.json +2 -1
  20. package/data/council-evaluation-protocol.v1.json +7 -4
  21. package/data/master-selector-method-locales.v1.mjs +296 -0
  22. package/data/persona-v3-ai-assisted-solo-profile.v1.json +2 -2
  23. package/data/persona-v3-build-specs.v1.mjs +60 -3
  24. package/docs/INSTALL.md +43 -6
  25. package/docs/personas.md +2 -1
  26. package/docs/plans/v1.0-roadmap.md +487 -0
  27. package/docs/releases/v0.9.3.md +86 -0
  28. package/docs/releases/v0.9.4.md +79 -0
  29. package/docs/releases/v0.9.5.md +96 -0
  30. package/docs/releases/v1.0.0.md +164 -0
  31. package/docs/report-contract.md +75 -2
  32. package/knowledge/ai-assisted-solo/experiments/runs/a.json +13 -13
  33. package/knowledge/ai-assisted-solo/experiments/runs/b.json +2 -2
  34. package/knowledge/ai-assisted-solo/experiments/runs/c.json +2 -2
  35. package/knowledge/ai-assisted-solo/experiments/runs/d13.json +126 -126
  36. package/knowledge/ai-assisted-solo/experiments/runs/d26.json +274 -254
  37. package/knowledge/ai-assisted-solo/experiments/runs/e-d13.json +129 -129
  38. package/knowledge/ai-assisted-solo/experiments/runs/e-d26.json +277 -257
  39. package/knowledge/ai-assisted-solo/experiments/runs/h_ai_reference.json +278 -258
  40. package/knowledge/ai-assisted-solo/experiments/simulation-input.json +7278 -556
  41. package/knowledge/ai-assisted-solo/experiments/simulation-manifest.json +22 -22
  42. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_ackman/reviews/{change_value_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  43. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_ackman/reviews/{power_map.ai-review.json → owner_earnings_yield.ai-review.json} +46 -46
  44. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_aschenbrenner/reviews/{compute_power_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  45. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_aschenbrenner/reviews/{timeline_reverse_valuation.ai-review.json → price_implied_cash_yield.ai-review.json} +46 -46
  46. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_asness/reviews/{crowding_cost_stress.ai-review.json → nominal_earnings_yield_gap.ai-review.json} +49 -49
  47. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_asness/reviews/{factor_decomposer.ai-review.json → real_earnings_yield_gap.ai-review.json} +49 -49
  48. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/expected_return_over_long_bond.ai-review.json +277 -0
  49. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/fundamental_expected_return.ai-review.json +277 -0
  50. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_buffett/reviews/{incremental_returns.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  51. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_buffett/reviews/{owner_earnings_rebuilder.ai-review.json → owner_earnings_yield.ai-review.json} +46 -46
  52. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_burry/reviews/{mispricing_carry.ai-review.json → net_current_asset_surplus_per_share.ai-review.json} +49 -49
  53. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_burry/reviews/{capital_structure_reader.ai-review.json → net_current_asset_value_per_share.ai-review.json} +46 -46
  54. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_cathie_wood/reviews/{cost_adoption_curve.ai-review.json → current_cash_yield.ai-review.json} +46 -46
  55. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_cathie_wood/reviews/{capture_valuation_bridge.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  56. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_dalio/reviews/{debt_driver_stress.ai-review.json → policy_real_rate.ai-review.json} +49 -49
  57. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_dalio/reviews/{regime_classifier.ai-review.json → real_curve_slope.ai-review.json} +49 -49
  58. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_damodaran/reviews/{reverse_valuation.ai-review.json → implied_equity_risk_premium.ai-review.json} +49 -49
  59. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_damodaran/reviews/{story_dcf.ai-review.json → premium_versus_long_run_average.ai-review.json} +49 -49
  60. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_druckenmiller/reviews/{liquidity_revision_map.ai-review.json → liquidity_curve_impulse.ai-review.json} +49 -49
  61. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_druckenmiller/reviews/{inflection_payoff.ai-review.json → policy_real_rate.ai-review.json} +49 -49
  62. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{opportunity_cost.ai-review.json → five_year_opportunity_cost.ai-review.json} +46 -46
  63. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{user_value_evidence.ai-review.json → margin_retention.ai-review.json} +46 -46
  64. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_fisher/reviews/{research_productivity.ai-review.json → margin_retention.ai-review.json} +46 -46
  65. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_fisher/reviews/{scuttlebutt_graph.ai-review.json → reinvestment_spread.ai-review.json} +49 -49
  66. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_forensic_short/reviews/{borrow_catalyst.ai-review.json → cash_conversion_gap.ai-review.json} +49 -49
  67. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_forensic_short/reviews/{accounting_rebuilder.ai-review.json → cash_cover_of_leverage.ai-review.json} +46 -46
  68. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_graham/reviews/{asset_floor.ai-review.json → defensive_hurdle_base.ai-review.json} +46 -46
  69. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_graham/reviews/{normalized_earnings.ai-review.json → half_normalised_earnings_yield.ai-review.json} +46 -46
  70. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_jhunjhunwala/reviews/{penetration_liquidity.ai-review.json → cash_quality_gap.ai-review.json} +49 -49
  71. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_jhunjhunwala/reviews/{promoter_governance.ai-review.json → real_structural_growth.ai-review.json} +49 -49
  72. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_klarman/reviews/{recovery_waterfall.ai-review.json → downside_asset_coverage.ai-review.json} +46 -46
  73. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_klarman/reviews/{cash_catalyst_compare.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  74. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_li_lu/reviews/{promise_integrity_ledger.ai-review.json → cash_backed_decade_return.ai-review.json} +46 -46
  75. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_li_lu/reviews/{ten_year_return_bridge.ai-review.json → decade_return_over_long_bond.ai-review.json} +49 -49
  76. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_lynch/reviews/{story_numbers_check.ai-review.json → growth_justified_capitalisation.ai-review.json} +46 -46
  77. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_lynch/reviews/{category_classifier.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  78. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_marks/reviews/{cycle_temperature.ai-review.json → credit_cycle_position.ai-review.json} +49 -49
  79. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_marks/reviews/{implied_expectations.ai-review.json → equity_over_corporate_debt.ai-review.json} +49 -49
  80. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_munger/reviews/{failure_path_graph.ai-review.json → debt_service_cushion.ai-review.json} +49 -49
  81. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_munger/reviews/{incentive_map.ai-review.json → reported_earnings_cash_gap.ai-review.json} +49 -49
  82. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_natenberg/reviews/{surface_builder.ai-review.json → normalised_skew.ai-review.json} +46 -46
  83. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_natenberg/reviews/{greeks_payoff.ai-review.json → round_trip_cost.ai-review.json} +46 -46
  84. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_pabrai/reviews/{downside_floor.ai-review.json → downside_floor_coverage.ai-review.json} +46 -46
  85. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_pabrai/reviews/{discrete_payoff.ai-review.json → market_capitalisation.ai-review.json} +46 -46
  86. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{oos_cost_test.ai-review.json → absolute_session_move.ai-review.json} +42 -42
  87. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{leakage_audit.ai-review.json → session_move_over_implied.ai-review.json} +46 -46
  88. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_sinclair/reviews/{realized_vol_forecast.ai-review.json → round_trip_cost.ai-review.json} +46 -46
  89. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_sinclair/reviews/{net_edge_sizer.ai-review.json → volatility_per_unit_of_width.ai-review.json} +46 -46
  90. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reversal_monitor.ai-review.json → credit_cycle_position.ai-review.json} +49 -49
  91. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reflexivity_graph.ai-review.json → financing_burden.ai-review.json} +46 -46
  92. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_taleb/reviews/{tail_friction.ai-review.json → debt_service_cushion.ai-review.json} +49 -49
  93. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_taleb/reviews/{payoff_ruin.ai-review.json → normalised_skew.ai-review.json} +46 -46
  94. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{edge_recalculator.ai-review.json → edge_per_unit_of_volatility.ai-review.json} +46 -46
  95. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{fractional_kelly.ai-review.json → net_edge.ai-review.json} +49 -49
  96. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/review-manifest.json +288 -270
  97. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-adjudications/index.json +2 -2
  98. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-extractions/index.json +2 -2
  99. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-skeptic-reviews/index.json +2 -2
  100. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-source-prereviews/index.json +6 -2
  101. package/knowledge/solo-test/masters/master_ackman/decision_policy.json +122 -11
  102. package/knowledge/solo-test/masters/master_ackman/doctrine.jsonl +2 -2
  103. package/knowledge/solo-test/masters/master_ackman/manifest.json +27 -10
  104. package/knowledge/solo-test/masters/master_ackman/provisional-index.json +3 -3
  105. package/knowledge/solo-test/masters/master_ackman/sources.jsonl +1 -1
  106. package/knowledge/solo-test/masters/master_ackman/tools.json +56 -30
  107. package/knowledge/solo-test/masters/master_aschenbrenner/decision_policy.json +101 -10
  108. package/knowledge/solo-test/masters/master_aschenbrenner/doctrine.jsonl +2 -2
  109. package/knowledge/solo-test/masters/master_aschenbrenner/manifest.json +26 -8
  110. package/knowledge/solo-test/masters/master_aschenbrenner/provisional-index.json +3 -3
  111. package/knowledge/solo-test/masters/master_aschenbrenner/sources.jsonl +1 -1
  112. package/knowledge/solo-test/masters/master_aschenbrenner/tools.json +56 -30
  113. package/knowledge/solo-test/masters/master_asness/decision_policy.json +89 -10
  114. package/knowledge/solo-test/masters/master_asness/doctrine.jsonl +2 -2
  115. package/knowledge/solo-test/masters/master_asness/manifest.json +25 -8
  116. package/knowledge/solo-test/masters/master_asness/provisional-index.json +3 -3
  117. package/knowledge/solo-test/masters/master_asness/sources.jsonl +1 -1
  118. package/knowledge/solo-test/masters/master_asness/tools.json +56 -30
  119. package/knowledge/solo-test/masters/master_bogle/counterfactuals.jsonl +0 -0
  120. package/knowledge/solo-test/masters/master_bogle/decision_cases.jsonl +0 -0
  121. package/knowledge/solo-test/masters/master_bogle/decision_policy.json +170 -0
  122. package/knowledge/solo-test/masters/master_bogle/doctrine.jsonl +14 -0
  123. package/knowledge/solo-test/masters/master_bogle/evaluation/calibration_cases.jsonl +0 -0
  124. package/knowledge/solo-test/masters/master_bogle/evaluation/experiments.json +5 -0
  125. package/knowledge/solo-test/masters/master_bogle/evaluation/golden_cases.jsonl +0 -0
  126. package/knowledge/solo-test/masters/master_bogle/evaluation/pairwise_cases.jsonl +0 -0
  127. package/knowledge/solo-test/masters/master_bogle/failures.jsonl +0 -0
  128. package/knowledge/solo-test/masters/master_bogle/manifest.json +141 -0
  129. package/knowledge/solo-test/masters/master_bogle/memory_policy.json +5 -0
  130. package/knowledge/solo-test/masters/master_bogle/provisional-index.json +41 -0
  131. package/knowledge/solo-test/masters/master_bogle/research_policy.json +11 -0
  132. package/knowledge/solo-test/masters/master_bogle/sources.jsonl +1 -0
  133. package/knowledge/solo-test/masters/master_bogle/tools.json +120 -0
  134. package/knowledge/solo-test/masters/master_bogle/voice.en.md +7 -0
  135. package/knowledge/solo-test/masters/master_bogle/voice.zh.md +7 -0
  136. package/knowledge/solo-test/masters/master_buffett/decision_policy.json +102 -11
  137. package/knowledge/solo-test/masters/master_buffett/doctrine.jsonl +2 -2
  138. package/knowledge/solo-test/masters/master_buffett/manifest.json +24 -8
  139. package/knowledge/solo-test/masters/master_buffett/provisional-index.json +3 -3
  140. package/knowledge/solo-test/masters/master_buffett/sources.jsonl +1 -1
  141. package/knowledge/solo-test/masters/master_buffett/tools.json +55 -29
  142. package/knowledge/solo-test/masters/master_burry/decision_policy.json +102 -12
  143. package/knowledge/solo-test/masters/master_burry/doctrine.jsonl +2 -2
  144. package/knowledge/solo-test/masters/master_burry/manifest.json +26 -10
  145. package/knowledge/solo-test/masters/master_burry/provisional-index.json +3 -3
  146. package/knowledge/solo-test/masters/master_burry/sources.jsonl +1 -1
  147. package/knowledge/solo-test/masters/master_burry/tools.json +56 -30
  148. package/knowledge/solo-test/masters/master_cathie_wood/decision_policy.json +74 -12
  149. package/knowledge/solo-test/masters/master_cathie_wood/doctrine.jsonl +2 -2
  150. package/knowledge/solo-test/masters/master_cathie_wood/manifest.json +26 -10
  151. package/knowledge/solo-test/masters/master_cathie_wood/provisional-index.json +3 -3
  152. package/knowledge/solo-test/masters/master_cathie_wood/sources.jsonl +1 -1
  153. package/knowledge/solo-test/masters/master_cathie_wood/tools.json +56 -30
  154. package/knowledge/solo-test/masters/master_dalio/decision_policy.json +123 -16
  155. package/knowledge/solo-test/masters/master_dalio/doctrine.jsonl +2 -2
  156. package/knowledge/solo-test/masters/master_dalio/manifest.json +24 -8
  157. package/knowledge/solo-test/masters/master_dalio/provisional-index.json +3 -3
  158. package/knowledge/solo-test/masters/master_dalio/sources.jsonl +1 -1
  159. package/knowledge/solo-test/masters/master_dalio/tools.json +56 -30
  160. package/knowledge/solo-test/masters/master_damodaran/decision_policy.json +58 -10
  161. package/knowledge/solo-test/masters/master_damodaran/doctrine.jsonl +2 -2
  162. package/knowledge/solo-test/masters/master_damodaran/manifest.json +23 -8
  163. package/knowledge/solo-test/masters/master_damodaran/provisional-index.json +3 -3
  164. package/knowledge/solo-test/masters/master_damodaran/sources.jsonl +1 -1
  165. package/knowledge/solo-test/masters/master_damodaran/tools.json +54 -28
  166. package/knowledge/solo-test/masters/master_druckenmiller/decision_policy.json +89 -10
  167. package/knowledge/solo-test/masters/master_druckenmiller/doctrine.jsonl +2 -2
  168. package/knowledge/solo-test/masters/master_druckenmiller/manifest.json +25 -8
  169. package/knowledge/solo-test/masters/master_druckenmiller/provisional-index.json +3 -3
  170. package/knowledge/solo-test/masters/master_druckenmiller/sources.jsonl +1 -1
  171. package/knowledge/solo-test/masters/master_druckenmiller/tools.json +55 -29
  172. package/knowledge/solo-test/masters/master_duan_yongping/decision_policy.json +138 -13
  173. package/knowledge/solo-test/masters/master_duan_yongping/doctrine.jsonl +2 -2
  174. package/knowledge/solo-test/masters/master_duan_yongping/manifest.json +31 -11
  175. package/knowledge/solo-test/masters/master_duan_yongping/provisional-index.json +3 -3
  176. package/knowledge/solo-test/masters/master_duan_yongping/sources.jsonl +1 -1
  177. package/knowledge/solo-test/masters/master_duan_yongping/tools.json +82 -30
  178. package/knowledge/solo-test/masters/master_fisher/decision_policy.json +102 -11
  179. package/knowledge/solo-test/masters/master_fisher/doctrine.jsonl +2 -2
  180. package/knowledge/solo-test/masters/master_fisher/manifest.json +27 -10
  181. package/knowledge/solo-test/masters/master_fisher/provisional-index.json +3 -3
  182. package/knowledge/solo-test/masters/master_fisher/sources.jsonl +1 -1
  183. package/knowledge/solo-test/masters/master_fisher/tools.json +58 -32
  184. package/knowledge/solo-test/masters/master_forensic_short/decision_policy.json +93 -14
  185. package/knowledge/solo-test/masters/master_forensic_short/doctrine.jsonl +2 -2
  186. package/knowledge/solo-test/masters/master_forensic_short/manifest.json +20 -8
  187. package/knowledge/solo-test/masters/master_forensic_short/provisional-index.json +3 -3
  188. package/knowledge/solo-test/masters/master_forensic_short/sources.jsonl +1 -1
  189. package/knowledge/solo-test/masters/master_forensic_short/tools.json +53 -27
  190. package/knowledge/solo-test/masters/master_graham/decision_policy.json +103 -12
  191. package/knowledge/solo-test/masters/master_graham/doctrine.jsonl +2 -2
  192. package/knowledge/solo-test/masters/master_graham/manifest.json +26 -8
  193. package/knowledge/solo-test/masters/master_graham/provisional-index.json +3 -3
  194. package/knowledge/solo-test/masters/master_graham/sources.jsonl +1 -1
  195. package/knowledge/solo-test/masters/master_graham/tools.json +67 -28
  196. package/knowledge/solo-test/masters/master_jhunjhunwala/decision_policy.json +77 -12
  197. package/knowledge/solo-test/masters/master_jhunjhunwala/doctrine.jsonl +2 -2
  198. package/knowledge/solo-test/masters/master_jhunjhunwala/manifest.json +25 -10
  199. package/knowledge/solo-test/masters/master_jhunjhunwala/provisional-index.json +3 -3
  200. package/knowledge/solo-test/masters/master_jhunjhunwala/sources.jsonl +1 -1
  201. package/knowledge/solo-test/masters/master_jhunjhunwala/tools.json +54 -28
  202. package/knowledge/solo-test/masters/master_klarman/decision_policy.json +105 -14
  203. package/knowledge/solo-test/masters/master_klarman/doctrine.jsonl +2 -2
  204. package/knowledge/solo-test/masters/master_klarman/manifest.json +22 -6
  205. package/knowledge/solo-test/masters/master_klarman/provisional-index.json +3 -3
  206. package/knowledge/solo-test/masters/master_klarman/sources.jsonl +1 -1
  207. package/knowledge/solo-test/masters/master_klarman/tools.json +55 -29
  208. package/knowledge/solo-test/masters/master_li_lu/decision_policy.json +101 -10
  209. package/knowledge/solo-test/masters/master_li_lu/doctrine.jsonl +2 -2
  210. package/knowledge/solo-test/masters/master_li_lu/manifest.json +27 -10
  211. package/knowledge/solo-test/masters/master_li_lu/provisional-index.json +3 -3
  212. package/knowledge/solo-test/masters/master_li_lu/sources.jsonl +1 -1
  213. package/knowledge/solo-test/masters/master_li_lu/tools.json +58 -32
  214. package/knowledge/solo-test/masters/master_lynch/decision_policy.json +127 -16
  215. package/knowledge/solo-test/masters/master_lynch/doctrine.jsonl +2 -2
  216. package/knowledge/solo-test/masters/master_lynch/manifest.json +28 -10
  217. package/knowledge/solo-test/masters/master_lynch/provisional-index.json +3 -3
  218. package/knowledge/solo-test/masters/master_lynch/sources.jsonl +1 -1
  219. package/knowledge/solo-test/masters/master_lynch/tools.json +67 -28
  220. package/knowledge/solo-test/masters/master_marks/decision_policy.json +71 -9
  221. package/knowledge/solo-test/masters/master_marks/doctrine.jsonl +2 -2
  222. package/knowledge/solo-test/masters/master_marks/manifest.json +25 -10
  223. package/knowledge/solo-test/masters/master_marks/provisional-index.json +3 -3
  224. package/knowledge/solo-test/masters/master_marks/sources.jsonl +1 -1
  225. package/knowledge/solo-test/masters/master_marks/tools.json +54 -28
  226. package/knowledge/solo-test/masters/master_munger/decision_policy.json +141 -16
  227. package/knowledge/solo-test/masters/master_munger/doctrine.jsonl +2 -2
  228. package/knowledge/solo-test/masters/master_munger/manifest.json +24 -10
  229. package/knowledge/solo-test/masters/master_munger/provisional-index.json +3 -3
  230. package/knowledge/solo-test/masters/master_munger/sources.jsonl +1 -1
  231. package/knowledge/solo-test/masters/master_munger/tools.json +52 -26
  232. package/knowledge/solo-test/masters/master_natenberg/decision_policy.json +59 -11
  233. package/knowledge/solo-test/masters/master_natenberg/doctrine.jsonl +2 -2
  234. package/knowledge/solo-test/masters/master_natenberg/manifest.json +23 -10
  235. package/knowledge/solo-test/masters/master_natenberg/provisional-index.json +3 -3
  236. package/knowledge/solo-test/masters/master_natenberg/sources.jsonl +1 -1
  237. package/knowledge/solo-test/masters/master_natenberg/tools.json +50 -24
  238. package/knowledge/solo-test/masters/master_pabrai/decision_policy.json +125 -14
  239. package/knowledge/solo-test/masters/master_pabrai/doctrine.jsonl +2 -2
  240. package/knowledge/solo-test/masters/master_pabrai/manifest.json +22 -6
  241. package/knowledge/solo-test/masters/master_pabrai/provisional-index.json +3 -3
  242. package/knowledge/solo-test/masters/master_pabrai/sources.jsonl +1 -1
  243. package/knowledge/solo-test/masters/master_pabrai/tools.json +55 -29
  244. package/knowledge/solo-test/masters/master_simons/decision_policy.json +59 -11
  245. package/knowledge/solo-test/masters/master_simons/doctrine.jsonl +2 -2
  246. package/knowledge/solo-test/masters/master_simons/manifest.json +22 -8
  247. package/knowledge/solo-test/masters/master_simons/provisional-index.json +3 -3
  248. package/knowledge/solo-test/masters/master_simons/sources.jsonl +1 -1
  249. package/knowledge/solo-test/masters/master_simons/tools.json +43 -30
  250. package/knowledge/solo-test/masters/master_sinclair/decision_policy.json +59 -11
  251. package/knowledge/solo-test/masters/master_sinclair/doctrine.jsonl +2 -2
  252. package/knowledge/solo-test/masters/master_sinclair/manifest.json +22 -10
  253. package/knowledge/solo-test/masters/master_sinclair/provisional-index.json +3 -3
  254. package/knowledge/solo-test/masters/master_sinclair/sources.jsonl +1 -1
  255. package/knowledge/solo-test/masters/master_sinclair/tools.json +54 -28
  256. package/knowledge/solo-test/masters/master_soros/decision_policy.json +98 -10
  257. package/knowledge/solo-test/masters/master_soros/doctrine.jsonl +2 -2
  258. package/knowledge/solo-test/masters/master_soros/manifest.json +24 -11
  259. package/knowledge/solo-test/masters/master_soros/provisional-index.json +3 -3
  260. package/knowledge/solo-test/masters/master_soros/sources.jsonl +1 -1
  261. package/knowledge/solo-test/masters/master_soros/tools.json +54 -28
  262. package/knowledge/solo-test/masters/master_taleb/decision_policy.json +124 -13
  263. package/knowledge/solo-test/masters/master_taleb/doctrine.jsonl +2 -2
  264. package/knowledge/solo-test/masters/master_taleb/manifest.json +23 -9
  265. package/knowledge/solo-test/masters/master_taleb/provisional-index.json +3 -3
  266. package/knowledge/solo-test/masters/master_taleb/sources.jsonl +1 -1
  267. package/knowledge/solo-test/masters/master_taleb/tools.json +50 -24
  268. package/knowledge/solo-test/masters/master_thorp/decision_policy.json +61 -13
  269. package/knowledge/solo-test/masters/master_thorp/doctrine.jsonl +2 -2
  270. package/knowledge/solo-test/masters/master_thorp/manifest.json +25 -10
  271. package/knowledge/solo-test/masters/master_thorp/provisional-index.json +3 -3
  272. package/knowledge/solo-test/masters/master_thorp/sources.jsonl +1 -1
  273. package/knowledge/solo-test/masters/master_thorp/tools.json +56 -30
  274. package/knowledge/solo-test/persona-v3-solo-test-formulas/compilation-manifest.json +290 -264
  275. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/components/tools.json +58 -32
  276. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  277. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
  278. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/components/tools.json +58 -32
  279. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  280. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/price_implied_cash_yield.derived-proxy-evidence.json +76 -0
  281. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/components/tools.json +58 -32
  282. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/nominal_earnings_yield_gap.derived-proxy-evidence.json +76 -0
  283. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/real_earnings_yield_gap.derived-proxy-evidence.json +76 -0
  284. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/components/tools.json +120 -0
  285. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/expected_return_over_long_bond.derived-proxy-evidence.json +77 -0
  286. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/fundamental_expected_return.derived-proxy-evidence.json +76 -0
  287. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/components/tools.json +57 -31
  288. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  289. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
  290. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/components/tools.json +58 -32
  291. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/net_current_asset_surplus_per_share.derived-proxy-evidence.json +77 -0
  292. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/net_current_asset_value_per_share.derived-proxy-evidence.json +76 -0
  293. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/components/tools.json +58 -32
  294. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/current_cash_yield.derived-proxy-evidence.json +76 -0
  295. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  296. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/components/tools.json +58 -32
  297. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
  298. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/real_curve_slope.derived-proxy-evidence.json +76 -0
  299. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/components/tools.json +56 -30
  300. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/implied_equity_risk_premium.derived-proxy-evidence.json +76 -0
  301. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/{reverse_valuation.derived-proxy-evidence.json → premium_versus_long_run_average.derived-proxy-evidence.json} +29 -16
  302. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/components/tools.json +57 -31
  303. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_curve_impulse.derived-proxy-evidence.json +76 -0
  304. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
  305. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/components/tools.json +84 -32
  306. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/five_year_opportunity_cost.derived-proxy-evidence.json +102 -0
  307. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
  308. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/components/tools.json +60 -34
  309. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
  310. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/reinvestment_spread.derived-proxy-evidence.json +76 -0
  311. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/components/tools.json +55 -29
  312. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/{accounting_rebuilder.derived-proxy-evidence.json → cash_conversion_gap.derived-proxy-evidence.json} +28 -15
  313. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/cash_cover_of_leverage.derived-proxy-evidence.json +76 -0
  314. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/components/tools.json +69 -30
  315. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/defensive_hurdle_base.derived-proxy-evidence.json +89 -0
  316. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/half_normalised_earnings_yield.derived-proxy-evidence.json +76 -0
  317. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/components/tools.json +56 -30
  318. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/cash_quality_gap.derived-proxy-evidence.json +76 -0
  319. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/real_structural_growth.derived-proxy-evidence.json +76 -0
  320. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/components/tools.json +57 -31
  321. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/downside_asset_coverage.derived-proxy-evidence.json +76 -0
  322. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  323. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/components/tools.json +60 -34
  324. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/cash_backed_decade_return.derived-proxy-evidence.json +76 -0
  325. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/decade_return_over_long_bond.derived-proxy-evidence.json +76 -0
  326. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/components/tools.json +69 -30
  327. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/growth_justified_capitalisation.derived-proxy-evidence.json +89 -0
  328. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  329. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/components/tools.json +56 -30
  330. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
  331. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/equity_over_corporate_debt.derived-proxy-evidence.json +76 -0
  332. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/components/tools.json +54 -28
  333. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
  334. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/reported_earnings_cash_gap.derived-proxy-evidence.json +76 -0
  335. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/components/tools.json +52 -26
  336. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/{surface_builder.derived-proxy-evidence.json → normalised_skew.derived-proxy-evidence.json} +27 -14
  337. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
  338. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/components/tools.json +57 -31
  339. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor_coverage.derived-proxy-evidence.json +76 -0
  340. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  341. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/components/tools.json +45 -32
  342. package/knowledge/solo-test/persona-v3-solo-test-formulas/{master_natenberg/provisional-derivations/greeks_payoff.derived-proxy-evidence.json → master_simons/provisional-derivations/absolute_session_move.derived-proxy-evidence.json} +17 -17
  343. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/session_move_over_implied.derived-proxy-evidence.json +77 -0
  344. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/components/tools.json +56 -30
  345. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
  346. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/volatility_per_unit_of_width.derived-proxy-evidence.json +76 -0
  347. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/components/tools.json +56 -30
  348. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
  349. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/financing_burden.derived-proxy-evidence.json +76 -0
  350. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/components/tools.json +52 -26
  351. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
  352. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/{tail_friction.derived-proxy-evidence.json → normalised_skew.derived-proxy-evidence.json} +27 -14
  353. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/components/tools.json +58 -32
  354. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_per_unit_of_volatility.derived-proxy-evidence.json +77 -0
  355. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/net_edge.derived-proxy-evidence.json +76 -0
  356. package/mcp/lib/breadth.mjs +122 -0
  357. package/mcp/lib/codex.mjs +3 -3
  358. package/mcp/lib/constants.mjs +76 -25
  359. package/mcp/lib/council-options.mjs +95 -40
  360. package/mcp/lib/council-selection.mjs +95 -9
  361. package/mcp/lib/damodaran.mjs +119 -0
  362. package/mcp/lib/fred.mjs +246 -0
  363. package/mcp/lib/fund-holdings-parsers.mjs +297 -0
  364. package/mcp/lib/fundamentals.mjs +801 -0
  365. package/mcp/lib/funds.mjs +750 -0
  366. package/mcp/lib/gates.mjs +149 -15
  367. package/mcp/lib/grounding.mjs +188 -36
  368. package/mcp/lib/index-aggregate.mjs +718 -0
  369. package/mcp/lib/insider-ownership.mjs +149 -0
  370. package/mcp/lib/instrument-facts.mjs +557 -0
  371. package/mcp/lib/instruments.mjs +191 -0
  372. package/mcp/lib/lang.mjs +109 -2
  373. package/mcp/lib/markdown.mjs +620 -138
  374. package/mcp/lib/master-catalog.mjs +32 -3
  375. package/mcp/lib/orchestrator.mjs +1121 -290
  376. package/mcp/lib/packets.mjs +227 -21
  377. package/mcp/lib/personas/engine.mjs +44 -31
  378. package/mcp/lib/personas-v3/compiler.mjs +2 -0
  379. package/mcp/lib/personas-v3/deterministic-executor.mjs +13 -2
  380. package/mcp/lib/personas-v3/ga-external-evidence.mjs +3 -2
  381. package/mcp/lib/personas-v3/ga-gate.mjs +2 -1
  382. package/mcp/lib/personas-v3/ga-package-evidence.mjs +5 -4
  383. package/mcp/lib/personas-v3/grounding-adapter.mjs +309 -2
  384. package/mcp/lib/personas-v3/loader.mjs +10 -7
  385. package/mcp/lib/personas-v3/production-root.mjs +5 -4
  386. package/mcp/lib/personas-v3/release-formula-evidence.mjs +14 -7
  387. package/mcp/lib/personas-v3/release-source-evidence.mjs +2 -1
  388. package/mcp/lib/personas-v3/releases.mjs +5 -4
  389. package/mcp/lib/personas-v3/runtime-release-integrity.mjs +6 -5
  390. package/mcp/lib/personas-v3/semantic-source-adjudication.mjs +2 -1
  391. package/mcp/lib/personas-v3/semantic-source-extraction.mjs +2 -1
  392. package/mcp/lib/personas-v3/semantic-source-skeptic-review.mjs +2 -1
  393. package/mcp/lib/personas-v3/source-acquisition.mjs +10 -3
  394. package/mcp/lib/personas-v3/source-review-operations.mjs +3 -2
  395. package/mcp/lib/personas-v3/staging.mjs +22 -3
  396. package/mcp/lib/prompts.mjs +119 -2
  397. package/mcp/lib/quotes.mjs +5 -0
  398. package/mcp/lib/rpc.mjs +101 -42
  399. package/mcp/lib/run-store.mjs +28 -3
  400. package/mcp/lib/sec.mjs +32 -0
  401. package/mcp/lib/tables.mjs +11 -0
  402. package/mcp/lib/voice.mjs +122 -0
  403. package/mcp/lib/xbrl-aggregates.mjs +153 -0
  404. package/mcp/lib/xbrl-series.mjs +339 -0
  405. package/mcp/lib/xlsx.mjs +155 -0
  406. package/package.json +5 -5
  407. package/personas/masters/masters-value/bogle.md +145 -0
  408. package/schemas/council-evaluation-protocol-v1.schema.json +2 -2
  409. package/schemas/persona-v3-ai-assisted-solo-profile-v1.schema.json +2 -2
  410. package/schemas/persona-v3-ai-machine-simulation-v1.schema.json +1 -1
  411. package/schemas/persona-v3-build-spec-v1.schema.json +3 -3
  412. package/schemas/persona-v3-release-formula-review-evidence-v1.schema.json +3 -3
  413. package/schemas/persona-v3-release-manifest-v1.schema.json +6 -6
  414. package/schemas/persona-v3-release-source-review-evidence-v1.schema.json +3 -3
  415. package/schemas/persona-v3-tool-graph-v1.schema.json +1 -1
  416. package/schemas/persona-v3.schema.json +37 -2
  417. package/schemas/source-review-batch-v1.schema.json +9 -9
  418. package/scripts/assemble-persona-v3-release.mjs +3 -2
  419. package/scripts/build-persona-v3-solo-test-packs.mjs +6 -8
  420. package/scripts/check-persona-v3-ga.mjs +1 -1
  421. package/scripts/check-persona-v3-production-candidates.mjs +1 -1
  422. package/scripts/compile-persona-v3-formulas.mjs +19 -18
  423. package/scripts/doctor.mjs +11 -9
  424. package/scripts/export-persona-source-review-batch.mjs +1 -1
  425. package/scripts/generate-persona-v3-drafts.mjs +2 -2
  426. package/scripts/lib/build-profile.mjs +24 -0
  427. package/scripts/lib/council-evaluation-protocol.mjs +7 -6
  428. package/scripts/lib/host-capabilities.mjs +2 -1
  429. package/scripts/lib/packaged-host-parity.mjs +63 -8
  430. package/scripts/lib/persona-v3-ai-assisted-solo-status.mjs +6 -4
  431. package/scripts/lib/persona-v3-ai-formula-review.mjs +6 -5
  432. package/scripts/lib/persona-v3-ai-machine-simulations.mjs +32 -4
  433. package/scripts/lib/persona-v3-build-specs.mjs +3 -2
  434. package/scripts/lib/persona-v3-draft-packs.mjs +2 -2
  435. package/scripts/lib/persona-v3-formula-pipeline.mjs +11 -10
  436. package/scripts/lib/persona-v3-production-candidates.mjs +10 -9
  437. package/scripts/lib/persona-v3-solo-formula-pipeline.mjs +182 -16
  438. package/scripts/lib/persona-v3-solo-test-packs.mjs +143 -16
  439. package/scripts/package-smoke.mjs +32 -12
  440. package/scripts/report-persona-corpus-gaps.mjs +4 -1
  441. package/scripts/review-persona-v3-solo-formulas.mjs +12 -8
  442. package/scripts/run-tests.mjs +23 -2
  443. package/scripts/scaffold-persona-v3-staging.mjs +1 -1
  444. package/skills/agent-skills-governance/SKILL.md +8 -2
  445. package/skills/alphacouncil-agent/SKILL.md +60 -9
  446. package/skills/public-equity-investing/SKILL.md +17 -0
  447. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/change_value_bridge.derived-proxy-evidence.json +0 -64
  448. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/power_map.derived-proxy-evidence.json +0 -64
  449. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/compute_power_bridge.derived-proxy-evidence.json +0 -64
  450. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/timeline_reverse_valuation.derived-proxy-evidence.json +0 -64
  451. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/crowding_cost_stress.derived-proxy-evidence.json +0 -64
  452. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/factor_decomposer.derived-proxy-evidence.json +0 -64
  453. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/incremental_returns.derived-proxy-evidence.json +0 -64
  454. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_rebuilder.derived-proxy-evidence.json +0 -64
  455. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/capital_structure_reader.derived-proxy-evidence.json +0 -64
  456. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/mispricing_carry.derived-proxy-evidence.json +0 -64
  457. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/capture_valuation_bridge.derived-proxy-evidence.json +0 -64
  458. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/cost_adoption_curve.derived-proxy-evidence.json +0 -64
  459. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/debt_driver_stress.derived-proxy-evidence.json +0 -64
  460. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/regime_classifier.derived-proxy-evidence.json +0 -64
  461. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/story_dcf.derived-proxy-evidence.json +0 -64
  462. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/inflection_payoff.derived-proxy-evidence.json +0 -64
  463. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_revision_map.derived-proxy-evidence.json +0 -64
  464. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/opportunity_cost.derived-proxy-evidence.json +0 -64
  465. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/user_value_evidence.derived-proxy-evidence.json +0 -64
  466. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/research_productivity.derived-proxy-evidence.json +0 -64
  467. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/scuttlebutt_graph.derived-proxy-evidence.json +0 -64
  468. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/borrow_catalyst.derived-proxy-evidence.json +0 -64
  469. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/asset_floor.derived-proxy-evidence.json +0 -64
  470. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/normalized_earnings.derived-proxy-evidence.json +0 -64
  471. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/penetration_liquidity.derived-proxy-evidence.json +0 -64
  472. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/promoter_governance.derived-proxy-evidence.json +0 -64
  473. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/cash_catalyst_compare.derived-proxy-evidence.json +0 -64
  474. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/recovery_waterfall.derived-proxy-evidence.json +0 -64
  475. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/promise_integrity_ledger.derived-proxy-evidence.json +0 -64
  476. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/ten_year_return_bridge.derived-proxy-evidence.json +0 -64
  477. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/category_classifier.derived-proxy-evidence.json +0 -64
  478. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/story_numbers_check.derived-proxy-evidence.json +0 -64
  479. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/cycle_temperature.derived-proxy-evidence.json +0 -64
  480. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/implied_expectations.derived-proxy-evidence.json +0 -64
  481. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/failure_path_graph.derived-proxy-evidence.json +0 -64
  482. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/incentive_map.derived-proxy-evidence.json +0 -64
  483. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/discrete_payoff.derived-proxy-evidence.json +0 -64
  484. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor.derived-proxy-evidence.json +0 -64
  485. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/leakage_audit.derived-proxy-evidence.json +0 -64
  486. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/oos_cost_test.derived-proxy-evidence.json +0 -64
  487. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/net_edge_sizer.derived-proxy-evidence.json +0 -64
  488. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/realized_vol_forecast.derived-proxy-evidence.json +0 -64
  489. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reflexivity_graph.derived-proxy-evidence.json +0 -64
  490. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reversal_monitor.derived-proxy-evidence.json +0 -64
  491. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/payoff_ruin.derived-proxy-evidence.json +0 -64
  492. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_recalculator.derived-proxy-evidence.json +0 -64
  493. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/fractional_kelly.derived-proxy-evidence.json +0 -64
@@ -0,0 +1,557 @@
1
+ /**
2
+ * Turn a fund or index into typed-fact candidates, including look-through.
3
+ *
4
+ * A basket has no income statement, which is why twenty-five method seats used to abstain on
5
+ * QQQ. But Buffett defined look-through earnings in the 1990 shareholder letter for exactly
6
+ * this situation -- owning pieces of many businesses -- so aggregating the constituents'
7
+ * ratios by weight is the method's own answer, not a workaround bolted onto it.
8
+ *
9
+ * The aggregation itself lives in `funds.mjs`, which refuses to express an absolute-currency
10
+ * sum at all. This module's job is orchestration and honesty about coverage: every
11
+ * look-through fact carries the weight it was computed over, because a portfolio ratio
12
+ * measured across 8% of the basket is a different claim from one measured across 95%.
13
+ */
14
+
15
+ import { LIMITS } from "./constants.mjs";
16
+ import { fetchFundHoldings, fetchFundMetadata, lookThroughAggregate, topHoldingsCoverage } from "./funds.mjs";
17
+ import { fetchIndexAggregate, INDEX_PROXIES, normalizeIndexSymbol } from "./index-aggregate.mjs";
18
+ import { fetchImpliedErp } from "./damodaran.mjs";
19
+ import { fetchBasketBreadth } from "./breadth.mjs";
20
+ import { fetchFundamentals } from "./fundamentals.mjs";
21
+ import { fetchUniverse } from "./sec.mjs";
22
+
23
+ /**
24
+ * How many constituents may be resolved for a look-through pass.
25
+ *
26
+ * Every constituent costs one filing fetch, and weights decay fast enough that the tail buys
27
+ * coverage very slowly: on a cap-weighted basket the top forty names usually clear 60%.
28
+ * ponytail: fixed cap, revisit if a genuinely equal-weighted basket needs the tail.
29
+ */
30
+ export const LOOK_THROUGH_MAX_CONSTITUENTS = 40;
31
+ export const LOOK_THROUGH_TARGET_COVERAGE = 0.6;
32
+
33
+ /**
34
+ * The operating-company facts a basket can supply by aggregating its constituents.
35
+ *
36
+ * Only ratios appear here. An absolute-currency look-through would be "ETF revenue", which is
37
+ * a category error `funds.mjs` refuses to express at all.
38
+ */
39
+ /**
40
+ * Pack fact id -> the aggregation rule that governs it in `funds.mjs`.
41
+ *
42
+ * The two vocabularies differ on purpose: the aggregator is named for the SHAPE of a metric
43
+ * (a price multiple aggregates harmonically, a margin arithmetically), while a pack asks for
44
+ * the fact it reasons about. Keeping the translation explicit here means neither side has to
45
+ * rename anything, and an unmapped fact simply produces no look-through value rather than a
46
+ * silently mis-aggregated one.
47
+ *
48
+ * Only ratios appear. An absolute-currency look-through would be "ETF revenue", which is a
49
+ * category error `funds.mjs` refuses to express at all.
50
+ */
51
+ export const LOOK_THROUGH_FACT_RULES = Object.freeze({
52
+ "financial.leverage": "leverage.debt_to_equity",
53
+ "valuation.revenue_growth": "growth.revenue_growth",
54
+ });
55
+
56
+ /**
57
+ * Facts a constituent publishes that are NOT aggregable, and why.
58
+ *
59
+ * Owner earnings, NCAV and the downside values are absolute currency amounts. Summing them
60
+ * across a basket produces "the ETF's owner earnings", which is the exact category error the
61
+ * whole look-through discipline exists to prevent. Turning them into a portfolio number needs
62
+ * a per-constituent denominator -- market capitalisation -- so they become yields first. That
63
+ * is real and worth doing; it is simply not this pass, and pretending otherwise by summing is
64
+ * the failure mode, not the shortcut.
65
+ */
66
+ export const LOOK_THROUGH_BLOCKED = Object.freeze({
67
+ "financial.owner_earnings": "absolute currency; needs a per-constituent market capitalisation to become a yield",
68
+ "financial.net_current_asset_value": "absolute currency; needs a per-constituent market capitalisation to become a ratio",
69
+ "valuation.downside_asset_value": "absolute currency; needs a per-constituent market capitalisation to become a ratio",
70
+ "valuation.downside_floor": "absolute currency; needs a per-constituent market capitalisation to become a ratio",
71
+ "capital_allocation.share_count": "a count, not a rate; it has no portfolio-level meaning",
72
+ });
73
+
74
+ export const LOOK_THROUGH_FACT_IDS = Object.freeze(Object.keys(LOOK_THROUGH_FACT_RULES));
75
+
76
+ const finite = (value) => typeof value === "number" && Number.isFinite(value);
77
+
78
+ /**
79
+ * The index whose published valuation describes a fund's portfolio.
80
+ *
81
+ * A cap-weighted tracker holds the index, so the index's aggregate P/E is the honest
82
+ * valuation of the fund's book -- and it is the only same-basis aggregate available for free.
83
+ * Derived by inverting the proxy map so the two directions cannot drift apart: whichever ETF
84
+ * stands in for an index is also the ETF that borrows that index's valuation.
85
+ */
86
+ const VALUATION_INDEX_BY_FUND = Object.freeze(Object.fromEntries(
87
+ Object.entries(INDEX_PROXIES).flatMap(([index, proxy]) => (
88
+ [proxy.etf, ...(proxy.alternates || [])].map((etf) => [etf, index])
89
+ )),
90
+ ));
91
+
92
+ export function valuationIndexFor(symbol) {
93
+ return VALUATION_INDEX_BY_FUND[String(symbol || "").trim().toUpperCase()] || null;
94
+ }
95
+
96
+ /**
97
+ * Facts an index publishes about itself. Each carries its basis, because index P/E is quoted
98
+ * on incompatible bases and a fact that does not name its own is unusable.
99
+ */
100
+ function valuationFacts(aggregate) {
101
+ const valuation = aggregate?.valuation;
102
+ if (!valuation || !finite(valuation.pe_trailing)) return [];
103
+ const facts = [];
104
+ const shared = {
105
+ source_kind: "market_snapshot",
106
+ source_url: valuation.source_url,
107
+ public_at: valuation.public_at,
108
+ observation_date: valuation.trade_date,
109
+ basis: valuation.basis,
110
+ title: `${valuation.name} valuation (${valuation.basis})`,
111
+ confidence: 0.8,
112
+ };
113
+ facts.push({
114
+ ...shared,
115
+ fact_id: "index.aggregate_pe_ttm",
116
+ value: valuation.pe_trailing,
117
+ value_kind: "ratio",
118
+ unit: "multiple",
119
+ ratio_denominator: "trailing_twelve_month_earnings",
120
+ method: valuation.basis,
121
+ });
122
+ // The reciprocal is what a valuation method actually compares against a bond yield, so it
123
+ // is published as its own fact rather than left for each seat to recompute differently.
124
+ facts.push({
125
+ ...shared,
126
+ fact_id: "index.aggregate_earnings_yield",
127
+ value: Number((1 / valuation.pe_trailing).toFixed(6)),
128
+ value_kind: "ratio",
129
+ unit: "decimal",
130
+ ratio_denominator: "price",
131
+ method: `reciprocal_of_${valuation.basis}_trailing_pe`,
132
+ });
133
+ if (finite(valuation.pe_forward)) {
134
+ facts.push({
135
+ ...shared,
136
+ fact_id: "index.aggregate_pe_forward",
137
+ value: valuation.pe_forward,
138
+ value_kind: "ratio",
139
+ unit: "multiple",
140
+ ratio_denominator: "forward_twelve_month_earnings",
141
+ method: `${valuation.basis}_forward`,
142
+ });
143
+ }
144
+ if (finite(valuation.dividend_yield)) {
145
+ facts.push({
146
+ ...shared,
147
+ fact_id: "index.dividend_yield",
148
+ // Declared as percent by the source; the typed-fact contract is decimal.
149
+ value: valuation.dividend_yield / 100,
150
+ value_kind: "ratio",
151
+ unit: "decimal",
152
+ ratio_denominator: "price",
153
+ method: valuation.basis,
154
+ });
155
+ }
156
+ return facts;
157
+ }
158
+
159
+ /** Concentration and cost, which are properties of the wrapper rather than of the businesses. */
160
+ function structureFacts(holdings, metadata) {
161
+ const facts = [];
162
+ if (!holdings?.holdings?.length) return facts;
163
+ const shared = {
164
+ source_kind: "issuer_disclosure",
165
+ source_url: holdings.source_url,
166
+ public_at: holdings.public_at,
167
+ observation_date: holdings.as_of,
168
+ confidence: 0.9,
169
+ derivation: "rederived",
170
+ };
171
+ const sorted = [...holdings.holdings].sort((left, right) => (right.weight || 0) - (left.weight || 0));
172
+ const topTen = sorted.slice(0, 10).reduce((sum, row) => sum + (row.weight || 0), 0);
173
+ facts.push({
174
+ ...shared,
175
+ fact_id: "fund.top_ten_weight",
176
+ value: Number(topTen.toFixed(6)),
177
+ value_kind: "ratio",
178
+ unit: "decimal",
179
+ ratio_denominator: "portfolio_weight",
180
+ method: "sum_of_ten_largest_published_weights",
181
+ title: `${holdings.symbol} top-ten concentration`,
182
+ });
183
+ // Herfindahl over published weights: one number that separates "a basket" from "three
184
+ // positions and some rounding".
185
+ const hhi = sorted.reduce((sum, row) => sum + ((row.weight || 0) ** 2), 0);
186
+ facts.push({
187
+ ...shared,
188
+ fact_id: "fund.concentration_hhi",
189
+ value: Number(hhi.toFixed(6)),
190
+ value_kind: "ratio",
191
+ unit: "decimal",
192
+ ratio_denominator: "sum_of_squared_weights",
193
+ method: "herfindahl_over_published_weights",
194
+ title: `${holdings.symbol} concentration index`,
195
+ });
196
+ if (finite(metadata?.expense_ratio)) {
197
+ // Issuers publish the fee as a percent; the typed-fact contract is a decimal fraction.
198
+ // Passing it through unconverted is a hundredfold error that looks entirely plausible.
199
+ const asDecimal = metadata.expense_ratio_unit === "percent"
200
+ ? metadata.expense_ratio / 100
201
+ : metadata.expense_ratio;
202
+ facts.push({
203
+ ...shared,
204
+ fact_id: "fund.expense_ratio",
205
+ value: Number(asDecimal.toFixed(6)),
206
+ value_kind: "ratio",
207
+ unit: "decimal",
208
+ ratio_denominator: "net_assets",
209
+ derivation: "reported",
210
+ source_url: metadata.source_url || holdings.source_url,
211
+ public_at: metadata.public_at || holdings.public_at,
212
+ method: "issuer_published",
213
+ title: `${holdings.symbol} expense ratio`,
214
+ });
215
+ }
216
+ return facts;
217
+ }
218
+
219
+ /**
220
+ * Resolve constituent fundamentals for a look-through pass.
221
+ *
222
+ * One filing fetch per constituent, bounded twice over: by `LOOK_THROUGH_MAX_CONSTITUENTS`
223
+ * and by stopping as soon as the target coverage weight is reached. A constituent that cannot
224
+ * be resolved -- a foreign filer, a share class the ticker map does not carry -- is skipped
225
+ * rather than substituted, and its weight simply does not count toward coverage. That keeps
226
+ * the coverage number honest, which is the only thing that makes the aggregate meaningful.
227
+ */
228
+ /**
229
+ * True when a diagnostic names a fact the pack ended up producing anyway. Matching is by the
230
+ * fact id appearing in the note, so a note that names no fact is always kept.
231
+ */
232
+ function factsProducedFor(note, facts) {
233
+ const produced = new Set(facts.map((fact) => fact.fact_id));
234
+ return [...produced].some((factId) => String(note).includes(factId))
235
+ || (/implied equity risk premium/iu.test(note) && produced.has("valuation.implied_erp"))
236
+ || (/valuation percentile/iu.test(note) && produced.has("cycle.valuation_percentile"));
237
+ }
238
+
239
+ export async function resolveConstituentFacts(holdings, { signal, asOf = null, concurrency = 6 } = {}) {
240
+ const perHolding = new Map();
241
+ // The aggregate inherits whatever span its inputs covered; without carrying it the basket
242
+ // fact arrives as a bare number that no duration contract can accept.
243
+ const perHoldingPeriods = new Map();
244
+ const unavailable = [];
245
+ const ranked = [...holdings]
246
+ .sort((left, right) => (right.weight || 0) - (left.weight || 0))
247
+ .slice(0, LOOK_THROUGH_MAX_CONSTITUENTS);
248
+ if (!ranked.length) return { perHolding, perHoldingPeriods, unavailable, attempted: 0 };
249
+
250
+ let universe = null;
251
+ try {
252
+ universe = new Map((await fetchUniverse({ signal }))
253
+ .map((row) => [String(row.ticker).toUpperCase(), row.cik]));
254
+ } catch (error) {
255
+ return {
256
+ perHolding,
257
+ perHoldingPeriods,
258
+ unavailable: [`look-through: SEC ticker universe unavailable (${String(error?.message || error)})`],
259
+ attempted: 0,
260
+ };
261
+ }
262
+
263
+ const queue = [...ranked];
264
+ const worker = async () => {
265
+ for (let next = queue.shift(); next; next = queue.shift()) {
266
+ const ticker = String(next.ticker || "").toUpperCase();
267
+ const cik = universe.get(ticker);
268
+ if (!cik) { unavailable.push(`look-through ${ticker}: no SEC registrant for this ticker`); continue; }
269
+ try {
270
+ const derived = await fetchFundamentals({ cik, ticker, asOf, signal });
271
+ const facts = {};
272
+ const periods = {};
273
+ for (const [factId, metric] of Object.entries(derived.metrics || {})) {
274
+ if (!metric || !Number.isFinite(metric.value)) continue;
275
+ facts[factId] = metric.value;
276
+ if (metric.period_start && metric.period_end) {
277
+ periods[factId] = { start: metric.period_start, end: metric.period_end };
278
+ }
279
+ }
280
+ if (Object.keys(facts).length) perHolding.set(ticker, facts);
281
+ if (Object.keys(periods).length) perHoldingPeriods.set(ticker, periods);
282
+ } catch (error) {
283
+ unavailable.push(`look-through ${ticker}: ${String(error?.message || error)}`);
284
+ }
285
+ }
286
+ };
287
+ await Promise.all(Array.from({ length: Math.min(concurrency, ranked.length) }, worker));
288
+ return { perHolding, perHoldingPeriods, unavailable, attempted: ranked.length };
289
+ }
290
+
291
+ /**
292
+ * Aggregate constituent ratios into portfolio-level operating-company facts.
293
+ *
294
+ * `perHoldingFacts` is supplied by the caller rather than fetched here: resolving it means one
295
+ * filing per constituent, and the caller owns the budget for that. Passing an empty map is a
296
+ * valid, cheap run -- it yields no look-through facts and one explicit gap, which is the
297
+ * correct outcome and not a failure.
298
+ */
299
+ /**
300
+ * The interval a basket-level aggregate covers: the widest span its contributing constituents
301
+ * reported. Stating a narrower one would claim coverage the inputs do not have, and stating
302
+ * none at all leaves the fact unusable by any duration contract.
303
+ */
304
+ function aggregatePeriod(perHoldingPeriods, factId, tickers) {
305
+ let start = null;
306
+ let end = null;
307
+ for (const ticker of tickers) {
308
+ const span = perHoldingPeriods?.get(ticker)?.[factId];
309
+ if (!span?.start || !span?.end) continue;
310
+ if (!start || span.start < start) start = span.start;
311
+ if (!end || span.end > end) end = span.end;
312
+ }
313
+ return start && end ? { period_start: start, period_end: end } : {};
314
+ }
315
+
316
+ export function lookThroughFacts({ holdings, perHoldingFacts, perHoldingPeriods, factIds, holdingsMeta }) {
317
+ const facts = [];
318
+ const unavailable = [];
319
+ if (!holdings?.length) return { facts, unavailable };
320
+ const coverage = topHoldingsCoverage(holdings, { minWeight: LOOK_THROUGH_TARGET_COVERAGE });
321
+ for (const factId of factIds) {
322
+ const rule = LOOK_THROUGH_FACT_RULES[factId];
323
+ if (!rule) {
324
+ unavailable.push(`look-through ${factId}: ${LOOK_THROUGH_BLOCKED[factId] || "no aggregation rule is defined for this fact"}`);
325
+ continue;
326
+ }
327
+ // The aggregator reads one number per ticker; the rule name selects how it is combined.
328
+ const byTicker = new Map([...perHoldingFacts]
329
+ .filter(([, facts]) => Number.isFinite(facts?.[factId]))
330
+ .map(([ticker, facts]) => [ticker, facts[factId]]));
331
+ const aggregate = lookThroughAggregate({
332
+ holdings: coverage.holdings,
333
+ perHoldingFacts: byTicker,
334
+ factId: rule,
335
+ coverageWeight: coverage.coverage_weight,
336
+ });
337
+ if (!aggregate || !finite(aggregate.value)) {
338
+ unavailable.push(`look-through ${factId}: ${aggregate?.unavailable?.join("; ") || "no constituent supplied this fact"}`);
339
+ continue;
340
+ }
341
+ facts.push({
342
+ fact_id: factId,
343
+ value: aggregate.value,
344
+ value_kind: "ratio",
345
+ unit: "decimal",
346
+ ratio_denominator: `weight_${aggregate.method}`,
347
+ source_kind: "issuer_disclosure",
348
+ source_url: holdingsMeta?.source_url,
349
+ public_at: holdingsMeta?.public_at,
350
+ observation_date: holdingsMeta?.as_of,
351
+ ...aggregatePeriod(perHoldingPeriods, factId, [...byTicker.keys()]),
352
+ confidence: 0.7,
353
+ derivation: "rederived",
354
+ method: aggregate.method,
355
+ coverage_weight: aggregate.coverage_weight,
356
+ title: `look-through ${factId} over ${aggregate.constituent_count} constituents`,
357
+ });
358
+ }
359
+ return { facts, unavailable };
360
+ }
361
+
362
+ /**
363
+ * Compose everything a fund or index instrument can contribute.
364
+ *
365
+ * An index has no issuer to publish holdings, so it borrows its tracking ETF's -- labelled a
366
+ * proxy in the returned provenance, because the constituents themselves are a licensed asset
367
+ * and presenting borrowed weights as the index would be both a licensing and an accuracy
368
+ * claim this project has no basis for.
369
+ */
370
+ export async function gatherInstrumentFacts({
371
+ symbol,
372
+ instrument,
373
+ perHoldingFacts = null,
374
+ lookThroughFactIds = [],
375
+ signal,
376
+ asOf = null,
377
+ } = {}) {
378
+ const facts = [];
379
+ const unavailable = [];
380
+ const provenance = {};
381
+ const normalized = normalizeIndexSymbol(symbol);
382
+ const proxy = INDEX_PROXIES[normalized];
383
+ const holdingsSymbol = instrument?.index_like ? proxy?.etf : symbol;
384
+ // A tracker has no valuation of its own to publish, so it reads the index it holds. Without
385
+ // this a fund run reported "WSJ publishes only three indices" as a gap while the very index
386
+ // it tracks was one of the three.
387
+ const valuationSymbol = instrument?.index_like ? normalized : (valuationIndexFor(symbol) || normalized);
388
+ if (!instrument?.index_like && valuationSymbol !== normalized) {
389
+ provenance.valuation_source = {
390
+ kind: "tracked_index_valuation",
391
+ index: valuationSymbol,
392
+ why: "a cap-weighted tracker holds the index, so the index aggregate describes the fund's book on the same basis",
393
+ };
394
+ }
395
+
396
+ if (instrument?.index_like) {
397
+ provenance.constituent_source = proxy
398
+ ? { kind: "tracking_etf_proxy", etf: proxy.etf, licensor: proxy.licensor, why: proxy.why }
399
+ : { kind: "unavailable", why: "no tracking-ETF proxy is registered for this index" };
400
+ }
401
+
402
+ // Fee and size come from the issuer, not from the index: an index has no expense ratio.
403
+ // This was previously read off the index aggregate, which never carries one, so the fee
404
+ // fact was unreachable code that silently produced nothing.
405
+ const [aggregate, holdings, metadata, erp] = await Promise.all([
406
+ fetchIndexAggregate({ symbol: valuationSymbol, signal, asOf })
407
+ .catch((error) => ({ unavailable: [`index aggregate: ${String(error?.message || error)}`] })),
408
+ holdingsSymbol
409
+ ? fetchFundHoldings(holdingsSymbol, { signal })
410
+ .catch((error) => ({ unavailable: [`fund holdings: ${String(error?.message || error)}`] }))
411
+ : Promise.resolve(null),
412
+ holdingsSymbol
413
+ ? fetchFundMetadata(holdingsSymbol, { signal })
414
+ .catch((error) => ({ unavailable: [`fund metadata: ${String(error?.message || error)}`] }))
415
+ : Promise.resolve(null),
416
+ fetchImpliedErp({ signal, asOf })
417
+ .catch((error) => ({ unavailable: [`implied equity risk premium: ${String(error?.message || error)}`] })),
418
+ ]);
419
+
420
+ facts.push(...valuationFacts(aggregate));
421
+ if (erp && finite(erp.latest)) {
422
+ // The premium the market is actually pricing, with where it sits in its own history. A
423
+ // level alone cannot say whether the market is paying up; the percentile is the claim.
424
+ facts.push({
425
+ fact_id: "valuation.implied_erp",
426
+ value: erp.latest,
427
+ value_kind: "ratio",
428
+ unit: "decimal",
429
+ ratio_denominator: "equity_over_riskfree",
430
+ source_kind: "published_dataset",
431
+ source_url: erp.source_url,
432
+ public_at: erp.public_at,
433
+ observation_date: erp.observation_date,
434
+ confidence: 0.85,
435
+ derivation: "reported",
436
+ method: erp.basis,
437
+ title: "Damodaran implied equity risk premium",
438
+ });
439
+ if (erp.percentile) {
440
+ facts.push({
441
+ fact_id: "cycle.valuation_percentile",
442
+ value: erp.percentile.percentile,
443
+ value_kind: "ratio",
444
+ unit: "decimal",
445
+ ratio_denominator: `rank_within_${erp.percentile.sample_size}_published_months`,
446
+ source_kind: "published_dataset",
447
+ source_url: erp.source_url,
448
+ public_at: erp.public_at,
449
+ observation_date: erp.observation_date,
450
+ confidence: 0.8,
451
+ derivation: "rederived",
452
+ method: `percentile_of_${erp.basis}_since_${erp.percentile.sample_start}`,
453
+ title: "implied equity risk premium percentile",
454
+ });
455
+ }
456
+ }
457
+ unavailable.push(...(erp?.unavailable || []));
458
+ unavailable.push(...(aggregate?.unavailable || []));
459
+ if (holdings?.holdings?.length) {
460
+ facts.push(...structureFacts(holdings, metadata));
461
+ // Breadth is computed from the basket rather than bought: every free screener that
462
+ // publishes it forbids the query, and the holdings are already in hand.
463
+ const breadth = await fetchBasketBreadth(holdings.holdings, { signal })
464
+ .catch((error) => ({ available: false, unavailable: [`breadth: ${String(error?.message || error)}`] }));
465
+ unavailable.push(...(breadth.unavailable || []));
466
+ if (breadth.available) {
467
+ const shared = {
468
+ source_kind: "market_snapshot",
469
+ source_url: holdings.source_url,
470
+ public_at: holdings.public_at,
471
+ observation_date: holdings.as_of,
472
+ value_kind: "ratio",
473
+ unit: "decimal",
474
+ derivation: "rederived",
475
+ confidence: 0.8,
476
+ coverage_weight: breadth.coverage_weight,
477
+ method: breadth.method,
478
+ };
479
+ facts.push({
480
+ ...shared,
481
+ fact_id: "index.breadth_above_200dma",
482
+ value: breadth.weighted_above,
483
+ ratio_denominator: "measured_basket_weight",
484
+ title: "share of basket weight above its 200-day average",
485
+ });
486
+ if (finite(breadth.net_assets) && !finite(metadata?.aum)) {
487
+ facts.push({
488
+ ...shared,
489
+ fact_id: "fund.aum",
490
+ value: breadth.net_assets,
491
+ value_kind: "monetary",
492
+ unit: "currency_units",
493
+ currency: "USD",
494
+ scale: 1,
495
+ ratio_denominator: undefined,
496
+ method: "sum_of_disclosed_units_at_last_close",
497
+ title: `${holdings.symbol} assets from disclosed positions`,
498
+ });
499
+ }
500
+ // The gap between weighted and counted breadth IS the concentration story: a
501
+ // cap-weighted basket can be above its average on weight while most members are below.
502
+ facts.push({
503
+ ...shared,
504
+ fact_id: "index.breadth_counted_above_200dma",
505
+ value: breadth.counted_above,
506
+ ratio_denominator: "measured_constituent_count",
507
+ title: "share of measured constituents above their 200-day average",
508
+ });
509
+ }
510
+ provenance.holdings_as_of = holdings.as_of;
511
+ provenance.holdings_count = holdings.holdings.length;
512
+ }
513
+ unavailable.push(...(holdings?.unavailable || []));
514
+ unavailable.push(...(metadata?.unavailable || []));
515
+
516
+ if (holdings?.holdings?.length && lookThroughFactIds.length) {
517
+ let resolved = perHoldingFacts;
518
+ let resolvedPeriods = null;
519
+ if (!resolved) {
520
+ const constituents = await resolveConstituentFacts(holdings.holdings, { signal, asOf });
521
+ resolved = constituents.perHolding;
522
+ resolvedPeriods = constituents.perHoldingPeriods;
523
+ unavailable.push(...constituents.unavailable);
524
+ provenance.look_through = {
525
+ constituents_attempted: constituents.attempted,
526
+ constituents_resolved: resolved.size,
527
+ };
528
+ }
529
+ const through = lookThroughFacts({
530
+ holdings: holdings.holdings,
531
+ perHoldingFacts: resolved,
532
+ perHoldingPeriods: resolvedPeriods,
533
+ factIds: lookThroughFactIds,
534
+ holdingsMeta: holdings,
535
+ });
536
+ facts.push(...through.facts);
537
+ unavailable.push(...through.unavailable);
538
+ }
539
+
540
+ return {
541
+ symbol,
542
+ research_model: instrument?.research_model || "market_instrument",
543
+ provenance,
544
+ facts,
545
+ // Several facts have more than one route -- the implied ERP and the valuation percentile
546
+ // are computed from the published workbook when the index feed cannot supply them -- and
547
+ // each route reports its own failure. Keeping a note about a fact the pack actually
548
+ // produced reads as a gap that is filled, which is worse than saying nothing: it invites
549
+ // a reader to go and solve a problem that is already solved.
550
+ unavailable: unavailable.filter((note) => !factsProducedFor(note, facts)),
551
+ limits: {
552
+ max_constituents: LOOK_THROUGH_MAX_CONSTITUENTS,
553
+ target_coverage: LOOK_THROUGH_TARGET_COVERAGE,
554
+ fetch_timeout_ms: LIMITS.QUOTE_FETCH_MS,
555
+ },
556
+ };
557
+ }