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,246 @@
1
+ /**
2
+ * Keyless FRED series, with history.
3
+ *
4
+ * The macro block already gives point-in-time market prices, and a snapshot is enough for a
5
+ * level but not for an impulse. A "liquidity impulse" or a "growth regime" computed from one
6
+ * day of quotes is fabricated precision, so those readings need an actual series behind them.
7
+ *
8
+ * `api.stlouisfed.org` requires a key; the CSV graph endpoint does not, and it returns the
9
+ * full observation history. That is the only reason this module exists as a separate feed:
10
+ * everything here is a dated observation published by the source, so it can carry real
11
+ * lineage into the typed-fact pack instead of being asserted at the run's `as_of`.
12
+ *
13
+ * Deliberately NOT here: any single number claiming to be "the regime". The series are
14
+ * inputs. The composites below are named for exactly what they compute and carry their own
15
+ * window, so a reader can disagree with the window rather than with an opaque score.
16
+ */
17
+
18
+ import { LIMITS } from "./constants.mjs";
19
+ import { fetchText } from "./quotes.mjs";
20
+
21
+ const FRED_CSV = "https://fred.stlouisfed.org/graph/fredgraph.csv?id=";
22
+
23
+ /**
24
+ * Units are not uniform across FRED and mixing them silently is the obvious way to produce a
25
+ * confident wrong number: WALCL is millions of dollars while RRPONTSYD is billions. Every
26
+ * series therefore declares its scale, and the composites below convert explicitly.
27
+ */
28
+ export const FRED_SERIES = Object.freeze({
29
+ DGS10: { fact: "macro.long_bond_yield", unit: "percent", label: "10-year Treasury constant maturity" },
30
+ DGS2: { fact: "macro.short_bond_yield", unit: "percent", label: "2-year Treasury constant maturity" },
31
+ DGS3MO: { fact: null, unit: "percent", label: "3-month Treasury constant maturity" },
32
+ T10Y3M: { fact: "macro.term_structure_slope", unit: "percent", label: "10-year minus 3-month Treasury" },
33
+ DFII10: { fact: "macro.real_rate", unit: "percent", label: "10-year TIPS real yield" },
34
+ T5YIE: { fact: "macro.breakeven_inflation", unit: "percent", label: "5-year breakeven inflation" },
35
+ AAA: { fact: "macro.aaa_corporate_yield", unit: "percent", label: "Moody's seasoned Aaa corporate bond yield" },
36
+ BAMLH0A0HYM2: { fact: "macro.credit_spread", unit: "percent", label: "ICE BofA US high yield option-adjusted spread" },
37
+ WALCL: { fact: null, unit: "usd_millions", label: "Federal Reserve total assets" },
38
+ RRPONTSYD: { fact: null, unit: "usd_billions", label: "Overnight reverse repurchase agreements" },
39
+ WTREGEN: { fact: null, unit: "usd_millions", label: "Treasury General Account balance" },
40
+ });
41
+
42
+ export function seriesUrl(id) {
43
+ return `${FRED_CSV}${encodeURIComponent(id)}`;
44
+ }
45
+
46
+ /**
47
+ * FRED writes `.` for a missing observation on a holiday or a not-yet-published date. Those
48
+ * rows are dropped rather than carried forward: a stale value silently reused as today's
49
+ * reading is the failure mode this whole pipeline is built to avoid.
50
+ */
51
+ export function parseFredCsv(csv, id) {
52
+ const lines = String(csv || "").trim().split(/\r?\n/);
53
+ if (lines.length < 2) throw new Error(`empty FRED series ${id}`);
54
+ const header = lines[0].split(",");
55
+ if (header.length < 2) throw new Error(`unexpected FRED header for ${id}: ${lines[0]}`);
56
+ const observations = [];
57
+ for (const line of lines.slice(1)) {
58
+ const [date, raw] = line.split(",");
59
+ if (!/^\d{4}-\d{2}-\d{2}$/u.test(String(date || "").trim())) continue;
60
+ const value = Number(raw);
61
+ if (!Number.isFinite(value)) continue;
62
+ observations.push({ date: date.trim(), value });
63
+ }
64
+ if (!observations.length) throw new Error(`no numeric observations in FRED series ${id}`);
65
+ return observations;
66
+ }
67
+
68
+ export async function fetchFredSeries(id, { signal, asOf = null } = {}) {
69
+ if (!Object.prototype.hasOwnProperty.call(FRED_SERIES, id)) {
70
+ throw new Error(`unknown FRED series: ${id}`);
71
+ }
72
+ const url = seriesUrl(id);
73
+ const observations = parseFredCsv(await fetchText(url, LIMITS.QUOTE_FETCH_MS * 2, signal), id);
74
+ // A historical cutoff must not see observations published after it.
75
+ const visible = asOf ? observations.filter((row) => row.date <= String(asOf).slice(0, 10)) : observations;
76
+ if (!visible.length) throw new Error(`FRED series ${id} has no observation at or before ${asOf}`);
77
+ const last = visible.at(-1);
78
+ return Object.freeze({
79
+ id,
80
+ ...FRED_SERIES[id],
81
+ observations: visible,
82
+ latest: last.value,
83
+ // The observation date IS the publication anchor for this feed, so it never has to be
84
+ // stamped with the run time.
85
+ public_at: `${last.date}T00:00:00.000Z`,
86
+ observation_date: last.date,
87
+ source_url: url,
88
+ });
89
+ }
90
+
91
+ /** Value `windowDays` calendar days before the latest observation, or null when unavailable. */
92
+ export function valueBefore(series, windowDays) {
93
+ const rows = series?.observations;
94
+ if (!Array.isArray(rows) || !rows.length) return null;
95
+ const cutoff = new Date(`${rows.at(-1).date}T00:00:00Z`);
96
+ cutoff.setUTCDate(cutoff.getUTCDate() - windowDays);
97
+ const target = cutoff.toISOString().slice(0, 10);
98
+ const prior = rows.filter((row) => row.date <= target);
99
+ return prior.length ? prior.at(-1) : null;
100
+ }
101
+
102
+ /**
103
+ * Where the latest observation sits in its own history, as a 0-1 rank.
104
+ *
105
+ * Reported with the sample it was computed against, because "the 92nd percentile" means
106
+ * nothing without saying percentile of what and since when.
107
+ */
108
+ export function percentileRank(series, { sinceDays = 365 * 10 } = {}) {
109
+ const rows = series?.observations;
110
+ if (!Array.isArray(rows) || rows.length < 2) return null;
111
+ const start = valueBefore(series, sinceDays);
112
+ const sample = start ? rows.filter((row) => row.date >= start.date) : rows;
113
+ if (sample.length < 30) return null;
114
+ const latest = rows.at(-1).value;
115
+ const below = sample.filter((row) => row.value < latest).length;
116
+ return {
117
+ percentile: Number((below / sample.length).toFixed(4)),
118
+ sample_size: sample.length,
119
+ sample_start: sample[0].date,
120
+ sample_end: rows.at(-1).date,
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Fed balance sheet less the two largest sterilising liabilities, in millions of dollars.
126
+ *
127
+ * This is the common "net liquidity" construction, not an official series. It is labelled as
128
+ * derived and its inputs are returned so the arithmetic can be checked, including the
129
+ * billions-to-millions conversion on the reverse repo leg.
130
+ */
131
+ export function netLiquidity({ walcl, rrp, tga }) {
132
+ if (!walcl?.observations?.length) return null;
133
+ const byDate = (series) => new Map((series?.observations || []).map((row) => [row.date, row.value]));
134
+ const rrpByDate = byDate(rrp);
135
+ const tgaByDate = byDate(tga);
136
+ const nearest = (map, date) => {
137
+ if (!map.size) return null;
138
+ const keys = [...map.keys()].filter((key) => key <= date);
139
+ return keys.length ? map.get(keys.at(-1)) : null;
140
+ };
141
+ const observations = [];
142
+ for (const row of walcl.observations) {
143
+ const rrpValue = nearest(rrpByDate, row.date);
144
+ const tgaValue = nearest(tgaByDate, row.date);
145
+ if (rrpValue === null || tgaValue === null) continue;
146
+ // RRPONTSYD is billions; WALCL and WTREGEN are millions.
147
+ observations.push({ date: row.date, value: row.value - (rrpValue * 1000) - tgaValue });
148
+ }
149
+ if (!observations.length) return null;
150
+ return Object.freeze({
151
+ id: "NET_LIQUIDITY",
152
+ unit: "usd_millions",
153
+ label: "Fed total assets less reverse repo and Treasury General Account",
154
+ derived_from: ["WALCL", "RRPONTSYD", "WTREGEN"],
155
+ observations,
156
+ latest: observations.at(-1).value,
157
+ observation_date: observations.at(-1).date,
158
+ public_at: `${observations.at(-1).date}T00:00:00.000Z`,
159
+ source_url: [walcl.source_url, rrp?.source_url, tga?.source_url].filter(Boolean),
160
+ });
161
+ }
162
+
163
+ /**
164
+ * Change in net liquidity over a window, as a fraction of the level at the start of it.
165
+ *
166
+ * A level tells you nothing about direction, and direction is the whole content of this
167
+ * reading, so the window is part of the value and travels with it.
168
+ */
169
+ export function liquidityImpulse(series, { windowDays = 91 } = {}) {
170
+ const start = valueBefore(series, windowDays);
171
+ if (!start || !series?.observations?.length || !start.value) return null;
172
+ const latest = series.observations.at(-1);
173
+ return {
174
+ value: Number(((latest.value - start.value) / Math.abs(start.value)).toFixed(6)),
175
+ window_days: windowDays,
176
+ from_date: start.date,
177
+ to_date: latest.date,
178
+ from_value: start.value,
179
+ to_value: latest.value,
180
+ };
181
+ }
182
+
183
+ const REGIME_STATES = Object.freeze([
184
+ "rising_growth_rising_inflation",
185
+ "rising_growth_falling_inflation",
186
+ "falling_growth_rising_inflation",
187
+ "falling_growth_falling_inflation",
188
+ ]);
189
+
190
+ /**
191
+ * The growth/inflation quadrant, from the direction of two market-priced series.
192
+ *
193
+ * Growth uses the curve slope (steepening prices growth and term premium, inversion prices
194
+ * the opposite) and inflation uses the breakeven. Returns null rather than a quadrant when
195
+ * either axis lacks the history to have a direction at all -- an unknown regime is a gap, and
196
+ * a seat that needs one should decline rather than receive a coin flip.
197
+ */
198
+ export function growthInflationRegime({ slope, breakeven, windowDays = 91 }) {
199
+ const direction = (series) => {
200
+ const start = valueBefore(series, windowDays);
201
+ if (!start || !series?.observations?.length) return null;
202
+ return series.observations.at(-1).value - start.value;
203
+ };
204
+ const growth = direction(slope);
205
+ const inflation = direction(breakeven);
206
+ if (growth === null || inflation === null) return null;
207
+ const state = `${growth >= 0 ? "rising" : "falling"}_growth_${inflation >= 0 ? "rising" : "falling"}_inflation`;
208
+ if (!REGIME_STATES.includes(state)) return null;
209
+ return {
210
+ state,
211
+ window_days: windowDays,
212
+ growth_axis: { series: slope.id, change: Number(growth.toFixed(4)) },
213
+ inflation_axis: { series: breakeven.id, change: Number(inflation.toFixed(4)) },
214
+ };
215
+ }
216
+
217
+ export const MACRO_FRED_SERIES = Object.freeze([
218
+ "DGS10", "DGS2", "T10Y3M", "DFII10", "T5YIE", "AAA", "BAMLH0A0HYM2",
219
+ "WALCL", "RRPONTSYD", "WTREGEN",
220
+ ]);
221
+
222
+ /**
223
+ * Fetch the macro series set concurrently. A failed series is a named gap, never a zero.
224
+ */
225
+ export async function fetchMacroSeries({ ids = MACRO_FRED_SERIES, signal, asOf = null } = {}) {
226
+ const results = await Promise.all(ids.map((id) => fetchFredSeries(id, { signal, asOf })
227
+ .then((series) => ({ ok: true, id, series }))
228
+ .catch((error) => ({ ok: false, id, error: String(error?.message || error) }))));
229
+ const series = {};
230
+ const unavailable = [];
231
+ for (const result of results) {
232
+ if (result.ok) series[result.id] = result.series;
233
+ else unavailable.push(`FRED ${result.id}: ${result.error}`);
234
+ }
235
+ const liquidity = netLiquidity({ walcl: series.WALCL, rrp: series.RRPONTSYD, tga: series.WTREGEN });
236
+ return {
237
+ series,
238
+ net_liquidity: liquidity,
239
+ liquidity_impulse: liquidity ? liquidityImpulse(liquidity) : null,
240
+ regime: series.T10Y3M && series.T5YIE
241
+ ? growthInflationRegime({ slope: series.T10Y3M, breakeven: series.T5YIE })
242
+ : null,
243
+ credit_spread_percentile: series.BAMLH0A0HYM2 ? percentileRank(series.BAMLH0A0HYM2) : null,
244
+ unavailable,
245
+ };
246
+ }
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Per-issuer holdings parsers.
3
+ *
4
+ * Four issuers publish the same thing in four shapes -- iShares as CSV with a preamble, SSGA as
5
+ * an XLSX workbook, Invesco as JSON, Vanguard as a paged JSON feed -- and none of them agrees on
6
+ * a column name or a date format. The parsing lives here so `funds.mjs` reads as fetch, cache
7
+ * and aggregate rather than as a tour of four vendors' quirks.
8
+ *
9
+ * Every parser returns the same record shape and refuses rather than guessing: a row with no
10
+ * resolvable weight is dropped and counted, not defaulted to zero.
11
+ */
12
+
13
+ import { readWorkbook, unzip, xlsxRows, xmlText } from "./xlsx.mjs";
14
+
15
+ const WEIGHT_SUM_TOLERANCE = 0.02;
16
+
17
+ /** The one record shape every issuer's rows are normalised into. */
18
+ const holding = ({ ticker, name, weight, units, asset_class = null }) => ({
19
+ ticker: ticker ? String(ticker).trim().toUpperCase() : null,
20
+ name: name ? String(name).trim() : null,
21
+ weight,
22
+ units,
23
+ asset_class,
24
+ });
25
+
26
+ /**
27
+ * Parse the SSGA daily holdings workbook.
28
+ *
29
+ * The sheet opens with a few label/value rows (fund name, ticker, "As of 27-Jul-2026") before
30
+ * the table, and closes with disclosure prose, so the header row is located by content rather
31
+ * than by a fixed offset -- SSGA moves it when the disclaimer text changes length.
32
+ */
33
+ /**
34
+ * Merge Vanguard's pages, refusing an incomplete pagination.
35
+ *
36
+ * Each page states the fund's full `size`, so a short walk is detectable. This matters more
37
+ * than usual here because the payload's own `next` link is dead: a caller that trusts it gets
38
+ * page one and a fund that looks like it holds 500 names.
39
+ */
40
+ /**
41
+ * Parse Invesco's cache payload, refusing a silently truncated one.
42
+ *
43
+ * `loadType=initial` returns 10 holdings while `totalNumberOfHoldings` still says 108. The
44
+ * count the issuer states about itself is therefore the check: if it disagrees with the array
45
+ * it shipped, the file is short and no weight computed from it means anything.
46
+ */
47
+ /**
48
+ * Parse an iShares holdings CSV, refusing the HTML-body-with-HTTP-200 trap.
49
+ *
50
+ * The retired `.ajax?fileType=csv` endpoint returns status 200 and `Content-Type: text/csv`
51
+ * and a full HTML product page as the body. Nothing about the response envelope reveals this,
52
+ * so the check is on the first bytes of the body: a status code and a content type are both
53
+ * claims made by the server, and here both are false.
54
+ */
55
+ /**
56
+ * Do the published weights add up to the whole fund?
57
+ *
58
+ * A holdings file that sums to 0.62 is a truncated download, not a concentrated fund, and it
59
+ * is the failure every adapter here can suffer. This never repairs the weights by rescaling:
60
+ * rescaling a truncated file produces a plausible-looking portfolio that does not exist.
61
+ */
62
+ /** RFC4180-ish field splitter; iShares quotes every value and embeds commas inside them. */
63
+ /** Issuer numbers arrive as "1,167,700,000.00", "7.75" or "1.81367013E8". */
64
+ /**
65
+ * The issuers state their date in three different shapes and none of them is ISO. A date this
66
+ * module cannot parse becomes null, which downstream reports as a gap -- it never falls back
67
+ * to "today", because stamping a run time onto an issuer's file is how stale holdings start
68
+ * looking fresh.
69
+ */
70
+ const MONTHS = Object.freeze({
71
+ jan: "01", feb: "02", mar: "03", apr: "04", may: "05", jun: "06",
72
+ jul: "07", aug: "08", sep: "09", oct: "10", nov: "11", dec: "12",
73
+ });
74
+
75
+ export function isoDate(text) {
76
+ const raw = String(text || "").trim().replace(/^as of\s+/iu, "");
77
+ if (!raw) return null;
78
+ const iso = /^(\d{4}-\d{2}-\d{2})/u.exec(raw);
79
+ if (iso) return iso[1];
80
+ // "Jul 27, 2026" (iShares)
81
+ const mdy = /^([A-Za-z]{3})[a-z]*\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(raw);
82
+ if (mdy && MONTHS[mdy[1].toLowerCase()]) {
83
+ return `${mdy[3]}-${MONTHS[mdy[1].toLowerCase()]}-${String(mdy[2]).padStart(2, "0")}`;
84
+ }
85
+ // "27-Jul-2026" (SSGA)
86
+ const dmy = /^(\d{1,2})-([A-Za-z]{3})[a-z]*-(\d{4})$/u.exec(raw);
87
+ if (dmy && MONTHS[dmy[2].toLowerCase()]) {
88
+ return `${dmy[3]}-${MONTHS[dmy[2].toLowerCase()]}-${String(dmy[1]).padStart(2, "0")}`;
89
+ }
90
+ return null;
91
+ }
92
+
93
+ export function numeric(value) {
94
+ if (value === null || value === undefined) return null;
95
+ const cleaned = String(value).replace(/[",\s%]/gu, "");
96
+ if (!cleaned || cleaned === "-") return null;
97
+ const parsed = Number(cleaned);
98
+ return Number.isFinite(parsed) ? parsed : null;
99
+ }
100
+
101
+ export function csvFields(line) {
102
+ const out = [];
103
+ let field = "";
104
+ let quoted = false;
105
+ for (let i = 0; i < line.length; i += 1) {
106
+ const ch = line[i];
107
+ if (quoted) {
108
+ if (ch === '"' && line[i + 1] === '"') { field += '"'; i += 1; continue; }
109
+ if (ch === '"') { quoted = false; continue; }
110
+ field += ch;
111
+ continue;
112
+ }
113
+ if (ch === '"') { quoted = true; continue; }
114
+ if (ch === ",") { out.push(field); field = ""; continue; }
115
+ field += ch;
116
+ }
117
+ out.push(field);
118
+ return out.map((cell) => cell.trim());
119
+ }
120
+
121
+ export function checkWeightSum(holdings, { tolerance = WEIGHT_SUM_TOLERANCE } = {}) {
122
+ const sum = (holdings || []).reduce((total, row) => total + (Number(row?.weight) || 0), 0);
123
+ const ok = Number.isFinite(sum) && Math.abs(sum - 1) <= tolerance;
124
+ return {
125
+ ok,
126
+ sum: Number(sum.toFixed(6)),
127
+ tolerance,
128
+ gap: ok ? null : `holdings weights sum to ${sum.toFixed(4)}, not ~1 (tolerance ${tolerance}); treat the file as incomplete`,
129
+ };
130
+ }
131
+
132
+ export function parseIsharesHoldingsCsv(csv, { symbol = null } = {}) {
133
+ const text = String(csv || "");
134
+ const head = text.slice(0, 512).trimStart();
135
+ if (!head) throw new Error("iShares holdings response was empty");
136
+ if (head.startsWith("<") || /<!doctype html|<html[\s>]/iu.test(head)) {
137
+ throw new Error("iShares returned an HTML document with a CSV content-type (the retired .ajax holdings path does this at HTTP 200); use the /x/latest-holdings.csv path");
138
+ }
139
+
140
+ const lines = text.split(/\r?\n/);
141
+ const headerIndex = lines.findIndex((line) => /^"?Ticker"?\s*,\s*"?Name"?/u.test(line.trim()));
142
+ if (headerIndex < 0) throw new Error("iShares CSV has no `Ticker,Name` holdings header row");
143
+
144
+ // The block above the table carries the fund name, the stated date and shares outstanding.
145
+ const meta = new Map();
146
+ for (const line of lines.slice(0, headerIndex)) {
147
+ const cells = csvFields(line);
148
+ if (cells.length >= 2 && cells[0]) meta.set(cells[0].replace(/:$/u, "").toLowerCase(), cells[1]);
149
+ }
150
+
151
+ const columns = csvFields(lines[headerIndex]);
152
+ const at = (row, label) => {
153
+ const index = columns.findIndex((column) => column.toLowerCase() === label);
154
+ return index >= 0 ? row[index] : null;
155
+ };
156
+
157
+ const holdings = [];
158
+ for (const line of lines.slice(headerIndex + 1)) {
159
+ if (!line.trim()) break; // a blank line ends the table; disclosure sections follow
160
+ const row = csvFields(line);
161
+ const ticker = at(row, "ticker");
162
+ const weight = numeric(at(row, "weight (%)"));
163
+ if (!ticker || weight === null) continue;
164
+ holdings.push(holding({
165
+ ticker,
166
+ name: at(row, "name"),
167
+ weight: weight / 100,
168
+ units: numeric(at(row, "quantity")),
169
+ asset_class: at(row, "asset class"),
170
+ }));
171
+ }
172
+ if (!holdings.length) throw new Error("iShares CSV holdings table has no rows");
173
+
174
+ return {
175
+ symbol,
176
+ issuer: "ishares",
177
+ fund_name: lines[0] ? csvFields(lines[0])[0] || null : null,
178
+ as_of: isoDate(meta.get("fund holdings as of")),
179
+ shares_outstanding: numeric(meta.get("shares outstanding")),
180
+ holdings,
181
+ };
182
+ }
183
+
184
+ export function parseInvescoHoldings(payload, { symbol = null } = {}) {
185
+ const data = typeof payload === "string" ? JSON.parse(payload) : payload;
186
+ if (!data || typeof data !== "object") throw new Error("invesco holdings payload was not an object");
187
+ const rows = data.holdings;
188
+ if (!Array.isArray(rows) || !rows.length) throw new Error("invesco holdings payload carried no holdings array");
189
+
190
+ const declared = Number(data.totalNumberOfHoldings);
191
+ if (Number.isFinite(declared) && declared !== rows.length) {
192
+ throw new Error(`invesco returned ${rows.length} holdings but declares ${declared}; the response is truncated (loadType=initial does this at HTTP 200)`);
193
+ }
194
+
195
+ const asOf = isoDate(data.effectiveDate || data.effectiveBusinessDate);
196
+ if (!asOf) throw new Error("invesco holdings payload carried no parseable effectiveDate");
197
+
198
+ const holdings = rows.map((row) => holding({
199
+ ticker: row?.ticker,
200
+ name: row?.issuerName,
201
+ weight: (numeric(row?.percentageOfTotalNetAssets) ?? 0) / 100,
202
+ units: numeric(row?.units),
203
+ // Nasdaq-100 files carry index futures, currency collateral and several cash sleeves
204
+ // alongside common stock. Look-through must be able to tell them apart.
205
+ asset_class: row?.securityTypeName || null,
206
+ }));
207
+
208
+ return { symbol, issuer: "invesco", fund_name: null, as_of: asOf, shares_outstanding: null, holdings };
209
+ }
210
+
211
+ export function parseVanguardHoldings(pages, { symbol = null } = {}) {
212
+ const list = (Array.isArray(pages) ? pages : [pages])
213
+ .map((page) => (typeof page === "string" ? JSON.parse(page) : page))
214
+ .filter(Boolean);
215
+ if (!list.length) throw new Error("vanguard holdings response was empty");
216
+
217
+ const entities = list.flatMap((page) => (Array.isArray(page?.fund?.entity) ? page.fund.entity : []));
218
+ if (!entities.length) throw new Error("vanguard holdings payload carried no entities");
219
+
220
+ const declared = Number(list[0]?.size);
221
+ if (Number.isFinite(declared) && declared !== entities.length) {
222
+ throw new Error(`vanguard returned ${entities.length} holdings but declares ${declared}; pagination is incomplete (the payload's own next link points at the dead api.vanguard.com host)`);
223
+ }
224
+
225
+ const asOf = isoDate(String(list[0]?.asOfDate || "").slice(0, 10));
226
+ if (!asOf) throw new Error("vanguard holdings payload carried no parseable asOfDate");
227
+
228
+ const holdings = entities.map((row) => holding({
229
+ ticker: row?.ticker,
230
+ name: row?.longName || row?.shortName,
231
+ weight: (numeric(row?.percentWeight) ?? 0) / 100,
232
+ units: numeric(row?.sharesHeld),
233
+ asset_class: row?.secMainType || null,
234
+ }));
235
+
236
+ return {
237
+ symbol,
238
+ issuer: "vanguard",
239
+ fund_name: null,
240
+ as_of: asOf,
241
+ shares_outstanding: null,
242
+ holdings,
243
+ // Month-end, not daily. A reader comparing this to a daily iShares file needs to know.
244
+ cadence: "month_end",
245
+ };
246
+ }
247
+
248
+ export function parseSsgaHoldingsXlsx(buffer, { symbol = null } = {}) {
249
+ const entries = unzip(buffer);
250
+ const sheet = entries.get("xl/worksheets/sheet1.xml");
251
+ if (!sheet) throw new Error("SSGA workbook has no xl/worksheets/sheet1.xml");
252
+ const sharedXml = entries.get("xl/sharedStrings.xml");
253
+ const shared = sharedXml
254
+ ? [...sharedXml().matchAll(/<si>([\s\S]*?)<\/si>/gu)].map((match) => xmlText(match[1]))
255
+ : [];
256
+ const rows = xlsxRows(sheet(), shared);
257
+
258
+ const label = (needle) => {
259
+ const row = rows.find((cells) => String(cells?.[0] || "").toLowerCase().startsWith(needle));
260
+ return row ? row.slice(1).find((cell) => cell) || null : null;
261
+ };
262
+
263
+ const headerIndex = rows.findIndex((cells) => {
264
+ const lower = (cells || []).map((cell) => String(cell || "").toLowerCase());
265
+ return lower.includes("ticker") && lower.includes("weight");
266
+ });
267
+ if (headerIndex < 0) throw new Error("SSGA workbook has no `Ticker`/`Weight` header row");
268
+ const columns = rows[headerIndex].map((cell) => String(cell || "").toLowerCase());
269
+ const at = (row, name) => {
270
+ const index = columns.indexOf(name);
271
+ return index >= 0 ? row[index] : null;
272
+ };
273
+
274
+ const holdings = [];
275
+ for (const row of rows.slice(headerIndex + 1)) {
276
+ const ticker = at(row, "ticker");
277
+ const weight = numeric(at(row, "weight"));
278
+ if (!ticker || weight === null) continue;
279
+ holdings.push(holding({
280
+ ticker,
281
+ name: at(row, "name"),
282
+ weight: weight / 100,
283
+ units: numeric(at(row, "shares held")),
284
+ asset_class: at(row, "sector"),
285
+ }));
286
+ }
287
+ if (!holdings.length) throw new Error("SSGA workbook holdings table has no rows");
288
+
289
+ return {
290
+ symbol,
291
+ issuer: "ssga",
292
+ fund_name: label("fund name"),
293
+ as_of: isoDate(label("holdings")),
294
+ shares_outstanding: numeric(label("shares outstanding")),
295
+ holdings,
296
+ };
297
+ }