alphacouncil-agent 0.9.4 → 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 (478) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.claude-plugin/plugin.json +2 -2
  3. package/.codex-plugin/plugin.json +4 -4
  4. package/AGENTS.md +22 -7
  5. package/CHANGELOG.md +97 -0
  6. package/CLAUDE.md +21 -3
  7. package/README.ja.md +9 -5
  8. package/README.md +15 -7
  9. package/README.zh-CN.md +12 -7
  10. package/data/authored/core-seats.mjs +808 -0
  11. package/data/authored/growth-seats.mjs +581 -0
  12. package/data/authored/index.mjs +114 -0
  13. package/data/authored/quant-seats.mjs +564 -0
  14. package/data/authored/value-seats.mjs +663 -0
  15. package/data/build-profile.v1.json +2 -1
  16. package/data/council-evaluation-protocol.v1.json +7 -4
  17. package/data/master-selector-method-locales.v1.mjs +10 -0
  18. package/data/persona-v3-ai-assisted-solo-profile.v1.json +2 -2
  19. package/data/persona-v3-build-specs.v1.mjs +60 -3
  20. package/docs/INSTALL.md +4 -4
  21. package/docs/personas.md +2 -1
  22. package/docs/plans/v1.0-roadmap.md +487 -0
  23. package/docs/releases/v0.9.5.md +96 -0
  24. package/docs/releases/v1.0.0.md +164 -0
  25. package/docs/report-contract.md +30 -6
  26. package/knowledge/ai-assisted-solo/experiments/runs/a.json +13 -13
  27. package/knowledge/ai-assisted-solo/experiments/runs/b.json +2 -2
  28. package/knowledge/ai-assisted-solo/experiments/runs/c.json +2 -2
  29. package/knowledge/ai-assisted-solo/experiments/runs/d13.json +126 -126
  30. package/knowledge/ai-assisted-solo/experiments/runs/d26.json +274 -254
  31. package/knowledge/ai-assisted-solo/experiments/runs/e-d13.json +129 -129
  32. package/knowledge/ai-assisted-solo/experiments/runs/e-d26.json +277 -257
  33. package/knowledge/ai-assisted-solo/experiments/runs/h_ai_reference.json +278 -258
  34. package/knowledge/ai-assisted-solo/experiments/simulation-input.json +7278 -556
  35. package/knowledge/ai-assisted-solo/experiments/simulation-manifest.json +22 -22
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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
  41. 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
  42. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/expected_return_over_long_bond.ai-review.json +277 -0
  43. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/fundamental_expected_return.ai-review.json +277 -0
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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
  56. 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
  57. 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
  58. 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
  59. 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
  60. 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
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. 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
  69. 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
  70. 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
  71. 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
  72. 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
  73. 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
  74. 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
  75. 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
  76. 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
  77. 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
  78. 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
  79. 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
  80. 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
  81. 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
  82. 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
  83. 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
  84. 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
  85. 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
  86. 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
  87. 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
  88. 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
  89. 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
  90. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/review-manifest.json +288 -270
  91. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-adjudications/index.json +2 -2
  92. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-extractions/index.json +2 -2
  93. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-skeptic-reviews/index.json +2 -2
  94. package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-source-prereviews/index.json +6 -2
  95. package/knowledge/solo-test/masters/master_ackman/decision_policy.json +122 -11
  96. package/knowledge/solo-test/masters/master_ackman/doctrine.jsonl +2 -2
  97. package/knowledge/solo-test/masters/master_ackman/manifest.json +13 -6
  98. package/knowledge/solo-test/masters/master_ackman/provisional-index.json +3 -3
  99. package/knowledge/solo-test/masters/master_ackman/sources.jsonl +1 -1
  100. package/knowledge/solo-test/masters/master_ackman/tools.json +56 -30
  101. package/knowledge/solo-test/masters/master_aschenbrenner/decision_policy.json +101 -10
  102. package/knowledge/solo-test/masters/master_aschenbrenner/doctrine.jsonl +2 -2
  103. package/knowledge/solo-test/masters/master_aschenbrenner/manifest.json +12 -4
  104. package/knowledge/solo-test/masters/master_aschenbrenner/provisional-index.json +3 -3
  105. package/knowledge/solo-test/masters/master_aschenbrenner/sources.jsonl +1 -1
  106. package/knowledge/solo-test/masters/master_aschenbrenner/tools.json +56 -30
  107. package/knowledge/solo-test/masters/master_asness/decision_policy.json +89 -10
  108. package/knowledge/solo-test/masters/master_asness/doctrine.jsonl +2 -2
  109. package/knowledge/solo-test/masters/master_asness/manifest.json +11 -4
  110. package/knowledge/solo-test/masters/master_asness/provisional-index.json +3 -3
  111. package/knowledge/solo-test/masters/master_asness/sources.jsonl +1 -1
  112. package/knowledge/solo-test/masters/master_asness/tools.json +56 -30
  113. package/knowledge/solo-test/masters/master_bogle/counterfactuals.jsonl +0 -0
  114. package/knowledge/solo-test/masters/master_bogle/decision_cases.jsonl +0 -0
  115. package/knowledge/solo-test/masters/master_bogle/decision_policy.json +170 -0
  116. package/knowledge/solo-test/masters/master_bogle/doctrine.jsonl +14 -0
  117. package/knowledge/solo-test/masters/master_bogle/evaluation/calibration_cases.jsonl +0 -0
  118. package/knowledge/solo-test/masters/master_bogle/evaluation/experiments.json +5 -0
  119. package/knowledge/solo-test/masters/master_bogle/evaluation/golden_cases.jsonl +0 -0
  120. package/knowledge/solo-test/masters/master_bogle/evaluation/pairwise_cases.jsonl +0 -0
  121. package/knowledge/solo-test/masters/master_bogle/failures.jsonl +0 -0
  122. package/knowledge/solo-test/masters/master_bogle/manifest.json +141 -0
  123. package/knowledge/solo-test/masters/master_bogle/memory_policy.json +5 -0
  124. package/knowledge/solo-test/masters/master_bogle/provisional-index.json +41 -0
  125. package/knowledge/solo-test/masters/master_bogle/research_policy.json +11 -0
  126. package/knowledge/solo-test/masters/master_bogle/sources.jsonl +1 -0
  127. package/knowledge/solo-test/masters/master_bogle/tools.json +120 -0
  128. package/knowledge/solo-test/masters/master_bogle/voice.en.md +7 -0
  129. package/knowledge/solo-test/masters/master_bogle/voice.zh.md +7 -0
  130. package/knowledge/solo-test/masters/master_buffett/decision_policy.json +102 -11
  131. package/knowledge/solo-test/masters/master_buffett/doctrine.jsonl +2 -2
  132. package/knowledge/solo-test/masters/master_buffett/manifest.json +10 -4
  133. package/knowledge/solo-test/masters/master_buffett/provisional-index.json +3 -3
  134. package/knowledge/solo-test/masters/master_buffett/sources.jsonl +1 -1
  135. package/knowledge/solo-test/masters/master_buffett/tools.json +55 -29
  136. package/knowledge/solo-test/masters/master_burry/decision_policy.json +102 -12
  137. package/knowledge/solo-test/masters/master_burry/doctrine.jsonl +2 -2
  138. package/knowledge/solo-test/masters/master_burry/manifest.json +12 -6
  139. package/knowledge/solo-test/masters/master_burry/provisional-index.json +3 -3
  140. package/knowledge/solo-test/masters/master_burry/sources.jsonl +1 -1
  141. package/knowledge/solo-test/masters/master_burry/tools.json +56 -30
  142. package/knowledge/solo-test/masters/master_cathie_wood/decision_policy.json +74 -12
  143. package/knowledge/solo-test/masters/master_cathie_wood/doctrine.jsonl +2 -2
  144. package/knowledge/solo-test/masters/master_cathie_wood/manifest.json +12 -6
  145. package/knowledge/solo-test/masters/master_cathie_wood/provisional-index.json +3 -3
  146. package/knowledge/solo-test/masters/master_cathie_wood/sources.jsonl +1 -1
  147. package/knowledge/solo-test/masters/master_cathie_wood/tools.json +56 -30
  148. package/knowledge/solo-test/masters/master_dalio/decision_policy.json +123 -16
  149. package/knowledge/solo-test/masters/master_dalio/doctrine.jsonl +2 -2
  150. package/knowledge/solo-test/masters/master_dalio/manifest.json +10 -4
  151. package/knowledge/solo-test/masters/master_dalio/provisional-index.json +3 -3
  152. package/knowledge/solo-test/masters/master_dalio/sources.jsonl +1 -1
  153. package/knowledge/solo-test/masters/master_dalio/tools.json +56 -30
  154. package/knowledge/solo-test/masters/master_damodaran/decision_policy.json +58 -10
  155. package/knowledge/solo-test/masters/master_damodaran/doctrine.jsonl +2 -2
  156. package/knowledge/solo-test/masters/master_damodaran/manifest.json +9 -4
  157. package/knowledge/solo-test/masters/master_damodaran/provisional-index.json +3 -3
  158. package/knowledge/solo-test/masters/master_damodaran/sources.jsonl +1 -1
  159. package/knowledge/solo-test/masters/master_damodaran/tools.json +54 -28
  160. package/knowledge/solo-test/masters/master_druckenmiller/decision_policy.json +89 -10
  161. package/knowledge/solo-test/masters/master_druckenmiller/doctrine.jsonl +2 -2
  162. package/knowledge/solo-test/masters/master_druckenmiller/manifest.json +11 -4
  163. package/knowledge/solo-test/masters/master_druckenmiller/provisional-index.json +3 -3
  164. package/knowledge/solo-test/masters/master_druckenmiller/sources.jsonl +1 -1
  165. package/knowledge/solo-test/masters/master_druckenmiller/tools.json +55 -29
  166. package/knowledge/solo-test/masters/master_duan_yongping/decision_policy.json +138 -13
  167. package/knowledge/solo-test/masters/master_duan_yongping/doctrine.jsonl +2 -2
  168. package/knowledge/solo-test/masters/master_duan_yongping/manifest.json +17 -7
  169. package/knowledge/solo-test/masters/master_duan_yongping/provisional-index.json +3 -3
  170. package/knowledge/solo-test/masters/master_duan_yongping/sources.jsonl +1 -1
  171. package/knowledge/solo-test/masters/master_duan_yongping/tools.json +82 -30
  172. package/knowledge/solo-test/masters/master_fisher/decision_policy.json +102 -11
  173. package/knowledge/solo-test/masters/master_fisher/doctrine.jsonl +2 -2
  174. package/knowledge/solo-test/masters/master_fisher/manifest.json +13 -6
  175. package/knowledge/solo-test/masters/master_fisher/provisional-index.json +3 -3
  176. package/knowledge/solo-test/masters/master_fisher/sources.jsonl +1 -1
  177. package/knowledge/solo-test/masters/master_fisher/tools.json +58 -32
  178. package/knowledge/solo-test/masters/master_forensic_short/decision_policy.json +93 -14
  179. package/knowledge/solo-test/masters/master_forensic_short/doctrine.jsonl +2 -2
  180. package/knowledge/solo-test/masters/master_forensic_short/manifest.json +6 -4
  181. package/knowledge/solo-test/masters/master_forensic_short/provisional-index.json +3 -3
  182. package/knowledge/solo-test/masters/master_forensic_short/sources.jsonl +1 -1
  183. package/knowledge/solo-test/masters/master_forensic_short/tools.json +53 -27
  184. package/knowledge/solo-test/masters/master_graham/decision_policy.json +103 -12
  185. package/knowledge/solo-test/masters/master_graham/doctrine.jsonl +2 -2
  186. package/knowledge/solo-test/masters/master_graham/manifest.json +12 -4
  187. package/knowledge/solo-test/masters/master_graham/provisional-index.json +3 -3
  188. package/knowledge/solo-test/masters/master_graham/sources.jsonl +1 -1
  189. package/knowledge/solo-test/masters/master_graham/tools.json +67 -28
  190. package/knowledge/solo-test/masters/master_jhunjhunwala/decision_policy.json +77 -12
  191. package/knowledge/solo-test/masters/master_jhunjhunwala/doctrine.jsonl +2 -2
  192. package/knowledge/solo-test/masters/master_jhunjhunwala/manifest.json +11 -6
  193. package/knowledge/solo-test/masters/master_jhunjhunwala/provisional-index.json +3 -3
  194. package/knowledge/solo-test/masters/master_jhunjhunwala/sources.jsonl +1 -1
  195. package/knowledge/solo-test/masters/master_jhunjhunwala/tools.json +54 -28
  196. package/knowledge/solo-test/masters/master_klarman/decision_policy.json +105 -14
  197. package/knowledge/solo-test/masters/master_klarman/doctrine.jsonl +2 -2
  198. package/knowledge/solo-test/masters/master_klarman/manifest.json +8 -2
  199. package/knowledge/solo-test/masters/master_klarman/provisional-index.json +3 -3
  200. package/knowledge/solo-test/masters/master_klarman/sources.jsonl +1 -1
  201. package/knowledge/solo-test/masters/master_klarman/tools.json +55 -29
  202. package/knowledge/solo-test/masters/master_li_lu/decision_policy.json +101 -10
  203. package/knowledge/solo-test/masters/master_li_lu/doctrine.jsonl +2 -2
  204. package/knowledge/solo-test/masters/master_li_lu/manifest.json +13 -6
  205. package/knowledge/solo-test/masters/master_li_lu/provisional-index.json +3 -3
  206. package/knowledge/solo-test/masters/master_li_lu/sources.jsonl +1 -1
  207. package/knowledge/solo-test/masters/master_li_lu/tools.json +58 -32
  208. package/knowledge/solo-test/masters/master_lynch/decision_policy.json +127 -16
  209. package/knowledge/solo-test/masters/master_lynch/doctrine.jsonl +2 -2
  210. package/knowledge/solo-test/masters/master_lynch/manifest.json +14 -6
  211. package/knowledge/solo-test/masters/master_lynch/provisional-index.json +3 -3
  212. package/knowledge/solo-test/masters/master_lynch/sources.jsonl +1 -1
  213. package/knowledge/solo-test/masters/master_lynch/tools.json +67 -28
  214. package/knowledge/solo-test/masters/master_marks/decision_policy.json +71 -9
  215. package/knowledge/solo-test/masters/master_marks/doctrine.jsonl +2 -2
  216. package/knowledge/solo-test/masters/master_marks/manifest.json +11 -6
  217. package/knowledge/solo-test/masters/master_marks/provisional-index.json +3 -3
  218. package/knowledge/solo-test/masters/master_marks/sources.jsonl +1 -1
  219. package/knowledge/solo-test/masters/master_marks/tools.json +54 -28
  220. package/knowledge/solo-test/masters/master_munger/decision_policy.json +141 -16
  221. package/knowledge/solo-test/masters/master_munger/doctrine.jsonl +2 -2
  222. package/knowledge/solo-test/masters/master_munger/manifest.json +10 -6
  223. package/knowledge/solo-test/masters/master_munger/provisional-index.json +3 -3
  224. package/knowledge/solo-test/masters/master_munger/sources.jsonl +1 -1
  225. package/knowledge/solo-test/masters/master_munger/tools.json +52 -26
  226. package/knowledge/solo-test/masters/master_natenberg/decision_policy.json +59 -11
  227. package/knowledge/solo-test/masters/master_natenberg/doctrine.jsonl +2 -2
  228. package/knowledge/solo-test/masters/master_natenberg/manifest.json +9 -6
  229. package/knowledge/solo-test/masters/master_natenberg/provisional-index.json +3 -3
  230. package/knowledge/solo-test/masters/master_natenberg/sources.jsonl +1 -1
  231. package/knowledge/solo-test/masters/master_natenberg/tools.json +50 -24
  232. package/knowledge/solo-test/masters/master_pabrai/decision_policy.json +125 -14
  233. package/knowledge/solo-test/masters/master_pabrai/doctrine.jsonl +2 -2
  234. package/knowledge/solo-test/masters/master_pabrai/manifest.json +8 -2
  235. package/knowledge/solo-test/masters/master_pabrai/provisional-index.json +3 -3
  236. package/knowledge/solo-test/masters/master_pabrai/sources.jsonl +1 -1
  237. package/knowledge/solo-test/masters/master_pabrai/tools.json +55 -29
  238. package/knowledge/solo-test/masters/master_simons/decision_policy.json +59 -11
  239. package/knowledge/solo-test/masters/master_simons/doctrine.jsonl +2 -2
  240. package/knowledge/solo-test/masters/master_simons/manifest.json +8 -4
  241. package/knowledge/solo-test/masters/master_simons/provisional-index.json +3 -3
  242. package/knowledge/solo-test/masters/master_simons/sources.jsonl +1 -1
  243. package/knowledge/solo-test/masters/master_simons/tools.json +43 -30
  244. package/knowledge/solo-test/masters/master_sinclair/decision_policy.json +59 -11
  245. package/knowledge/solo-test/masters/master_sinclair/doctrine.jsonl +2 -2
  246. package/knowledge/solo-test/masters/master_sinclair/manifest.json +8 -6
  247. package/knowledge/solo-test/masters/master_sinclair/provisional-index.json +3 -3
  248. package/knowledge/solo-test/masters/master_sinclair/sources.jsonl +1 -1
  249. package/knowledge/solo-test/masters/master_sinclair/tools.json +54 -28
  250. package/knowledge/solo-test/masters/master_soros/decision_policy.json +98 -10
  251. package/knowledge/solo-test/masters/master_soros/doctrine.jsonl +2 -2
  252. package/knowledge/solo-test/masters/master_soros/manifest.json +10 -7
  253. package/knowledge/solo-test/masters/master_soros/provisional-index.json +3 -3
  254. package/knowledge/solo-test/masters/master_soros/sources.jsonl +1 -1
  255. package/knowledge/solo-test/masters/master_soros/tools.json +54 -28
  256. package/knowledge/solo-test/masters/master_taleb/decision_policy.json +124 -13
  257. package/knowledge/solo-test/masters/master_taleb/doctrine.jsonl +2 -2
  258. package/knowledge/solo-test/masters/master_taleb/manifest.json +9 -5
  259. package/knowledge/solo-test/masters/master_taleb/provisional-index.json +3 -3
  260. package/knowledge/solo-test/masters/master_taleb/sources.jsonl +1 -1
  261. package/knowledge/solo-test/masters/master_taleb/tools.json +50 -24
  262. package/knowledge/solo-test/masters/master_thorp/decision_policy.json +61 -13
  263. package/knowledge/solo-test/masters/master_thorp/doctrine.jsonl +2 -2
  264. package/knowledge/solo-test/masters/master_thorp/manifest.json +11 -6
  265. package/knowledge/solo-test/masters/master_thorp/provisional-index.json +3 -3
  266. package/knowledge/solo-test/masters/master_thorp/sources.jsonl +1 -1
  267. package/knowledge/solo-test/masters/master_thorp/tools.json +56 -30
  268. package/knowledge/solo-test/persona-v3-solo-test-formulas/compilation-manifest.json +290 -264
  269. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/components/tools.json +58 -32
  270. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  271. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
  272. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/components/tools.json +58 -32
  273. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  274. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/price_implied_cash_yield.derived-proxy-evidence.json +76 -0
  275. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/components/tools.json +58 -32
  276. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/nominal_earnings_yield_gap.derived-proxy-evidence.json +76 -0
  277. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/real_earnings_yield_gap.derived-proxy-evidence.json +76 -0
  278. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/components/tools.json +120 -0
  279. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/expected_return_over_long_bond.derived-proxy-evidence.json +77 -0
  280. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/fundamental_expected_return.derived-proxy-evidence.json +76 -0
  281. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/components/tools.json +57 -31
  282. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  283. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
  284. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/components/tools.json +58 -32
  285. 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
  286. 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
  287. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/components/tools.json +58 -32
  288. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/current_cash_yield.derived-proxy-evidence.json +76 -0
  289. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  290. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/components/tools.json +58 -32
  291. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
  292. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/real_curve_slope.derived-proxy-evidence.json +76 -0
  293. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/components/tools.json +56 -30
  294. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/implied_equity_risk_premium.derived-proxy-evidence.json +76 -0
  295. 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
  296. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/components/tools.json +57 -31
  297. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_curve_impulse.derived-proxy-evidence.json +76 -0
  298. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
  299. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/components/tools.json +84 -32
  300. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/five_year_opportunity_cost.derived-proxy-evidence.json +102 -0
  301. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
  302. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/components/tools.json +60 -34
  303. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
  304. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/reinvestment_spread.derived-proxy-evidence.json +76 -0
  305. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/components/tools.json +55 -29
  306. 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
  307. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/cash_cover_of_leverage.derived-proxy-evidence.json +76 -0
  308. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/components/tools.json +69 -30
  309. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/defensive_hurdle_base.derived-proxy-evidence.json +89 -0
  310. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/half_normalised_earnings_yield.derived-proxy-evidence.json +76 -0
  311. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/components/tools.json +56 -30
  312. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/cash_quality_gap.derived-proxy-evidence.json +76 -0
  313. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/real_structural_growth.derived-proxy-evidence.json +76 -0
  314. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/components/tools.json +57 -31
  315. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/downside_asset_coverage.derived-proxy-evidence.json +76 -0
  316. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  317. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/components/tools.json +60 -34
  318. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/cash_backed_decade_return.derived-proxy-evidence.json +76 -0
  319. 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
  320. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/components/tools.json +69 -30
  321. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/growth_justified_capitalisation.derived-proxy-evidence.json +89 -0
  322. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  323. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/components/tools.json +56 -30
  324. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
  325. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/equity_over_corporate_debt.derived-proxy-evidence.json +76 -0
  326. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/components/tools.json +54 -28
  327. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
  328. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/reported_earnings_cash_gap.derived-proxy-evidence.json +76 -0
  329. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/components/tools.json +52 -26
  330. 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
  331. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
  332. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/components/tools.json +57 -31
  333. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor_coverage.derived-proxy-evidence.json +76 -0
  334. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
  335. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/components/tools.json +45 -32
  336. 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
  337. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/session_move_over_implied.derived-proxy-evidence.json +77 -0
  338. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/components/tools.json +56 -30
  339. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
  340. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/volatility_per_unit_of_width.derived-proxy-evidence.json +76 -0
  341. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/components/tools.json +56 -30
  342. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
  343. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/financing_burden.derived-proxy-evidence.json +76 -0
  344. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/components/tools.json +52 -26
  345. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
  346. 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
  347. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/components/tools.json +58 -32
  348. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_per_unit_of_volatility.derived-proxy-evidence.json +77 -0
  349. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/net_edge.derived-proxy-evidence.json +76 -0
  350. package/mcp/lib/breadth.mjs +122 -0
  351. package/mcp/lib/constants.mjs +15 -0
  352. package/mcp/lib/damodaran.mjs +119 -0
  353. package/mcp/lib/fred.mjs +246 -0
  354. package/mcp/lib/fund-holdings-parsers.mjs +297 -0
  355. package/mcp/lib/fundamentals.mjs +801 -0
  356. package/mcp/lib/funds.mjs +750 -0
  357. package/mcp/lib/gates.mjs +71 -4
  358. package/mcp/lib/grounding.mjs +188 -36
  359. package/mcp/lib/index-aggregate.mjs +718 -0
  360. package/mcp/lib/insider-ownership.mjs +149 -0
  361. package/mcp/lib/instrument-facts.mjs +557 -0
  362. package/mcp/lib/instruments.mjs +191 -0
  363. package/mcp/lib/markdown.mjs +216 -43
  364. package/mcp/lib/master-catalog.mjs +4 -0
  365. package/mcp/lib/orchestrator.mjs +173 -29
  366. package/mcp/lib/packets.mjs +59 -6
  367. package/mcp/lib/personas/engine.mjs +23 -10
  368. package/mcp/lib/personas-v3/deterministic-executor.mjs +13 -2
  369. package/mcp/lib/personas-v3/ga-external-evidence.mjs +3 -2
  370. package/mcp/lib/personas-v3/ga-gate.mjs +2 -1
  371. package/mcp/lib/personas-v3/ga-package-evidence.mjs +5 -4
  372. package/mcp/lib/personas-v3/grounding-adapter.mjs +309 -2
  373. package/mcp/lib/personas-v3/production-root.mjs +5 -4
  374. package/mcp/lib/personas-v3/release-formula-evidence.mjs +14 -7
  375. package/mcp/lib/personas-v3/release-source-evidence.mjs +2 -1
  376. package/mcp/lib/personas-v3/releases.mjs +5 -4
  377. package/mcp/lib/personas-v3/runtime-release-integrity.mjs +6 -5
  378. package/mcp/lib/personas-v3/semantic-source-adjudication.mjs +2 -1
  379. package/mcp/lib/personas-v3/semantic-source-extraction.mjs +2 -1
  380. package/mcp/lib/personas-v3/semantic-source-skeptic-review.mjs +2 -1
  381. package/mcp/lib/personas-v3/source-review-operations.mjs +3 -2
  382. package/mcp/lib/personas-v3/staging.mjs +22 -3
  383. package/mcp/lib/prompts.mjs +87 -3
  384. package/mcp/lib/quotes.mjs +5 -0
  385. package/mcp/lib/rpc.mjs +27 -10
  386. package/mcp/lib/run-store.mjs +5 -3
  387. package/mcp/lib/sec.mjs +32 -0
  388. package/mcp/lib/tables.mjs +11 -0
  389. package/mcp/lib/voice.mjs +122 -0
  390. package/mcp/lib/xbrl-aggregates.mjs +153 -0
  391. package/mcp/lib/xbrl-series.mjs +339 -0
  392. package/mcp/lib/xlsx.mjs +155 -0
  393. package/package.json +4 -4
  394. package/personas/masters/masters-value/bogle.md +145 -0
  395. package/schemas/council-evaluation-protocol-v1.schema.json +2 -2
  396. package/schemas/persona-v3-ai-assisted-solo-profile-v1.schema.json +2 -2
  397. package/schemas/persona-v3-ai-machine-simulation-v1.schema.json +1 -1
  398. package/schemas/persona-v3-build-spec-v1.schema.json +3 -3
  399. package/schemas/persona-v3-release-formula-review-evidence-v1.schema.json +3 -3
  400. package/schemas/persona-v3-release-manifest-v1.schema.json +6 -6
  401. package/schemas/persona-v3-release-source-review-evidence-v1.schema.json +3 -3
  402. package/schemas/persona-v3-tool-graph-v1.schema.json +1 -1
  403. package/schemas/source-review-batch-v1.schema.json +9 -9
  404. package/scripts/assemble-persona-v3-release.mjs +3 -2
  405. package/scripts/build-persona-v3-solo-test-packs.mjs +6 -8
  406. package/scripts/check-persona-v3-ga.mjs +1 -1
  407. package/scripts/check-persona-v3-production-candidates.mjs +1 -1
  408. package/scripts/compile-persona-v3-formulas.mjs +19 -18
  409. package/scripts/doctor.mjs +11 -9
  410. package/scripts/export-persona-source-review-batch.mjs +1 -1
  411. package/scripts/generate-persona-v3-drafts.mjs +2 -2
  412. package/scripts/lib/build-profile.mjs +24 -0
  413. package/scripts/lib/council-evaluation-protocol.mjs +7 -6
  414. package/scripts/lib/host-capabilities.mjs +2 -1
  415. package/scripts/lib/packaged-host-parity.mjs +9 -3
  416. package/scripts/lib/persona-v3-ai-assisted-solo-status.mjs +6 -4
  417. package/scripts/lib/persona-v3-ai-formula-review.mjs +6 -5
  418. package/scripts/lib/persona-v3-ai-machine-simulations.mjs +32 -4
  419. package/scripts/lib/persona-v3-build-specs.mjs +3 -2
  420. package/scripts/lib/persona-v3-draft-packs.mjs +2 -2
  421. package/scripts/lib/persona-v3-formula-pipeline.mjs +11 -10
  422. package/scripts/lib/persona-v3-production-candidates.mjs +10 -9
  423. package/scripts/lib/persona-v3-solo-formula-pipeline.mjs +182 -16
  424. package/scripts/lib/persona-v3-solo-test-packs.mjs +112 -11
  425. package/scripts/package-smoke.mjs +2 -1
  426. package/scripts/report-persona-corpus-gaps.mjs +4 -1
  427. package/scripts/review-persona-v3-solo-formulas.mjs +12 -8
  428. package/scripts/scaffold-persona-v3-staging.mjs +1 -1
  429. package/skills/agent-skills-governance/SKILL.md +8 -2
  430. package/skills/alphacouncil-agent/SKILL.md +12 -4
  431. package/skills/public-equity-investing/SKILL.md +17 -0
  432. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/change_value_bridge.derived-proxy-evidence.json +0 -64
  433. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/power_map.derived-proxy-evidence.json +0 -64
  434. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/compute_power_bridge.derived-proxy-evidence.json +0 -64
  435. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/timeline_reverse_valuation.derived-proxy-evidence.json +0 -64
  436. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/crowding_cost_stress.derived-proxy-evidence.json +0 -64
  437. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/factor_decomposer.derived-proxy-evidence.json +0 -64
  438. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/incremental_returns.derived-proxy-evidence.json +0 -64
  439. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_rebuilder.derived-proxy-evidence.json +0 -64
  440. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/capital_structure_reader.derived-proxy-evidence.json +0 -64
  441. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/mispricing_carry.derived-proxy-evidence.json +0 -64
  442. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/capture_valuation_bridge.derived-proxy-evidence.json +0 -64
  443. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/cost_adoption_curve.derived-proxy-evidence.json +0 -64
  444. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/debt_driver_stress.derived-proxy-evidence.json +0 -64
  445. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/regime_classifier.derived-proxy-evidence.json +0 -64
  446. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/story_dcf.derived-proxy-evidence.json +0 -64
  447. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/inflection_payoff.derived-proxy-evidence.json +0 -64
  448. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_revision_map.derived-proxy-evidence.json +0 -64
  449. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/opportunity_cost.derived-proxy-evidence.json +0 -64
  450. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/user_value_evidence.derived-proxy-evidence.json +0 -64
  451. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/research_productivity.derived-proxy-evidence.json +0 -64
  452. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/scuttlebutt_graph.derived-proxy-evidence.json +0 -64
  453. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/borrow_catalyst.derived-proxy-evidence.json +0 -64
  454. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/asset_floor.derived-proxy-evidence.json +0 -64
  455. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/normalized_earnings.derived-proxy-evidence.json +0 -64
  456. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/penetration_liquidity.derived-proxy-evidence.json +0 -64
  457. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/promoter_governance.derived-proxy-evidence.json +0 -64
  458. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/cash_catalyst_compare.derived-proxy-evidence.json +0 -64
  459. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/recovery_waterfall.derived-proxy-evidence.json +0 -64
  460. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/promise_integrity_ledger.derived-proxy-evidence.json +0 -64
  461. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/ten_year_return_bridge.derived-proxy-evidence.json +0 -64
  462. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/category_classifier.derived-proxy-evidence.json +0 -64
  463. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/story_numbers_check.derived-proxy-evidence.json +0 -64
  464. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/cycle_temperature.derived-proxy-evidence.json +0 -64
  465. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/implied_expectations.derived-proxy-evidence.json +0 -64
  466. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/failure_path_graph.derived-proxy-evidence.json +0 -64
  467. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/incentive_map.derived-proxy-evidence.json +0 -64
  468. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/discrete_payoff.derived-proxy-evidence.json +0 -64
  469. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor.derived-proxy-evidence.json +0 -64
  470. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/leakage_audit.derived-proxy-evidence.json +0 -64
  471. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/oos_cost_test.derived-proxy-evidence.json +0 -64
  472. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/net_edge_sizer.derived-proxy-evidence.json +0 -64
  473. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/realized_vol_forecast.derived-proxy-evidence.json +0 -64
  474. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reflexivity_graph.derived-proxy-evidence.json +0 -64
  475. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reversal_monitor.derived-proxy-evidence.json +0 -64
  476. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/payoff_ruin.derived-proxy-evidence.json +0 -64
  477. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_recalculator.derived-proxy-evidence.json +0 -64
  478. package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/fractional_kelly.derived-proxy-evidence.json +0 -64
@@ -111,6 +111,10 @@ const CARDS = Object.freeze({
111
111
  zh: ["Mohnish Pabrai,Pabrai Funds 创始人和 Dhandho 价值投资人", "寻找低永久损失、高不确定性、离散催化剂和明显不对称赔率。", "特殊情形、资产保护、克隆后独立复算和集中机会"],
112
112
  en: ["Mohnish Pabrai, Pabrai Funds founder and Dhandho value investor", "Looks for low permanent-loss risk, high uncertainty, discrete catalysts and strongly asymmetric odds.", "Special situations, asset protection, independently rebuilt clones and concentration"],
113
113
  },
114
+ master_bogle: {
115
+ zh: ["约翰·博格,先锋集团创始人和低成本指数投资的倡导者", "把一篮子的长期预期回报拆成股息率、盈利增长和估值变化,再减去持有成本。", "指数基金、ETF、整体市场预期回报和持有成本"],
116
+ en: ["John C. Bogle, Vanguard's founder and the advocate of low-cost index investing", "Decomposes a basket's long-run expected return into dividend yield, earnings growth and the change in valuation, then subtracts the cost of holding it.", "Index funds, ETFs, market-wide expected return and cost of ownership"],
117
+ },
114
118
  master_jhunjhunwala: {
115
119
  zh: ["Rakesh Jhunjhunwala,以长期集中持仓闻名的印度投资人", "结合印度结构成长、promoter 治理、现金质量、规模扩张和流动性。", "印度上市公司、结构渗透、治理和集中成长机会"],
116
120
  en: ["Rakesh Jhunjhunwala, an Indian investor known for long-duration concentrated holdings", "Combines Indian structural growth, promoter governance, cash quality, scaling and liquidity.", "Indian equities, structural penetration, governance and concentrated growth"],
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync } from "node:fs";
1
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { COUNCIL_MODES, DEBATE_ROLES, DEFAULT_TASKS, LIMITS, OUTPUT_MODES, QUICK_TASKS } from "./constants.mjs";
4
4
  import { invalidParams } from "./errors.mjs";
@@ -6,7 +6,7 @@ import { readJson, writeJson } from "./fsutil.mjs";
6
6
  import { registry } from "./personas/registry.mjs";
7
7
  import { assertReaderLanguage, isChineseLanguage, localized, resolveLanguage } from "./lang.mjs";
8
8
  import { cleanLog } from "./text.mjs";
9
- import { completenessStatus, verificationStatus } from "./gates.mjs";
9
+ import { completenessStatus, masterSeatIncomplete, verificationStatus } from "./gates.mjs";
10
10
  import { agentState, appendEvent, artifactPaths, existingDebate, runPath, runId, safeSymbol, saveRun, taskState, today, updateAgent, updateTask, writeSourceManifest, writeStatus } from "./run-store.mjs";
11
11
  import { writeAllAgentsMarkdown, writeAnalystMarkdownFiles, writeArtifactIndex, writeFinalArtifacts } from "./markdown.mjs";
12
12
  import { debateFailurePacket, debateFromCodex, debateQnaGate, dryDebate, dryPacket, extractJson, firstFailedDebateResult, managerFallback, mergeDebateRounds, normalizeDebate, normalizeMasterOpinion, normalizeMasterVoice, normalizePacket, rawRecordText } from "./packets.mjs";
@@ -290,9 +290,9 @@ export function visibleAgentSpecs(run, userPrompt = "") {
290
290
  ].filter(Boolean).join("\n"),
291
291
  output_contract: localized(run.language, { en: `Return one JSON debate packet with reader-facing fields in ${run.language}.`, zh: "只返回一个 JSON debate packet。", ja: "読者向けフィールドを日本語にした JSON debate packet を1つだけ返してください。", ko: "독자용 필드를 한국어로 작성한 JSON debate packet 하나만 반환하십시오." }),
292
292
  }));
293
- // The deterministic pass runs first and settles, for free, every seat whose method cannot
294
- // reach this security. Spawning an agent for a lens that has already declined is how the
295
- // previous design produced ten confident essays over a screen that computed nothing.
293
+ // The deterministic pass freezes every physical v3 stance before language generation.
294
+ // Visible v3 workers below may explain that frozen result after evidence completes, but
295
+ // cannot turn an out_of_scope method into a directional vote.
296
296
  const plan = planMasterSeats(run, selectedMasters(run));
297
297
  run.master_decisions = plan.decisions;
298
298
  run.fact_pack_hash = plan.shared_fact_pack_hash;
@@ -321,27 +321,44 @@ export function visibleAgentSpecs(run, userPrompt = "") {
321
321
  ko: "독자용 필드를 한국어로 작성한 JSON master opinion 하나만 반환하십시오.",
322
322
  }),
323
323
  }));
324
- // A declined seat is settled here rather than skipped: it is written straight into the
325
- // run as an out_of_scope opinion, so the completeness gate is satisfied and no agent is
326
- // ever spawned for a method that cannot look.
324
+ // Persist the deterministic fallback before the visible worker runs. It remains auditable
325
+ // if the host fails, but a full visible PM now waits for the returned explanation worker.
327
326
  if (plan.declined.length) {
328
327
  const byId = new Map((run.master_opinions || []).map((o) => [o.master, o]));
329
328
  for (const item of plan.declined) {
330
329
  if (!byId.has(item.id)) {
330
+ const fallback = declinedMasterOpinion(run, item);
331
331
  byId.set(item.id, attachMasterRuntimeProvenance(
332
332
  run,
333
333
  item.id,
334
- declinedMasterOpinion(run, item),
334
+ {
335
+ ...fallback,
336
+ voice_statement: fallback.voice_statement || fallback.summary || fallback.verdict,
337
+ voice_status: fallback.voice_status || "deterministic_fallback",
338
+ statement_origin: fallback.statement_origin || "deterministic_scope_fallback",
339
+ },
335
340
  item.engine,
336
341
  ));
337
342
  }
343
+ // A declined seat already carries a readable deterministic scope statement and a frozen
344
+ // out_of_scope stance no worker may change, so the explanation worker could not alter
345
+ // the record -- it only cost one sequential model turn per seat on a host with no
346
+ // fan-out. On a full bench that was 26 extra turns, which roughly doubled visible
347
+ // wall-clock. Seats that actually reached a decision still get their worker below.
348
+ const requiresVisibleVoice = false;
349
+ const alreadyVoiced = run.master_status?.[item.id]?.status === "completed"
350
+ && byId.get(item.id)?.voice_status === "completed";
351
+ const completed = alreadyVoiced || !requiresVisibleVoice;
338
352
  run.master_status[item.id] = {
339
353
  ...(run.master_status[item.id] || {}),
340
354
  master: item.id,
341
- status: "completed",
355
+ status: completed ? "completed" : "waiting",
342
356
  engine: item.engine || "v2_method_model",
343
357
  deterministic_decline: true,
344
- completed_at: new Date().toISOString(),
358
+ voice_required: requiresVisibleVoice,
359
+ completed_at: completed
360
+ ? (run.master_status[item.id]?.completed_at || new Date().toISOString())
361
+ : null,
345
362
  };
346
363
  }
347
364
  run.master_opinions = selectedMasters(run).map((id) => byId.get(id)).filter(Boolean);
@@ -357,13 +374,16 @@ export function visibleAgentSpecs(run, userPrompt = "") {
357
374
  item.engine,
358
375
  ));
359
376
  }
377
+ const alreadyVoiced = run.master_status?.[item.id]?.status === "completed"
378
+ && byId.get(item.id)?.voice_status === "completed";
360
379
  run.master_status[item.id] = {
361
380
  ...(run.master_status[item.id] || {}),
362
381
  master: item.id,
363
- status: "completed",
382
+ status: alreadyVoiced ? "completed" : "waiting",
364
383
  engine: item.engine,
365
384
  deterministic_execution: true,
366
- completed_at: new Date().toISOString(),
385
+ voice_required: true,
386
+ completed_at: alreadyVoiced ? run.master_status[item.id].completed_at : null,
367
387
  };
368
388
  }
369
389
  run.master_opinions = selectedMasters(run).map((id) => byId.get(id)).filter(Boolean);
@@ -378,10 +398,43 @@ export function visibleAgentSpecs(run, userPrompt = "") {
378
398
  updated_at: new Date().toISOString(),
379
399
  };
380
400
  }
401
+ const frozenById = new Map((run.master_opinions || []).map((opinion) => [opinion.master, opinion]));
402
+ const v3VoiceAgents = plan.completed
403
+ .filter((item) => item.engine === "v3_method_runtime")
404
+ .filter((item) => run.master_status?.[item.id]?.status !== "completed")
405
+ .map((item) => {
406
+ const frozenOpinion = frozenById.get(item.id);
407
+ return {
408
+ role: item.id,
409
+ engine: "v3_method_runtime",
410
+ worker_kind: "visible_method_voice",
411
+ frozen_stance: frozenOpinion?.stance || "out_of_scope",
412
+ title: `AlphaCouncil Agent ${run.symbol} ${item.id} method-seat explanation`,
413
+ prompt_template: [
414
+ masterVoicePrompt(item.id, run, frozenOpinion),
415
+ localized(run.language, {
416
+ en: "The main thread MUST append the completed Evidence JSON before launching this visible worker. Use it only to explain or challenge analyst interpretation; never change the frozen stance or add a fact.",
417
+ zh: "主线程必须在启动这个可见方法席前附上已完成的 Evidence JSON。它只能用于解释或质疑分析师解读;不得改变冻结立场,也不得新增事实。",
418
+ ja: "メインスレッドは、この可視メソッド席を起動する前に完成済み Evidence JSON を追加してください。分析担当の解釈を説明・検討する目的だけに使い、凍結済みスタンスの変更や事実追加は禁止です。",
419
+ ko: "메인 스레드는 이 표시형 방법론 좌석을 시작하기 전에 완료된 Evidence JSON을 추가해야 합니다. 분석가 해석을 설명·검토하는 데만 사용하고 동결된 입장을 바꾸거나 사실을 추가하지 마십시오.",
420
+ }),
421
+ ].join("\n\n"),
422
+ output_contract: localized(run.language, {
423
+ en: "Return one JSON method voice: master, acknowledged_stance, statement, key_findings, disagreements, what_would_change_my_mind, source_ids, confidence. acknowledged_stance must equal frozen_stance.",
424
+ zh: "只返回一个 JSON 方法席陈词:master、acknowledged_stance、statement、key_findings、disagreements、what_would_change_my_mind、source_ids、confidence;acknowledged_stance 必须等于冻结立场。",
425
+ ja: "master、acknowledged_stance、statement、key_findings、disagreements、what_would_change_my_mind、source_ids、confidence を持つ JSON を1つだけ返し、acknowledged_stance は凍結済みスタンスと一致させてください。",
426
+ ko: "master, acknowledged_stance, statement, key_findings, disagreements, what_would_change_my_mind, source_ids, confidence를 가진 JSON 하나만 반환하고 acknowledged_stance는 동결된 입장과 같아야 합니다.",
427
+ }),
428
+ };
429
+ });
430
+ master_agents.push(...v3VoiceAgents);
431
+ const orderedMasterAgents = selectedMasters(run)
432
+ .map((id) => master_agents.find((agent) => agent.role === id))
433
+ .filter(Boolean);
381
434
  saveRun(run);
382
435
  return {
383
436
  evidence_agents,
384
- master_agents,
437
+ master_agents: orderedMasterAgents,
385
438
  debate_agents,
386
439
  // Recorded, not hidden: a reader must be able to tell a method that judged from a method
387
440
  // that could not look, and neither from a seat that was never offered.
@@ -455,19 +508,90 @@ export function recordMasterOpinion(args) {
455
508
  if (!allowed.includes(args.master)) {
456
509
  throw invalidParams(`master ${args.master} was not selected for this run. Selected: ${allowed.join(", ") || "none"}`);
457
510
  }
511
+ const missingEvidence = (run.tasks || []).filter((task) => taskState(run, task).status !== "completed");
512
+ if (missingEvidence.length) {
513
+ throw invalidParams("record_master_opinion rejected: every planned evidence packet must complete first.", {
514
+ reason: "VISIBLE_MASTER_EVIDENCE_INCOMPLETE",
515
+ run_id: run.run_id,
516
+ missing_evidence: missingEvidence,
517
+ });
518
+ }
458
519
  const dir = runPath(run.run_id);
459
- const normalized = normalizeMasterOpinion(
460
- { ...(args.packet || {}), thread_id: args.thread_id },
461
- args.master,
462
- run,
463
- rawRecordText(args.packet),
464
- );
465
- assertVisibleReaderLanguage(masterReaderText(normalized), run, `visible master ${args.master}`);
466
- // A narrated stance that disagrees with the arithmetic does not get to win quietly. The
467
- // deterministic verdict stands and the disagreement is preserved on the record.
468
- const reconciled = reconcileMasterOpinion(run, args.master, normalized);
469
- const opinion = attachMasterRuntimeProvenance(run, args.master, reconciled.opinion, reconciled.engine);
470
- const { overridden } = reconciled;
520
+ const frozenOpinion = (run.master_opinions || []).find((item) => item.master === args.master);
521
+ const v3Voice = frozenOpinion?.engine === "v3_method_runtime"
522
+ || run.master_runtime_provenance?.[args.master]?.engine === "v3_method_runtime";
523
+ let opinion;
524
+ let overridden = false;
525
+ if (v3Voice) {
526
+ if (!frozenOpinion) throw invalidParams(`v3 master ${args.master} has no frozen deterministic opinion.`);
527
+ if (args.packet?.master !== args.master || args.packet?.acknowledged_stance !== frozenOpinion.stance) {
528
+ throw invalidParams("visible v3 method voice must acknowledge the exact frozen master and stance.", {
529
+ reason: "VISIBLE_MASTER_FROZEN_STANCE_MISMATCH",
530
+ run_id: run.run_id,
531
+ master: args.master,
532
+ expected_stance: frozenOpinion.stance,
533
+ supplied_master: args.packet?.master || null,
534
+ supplied_stance: args.packet?.acknowledged_stance || null,
535
+ });
536
+ }
537
+ const voice = normalizeMasterVoice(
538
+ args.packet,
539
+ args.master,
540
+ run,
541
+ frozenOpinion,
542
+ rawRecordText(args.packet),
543
+ );
544
+ assertVisibleReaderLanguage([
545
+ voice.statement,
546
+ ...(voice.key_findings || []),
547
+ ...(voice.disagreements || []),
548
+ ...(voice.what_would_change_my_mind || []),
549
+ ].filter(Boolean).join("\n"), run, `visible master voice ${args.master}`);
550
+ opinion = attachMasterRuntimeProvenance(run, args.master, {
551
+ ...frozenOpinion,
552
+ deterministic_summary: frozenOpinion.deterministic_summary || frozenOpinion.summary,
553
+ summary: voice.statement,
554
+ voice_statement: voice.statement,
555
+ voice_status: "completed",
556
+ voice_language: run.language,
557
+ statement_origin: "visible_method_voice_worker",
558
+ key_findings: voice.key_findings.length ? voice.key_findings : frozenOpinion.key_findings,
559
+ disagreements: voice.disagreements,
560
+ what_would_change_my_mind: voice.what_would_change_my_mind.length
561
+ ? voice.what_would_change_my_mind
562
+ : frozenOpinion.what_would_change_my_mind,
563
+ source_ids: [...new Set([...(frozenOpinion.source_ids || []), ...voice.source_ids])],
564
+ confidence: voice.confidence,
565
+ thread_id: args.thread_id,
566
+ dedicated_worker: {
567
+ status: "completed",
568
+ language: run.language,
569
+ execution_mode: "visible_host_thread",
570
+ thread_id: args.thread_id,
571
+ },
572
+ }, "v3_method_runtime");
573
+ } else {
574
+ const normalized = normalizeMasterOpinion(
575
+ { ...(args.packet || {}), thread_id: args.thread_id },
576
+ args.master,
577
+ run,
578
+ rawRecordText(args.packet),
579
+ );
580
+ assertVisibleReaderLanguage(masterReaderText(normalized), run, `visible master ${args.master}`);
581
+ // A narrated stance that disagrees with the arithmetic does not get to win quietly. The
582
+ // deterministic verdict stands and the disagreement is preserved on the record.
583
+ const reconciled = reconcileMasterOpinion(run, args.master, normalized);
584
+ opinion = attachMasterRuntimeProvenance(run, args.master, {
585
+ ...reconciled.opinion,
586
+ voice_statement: reconciled.opinion.voice_statement
587
+ || reconciled.opinion.summary
588
+ || reconciled.opinion.verdict,
589
+ voice_status: "completed",
590
+ voice_language: run.language,
591
+ statement_origin: "visible_legacy_method_worker",
592
+ }, reconciled.engine);
593
+ overridden = reconciled.overridden;
594
+ }
471
595
  const byId = new Map((run.master_opinions || []).map((item) => [item.master, item]));
472
596
  byId.set(args.master, opinion);
473
597
  run.master_opinions = allowed.map((id) => byId.get(id)).filter(Boolean);
@@ -654,6 +778,16 @@ function visibleRoundAgentPatch(run, state, role) {
654
778
 
655
779
  function recordVisibleDebateRound(run, args) {
656
780
  const role = args.role;
781
+ const missingEvidence = (run.tasks || []).filter((task) => taskState(run, task).status !== "completed");
782
+ const missingMasters = selectedMasters(run).filter((master) => masterSeatIncomplete(run, master));
783
+ if (missingEvidence.length || missingMasters.length) {
784
+ rejectVisibleDecision(
785
+ run,
786
+ "VISIBLE_DEBATE_PREREQUISITES_INCOMPLETE",
787
+ "Bull/Bear debate rejected: complete every evidence packet and returned method-seat worker first.",
788
+ { missing_evidence: missingEvidence, missing_masters: missingMasters },
789
+ );
790
+ }
657
791
  const expected = run.council_mode === "quick" ? [1] : [1, 2, 3];
658
792
  if (!Number.isInteger(args.round) || !expected.includes(args.round)) {
659
793
  rejectVisibleDecision(
@@ -767,8 +901,7 @@ function recordVisibleDebateRound(run, args) {
767
901
  function visiblePmPrerequisites(run, state) {
768
902
  const missingEvidence = (run.tasks || [])
769
903
  .filter((task) => taskState(run, task).status !== "completed");
770
- const recordedMasters = new Set((run.master_opinions || []).map((opinion) => opinion.master));
771
- const missingMasters = selectedMasters(run).filter((master) => !recordedMasters.has(master));
904
+ const missingMasters = selectedMasters(run).filter((master) => masterSeatIncomplete(run, master));
772
905
  const expected = run.council_mode === "quick" ? [1] : [1, 2, 3];
773
906
  const missingRounds = ["bull_researcher", "bear_researcher"].flatMap((role) => (
774
907
  expected.filter((round) => !visibleRoundEntry(state, role, round)).map((round) => `${role}:${round}`)
@@ -816,7 +949,18 @@ function recordVisiblePortfolioManager(run, args) {
816
949
  submitted_content_hash: contentHash,
817
950
  });
818
951
  }
819
- return { run, decision: state.portfolio_manager.packet, idempotent_replay: true };
952
+ const handoffPath = join(dir, "user_response.md");
953
+ const reportPath = join(dir, "final_report.md");
954
+ const qualityPath = join(dir, "report_quality.json");
955
+ return {
956
+ run,
957
+ decision: state.portfolio_manager.packet,
958
+ idempotent_replay: true,
959
+ user_response_markdown: existsSync(handoffPath) ? readFileSync(handoffPath, "utf8") : "",
960
+ final_report_markdown: existsSync(reportPath) ? readFileSync(reportPath, "utf8") : "",
961
+ report_quality: existsSync(qualityPath) ? readJson(qualityPath) : null,
962
+ artifacts: artifactPaths(run),
963
+ };
820
964
  }
821
965
 
822
966
  const prerequisites = visiblePmPrerequisites(run, state);
@@ -1,7 +1,17 @@
1
1
  import { join } from "node:path";
2
2
  import { LIMITS, MASTER_STANCES, RATINGS } from "./constants.mjs";
3
- import { internalError } from "./errors.mjs";
3
+ // A worker returning a malformed packet is a client contract violation, not a server bug:
4
+ // these three checks used to raise -32603 while the equivalent checks in the orchestrator
5
+ // correctly raised -32602.
6
+ import { internalError, invalidParams } from "./errors.mjs";
4
7
  import { isChineseLanguage, languageKey, localized } from "./lang.mjs";
8
+ import {
9
+ composeVoiceStatement,
10
+ defaultIntentForStance,
11
+ intentsForStance,
12
+ isIntentAllowed,
13
+ VOICE_FIELDS,
14
+ } from "./voice.mjs";
5
15
  import { cleanLog, clip } from "./text.mjs";
6
16
  import { scopedSourceId } from "./gates.mjs";
7
17
  import { runPath } from "./run-store.mjs";
@@ -571,19 +581,62 @@ export function normalizeMasterOpinion(packet, masterId, run, raw = "") {
571
581
  * choose or rewrite the stance. Keeping this packet separate from normalizeMasterOpinion
572
582
  * makes a persuasive narrative incapable of overriding deterministic policy output.
573
583
  */
584
+ /**
585
+ * A worker statement is prose that gets interpolated into a system-owned report section.
586
+ * Left raw, a statement containing a line such as `## Conclusion` emits a real level-2
587
+ * heading inside that section; heading assignment keeps the richest body, so the injected
588
+ * block becomes the section the quality gate validates and the genuine PM conclusion drops
589
+ * out of the gate's view entirely. Escape structural markdown at the trust boundary rather
590
+ * than at each render site, so a new renderer cannot reintroduce the hole.
591
+ */
592
+ export function sanitizeStatementMarkdown(value) {
593
+ return String(value ?? "")
594
+ .replace(/\r\n?/gu, "\n")
595
+ .split("\n")
596
+ .map((line) => line
597
+ .replace(/^(\s*)(#{1,6})(\s)/u, "$1\\$2$3")
598
+ .replace(/^(\s*)(={3,}|-{3,}|\*{3,}|_{3,})\s*$/u, "$1\\$2"))
599
+ .join("\n")
600
+ .replace(/\n{2,}/gu, "\n")
601
+ .trim();
602
+ }
603
+
574
604
  export function normalizeMasterVoice(packet, masterId, run, frozenOpinion, raw = "") {
575
- const list = (value) => (Array.isArray(value) ? value.filter((x) => typeof x === "string" && x.trim()) : []);
576
- if (packet?.master !== masterId) throw internalError(`dedicated method worker returned the wrong master id for ${masterId}`);
605
+ // Every one of these is rendered into the system-owned bench, so all of them are escaped.
606
+ const list = (value) => (Array.isArray(value)
607
+ ? value.map(sanitizeStatementMarkdown).filter(Boolean)
608
+ : []);
609
+ if (packet?.master !== masterId) throw invalidParams(`dedicated method worker returned the wrong master id for ${masterId}`);
577
610
  if (packet?.acknowledged_stance !== frozenOpinion?.stance) {
578
- throw internalError(`dedicated method worker attempted to change frozen stance for ${masterId}`);
611
+ throw invalidParams(`dedicated method worker attempted to change frozen stance for ${masterId}`);
579
612
  }
580
- const statement = typeof packet?.statement === "string" ? packet.statement.trim() : "";
581
- if (!statement) throw internalError(`dedicated method worker returned no statement for ${masterId}`);
613
+ // The five-field voice is the current contract; a flat `statement` remains accepted so a
614
+ // legacy worker, or one that answered before the contract moved, is not a hard failure.
615
+ const voice = Object.fromEntries(VOICE_FIELDS
616
+ .map((field) => [field, sanitizeStatementMarkdown(packet?.voice?.[field])])
617
+ .filter(([, text]) => text));
618
+ const statement = Object.keys(voice).length
619
+ ? composeVoiceStatement(voice, run.language)
620
+ : sanitizeStatementMarkdown(packet?.statement);
621
+ if (!statement) throw invalidParams(`dedicated method worker returned no statement for ${masterId}`);
622
+
623
+ // Intent narrows the frozen stance; it never reopens it. Rejected the same way a changed
624
+ // stance is, so a worker cannot turn `opposed` into `would_buy` by choosing a label.
625
+ const requested = packet?.position_intent;
626
+ if (requested !== undefined && !isIntentAllowed(requested, frozenOpinion.stance)) {
627
+ throw invalidParams(
628
+ `dedicated method worker returned an intent outside the frozen stance for ${masterId}: `
629
+ + `${JSON.stringify(requested)} is not one of ${intentsForStance(frozenOpinion.stance).join(", ")}`,
630
+ );
631
+ }
632
+
582
633
  return {
583
634
  master: masterId,
584
635
  symbol: run.symbol,
585
636
  as_of: run.as_of,
586
637
  acknowledged_stance: frozenOpinion.stance,
638
+ position_intent: requested ?? defaultIntentForStance(frozenOpinion.stance),
639
+ voice: Object.keys(voice).length ? voice : null,
587
640
  statement,
588
641
  key_findings: list(packet?.key_findings),
589
642
  disagreements: list(packet?.disagreements),
@@ -194,10 +194,10 @@ export function completedMasterOpinion(run, item) {
194
194
  const label = item.pack.admitted_label?.[locale]
195
195
  || item.pack.admitted_label?.en || item.id;
196
196
  const copy = localized(run.language, {
197
- en: { withheld: (pct) => `${pct}% coverage; score withheld`, unscored: "not scored", verdict: (stance, reason) => `${label} frozen decision: ${stance} (${reason})`, summary: (score) => `The PersonaPack v3 deterministic policy executed with score ${score}. Typed facts, hard vetoes, and score bands produced this stance; no language model selected it.`, hit: (id) => `score hit: ${id}`, miss: (id) => `score miss: ${id}`, eligibility: (id) => `eligibility condition ${id} becomes satisfied`, veto: (id) => `hard veto ${id} no longer triggers`, score: (id) => `score condition ${id} becomes satisfied` },
198
- zh: { withheld: (pct) => `覆盖率 ${pct}%,分数被保留不发布`, unscored: "未评分", verdict: (stance, reason) => `${label}的冻结结论:${stance}(${reason})`, summary: (score) => `PersonaPack v3 确定性政策已执行;得分 ${score}。该立场由结构化事实、硬否决和评分带产生,没有让语言模型选择立场。`, hit: (id) => `评分命中:${id}`, miss: (id) => `评分未命中:${id}`, eligibility: (id) => `资格条件 ${id} 变为满足`, veto: (id) => `硬否决 ${id} 不再触发`, score: (id) => `评分条件 ${id} 变为满足` },
199
- ja: { withheld: (pct) => `カバレッジ ${pct}% のためスコアは非公開`, unscored: "未採点", verdict: (stance, reason) => `${label}の凍結済み判断:${stance}(${reason})`, summary: (score) => `PersonaPack v3 の決定論的ポリシーを実行し、スコアは ${score}。構造化事実、ハード拒否条件、スコア帯がこの立場を生成しており、言語モデルは立場を選択していない。`, hit: (id) => `採点条件を満たす:${id}`, miss: (id) => `採点条件を満たさない:${id}`, eligibility: (id) => `適格条件 ${id} が満たされる`, veto: (id) => `ハード拒否条件 ${id} が解除される`, score: (id) => `採点条件 ${id} が満たされる` },
200
- ko: { withheld: (pct) => `커버리지 ${pct}%로 점수를 공개하지 않음`, unscored: "미채점", verdict: (stance, reason) => `${label}의 동결된 판단: ${stance}(${reason})`, summary: (score) => `PersonaPack v3 결정론적 정책을 실행했으며 점수는 ${score}입니다. 구조화된 사실, 하드 거부 조건, 점수 구간이 이 입장을 만들었고 언어 모델은 입장을 선택하지 않았습니다.`, hit: (id) => `점수 조건 충족: ${id}`, miss: (id) => `점수 조건 미충족: ${id}`, eligibility: (id) => `적격 조건 ${id} 충족`, veto: (id) => `하드 거부 조건 ${id} 해제`, score: (id) => `점수 조건 ${id} 충족` },
197
+ en: { withheld: (pct) => `${pct}% coverage; score withheld`, unscored: "not scored", verdict: (stance, reason) => `${label} frozen decision: ${stance} (${reason})`, summary: (score) => `Using the ${label} method on ${run.symbol}, the PersonaPack v3 deterministic policy executed with score ${score}. Typed facts, hard vetoes, and score bands produced this stance; no language model selected it.`, hit: (id) => `score hit: ${id}`, miss: (id) => `score miss: ${id}`, eligibility: (id) => `eligibility condition ${id} becomes satisfied`, veto: (id) => `hard veto ${id} no longer triggers`, score: (id) => `score condition ${id} becomes satisfied` },
198
+ zh: { withheld: (pct) => `覆盖率 ${pct}%,分数被保留不发布`, unscored: "未评分", verdict: (stance, reason) => `${label}的冻结结论:${stance}(${reason})`, summary: (score) => `按${label}方法审视 ${run.symbol}:PersonaPack v3 确定性政策已执行,得分 ${score}。该立场由结构化事实、硬否决和评分带产生,没有让语言模型选择立场。`, hit: (id) => `评分命中:${id}`, miss: (id) => `评分未命中:${id}`, eligibility: (id) => `资格条件 ${id} 变为满足`, veto: (id) => `硬否决 ${id} 不再触发`, score: (id) => `评分条件 ${id} 变为满足` },
199
+ ja: { withheld: (pct) => `カバレッジ ${pct}% のためスコアは非公開`, unscored: "未採点", verdict: (stance, reason) => `${label}の凍結済み判断:${stance}(${reason})`, summary: (score) => `${label}の方法で ${run.symbol} を評価し、PersonaPack v3 の決定論的ポリシーを実行した結果、スコアは ${score}。構造化事実、ハード拒否条件、スコア帯がこの立場を生成しており、言語モデルは立場を選択していない。`, hit: (id) => `採点条件を満たす:${id}`, miss: (id) => `採点条件を満たさない:${id}`, eligibility: (id) => `適格条件 ${id} が満たされる`, veto: (id) => `ハード拒否条件 ${id} が解除される`, score: (id) => `採点条件 ${id} が満たされる` },
200
+ ko: { withheld: (pct) => `커버리지 ${pct}%로 점수를 공개하지 않음`, unscored: "미채점", verdict: (stance, reason) => `${label}의 동결된 판단: ${stance}(${reason})`, summary: (score) => `${label} 방법으로 ${run.symbol}을 검토하여 PersonaPack v3 결정론적 정책을 실행했으며 점수는 ${score}입니다. 구조화된 사실, 하드 거부 조건, 점수 구간이 이 입장을 만들었고 언어 모델은 입장을 선택하지 않았습니다.`, hit: (id) => `점수 조건 충족: ${id}`, miss: (id) => `점수 조건 미충족: ${id}`, eligibility: (id) => `적격 조건 ${id} 충족`, veto: (id) => `하드 거부 조건 ${id} 해제`, score: (id) => `점수 조건 ${id} 충족` },
201
201
  });
202
202
  const vetoIds = (result.vetoes_triggered || []).map((veto) => veto.veto_id);
203
203
  const unmet = result.eligibility?.unmet_condition_ids || [];
@@ -214,13 +214,18 @@ export function completedMasterOpinion(run, item) {
214
214
  : result.score
215
215
  ? `${result.score.score}/${result.score.max_possible} (${Math.round((result.ratio || 0) * 100)}%)`
216
216
  : copy.unscored;
217
+ const deterministicStatement = copy.summary(scoreText);
217
218
  return {
218
219
  master: item.id,
219
220
  symbol: run.symbol,
220
221
  as_of: run.as_of,
221
222
  stance: result.stance,
222
223
  verdict: copy.verdict(result.stance, result.reason),
223
- summary: copy.summary(scoreText),
224
+ summary: deterministicStatement,
225
+ voice_statement: deterministicStatement,
226
+ voice_status: "deterministic_fallback",
227
+ voice_language: run.language,
228
+ statement_origin: "deterministic_policy_fallback",
224
229
  key_findings: uniqueStrings([
225
230
  ...hitIds.map(copy.hit),
226
231
  ...missIds.map(copy.miss),
@@ -260,13 +265,17 @@ export function declinedMasterOpinion(run, item) {
260
265
  const locale = languageKey(run.language);
261
266
  const label = item.pack.admitted_label?.[locale]
262
267
  || item.pack.admitted_label?.en || item.id;
268
+ const instrument = run?.grounding?.instrument;
269
+ const fundOrIndex = instrument?.fund_like === true || instrument?.index_like === true
270
+ || ["etf", "mutual_fund", "index"].includes(instrument?.asset_type);
263
271
  const copy = localized(run.language, {
264
- en: { none: "none", verdict: `${label} cannot evaluate ${run.symbol}: ${eligibility.reason}`, summary: (missing) => `The v3 typed-fact gate returned ${eligibility.status}; missing: ${missing}. No legacy prompt or narrative decision layer was called.`, available: (id) => `${id} becomes available from a point-in-time source` },
265
- zh: { none: "无", verdict: `${label}无法评估 ${run.symbol}:${eligibility.reason}`, summary: (missing) => `v3 typed-fact 闸门返回 ${eligibility.status};缺失:${missing}。系统未调用旧提示词或叙述决策层。`, available: (id) => `${id} 可从时点一致的来源取得` },
266
- ja: { none: "なし", verdict: `${label}は ${run.symbol} を評価できません:${eligibility.reason}`, summary: (missing) => `v3 typed-fact ゲートは ${eligibility.status} を返しました。欠落:${missing}。旧プロンプトや叙述型の判断層は呼び出していません。`, available: (id) => `${id} が時点整合した出典から利用可能になる` },
267
- ko: { none: "없음", verdict: `${label}은 ${run.symbol}을 평가할 수 없습니다: ${eligibility.reason}`, summary: (missing) => `v3 typed-fact 게이트가 ${eligibility.status}을 반환했습니다. 누락: ${missing}. 기존 프롬프트나 서술형 판단 계층은 호출하지 않았습니다.`, available: (id) => `${id}을 시점 일치 출처에서 확보할 수 있게 됨` },
272
+ en: { none: "none", verdict: `${label} cannot evaluate ${run.symbol}: ${eligibility.reason}`, summary: (missing) => `The v3 typed-fact gate returned ${eligibility.status}; missing: ${missing}. No legacy prompt or narrative decision layer was called.`, fundContext: fundOrIndex ? `${run.symbol} is classified as ${instrument.asset_type}; this method must use dated holdings or aggregate index evidence rather than treating the instrument as an operating company. ` : "", statement: (missing, context) => `${context}Using the ${label} method, I do not issue a directional view on ${run.symbol} in this run because the point-in-time record lacks ${missing}. This is neither bearish nor a vote against the asset. I would reassess only after those method-critical facts are available.`, available: (id) => `${id} becomes available from a point-in-time source` },
273
+ zh: { none: "无", verdict: `${label}无法评估 ${run.symbol}:${eligibility.reason}`, summary: (missing) => `v3 typed-fact 闸门返回 ${eligibility.status};缺失:${missing}。系统未调用旧提示词或叙述决策层。`, fundContext: fundOrIndex ? `${run.symbol} 已识别为 ${instrument.asset_type};该方法必须通过带时点的持仓穿透或指数聚合证据使用,不能把它当成经营公司。` : "", statement: (missing, context) => `${context}按${label}方法审视 ${run.symbol},本轮不作方向判断,因为时点一致的资料缺少:${missing}。这不是看空,也不是一张反对票;只有取得这些方法关键事实后,该席位才会重新评估。`, available: (id) => `${id} 可从时点一致的来源取得` },
274
+ ja: { none: "なし", verdict: `${label}は ${run.symbol} を評価できません:${eligibility.reason}`, summary: (missing) => `v3 typed-fact ゲートは ${eligibility.status} を返しました。欠落:${missing}。旧プロンプトや叙述型の判断層は呼び出していません。`, fundContext: fundOrIndex ? `${run.symbol} は ${instrument.asset_type} に分類されており、事業会社として扱わず、基準日付き保有銘柄のルックスルーまたは指数集計証拠を用いる必要があります。` : "", statement: (missing, context) => `${context}${label}の方法では、時点整合した資料に ${missing} が欠けているため、今回は ${run.symbol} の方向判断を出しません。弱気判断や反対票ではなく、これらの方法上重要な事実が揃った時点で再評価します。`, available: (id) => `${id} が時点整合した出典から利用可能になる` },
275
+ ko: { none: "없음", verdict: `${label}은 ${run.symbol}을 평가할 수 없습니다: ${eligibility.reason}`, summary: (missing) => `v3 typed-fact 게이트가 ${eligibility.status}을 반환했습니다. 누락: ${missing}. 기존 프롬프트나 서술형 판단 계층은 호출하지 않았습니다.`, fundContext: fundOrIndex ? `${run.symbol}은 ${instrument.asset_type}로 분류되므로 영업회사처럼 취급하지 않고 기준일이 있는 보유 종목 룩스루 또는 지수 집계 증거를 사용해야 합니다. ` : "", statement: (missing, context) => `${context}${label} 방법으로는 시점 일치 자료에 ${missing}이 없어 이번 실행에서 ${run.symbol}의 방향 판단을 내리지 않습니다. 이는 약세 판단이나 반대표가 아니며, 해당 핵심 사실이 확보된 뒤에만 재평가합니다.`, available: (id) => `${id}을 시점 일치 출처에서 확보할 수 있게 됨` },
268
276
  });
269
277
  const missing = eligibility.missing_required_fact_types.join(", ") || copy.none;
278
+ const deterministicStatement = copy.statement(missing, copy.fundContext);
270
279
  return {
271
280
  master: item.id,
272
281
  symbol: run.symbol,
@@ -274,7 +283,11 @@ export function declinedMasterOpinion(run, item) {
274
283
  stance: "out_of_scope",
275
284
  verdict: copy.verdict,
276
285
  summary: copy.summary(missing),
277
- key_findings: [],
286
+ voice_statement: deterministicStatement,
287
+ voice_status: "deterministic_fallback",
288
+ voice_language: run.language,
289
+ statement_origin: "deterministic_scope_fallback",
290
+ key_findings: [deterministicStatement],
278
291
  disagreements: [],
279
292
  disqualifiers_triggered: eligibility.missing_required_fact_types,
280
293
  what_would_change_my_mind: eligibility.missing_required_fact_types.map(copy.available),
@@ -227,7 +227,7 @@ function validatePeriodContract(period, path, errors) {
227
227
  if (!exactFields(period, path, fields, [...fields], errors)) return;
228
228
  if (!["instant", "duration", "forecast_horizon", "not_applicable"].includes(period.basis)) add(errors, `${path}.basis`, "is invalid");
229
229
  if (!["exact", "same_period", "as_of", "not_applicable"].includes(period.alignment)) add(errors, `${path}.alignment`, "is invalid");
230
- if (period.window !== null && (typeof period.window !== "string" || !/^P[1-9]\d*[DMY]$/u.test(period.window))) add(errors, `${path}.window`, "must be null or P<n>D, P<n>M, or P<n>Y");
230
+ if (period.window !== null && (typeof period.window !== "string" || !/^(P[1-9]\d*[DMY]|ANY)$/u.test(period.window))) add(errors, `${path}.window`, "must be null, ANY, or P<n>D, P<n>M, or P<n>Y");
231
231
  if (["instant", "not_applicable"].includes(period.basis) && period.window !== null) add(errors, `${path}.window`, `must be null for ${period.basis}`);
232
232
  if (["duration", "forecast_horizon"].includes(period.basis) && period.window === null) add(errors, `${path}.window`, `is required for ${period.basis}`);
233
233
  if (period.basis === "not_applicable" && period.alignment !== "not_applicable") add(errors, `${path}.alignment`, "must be not_applicable");
@@ -532,18 +532,29 @@ function periodTuple(fact) {
532
532
  return [fact.period_start, fact.period_end, fact.fiscal_year];
533
533
  }
534
534
 
535
+ /** Window token for a duration whose length is set by data availability, not by the method. */
536
+ export const ANY_REPORTING_INTERVAL = "ANY";
537
+
535
538
  function periodWindowMatches(fact, window) {
536
539
  if (!fact.period_start || !fact.period_end) return false;
537
540
  const start = Date.parse(fact.period_start);
538
541
  const end = Date.parse(fact.period_end);
539
542
  if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) return false;
543
+ // Some aggregates cover as many periods as the filings supplied rather than a fixed span --
544
+ // interest coverage is three years for one issuer and one for the next. Pinning a count there
545
+ // would reject the fact for being honest about its own coverage; what still has to hold is
546
+ // that it carries a real interval rather than a stray observation date.
547
+ if (window === ANY_REPORTING_INTERVAL) return true;
540
548
  const match = /^P([1-9]\d*)([DMY])$/u.exec(window || "");
541
549
  if (!match) return false;
542
550
  const count = Number(match[1]);
543
551
  const elapsedDays = (end - start) / 86_400_000;
544
552
  if (match[2] === "D") return elapsedDays === count;
545
553
  if (match[2] === "M") return elapsedDays >= count * 27 && elapsedDays <= count * 32;
546
- return elapsedDays >= count * 365 - 1 && elapsedDays <= count * 366 + 1;
554
+ // A fiscal year is 52 or 53 weeks, not 365 days, and it is measured between two fiscal
555
+ // year-end dates -- so a real one-year filing span is routinely 363 or 364 days. Demanding
556
+ // 365 rejected every issuer whose year ends on a weekday.
557
+ return elapsedDays >= count * 364 - 2 && elapsedDays <= count * 366 + 1;
547
558
  }
548
559
 
549
560
  function assertFactInputContract(fact, contract, factPackAsOf, path) {
@@ -1,3 +1,4 @@
1
+ import { CANONICAL_MASTER_COUNT } from "./staging.mjs";
1
2
  import { createHash } from "node:crypto";
2
3
  import {
3
4
  existsSync,
@@ -441,8 +442,8 @@ export function inspectGaExternalEvidence({
441
442
  const releaseIds = manifest.canonical_master_ids || [];
442
443
  const releasePackHashes = (manifest.packs || []).map((pack) => pack.pack_hash);
443
444
  const releaseVersions = (manifest.packs || []).map((pack) => pack.pack_version);
444
- if (releaseVersions.length !== 26 || releaseVersions.some((version) => version !== expectedVersion)) {
445
- errors.push(`all 26 immutable release pack versions must equal ${expectedVersion}`);
445
+ if (releaseVersions.length !== CANONICAL_MASTER_COUNT || releaseVersions.some((version) => version !== expectedVersion)) {
446
+ errors.push(`all ${CANONICAL_MASTER_COUNT} immutable release pack versions must equal ${expectedVersion}`);
446
447
  }
447
448
  if (packageEvidence?.artifact) {
448
449
  if (!same(packageEvidence.derived_catalog?.selected_master_ids, releaseIds)) errors.push("installed package selected master IDs/order differ from the release manifest");
@@ -19,9 +19,10 @@ import { verifyPersonaRelease } from "./releases.mjs";
19
19
  import { inspectSourceAcquisitions } from "./source-acquisition.mjs";
20
20
  import { inspectSourceAdjudications } from "./source-adjudication.mjs";
21
21
  import { defaultStagingRoot, inspectPersonaV3Staging } from "./staging.mjs";
22
+ import { CANONICAL_MASTER_COUNT } from "./staging.mjs";
22
23
 
23
24
  export const GA_REPORT_SCHEMA_VERSION = 1;
24
- export const GA_DEFAULT_COUNT = 26;
25
+ export const GA_DEFAULT_COUNT = CANONICAL_MASTER_COUNT;
25
26
  export const GA_DEFAULT_MIN_ADMISSION = "operational";
26
27
  export const GA_TARGET_VERSION = "0.9.0";
27
28
 
@@ -1,3 +1,4 @@
1
+ import { CANONICAL_MASTER_COUNT } from "./staging.mjs";
1
2
  import { createHash } from "node:crypto";
2
3
  import { spawnSync } from "node:child_process";
3
4
  import {
@@ -219,9 +220,9 @@ function safelyInstallAndDerive(tarball, { packageName, releaseId }) {
219
220
  const releaseFile = containedPhysicalFile(installedRoot, join("knowledge", "persona-releases", releaseId, "manifest.json"), "installed release manifest");
220
221
  const release = parseJson(releaseFile.bytes, "installed release manifest");
221
222
  if (release.artifact_kind !== "persona_v3_release_manifest" || release.release_id !== releaseId) throw new Error("installed release manifest identity differs from the package artifact");
222
- if (release.canonical_master_count !== 26 || !Array.isArray(release.canonical_master_ids)
223
- || release.canonical_master_ids.length !== 26 || new Set(release.canonical_master_ids).size !== 26
224
- || !Array.isArray(release.packs) || release.packs.length !== 26) throw new Error("installed release manifest does not contain exactly 26 canonical packs");
223
+ if (release.canonical_master_count !== CANONICAL_MASTER_COUNT || !Array.isArray(release.canonical_master_ids)
224
+ || release.canonical_master_ids.length !== CANONICAL_MASTER_COUNT || new Set(release.canonical_master_ids).size !== CANONICAL_MASTER_COUNT
225
+ || !Array.isArray(release.packs) || release.packs.length !== CANONICAL_MASTER_COUNT) throw new Error(`installed release manifest does not contain exactly ${CANONICAL_MASTER_COUNT} canonical packs`);
225
226
  const selectedPackHashes = release.packs.map((pack, index) => {
226
227
  if (pack?.persona_id !== release.canonical_master_ids[index] || !HASH.test(pack?.pack_hash || "")) throw new Error(`installed release manifest pack ${index} does not bind canonical ID/order/hash`);
227
228
  return pack.pack_hash;
@@ -323,7 +324,7 @@ export function checkGaPackageArtifactFile(file, { packageJsonPath, expectedVers
323
324
  if (artifact.package?.[field] !== sourcePackage?.[field]) errors.push(`package artifact ${field} differs from repository package.json`);
324
325
  if (artifact.package?.[field] !== tarballPackage?.[field]) errors.push(`package artifact ${field} differs from tarball package.json`);
325
326
  }
326
- if (artifact.catalog?.selected_master_ids?.length === 26) {
327
+ if (artifact.catalog?.selected_master_ids?.length === CANONICAL_MASTER_COUNT) {
327
328
  installedMetadata = safelyInstallAndDerive(tarballFile.absolute, {
328
329
  packageName: tarballPackage.name,
329
330
  releaseId: artifact.release_id,