alphacouncil-agent 0.9.4 → 1.0.1
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.
- package/.claude-plugin/marketplace.json +3 -3
- package/.claude-plugin/plugin.json +2 -2
- package/.codex-plugin/plugin.json +4 -4
- package/AGENTS.md +25 -11
- package/CHANGELOG.md +146 -0
- package/CLAUDE.md +24 -7
- package/README.ja.md +15 -10
- package/README.md +21 -13
- package/README.zh-CN.md +17 -12
- package/data/authored/core-seats.mjs +808 -0
- package/data/authored/growth-seats.mjs +581 -0
- package/data/authored/index.mjs +114 -0
- package/data/authored/quant-seats.mjs +564 -0
- package/data/authored/value-seats.mjs +663 -0
- package/data/build-profile.v1.json +2 -1
- package/data/council-evaluation-protocol.v1.json +7 -4
- package/data/master-selector-method-locales.v1.mjs +10 -0
- package/data/persona-v3-ai-assisted-solo-profile.v1.json +2 -2
- package/data/persona-v3-build-specs.v1.mjs +60 -3
- package/docs/INSTALL.md +6 -10
- package/docs/personas.md +2 -1
- package/docs/plans/v1.0-roadmap.md +487 -0
- package/docs/plans/v1.1-basket-native-seats.md +267 -0
- package/docs/releases/v0.9.5.md +96 -0
- package/docs/releases/v1.0.0.md +164 -0
- package/docs/report-contract.md +30 -6
- package/knowledge/ai-assisted-solo/experiments/runs/a.json +13 -13
- package/knowledge/ai-assisted-solo/experiments/runs/b.json +2 -2
- package/knowledge/ai-assisted-solo/experiments/runs/c.json +2 -2
- package/knowledge/ai-assisted-solo/experiments/runs/d13.json +126 -126
- package/knowledge/ai-assisted-solo/experiments/runs/d26.json +274 -254
- package/knowledge/ai-assisted-solo/experiments/runs/e-d13.json +129 -129
- package/knowledge/ai-assisted-solo/experiments/runs/e-d26.json +277 -257
- package/knowledge/ai-assisted-solo/experiments/runs/h_ai_reference.json +278 -258
- package/knowledge/ai-assisted-solo/experiments/simulation-input.json +7278 -556
- package/knowledge/ai-assisted-solo/experiments/simulation-manifest.json +22 -22
- 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
- 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
- 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
- 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
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/expected_return_over_long_bond.ai-review.json +277 -0
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_bogle/reviews/fundamental_expected_return.ai-review.json +277 -0
- 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
- 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
- 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
- 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
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_dalio/reviews/{regime_classifier.ai-review.json → policy_real_rate.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/{master_munger/reviews/incentive_map.ai-review.json → master_dalio/reviews/real_curve_slope.ai-review.json} +51 -51
- 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
- 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
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{user_value_evidence.ai-review.json → five_year_opportunity_cost.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_duan_yongping/reviews/{opportunity_cost.ai-review.json → margin_retention.ai-review.json} +46 -46
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/{master_dalio/reviews/debt_driver_stress.ai-review.json → master_forensic_short/reviews/cash_conversion_gap.ai-review.json} +51 -51
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_munger/reviews/reported_earnings_cash_gap.ai-review.json +277 -0
- 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
- 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
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{leakage_audit.ai-review.json → absolute_session_move.ai-review.json} +42 -42
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_simons/reviews/{oos_cost_test.ai-review.json → session_move_over_implied.ai-review.json} +46 -46
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reflexivity_graph.ai-review.json → credit_cycle_position.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_soros/reviews/{reversal_monitor.ai-review.json → financing_burden.ai-review.json} +46 -46
- 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
- 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
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{fractional_kelly.ai-review.json → edge_per_unit_of_volatility.ai-review.json} +46 -46
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_thorp/reviews/{edge_recalculator.ai-review.json → net_edge.ai-review.json} +49 -49
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/review-manifest.json +288 -270
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-adjudications/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-extractions/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-semantic-skeptic-reviews/index.json +2 -2
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-source-prereviews/index.json +6 -2
- package/knowledge/solo-test/masters/master_ackman/decision_policy.json +122 -11
- package/knowledge/solo-test/masters/master_ackman/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_ackman/manifest.json +13 -6
- package/knowledge/solo-test/masters/master_ackman/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_ackman/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_ackman/tools.json +56 -30
- package/knowledge/solo-test/masters/master_aschenbrenner/decision_policy.json +101 -10
- package/knowledge/solo-test/masters/master_aschenbrenner/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_aschenbrenner/manifest.json +12 -4
- package/knowledge/solo-test/masters/master_aschenbrenner/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_aschenbrenner/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_aschenbrenner/tools.json +56 -30
- package/knowledge/solo-test/masters/master_asness/decision_policy.json +89 -10
- package/knowledge/solo-test/masters/master_asness/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_asness/manifest.json +11 -4
- package/knowledge/solo-test/masters/master_asness/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_asness/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_asness/tools.json +56 -30
- package/knowledge/solo-test/masters/master_bogle/counterfactuals.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/decision_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/decision_policy.json +170 -0
- package/knowledge/solo-test/masters/master_bogle/doctrine.jsonl +14 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/calibration_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/experiments.json +5 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/golden_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/evaluation/pairwise_cases.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/failures.jsonl +0 -0
- package/knowledge/solo-test/masters/master_bogle/manifest.json +141 -0
- package/knowledge/solo-test/masters/master_bogle/memory_policy.json +5 -0
- package/knowledge/solo-test/masters/master_bogle/provisional-index.json +41 -0
- package/knowledge/solo-test/masters/master_bogle/research_policy.json +11 -0
- package/knowledge/solo-test/masters/master_bogle/sources.jsonl +1 -0
- package/knowledge/solo-test/masters/master_bogle/tools.json +120 -0
- package/knowledge/solo-test/masters/master_bogle/voice.en.md +7 -0
- package/knowledge/solo-test/masters/master_bogle/voice.zh.md +7 -0
- package/knowledge/solo-test/masters/master_buffett/decision_policy.json +102 -11
- package/knowledge/solo-test/masters/master_buffett/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_buffett/manifest.json +10 -4
- package/knowledge/solo-test/masters/master_buffett/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_buffett/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_buffett/tools.json +55 -29
- package/knowledge/solo-test/masters/master_burry/decision_policy.json +102 -12
- package/knowledge/solo-test/masters/master_burry/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_burry/manifest.json +12 -6
- package/knowledge/solo-test/masters/master_burry/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_burry/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_burry/tools.json +56 -30
- package/knowledge/solo-test/masters/master_cathie_wood/decision_policy.json +74 -12
- package/knowledge/solo-test/masters/master_cathie_wood/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_cathie_wood/manifest.json +12 -6
- package/knowledge/solo-test/masters/master_cathie_wood/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_cathie_wood/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_cathie_wood/tools.json +56 -30
- package/knowledge/solo-test/masters/master_dalio/decision_policy.json +123 -16
- package/knowledge/solo-test/masters/master_dalio/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_dalio/manifest.json +10 -4
- package/knowledge/solo-test/masters/master_dalio/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_dalio/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_dalio/tools.json +56 -30
- package/knowledge/solo-test/masters/master_damodaran/decision_policy.json +58 -10
- package/knowledge/solo-test/masters/master_damodaran/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_damodaran/manifest.json +9 -4
- package/knowledge/solo-test/masters/master_damodaran/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_damodaran/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_damodaran/tools.json +54 -28
- package/knowledge/solo-test/masters/master_druckenmiller/decision_policy.json +89 -10
- package/knowledge/solo-test/masters/master_druckenmiller/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_druckenmiller/manifest.json +11 -4
- package/knowledge/solo-test/masters/master_druckenmiller/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_druckenmiller/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_druckenmiller/tools.json +55 -29
- package/knowledge/solo-test/masters/master_duan_yongping/decision_policy.json +138 -13
- package/knowledge/solo-test/masters/master_duan_yongping/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_duan_yongping/manifest.json +17 -7
- package/knowledge/solo-test/masters/master_duan_yongping/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_duan_yongping/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_duan_yongping/tools.json +82 -30
- package/knowledge/solo-test/masters/master_fisher/decision_policy.json +102 -11
- package/knowledge/solo-test/masters/master_fisher/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_fisher/manifest.json +13 -6
- package/knowledge/solo-test/masters/master_fisher/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_fisher/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_fisher/tools.json +58 -32
- package/knowledge/solo-test/masters/master_forensic_short/decision_policy.json +93 -14
- package/knowledge/solo-test/masters/master_forensic_short/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_forensic_short/manifest.json +6 -4
- package/knowledge/solo-test/masters/master_forensic_short/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_forensic_short/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_forensic_short/tools.json +53 -27
- package/knowledge/solo-test/masters/master_graham/decision_policy.json +103 -12
- package/knowledge/solo-test/masters/master_graham/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_graham/manifest.json +12 -4
- package/knowledge/solo-test/masters/master_graham/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_graham/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_graham/tools.json +67 -28
- package/knowledge/solo-test/masters/master_jhunjhunwala/decision_policy.json +77 -12
- package/knowledge/solo-test/masters/master_jhunjhunwala/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_jhunjhunwala/manifest.json +11 -6
- package/knowledge/solo-test/masters/master_jhunjhunwala/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_jhunjhunwala/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_jhunjhunwala/tools.json +54 -28
- package/knowledge/solo-test/masters/master_klarman/decision_policy.json +105 -14
- package/knowledge/solo-test/masters/master_klarman/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_klarman/manifest.json +8 -2
- package/knowledge/solo-test/masters/master_klarman/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_klarman/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_klarman/tools.json +55 -29
- package/knowledge/solo-test/masters/master_li_lu/decision_policy.json +101 -10
- package/knowledge/solo-test/masters/master_li_lu/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_li_lu/manifest.json +13 -6
- package/knowledge/solo-test/masters/master_li_lu/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_li_lu/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_li_lu/tools.json +58 -32
- package/knowledge/solo-test/masters/master_lynch/decision_policy.json +127 -16
- package/knowledge/solo-test/masters/master_lynch/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_lynch/manifest.json +14 -6
- package/knowledge/solo-test/masters/master_lynch/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_lynch/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_lynch/tools.json +67 -28
- package/knowledge/solo-test/masters/master_marks/decision_policy.json +71 -9
- package/knowledge/solo-test/masters/master_marks/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_marks/manifest.json +11 -6
- package/knowledge/solo-test/masters/master_marks/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_marks/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_marks/tools.json +54 -28
- package/knowledge/solo-test/masters/master_munger/decision_policy.json +141 -16
- package/knowledge/solo-test/masters/master_munger/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_munger/manifest.json +10 -6
- package/knowledge/solo-test/masters/master_munger/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_munger/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_munger/tools.json +52 -26
- package/knowledge/solo-test/masters/master_natenberg/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_natenberg/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_natenberg/manifest.json +9 -6
- package/knowledge/solo-test/masters/master_natenberg/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_natenberg/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_natenberg/tools.json +50 -24
- package/knowledge/solo-test/masters/master_pabrai/decision_policy.json +125 -14
- package/knowledge/solo-test/masters/master_pabrai/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_pabrai/manifest.json +8 -2
- package/knowledge/solo-test/masters/master_pabrai/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_pabrai/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_pabrai/tools.json +55 -29
- package/knowledge/solo-test/masters/master_simons/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_simons/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_simons/manifest.json +8 -4
- package/knowledge/solo-test/masters/master_simons/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_simons/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_simons/tools.json +43 -30
- package/knowledge/solo-test/masters/master_sinclair/decision_policy.json +59 -11
- package/knowledge/solo-test/masters/master_sinclair/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_sinclair/manifest.json +8 -6
- package/knowledge/solo-test/masters/master_sinclair/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_sinclair/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_sinclair/tools.json +54 -28
- package/knowledge/solo-test/masters/master_soros/decision_policy.json +98 -10
- package/knowledge/solo-test/masters/master_soros/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_soros/manifest.json +10 -7
- package/knowledge/solo-test/masters/master_soros/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_soros/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_soros/tools.json +54 -28
- package/knowledge/solo-test/masters/master_taleb/decision_policy.json +124 -13
- package/knowledge/solo-test/masters/master_taleb/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_taleb/manifest.json +9 -5
- package/knowledge/solo-test/masters/master_taleb/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_taleb/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_taleb/tools.json +50 -24
- package/knowledge/solo-test/masters/master_thorp/decision_policy.json +61 -13
- package/knowledge/solo-test/masters/master_thorp/doctrine.jsonl +2 -2
- package/knowledge/solo-test/masters/master_thorp/manifest.json +11 -6
- package/knowledge/solo-test/masters/master_thorp/provisional-index.json +3 -3
- package/knowledge/solo-test/masters/master_thorp/sources.jsonl +1 -1
- package/knowledge/solo-test/masters/master_thorp/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/compilation-manifest.json +290 -264
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/price_implied_cash_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/nominal_earnings_yield_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/real_earnings_yield_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/components/tools.json +120 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/expected_return_over_long_bond.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_bogle/provisional-derivations/fundamental_expected_return.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/components/tools.json +58 -32
- 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
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/current_cash_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/real_curve_slope.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/implied_equity_risk_premium.derived-proxy-evidence.json +76 -0
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_curve_impulse.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/policy_real_rate.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/components/tools.json +84 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/five_year_opportunity_cost.derived-proxy-evidence.json +102 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/components/tools.json +60 -34
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/margin_retention.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/reinvestment_spread.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/components/tools.json +55 -29
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/cash_cover_of_leverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/components/tools.json +69 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/defensive_hurdle_base.derived-proxy-evidence.json +89 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/half_normalised_earnings_yield.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/cash_quality_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/real_structural_growth.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/downside_asset_coverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/components/tools.json +60 -34
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/cash_backed_decade_return.derived-proxy-evidence.json +76 -0
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/components/tools.json +69 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/growth_justified_capitalisation.derived-proxy-evidence.json +89 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/equity_over_corporate_debt.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/components/tools.json +54 -28
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/reported_earnings_cash_gap.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/components/tools.json +52 -26
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_natenberg/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/components/tools.json +57 -31
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor_coverage.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/market_capitalisation.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/components/tools.json +45 -32
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/session_move_over_implied.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/round_trip_cost.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/volatility_per_unit_of_width.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/components/tools.json +56 -30
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/credit_cycle_position.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/financing_burden.derived-proxy-evidence.json +76 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/components/tools.json +52 -26
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/debt_service_cushion.derived-proxy-evidence.json +76 -0
- 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
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/components/tools.json +58 -32
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_per_unit_of_volatility.derived-proxy-evidence.json +77 -0
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/net_edge.derived-proxy-evidence.json +76 -0
- package/mcp/lib/breadth.mjs +126 -0
- package/mcp/lib/constants.mjs +15 -0
- package/mcp/lib/damodaran.mjs +119 -0
- package/mcp/lib/fred.mjs +246 -0
- package/mcp/lib/fund-holdings-parsers.mjs +297 -0
- package/mcp/lib/fund-observations.mjs +152 -0
- package/mcp/lib/fundamentals.mjs +806 -0
- package/mcp/lib/funds.mjs +785 -0
- package/mcp/lib/gates.mjs +71 -4
- package/mcp/lib/grounding.mjs +209 -36
- package/mcp/lib/index-aggregate.mjs +733 -0
- package/mcp/lib/insider-ownership.mjs +149 -0
- package/mcp/lib/instrument-facts.mjs +855 -0
- package/mcp/lib/instruments.mjs +216 -0
- package/mcp/lib/markdown.mjs +216 -43
- package/mcp/lib/master-catalog.mjs +4 -0
- package/mcp/lib/orchestrator.mjs +173 -29
- package/mcp/lib/packets.mjs +59 -6
- package/mcp/lib/personas/engine.mjs +23 -10
- package/mcp/lib/personas-v3/deterministic-executor.mjs +13 -2
- package/mcp/lib/personas-v3/ga-external-evidence.mjs +3 -2
- package/mcp/lib/personas-v3/ga-gate.mjs +2 -1
- package/mcp/lib/personas-v3/ga-package-evidence.mjs +5 -4
- package/mcp/lib/personas-v3/grounding-adapter.mjs +309 -2
- package/mcp/lib/personas-v3/production-root.mjs +5 -4
- package/mcp/lib/personas-v3/release-formula-evidence.mjs +14 -7
- package/mcp/lib/personas-v3/release-source-evidence.mjs +2 -1
- package/mcp/lib/personas-v3/releases.mjs +5 -4
- package/mcp/lib/personas-v3/runtime-release-integrity.mjs +6 -5
- package/mcp/lib/personas-v3/semantic-source-adjudication.mjs +2 -1
- package/mcp/lib/personas-v3/semantic-source-extraction.mjs +2 -1
- package/mcp/lib/personas-v3/semantic-source-skeptic-review.mjs +2 -1
- package/mcp/lib/personas-v3/source-review-operations.mjs +3 -2
- package/mcp/lib/personas-v3/staging.mjs +22 -3
- package/mcp/lib/prompts.mjs +87 -3
- package/mcp/lib/quotes.mjs +5 -0
- package/mcp/lib/rpc.mjs +27 -10
- package/mcp/lib/run-store.mjs +5 -3
- package/mcp/lib/sec.mjs +32 -0
- package/mcp/lib/tables.mjs +11 -0
- package/mcp/lib/voice.mjs +122 -0
- package/mcp/lib/xbrl-aggregates.mjs +153 -0
- package/mcp/lib/xbrl-series.mjs +341 -0
- package/mcp/lib/xlsx.mjs +155 -0
- package/package.json +5 -5
- package/personas/masters/masters-value/bogle.md +145 -0
- package/schemas/council-evaluation-protocol-v1.schema.json +2 -2
- package/schemas/persona-v3-ai-assisted-solo-profile-v1.schema.json +2 -2
- package/schemas/persona-v3-ai-machine-simulation-v1.schema.json +1 -1
- package/schemas/persona-v3-build-spec-v1.schema.json +3 -3
- package/schemas/persona-v3-release-formula-review-evidence-v1.schema.json +3 -3
- package/schemas/persona-v3-release-manifest-v1.schema.json +6 -6
- package/schemas/persona-v3-release-source-review-evidence-v1.schema.json +3 -3
- package/schemas/persona-v3-tool-graph-v1.schema.json +1 -1
- package/schemas/source-review-batch-v1.schema.json +9 -9
- package/scripts/assemble-persona-v3-release.mjs +3 -2
- package/scripts/build-persona-v3-solo-test-packs.mjs +6 -8
- package/scripts/check-persona-v3-ga.mjs +1 -1
- package/scripts/check-persona-v3-production-candidates.mjs +1 -1
- package/scripts/compile-persona-v3-formulas.mjs +19 -18
- package/scripts/doctor.mjs +11 -9
- package/scripts/export-persona-source-review-batch.mjs +1 -1
- package/scripts/generate-persona-v3-drafts.mjs +2 -2
- package/scripts/lib/build-profile.mjs +24 -0
- package/scripts/lib/council-evaluation-protocol.mjs +7 -6
- package/scripts/lib/host-capabilities.mjs +2 -1
- package/scripts/lib/packaged-host-parity.mjs +9 -3
- package/scripts/lib/persona-v3-ai-assisted-solo-status.mjs +6 -4
- package/scripts/lib/persona-v3-ai-formula-review.mjs +6 -5
- package/scripts/lib/persona-v3-ai-machine-simulations.mjs +32 -4
- package/scripts/lib/persona-v3-build-specs.mjs +3 -2
- package/scripts/lib/persona-v3-draft-packs.mjs +2 -2
- package/scripts/lib/persona-v3-formula-pipeline.mjs +11 -10
- package/scripts/lib/persona-v3-production-candidates.mjs +10 -9
- package/scripts/lib/persona-v3-solo-formula-pipeline.mjs +188 -16
- package/scripts/lib/persona-v3-solo-test-packs.mjs +112 -11
- package/scripts/package-smoke.mjs +2 -1
- package/scripts/report-persona-corpus-gaps.mjs +4 -1
- package/scripts/review-persona-v3-solo-formulas.mjs +12 -8
- package/scripts/scaffold-persona-v3-staging.mjs +1 -1
- package/skills/agent-skills-governance/SKILL.md +8 -2
- package/skills/alphacouncil-agent/SKILL.md +12 -4
- package/skills/public-equity-investing/SKILL.md +17 -0
- package/knowledge/ai-assisted-solo/reviews/persona-v3-ai-formula-reviews/master_forensic_short/reviews/borrow_catalyst.ai-review.json +0 -277
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/change_value_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_ackman/provisional-derivations/power_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/compute_power_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_aschenbrenner/provisional-derivations/timeline_reverse_valuation.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/crowding_cost_stress.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_asness/provisional-derivations/factor_decomposer.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/incremental_returns.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_buffett/provisional-derivations/owner_earnings_rebuilder.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/capital_structure_reader.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_burry/provisional-derivations/mispricing_carry.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/capture_valuation_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_cathie_wood/provisional-derivations/cost_adoption_curve.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/debt_driver_stress.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_dalio/provisional-derivations/regime_classifier.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_damodaran/provisional-derivations/story_dcf.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/inflection_payoff.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_druckenmiller/provisional-derivations/liquidity_revision_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/opportunity_cost.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_duan_yongping/provisional-derivations/user_value_evidence.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/research_productivity.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_fisher/provisional-derivations/scuttlebutt_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_forensic_short/provisional-derivations/borrow_catalyst.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/asset_floor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_graham/provisional-derivations/normalized_earnings.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/penetration_liquidity.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_jhunjhunwala/provisional-derivations/promoter_governance.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/cash_catalyst_compare.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_klarman/provisional-derivations/recovery_waterfall.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/promise_integrity_ledger.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_li_lu/provisional-derivations/ten_year_return_bridge.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/category_classifier.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_lynch/provisional-derivations/story_numbers_check.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/cycle_temperature.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_marks/provisional-derivations/implied_expectations.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/failure_path_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_munger/provisional-derivations/incentive_map.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/discrete_payoff.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_pabrai/provisional-derivations/downside_floor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/leakage_audit.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_simons/provisional-derivations/oos_cost_test.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/net_edge_sizer.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_sinclair/provisional-derivations/realized_vol_forecast.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reflexivity_graph.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_soros/provisional-derivations/reversal_monitor.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_taleb/provisional-derivations/payoff_ruin.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/edge_recalculator.derived-proxy-evidence.json +0 -64
- package/knowledge/solo-test/persona-v3-solo-test-formulas/master_thorp/provisional-derivations/fractional_kelly.derived-proxy-evidence.json +0 -64
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fiscal-year aggregates assembled from an aligned XBRL series.
|
|
3
|
+
*
|
|
4
|
+
* These answer "what does this filer report for year N", not "is that good". Debt is summed
|
|
5
|
+
* from non-overlapping buckets and names the ones a filer omits; tangible book deducts what
|
|
6
|
+
* is tagged and records the reading when a concept is absent from the whole document; the
|
|
7
|
+
* trailing-four-quarters window checks its own seams. Each returns null rather than zero when
|
|
8
|
+
* the filings do not support the figure -- a company with unknown debt is not a debt-free one.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
DEBT_BUCKETS,
|
|
13
|
+
FUNDAMENTAL_CONCEPTS,
|
|
14
|
+
alignYear,
|
|
15
|
+
daysBetween,
|
|
16
|
+
decimal,
|
|
17
|
+
fiscalYearOf,
|
|
18
|
+
gap,
|
|
19
|
+
} from "./xbrl-series.mjs";
|
|
20
|
+
|
|
21
|
+
const sum = (values) => values.reduce((total, value) => total + value, 0);
|
|
22
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Both endpoints on one profit basis. Pairing a NOPAT endpoint with a net-income endpoint
|
|
26
|
+
* would difference two different quantities and call the result a return.
|
|
27
|
+
*/
|
|
28
|
+
/** Four contiguous quarters ending at `index`, or null when a quarter is missing or overlaps. */
|
|
29
|
+
/**
|
|
30
|
+
* Profit for the incremental-return window: NOPAT when the tax inputs exist, otherwise net
|
|
31
|
+
* income -- and the basis is named in the output rather than left for the reader to guess.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Tangible book value: equity less goodwill and intangibles.
|
|
35
|
+
*
|
|
36
|
+
* A filer with goodwill on its balance sheet must tag it, so a concept absent from every
|
|
37
|
+
* period of the document is evidence of nil rather than a data gap -- and that reading is
|
|
38
|
+
* still written into `assumptions`. A concept reported in other years but not this one is
|
|
39
|
+
* treated as a genuine misalignment and refuses to compute.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Total debt for one fiscal year.
|
|
43
|
+
*
|
|
44
|
+
* A single combined tag wins outright. Otherwise the three non-overlapping buckets are summed
|
|
45
|
+
* and the ones a filer does not report are named in `missing_buckets` rather than assumed
|
|
46
|
+
* away silently. No bucket at all is null, never zero: a company with unknown debt is not a
|
|
47
|
+
* debt-free company.
|
|
48
|
+
*/
|
|
49
|
+
export function totalDebtForYear(series, fiscalYear) {
|
|
50
|
+
const combined = series.debt_combined.find((entry) => entry.fiscal_year === fiscalYear);
|
|
51
|
+
if (combined) {
|
|
52
|
+
return { value: combined.value, entries: [combined], buckets: ["debt_combined"], missing_buckets: [] };
|
|
53
|
+
}
|
|
54
|
+
const present = DEBT_BUCKETS
|
|
55
|
+
.map((bucket) => ({ bucket, entry: series[bucket].find((item) => item.fiscal_year === fiscalYear) }))
|
|
56
|
+
.filter((item) => item.entry);
|
|
57
|
+
if (!present.length) return null;
|
|
58
|
+
return {
|
|
59
|
+
value: sum(present.map((item) => item.entry.value)),
|
|
60
|
+
entries: present.map((item) => item.entry),
|
|
61
|
+
buckets: present.map((item) => item.bucket),
|
|
62
|
+
missing_buckets: DEBT_BUCKETS.filter((bucket) => !present.some((item) => item.bucket === bucket)),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function tangibleBookForYear(series, fiscalYear) {
|
|
67
|
+
const equity = series.equity.find((entry) => entry.fiscal_year === fiscalYear);
|
|
68
|
+
if (!equity) return null;
|
|
69
|
+
const deductions = [];
|
|
70
|
+
const assumptions = [];
|
|
71
|
+
const entries = [equity];
|
|
72
|
+
for (const concept of ["goodwill", "intangibles"]) {
|
|
73
|
+
const entry = series[concept].find((item) => item.fiscal_year === fiscalYear);
|
|
74
|
+
if (entry) {
|
|
75
|
+
deductions.push({ concept, tag: entry.tag, value: entry.value });
|
|
76
|
+
entries.push(entry);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (series[concept].length) return { misaligned: concept };
|
|
80
|
+
assumptions.push(`${concept} is not tagged in any period of this filer's Company Facts and is treated as 0`);
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
value: equity.value - sum(deductions.map((item) => item.value)),
|
|
84
|
+
equity: equity.value,
|
|
85
|
+
deductions,
|
|
86
|
+
assumptions,
|
|
87
|
+
entries,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function profitForYear(series, fiscalYear) {
|
|
92
|
+
const nopat = alignYear(series, ["operating_income", "tax_expense", "pretax_income"], fiscalYear);
|
|
93
|
+
if (nopat.ok && nopat.entries.pretax_income.value > 0) {
|
|
94
|
+
const rate = nopat.entries.tax_expense.value / nopat.entries.pretax_income.value;
|
|
95
|
+
if (rate >= 0 && rate < 1) {
|
|
96
|
+
return {
|
|
97
|
+
basis: "nopat",
|
|
98
|
+
value: nopat.entries.operating_income.value * (1 - rate),
|
|
99
|
+
effective_tax_rate: decimal(rate),
|
|
100
|
+
entries: nopat.used,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const netIncome = series.net_income.find((entry) => entry.fiscal_year === fiscalYear);
|
|
105
|
+
if (!netIncome) return null;
|
|
106
|
+
return { basis: "net_income", value: netIncome.value, effective_tax_rate: null, entries: [netIncome] };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function fourQuarters(quarters, index) {
|
|
110
|
+
if (index < 3) return null;
|
|
111
|
+
const window = quarters.slice(index - 3, index + 1);
|
|
112
|
+
const span = daysBetween(window[0].start, window.at(-1).end);
|
|
113
|
+
if (span < 330 || span > 400) return null;
|
|
114
|
+
for (let position = 1; position < window.length; position += 1) {
|
|
115
|
+
const seam = daysBetween(window[position - 1].end, window[position].start);
|
|
116
|
+
if (seam < -5 || seam > 15) return null;
|
|
117
|
+
}
|
|
118
|
+
return { total: sum(window.map((entry) => entry.val)), window };
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function matchedProfits(series, startYear, endYear) {
|
|
122
|
+
const profits = [startYear, endYear].map((year) => profitForYear(series, year));
|
|
123
|
+
if (profits.some((profit) => !profit)) return null;
|
|
124
|
+
if (profits.every((profit) => profit.basis === "nopat")) return { basis: "nopat", profits };
|
|
125
|
+
const fallback = [startYear, endYear]
|
|
126
|
+
.map((year) => series.net_income.find((entry) => entry.fiscal_year === year));
|
|
127
|
+
if (fallback.some((entry) => !entry)) return null;
|
|
128
|
+
return {
|
|
129
|
+
basis: "net_income",
|
|
130
|
+
profits: fallback.map((entry) => ({ basis: "net_income", value: entry.value, entries: [entry] })),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function investedCapital(series, fiscalYear) {
|
|
135
|
+
const alignment = alignYear(series, ["equity", "cash"], fiscalYear);
|
|
136
|
+
if (!alignment.ok) return null;
|
|
137
|
+
const debt = totalDebtForYear(series, fiscalYear);
|
|
138
|
+
if (!debt) return null;
|
|
139
|
+
return {
|
|
140
|
+
value: alignment.entries.equity.value + debt.value - alignment.entries.cash.value,
|
|
141
|
+
period_end: alignment.period_end,
|
|
142
|
+
entries: [...alignment.used, ...debt.entries],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function ebitdaForYear(series, fiscalYear) {
|
|
147
|
+
const alignment = alignYear(series, ["operating_income", "depreciation_amortisation"], fiscalYear);
|
|
148
|
+
if (!alignment.ok) return null;
|
|
149
|
+
return {
|
|
150
|
+
value: alignment.entries.operating_income.value + alignment.entries.depreciation_amortisation.value,
|
|
151
|
+
entries: alignment.used,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XBRL series plumbing shared by every derived fundamental.
|
|
3
|
+
*
|
|
4
|
+
* Nothing here knows what a metric means. It answers four mechanical questions about SEC
|
|
5
|
+
* Company Facts documents -- which periods exist for a concept, which of them align, when the
|
|
6
|
+
* newest input became public, and how a computed number is packaged with its lineage -- and
|
|
7
|
+
* `fundamentals.mjs` builds the operating figures on top. Separating them keeps the alignment
|
|
8
|
+
* rules in one place: a metric that quietly aligned differently from its neighbours would be
|
|
9
|
+
* the kind of defect no test asks about.
|
|
10
|
+
*
|
|
11
|
+
* All network access goes through sec.mjs, which owns the throttle and the User-Agent.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { CONCEPTS, annualSeries } from "./sec.mjs";
|
|
15
|
+
import { sha256 } from "./personas-v3/canonical.mjs";
|
|
16
|
+
|
|
17
|
+
export const TOOL_ID = "sec_fundamentals";
|
|
18
|
+
export const TOOL_VERSION = "1.0.0";
|
|
19
|
+
const HASH_DOMAIN = "alphacouncil.fundamentals.sec-companyfacts.v1";
|
|
20
|
+
|
|
21
|
+
const finite = (value) => typeof value === "number" && Number.isFinite(value);
|
|
22
|
+
export const decimal = (value) => Number(value.toFixed(6));
|
|
23
|
+
const DAY_MS = 86_400_000;
|
|
24
|
+
export const daysBetween = (from, to) => Math.round((Date.parse(to) - Date.parse(from)) / DAY_MS);
|
|
25
|
+
|
|
26
|
+
/** Two facts claiming the same period may not disagree by more than this. */
|
|
27
|
+
export const MAX_ALIGNMENT_DRIFT_DAYS = 45;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Concept aliases, ordered by preference, on top of the ones sec.mjs already publishes.
|
|
31
|
+
*
|
|
32
|
+
* Aliases inside one entry are the same economic quantity under different taxonomies. They
|
|
33
|
+
* are never a fallback to a different concept: total liabilities is not reconstructed from
|
|
34
|
+
* an equity subtraction, and a missing depreciation tag stays missing.
|
|
35
|
+
*/
|
|
36
|
+
export const FUNDAMENTAL_CONCEPTS = Object.freeze({
|
|
37
|
+
revenue: { tags: CONCEPTS.revenue, unit: "USD" },
|
|
38
|
+
net_income: { tags: CONCEPTS.netIncome, unit: "USD" },
|
|
39
|
+
operating_income: { tags: CONCEPTS.operatingIncome, unit: "USD" },
|
|
40
|
+
capex: { tags: CONCEPTS.capex, unit: "USD" },
|
|
41
|
+
equity: { tags: CONCEPTS.equity, unit: "USD" },
|
|
42
|
+
depreciation_amortisation: {
|
|
43
|
+
tags: [
|
|
44
|
+
"DepreciationDepletionAndAmortization",
|
|
45
|
+
"DepreciationAmortizationAndAccretionNet",
|
|
46
|
+
"DepreciationAndAmortization",
|
|
47
|
+
"Depreciation",
|
|
48
|
+
],
|
|
49
|
+
unit: "USD",
|
|
50
|
+
},
|
|
51
|
+
current_assets: { tags: ["AssetsCurrent"], unit: "USD" },
|
|
52
|
+
total_liabilities: { tags: ["Liabilities"], unit: "USD" },
|
|
53
|
+
goodwill: { tags: ["Goodwill"], unit: "USD" },
|
|
54
|
+
intangibles: { tags: ["IntangibleAssetsNetExcludingGoodwill", "FiniteLivedIntangibleAssetsNet"], unit: "USD" },
|
|
55
|
+
cash: {
|
|
56
|
+
tags: [
|
|
57
|
+
"CashAndCashEquivalentsAtCarryingValue",
|
|
58
|
+
"CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalents",
|
|
59
|
+
],
|
|
60
|
+
unit: "USD",
|
|
61
|
+
},
|
|
62
|
+
// Debt buckets are non-overlapping by construction so they can be summed. `debt_combined`
|
|
63
|
+
// is the whole of it in one tag and wins outright when a filer publishes it.
|
|
64
|
+
debt_combined: { tags: ["DebtLongtermAndShorttermCombinedAmount"], unit: "USD" },
|
|
65
|
+
debt_long_term_noncurrent: { tags: ["LongTermDebtNoncurrent", "LongTermDebtAndCapitalLeaseObligations"], unit: "USD" },
|
|
66
|
+
debt_long_term_current: { tags: ["LongTermDebtCurrent", "LongTermDebtAndCapitalLeaseObligationsCurrent"], unit: "USD" },
|
|
67
|
+
debt_short_term: { tags: ["ShortTermBorrowings", "OtherShortTermBorrowings", "CommercialPaper"], unit: "USD" },
|
|
68
|
+
tax_expense: { tags: ["IncomeTaxExpenseBenefit"], unit: "USD" },
|
|
69
|
+
pretax_income: {
|
|
70
|
+
tags: [
|
|
71
|
+
"IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest",
|
|
72
|
+
"IncomeLossFromContinuingOperationsBeforeIncomeTaxesMinorityInterestAndIncomeLossFromEquityMethodInvestments",
|
|
73
|
+
],
|
|
74
|
+
unit: "USD",
|
|
75
|
+
},
|
|
76
|
+
diluted_shares: {
|
|
77
|
+
tags: ["WeightedAverageNumberOfDilutedSharesOutstanding", "WeightedAverageNumberOfDilutedSharesOutstandingBasicAndDiluted"],
|
|
78
|
+
// Share concepts are filed under `shares`, not USD. Asking for USD returns nothing, which
|
|
79
|
+
// is how the screen's dilution rule once reported "skipped" for every company alive.
|
|
80
|
+
unit: "shares",
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const DEBT_BUCKETS = Object.freeze(["debt_long_term_noncurrent", "debt_long_term_current", "debt_short_term"]);
|
|
85
|
+
|
|
86
|
+
/** A date-only SEC field becomes an explicit UTC instant; anything unparseable becomes null. */
|
|
87
|
+
export function toInstant(value) {
|
|
88
|
+
if (typeof value !== "string" || value.length < 10) return null;
|
|
89
|
+
const time = Date.parse(value.length === 10 ? `${value}T00:00:00.000Z` : value);
|
|
90
|
+
return Number.isFinite(time) ? new Date(time).toISOString() : null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The fiscal year a period belongs to, taken from its end date -- the sec.mjs convention. */
|
|
94
|
+
export const fiscalYearOf = (end) => Number(String(end).slice(0, 4));
|
|
95
|
+
|
|
96
|
+
/* -------------------------------------------------------------- series and alignment -- */
|
|
97
|
+
|
|
98
|
+
/** One concept's annual history, flattened the way screen.mjs flattens it. */
|
|
99
|
+
export function conceptSeries(companyFacts, concept, asOf) {
|
|
100
|
+
const spec = FUNDAMENTAL_CONCEPTS[concept];
|
|
101
|
+
const found = annualSeries(companyFacts, spec.tags, { asOf, unit: spec.unit });
|
|
102
|
+
if (!found) return [];
|
|
103
|
+
return found.series.map((entry) => Object.freeze({
|
|
104
|
+
concept,
|
|
105
|
+
tag: entry.tag || found.tag,
|
|
106
|
+
unit: spec.unit,
|
|
107
|
+
start: entry.start || null,
|
|
108
|
+
end: entry.end,
|
|
109
|
+
filed: entry.filed || null,
|
|
110
|
+
accession: entry.accn || null,
|
|
111
|
+
value: entry.val,
|
|
112
|
+
fiscal_year: fiscalYearOf(entry.end),
|
|
113
|
+
}));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function loadSeries(companyFacts, asOf) {
|
|
117
|
+
return Object.freeze(Object.fromEntries(Object.keys(FUNDAMENTAL_CONCEPTS)
|
|
118
|
+
.map((concept) => [concept, conceptSeries(companyFacts, concept, asOf)])));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Quarterly history for a concept. sec.mjs only merges annual periods, so this mirrors its
|
|
123
|
+
* rules for ~quarter-length durations: alias preference decides a period, a later filing of
|
|
124
|
+
* the same alias supersedes an earlier one, and nothing filed after `asOf` is visible.
|
|
125
|
+
*/
|
|
126
|
+
export function quarterlySeries(companyFacts, tags, { asOf = null, unit = "USD" } = {}) {
|
|
127
|
+
const cutoff = asOf ? new Date(asOf).getTime() : null;
|
|
128
|
+
const byEnd = new Map();
|
|
129
|
+
for (const tag of tags) {
|
|
130
|
+
const entries = companyFacts?.facts?.["us-gaap"]?.[tag]?.units?.[unit];
|
|
131
|
+
if (!Array.isArray(entries)) continue;
|
|
132
|
+
for (const entry of entries) {
|
|
133
|
+
if (entry.form !== "10-Q" && entry.form !== "10-K") continue;
|
|
134
|
+
if (!entry.start || !entry.end || !Number.isFinite(entry.val)) continue;
|
|
135
|
+
const days = daysBetween(entry.start, entry.end);
|
|
136
|
+
if (days < 80 || days > 100) continue;
|
|
137
|
+
if (cutoff && new Date(entry.filed).getTime() > cutoff) continue;
|
|
138
|
+
const prior = byEnd.get(entry.end);
|
|
139
|
+
if (!prior) {
|
|
140
|
+
byEnd.set(entry.end, { ...entry, tag });
|
|
141
|
+
} else if (prior.tag === tag && new Date(entry.filed) > new Date(prior.filed)) {
|
|
142
|
+
byEnd.set(entry.end, { ...entry, tag });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (!byEnd.size) return null;
|
|
147
|
+
return [...byEnd.values()].sort((left, right) => Date.parse(left.end) - Date.parse(right.end));
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** The newest filing instant across a set of entries -- the moment the metric became public. */
|
|
151
|
+
export function publicInstant(entries) {
|
|
152
|
+
const instants = entries.map((entry) => toInstant(entry.filed)).filter(Boolean);
|
|
153
|
+
if (instants.length !== entries.length) return null;
|
|
154
|
+
return instants.sort().at(-1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The most recent fiscal year in which every named concept has a value.
|
|
159
|
+
*
|
|
160
|
+
* Aligning matters more than it looks: pairing this year's net income with last year's
|
|
161
|
+
* balance sheet because one tag stopped being filed is exactly the stale-period carry-forward
|
|
162
|
+
* this module exists to refuse.
|
|
163
|
+
*/
|
|
164
|
+
export function alignLatest(series, concepts) {
|
|
165
|
+
const missing = concepts.filter((concept) => !series[concept]?.length);
|
|
166
|
+
if (missing.length) return { ok: false, reason: "missing_tag", missing };
|
|
167
|
+
|
|
168
|
+
const byYear = concepts.map((concept) => new Map(series[concept].map((entry) => [entry.fiscal_year, entry])));
|
|
169
|
+
const shared = [...byYear[0].keys()].filter((year) => byYear.every((map) => map.has(year)));
|
|
170
|
+
if (!shared.length) return { ok: false, reason: "no_common_period", missing: [] };
|
|
171
|
+
|
|
172
|
+
const fiscalYear = Math.max(...shared);
|
|
173
|
+
const entries = concepts.map((concept, index) => byYear[index].get(fiscalYear));
|
|
174
|
+
return finishAlignment(entries, concepts, fiscalYear);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** The same alignment, pinned to a stated fiscal year rather than to the newest one. */
|
|
178
|
+
export function alignYear(series, concepts, fiscalYear) {
|
|
179
|
+
const picked = concepts.map((concept) => series[concept]?.find((entry) => entry.fiscal_year === fiscalYear));
|
|
180
|
+
const missing = concepts.filter((concept, index) => !picked[index]);
|
|
181
|
+
if (missing.length) return { ok: false, reason: "no_common_period", missing };
|
|
182
|
+
return finishAlignment(picked, concepts, fiscalYear);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function finishAlignment(entries, concepts, fiscalYear) {
|
|
186
|
+
const ends = entries.map((entry) => Date.parse(entry.end));
|
|
187
|
+
if (Math.max(...ends) - Math.min(...ends) > MAX_ALIGNMENT_DRIFT_DAYS * DAY_MS) {
|
|
188
|
+
return { ok: false, reason: "period_misaligned", missing: [] };
|
|
189
|
+
}
|
|
190
|
+
const publicAt = publicInstant(entries);
|
|
191
|
+
if (!publicAt) return { ok: false, reason: "missing_filing_date", missing: [] };
|
|
192
|
+
|
|
193
|
+
const starts = entries.map((entry) => entry.start).filter(Boolean).sort();
|
|
194
|
+
return {
|
|
195
|
+
ok: true,
|
|
196
|
+
fiscal_year: fiscalYear,
|
|
197
|
+
period_start: starts[0] || null,
|
|
198
|
+
period_end: entries.map((entry) => entry.end).sort().at(-1),
|
|
199
|
+
public_at: publicAt,
|
|
200
|
+
entries: Object.fromEntries(concepts.map((concept, index) => [concept, entries[index]])),
|
|
201
|
+
used: entries,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/** Merge alignments that must describe the same balance sheet or the same fiscal year. */
|
|
206
|
+
export function combineAlignments(alignments) {
|
|
207
|
+
const ends = alignments.map((alignment) => Date.parse(alignment.period_end));
|
|
208
|
+
if (Math.max(...ends) - Math.min(...ends) > MAX_ALIGNMENT_DRIFT_DAYS * DAY_MS) {
|
|
209
|
+
return { ok: false, reason: "period_misaligned", missing: [] };
|
|
210
|
+
}
|
|
211
|
+
const used = alignments.flatMap((alignment) => alignment.used);
|
|
212
|
+
const starts = used.map((entry) => entry.start).filter(Boolean).sort();
|
|
213
|
+
return {
|
|
214
|
+
ok: true,
|
|
215
|
+
fiscal_year: Math.max(...alignments.map((alignment) => alignment.fiscal_year)),
|
|
216
|
+
period_start: starts[0] || null,
|
|
217
|
+
period_end: alignments.map((alignment) => alignment.period_end).sort().at(-1),
|
|
218
|
+
public_at: alignments.map((alignment) => alignment.public_at).sort().at(-1),
|
|
219
|
+
entries: Object.assign({}, ...alignments.map((alignment) => alignment.entries)),
|
|
220
|
+
used,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* ------------------------------------------------------------------------------- gaps -- */
|
|
225
|
+
|
|
226
|
+
export const tagsFor = (concepts) => concepts.flatMap((concept) => FUNDAMENTAL_CONCEPTS[concept]?.tags || []);
|
|
227
|
+
|
|
228
|
+
export function gap({ factId, component = null, code, detail, missingTags = [] }) {
|
|
229
|
+
return Object.freeze({
|
|
230
|
+
metric: factId,
|
|
231
|
+
component,
|
|
232
|
+
code,
|
|
233
|
+
detail,
|
|
234
|
+
missing_tags: Object.freeze([...missingTags]),
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** Turn a failed alignment into a gap that names the concept and every tag that was tried. */
|
|
239
|
+
export function alignmentGap(factId, alignment, concepts, component = null) {
|
|
240
|
+
if (alignment.reason === "missing_tag" || (alignment.reason === "no_common_period" && alignment.missing.length)) {
|
|
241
|
+
const missingTags = tagsFor(alignment.missing);
|
|
242
|
+
return gap({
|
|
243
|
+
factId,
|
|
244
|
+
component,
|
|
245
|
+
code: alignment.reason,
|
|
246
|
+
detail: alignment.reason === "missing_tag"
|
|
247
|
+
? `no XBRL tag for ${alignment.missing.join(", ")} in Company Facts (tried ${missingTags.join(", ")})`
|
|
248
|
+
: `${alignment.missing.join(", ")} is not reported for the aligned fiscal year`,
|
|
249
|
+
missingTags,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
const detail = {
|
|
253
|
+
no_common_period: `no fiscal year in which all of ${concepts.join(", ")} are reported together`,
|
|
254
|
+
period_misaligned: `${concepts.join(", ")} disagree on the period end by more than ${MAX_ALIGNMENT_DRIFT_DAYS} days`,
|
|
255
|
+
missing_filing_date: `an input carries no filing date, so public_at cannot be taken from the filing`,
|
|
256
|
+
}[alignment.reason] || `inputs unavailable for ${concepts.join(", ")}`;
|
|
257
|
+
return gap({ factId, component, code: alignment.reason, detail, missingTags: tagsFor(concepts) });
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/* --------------------------------------------------------------------- metric factory -- */
|
|
261
|
+
|
|
262
|
+
const CONFIDENCE = Object.freeze({ reported: 0.95, rederived: 0.9, estimated: 0.6 });
|
|
263
|
+
|
|
264
|
+
export function sourceRecords(entries) {
|
|
265
|
+
const seen = new Set();
|
|
266
|
+
const records = [];
|
|
267
|
+
for (const entry of entries) {
|
|
268
|
+
const key = `${entry.tag}:${entry.accession || entry.filed}:${entry.end}`;
|
|
269
|
+
if (seen.has(key)) continue;
|
|
270
|
+
seen.add(key);
|
|
271
|
+
records.push(Object.freeze({
|
|
272
|
+
concept: entry.concept,
|
|
273
|
+
tag: entry.tag,
|
|
274
|
+
accession: entry.accession,
|
|
275
|
+
filed: entry.filed,
|
|
276
|
+
period_end: entry.end,
|
|
277
|
+
unit: entry.unit,
|
|
278
|
+
value: entry.value,
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
return Object.freeze(records);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* `sec:companyfacts:<cik>:<tag>:<accession|filed>:<period_end>` -- the identity the typed-fact
|
|
286
|
+
* adapter already knows how to parse back into a filing locator.
|
|
287
|
+
*/
|
|
288
|
+
export function sourceIds(cik, entries) {
|
|
289
|
+
return Object.freeze([...new Set(sourceRecords(entries)
|
|
290
|
+
.map((record) => `sec:companyfacts:${cik}:${record.tag}:${record.accession || record.filed}:${record.period_end}`))]);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function buildMetric({
|
|
294
|
+
factId,
|
|
295
|
+
valueKind,
|
|
296
|
+
value,
|
|
297
|
+
unit,
|
|
298
|
+
currency = null,
|
|
299
|
+
scale = null,
|
|
300
|
+
ratioDenominator = null,
|
|
301
|
+
alignment,
|
|
302
|
+
cik,
|
|
303
|
+
derivation,
|
|
304
|
+
inputs,
|
|
305
|
+
assumptions,
|
|
306
|
+
components = null,
|
|
307
|
+
}) {
|
|
308
|
+
const derived = derivation !== "reported";
|
|
309
|
+
const parameters = { hash_domain: HASH_DOMAIN, fact_id: factId, tool_id: TOOL_ID, tool_version: TOOL_VERSION };
|
|
310
|
+
return Object.freeze({
|
|
311
|
+
fact_id: factId,
|
|
312
|
+
value_kind: valueKind,
|
|
313
|
+
value,
|
|
314
|
+
unit,
|
|
315
|
+
currency,
|
|
316
|
+
scale,
|
|
317
|
+
ratio_denominator: ratioDenominator,
|
|
318
|
+
// A metric may declare itself a point-in-time quantity, in which case the span its inputs
|
|
319
|
+
// were aligned over is not the period it covers and stating one would be wrong.
|
|
320
|
+
period_start: alignment.suppressInterval ? null : alignment.period_start,
|
|
321
|
+
period_end: alignment.suppressInterval ? null : alignment.period_end,
|
|
322
|
+
fiscal_year: Number.isInteger(alignment.fiscal_year) ? alignment.fiscal_year : null,
|
|
323
|
+
// Never the clock: the newest filing among the inputs is the moment this became knowable.
|
|
324
|
+
public_at: alignment.public_at,
|
|
325
|
+
derivation,
|
|
326
|
+
confidence: CONFIDENCE[derivation],
|
|
327
|
+
source_ids: sourceIds(cik, alignment.used),
|
|
328
|
+
source_records: sourceRecords(alignment.used),
|
|
329
|
+
inputs: Object.freeze(inputs),
|
|
330
|
+
components: components ? Object.freeze(components) : null,
|
|
331
|
+
assumptions: Object.freeze([...assumptions]),
|
|
332
|
+
tool_id: derived ? TOOL_ID : null,
|
|
333
|
+
tool_version: derived ? TOOL_VERSION : null,
|
|
334
|
+
// A reported figure is not a calculation, so it carries no calculation hash -- which is
|
|
335
|
+
// exactly what the typed-fact contract requires of `derivation: "reported"`.
|
|
336
|
+
calculation_hash: derived ? sha256({ ...parameters, inputs, assumptions, value }) : null,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/* -------------------------------------------------------------- shared derived pieces -- */
|
|
341
|
+
|
package/mcp/lib/xlsx.mjs
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read an .xlsx with Node built-ins and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* An xlsx is a ZIP of XML parts, and `zlib.inflateRawSync` is enough to open one. Extracted
|
|
5
|
+
* from the fund adapter because it has no fund-domain knowledge at all: any publisher that
|
|
6
|
+
* ships a workbook -- issuer holdings, an academic dataset -- reads through the same three
|
|
7
|
+
* steps. Adding a spreadsheet dependency to a zero-dependency package is not worth it for
|
|
8
|
+
* what fits in a hundred lines.
|
|
9
|
+
*
|
|
10
|
+
* Everything unusual fails closed. This reads the ordinary single-workbook shape; it is not a
|
|
11
|
+
* general ZIP implementation and must not quietly behave like one.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { inflateRawSync } from "node:zlib";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Minimal ZIP central-directory reader.
|
|
18
|
+
*
|
|
19
|
+
* An xlsx is a ZIP of XML parts, and `zlib.inflateRawSync` is enough to read one, so a workbook is
|
|
20
|
+
* readable without adding a dependency. Entries are located through the CENTRAL directory
|
|
21
|
+
* rather than the local headers on purpose: when the archive uses a data descriptor, the
|
|
22
|
+
* local header's sizes are zeroed and only the central directory is truthful.
|
|
23
|
+
*
|
|
24
|
+
* Everything unusual fails closed. This reads the one archive shape SSGA publishes; it is not
|
|
25
|
+
* a general ZIP implementation and must not silently behave like one.
|
|
26
|
+
*/
|
|
27
|
+
export function unzip(buffer) {
|
|
28
|
+
const buf = Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
|
|
29
|
+
if (buf.length < 22 || buf.readUInt32LE(0) !== 0x04034b50) {
|
|
30
|
+
throw new Error("response is not a ZIP/xlsx container");
|
|
31
|
+
}
|
|
32
|
+
let eocd = -1;
|
|
33
|
+
for (let i = buf.length - 22; i >= 0; i -= 1) {
|
|
34
|
+
if (buf.readUInt32LE(i) === 0x06054b50) { eocd = i; break; }
|
|
35
|
+
}
|
|
36
|
+
if (eocd < 0) throw new Error("xlsx container has no end-of-central-directory record");
|
|
37
|
+
if (buf.readUInt16LE(eocd + 10) === 0xffff) throw new Error("ZIP64 xlsx containers are not supported");
|
|
38
|
+
|
|
39
|
+
const count = buf.readUInt16LE(eocd + 10);
|
|
40
|
+
let offset = buf.readUInt32LE(eocd + 16);
|
|
41
|
+
const entries = new Map();
|
|
42
|
+
for (let i = 0; i < count; i += 1) {
|
|
43
|
+
if (offset + 46 > buf.length || buf.readUInt32LE(offset) !== 0x02014b50) {
|
|
44
|
+
throw new Error("xlsx central directory is malformed");
|
|
45
|
+
}
|
|
46
|
+
const flags = buf.readUInt16LE(offset + 8);
|
|
47
|
+
const method = buf.readUInt16LE(offset + 10);
|
|
48
|
+
const compressedSize = buf.readUInt32LE(offset + 20);
|
|
49
|
+
const nameLen = buf.readUInt16LE(offset + 28);
|
|
50
|
+
const extraLen = buf.readUInt16LE(offset + 30);
|
|
51
|
+
const commentLen = buf.readUInt16LE(offset + 32);
|
|
52
|
+
const localOffset = buf.readUInt32LE(offset + 42);
|
|
53
|
+
const name = buf.toString("utf8", offset + 46, offset + 46 + nameLen);
|
|
54
|
+
if (flags & 0x0001) throw new Error(`xlsx entry ${name} is encrypted`);
|
|
55
|
+
if (method !== 0 && method !== 8) throw new Error(`xlsx entry ${name} uses unsupported compression method ${method}`);
|
|
56
|
+
const localNameLen = buf.readUInt16LE(localOffset + 26);
|
|
57
|
+
const localExtraLen = buf.readUInt16LE(localOffset + 28);
|
|
58
|
+
const start = localOffset + 30 + localNameLen + localExtraLen;
|
|
59
|
+
const raw = buf.subarray(start, start + compressedSize);
|
|
60
|
+
entries.set(name, () => (method === 0 ? raw : inflateRawSync(raw)).toString("utf8"));
|
|
61
|
+
offset += 46 + nameLen + extraLen + commentLen;
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const XML_ENTITIES = Object.freeze({ "<": "<", ">": ">", """: '"', "'": "'", "&": "&" });
|
|
67
|
+
const unescapeXml = (text) => String(text).replace(/&(?:lt|gt|quot|apos|amp);/gu, (m) => XML_ENTITIES[m]);
|
|
68
|
+
|
|
69
|
+
/** Concatenate every <t> inside an element: a shared string may be split into rich-text runs. */
|
|
70
|
+
export const xmlText = (fragment) => {
|
|
71
|
+
let out = "";
|
|
72
|
+
for (const match of String(fragment).matchAll(/<t[^>]*>([\s\S]*?)<\/t>/gu)) out += match[1];
|
|
73
|
+
return unescapeXml(out);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/** "AB12" -> 27. Cells are addressed, not ordered: empty cells are simply absent. */
|
|
77
|
+
export const columnIndex = (ref) => {
|
|
78
|
+
const letters = /^([A-Z]+)/u.exec(String(ref || "").toUpperCase());
|
|
79
|
+
if (!letters) return -1;
|
|
80
|
+
return [...letters[1]].reduce((acc, ch) => acc * 26 + (ch.charCodeAt(0) - 64), 0) - 1;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export function xlsxRows(sheetXml, sharedStrings) {
|
|
84
|
+
const rows = [];
|
|
85
|
+
for (const rowMatch of sheetXml.matchAll(/<row[^>]*>([\s\S]*?)<\/row>/gu)) {
|
|
86
|
+
const cells = [];
|
|
87
|
+
for (const cellMatch of rowMatch[1].matchAll(/<c\s+r="([A-Z]+\d+)"([^>]*)>([\s\S]*?)<\/c>/gu)) {
|
|
88
|
+
const index = columnIndex(cellMatch[1]);
|
|
89
|
+
if (index < 0) continue;
|
|
90
|
+
const type = /t="([^"]+)"/u.exec(cellMatch[2])?.[1] || "n";
|
|
91
|
+
const body = cellMatch[3];
|
|
92
|
+
const value = /<v>([\s\S]*?)<\/v>/u.exec(body)?.[1];
|
|
93
|
+
if (type === "s") cells[index] = sharedStrings[Number(value)] ?? null;
|
|
94
|
+
else if (type === "inlineStr") cells[index] = xmlText(/<is>([\s\S]*?)<\/is>/u.exec(body)?.[1] || "");
|
|
95
|
+
else cells[index] = value === undefined ? null : unescapeXml(value);
|
|
96
|
+
}
|
|
97
|
+
rows.push(cells);
|
|
98
|
+
}
|
|
99
|
+
return rows;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Open a workbook: every sheet's rows, plus the date system its serials are counted in.
|
|
104
|
+
*
|
|
105
|
+
* The date system is not optional detail. A workbook written by Mac Excel sets
|
|
106
|
+
* `date1904="1"` and its serials sit 1,462 days from the default epoch -- read with the wrong
|
|
107
|
+
* one, every date is silently four years and a day early, which looks entirely plausible and
|
|
108
|
+
* is how a current dataset gets mistaken for a stale one.
|
|
109
|
+
*
|
|
110
|
+
* Callers locate their header row by content rather than by offset: publishers move the table
|
|
111
|
+
* when the surrounding label and disclosure rows change length.
|
|
112
|
+
*/
|
|
113
|
+
export function readWorkbook(buffer) {
|
|
114
|
+
const entries = unzip(buffer);
|
|
115
|
+
const workbookPart = entries.get("xl/workbook.xml");
|
|
116
|
+
const date1904 = workbookPart ? /date1904\s*=\s*"(?:1|true)"/iu.test(workbookPart()) : false;
|
|
117
|
+
const sharedPart = entries.get("xl/sharedStrings.xml");
|
|
118
|
+
const sharedStrings = sharedPart
|
|
119
|
+
? [...sharedPart().matchAll(/<si>([\s\S]*?)<\/si>/gu)].map((match) => xmlText(match[1]))
|
|
120
|
+
: [];
|
|
121
|
+
const sheets = [...entries.keys()]
|
|
122
|
+
.filter((name) => /^xl\/worksheets\/[^/]+\.xml$/u.test(name))
|
|
123
|
+
.sort()
|
|
124
|
+
.map((name) => ({ name, rows: xlsxRows(entries.get(name)(), sharedStrings) }));
|
|
125
|
+
if (!sheets.length) throw new Error("workbook contains no worksheet part");
|
|
126
|
+
return { date1904, sheets };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Excel serial date to ISO, honouring the workbook's date system.
|
|
131
|
+
*
|
|
132
|
+
* In the default 1900 system day 1 is 1900-01-01 and the format wrongly treats 1900 as a leap
|
|
133
|
+
* year, so serials at or above 60 carry an extra day that has to come back out. The 1904
|
|
134
|
+
* system has neither quirk.
|
|
135
|
+
*/
|
|
136
|
+
export function excelSerialToIso(serial, { date1904 = false } = {}) {
|
|
137
|
+
const value = Number(serial);
|
|
138
|
+
if (!Number.isFinite(value) || value < 0) return null;
|
|
139
|
+
const epoch = date1904 ? Date.UTC(1904, 0, 1) : Date.UTC(1899, 11, 31);
|
|
140
|
+
const days = date1904 ? value : (value >= 60 ? value - 1 : value);
|
|
141
|
+
return new Date(epoch + (days * 86400000)).toISOString().slice(0, 10);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function readWorkbookRows(buffer, { sheetPath = null } = {}) {
|
|
145
|
+
const entries = unzip(buffer);
|
|
146
|
+
const sharedPart = entries.get("xl/sharedStrings.xml");
|
|
147
|
+
const sharedStrings = sharedPart
|
|
148
|
+
? [...sharedPart().matchAll(/<si>([\s\S]*?)<\/si>/gu)].map((match) => xmlText(match[1]))
|
|
149
|
+
: [];
|
|
150
|
+
const target = sheetPath
|
|
151
|
+
|| [...entries.keys()].find((name) => /^xl\/worksheets\/sheet1\.xml$/u.test(name))
|
|
152
|
+
|| [...entries.keys()].find((name) => /^xl\/worksheets\/.+\.xml$/u.test(name));
|
|
153
|
+
if (!target) throw new Error("workbook contains no worksheet part");
|
|
154
|
+
return xlsxRows(entries.get(target)(), sharedStrings);
|
|
155
|
+
}
|