alphacouncil-agent 1.0.2 → 1.0.4

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 (38) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/CHANGELOG.md +70 -0
  5. package/README.md +24 -15
  6. package/README.zh-CN.md +18 -10
  7. package/data/authored/core-seats.mjs +8 -4
  8. package/data/build-profile.v1.json +1 -1
  9. package/data/persona-v3-build-specs.v1.mjs +1 -1
  10. package/docs/plans/v1.1-say-something-worth-reading.md +116 -0
  11. package/knowledge/ai-assisted-solo/experiments/runs/a.json +2 -2
  12. package/knowledge/ai-assisted-solo/experiments/runs/b.json +2 -2
  13. package/knowledge/ai-assisted-solo/experiments/runs/c.json +2 -2
  14. package/knowledge/ai-assisted-solo/experiments/runs/d13.json +2 -2
  15. package/knowledge/ai-assisted-solo/experiments/runs/d26.json +9 -9
  16. package/knowledge/ai-assisted-solo/experiments/runs/e-d13.json +4 -4
  17. package/knowledge/ai-assisted-solo/experiments/runs/e-d26.json +12 -12
  18. package/knowledge/ai-assisted-solo/experiments/runs/h_ai_reference.json +13 -13
  19. package/knowledge/ai-assisted-solo/experiments/simulation-input.json +6 -6
  20. package/knowledge/ai-assisted-solo/experiments/simulation-manifest.json +19 -19
  21. package/knowledge/solo-test/masters/master_bogle/decision_policy.json +4 -3
  22. package/knowledge/solo-test/masters/master_bogle/provisional-index.json +3 -0
  23. package/knowledge/solo-test/masters/master_bogle/sources.jsonl +1 -1
  24. package/mcp/lib/constants.mjs +3 -0
  25. package/mcp/lib/council-options.mjs +8 -4
  26. package/mcp/lib/fundamentals.mjs +61 -10
  27. package/mcp/lib/grounding.mjs +67 -1
  28. package/mcp/lib/insider-ownership.mjs +23 -12
  29. package/mcp/lib/orchestrator.mjs +10 -2
  30. package/mcp/lib/personas/engine.mjs +66 -9
  31. package/mcp/lib/personas-v3/deterministic-executor.mjs +39 -2
  32. package/mcp/lib/personas-v3/grounding-adapter.mjs +4 -0
  33. package/mcp/lib/personas-v3/runtime.mjs +9 -2
  34. package/mcp/lib/screen.mjs +27 -1
  35. package/mcp/lib/sec.mjs +80 -17
  36. package/mcp/lib/voice-from-decision.mjs +211 -0
  37. package/mcp/lib/xbrl-series.mjs +10 -3
  38. package/package.json +1 -1
@@ -44,12 +44,12 @@
44
44
  "formal_h_satisfied": false,
45
45
  "human_reference": false,
46
46
  "input_binding": {
47
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
47
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
48
48
  "path": "simulation-input.json"
49
49
  },
50
50
  "network_allowed": false,
51
51
  "production_effect": "none",
52
- "result_hash": "sha256:de7e06a9bf681eb8d55a26c5130bb2f4c8cd0f586958f4e659cdcad43d335315",
52
+ "result_hash": "sha256:8f99e06ff6ea3c5df7eefad85005b5c94a5508e62c9f39616d9de2b8115cde3e",
53
53
  "results": {
54
54
  "blocked_fail_closed_count": 1,
55
55
  "completion_status": "completed_machine_simulation",
@@ -417,18 +417,18 @@
417
417
  "structured_decision_hash": "sha256:c7a93f8c67eb3c423fc94ef0d51bb868ab5444d75aba2d17455e9ce0a20965d1"
418
418
  },
419
419
  {
420
- "anonymous_method_hash": "sha256:7c9acb22fb3cc01bde6064242f52e2cd9d64cde774945543c6465c4eacfe23fb",
421
- "deterministic_core_hash": "sha256:9d6d0a0af67b24c6b66edba2816e8b7e6b68ece2049752e5803bb3d6d9ea11d3",
420
+ "anonymous_method_hash": "sha256:7e72f0c819a737e9e2c95938807bd1f856427fefbff42cc6a52dad7c4b9648b9",
421
+ "deterministic_core_hash": "sha256:aedc8b29c59176e6cf5994b51682a2fb1cfe2cb62f0f5882f4de16c220ce00f6",
422
422
  "fact_pack_hash": "sha256:d035c7f7cbace9a80cce787b1ea3204f7b85437e4552dec34681765f0ab3af26",
423
- "frozen_decision_hash": "sha256:6a20b189b8a782c7e03c290eab45f7fc3ee8826fb3bc158ded0880d4e1f287ad",
423
+ "frozen_decision_hash": "sha256:f82a1fb3c31d68ae5c1ce9e93fa6d1f61f3f373c14a999d7ac52bc398b8f1ca4",
424
424
  "native_state": "provisional_fair_expected_return",
425
- "pack_hash": "sha256:73e829f5d2e3b1124689635cb70bbef8f764559603689a5eae9920716eaf5d1c",
425
+ "pack_hash": "sha256:cbc29f36bcf214b24045d582bf954d06cda6cec3aab06c41f650f7410df510f0",
426
426
  "persona_id": "master_bogle",
427
- "policy_execution_hash": "sha256:faa5ebcd8ead470e03bb2c38e6b62eb2aade6218f049655e7e901aeccf280f5b",
427
+ "policy_execution_hash": "sha256:3f4dfca52772b1f9ad7adec925acdba1d45bdabcd9a5d1272646d86601e20c4c",
428
428
  "score_ratio": 0.6666666666666666,
429
429
  "stance": "cautious",
430
430
  "status": "executed",
431
- "structured_decision_hash": "sha256:039e8c42dea63e6bc432446a6a285a3a3c1f6b4a2011faa46f3f40d81113e12a"
431
+ "structured_decision_hash": "sha256:71b52271b65d7229fe95524d953262eb175380066709f7bf50e4ee9386083a0e"
432
432
  }
433
433
  ],
434
434
  "deterministic_execution_count": 27,
@@ -449,13 +449,13 @@
449
449
  "verifier_checks": [
450
450
  {
451
451
  "check_id": "physical_input_hash_binding",
452
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
452
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
453
453
  "status": "pass"
454
454
  },
455
455
  {
456
456
  "check_id": "deterministic_rederivation",
457
- "first_result_hash": "sha256:dbb01a7bdcaccf19f2f022ca64586dd0866fe1ce4f3d5c33ffad61efccc8e997",
458
- "repeated_result_hash": "sha256:dbb01a7bdcaccf19f2f022ca64586dd0866fe1ce4f3d5c33ffad61efccc8e997",
457
+ "first_result_hash": "sha256:70f60386d393bb2323c0fa970bebb5659d31e468cf48519c5d31af045df40a06",
458
+ "repeated_result_hash": "sha256:70f60386d393bb2323c0fa970bebb5659d31e468cf48519c5d31af045df40a06",
459
459
  "status": "pass"
460
460
  },
461
461
  {
@@ -466,7 +466,7 @@
466
466
  ]
467
467
  },
468
468
  "reviewer_kind": "ai",
469
- "run_artifact_hash": "sha256:8120ff805d85265449c057f713f2684f06f409b5d0c288de3e3e620c220ec531",
469
+ "run_artifact_hash": "sha256:be206b4a629bcb349da681e6eaed9f695b0c880d84963092466285c19f830ce4",
470
470
  "run_id": "E:D26",
471
471
  "schema_version": 1,
472
472
  "simulation_scope": "D26 deterministic seats plus machine-only hash, rederivation and fail-closed checks"
@@ -44,12 +44,12 @@
44
44
  "formal_h_satisfied": false,
45
45
  "human_reference": false,
46
46
  "input_binding": {
47
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
47
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
48
48
  "path": "simulation-input.json"
49
49
  },
50
50
  "network_allowed": false,
51
51
  "production_effect": "none",
52
- "result_hash": "sha256:f910df4d8cc64bb5e25f0a238d23a6b785699d45863ca092b120afc4d4e2c4b6",
52
+ "result_hash": "sha256:f3213233355e046dbee466b468eac2714db0754559bcb93533cb5728d168ea9d",
53
53
  "results": {
54
54
  "blocked_fail_closed_count": 1,
55
55
  "completion_status": "completed_machine_simulation",
@@ -417,24 +417,24 @@
417
417
  "structured_decision_hash": "sha256:c7a93f8c67eb3c423fc94ef0d51bb868ab5444d75aba2d17455e9ce0a20965d1"
418
418
  },
419
419
  {
420
- "anonymous_method_hash": "sha256:7c9acb22fb3cc01bde6064242f52e2cd9d64cde774945543c6465c4eacfe23fb",
421
- "deterministic_core_hash": "sha256:9d6d0a0af67b24c6b66edba2816e8b7e6b68ece2049752e5803bb3d6d9ea11d3",
420
+ "anonymous_method_hash": "sha256:7e72f0c819a737e9e2c95938807bd1f856427fefbff42cc6a52dad7c4b9648b9",
421
+ "deterministic_core_hash": "sha256:aedc8b29c59176e6cf5994b51682a2fb1cfe2cb62f0f5882f4de16c220ce00f6",
422
422
  "fact_pack_hash": "sha256:d035c7f7cbace9a80cce787b1ea3204f7b85437e4552dec34681765f0ab3af26",
423
- "frozen_decision_hash": "sha256:6a20b189b8a782c7e03c290eab45f7fc3ee8826fb3bc158ded0880d4e1f287ad",
423
+ "frozen_decision_hash": "sha256:f82a1fb3c31d68ae5c1ce9e93fa6d1f61f3f373c14a999d7ac52bc398b8f1ca4",
424
424
  "native_state": "provisional_fair_expected_return",
425
- "pack_hash": "sha256:73e829f5d2e3b1124689635cb70bbef8f764559603689a5eae9920716eaf5d1c",
425
+ "pack_hash": "sha256:cbc29f36bcf214b24045d582bf954d06cda6cec3aab06c41f650f7410df510f0",
426
426
  "persona_id": "master_bogle",
427
- "policy_execution_hash": "sha256:faa5ebcd8ead470e03bb2c38e6b62eb2aade6218f049655e7e901aeccf280f5b",
427
+ "policy_execution_hash": "sha256:3f4dfca52772b1f9ad7adec925acdba1d45bdabcd9a5d1272646d86601e20c4c",
428
428
  "score_ratio": 0.6666666666666666,
429
429
  "stance": "cautious",
430
430
  "status": "executed",
431
- "structured_decision_hash": "sha256:039e8c42dea63e6bc432446a6a285a3a3c1f6b4a2011faa46f3f40d81113e12a"
431
+ "structured_decision_hash": "sha256:71b52271b65d7229fe95524d953262eb175380066709f7bf50e4ee9386083a0e"
432
432
  }
433
433
  ],
434
434
  "deterministic_execution_count": 27,
435
435
  "executed_count": 26,
436
436
  "formal_results": null,
437
- "machine_reference_digest": "sha256:dbb01a7bdcaccf19f2f022ca64586dd0866fe1ce4f3d5c33ffad61efccc8e997",
437
+ "machine_reference_digest": "sha256:70f60386d393bb2323c0fa970bebb5659d31e468cf48519c5d31af045df40a06",
438
438
  "metric_claims": [],
439
439
  "network_call_count": 0,
440
440
  "provider_cost_usd": 0,
@@ -449,13 +449,13 @@
449
449
  "verifier_checks": [
450
450
  {
451
451
  "check_id": "physical_input_hash_binding",
452
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
452
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
453
453
  "status": "pass"
454
454
  },
455
455
  {
456
456
  "check_id": "deterministic_rederivation",
457
- "first_result_hash": "sha256:dbb01a7bdcaccf19f2f022ca64586dd0866fe1ce4f3d5c33ffad61efccc8e997",
458
- "repeated_result_hash": "sha256:dbb01a7bdcaccf19f2f022ca64586dd0866fe1ce4f3d5c33ffad61efccc8e997",
457
+ "first_result_hash": "sha256:70f60386d393bb2323c0fa970bebb5659d31e468cf48519c5d31af045df40a06",
458
+ "repeated_result_hash": "sha256:70f60386d393bb2323c0fa970bebb5659d31e468cf48519c5d31af045df40a06",
459
459
  "status": "pass"
460
460
  },
461
461
  {
@@ -466,7 +466,7 @@
466
466
  ]
467
467
  },
468
468
  "reviewer_kind": "ai",
469
- "run_artifact_hash": "sha256:c383e1ed38d866258fd55e7ad1521df91487c4f14a3cf60e6cdae3fb49bcaa4d",
469
+ "run_artifact_hash": "sha256:790838e3d208ed1c9c3da3210ced26871f02b7fc8b01de920804bfbdefb4c000",
470
470
  "run_id": "H_ai_reference",
471
471
  "schema_version": 1,
472
472
  "simulation_scope": "AI deterministic reference digest only; no human analysts or blinded human adjudicator"
@@ -18,7 +18,7 @@
18
18
  "formal_ga_effect": "none",
19
19
  "formal_h_satisfied": false,
20
20
  "human_reference": false,
21
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
21
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
22
22
  "network_allowed": false,
23
23
  "production_effect": "none",
24
24
  "protocol_binding": {
@@ -31,14 +31,14 @@
31
31
  "reviewer_kind": "ai",
32
32
  "runtime_bindings": [
33
33
  {
34
- "byte_length": 27327,
34
+ "byte_length": 27650,
35
35
  "path": "mcp/lib/personas-v3/runtime.mjs",
36
- "physical_file_hash": "sha256:ad06e3d004cdb072909fc2fb9cf643dace28ff542a4c7092309fdd53f5623b63"
36
+ "physical_file_hash": "sha256:aa32cf59eaec9eeb9583e44b76b31fac8fb8661e49b0b19da6de0f9b4ca5f568"
37
37
  },
38
38
  {
39
- "byte_length": 49532,
39
+ "byte_length": 51789,
40
40
  "path": "mcp/lib/personas-v3/deterministic-executor.mjs",
41
- "physical_file_hash": "sha256:1222b8c56e5535ec1f446f55aee0a3c1b948f80403e53085de932398ae90f7ef"
41
+ "physical_file_hash": "sha256:ee45aed55448644c194e576b9f8611a9afd163e53b36f744ee687ae25ca99bdb"
42
42
  },
43
43
  {
44
44
  "byte_length": 8032,
@@ -8278,7 +8278,7 @@
8278
8278
  "schema_version": 1
8279
8279
  },
8280
8280
  "fact_pack_hash": "sha256:d035c7f7cbace9a80cce787b1ea3204f7b85437e4552dec34681765f0ab3af26",
8281
- "pack_hash": "sha256:73e829f5d2e3b1124689635cb70bbef8f764559603689a5eae9920716eaf5d1c",
8281
+ "pack_hash": "sha256:cbc29f36bcf214b24045d582bf954d06cda6cec3aab06c41f650f7410df510f0",
8282
8282
  "pack_manifest_binding": {
8283
8283
  "byte_length": 5640,
8284
8284
  "path": "knowledge/solo-test/masters/master_bogle/manifest.json",
@@ -6,11 +6,11 @@
6
6
  "formal_h_satisfied": false,
7
7
  "human_reference": false,
8
8
  "input_binding": {
9
- "content_hash": "sha256:cdbc6e5a916b1aca475748ce06158fc9ae8caaf7ab7650337baa9d74af9fc828",
10
- "input_hash": "sha256:db8f31c70e4b4589561a53127b16985a8b9d09000ba536df3467eacf857d2d0c",
9
+ "content_hash": "sha256:6340496a97245ce4bef30d91fdd7007e1128d7324ab28f55f8ff884a221a1363",
10
+ "input_hash": "sha256:cc4ffaa54c9477000383adc82ba43800c3725c331638f2f8f63cad15582a128f",
11
11
  "path": "simulation-input.json"
12
12
  },
13
- "manifest_hash": "sha256:6f23223d57531653456b1b5c67e4b1ceedce6f263d334bdcd4865c5ba05ae1d3",
13
+ "manifest_hash": "sha256:bb7437c3661c054886c048ed258739064cd132b86fb286265e7f0b43e22cd2f3",
14
14
  "n_eff_disclosure_binding": {
15
15
  "artifact_hash": "sha256:42ddb52fb8c5cc6335a0c90bbb4989fcfcc0a626ea1a32c87697ba4335ec94ab",
16
16
  "content_hash": "sha256:18f4efc086ffa86322eeb9b442960b291f41811d92b7fc3f59db72dfb5cbc305",
@@ -32,66 +32,66 @@
32
32
  "run_bindings": [
33
33
  {
34
34
  "blocked_fail_closed_count": 0,
35
- "content_hash": "sha256:2a77e9c2c0593f2a827e07d3814088228118b1a83d75567f3378fc73556387ac",
35
+ "content_hash": "sha256:6370e7f572f4ebcdec74b2424cd4a8b7f2867bd788902d38319b09d7c966ce52",
36
36
  "executed_count": 1,
37
37
  "path": "runs/a.json",
38
- "run_artifact_hash": "sha256:a0161522586f9a9b2ee80b68081279ec2b9399692e8e9e1ec56aef00379d27db",
38
+ "run_artifact_hash": "sha256:699e79ff212ba32d287d8847828b46e6bd46076519c6dc8dca5e9ac09f6d769f",
39
39
  "run_id": "A"
40
40
  },
41
41
  {
42
42
  "blocked_fail_closed_count": 0,
43
- "content_hash": "sha256:e7546d43a7fedcdcf33e04f444d876d8c587d1e76d1e558ca9fea1bf9a5f91fa",
43
+ "content_hash": "sha256:82ad061ab98755a8f62ac2007ef245f28c711f71bbb9e99d27d02c8a61a52451",
44
44
  "executed_count": 0,
45
45
  "path": "runs/b.json",
46
- "run_artifact_hash": "sha256:133ca81d8703085824a374f545ca30f83e90e4af45b8bdab17ed5aaa0e39adb1",
46
+ "run_artifact_hash": "sha256:423ac48286f88cd5e95942dce855507559d54fe7fd3a5481327424c4e6966f85",
47
47
  "run_id": "B"
48
48
  },
49
49
  {
50
50
  "blocked_fail_closed_count": 0,
51
- "content_hash": "sha256:eddda5b2d8702a9f4abe535f01a4a3f2a4cdd03585afa0f9656ab6fffb98d900",
51
+ "content_hash": "sha256:900dc8d6b6514e06080c207d67e98564dccb9bb04170bf3e1dc19bbe8db90c1e",
52
52
  "executed_count": 0,
53
53
  "path": "runs/c.json",
54
- "run_artifact_hash": "sha256:0760f289508bcbed0222e48531f3b0f8c394243fca4d7f6ad0a8de0b53fbb1b9",
54
+ "run_artifact_hash": "sha256:9a10ff578582c9476676ac454577d40e71aeb83dea128275e76d1d7e1d566f6c",
55
55
  "run_id": "C"
56
56
  },
57
57
  {
58
58
  "blocked_fail_closed_count": 0,
59
- "content_hash": "sha256:57d6781678d68417bec0cf6d2ff645234238f389e6d2f2a533b99edb28009170",
59
+ "content_hash": "sha256:acfe2440cd09928f73f542b39561bb5b66c77fc78cc37d56ec35b413daef32a5",
60
60
  "executed_count": 13,
61
61
  "path": "runs/d13.json",
62
- "run_artifact_hash": "sha256:6e5ae1711c012a4a7bb670090485ed071f5fdb66f33145e3adf9fb394c2231df",
62
+ "run_artifact_hash": "sha256:4ea0207eb1f9090b7a841585a268d8bef366a61d23b22bdeee0295bb52d47610",
63
63
  "run_id": "D13"
64
64
  },
65
65
  {
66
66
  "blocked_fail_closed_count": 1,
67
- "content_hash": "sha256:e50ac873b27e99b5459b75929b0a73986fc8cc64464f6d297f5460c58b047ccf",
67
+ "content_hash": "sha256:ccf02804dd2e4e41d8d79f81d4226227c6796ba5b753d0ab9724c1617839f476",
68
68
  "executed_count": 26,
69
69
  "path": "runs/d26.json",
70
- "run_artifact_hash": "sha256:184b9acfc9670ced5e8a41f346a3f6fc90d3e7f5db5f6093f61e4425d267d527",
70
+ "run_artifact_hash": "sha256:eb5d0df7917c119e07f82f7d7b84b4d4e84c6423753462ca7a26f9be16ebfef8",
71
71
  "run_id": "D26"
72
72
  },
73
73
  {
74
74
  "blocked_fail_closed_count": 0,
75
- "content_hash": "sha256:ed0b970d7de787d9cbf37745cfb8f3f1488375b5e1904764f2a1a4bccf4b70a2",
75
+ "content_hash": "sha256:443b278936de20e6f1645dc9eda2b1e3743c0ed58933c00794177549b256be67",
76
76
  "executed_count": 13,
77
77
  "path": "runs/e-d13.json",
78
- "run_artifact_hash": "sha256:76d61211082a3e02ac4e9196b5732183d6ca6c529e9e990622a228bc0e599bd5",
78
+ "run_artifact_hash": "sha256:3817bcac7b4ce7d1d0ddf06381b31b463b05790461f38de6b17e26ae2250f297",
79
79
  "run_id": "E:D13"
80
80
  },
81
81
  {
82
82
  "blocked_fail_closed_count": 1,
83
- "content_hash": "sha256:07cd8c9528cb72a9993c8121b353ea91a964f6dab6183e22881a3779fdc67dfd",
83
+ "content_hash": "sha256:9d5712d5baff1efe560691bc8208b25a5c90843b4ada21d1a339376a2b7395c7",
84
84
  "executed_count": 26,
85
85
  "path": "runs/e-d26.json",
86
- "run_artifact_hash": "sha256:8120ff805d85265449c057f713f2684f06f409b5d0c288de3e3e620c220ec531",
86
+ "run_artifact_hash": "sha256:be206b4a629bcb349da681e6eaed9f695b0c880d84963092466285c19f830ce4",
87
87
  "run_id": "E:D26"
88
88
  },
89
89
  {
90
90
  "blocked_fail_closed_count": 1,
91
- "content_hash": "sha256:0e57e34f69dff242a233522562a80d10d24390fb7837ce167e17a39cf2e87be5",
91
+ "content_hash": "sha256:805833bcc92aebb115c42de08e25c94ad4b8a98032d3375ed4301722521be02d",
92
92
  "executed_count": 26,
93
93
  "path": "runs/h_ai_reference.json",
94
- "run_artifact_hash": "sha256:c383e1ed38d866258fd55e7ad1521df91487c4f14a3cf60e6cdae3fb49bcaa4d",
94
+ "run_artifact_hash": "sha256:790838e3d208ed1c9c3da3210ced26871f02b7fc8b01de920804bfbdefb4c000",
95
95
  "run_id": "H_ai_reference"
96
96
  }
97
97
  ],
@@ -10,14 +10,14 @@
10
10
  "fact_id": "fund.top_ten_weight"
11
11
  }
12
12
  },
13
- "condition_id": "master_bogle.holdings_breadth_visible",
13
+ "condition_id": "master_bogle.subject_is_a_basket",
14
14
  "on_false": {
15
15
  "common_stance": "out_of_scope",
16
- "native_state": "provisional_insufficient_return_inputs"
16
+ "native_state": "provisional_not_a_basket"
17
17
  },
18
18
  "on_uncomputable": {
19
19
  "common_stance": "out_of_scope",
20
- "native_state": "provisional_insufficient_return_inputs"
20
+ "native_state": "provisional_not_a_basket"
21
21
  },
22
22
  "source_ids": [
23
23
  "proxy:1b982d2dc6b935fc0"
@@ -77,6 +77,7 @@
77
77
  }
78
78
  ],
79
79
  "native_states": [
80
+ "provisional_not_a_basket",
80
81
  "provisional_insufficient_return_inputs",
81
82
  "provisional_overpriced_market",
82
83
  "provisional_fair_expected_return",
@@ -6,9 +6,11 @@
6
6
  "provisional_fair_expected_return": "cautious",
7
7
  "provisional_insufficient_return_inputs": "out_of_scope",
8
8
  "provisional_low_cost_index_candidate": "cautious",
9
+ "provisional_not_a_basket": "cautious",
9
10
  "provisional_overpriced_market": "opposed"
10
11
  },
11
12
  "declared_state_hypotheses": [
13
+ "not_a_basket",
12
14
  "insufficient_return_inputs",
13
15
  "overpriced_market",
14
16
  "fair_expected_return",
@@ -19,6 +21,7 @@
19
21
  "formula_compilation_manifest_hash": "sha256:9eb750e5aec2e4b6ef7a7033aba119927d5a6540220d608cbe6fd90eaf255b05",
20
22
  "method_model_eligible": false,
21
23
  "native_states": [
24
+ "provisional_not_a_basket",
22
25
  "provisional_insufficient_return_inputs",
23
26
  "provisional_overpriced_market",
24
27
  "provisional_fair_expected_return",
@@ -1 +1 @@
1
- {"adjudication":{"notes":"No human review, no named-method attribution, no production effect.","reviewer_ids":[],"status":"pending"},"author":"AlphaCouncil project build specification","content_hash":"sha256:f0a1c271c11a09700d1fd65dc1b772a8d68433473478fc9d962e2078877ac494","grade":"E","known_at":"2026-07-27","locator":{"section":"master_bogle"},"public_at":"2026-07-27","published_at":"2026-07-27","retrieved_at":"2026-07-27","schema_version":1,"source_id":"proxy:1b982d2dc6b935fc0","source_kind":"derived_proxy","summary":"Project-authored provisional proxy used only to exercise the deterministic solo-test build; it is not source approval or method attribution.","supports":["solo_test_structure","deterministic_execution_only"],"title":"Provisional project-derived method hypothesis for master_bogle","url":"https://github.com/Zhao73/alphacouncil-agent/blob/main/data/persona-v3-build-specs.v1.mjs"}
1
+ {"adjudication":{"notes":"No human review, no named-method attribution, no production effect.","reviewer_ids":[],"status":"pending"},"author":"AlphaCouncil project build specification","content_hash":"sha256:21670e88406249cc764918c4137c9782bcd28419ef8f2e96077ccb5f18df121c","grade":"E","known_at":"2026-07-27","locator":{"section":"master_bogle"},"public_at":"2026-07-27","published_at":"2026-07-27","retrieved_at":"2026-07-27","schema_version":1,"source_id":"proxy:1b982d2dc6b935fc0","source_kind":"derived_proxy","summary":"Project-authored provisional proxy used only to exercise the deterministic solo-test build; it is not source approval or method attribution.","supports":["solo_test_structure","deterministic_execution_only"],"title":"Provisional project-derived method hypothesis for master_bogle","url":"https://github.com/Zhao73/alphacouncil-agent/blob/main/data/persona-v3-build-specs.v1.mjs"}
@@ -183,6 +183,9 @@ export const LIMITS = Object.freeze({
183
183
  )),
184
184
  /** Deterministic grounding is useful, but it may not hold the whole run hostage. */
185
185
  FULL_GROUNDING_MS: 30 * 1000,
186
+ // Grounding settles at its own budget and returns a partial result. This is only the
187
+ // backstop for a call that never returns at all, so it sits just beyond the budget.
188
+ GROUNDING_SETTLE_HEADROOM_MS: 5 * 1000,
186
189
  /** All eight full evidence seats launch in one wave under this per-seat cap. */
187
190
  FULL_EVIDENCE_MS: Math.max(1_000, Math.min(
188
191
  Number(process.env.ALPHACOUNCIL_FULL_EVIDENCE_MS) || 6 * 60 * 1000,
@@ -100,11 +100,15 @@ export function councilOptions({ language = "English" } = {}) {
100
100
  best_for: field(v3Selection.best_for, "best_for"),
101
101
  } : selectorCard(persona, language)),
102
102
  maturity: v3?.maturity || pack?.kind || "prompt_lens",
103
+ // The label names what a seat IS. It used to lead with "provisional", which read as a
104
+ // standing warning next to all twenty-seven names in the selector and repeated a review
105
+ // status the assurance section already reports. The machine-verified admission level is
106
+ // unchanged and still published as `admission_level` below.
103
107
  maturity_label: copy({
104
- en: v3?.maturity === "method_model" ? "Validated method model" : v3?.maturity === "candidate" ? "Candidate method" : "Provisional operator lens",
105
- zh: v3?.maturity === "method_model" ? "已验证方法模型" : v3?.maturity === "candidate" ? "候选方法" : "临时操作视角",
106
- ja: v3?.maturity === "method_model" ? "検証済みメソッドモデル" : v3?.maturity === "candidate" ? "候補メソッド" : "暫定オペレーター・レンズ",
107
- ko: v3?.maturity === "method_model" ? "검증된 방법론 모델" : v3?.maturity === "candidate" ? "후보 방법론" : "임시 오퍼레이터 렌즈",
108
+ en: v3?.maturity === "method_model" ? "Validated method model" : v3?.maturity === "candidate" ? "Candidate method" : "Operator method lens",
109
+ zh: v3?.maturity === "method_model" ? "已验证方法模型" : v3?.maturity === "candidate" ? "候选方法" : "方法透镜",
110
+ ja: v3?.maturity === "method_model" ? "検証済みメソッドモデル" : v3?.maturity === "candidate" ? "候補メソッド" : "メソッド・レンズ",
111
+ ko: v3?.maturity === "method_model" ? "검증된 방법론 모델" : v3?.maturity === "candidate" ? "후보 방법론" : "방법론 렌즈",
108
112
  }),
109
113
  runtime_level: v3?.admission?.level || (pack ? "v2_operator" : "v1_prompt"),
110
114
  admission_level: v3?.admission?.level || (pack ? "operator_lens" : "prompt_lens"),
@@ -182,17 +182,40 @@ function ownerEarnings(series, cik, gaps, proxy) {
182
182
  });
183
183
  }
184
184
 
185
+ /**
186
+ * Total liabilities, tagged where the filer tags it and reconstructed exactly where not.
187
+ *
188
+ * Many filers never tag `Liabilities`; they tag the balance-sheet total and equity. The
189
+ * subtraction is only safe against the INCLUDING-non-controlling-interests equity tag -- with
190
+ * the parent-only tag, minority interest lands inside "liabilities" and nothing says so. When
191
+ * that tag is absent the figure stays missing, which is why this returns null rather than
192
+ * reaching for the nearest number.
193
+ */
194
+ function totalLiabilitiesFor(series, gaps, factId) {
195
+ const direct = alignLatest(series, ["current_assets", "total_liabilities"]);
196
+ if (direct.ok) {
197
+ return { alignment: direct, value: direct.entries.total_liabilities.value, basis: "filed_total_liabilities" };
198
+ }
199
+ const derived = alignLatest(series, ["current_assets", "liabilities_and_equity", "equity_including_nci"]);
200
+ if (!derived.ok) {
201
+ gaps.push(alignmentGap(factId, direct, ["current_assets", "total_liabilities"]));
202
+ return null;
203
+ }
204
+ return {
205
+ alignment: derived,
206
+ value: derived.entries.liabilities_and_equity.value - derived.entries.equity_including_nci.value,
207
+ basis: "balance_sheet_total_less_equity_including_noncontrolling_interests",
208
+ };
209
+ }
210
+
185
211
  /** 2. Graham NCAV: current assets - total liabilities. */
186
212
  function netCurrentAssetValue(series, cik, gaps) {
187
213
  const factId = "financial.net_current_asset_value";
188
- const concepts = ["current_assets", "total_liabilities"];
189
- const alignment = alignLatest(series, concepts);
190
- if (!alignment.ok) {
191
- gaps.push(alignmentGap(factId, alignment, concepts));
192
- return null;
193
- }
214
+ const resolved = totalLiabilitiesFor(series, gaps, factId);
215
+ if (!resolved) return null;
216
+ const alignment = resolved.alignment;
194
217
  const currentAssets = alignment.entries.current_assets.value;
195
- const liabilities = alignment.entries.total_liabilities.value;
218
+ const liabilities = resolved.value;
196
219
  return buildMetric({
197
220
  factId,
198
221
  valueKind: "monetary",
@@ -207,6 +230,9 @@ function netCurrentAssetValue(series, cik, gaps) {
207
230
  assumptions: [
208
231
  "Graham NCAV as filed: current assets less ALL liabilities, with no haircut applied to receivables or inventory",
209
232
  "an unclassified balance sheet (banks, insurers, many REITs) files no AssetsCurrent, which is reported as a gap rather than substituted",
233
+ resolved.basis === "filed_total_liabilities"
234
+ ? "total liabilities taken from the filer's own Liabilities tag"
235
+ : "the filer tags no Liabilities total, so it is the balance-sheet total less equity INCLUDING non-controlling interests, which is exact rather than approximate",
210
236
  ],
211
237
  });
212
238
  }
@@ -465,10 +491,24 @@ function trailingYearOverYear(companyFacts, asOf) {
465
491
  },
466
492
  };
467
493
  }
468
- const latest = fourQuarters(quarters, quarters.length - 1);
469
- const prior = fourQuarters(quarters, quarters.length - 5);
494
+ // Search backwards for the most recent pair of clean four-quarter blocks rather than
495
+ // insisting the last eight filings are them. One restated quarter, one stub period or one
496
+ // duplicated filing at the end used to discard a company's entire revenue history -- INTC and
497
+ // GLW both failed here while holding years of usable quarters behind the ragged edge. Each
498
+ // window is still checked exactly as strictly; only the search moved.
499
+ let latest = null;
500
+ let prior = null;
501
+ let offset = 0;
502
+ for (; offset <= quarters.length - 8; offset += 1) {
503
+ const end = quarters.length - 1 - offset;
504
+ latest = fourQuarters(quarters, end);
505
+ prior = fourQuarters(quarters, end - 4);
506
+ if (latest && prior) break;
507
+ latest = null;
508
+ prior = null;
509
+ }
470
510
  if (!latest || !prior) {
471
- return { ...empty, gap: { code: "period_misaligned", detail: "the eight most recent quarters are not contiguous four-quarter blocks" } };
511
+ return { ...empty, gap: { code: "period_misaligned", detail: `no contiguous pair of four-quarter blocks in the ${quarters.length} tagged quarters` } };
472
512
  }
473
513
  if (!(prior.total > 0)) {
474
514
  return { ...empty, gap: { code: "non_positive_base", detail: `prior-year four-quarter revenue is ${prior.total}` } };
@@ -781,6 +821,17 @@ export function deriveFundamentals({ companyFacts, asOf = null, maintenanceCapex
781
821
  });
782
822
  }
783
823
 
824
+ /**
825
+ * True when a registrant has filed no XBRL at all.
826
+ *
827
+ * SEC's own ticker file maps XOM to ExxonMobil Holdings Corp -- a newly formed entity with zero
828
+ * us-gaap tags -- while the operating history sits under a different CIK. Every metric then
829
+ * reported as missing, individually, and nothing said the registrant itself was empty.
830
+ */
831
+ export function hasNoXbrlHistory(companyFacts) {
832
+ return Object.keys(companyFacts?.facts?.["us-gaap"] || {}).length === 0;
833
+ }
834
+
784
835
  /**
785
836
  * Thin fetching wrapper: resolve the filer, pull Company Facts through the throttled and
786
837
  * User-Agent-bearing sec.mjs client, then hand the JSON to the pure function above.
@@ -8,6 +8,25 @@ import { INDEX_PROXIES, normalizeIndexSymbol } from "./index-aggregate.mjs";
8
8
  import { SECTOR_SPDRS, fetchCrossMarket, fetchSectorDispersion } from "./cross-market.mjs";
9
9
  import { fetchBasketNews } from "./basket-news.mjs";
10
10
  import { gatherInstrumentFacts, LOOK_THROUGH_FACT_IDS } from "./instrument-facts.mjs";
11
+
12
+ /** The index a US company is measured against when a method asks what the market costs. */
13
+ const BROAD_MARKET_INDEX = "^GSPC";
14
+
15
+ /**
16
+ * Facts that describe the market rather than the subject.
17
+ *
18
+ * Everything else the index block produces -- leverage, growth, breadth of a basket -- is about
19
+ * a portfolio the company is not, and forwarding it would answer a different question in the
20
+ * subject's name.
21
+ */
22
+ const MARKET_LEVEL_FACTS = new Set([
23
+ "index.aggregate_pe_ttm",
24
+ "index.aggregate_pe_forward",
25
+ "index.aggregate_earnings_yield",
26
+ "index.dividend_yield",
27
+ "valuation.implied_erp",
28
+ "cycle.valuation_percentile",
29
+ ]);
11
30
  import { fetchOptionsChain } from "./options.mjs";
12
31
  import { screenTicker } from "./screen.mjs";
13
32
  import { resolveIndustry, industryCoverage } from "./industry.mjs";
@@ -95,6 +114,7 @@ export async function gatherGrounding({
95
114
  now = new Date(),
96
115
  language = "English",
97
116
  signal,
117
+ budgetMs = null,
98
118
  } = {}) {
99
119
  const snapshotPolicy = liveSnapshotPolicy(asOf, { now });
100
120
  const gatheredAt = now instanceof Date ? now.toISOString() : new Date(now).toISOString();
@@ -320,6 +340,27 @@ export async function gatherGrounding({
320
340
  out.unavailable.push(`structured financials for ${symbol}: this adapter is not point-in-time versioned; current data was not fetched for a historical cutoff`);
321
341
  }
322
342
 
343
+ // The market's own valuation, for every US subject rather than only for baskets.
344
+ //
345
+ // Three seats require `index.aggregate_earnings_yield` and reported it missing on every
346
+ // single-company run this product has ever done. They were right to ask: the market's
347
+ // aggregate earnings yield is not a property of the subject, it is the yardstick the subject
348
+ // is measured against. Damodaran's implied premium needs it, Asness's Fed-model critique IS
349
+ // about it, and Marks reads it as where the cycle stands. The subject decides whose holdings
350
+ // get read; it does not decide whether the market has a price-earnings ratio.
351
+ if (symbol && !isFundOrIndex(out.instrument) && symbolMarket?.id === "US" && snapshotPolicy.allowed) {
352
+ jobs.push(safely("market valuation", () => gatherInstrumentFacts({
353
+ symbol: BROAD_MARKET_INDEX, instrument: { research_model: "index_aggregate", index_like: true },
354
+ asOf, signal, lookThroughFactIds: [],
355
+ })).then((r) => {
356
+ if (!r.ok) { out.unavailable.push(r.error); return; }
357
+ // Only the market-level block. A company's own leverage and growth come from its filings,
358
+ // and taking them from the index would be silently answering a different question.
359
+ const marketFacts = (r.value.facts || []).filter((fact) => MARKET_LEVEL_FACTS.has(fact.fact_id));
360
+ if (marketFacts.length) out.market_valuation = { ...r.value, facts: marketFacts };
361
+ }));
362
+ }
363
+
323
364
  // A fund or index has no issuer financials, so this is where its evidence comes from
324
365
  // instead: published holdings, index-level valuation and the look-through aggregates that
325
366
  // let an operating-company method run against a basket at all.
@@ -379,7 +420,32 @@ export async function gatherGrounding({
379
420
  out.unavailable.push("industry map: the curated map is not publication-versioned and was excluded from the historical information set");
380
421
  }
381
422
 
382
- await Promise.all(jobs);
423
+ // Return what arrived, not nothing.
424
+ //
425
+ // A caller that raced this whole function against a timer threw away a completed quote, a
426
+ // completed screen and a completed filing set because one slow feed had not landed -- and the
427
+ // analysts downstream, handed an empty object, reported "no ticker was provided". The symbol
428
+ // had been provided; the fetch had not finished. Settling at the budget keeps everything that
429
+ // did arrive and names what did not.
430
+ if (Number.isFinite(budgetMs) && budgetMs > 0) {
431
+ let settled = false;
432
+ const all = Promise.all(jobs).then(() => { settled = true; });
433
+ let timer;
434
+ await Promise.race([
435
+ all,
436
+ new Promise((resolve) => { timer = setTimeout(resolve, budgetMs); }),
437
+ ]);
438
+ clearTimeout(timer);
439
+ if (!settled) {
440
+ out.partial = true;
441
+ out.unavailable.push(
442
+ `grounding budget of ${Math.round(budgetMs)}ms elapsed before every source answered;`
443
+ + " this run carries what arrived by then and names the rest as gaps rather than discarding it",
444
+ );
445
+ }
446
+ } else {
447
+ await Promise.all(jobs);
448
+ }
383
449
 
384
450
  // Coverage across every symbol in play, so a report cannot quietly become US-only.
385
451
  const inPlay = [symbol, ...(out.industry?.participants || []).map((p) => p.symbol)].filter(Boolean);
@@ -26,6 +26,9 @@ const OWNERSHIP_FORMS = new Set(["3", "4", "5", "3/A", "4/A", "5/A"]);
26
26
  /** A registrant with more insiders than this is not a governance question, it is a bad parse. */
27
27
  const MAX_DISTINCT_OWNERS = 60;
28
28
 
29
+ /** Filings read per round. SEC's ~10 req/s guidance is enforced by the client's own throttle. */
30
+ const OWNERSHIP_BATCH = 8;
31
+
29
32
  /** Below this share of the register the aggregate says nothing, so it refuses instead. */
30
33
  export const MIN_OWNER_COVERAGE = 1;
31
34
 
@@ -105,19 +108,27 @@ export async function fetchInsiderOwnership(cik, { sharesOutstanding, asOf = nul
105
108
  const byOwner = new Map();
106
109
  const sources = [];
107
110
  let newestFiling = null;
108
- for (const filing of ownershipFilings) {
109
- if (byOwner.size >= MAX_DISTINCT_OWNERS) break;
110
- let document;
111
- try {
112
- document = await fetchFilingDocument(index.cik, filing.accession, filing.primary_document, { signal });
113
- } catch {
114
- continue;
111
+ // Read in bounded concurrent batches rather than one filing at a time. Sequentially this was
112
+ // up to sixty throttled round trips on the critical path of every company run, which is what
113
+ // pushed grounding past its budget -- and a budget overrun used to discard the whole run's
114
+ // evidence. Newest-first order is preserved across batches, so an owner is still taken from
115
+ // their most recent filing.
116
+ const candidates = ownershipFilings.slice(0, MAX_DISTINCT_OWNERS * 3);
117
+ for (let offset = 0; offset < candidates.length && byOwner.size < MAX_DISTINCT_OWNERS; offset += OWNERSHIP_BATCH) {
118
+ const batch = candidates.slice(offset, offset + OWNERSHIP_BATCH);
119
+ const documents = await Promise.all(batch.map((filing) => (
120
+ fetchFilingDocument(index.cik, filing.accession, filing.primary_document, { signal })
121
+ .then((document) => ({ filing, document }))
122
+ .catch(() => null)
123
+ )));
124
+ for (const entry of documents) {
125
+ if (!entry) continue;
126
+ const parsed = parseOwnershipDocument(entry.document.text);
127
+ if (!parsed || byOwner.has(parsed.owner_cik)) continue;
128
+ byOwner.set(parsed.owner_cik, { ...parsed, filing_date: entry.filing.filing_date, url: entry.document.url });
129
+ sources.push(`sec:ownership:${index.cik}:${entry.filing.accession}`);
130
+ if (!newestFiling || entry.filing.filing_date > newestFiling) newestFiling = entry.filing.filing_date;
115
131
  }
116
- const parsed = parseOwnershipDocument(document.text);
117
- if (!parsed || byOwner.has(parsed.owner_cik)) continue;
118
- byOwner.set(parsed.owner_cik, { ...parsed, filing_date: filing.filing_date, url: document.url });
119
- sources.push(`sec:ownership:${index.cik}:${filing.accession}`);
120
- if (!newestFiling || filing.filing_date > newestFiling) newestFiling = filing.filing_date;
121
132
  }
122
133
  if (byOwner.size < MIN_OWNER_COVERAGE) {
123
134
  return gap(`insider ownership: no Section 16 document for ${index.name || cik} could be parsed`);