From d8d03b5a6901387745d7943fed9a0b334773e136 Mon Sep 17 00:00:00 2001 From: jesse-ux Date: Sun, 27 Sep 2026 01:24:04 +0800 Subject: [PATCH] research: consultation evidence-card inventory and draft Measure the model-visible consultation payload on three public charts, draft per-domain cards, and record the Narayana/pratyantar projection gap as BUG-1054. No runtime behavior change. --- docs/BUG_HISTORY.md | 15 + ...onsult_evidence_card_draft_2026_09_27.json | 601 ++ ...lt_evidence_card_inventory_2026_09_27.json | 6321 +++++++++++++++++ ...nsult_evidence_card_research_2026_09_27.md | 189 + ...idence_card_sample_parents_2026_09_27.json | 294 + ...sult_evidence_card_timings_2026_09_27.json | 35 + ...consult-evidence-card-research-20260927.md | 30 + docs/tasks/README.md | 2 +- scripts/research/consult_evidence_card_lib.py | 811 +++ scripts/research/consult_evidence_card_run.py | 263 + .../research/consult_evidence_card_time.py | 88 + .../research/project_consult_model_context.ts | 107 + tests/test_consult_evidence_card_research.py | 127 + 13 files changed, 8882 insertions(+), 1 deletion(-) create mode 100644 docs/research/consult_evidence_card_draft_2026_09_27.json create mode 100644 docs/research/consult_evidence_card_inventory_2026_09_27.json create mode 100644 docs/research/consult_evidence_card_research_2026_09_27.md create mode 100644 docs/research/consult_evidence_card_sample_parents_2026_09_27.json create mode 100644 docs/research/consult_evidence_card_timings_2026_09_27.json create mode 100644 docs/tasks/PROGRESS-consult-evidence-card-research-20260927.md create mode 100644 scripts/research/consult_evidence_card_lib.py create mode 100644 scripts/research/consult_evidence_card_run.py create mode 100644 scripts/research/consult_evidence_card_time.py create mode 100644 scripts/research/project_consult_model_context.ts create mode 100644 tests/test_consult_evidence_card_research.py diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 936becf8..d018d8f6 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -14186,3 +14186,18 @@ - 相关记录:BUG-612(分段写作再调工具,同一 compose 结构)、BUG-942 / BUG-943 / BUG-944(三通道重做,保留了丢弃主循环正文的结构)、BUG-1051(写回答时钟与结算规则,本单沿用并搬进主循环)、BUG-305、BUG-937(主循环开 thinking,不得用非 `auto` 的 toolChoice)。 - 复发自:无(新缺陷)。 - 修复版本:待提交 + +## BUG-1054 | 咨询投影把当前 Narayana 段和子运日期裁成空 + +- 状态:investigating +- 首次发现 / 最近更新:2026-09-27 / 2026-09-27 +- 影响面:`frontend/src/mastra/consultation-workflow.ts` 的 `toModelOutput` / `projectAllowlistedTree`;普通咨询写答案时看到的 timing 卡 +- 现象:引擎已经算出当前 Narayana 段和 Vimshottari 子运(pratyantar)起止日期,投影给模型的 timing 卡里 `current_dasha` 是空对象,子运日期整段不在。 +- 触发条件:有出生分钟的本命咨询走 `toModelOutput`。2026-09-27 数据卡调研用 3 张公开 AA 盘 × 10 种问法,30/30 都是这个形状。 +- 根因:timing 投影只保留 allowlist 里的键。Narayana 当前段写在 `current_dasha.md` / `ad` / `pd` 下,`md` 不在 allowlist 里,于是对象被留成空。子运日期的键是 `pratyantar_dasha_timeline`,也不在 allowlist 里,整段被丢掉。大运和子运(antardasha)的日期键在 allowlist 里,所以那两段还在。 +- 修复:未修。本单是调研,不改投影。 +- 验证:调研脚本对 30 次投影做了结构化比对:上升、月亮星座与宫位、当前大运起止、D12 落点与引擎一致;Narayana 当前星座和子运起止在卡里是空。见 `docs/research/consult_evidence_card_research_2026_09_27.md`。 +- 防复发:实现单补投影时,要锁住「引擎当前 Narayana 星座和子运起止日期原样出现在模型 timing 卡里」,不能只断言 `narayana_dasha` 键存在。 +- 相关记录:BUG-287(同一条 allowlist 曾经把分盘和审计表整段挡住;这次是嵌套键还没放行,不是「没算」复发) +- 复发自:无 +- 修复版本:无 diff --git a/docs/research/consult_evidence_card_draft_2026_09_27.json b/docs/research/consult_evidence_card_draft_2026_09_27.json new file mode 100644 index 00000000..b7f4a2e8 --- /dev/null +++ b/docs/research/consult_evidence_card_draft_2026_09_27.json @@ -0,0 +1,601 @@ +{ + "card_version": "evidence-card-draft-20260927", + "reference_date": "2026-09-27", + "ayanamsa": "raman", + "node_mode": "mean", + "cards": { + "career": { + "label": "事业", + "vargas": [ + "D10" + ], + "houses": [ + 10 + ], + "arudha": [ + "A10" + ], + "karakas": [ + "AmK" + ], + "planets": [], + "yogas": true, + "transits": true, + "ashtakavarga": false, + "shadbala": true + }, + "marriage": { + "label": "婚恋", + "vargas": [ + "D9" + ], + "houses": [ + 7 + ], + "arudha": [ + "UL", + "A7" + ], + "karakas": [ + "DK" + ], + "planets": [ + "venus", + "jupiter" + ], + "yogas": false, + "transits": true, + "ashtakavarga": false, + "shadbala": false + }, + "wealth": { + "label": "财富", + "vargas": [ + "D2", + "D11" + ], + "houses": [ + 2, + 11, + 9, + 5 + ], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": true, + "transits": false, + "ashtakavarga": true, + "shadbala": true + }, + "health": { + "label": "健康", + "vargas": [ + "D6", + "D8", + "D30" + ], + "houses": [ + 6, + 8 + ], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": false, + "transits": true, + "ashtakavarga": false, + "shadbala": true + }, + "education": { + "label": "学习", + "vargas": [ + "D5", + "D24" + ], + "houses": [ + 5, + 9 + ], + "arudha": [], + "karakas": [], + "planets": [ + "mercury", + "jupiter" + ], + "yogas": false, + "transits": false, + "ashtakavarga": false, + "shadbala": false + }, + "migration": { + "label": "迁居", + "vargas": [ + "D4", + "D12" + ], + "houses": [ + 4, + 12 + ], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": false, + "transits": false, + "ashtakavarga": false, + "shadbala": false + }, + "family": { + "label": "家庭(现路由,父母与子女混在一起)", + "vargas": [ + "D7", + "D12" + ], + "houses": [ + 4, + 5, + 9 + ], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": false, + "transits": false, + "ashtakavarga": false, + "shadbala": false + }, + "parents": { + "label": "父母", + "vargas": [ + "D12" + ], + "houses": [ + 4, + 9 + ], + "arudha": [], + "karakas": [], + "planets": [ + "sun", + "moon" + ], + "yogas": false, + "transits": false, + "ashtakavarga": false, + "shadbala": false, + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D12 for family/ancestral themes", + "references/birth-time-rectification-decision-tree.md section 4: 父母/家族 -> D12" + ] + }, + "children": { + "label": "子女", + "vargas": [ + "D7" + ], + "houses": [ + 5 + ], + "arudha": [], + "karakas": [ + "PK" + ], + "planets": [ + "jupiter" + ], + "yogas": false, + "transits": false, + "ashtakavarga": false, + "shadbala": false, + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D7 for children", + "references/birth-time-rectification-decision-tree.md section 4: 子女/生育 -> D7" + ] + }, + "general": { + "label": "综合", + "vargas": [ + "D9", + "D10", + "D2" + ], + "houses": [ + 1, + 10, + 7, + 2 + ], + "arudha": [ + "A10" + ], + "karakas": [], + "planets": [], + "yogas": true, + "transits": true, + "ashtakavarga": true, + "shadbala": true + } + }, + "source_matrix": { + "domains": [ + { + "domain": "annual", + "registry_required_layers": [ + "D1", + "Annual chart boundary", + "Dasha", + "Transit", + "Tajika candidate" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [ + "Narayana Dasha", + "Vimshottari sub-periods", + "Chara Dasha" + ], + "python_focus_techniques": [ + "Annual chart boundary", + "Dasha", + "Transit", + "Tajika candidate", + "claim boundary" + ], + "card_vargas": [], + "parents_children_split": false + }, + { + "domain": "career", + "registry_required_layers": [ + "D1", + "D10", + "10th house/lord", + "A10", + "AmK", + "Vimshottari", + "Narayana", + "Transit" + ], + "methodology_strict_route": "career-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Arudha / UL / A10", + "Narayana Dasha", + "Chara Dasha" + ], + "python_focus_techniques": [ + "D10", + "Dasha", + "Shadbala", + "Transit", + "Narayana Dasha" + ], + "card_vargas": [ + "D10" + ], + "parents_children_split": false + }, + { + "domain": "children", + "registry_required_layers": [], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [], + "card_vargas": [ + "D7" + ], + "parents_children_split": false + }, + { + "domain": "education", + "registry_required_layers": [ + "D1", + "D24", + "5th/9th houses", + "Mercury/Jupiter", + "Dasha" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D5", + "D24", + "5th house", + "9th house", + "Dasha" + ], + "card_vargas": [ + "D5", + "D24" + ], + "parents_children_split": false + }, + { + "domain": "family", + "registry_required_layers": [ + "D1", + "D7", + "D12", + "4th/5th/9th houses", + "Dasha" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "card_vargas": [ + "D7", + "D12" + ], + "parents_children_split": true + }, + { + "domain": "general", + "registry_required_layers": [ + "D1", + "D9", + "D10", + "D2", + "Dasha", + "Narayana", + "Transit", + "Functional Benefic/Malefic" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D1", + "D9", + "Dasha", + "Yoga", + "Shadbala", + "Ashtakavarga" + ], + "card_vargas": [ + "D9", + "D10", + "D2" + ], + "parents_children_split": false + }, + { + "domain": "health", + "registry_required_layers": [ + "D1", + "D6", + "D8", + "6th/8th houses", + "Dasha", + "non-medical boundary" + ], + "methodology_strict_route": "health-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Shadbala components" + ], + "python_focus_techniques": [ + "D6", + "D8", + "D30", + "Dasha", + "Narayana Dasha", + "Shadbala", + "Transit", + "Functional Benefic/Malefic" + ], + "card_vargas": [ + "D6", + "D8", + "D30" + ], + "parents_children_split": false + }, + { + "domain": "marriage", + "registry_required_layers": [ + "D1", + "D9", + "7th house/lord", + "Venus/Jupiter", + "DK", + "UL", + "A7", + "Vimshottari", + "Narayana", + "Transit" + ], + "methodology_strict_route": "relationship-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Arudha / UL / A10" + ], + "python_focus_techniques": [ + "D9", + "UL Upapada", + "Dasha", + "Nakshatra", + "Vivah Saham" + ], + "card_vargas": [ + "D9" + ], + "parents_children_split": false + }, + { + "domain": "migration", + "registry_required_layers": [ + "D1", + "D4", + "D12", + "4th/12th houses", + "Dasha", + "Narayana" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D4", + "D12", + "12th house", + "Dasha", + "Narayana Dasha" + ], + "card_vargas": [ + "D4", + "D12" + ], + "parents_children_split": false + }, + { + "domain": "parents", + "registry_required_layers": [], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [], + "card_vargas": [ + "D12" + ], + "parents_children_split": false + }, + { + "domain": "timing", + "registry_required_layers": [ + "Vimshottari", + "Narayana", + "Transit", + "Varga", + "negative holdout gate" + ], + "methodology_strict_route": "event-timing-strict", + "ts_must_use_layers": [ + "Narayana Dasha", + "Vimshottari sub-periods", + "Transits / Sade Sati", + "Chara Dasha" + ], + "python_focus_techniques": [ + "Dasha", + "Transit", + "Double Transit", + "Gochara" + ], + "card_vargas": [], + "parents_children_split": false + }, + { + "domain": "wealth", + "registry_required_layers": [ + "D1", + "D2", + "D11", + "2nd/11th/9th/5th houses", + "Wealth Yogas", + "Ashtakavarga", + "Dasha" + ], + "methodology_strict_route": "finance-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Ashtakavarga" + ], + "python_focus_techniques": [ + "D2", + "D11", + "Dasha", + "Shadbala", + "Ashtakavarga" + ], + "card_vargas": [ + "D2", + "D11" + ], + "parents_children_split": false + } + ], + "skill_citations": { + "d12_family": "references/strict-workflow-router.md: D12 for family/ancestral themes", + "d7_children": "references/strict-workflow-router.md: D7 for children", + "decision_tree_parents": "references/birth-time-rectification-decision-tree.md: 父母/家族 -> D12", + "decision_tree_children": "references/birth-time-rectification-decision-tree.md: 子女/生育 -> D7" + } + }, + "telemetry": { + "stores": "numbers, enums, and field names only", + "does_not_store": [ + "question text", + "answer text", + "birth date", + "birth time", + "birth place", + "name", + "email", + "user id", + "session id", + "matched substring" + ], + "fields": [ + { + "name": "domain", + "type": "enum", + "values": [ + "career", + "marriage", + "wealth", + "health", + "education", + "migration", + "family", + "general", + "parents", + "children" + ] + }, + { + "name": "card_version", + "type": "enum", + "values": [ + "evidence-card-draft-20260927" + ] + }, + { + "name": "card_chars", + "type": "int" + }, + { + "name": "card_token_estimate", + "type": "int" + }, + { + "name": "cited_field_ids", + "type": "enum[]", + "note": "ids from the card schema, not free text" + }, + { + "name": "feedback", + "type": "enum", + "values": [ + "up", + "down", + "none" + ] + } + ], + "citation_method": { + "rule": "A field is cited when its scalar value appears in the answer and the value is an ISO date, a degree token, or a compound planet-in-sign phrase of at least 8 characters. Bare planet or sign names are not counted.", + "false_positive": "A date or degree that also appears in the question, or a repeated stock phrase, can be counted without the model using that field.", + "false_negative": "A paraphrase that names the period without copying the date is not counted.", + "stored": "Only the field id. The matched text is discarded." + }, + "aggregates": [ + "count of answers by domain and card_version", + "fields whose cited rate stays under 5 percent after 30 answers in that domain", + "down rate by domain and card_version" + ] + } +} \ No newline at end of file diff --git a/docs/research/consult_evidence_card_inventory_2026_09_27.json b/docs/research/consult_evidence_card_inventory_2026_09_27.json new file mode 100644 index 00000000..9f5633b3 --- /dev/null +++ b/docs/research/consult_evidence_card_inventory_2026_09_27.json @@ -0,0 +1,6321 @@ +{ + "baseline": "76924e3362c0a47d9d8de896c448c66055826f70", + "reference_date": "2026-09-27", + "ayanamsa": "raman", + "node_mode": "mean", + "pythonhashseed": "0", + "external_vedastro": "not_called", + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer.", + "charts": [ + { + "id": "steve_jobs", + "label": "Steve Jobs", + "source": "references/real_case_calibration/minute_rectification_development_v1.json", + "case_id": "steve_jobs_1955_development", + "rodden_rating": "AA" + }, + { + "id": "barack_obama", + "label": "Barack Obama", + "source": "references/real_case_calibration/minute_rectification_holdout_v4.json", + "case_id": "barack_obama_1961_aa_v4_holdout", + "rodden_rating": "AA" + }, + { + "id": "elizabeth_taylor", + "label": "Elizabeth Taylor", + "source": "references/real_case_calibration/minute_rectification_holdout_v4.json", + "case_id": "elizabeth_taylor_1932_aa_v4_holdout", + "rodden_rating": "AA" + } + ], + "source_matrix": { + "domains": [ + { + "domain": "annual", + "registry_required_layers": [ + "D1", + "Annual chart boundary", + "Dasha", + "Transit", + "Tajika candidate" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [ + "Narayana Dasha", + "Vimshottari sub-periods", + "Chara Dasha" + ], + "python_focus_techniques": [ + "Annual chart boundary", + "Dasha", + "Transit", + "Tajika candidate", + "claim boundary" + ], + "card_vargas": [], + "parents_children_split": false + }, + { + "domain": "career", + "registry_required_layers": [ + "D1", + "D10", + "10th house/lord", + "A10", + "AmK", + "Vimshottari", + "Narayana", + "Transit" + ], + "methodology_strict_route": "career-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Arudha / UL / A10", + "Narayana Dasha", + "Chara Dasha" + ], + "python_focus_techniques": [ + "D10", + "Dasha", + "Shadbala", + "Transit", + "Narayana Dasha" + ], + "card_vargas": [ + "D10" + ], + "parents_children_split": false + }, + { + "domain": "children", + "registry_required_layers": [], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [], + "card_vargas": [ + "D7" + ], + "parents_children_split": false + }, + { + "domain": "education", + "registry_required_layers": [ + "D1", + "D24", + "5th/9th houses", + "Mercury/Jupiter", + "Dasha" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D5", + "D24", + "5th house", + "9th house", + "Dasha" + ], + "card_vargas": [ + "D5", + "D24" + ], + "parents_children_split": false + }, + { + "domain": "family", + "registry_required_layers": [ + "D1", + "D7", + "D12", + "4th/5th/9th houses", + "Dasha" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "card_vargas": [ + "D7", + "D12" + ], + "parents_children_split": true + }, + { + "domain": "general", + "registry_required_layers": [ + "D1", + "D9", + "D10", + "D2", + "Dasha", + "Narayana", + "Transit", + "Functional Benefic/Malefic" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D1", + "D9", + "Dasha", + "Yoga", + "Shadbala", + "Ashtakavarga" + ], + "card_vargas": [ + "D9", + "D10", + "D2" + ], + "parents_children_split": false + }, + { + "domain": "health", + "registry_required_layers": [ + "D1", + "D6", + "D8", + "6th/8th houses", + "Dasha", + "non-medical boundary" + ], + "methodology_strict_route": "health-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Shadbala components" + ], + "python_focus_techniques": [ + "D6", + "D8", + "D30", + "Dasha", + "Narayana Dasha", + "Shadbala", + "Transit", + "Functional Benefic/Malefic" + ], + "card_vargas": [ + "D6", + "D8", + "D30" + ], + "parents_children_split": false + }, + { + "domain": "marriage", + "registry_required_layers": [ + "D1", + "D9", + "7th house/lord", + "Venus/Jupiter", + "DK", + "UL", + "A7", + "Vimshottari", + "Narayana", + "Transit" + ], + "methodology_strict_route": "relationship-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Arudha / UL / A10" + ], + "python_focus_techniques": [ + "D9", + "UL Upapada", + "Dasha", + "Nakshatra", + "Vivah Saham" + ], + "card_vargas": [ + "D9" + ], + "parents_children_split": false + }, + { + "domain": "migration", + "registry_required_layers": [ + "D1", + "D4", + "D12", + "4th/12th houses", + "Dasha", + "Narayana" + ], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [ + "D4", + "D12", + "12th house", + "Dasha", + "Narayana Dasha" + ], + "card_vargas": [ + "D4", + "D12" + ], + "parents_children_split": false + }, + { + "domain": "parents", + "registry_required_layers": [], + "methodology_strict_route": null, + "ts_must_use_layers": [], + "python_focus_techniques": [], + "card_vargas": [ + "D12" + ], + "parents_children_split": false + }, + { + "domain": "timing", + "registry_required_layers": [ + "Vimshottari", + "Narayana", + "Transit", + "Varga", + "negative holdout gate" + ], + "methodology_strict_route": "event-timing-strict", + "ts_must_use_layers": [ + "Narayana Dasha", + "Vimshottari sub-periods", + "Transits / Sade Sati", + "Chara Dasha" + ], + "python_focus_techniques": [ + "Dasha", + "Transit", + "Double Transit", + "Gochara" + ], + "card_vargas": [], + "parents_children_split": false + }, + { + "domain": "wealth", + "registry_required_layers": [ + "D1", + "D2", + "D11", + "2nd/11th/9th/5th houses", + "Wealth Yogas", + "Ashtakavarga", + "Dasha" + ], + "methodology_strict_route": "finance-timing-strict", + "ts_must_use_layers": [ + "Formal Vargas D1–D60", + "Ashtakavarga" + ], + "python_focus_techniques": [ + "D2", + "D11", + "Dasha", + "Shadbala", + "Ashtakavarga" + ], + "card_vargas": [ + "D2", + "D11" + ], + "parents_children_split": false + } + ], + "skill_citations": { + "d12_family": "references/strict-workflow-router.md: D12 for family/ancestral themes", + "d7_children": "references/strict-workflow-router.md: D7 for children", + "decision_tree_parents": "references/birth-time-rectification-decision-tree.md: 父母/家族 -> D12", + "decision_tree_children": "references/birth-time-rectification-decision-tree.md: 子女/生育 -> D7" + } + }, + "runs": [ + { + "id": "steve_jobs__career", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "career", + "domain": "career", + "wall_seconds": 5.539, + "workflow_chars": 411737, + "route": "career", + "focus_techniques": [ + "D10", + "Dasha", + "Shadbala", + "Transit", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__career", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 7313, + "model_chars": 142680 + }, + "categories": { + "categories": { + "core": 47808, + "status": 16082, + "not_applicable": 1972, + "research": 43926, + "western": 32892 + }, + "total_chars": 142680, + "category_sum": 142680, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 142680, + "token_estimate": 40766, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67640, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3971, + "token_estimate": 1135, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10" + ], + "expected_vargas": [ + "D10" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits", + "shadbala", + "yogas" + ], + "sample_card": { + "card_id": "career", + "label": "事业", + "question": "未来一年,事业和收入该关注什么?", + "route": "career", + "base": { + "ascendant": { + "degree": 0.51, + "degree_in_sign": 0.51, + "lon": 150.5069, + "sign": "Virgo", + "sign_idx": 5 + }, + "houses": { + "1": { + "sign": "Virgo", + "sign_idx": 5 + }, + "2": { + "sign": "Libra", + "sign_idx": 6 + }, + "3": { + "sign": "Scorpio", + "sign_idx": 7 + }, + "4": { + "sign": "Sagittarius", + "sign_idx": 8 + }, + "5": { + "sign": "Capricorn", + "sign_idx": 9 + }, + "6": { + "sign": "Aquarius", + "sign_idx": 10 + }, + "7": { + "sign": "Pisces", + "sign_idx": 11 + }, + "8": { + "sign": "Aries", + "sign_idx": 0 + }, + "9": { + "sign": "Taurus", + "sign_idx": 1 + }, + "10": { + "sign": "Gemini", + "sign_idx": 2 + }, + "11": { + "sign": "Cancer", + "sign_idx": 3 + }, + "12": { + "sign": "Leo", + "sign_idx": 4 + } + }, + "planet_placements": { + "Jupiter": { + "sign": "Gemini", + "house": 10 + }, + "Ketu": { + "sign": "Gemini", + "house": 10 + }, + "Mars": { + "sign": "Aries", + "house": 8 + }, + "Mercury": { + "sign": "Capricorn", + "house": 5 + }, + "Moon": { + "sign": "Pisces", + "house": 7 + }, + "Rahu": { + "sign": "Sagittarius", + "house": 4 + }, + "Saturn": { + "sign": "Libra", + "house": 2 + }, + "Sun": { + "sign": "Aquarius", + "house": 6 + }, + "Venus": { + "sign": "Sagittarius", + "house": 4 + } + }, + "functional_benefic_malefic": { + "status": "used", + "ascendant": "Virgo", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Mars", + "Moon", + "Sun" + ], + "functional_neutrals": [ + "Jupiter" + ], + "yogakarakas": [ + "Mercury" + ], + "owned_houses": { + "Jupiter": [ + 4, + 7 + ], + "Mars": [ + 3, + 8 + ], + "Mercury": [ + 1, + 10 + ], + "Moon": [ + 11 + ], + "Saturn": [ + 5, + 6 + ], + "Sun": [ + 12 + ], + "Venus": [ + 2, + 9 + ] + }, + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "source": "strict_functional_benefic_malefic_v1" + }, + "vimshottari": { + "status": "ready", + "source": "chart.dasha.periods + dasha_analyzer.build_antardasha", + "method": "vimshottari_antardasha_proportional", + "current": { + "mahadasha": { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2041-02-24" + }, + "antardasha": { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + } + }, + "next": { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + "boundaries": [ + { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2025-11-07" + }, + { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + }, + { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + { + "lord": "Mercury", + "start": "2031-02-06", + "end": "2033-08-25" + }, + { + "lord": "Ketu", + "start": "2033-08-25", + "end": "2034-09-13" + }, + { + "lord": "Venus", + "start": "2034-09-13", + "end": "2037-09-12" + }, + { + "lord": "Sun", + "start": "2037-09-12", + "end": "2038-08-07" + }, + { + "lord": "Moon", + "start": "2038-08-07", + "end": "2040-02-06" + }, + { + "lord": "Mars", + "start": "2040-02-06", + "end": "2041-02-24" + } + ], + "boundary_count": 9, + "summary": "当前 Rahu 大运下的小运为 Jupiter,边界 2025-11-07 至 2028-04-01。更细的 Pratyantardasha 与行运触发不在本层计算范围内。" + }, + "narayana_dasha": { + "current_dasha": {} + } + }, + "domain": { + "vargas": { + "D10": { + "lagna": "Taurus", + "planets": { + "Sun": "Gemini", + "Moon": "Aries", + "Mars": "Gemini", + "Mercury": "Aries", + "Jupiter": "Pisces", + "Venus": "Virgo", + "Saturn": "Cancer", + "Rahu": "Pisces", + "Ketu": "Virgo" + }, + "name": "Dasamsa", + "meaning": "事业" + } + }, + "houses": { + "10": { + "sign": "Gemini", + "sign_idx": 2 + } + }, + "planets": {}, + "arudha": {}, + "karakas": {}, + "yogas": { + "status": "executed", + "count": 6, + "yogas": [ + { + "name": "Sunaphaa Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + }, + { + "name": "Anaphaa Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + }, + { + "name": "Duradhara Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + }, + { + "name": "Vosi Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + }, + { + "name": "Ubhayachara Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + }, + { + "name": "Naukaa Yoga", + "claim_boundary": "governed_support_only_candidate_ready" + } + ] + }, + "transits": { + "status": "executed", + "sade_sati": { + "active": true, + "phase": "peak", + "phase_name": "高峰期(Peak Phase)", + "moon_sign": "Pisces", + "saturn_sign": "Pisces", + "intensity": "高潮" + }, + "triggers": [ + { + "date": "2026-10-26", + "planet": "Saturn", + "target": "Moon", + "kind": "transit_contact", + "orb": 0.93 + } + ], + "trigger_count": 1, + "search_period": { + "start": "2026-09-27", + "end": "2026-12-26" + }, + "boundary": "observation windows, not guaranteed events; empty triggers means none in the searched window, not that transits were skipped" + }, + "ashtakavarga": null, + "shadbala": { + "Jupiter": {}, + "Mars": {}, + "Mercury": {}, + "Moon": {}, + "Saturn": {}, + "Sun": {}, + "Venus": {} + } + }, + "gaps": [], + "basis": [] + } + }, + { + "id": "steve_jobs__marriage", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "marriage", + "domain": "marriage", + "wall_seconds": 2.612, + "workflow_chars": 407665, + "route": "marriage", + "focus_techniques": [ + "D9", + "UL Upapada", + "Dasha", + "Nakshatra", + "Vivah Saham" + ], + "success": true, + "projection": { + "id": "steve_jobs__marriage", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 9708, + "model_chars": 143603 + }, + "categories": { + "categories": { + "core": 46936, + "status": 17877, + "not_applicable": 1972, + "research": 43926, + "western": 32892 + }, + "total_chars": 143603, + "category_sum": 143603, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 143603, + "token_estimate": 41029, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66903, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3832, + "token_estimate": 1095, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D9" + ], + "expected_vargas": [ + "D9" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits" + ], + "sample_card": null + }, + { + "id": "steve_jobs__wealth", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "wealth", + "domain": "wealth", + "wall_seconds": 2.581, + "workflow_chars": 410941, + "route": "wealth", + "focus_techniques": [ + "D2", + "D11", + "Dasha", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "steve_jobs__wealth", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 6841, + "model_chars": 139506 + }, + "categories": { + "categories": { + "core": 44598, + "status": 15502, + "not_applicable": 2588, + "research": 43926, + "western": 32892 + }, + "total_chars": 139506, + "category_sum": 139506, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 139506, + "token_estimate": 39859, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66289, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3766, + "token_estimate": 1076, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D11", + "D2" + ], + "expected_vargas": [ + "D2", + "D11" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "steve_jobs__health", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "health", + "domain": "health", + "wall_seconds": 2.604, + "workflow_chars": 431486, + "route": "health", + "focus_techniques": [ + "D6", + "D8", + "D30", + "Dasha", + "Narayana Dasha", + "Shadbala", + "Transit", + "Functional Benefic/Malefic" + ], + "success": true, + "projection": { + "id": "steve_jobs__health", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 2, + "methodology_chars": 3772, + "model_chars": 138895 + }, + "categories": { + "categories": { + "core": 45256, + "status": 14233, + "not_applicable": 2588, + "research": 43926, + "western": 32892 + }, + "total_chars": 138895, + "category_sum": 138895, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 138895, + "token_estimate": 39684, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67518, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3974, + "token_estimate": 1135, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D30", + "D6", + "D8" + ], + "expected_vargas": [ + "D6", + "D8", + "D30" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "transits", + "shadbala" + ], + "sample_card": null + }, + { + "id": "steve_jobs__education", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "education", + "domain": "education", + "wall_seconds": 2.616, + "workflow_chars": 429370, + "route": "education", + "focus_techniques": [ + "D5", + "D24", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__education", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 135306 + }, + "categories": { + "categories": { + "core": 43392, + "status": 12485, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 135306, + "category_sum": 135306, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135306, + "token_estimate": 38659, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66596, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3637, + "token_estimate": 1039, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D24", + "D5" + ], + "expected_vargas": [ + "D5", + "D24" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "steve_jobs__migration", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "migration", + "domain": "migration", + "wall_seconds": 2.58, + "workflow_chars": 429455, + "route": "migration", + "focus_techniques": [ + "D4", + "D12", + "12th house", + "Dasha", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__migration", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 135386 + }, + "categories": { + "categories": { + "core": 43392, + "status": 12565, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 135386, + "category_sum": 135386, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135386, + "token_estimate": 38682, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66636, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3168, + "token_estimate": 905, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D4" + ], + "expected_vargas": [ + "D4", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "steve_jobs__family", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "family", + "domain": "family", + "wall_seconds": 2.588, + "workflow_chars": 413339, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__family", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133308 + }, + "categories": { + "categories": { + "core": 42757, + "status": 11122, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 133308, + "category_sum": 133308, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133308, + "token_estimate": 38088, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65600, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3228, + "token_estimate": 922, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D7" + ], + "expected_vargas": [ + "D7", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "steve_jobs__general", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "general", + "domain": "general", + "wall_seconds": 2.599, + "workflow_chars": 429753, + "route": "general", + "focus_techniques": [ + "D1", + "D9", + "Dasha", + "Yoga", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "steve_jobs__general", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2022, + "model_chars": 135284 + }, + "categories": { + "categories": { + "core": 43372, + "status": 12483, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 135284, + "category_sum": 135284, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135284, + "token_estimate": 38653, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66587, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 5737, + "token_estimate": 1639, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10", + "D2", + "D9" + ], + "expected_vargas": [ + "D9", + "D10", + "D2" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "transits", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "steve_jobs__parents", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "parents", + "domain": "family", + "wall_seconds": 2.611, + "workflow_chars": 413258, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__parents", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133290 + }, + "categories": { + "categories": { + "core": 42739, + "status": 11122, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 133290, + "category_sum": 133290, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133290, + "token_estimate": 38083, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65591, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3576, + "token_estimate": 1022, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12" + ], + "expected_vargas": [ + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": { + "card_id": "parents", + "label": "父母", + "question": "我和父母关系如何", + "route": "family", + "base": { + "ascendant": { + "degree": 0.51, + "degree_in_sign": 0.51, + "lon": 150.5069, + "sign": "Virgo", + "sign_idx": 5 + }, + "houses": { + "1": { + "sign": "Virgo", + "sign_idx": 5 + }, + "2": { + "sign": "Libra", + "sign_idx": 6 + }, + "3": { + "sign": "Scorpio", + "sign_idx": 7 + }, + "4": { + "sign": "Sagittarius", + "sign_idx": 8 + }, + "5": { + "sign": "Capricorn", + "sign_idx": 9 + }, + "6": { + "sign": "Aquarius", + "sign_idx": 10 + }, + "7": { + "sign": "Pisces", + "sign_idx": 11 + }, + "8": { + "sign": "Aries", + "sign_idx": 0 + }, + "9": { + "sign": "Taurus", + "sign_idx": 1 + }, + "10": { + "sign": "Gemini", + "sign_idx": 2 + }, + "11": { + "sign": "Cancer", + "sign_idx": 3 + }, + "12": { + "sign": "Leo", + "sign_idx": 4 + } + }, + "planet_placements": { + "Jupiter": { + "sign": "Gemini", + "house": 10 + }, + "Ketu": { + "sign": "Gemini", + "house": 10 + }, + "Mars": { + "sign": "Aries", + "house": 8 + }, + "Mercury": { + "sign": "Capricorn", + "house": 5 + }, + "Moon": { + "sign": "Pisces", + "house": 7 + }, + "Rahu": { + "sign": "Sagittarius", + "house": 4 + }, + "Saturn": { + "sign": "Libra", + "house": 2 + }, + "Sun": { + "sign": "Aquarius", + "house": 6 + }, + "Venus": { + "sign": "Sagittarius", + "house": 4 + } + }, + "functional_benefic_malefic": { + "status": "used", + "ascendant": "Virgo", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Mars", + "Moon", + "Sun" + ], + "functional_neutrals": [ + "Jupiter" + ], + "yogakarakas": [ + "Mercury" + ], + "owned_houses": { + "Jupiter": [ + 4, + 7 + ], + "Mars": [ + 3, + 8 + ], + "Mercury": [ + 1, + 10 + ], + "Moon": [ + 11 + ], + "Saturn": [ + 5, + 6 + ], + "Sun": [ + 12 + ], + "Venus": [ + 2, + 9 + ] + }, + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "source": "strict_functional_benefic_malefic_v1" + }, + "vimshottari": { + "status": "ready", + "source": "chart.dasha.periods + dasha_analyzer.build_antardasha", + "method": "vimshottari_antardasha_proportional", + "current": { + "mahadasha": { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2041-02-24" + }, + "antardasha": { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + } + }, + "next": { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + "boundaries": [ + { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2025-11-07" + }, + { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + }, + { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + { + "lord": "Mercury", + "start": "2031-02-06", + "end": "2033-08-25" + }, + { + "lord": "Ketu", + "start": "2033-08-25", + "end": "2034-09-13" + }, + { + "lord": "Venus", + "start": "2034-09-13", + "end": "2037-09-12" + }, + { + "lord": "Sun", + "start": "2037-09-12", + "end": "2038-08-07" + }, + { + "lord": "Moon", + "start": "2038-08-07", + "end": "2040-02-06" + }, + { + "lord": "Mars", + "start": "2040-02-06", + "end": "2041-02-24" + } + ], + "boundary_count": 9, + "summary": "当前 Rahu 大运下的小运为 Jupiter,边界 2025-11-07 至 2028-04-01。更细的 Pratyantardasha 与行运触发不在本层计算范围内。" + }, + "narayana_dasha": { + "current_dasha": {} + } + }, + "domain": { + "vargas": { + "D12": { + "lagna": "Virgo", + "planets": { + "Sun": "Cancer", + "Moon": "Virgo", + "Mars": "Gemini", + "Mercury": "Libra", + "Jupiter": "Taurus", + "Venus": "Scorpio", + "Saturn": "Virgo", + "Rahu": "Aries", + "Ketu": "Libra" + }, + "name": "Dwadasamsa", + "meaning": "父母" + } + }, + "houses": { + "4": { + "sign": "Sagittarius", + "sign_idx": 8 + }, + "9": { + "sign": "Taurus", + "sign_idx": 1 + } + }, + "planets": { + "Sun": { + "degree": 13.9638, + "degree_in_sign": 13.9638, + "degree_raw": 313.96378728533347, + "house": 6, + "lon": 313.96378728533347, + "nakshatra": "Shatabhisha", + "retrograde": false, + "sign": "Aquarius", + "sign_idx": 10, + "status": "极敌(Great Enemy)" + }, + "Moon": { + "degree": 15.9628, + "degree_in_sign": 15.9628, + "degree_raw": 345.9628222838024, + "house": 7, + "lon": 345.9628222838024, + "nakshatra": "Uttara Bhadrapada", + "retrograde": false, + "sign": "Pisces", + "sign_idx": 11, + "status": "入友(Friendly Sign)" + } + }, + "arudha": {}, + "karakas": {}, + "yogas": null, + "transits": null, + "ashtakavarga": null, + "shadbala": null + }, + "gaps": [], + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D12 for family/ancestral themes", + "references/birth-time-rectification-decision-tree.md section 4: 父母/家族 -> D12" + ] + } + }, + { + "id": "steve_jobs__children", + "chart_id": "steve_jobs", + "chart_label": "Steve Jobs", + "question_id": "children", + "domain": "family", + "wall_seconds": 2.591, + "workflow_chars": 413267, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "steve_jobs__children", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133292 + }, + "categories": { + "categories": { + "core": 42741, + "status": 11122, + "not_applicable": 2588, + "research": 43949, + "western": 32892 + }, + "total_chars": 133292, + "category_sum": 133292, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133292, + "token_estimate": 38083, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65592, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3310, + "token_estimate": 946, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D7" + ], + "expected_vargas": [ + "D7" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + }, + "moon_sign": { + "status": "match", + "expected": "Pisces", + "actual": "Pisces" + }, + "moon_house": { + "status": "match", + "expected": 7, + "actual": 7 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Rahu", + "actual": "Rahu" + }, + "vimshottari_start": { + "status": "match", + "expected": "2023-02-25", + "actual": "2023-02-25" + }, + "vimshottari_end": { + "status": "match", + "expected": "2041-02-24", + "actual": "2041-02-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-11-07", + "actual": "2025-11-07" + }, + "antardasha_end": { + "status": "match", + "expected": "2028-04-01", + "actual": "2028-04-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-07-20", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-11-21", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Leo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas" + ], + "sample_card": null + }, + { + "id": "barack_obama__career", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "career", + "domain": "career", + "wall_seconds": 2.813, + "workflow_chars": 412761, + "route": "career", + "focus_techniques": [ + "D10", + "Dasha", + "Shadbala", + "Transit", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__career", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 7313, + "model_chars": 142682 + }, + "categories": { + "categories": { + "core": 47688, + "status": 16044, + "not_applicable": 1972, + "research": 44050, + "western": 32928 + }, + "total_chars": 142682, + "category_sum": 142682, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 142682, + "token_estimate": 40766, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67641, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3984, + "token_estimate": 1138, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10" + ], + "expected_vargas": [ + "D10" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "barack_obama__marriage", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "marriage", + "domain": "marriage", + "wall_seconds": 2.603, + "workflow_chars": 406988, + "route": "marriage", + "focus_techniques": [ + "D9", + "UL Upapada", + "Dasha", + "Nakshatra", + "Vivah Saham" + ], + "success": true, + "projection": { + "id": "barack_obama__marriage", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 9708, + "model_chars": 142541 + }, + "categories": { + "categories": { + "core": 45742, + "status": 17849, + "not_applicable": 1972, + "research": 44050, + "western": 32928 + }, + "total_chars": 142541, + "category_sum": 142541, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 142541, + "token_estimate": 40726, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66372, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3724, + "token_estimate": 1064, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D9" + ], + "expected_vargas": [ + "D9" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits" + ], + "sample_card": null + }, + { + "id": "barack_obama__wealth", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "wealth", + "domain": "wealth", + "wall_seconds": 2.623, + "workflow_chars": 411563, + "route": "wealth", + "focus_techniques": [ + "D2", + "D11", + "Dasha", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "barack_obama__wealth", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 6841, + "model_chars": 139490 + }, + "categories": { + "categories": { + "core": 44460, + "status": 15464, + "not_applicable": 2588, + "research": 44050, + "western": 32928 + }, + "total_chars": 139490, + "category_sum": 139490, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 139490, + "token_estimate": 39854, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66281, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3853, + "token_estimate": 1101, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D11", + "D2" + ], + "expected_vargas": [ + "D2", + "D11" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "barack_obama__health", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "health", + "domain": "health", + "wall_seconds": 2.636, + "workflow_chars": 432490, + "route": "health", + "focus_techniques": [ + "D6", + "D8", + "D30", + "Dasha", + "Narayana Dasha", + "Shadbala", + "Transit", + "Functional Benefic/Malefic" + ], + "success": true, + "projection": { + "id": "barack_obama__health", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 2, + "methodology_chars": 3772, + "model_chars": 139179 + }, + "categories": { + "categories": { + "core": 45436, + "status": 14177, + "not_applicable": 2588, + "research": 44050, + "western": 32928 + }, + "total_chars": 139179, + "category_sum": 139179, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 139179, + "token_estimate": 39765, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67660, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3852, + "token_estimate": 1101, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D30", + "D6", + "D8" + ], + "expected_vargas": [ + "D6", + "D8", + "D30" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "transits", + "shadbala" + ], + "sample_card": null + }, + { + "id": "barack_obama__education", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "education", + "domain": "education", + "wall_seconds": 2.598, + "workflow_chars": 430364, + "route": "education", + "focus_techniques": [ + "D5", + "D24", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__education", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 135570 + }, + "categories": { + "categories": { + "core": 43552, + "status": 12429, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 135570, + "category_sum": 135570, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135570, + "token_estimate": 38734, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66728, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3631, + "token_estimate": 1037, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D24", + "D5" + ], + "expected_vargas": [ + "D5", + "D24" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "barack_obama__migration", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "migration", + "domain": "migration", + "wall_seconds": 2.568, + "workflow_chars": 430449, + "route": "migration", + "focus_techniques": [ + "D4", + "D12", + "12th house", + "Dasha", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__migration", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 135650 + }, + "categories": { + "categories": { + "core": 43552, + "status": 12509, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 135650, + "category_sum": 135650, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135650, + "token_estimate": 38757, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66768, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3181, + "token_estimate": 909, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D4" + ], + "expected_vargas": [ + "D4", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "barack_obama__family", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "family", + "domain": "family", + "wall_seconds": 2.609, + "workflow_chars": 413849, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__family", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133222 + }, + "categories": { + "categories": { + "core": 42543, + "status": 11090, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 133222, + "category_sum": 133222, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133222, + "token_estimate": 38063, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65557, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3214, + "token_estimate": 918, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D7" + ], + "expected_vargas": [ + "D7", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "barack_obama__general", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "general", + "domain": "general", + "wall_seconds": 2.572, + "workflow_chars": 430747, + "route": "general", + "focus_techniques": [ + "D1", + "D9", + "Dasha", + "Yoga", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "barack_obama__general", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2022, + "model_chars": 135548 + }, + "categories": { + "categories": { + "core": 43532, + "status": 12427, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 135548, + "category_sum": 135548, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 135548, + "token_estimate": 38728, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66719, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 5863, + "token_estimate": 1675, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10", + "D2", + "D9" + ], + "expected_vargas": [ + "D9", + "D10", + "D2" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "transits", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "barack_obama__parents", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "parents", + "domain": "family", + "wall_seconds": 2.58, + "workflow_chars": 413768, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__parents", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133204 + }, + "categories": { + "categories": { + "core": 42525, + "status": 11090, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 133204, + "category_sum": 133204, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133204, + "token_estimate": 38058, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65548, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3554, + "token_estimate": 1015, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12" + ], + "expected_vargas": [ + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "d12_moon": { + "status": "match", + "expected": "Virgo", + "actual": "Virgo" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "barack_obama__children", + "chart_id": "barack_obama", + "chart_label": "Barack Obama", + "question_id": "children", + "domain": "family", + "wall_seconds": 2.586, + "workflow_chars": 413777, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "barack_obama__children", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 133206 + }, + "categories": { + "categories": { + "core": 42527, + "status": 11090, + "not_applicable": 2588, + "research": 44073, + "western": 32928 + }, + "total_chars": 133206, + "category_sum": 133206, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 133206, + "token_estimate": 38059, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65549, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3305, + "token_estimate": 944, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D7" + ], + "expected_vargas": [ + "D7" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Capricorn", + "actual": "Capricorn" + }, + "moon_sign": { + "status": "match", + "expected": "Taurus", + "actual": "Taurus" + }, + "moon_house": { + "status": "match", + "expected": 5, + "actual": 5 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Saturn", + "actual": "Saturn" + }, + "vimshottari_start": { + "status": "match", + "expected": "2011-06-24", + "actual": "2011-06-24" + }, + "vimshottari_end": { + "status": "match", + "expected": "2030-06-24", + "actual": "2030-06-24" + }, + "antardasha_start": { + "status": "match", + "expected": "2025-02-03", + "actual": "2025-02-03" + }, + "antardasha_end": { + "status": "match", + "expected": "2027-12-11", + "actual": "2027-12-11" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-05-08", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-10-03", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Virgo", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Scorpio", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Virgo", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__career", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "career", + "domain": "career", + "wall_seconds": 3.421, + "workflow_chars": 409250, + "route": "career", + "focus_techniques": [ + "D10", + "Dasha", + "Shadbala", + "Transit", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__career", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 7313, + "model_chars": 142088 + }, + "categories": { + "categories": { + "core": 47550, + "status": 16060, + "not_applicable": 1972, + "research": 43662, + "western": 32844 + }, + "total_chars": 142088, + "category_sum": 142088, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 142088, + "token_estimate": 40597, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67344, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3872, + "token_estimate": 1106, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10" + ], + "expected_vargas": [ + "D10" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__marriage", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "marriage", + "domain": "marriage", + "wall_seconds": 2.625, + "workflow_chars": 403759, + "route": "marriage", + "focus_techniques": [ + "D9", + "UL Upapada", + "Dasha", + "Nakshatra", + "Vivah Saham" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__marriage", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 9708, + "model_chars": 142141 + }, + "categories": { + "categories": { + "core": 45808, + "status": 17855, + "not_applicable": 1972, + "research": 43662, + "western": 32844 + }, + "total_chars": 142141, + "category_sum": 142141, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 142141, + "token_estimate": 40612, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66172, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3702, + "token_estimate": 1058, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D9" + ], + "expected_vargas": [ + "D9" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas", + "transits" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__wealth", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "wealth", + "domain": "wealth", + "wall_seconds": 2.613, + "workflow_chars": 408166, + "route": "wealth", + "focus_techniques": [ + "D2", + "D11", + "Dasha", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__wealth", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 3, + "methodology_chars": 6841, + "model_chars": 138988 + }, + "categories": { + "categories": { + "core": 44414, + "status": 15480, + "not_applicable": 2588, + "research": 43662, + "western": 32844 + }, + "total_chars": 138988, + "category_sum": 138988, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 138988, + "token_estimate": 39711, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66030, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3778, + "token_estimate": 1079, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D11", + "D2" + ], + "expected_vargas": [ + "D2", + "D11" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__health", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "health", + "domain": "health", + "wall_seconds": 4.147, + "workflow_chars": 428729, + "route": "health", + "focus_techniques": [ + "D6", + "D8", + "D30", + "Dasha", + "Narayana Dasha", + "Shadbala", + "Transit", + "Functional Benefic/Malefic" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__health", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 2, + "methodology_chars": 3772, + "model_chars": 138361 + }, + "categories": { + "categories": { + "core": 45056, + "status": 14211, + "not_applicable": 2588, + "research": 43662, + "western": 32844 + }, + "total_chars": 138361, + "category_sum": 138361, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 138361, + "token_estimate": 39532, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 67251, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3856, + "token_estimate": 1102, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D30", + "D6", + "D8" + ], + "expected_vargas": [ + "D6", + "D8", + "D30" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "transits", + "shadbala" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__education", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "education", + "domain": "education", + "wall_seconds": 2.64, + "workflow_chars": 426624, + "route": "education", + "focus_techniques": [ + "D5", + "D24", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__education", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 134798 + }, + "categories": { + "categories": { + "core": 43218, + "status": 12463, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 134798, + "category_sum": 134798, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 134798, + "token_estimate": 38514, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66342, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3611, + "token_estimate": 1032, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D24", + "D5" + ], + "expected_vargas": [ + "D5", + "D24" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__migration", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "migration", + "domain": "migration", + "wall_seconds": 2.601, + "workflow_chars": 426709, + "route": "migration", + "focus_techniques": [ + "D4", + "D12", + "12th house", + "Dasha", + "Narayana Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__migration", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2024, + "model_chars": 134878 + }, + "categories": { + "categories": { + "core": 43218, + "status": 12543, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 134878, + "category_sum": 134878, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 134878, + "token_estimate": 38537, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66382, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3159, + "token_estimate": 903, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D4" + ], + "expected_vargas": [ + "D4", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + }, + "d12_moon": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__family", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "family", + "domain": "family", + "wall_seconds": 2.638, + "workflow_chars": 410647, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__family", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 132800 + }, + "categories": { + "categories": { + "core": 42583, + "status": 11100, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 132800, + "category_sum": 132800, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 132800, + "token_estimate": 37943, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65346, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3197, + "token_estimate": 913, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12", + "D7" + ], + "expected_vargas": [ + "D7", + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + }, + "d12_moon": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__general", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "general", + "domain": "general", + "wall_seconds": 2.607, + "workflow_chars": 427007, + "route": "general", + "focus_techniques": [ + "D1", + "D9", + "Dasha", + "Yoga", + "Shadbala", + "Ashtakavarga" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__general", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2022, + "model_chars": 134776 + }, + "categories": { + "categories": { + "core": 43198, + "status": 12461, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 134776, + "category_sum": 134776, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 134776, + "token_estimate": 38507, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 66333, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 5650, + "token_estimate": 1614, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D10", + "D2", + "D9" + ], + "expected_vargas": [ + "D9", + "D10", + "D2" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "transits", + "ashtakavarga", + "shadbala", + "yogas" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__parents", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "parents", + "domain": "family", + "wall_seconds": 2.609, + "workflow_chars": 410566, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__parents", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 132782 + }, + "categories": { + "categories": { + "core": 42565, + "status": 11100, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 132782, + "category_sum": 132782, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 132782, + "token_estimate": 37938, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65337, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3548, + "token_estimate": 1014, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D12" + ], + "expected_vargas": [ + "D12" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + }, + "d12_moon": { + "status": "match", + "expected": "Cancer", + "actual": "Cancer" + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only" + ], + "sample_card": null + }, + { + "id": "elizabeth_taylor__children", + "chart_id": "elizabeth_taylor", + "chart_label": "Elizabeth Taylor", + "question_id": "children", + "domain": "family", + "wall_seconds": 2.599, + "workflow_chars": 410575, + "route": "family", + "focus_techniques": [ + "D7", + "D12", + "4th house", + "5th house", + "9th house", + "Dasha" + ], + "success": true, + "projection": { + "id": "elizabeth_taylor__children", + "schema_ok": true, + "schema_error": null, + "methodology_sections": 1, + "methodology_chars": 2021, + "model_chars": 132784 + }, + "categories": { + "categories": { + "core": 42567, + "status": 11100, + "not_applicable": 2588, + "research": 43685, + "western": 32844 + }, + "total_chars": 132784, + "category_sum": 132784, + "sum_error_ratio": 0.0, + "tokens": { + "chars": 132784, + "token_estimate": 37938, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + } + }, + "duplicates": { + "consultation_copies": 2, + "spread_keys_matching_consultations_0": [ + "domain", + "packet_version", + "question", + "route", + "status", + "evidence_contract", + "claim_cards", + "presentation", + "rectification" + ], + "consultations_chars": 65338, + "named_subtree_copies": { + "technique_audit_table": 4, + "varga_spectrum": 4, + "western_spectrum": 4, + "methodology": 1 + } + }, + "card_size": { + "chars": 3276, + "token_estimate": 936, + "token_method": "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected characters as about 40000 tokens (3.6 chars/token). This estimate uses 3.5 so the research tables stay comparable. It is not a vendor tokenizer." + }, + "card_gaps": [], + "part_b": { + "dual_dasha": true, + "domain_divisional": true, + "functional_benefic_malefic": true, + "raw_data": true, + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": [], + "present": { + "functional_benefic_malefic": true, + "vimshottari": true, + "narayana": true, + "ascendant_raw": true, + "domain_vargas": [ + "D7" + ], + "expected_vargas": [ + "D7" + ] + } + }, + "verbatim": { + "ok": false, + "checks": { + "ascendant_sign": { + "status": "match", + "expected": "Scorpio", + "actual": "Scorpio" + }, + "moon_sign": { + "status": "match", + "expected": "Libra", + "actual": "Libra" + }, + "moon_house": { + "status": "match", + "expected": 12, + "actual": 12 + }, + "vimshottari_lord": { + "status": "match", + "expected": "Mars", + "actual": "Mars" + }, + "vimshottari_start": { + "status": "match", + "expected": "2022-01-07", + "actual": "2022-01-07" + }, + "vimshottari_end": { + "status": "match", + "expected": "2029-01-07", + "actual": "2029-01-07" + }, + "antardasha_start": { + "status": "match", + "expected": "2026-07-05", + "actual": "2026-07-05" + }, + "antardasha_end": { + "status": "match", + "expected": "2026-12-01", + "actual": "2026-12-01" + }, + "pratyantar_start": { + "status": "mismatch", + "expected": "2026-09-05", + "actual": null + }, + "pratyantar_end": { + "status": "mismatch", + "expected": "2026-09-27", + "actual": null + }, + "narayana_sign": { + "status": "mismatch", + "expected": "Capricorn", + "actual": null + }, + "d12_lagna": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + }, + "d12_moon": { + "status": "not_on_card", + "expected": "Cancer", + "actual": null + } + }, + "mismatched": [ + "pratyantar_start", + "pratyantar_end", + "narayana_sign" + ] + }, + "card_dependencies": [ + "compute_chart", + "functional_benefic_malefic", + "dasha_sub_periods", + "narayana_dasha", + "varga_requested_only", + "arudha_padas", + "chara_karakas" + ], + "sample_card": null + } + ], + "layer_timings_seconds": { + "steve_jobs": { + "error": "NameError", + "message": "name 'swe' is not defined" + }, + "barack_obama": { + "error": "NameError", + "message": "name 'swe' is not defined" + }, + "elizabeth_taylor": { + "error": "NameError", + "message": "name 'swe' is not defined" + } + } +} \ No newline at end of file diff --git a/docs/research/consult_evidence_card_research_2026_09_27.md b/docs/research/consult_evidence_card_research_2026_09_27.md new file mode 100644 index 00000000..948ec27a --- /dev/null +++ b/docs/research/consult_evidence_card_research_2026_09_27.md @@ -0,0 +1,189 @@ +# 普通对话数据卡调研(2026-09-27) + +写答案的模型现在每轮要读约 3.8–4.1 万 token,其中能写进一张领域数据卡的大约 900–1700 token,约 2.3%–4.3%。建议立实现单,但先拍板下面 7 项。本单没有改线上行为,也没有下占星结论。 + +基准是 `origin/staging` `76924e33`。三张公开 AA 盘:Steve Jobs、Barack Obama、Elizabeth Taylor。参考日钉在 `2026-09-27`,岁差 `raman`,交点 `mean`。外部 VedAstro 没有调用。 + +## 要拍板的 7 项 + +1. **按草案把写答案的上下文收成数据卡。** 推荐:收。父母问法现在给模型 133290 字符(约 38083 token),草案卡 3548–3576 字符(约 1014–1022 token)。 +2. **「家庭」拆成「父母」和「子女」。** 推荐:拆。两种问法现在都进 `family`,焦点技法都是 D7、D12、4/5/9 宫。仓库里 Skill 和校时决策树已经把子女写成 D7、父母/家族写成 D12。 +3. **状态说明、研究分盘、西洋层留在后台。** 推荐:留在后台。审计回执继续用,不进写答案的上下文。 +4. **Part B 与「只给相关数据」的冲突。** 高严谨解读要求 MEVG 和真实案例校准。这两项现在是「没做」的状态说明。推荐:回答模型不读长状态,回执保留一行「未做,置信度封顶」。这一项必须由产品定,本单不取舍。 +5. **先补投影缺口再上卡。** 推荐:先补。引擎算出了当前 Narayana 星座和子运起止,投影给模型时被裁空(BUG-1054,investigating,未修)。卡只复制投影,所以这两项现在进不了卡。 +6. **先不要为了提速少算。** 推荐:计算先照旧。本机不调 VedAstro 时,一轮约 2.6 秒,其中校正门约 2.5 秒;40 张研究分盘合计不到 0.01 秒。线上曾经约 31 秒/领域,那次含外部取证,本单没有重测。 +7. **埋点只存领域、卡版本、大小、被引用字段名、赞或踩。** 推荐:按这个做。不存问题、回答、出生资料。 + +## R1 模型现在看到什么 + +结论:投影后约 13.3–14.4 万字符,按诊断同一比例估成约 3.8–4.1 万 token。五类加总与总字符数一致(误差 0)。同一份包在 `consultations` 里再放一遍,约占一半。 + +复跑: + +```text +$env:PYTHONHASHSEED = "0" +python scripts/research/consult_evidence_card_run.py +``` + +token 估算是字符数 / 3.5。2026-09-27 诊断把约 144000 字符看成约 40000 token。这不是供应商分词器。 + +父母问法、Jobs 盘,模型可见文本 133290 字符: + +| 类别 | 字符 | 占总量 | +| --- | ---: | ---: | +| 核心数据 | 42739 | 32.1% | +| 研究用 | 43949 | 33.0% | +| 西洋 | 32892 | 24.7% | +| 状态说明 | 11122 | 8.3% | +| 本轮不适用 | 2588 | 1.9% | +| 合计 | 133290 | 100% | + +十种问法的模型可见文本在 132782–143603 字符之间。事业、婚恋带方法学长文,所以更大。30 次的类别合计都与各自总量一致。 + +重复:`consultations[0]` 与摊开的同一批键逐字相同。Jobs 父母问法里这段 65591 字符,占 49.2%。`varga_spectrum`、`western_spectrum`、`technique_audit_table` 各出现 4 次:本命卡或时间卡一份,证据合同再一份,然后整包再复制进 `consultations`。方法学只出现 1 次。 + +43 行技法审计表(同一套分类规则):核心 15、西洋 12、状态 8、不适用 5、研究 3。规则写在 `scripts/research/consult_evidence_card_lib.py` 的技法名表里。 + +原始工作流 JSON 是 394333–423130 字符(30 个缓存文件的字符数,均值 409085)。诊断里的约 478K 含外部取证原文;本单按任务要求没有调 VedAstro,所以原始包更小。库存 JSON 里的 `workflow_chars` 是文件字节数,不是字符数。 + +建议立实现单:是,但实现的是筛选,不是先改计算。 + +## R2 领域和技法对不上 + +结论:同一领域在注册表、方法学、前端必用层、Python 焦点技法四处不一致。父母和子女没有独立领域,两种问法都走 `family`。 + +复跑:草案 JSON 由下面的库函数生成,已写入 `docs/research/consult_evidence_card_draft_2026_09_27.json`。 + +```text +python -c "import json,sys; from pathlib import Path; sys.path[:0]=['scripts','scripts/research']; from consult_evidence_card_lib import CARD_SPECS, TELEMETRY_SPEC, source_matrix; json.dump({'cards':CARD_SPECS,'source_matrix':source_matrix(Path('.')),'telemetry':TELEMETRY_SPEC}, open('docs/research/consult_evidence_card_draft_2026_09_27.json','w',encoding='utf-8'), ensure_ascii=False, indent=2)" +``` + +| 领域 | 注册表要的层 | 方法学路线 | 前端必用层 | Python 焦点 | 草案分盘 | +| --- | --- | --- | --- | --- | --- | +| 事业 | D1 D10 10宫 A10 AmK 大运 Narayana 过境 | career-timing-strict | 正式分盘、A10、Narayana、Chara | D10 大运 Shadbala 过境 Narayana | D10 | +| 婚恋 | D1 D9 7宫 金木 DK UL A7 大运 Narayana 过境 | relationship-timing-strict | 正式分盘、Arudha | D9 UL 大运 星宿 婚姻份 | D9 | +| 财富 | D1 D2 D11 2/11/9/5 财富格局 Ashtakavarga 大运 | finance-timing-strict | 正式分盘、Ashtakavarga | D2 D11 大运 Shadbala Ashtakavarga | D2 D11 | +| 健康 | D1 D6 D8 6/8宫 大运 非医疗边界 | health-timing-strict | 正式分盘、Shadbala | D6 D8 D30 大运 Narayana Shadbala 过境 功能吉凶 | D6 D8 D30 | +| 学习 | D1 D24 5/9宫 水木 大运 | 无 | 无 | D5 D24 5宫 9宫 大运 | D5 D24 | +| 迁居 | D1 D4 D12 4/12宫 大运 Narayana | 无 | 无 | D4 D12 12宫 大运 Narayana | D4 D12 | +| 家庭 | D1 D7 D12 4/5/9宫 大运 | 无 | 无 | D7 D12 4宫 5宫 9宫 大运 | D7 D12 | +| 综合 | D1 D9 D10 D2 大运 Narayana 过境 功能吉凶 | 无 | 无 | D1 D9 大运 格局 Shadbala Ashtakavarga | D9 D10 D2 | +| 父母 | 无此领域 | 无 | 无 | 无;问法仍进 family | D12、4宫、9宫 | +| 子女 | 无此领域 | 无 | 无 | 无;问法仍进 family | D7、5宫 | + +每张卡的基础段都带:上升、十二宫星座、行星落宫、功能吉凶(含宫主归属)、当前 Vimshottari 大运与子运起止、Narayana 对象。领域段只带上表分盘和该领域的宫、行星、过境或力量层。值从投影里原样复制,不改写。 + +父母、子女的依据: + +- Skill `references/strict-workflow-router.md` 共用基线:子女用 D7,父母/家族主题用 D12。 +- `references/birth-time-rectification-decision-tree.md` 第 4 节:子女/生育 → D7;父母/家族 → D12。 + +Part B 覆盖:双轨大运、领域分盘、功能吉凶、上升与大运日期,在投影还留着的字段上是齐的。MEVG 和真实案例校准按草案留在后台,见拍板第 4 项。Narayana 当前星座和子运日期被投影裁掉,见拍板第 5 项。 + +建议立实现单:是。先让产品和懂印占的人确认这张表,尤其是健康域 Python 有 D30、注册表没有,学习域 Python 有 D5、注册表没有。 + +## R3 数据卡有多小,事实有没有被改 + +结论:十张草案卡是现状的 2.3%–4.3%。验收点名的事实与引擎逐字一致。卡没有改值。投影丢掉的两项记成缺陷,没有用引擎原文填回去。 + +复跑:同一条 R1 命令。比对在 `scripts/research/consult_evidence_card_lib.py` 的 `verbatim_check`。 + +三盘均值: + +| 问法 | 现状字符 | 现状 token 估计 | 卡字符 | 卡 token 估计 | 卡 / 现状 | +| --- | ---: | ---: | ---: | ---: | ---: | +| 事业 | 142483 | 40710 | 3942 | 1126 | 2.77% | +| 婚恋 | 142762 | 40789 | 3753 | 1072 | 2.63% | +| 财富 | 139328 | 39808 | 3799 | 1085 | 2.73% | +| 健康 | 138812 | 39660 | 3894 | 1113 | 2.81% | +| 学习 | 135225 | 38636 | 3626 | 1036 | 2.68% | +| 迁居 | 135305 | 38659 | 3169 | 906 | 2.34% | +| 家庭 | 133110 | 38031 | 3213 | 918 | 2.41% | +| 综合 | 135203 | 38629 | 5750 | 1643 | 4.25% | +| 父母 | 133092 | 38026 | 3559 | 1017 | 2.67% | +| 子女 | 133094 | 38027 | 3297 | 942 | 2.48% | + +逐字核对,30 次里凡是卡上有的都一致:上升星座、月亮星座、月亮宫位、当前大运起止、子运起止。带 D12 的 9 次(父母、家庭、迁居 × 3 盘)D12 上升和月亮落点也一致。不带 D12 的卡不拿 D12 做失败。 + +不一致、且没有改卡:30/30 的子运起止和 Narayana 当前星座。引擎有值,投影是空,卡跟着空。BUG-1054。 + +建议立实现单:是。实现时卡仍然只复制投影,先把 BUG-1054 的两段放进投影。 + +## R4 少算省不了这轮等待 + +结论:本机不调 VedAstro 时,少算研究分盘和西洋层省不到 0.05 秒。等待几乎全在校正门。外部取证没有计时,也不计入。 + +复跑: + +```text +$env:PYTHONHASHSEED = "0" +python scripts/research/consult_evidence_card_time.py +``` + +数字在 `docs/research/consult_evidence_card_timings_2026_09_27.json`。包一层计时的一轮(事业问法): + +| 模块 | Jobs | Obama | Taylor | +| --- | ---: | ---: | ---: | +| 整轮 | 4.81 秒 | 2.58 秒 | 2.59 秒 | +| 校正门 | 3.97 秒 | 2.47 秒 | 2.48 秒 | +| 本命计算 | 0.002 秒 | 0.002 秒 | 0.002 秒 | +| 本地附加层(含分盘) | 0.035 秒 | 0.031 秒 | 0.020 秒 | +| 其中正式分盘 | 0.002 秒 | 0.001 秒 | 0.001 秒 | +| 40 张研究分盘合计 | 0.000 秒 | 0.000 秒 | 0.0002 秒 | +| 主题报告 | 0.072 秒 | 0.008 秒 | 0.009 秒 | + +30 次库存跑的墙钟是 2.568–5.539 秒,去掉第一次冷启动后均值 2.692 秒。 + +卡依赖的计算是本命盘、功能吉凶、大运子运、Narayana,加上该领域 1–3 张分盘。这些层加起来远小于校正门。研究分盘 40 次调用都发生了,时间可以忽略。所以「只算卡里要的」相对「全算」的节省,在本机是毫秒级。 + +校正门不是数据卡的内容。要不要缩短它,是另一张单,不是这张卡的筛选。 + +线上约 31 秒/领域来自 BUG-1051 的观察,路径里含外部取证。本单按任务没有重跑 VedAstro,不把 31 秒写成本机结果。 + +建议立实现单:筛选可以立。少算先不立,除非产品要单独处理校正门或外部取证等待。 + +## R5 反馈只记字段名 + +结论:每轮可以记 6 个字段,用来以后删卡上没人用的项。不存用户句子。 + +| 字段 | 内容 | +| --- | --- | +| domain | 十个问法枚举 | +| card_version | `evidence-card-draft-20260927` | +| card_chars | 整数 | +| card_token_estimate | 整数 | +| cited_field_ids | 卡方案里的字段名 | +| feedback | up / down / none | + +怎样算「引用了」:字段值是 ISO 日期、度数,或至少 8 个字符的「行星在星座」短语,并且原样出现在回答里,才算引用。裸的行星名、星座名不算。误报:问题和回答里碰巧有同一个日期。漏报:模型改写了时期、没抄日期。落库只留字段名,匹配到的原文丢掉。 + +后台汇总:按领域和卡版本数回答数;某领域满 30 条后,引用率仍低于 5% 的字段;按领域和卡版本的点踩率。没有用户句、没有出生资料、没有会话 id。 + +建议立实现单:方案可以并进数据卡实现单,不必单独先做。 + +## 复跑与测试 + +```text +$env:PYTHONHASHSEED = "0" +python scripts/research/consult_evidence_card_run.py +python scripts/research/consult_evidence_card_time.py +python -m pytest tests/test_consult_evidence_card_research.py +``` + +Windows 上 `skills/jyotish-vedic-astrology/references` 若不是目录,投影读不到方法学。本机把仓库根的 `references`、`scripts`、`assets` 接成 junction,并把 `SKILL.md` 复制进技能目录后再投影。这些链接没有提交。 + +## 附录:父母卡样例 + +公开盘 Steve Jobs,问法「我和父母关系如何」,参考日 2026-09-27。完整卡片在 `docs/research/consult_evidence_card_sample_parents_2026_09_27.json`。下面是核对过的事实,不是解读。 + +| 项 | 卡里的值 | 与引擎 | +| --- | --- | --- | +| 上升 | Virgo 0.51° | 一致 | +| 月亮 | Pisces,7 宫 | 一致 | +| 大运 | Rahu,2023-02-25 至 2041-02-24 | 一致 | +| 子运 | Jupiter,2025-11-07 至 2028-04-01 | 一致 | +| D12 | 上升 Virgo,月亮 Virgo | 一致 | +| 功能吉星 | Mercury、Saturn、Venus | 来自投影,未改 | +| 4 宫 / 9 宫 | Sagittarius / Taurus | 来自投影,未改 | +| Narayana 当前段 | 投影后是空对象 | 引擎有值,BUG-1054 | +| 子运 PD | 不在投影里 | 引擎有值,BUG-1054 | diff --git a/docs/research/consult_evidence_card_sample_parents_2026_09_27.json b/docs/research/consult_evidence_card_sample_parents_2026_09_27.json new file mode 100644 index 00000000..c306a99c --- /dev/null +++ b/docs/research/consult_evidence_card_sample_parents_2026_09_27.json @@ -0,0 +1,294 @@ +{ + "card_id": "parents", + "label": "父母", + "question": "我和父母关系如何", + "route": "family", + "base": { + "ascendant": { + "degree": 0.51, + "degree_in_sign": 0.51, + "lon": 150.5069, + "sign": "Virgo", + "sign_idx": 5 + }, + "houses": { + "1": { + "sign": "Virgo", + "sign_idx": 5 + }, + "2": { + "sign": "Libra", + "sign_idx": 6 + }, + "3": { + "sign": "Scorpio", + "sign_idx": 7 + }, + "4": { + "sign": "Sagittarius", + "sign_idx": 8 + }, + "5": { + "sign": "Capricorn", + "sign_idx": 9 + }, + "6": { + "sign": "Aquarius", + "sign_idx": 10 + }, + "7": { + "sign": "Pisces", + "sign_idx": 11 + }, + "8": { + "sign": "Aries", + "sign_idx": 0 + }, + "9": { + "sign": "Taurus", + "sign_idx": 1 + }, + "10": { + "sign": "Gemini", + "sign_idx": 2 + }, + "11": { + "sign": "Cancer", + "sign_idx": 3 + }, + "12": { + "sign": "Leo", + "sign_idx": 4 + } + }, + "planet_placements": { + "Jupiter": { + "sign": "Gemini", + "house": 10 + }, + "Ketu": { + "sign": "Gemini", + "house": 10 + }, + "Mars": { + "sign": "Aries", + "house": 8 + }, + "Mercury": { + "sign": "Capricorn", + "house": 5 + }, + "Moon": { + "sign": "Pisces", + "house": 7 + }, + "Rahu": { + "sign": "Sagittarius", + "house": 4 + }, + "Saturn": { + "sign": "Libra", + "house": 2 + }, + "Sun": { + "sign": "Aquarius", + "house": 6 + }, + "Venus": { + "sign": "Sagittarius", + "house": 4 + } + }, + "functional_benefic_malefic": { + "status": "used", + "ascendant": "Virgo", + "functional_benefics": [ + "Mercury", + "Saturn", + "Venus" + ], + "functional_malefics": [ + "Mars", + "Moon", + "Sun" + ], + "functional_neutrals": [ + "Jupiter" + ], + "yogakarakas": [ + "Mercury" + ], + "owned_houses": { + "Jupiter": [ + 4, + 7 + ], + "Mars": [ + 3, + 8 + ], + "Mercury": [ + 1, + 10 + ], + "Moon": [ + 11 + ], + "Saturn": [ + 5, + 6 + ], + "Sun": [ + 12 + ], + "Venus": [ + 2, + 9 + ] + }, + "effect_on_confidence": "高严谨模式下必须叠加功能性宫主吉凶与自然吉凶;若功能属性与自然属性冲突,应降低置信度或显式标记冲突。", + "source": "strict_functional_benefic_malefic_v1" + }, + "vimshottari": { + "status": "ready", + "source": "chart.dasha.periods + dasha_analyzer.build_antardasha", + "method": "vimshottari_antardasha_proportional", + "current": { + "mahadasha": { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2041-02-24" + }, + "antardasha": { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + } + }, + "next": { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + "boundaries": [ + { + "lord": "Rahu", + "start": "2023-02-25", + "end": "2025-11-07" + }, + { + "lord": "Jupiter", + "start": "2025-11-07", + "end": "2028-04-01" + }, + { + "lord": "Saturn", + "start": "2028-04-01", + "end": "2031-02-06" + }, + { + "lord": "Mercury", + "start": "2031-02-06", + "end": "2033-08-25" + }, + { + "lord": "Ketu", + "start": "2033-08-25", + "end": "2034-09-13" + }, + { + "lord": "Venus", + "start": "2034-09-13", + "end": "2037-09-12" + }, + { + "lord": "Sun", + "start": "2037-09-12", + "end": "2038-08-07" + }, + { + "lord": "Moon", + "start": "2038-08-07", + "end": "2040-02-06" + }, + { + "lord": "Mars", + "start": "2040-02-06", + "end": "2041-02-24" + } + ], + "boundary_count": 9, + "summary": "当前 Rahu 大运下的小运为 Jupiter,边界 2025-11-07 至 2028-04-01。更细的 Pratyantardasha 与行运触发不在本层计算范围内。" + }, + "narayana_dasha": { + "current_dasha": {} + } + }, + "domain": { + "vargas": { + "D12": { + "lagna": "Virgo", + "planets": { + "Sun": "Cancer", + "Moon": "Virgo", + "Mars": "Gemini", + "Mercury": "Libra", + "Jupiter": "Taurus", + "Venus": "Scorpio", + "Saturn": "Virgo", + "Rahu": "Aries", + "Ketu": "Libra" + }, + "name": "Dwadasamsa", + "meaning": "父母" + } + }, + "houses": { + "4": { + "sign": "Sagittarius", + "sign_idx": 8 + }, + "9": { + "sign": "Taurus", + "sign_idx": 1 + } + }, + "planets": { + "Sun": { + "degree": 13.9638, + "degree_in_sign": 13.9638, + "degree_raw": 313.96378728533347, + "house": 6, + "lon": 313.96378728533347, + "nakshatra": "Shatabhisha", + "retrograde": false, + "sign": "Aquarius", + "sign_idx": 10, + "status": "极敌(Great Enemy)" + }, + "Moon": { + "degree": 15.9628, + "degree_in_sign": 15.9628, + "degree_raw": 345.9628222838024, + "house": 7, + "lon": 345.9628222838024, + "nakshatra": "Uttara Bhadrapada", + "retrograde": false, + "sign": "Pisces", + "sign_idx": 11, + "status": "入友(Friendly Sign)" + } + }, + "arudha": {}, + "karakas": {}, + "yogas": null, + "transits": null, + "ashtakavarga": null, + "shadbala": null + }, + "gaps": [], + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D12 for family/ancestral themes", + "references/birth-time-rectification-decision-tree.md section 4: 父母/家族 -> D12" + ] +} \ No newline at end of file diff --git a/docs/research/consult_evidence_card_timings_2026_09_27.json b/docs/research/consult_evidence_card_timings_2026_09_27.json new file mode 100644 index 00000000..ad26e303 --- /dev/null +++ b/docs/research/consult_evidence_card_timings_2026_09_27.json @@ -0,0 +1,35 @@ +{ + "steve_jobs": { + "compute_chart": 0.0024, + "rectification_gate": 3.9655, + "varga_full": 0.0017, + "research_dn_loop": 0.0, + "varga_spectrum": 0.0031, + "attach_local_layers": 0.0352, + "thematic_report": 0.072, + "workflow_wall": 4.8122, + "research_dn_calls": 40 + }, + "barack_obama": { + "compute_chart": 0.0023, + "rectification_gate": 2.4683, + "varga_full": 0.0006, + "research_dn_loop": 0.0, + "varga_spectrum": 0.0019, + "attach_local_layers": 0.0309, + "thematic_report": 0.0082, + "workflow_wall": 2.5763, + "research_dn_calls": 40 + }, + "elizabeth_taylor": { + "compute_chart": 0.0024, + "rectification_gate": 2.4828, + "varga_full": 0.0005, + "research_dn_loop": 0.0002, + "varga_spectrum": 0.0019, + "attach_local_layers": 0.0204, + "thematic_report": 0.0088, + "workflow_wall": 2.5871, + "research_dn_calls": 40 + } +} \ No newline at end of file diff --git a/docs/tasks/PROGRESS-consult-evidence-card-research-20260927.md b/docs/tasks/PROGRESS-consult-evidence-card-research-20260927.md new file mode 100644 index 00000000..3159809e --- /dev/null +++ b/docs/tasks/PROGRESS-consult-evidence-card-research-20260927.md @@ -0,0 +1,30 @@ +# PROGRESS · 普通对话数据卡调研(2026-09-27) + +## 开工基线 + +- 计量时 `origin/staging` 是 `76924e3362c0a47d9d8de896c448c66055826f70`(任务书自己的文档提交)。任务书里写的 `5f2e007f` 已被那次推送盖过。 +- 推送前 staging 又到了 `3b67d8e9`(BUG-1052、BUG-1053)。本地提交已接到这个 tip 上再快进。计量数字仍是 `76924e33` 上的引擎与投影;`toModelOutput` 的裁剪规则没有被这两单改动。 +- 工作树 `.worktrees/consult-evidence-card-research-20260927`,分支 `codex/consult-evidence-card-research-20260927`。 +- 主检出仍在 `staging`,没有在主检出上提交或切分支。 +- `PYTHONHASHSEED=0`。Python `C:\Users\74082\anaconda3\python.exe` 3.11.7。Node v22.23.2。 + +## 做了什么 + +- 3 张公开 AA 盘 × 10 种问法,调用 `JyotishAPIHandler._compute_consultation_workflow`,再用现有的 `toAgentConsultationContext` / `toModelOutput`,并按 `toModelDomainPlanContext` 的单领域分支包成模型可见文本。 +- 五类分区与总字符数一致。草案卡只复制投影。验收点名的事实与引擎逐字一致。 +- 投影丢掉当前 Narayana 段和子运日期,记为 BUG-1054,状态 `investigating`,没有改投影代码。 +- 本机计了本地层。外部 VedAstro 没有调用,也不计入耗时。 +- 报告:`docs/research/consult_evidence_card_research_2026_09_27.md`。 + +## 没做什么 + +- 没有改 `frontend/src/**`、`scripts/*.py`(`scripts/research/` 除外)、Skill 文本、数据库。 +- 没有推送,没有部署。 +- 没有下占星结论。 +- 没有重测线上约 31 秒/领域的外部取证等待。 + +## 环境缺口 + +- 预检 `scripts/pre_work_check.py` 退出 1。Python、远端、外部适配器正常。两条碎片扫描测试失败:这台机器没有 `.workbuddy/skills/jyotish-vedic-astrology`,工作树残留计数 3638。不挡住本单。没有往错误台账追加,因为这是本机工作树布局,不是新的引擎故障。 +- Windows 把 `skills/jyotish-vedic-astrology` 下的符号链接检出成小文本文件。投影前在工作树里接了 junction,并复制了 `SKILL.md`。这些改动不提交。 +- 无浏览器验收:本单不改界面。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index b20fb49f..c8ce6b70 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -128,7 +128,7 @@ | --- | --- | --- | --- | --- | | — (产品 09-27 拍板 D1–D4,直接执行) | [PROGRESS](PROGRESS-home-landing-blank-20260927.md) | **登录后 / 裸 `/` 落空白首页**:真机登录后在「首页」提问其实问进了上一次生时校正。删登录返回存根(401 / 次级页链接写、登录后写回 `?c=` 打开),裸 `/` 不再落最近会话,一律当前人物的空白首页(复用空草稿);`?c=` / `?new=1` / 对话内刷新不变;推翻 BUG-1038 存根与 BUG-599 默认落点 | 已验收(真机欠) | `codex/home-landing-blank-20260927`(BUG-1052,本地未推) | | — (产品 09-26 口头拍板 D1–D3,直接执行) | `PROGRESS-consult-answer-truncation-20260926.md` | **普通咨询回答写到一半被掐断仍扣点(BUG-1051,复发自 BUG-305)**:工具循环与写回答共用 110 秒 signal;Mastra 1.50 超时不抛错(`abort` 块 + `finish(tripwire)` 后正常关流),结算只认抛错与 `length`。D1 写回答自有 70 秒时钟(首用起算,续写 / 回答重试共用,最坏 180 秒,`maxDuration` 240);D2 写回答的最后一个流不是 `stop` 且有正文 → `answer_truncated`、不扣点、记 abort 步、不冲半句,`length` 续写不变;D3 观测加 `composeFinishReason` / `composeAborted` / `answerVisibleChars` | 已验收(真机欠) | `codex/consult-answer-truncation-20260926`(本地,未推送);新回归 15 条用真实 Mastra `Agent`(修复前 11 条红);全量失败名单 0 新增;Python 948/1;`/` ○、gzip 0%;真机清单 `docs/testing/consult-answer-truncation-20260926.md` | -| `TASK-consult-evidence-card-research-20260927.md` | `PROGRESS-consult-evidence-card-research-20260927.md` | **普通对话数据卡调研**:引擎输出逐项分五类计量(现约 4 万 token、父母问题相关约 3.5%);四处领域→技法来源对账并起草各领域数据卡(家庭拆父母/子女);卡体量与逐字一致性;按卡算的提速空间;反馈迭代埋点方案。只调研不改线上 | 待领取 | 分支 `codex/consult-evidence-card-research-20260927`;与 BUG-1053 实现单并行,不碰 consult route / stream-agent-response | +| `TASK-consult-evidence-card-research-20260927.md` | `PROGRESS-consult-evidence-card-research-20260927.md` | **普通对话数据卡调研**:引擎输出逐项分五类计量(现约 4 万 token、父母问题相关约 3.5%);四处领域→技法来源对账并起草各领域数据卡(家庭拆父母/子女);卡体量与逐字一致性;按卡算的提速空间;反馈迭代埋点方案。只调研不改线上 | 待验收 | `codex/consult-evidence-card-research-20260927` 快进 staging;报告 `docs/research/consult_evidence_card_research_2026_09_27.md`;投影缺口记 BUG-1054 investigating | | — (产品 09-27 拍板 D1–D3,直接执行) | `PROGRESS-consult-single-pass-answer-20260927.md` | **普通咨询回答没看过星盘(BUG-1053,引入 `04463e9a`,生产不受影响)**:本命主循环工具结果后那一步看得到证据、正文却被丢弃,用户看到的是另开的 compose 流(只有历史 + 问题、判断依据恒空)写的。D1 删 compose / interpret / drain,主循环最后一步的正文即回答(按步取答,调用工具的那一步正文整段丢);写作要求搬进用户轮;续写带计算结果;工具 110 秒不变,拿到计算结果后循环交给 70 秒答案钟,最坏 180 秒;BUG-1051 结算规则保留(按写回答那一步判定)。D2 观测字段名不变、含义改为写回答那一步 | 已验收(真机欠) | `codex/consult-single-pass-answer-20260927`(本地,未推送);新回归 15 条用真实 `getJyotishAgent` + 记录提示词的假模型 + golden 计算数据;全量失败名单 0 新增;Python 948/1;`/` ○、gzip +0.24%;真机清单 `docs/testing/consult-single-pass-answer-20260927.md` | | `TASK-scroll-anchor-hook-fixes-20260926.md` | `PROGRESS-scroll-anchor-hook-fixes-20260926.md` | **滚动锚两处老问题**:直接打开已有会话时监听未挂上(BUG-1043)、校正长回答钉顶后因 96px 阈值被拉到底(BUG-1044)。排在 BUG-1042 合入后。挂载改由容器元素本身驱动(每次提交比对元素 / active / resetKey);钉顶只由用户滚动手势解除 | 已验收(Claude 09-26 直接执行:子代理复现两处根因并修复;Claude 独立复验 tsc/lint 0、全量 3970 条失败名单与基线逐条一致、四路由 ○、gzip 不变;iOS 惯性滚动留真机清单) | `da2613ff`(随 `f1d16405` 部署,health 一致) | | `TASK-latest-turn-actions-gap-20260926.md` | — | **最后一轮正文与点赞 / 踩之间空大半屏**:BUG-930 钉顶留白(`min-height: 视口 − 本轮开头`)加在 `.message-assistant` 上,把兄弟节点 `.message-actions` 推到留白之后;改为加在整轮外层,按钮紧贴正文、空白落在后面;不动滚动 hook | 已验收(Claude 09-26 直接执行:子代理实现,Claude 独立复验 tsc/lint 0、全量 3961 条失败名单与基线逐条一致、四路由 ○、gzip 不变;CDP 实测间距 450–600px → 23px,钉顶仍在) | `080ea5ca`(已部署 `509987b9`,health 一致) | diff --git a/scripts/research/consult_evidence_card_lib.py b/scripts/research/consult_evidence_card_lib.py new file mode 100644 index 00000000..59caa1ad --- /dev/null +++ b/scripts/research/consult_evidence_card_lib.py @@ -0,0 +1,811 @@ +"""Pure helpers for the consultation evidence-card research. + +No network, no engine mutation. Classification partitions a JSON value so the +five category sizes sum to the canonical serialization length. +""" + +from __future__ import annotations + +import json +import re +from collections import Counter +from pathlib import Path +from typing import Any + +CATEGORIES = ("core", "status", "not_applicable", "research", "western") + +TOKEN_CHARS_PER_TOKEN = 3.5 +TOKEN_METHOD = ( + "chars/3.5. The 2026-09-27 diagnosis measured about 144000 projected " + "characters as about 40000 tokens (3.6 chars/token). This estimate uses " + "3.5 so the research tables stay comparable. It is not a vendor tokenizer." +) + +REFERENCE_DATE = "2026-09-27" +AYANAMSA = "raman" +NODE_MODE = "mean" + +QUESTIONS = ( + {"id": "career", "domain": "career", "question": "未来一年,事业和收入该关注什么?"}, + {"id": "marriage", "domain": "marriage", "question": "我的关系模式是什么?"}, + {"id": "wealth", "domain": "wealth", "question": "我的财富增长方式和风险点是什么?"}, + {"id": "health", "domain": "health", "question": "我近期的身心压力模式和调节重点是什么?"}, + {"id": "education", "domain": "education", "question": "我的学习优势、瓶颈和进阶方向是什么?"}, + {"id": "migration", "domain": "migration", "question": "迁居、置业或海外发展更适合怎样规划?"}, + {"id": "family", "domain": "family", "question": "我的家庭关系与责任边界该如何理解?"}, + {"id": "general", "domain": "general", "question": "请综合说明我当前最值得关注的主题。"}, + {"id": "parents", "domain": "family", "question": "我和父母关系如何"}, + {"id": "children", "domain": "family", "question": "我和子女的关系如何"}, +) + +CHART_SOURCES = ( + { + "id": "steve_jobs", + "label": "Steve Jobs", + "path": "references/real_case_calibration/minute_rectification_development_v1.json", + "case_id": "steve_jobs_1955_development", + }, + { + "id": "barack_obama", + "label": "Barack Obama", + "path": "references/real_case_calibration/minute_rectification_holdout_v4.json", + "case_id": "barack_obama_1961_aa_v4_holdout", + }, + { + "id": "elizabeth_taylor", + "label": "Elizabeth Taylor", + "path": "references/real_case_calibration/minute_rectification_holdout_v4.json", + "case_id": "elizabeth_taylor_1932_aa_v4_holdout", + }, +) + +STATUS_TECHNIQUES = { + "mevg / global web evidence", + "real case calibration", + "vedastro main entry overview", + "vedastro cloud state", + "external oracle progress", + "interpretation source pack", + "module execution audit", + "exact cusp oracle", + "blind technical mode", + "timing precision gate", + "evidence packet", + "shadbala boundary", +} +RESEARCH_TECHNIQUES = { + "research d-n through d60", + "extended vargas d81/d108/d144", + "ashtottari dasha", +} +NOT_APPLICABLE_TECHNIQUES = { + "prashna chart", + "ashtakoota matching", + "adhana / niseka", + "muhurta election", +} +WESTERN_PREFIX = "western" + +STATUS_KEYS = { + "methodology", + "presentation", + "rectification", + "answer_policy", + "user_facing_limitation", + "hard_blockers", + "missing_route_layers", + "available_layers", + "must_use_layers", + "technique_truth", + "reference_transparency", + "shadbala_boundary", + "vedastro_cross_check", + "vedastro_gateway", + "commercial_evidence_status", + "success", + "omitted_domains", + "status", + "packet_version", + "schema_error", +} + +# Domain card draft. Values are copied from the projection; nothing is rewritten. +CARD_SPECS: dict[str, dict[str, Any]] = { + "career": { + "label": "事业", + "vargas": ["D10"], + "houses": [10], + "arudha": ["A10"], + "karakas": ["AmK"], + "planets": [], + "yogas": True, + "transits": True, + "ashtakavarga": False, + "shadbala": True, + }, + "marriage": { + "label": "婚恋", + "vargas": ["D9"], + "houses": [7], + "arudha": ["UL", "A7"], + "karakas": ["DK"], + "planets": ["venus", "jupiter"], + "yogas": False, + "transits": True, + "ashtakavarga": False, + "shadbala": False, + }, + "wealth": { + "label": "财富", + "vargas": ["D2", "D11"], + "houses": [2, 11, 9, 5], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": True, + "transits": False, + "ashtakavarga": True, + "shadbala": True, + }, + "health": { + "label": "健康", + "vargas": ["D6", "D8", "D30"], + "houses": [6, 8], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": False, + "transits": True, + "ashtakavarga": False, + "shadbala": True, + }, + "education": { + "label": "学习", + "vargas": ["D5", "D24"], + "houses": [5, 9], + "arudha": [], + "karakas": [], + "planets": ["mercury", "jupiter"], + "yogas": False, + "transits": False, + "ashtakavarga": False, + "shadbala": False, + }, + "migration": { + "label": "迁居", + "vargas": ["D4", "D12"], + "houses": [4, 12], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": False, + "transits": False, + "ashtakavarga": False, + "shadbala": False, + }, + "family": { + "label": "家庭(现路由,父母与子女混在一起)", + "vargas": ["D7", "D12"], + "houses": [4, 5, 9], + "arudha": [], + "karakas": [], + "planets": [], + "yogas": False, + "transits": False, + "ashtakavarga": False, + "shadbala": False, + }, + "parents": { + "label": "父母", + "vargas": ["D12"], + "houses": [4, 9], + "arudha": [], + "karakas": [], + "planets": ["sun", "moon"], + "yogas": False, + "transits": False, + "ashtakavarga": False, + "shadbala": False, + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D12 for family/ancestral themes", + "references/birth-time-rectification-decision-tree.md section 4: 父母/家族 -> D12", + ], + }, + "children": { + "label": "子女", + "vargas": ["D7"], + "houses": [5], + "arudha": [], + "karakas": ["PK"], + "planets": ["jupiter"], + "yogas": False, + "transits": False, + "ashtakavarga": False, + "shadbala": False, + "basis": [ + "skills/jyotish-vedic-astrology/references/strict-workflow-router.md shared baseline: D7 for children", + "references/birth-time-rectification-decision-tree.md section 4: 子女/生育 -> D7", + ], + }, + "general": { + "label": "综合", + "vargas": ["D9", "D10", "D2"], + "houses": [1, 10, 7, 2], + "arudha": ["A10"], + "karakas": [], + "planets": [], + "yogas": True, + "transits": True, + "ashtakavarga": True, + "shadbala": True, + }, +} + +PART_B_BASE = ( + "functional_benefic_malefic", + "vimshottari_md_ad_pd", + "narayana_current", + "ascendant_degree", +) + + +def dumps(value: Any) -> str: + return json.dumps(value, ensure_ascii=False, separators=(",", ":")) + + +def estimate_tokens(text: str) -> dict[str, Any]: + chars = len(text) + return { + "chars": chars, + "token_estimate": int(round(chars / TOKEN_CHARS_PER_TOKEN)), + "token_method": TOKEN_METHOD, + } + + +def _norm(value: str) -> str: + return re.sub(r"\s+", " ", value).strip().lower() + + +def classify_audit_row(row: dict[str, Any]) -> str: + technique = _norm(str(row.get("technique") or "")) + system = _norm(str(row.get("system") or "")) + status = _norm(str(row.get("status") or "")) + if system == "western" or technique.startswith(WESTERN_PREFIX): + return "western" + if technique in RESEARCH_TECHNIQUES: + return "research" + if status == "not_applicable" or technique in NOT_APPLICABLE_TECHNIQUES: + return "not_applicable" + if technique in STATUS_TECHNIQUES or "vedastro" in technique or "mevg" in technique: + return "status" + return "core" + + +def classify(path: tuple[str, ...], value: Any) -> str: + joined = ".".join(path).lower() + if "western_spectrum" in joined or joined.startswith("western"): + return "western" + if "research_dn" in joined or "extended" in joined and "varga" in joined: + return "research" + if isinstance(value, dict) and "technique" in value and "status" in value and "technique_audit" in joined: + return classify_audit_row(value) + leaf = path[-1].lower() if path else "" + if leaf in STATUS_KEYS or leaf.endswith("_boundary") or leaf.endswith("_status"): + return "status" + if isinstance(value, str) and _norm(value) == "not_applicable": + return "not_applicable" + return "core" + + +def _whole(path: tuple[str, ...], value: Any) -> str | None: + joined = ".".join(path).lower() + if joined.endswith("western_spectrum"): + return "western" + if joined.endswith("research_dn") or joined.endswith("extended") and "varga_spectrum" in joined: + return "research" + if joined.endswith("methodology") or joined.endswith("presentation") or joined.endswith("rectification"): + return "status" + if ( + isinstance(value, dict) + and "technique" in value + and "status" in value + and any(part == "technique_audit_table" for part in path) + ): + return classify_audit_row(value) + return None + + +def _dominant(sizes: Counter[str]) -> str: + if not sizes: + return "status" + return max(CATEGORIES, key=lambda name: (sizes.get(name, 0), -CATEGORIES.index(name))) + + +def account(value: Any, path: tuple[str, ...] = ()) -> Counter[str]: + """Partition dumps(value) across the five categories. Sum equals len(dumps(value)).""" + whole = _whole(path, value) + if whole is not None: + return Counter({whole: len(dumps(value))}) + if isinstance(value, dict): + sizes: Counter[str] = Counter() + if not value: + sizes[classify(path, value)] = 2 + return sizes + items = list(value.items()) + for index, (key, child) in enumerate(items): + child_path = path + (str(key),) + child_sizes = account(child, child_path) + sizes.update(child_sizes) + overhead = len(dumps(str(key))) + 1 + if index: + overhead += 1 + sizes[_dominant(child_sizes)] += overhead + sizes[_dominant(sizes)] += 2 + return sizes + if isinstance(value, list): + sizes = Counter() + if not value: + sizes[classify(path, value)] = 2 + return sizes + for index, child in enumerate(value): + child_sizes = account(child, path + (str(index),)) + sizes.update(child_sizes) + if index: + sizes[_dominant(child_sizes)] += 1 + sizes[_dominant(sizes)] += 2 + return sizes + return Counter({classify(path, value): len(dumps(value))}) + + +def category_report(value: Any) -> dict[str, Any]: + sizes = account(value) + total = len(dumps(value)) + covered = sum(sizes[name] for name in CATEGORIES) + return { + "categories": {name: int(sizes.get(name, 0)) for name in CATEGORIES}, + "total_chars": total, + "category_sum": covered, + "sum_error_ratio": 0.0 if total == 0 else abs(covered - total) / total, + "tokens": estimate_tokens(dumps(value)), + } + + +def duplicate_report(model_context: dict[str, Any]) -> dict[str, Any]: + consultations = model_context.get("consultations") + first = consultations[0] if isinstance(consultations, list) and consultations else None + spread_keys = [ + key for key in (first or {}) + if key in model_context and key != "consultations" + ] + matching = [ + key for key in spread_keys + if dumps(model_context.get(key)) == dumps(first.get(key)) + ] + named_copies: dict[str, int] = {} + + def walk(node: Any, path: tuple[str, ...] = ()) -> None: + if isinstance(node, dict): + for key, child in node.items(): + leaf = str(key) + if leaf in {"varga_spectrum", "western_spectrum", "technique_audit_table", "methodology"}: + named_copies[leaf] = named_copies.get(leaf, 0) + 1 + walk(child, path + (leaf,)) + elif isinstance(node, list): + for index, child in enumerate(node): + walk(child, path + (str(index),)) + + walk(model_context) + consultation_chars = len(dumps(consultations)) if consultations is not None else 0 + return { + "consultation_copies": 1 + (1 if isinstance(first, dict) else 0), + "spread_keys_matching_consultations_0": matching, + "consultations_chars": consultation_chars, + "named_subtree_copies": named_copies, + } + + +def load_public_charts(root: Path) -> list[dict[str, Any]]: + charts = [] + for spec in CHART_SOURCES: + payload = json.loads((root / spec["path"]).read_text(encoding="utf-8")) + case = next(item for item in payload["cases"] if item["case_id"] == spec["case_id"]) + birth = case["birth"] + year, month, day = (int(part) for part in birth["date"].split("-")) + hour, minute = (int(part) for part in birth["time"].split(":")[:2]) + charts.append({ + "id": spec["id"], + "label": spec["label"], + "source": spec["path"], + "case_id": spec["case_id"], + "rodden_rating": (birth.get("source") or {}).get("rodden_rating"), + "place": birth.get("place"), + "body": { + "year": year, + "month": month, + "day": day, + "hour": hour, + "minute": minute, + "second": 0, + "lat": birth["latitude"], + "lon": birth["longitude"], + "tz": birth["timezone_offset"], + "city": birth.get("place") or spec["label"], + "ayanamsa": AYANAMSA, + "node_mode": NODE_MODE, + "today": REFERENCE_DATE, + "entry_mode": "direct_chart", + "defer_optional_external_evidence": True, + "declared_accuracy": "minute", + "birth_time_accuracy": "confirmed", + }, + }) + return charts + + +def _dig(value: Any, *keys: str) -> Any: + current = value + for key in keys: + if not isinstance(current, dict) or key not in current: + return None + current = current[key] + return current + + +def claim_evidence(model_context: dict[str, Any], category: str) -> dict[str, Any]: + cards = model_context.get("claim_cards") + if not isinstance(cards, list): + return {} + for card in cards: + if isinstance(card, dict) and card.get("category") == category and isinstance(card.get("evidence"), dict): + return card["evidence"] + return {} + + +def _house_entry(houses: Any, number: int) -> Any: + if isinstance(houses, dict): + for key in (str(number), f"house_{number}", f"h{number}"): + if key in houses: + return houses[key] + for value in houses.values(): + if isinstance(value, dict) and value.get("number") == number: + return value + if isinstance(houses, list): + for value in houses: + if isinstance(value, dict) and value.get("number") == number: + return value + if 1 <= number <= len(houses): + return houses[number - 1] + return None + + +def _pick(mapping: Any, names: list[str]) -> dict[str, Any]: + if not isinstance(mapping, dict): + return {} + lowered = {str(key).lower(): key for key in mapping} + picked = {} + for name in names: + key = lowered.get(name.lower()) + if key is not None: + picked[str(key)] = mapping[key] + return picked + + +def cut_evidence_card(model_context: dict[str, Any], question_id: str) -> dict[str, Any]: + """Copy card fields from the projected model context. Missing paths stay gaps.""" + spec = CARD_SPECS[question_id] + natal = claim_evidence(model_context, "natal_foundation") + timing = claim_evidence(model_context, "timing") + spectrum = natal.get("varga_spectrum") if isinstance(natal.get("varga_spectrum"), dict) else {} + formal = spectrum.get("formal") if isinstance(spectrum.get("formal"), dict) else {} + houses = natal.get("houses") + planets = natal.get("planets") if isinstance(natal.get("planets"), dict) else {} + functional = natal.get("functional_benefic_malefic") + dasha = timing.get("dasha_sub_periods") if isinstance(timing.get("dasha_sub_periods"), dict) else timing.get("dasha") + narayana = timing.get("narayana_dasha") + gaps = [] + vargas = {} + for code in spec["vargas"]: + chart = formal.get(code) + if chart is None: + gaps.append(f"varga:{code}") + else: + vargas[code] = chart + house_rows = {} + for number in spec["houses"]: + row = _house_entry(houses, number) + if row is None: + gaps.append(f"house:{number}") + else: + house_rows[str(number)] = row + picked_planets = _pick(planets, spec["planets"]) + for name in spec["planets"]: + if name.lower() not in {key.lower() for key in picked_planets}: + gaps.append(f"planet:{name}") + card = { + "card_id": question_id, + "label": spec["label"], + "question": model_context.get("question"), + "route": model_context.get("route"), + "base": { + "ascendant": natal.get("ascendant"), + "houses": houses, + "planet_placements": _planet_placements(planets), + "functional_benefic_malefic": functional, + "vimshottari": dasha, + "narayana_dasha": narayana, + }, + "domain": { + "vargas": vargas, + "houses": house_rows, + "planets": picked_planets, + "arudha": _pick(natal.get("arudha_padas"), spec["arudha"]), + "karakas": _pick(_dig(natal, "jaimini", "chara_karakas") or natal.get("chara_karakas"), spec["karakas"]), + "yogas": natal.get("yogas") if spec["yogas"] else None, + "transits": timing.get("transits") if spec["transits"] else None, + "ashtakavarga": natal.get("ashtakavarga") if spec["ashtakavarga"] else None, + "shadbala": natal.get("shadbala") if spec["shadbala"] else None, + }, + "gaps": gaps, + "basis": spec.get("basis", []), + } + if card["base"]["ascendant"] is None: + gaps.append("ascendant") + if functional is None: + gaps.append("functional_benefic_malefic") + if dasha is None: + gaps.append("vimshottari") + if narayana is None: + gaps.append("narayana_dasha") + text = dumps(card) + return {"card": card, "text": text, "size": estimate_tokens(text), "gaps": gaps} + + +def _ci_get(mapping: Any, name: str) -> Any: + if not isinstance(mapping, dict): + return None + for key, value in mapping.items(): + if str(key).lower() == name.lower(): + return value + return None + + +def _planet_placements(planets: Any) -> dict[str, Any]: + if not isinstance(planets, dict): + return {} + placed = {} + for name, row in planets.items(): + if isinstance(row, dict): + placed[str(name)] = { + key: row[key] for key in ("sign", "house") if key in row + } + elif isinstance(row, str): + placed[str(name)] = {"sign": row} + return placed + + +def engine_facts(workflow: dict[str, Any]) -> dict[str, Any]: + chart = workflow.get("chart") if isinstance(workflow.get("chart"), dict) else {} + modules = chart.get("modules") if isinstance(chart.get("modules"), dict) else {} + ascendant = chart.get("ascendant") if isinstance(chart.get("ascendant"), dict) else {} + planets = chart.get("planets") if isinstance(chart.get("planets"), dict) else {} + moon = _ci_get(planets, "moon") + moon = moon if isinstance(moon, dict) else {} + sub = modules.get("dasha_sub_periods") if isinstance(modules.get("dasha_sub_periods"), dict) else {} + current = sub.get("current") if isinstance(sub.get("current"), dict) else {} + mahadasha = current.get("mahadasha") if isinstance(current.get("mahadasha"), dict) else {} + antardasha = current.get("antardasha") if isinstance(current.get("antardasha"), dict) else {} + pratyantar = sub.get("pratyantar_dasha_timeline") if isinstance(sub.get("pratyantar_dasha_timeline"), dict) else {} + pratyantar_current = pratyantar.get("current") if isinstance(pratyantar.get("current"), dict) else {} + narayana = modules.get("narayana_dasha") if isinstance(modules.get("narayana_dasha"), dict) else {} + narayana_current = narayana.get("current_dasha") if isinstance(narayana.get("current_dasha"), dict) else {} + narayana_md = narayana_current.get("md") if isinstance(narayana_current.get("md"), dict) else {} + spectrum = modules.get("varga_spectrum") if isinstance(modules.get("varga_spectrum"), dict) else {} + formal = spectrum.get("formal") if isinstance(spectrum.get("formal"), dict) else {} + d12 = formal.get("D12") if isinstance(formal.get("D12"), dict) else {} + return { + "ascendant_sign": ascendant.get("sign"), + "moon_sign": moon.get("sign"), + "moon_house": moon.get("house"), + "vimshottari_lord": mahadasha.get("lord"), + "vimshottari_start": mahadasha.get("start"), + "vimshottari_end": mahadasha.get("end"), + "antardasha_start": antardasha.get("start"), + "antardasha_end": antardasha.get("end"), + "pratyantar_start": pratyantar_current.get("start"), + "pratyantar_end": pratyantar_current.get("end"), + "narayana_sign": narayana_md.get("sign"), + "d12_lagna": d12.get("lagna") if isinstance(d12.get("lagna"), str) else None, + "d12_moon": _ci_get(d12.get("planets"), "moon") if isinstance(d12.get("planets"), dict) else None, + } + + +def card_facts(card: dict[str, Any]) -> dict[str, Any]: + base = card.get("base") if isinstance(card.get("base"), dict) else {} + domain = card.get("domain") if isinstance(card.get("domain"), dict) else {} + ascendant = base.get("ascendant") if isinstance(base.get("ascendant"), dict) else {} + moon = _ci_get(base.get("planet_placements"), "moon") + if not isinstance(moon, dict): + moon = _ci_get(domain.get("planets"), "moon") + moon = moon if isinstance(moon, dict) else {} + sub = base.get("vimshottari") if isinstance(base.get("vimshottari"), dict) else {} + current = sub.get("current") if isinstance(sub.get("current"), dict) else {} + mahadasha = current.get("mahadasha") if isinstance(current.get("mahadasha"), dict) else {} + antardasha = current.get("antardasha") if isinstance(current.get("antardasha"), dict) else {} + pratyantar = sub.get("pratyantar_dasha_timeline") if isinstance(sub.get("pratyantar_dasha_timeline"), dict) else {} + pratyantar_current = pratyantar.get("current") if isinstance(pratyantar.get("current"), dict) else {} + narayana = base.get("narayana_dasha") if isinstance(base.get("narayana_dasha"), dict) else {} + narayana_current = narayana.get("current_dasha") if isinstance(narayana.get("current_dasha"), dict) else {} + narayana_md = narayana_current.get("md") if isinstance(narayana_current.get("md"), dict) else {} + d12 = (domain.get("vargas") or {}).get("D12") if isinstance(domain.get("vargas"), dict) else None + d12 = d12 if isinstance(d12, dict) else {} + return { + "ascendant_sign": ascendant.get("sign"), + "moon_sign": moon.get("sign"), + "moon_house": moon.get("house"), + "vimshottari_lord": mahadasha.get("lord"), + "vimshottari_start": mahadasha.get("start"), + "vimshottari_end": mahadasha.get("end"), + "antardasha_start": antardasha.get("start"), + "antardasha_end": antardasha.get("end"), + "pratyantar_start": pratyantar_current.get("start"), + "pratyantar_end": pratyantar_current.get("end"), + "narayana_sign": narayana_md.get("sign"), + "d12_lagna": d12.get("lagna"), + "d12_moon": _ci_get(d12.get("planets"), "moon"), + } + + +def verbatim_check(card: dict[str, Any], facts: dict[str, Any]) -> dict[str, Any]: + actual = card_facts(card) + has_d12 = isinstance((card.get("domain") or {}).get("vargas"), dict) and "D12" in card["domain"]["vargas"] + checks = {} + for key, expected in facts.items(): + if key.startswith("d12_") and not has_d12: + checks[key] = {"status": "not_on_card", "expected": expected, "actual": None} + continue + got = actual.get(key) + if expected is None or expected == "": + checks[key] = {"status": "engine_missing", "expected": None, "actual": got} + elif got == expected: + checks[key] = {"status": "match", "expected": expected, "actual": got} + else: + checks[key] = {"status": "mismatch", "expected": expected, "actual": got} + mismatched = [key for key, row in checks.items() if row["status"] == "mismatch"] + return {"ok": not mismatched, "checks": checks, "mismatched": mismatched} + + +def parse_registry_layers(source: str) -> dict[str, list[str]]: + found = {} + for match in re.finditer(r'id: "(\w+)".*?requiredLayers: \[([^\]]*)\]', source): + layers = re.findall(r'"([^"]+)"', match.group(2)) + found[match.group(1)] = layers + return found + + +def parse_methodology_routes(source: str) -> dict[str, str | None]: + found = {} + for match in re.finditer(r'(\w+): \{ strictRoute: (?:"([^"]+)"|null)', source): + found[match.group(1)] = match.group(2) + return found + + +def parse_must_use_layers(source: str) -> dict[str, list[str]]: + block = re.search(r"DOMAIN_MUST_USE_LAYERS[\s\S]*?};", source) + if not block: + return {} + found = {} + for match in re.finditer(r'(\w+): \[([^\]]*)\]', block.group(0)): + found[match.group(1)] = re.findall(r'"([^"]+)"', match.group(2)) + return found + + +def source_matrix(root: Path) -> dict[str, Any]: + registry = parse_registry_layers((root / "frontend/src/lib/consultation-domain-registry.ts").read_text(encoding="utf-8")) + methodology = parse_methodology_routes((root / "frontend/src/lib/consultation-methodology.ts").read_text(encoding="utf-8")) + must_use = parse_must_use_layers((root / "frontend/src/mastra/consultation-workflow.ts").read_text(encoding="utf-8")) + from unified_consultation_orchestrator import UnifiedConsultationOrchestrator + + python_routes = { + name: list(route.focus_techniques) + for name, route in UnifiedConsultationOrchestrator._ROUTE_DEFINITIONS.items() + } + domains = sorted(set(registry) | set(methodology) | set(python_routes) | set(CARD_SPECS)) + rows = [] + for domain in domains: + card_id = domain if domain in CARD_SPECS else None + rows.append({ + "domain": domain, + "registry_required_layers": registry.get(domain, []), + "methodology_strict_route": methodology.get(domain), + "ts_must_use_layers": must_use.get(domain, []), + "python_focus_techniques": python_routes.get(domain, []), + "card_vargas": CARD_SPECS.get(card_id, {}).get("vargas", []) if card_id else [], + "parents_children_split": domain == "family", + }) + return {"domains": rows, "skill_citations": { + "d12_family": "references/strict-workflow-router.md: D12 for family/ancestral themes", + "d7_children": "references/strict-workflow-router.md: D7 for children", + "decision_tree_parents": "references/birth-time-rectification-decision-tree.md: 父母/家族 -> D12", + "decision_tree_children": "references/birth-time-rectification-decision-tree.md: 子女/生育 -> D7", + }} + + +def part_b_coverage(card: dict[str, Any], question_id: str) -> dict[str, Any]: + base = card.get("base") if isinstance(card.get("base"), dict) else {} + domain = card.get("domain") if isinstance(card.get("domain"), dict) else {} + spec = CARD_SPECS[question_id] + present = { + "functional_benefic_malefic": base.get("functional_benefic_malefic") is not None, + "vimshottari": base.get("vimshottari") is not None, + "narayana": base.get("narayana_dasha") is not None, + "ascendant_raw": base.get("ascendant") is not None, + "domain_vargas": sorted(domain.get("vargas") or {}), + "expected_vargas": spec["vargas"], + } + missing_vargas = [code for code in spec["vargas"] if code not in (domain.get("vargas") or {})] + return { + "dual_dasha": present["vimshottari"] and present["narayana"], + "domain_divisional": not missing_vargas, + "functional_benefic_malefic": present["functional_benefic_malefic"], + "raw_data": present["ascendant_raw"] and present["vimshottari"], + "mevg": "kept_backstage", + "real_case_calibration": "kept_backstage", + "missing_vargas": missing_vargas, + "present": present, + } + + +TELEMETRY_SPEC = { + "stores": "numbers, enums, and field names only", + "does_not_store": [ + "question text", + "answer text", + "birth date", + "birth time", + "birth place", + "name", + "email", + "user id", + "session id", + "matched substring", + ], + "fields": [ + {"name": "domain", "type": "enum", "values": [item["id"] for item in QUESTIONS]}, + {"name": "card_version", "type": "enum", "values": ["evidence-card-draft-20260927"]}, + {"name": "card_chars", "type": "int"}, + {"name": "card_token_estimate", "type": "int"}, + {"name": "cited_field_ids", "type": "enum[]", "note": "ids from the card schema, not free text"}, + {"name": "feedback", "type": "enum", "values": ["up", "down", "none"]}, + ], + "citation_method": { + "rule": "A field is cited when its scalar value appears in the answer and the value is an ISO date, a degree token, or a compound planet-in-sign phrase of at least 8 characters. Bare planet or sign names are not counted.", + "false_positive": "A date or degree that also appears in the question, or a repeated stock phrase, can be counted without the model using that field.", + "false_negative": "A paraphrase that names the period without copying the date is not counted.", + "stored": "Only the field id. The matched text is discarded.", + }, + "aggregates": [ + "count of answers by domain and card_version", + "fields whose cited rate stays under 5 percent after 30 answers in that domain", + "down rate by domain and card_version", + ], +} + + +def card_dependencies(question_id: str) -> list[str]: + spec = CARD_SPECS[question_id] + modules = ["compute_chart", "functional_benefic_malefic", "dasha_sub_periods", "narayana_dasha"] + if spec["vargas"]: + modules.append("varga_requested_only") + if spec["arudha"] or spec["karakas"]: + modules.append("arudha_padas") + if spec["karakas"]: + modules.append("chara_karakas") + if spec["transits"]: + modules.append("transits") + if spec["ashtakavarga"]: + modules.append("ashtakavarga") + if spec["shadbala"]: + modules.append("shadbala") + if spec["yogas"]: + modules.append("yogas") + return modules diff --git a/scripts/research/consult_evidence_card_run.py b/scripts/research/consult_evidence_card_run.py new file mode 100644 index 00000000..7d009d6b --- /dev/null +++ b/scripts/research/consult_evidence_card_run.py @@ -0,0 +1,263 @@ +"""Run the consultation evidence-card inventory. Read-only toward the engine. + +External VedAstro is not called. The product foreground path still joins a +background gateway; this process replaces that join with the engine's own +blocked payload so local timing is not a network wait. Status text from that +blocked payload is what the model sees when the gateway does not return. +""" + +from __future__ import annotations + +import argparse +import json +import os +import subprocess +import sys +import time +from pathlib import Path +from typing import Any + +ROOT = Path(__file__).resolve().parents[2] +SCRIPTS = ROOT / "scripts" +RESEARCH = Path(__file__).resolve().parent +for path in (ROOT, SCRIPTS, RESEARCH): + if str(path) not in sys.path: + sys.path.insert(0, str(path)) + +from consult_evidence_card_lib import ( # noqa: E402 + QUESTIONS, + card_dependencies, + category_report, + cut_evidence_card, + duplicate_report, + engine_facts, + estimate_tokens, + load_public_charts, + part_b_coverage, + source_matrix, + verbatim_check, +) + + +def _block_external_vedastro() -> None: + import vedastro_foreground as gateway + + def start(self): + self.meta = { + "freshness": "research_not_called", + "external_vedastro": "not_called", + } + self.cached_gateway = gateway._blocked_foreground_vedastro( + reason="research_external_vedastro_not_called", + ) + self.future = None + return self + + gateway.ForegroundVedastroSession.start = start + + +def _workflow_body(chart: dict[str, Any], question: dict[str, str]) -> dict[str, Any]: + from consultation_plan_contract import PLAN_VERSION, plan_route_contract + + domain = question["domain"] + contract = plan_route_contract(domain) + if contract is None: + raise RuntimeError(f"no plan contract for {domain}") + body = dict(chart["body"]) + body.update({ + "question": question["question"], + "question_text": question["question"], + "theme": list(contract.themes), + "plan_version": PLAN_VERSION, + "strict_workflow_route": domain, + "required_layers": list(contract.required_layers), + "claim_boundary": contract.claim_boundary, + "plan_depth": "standard", + "requested_domains": list(contract.requested_domains), + "timing_horizon": None, + "precision_boundary": "server_evidence_required", + "required_evidence_categories": list(contract.required_evidence_categories), + "surface": "api_web", + }) + return body + + +def _run_workflow(body: dict[str, Any]) -> dict[str, Any]: + from jyotish_api_server import JyotishAPIHandler + + handler = JyotishAPIHandler.__new__(JyotishAPIHandler) + return handler._compute_consultation_workflow(body) + + +def _project(jobs: list[dict[str, str]], summary_path: Path) -> list[dict[str, Any]]: + spec_path = summary_path.with_suffix(".jobs.json") + spec_path.write_text(json.dumps({"items": jobs}), encoding="utf-8") + tsx = ROOT / "frontend" / "node_modules" / "tsx" / "dist" / "cli.mjs" + env = os.environ.copy() + env["JYOTISHA_PROJECT_ROOT"] = str(ROOT) + command = [ + "node", + str(tsx), + str(ROOT / "scripts" / "research" / "project_consult_model_context.ts"), + "project", + str(spec_path), + str(summary_path), + ] + completed = subprocess.run(command, cwd=ROOT, env=env, capture_output=True, text=True) + if completed.returncode != 0: + raise RuntimeError(completed.stderr[-4000:] or completed.stdout[-4000:]) + return json.loads(summary_path.read_text(encoding="utf-8")) + + +def _time_layers(chart_body: dict[str, Any]) -> dict[str, float]: + """Time local layers on one birth payload. VedAstro stays blocked.""" + from jyotish_api_server import ( + JyotishAPIHandler, + _attach_local_consultation_layers, + _build_consultation_varga_spectrum, + _custom_research_dn_chart, + _planet_longitudes, + ) + + handler = JyotishAPIHandler.__new__(JyotishAPIHandler) + timings: dict[str, float] = {} + + def elapsed(name: str, fn, *args, **kwargs): + started = time.perf_counter() + result = fn(*args, **kwargs) + timings[name] = round(time.perf_counter() - started, 4) + return result + + chart = elapsed("compute_chart", handler._compute_chart, { + **chart_body, + "skip_vedastro_main_entry_overview": True, + }) + planets = chart.get("planets") if isinstance(chart, dict) else {} + ascendant = chart.get("ascendant") if isinstance(chart, dict) else {} + elapsed("attach_local_layers", _attach_local_consultation_layers, handler, chart, chart_body, chart_body) + if isinstance(planets, dict) and isinstance(ascendant, dict) and planets and ascendant: + elapsed("varga_spectrum", _build_consultation_varga_spectrum, handler, planets, ascendant) + elapsed("shadbala", handler._compute_shadbala, {**chart_body, "planets": planets, "ascendant": ascendant}) + elapsed("ashtakavarga", handler._compute_ashtakavarga, {"planets": planets, "ascendant": ascendant}) + elapsed("functional_benefic_malefic", handler._functional_benefic_malefic_snapshot, planets, ascendant) + try: + module = __import__("divisional_charts_extended", fromlist=["DivisionalChartsCalculator"]) + calc = module.DivisionalChartsCalculator() + planet_lons = _planet_longitudes(planets) + asc_lon = float(ascendant.get("lon")) + elapsed("one_research_division", _custom_research_dn_chart, calc, planet_lons, asc_lon, 3) + except Exception as exc: + timings["one_research_division_error"] = exc.__class__.__name__ + return timings + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--out", default=str(ROOT / "docs" / "research" / "consult_evidence_card_inventory_2026_09_27.json")) + parser.add_argument("--cache", default="") + parser.add_argument("--only-chart", action="append", default=[]) + parser.add_argument("--only-question", action="append", default=[]) + parser.add_argument("--skip-timing", action="store_true") + args = parser.parse_args() + if os.environ.get("PYTHONHASHSEED") != "0": + raise SystemExit("Set PYTHONHASHSEED=0 before starting this process (ERR-111).") + + _block_external_vedastro() + cache = Path(args.cache) if args.cache else Path(os.environ.get("TEMP", ".")) / "consult-evidence-card-20260927" + cache.mkdir(parents=True, exist_ok=True) + charts = load_public_charts(ROOT) + questions = list(QUESTIONS) + if args.only_chart: + charts = [chart for chart in charts if chart["id"] in args.only_chart] + if args.only_question: + questions = [item for item in questions if item["id"] in args.only_question] + + runs = [] + jobs = [] + for chart in charts: + for question in questions: + run_id = f"{chart['id']}__{question['id']}" + workflow_path = cache / f"{run_id}.workflow.json" + started = time.perf_counter() + workflow = _run_workflow(_workflow_body(chart, question)) + wall = round(time.perf_counter() - started, 3) + workflow_path.write_text(json.dumps(workflow, ensure_ascii=False), encoding="utf-8") + projected_path = cache / f"{run_id}.model.json" + jobs.append({ + "id": run_id, + "domain": question["domain"], + "question": question["question"], + "workflow_path": str(workflow_path), + "out_path": str(projected_path), + }) + runs.append({ + "id": run_id, + "chart_id": chart["id"], + "chart_label": chart["label"], + "question_id": question["id"], + "domain": question["domain"], + "wall_seconds": wall, + "workflow_chars": workflow_path.stat().st_size, + "route": (workflow.get("routing") or {}).get("question_type"), + "focus_techniques": (workflow.get("routing") or {}).get("focus_techniques"), + "success": workflow.get("success"), + }) + print(f"{run_id} wall={wall}s route={runs[-1]['route']}", flush=True) + + summary_path = cache / "projection-summary.json" + projected = {item["id"]: item for item in _project(jobs, summary_path)} + inventory = [] + for run, job in zip(runs, jobs): + model_context = json.loads(Path(job["out_path"]).read_text(encoding="utf-8")) + workflow = json.loads(Path(job["workflow_path"]).read_text(encoding="utf-8")) + categories = category_report(model_context) + card = cut_evidence_card(model_context, run["question_id"]) + facts = engine_facts(workflow) + check = verbatim_check(card["card"], facts) + inventory.append({ + **run, + "projection": projected.get(run["id"]), + "categories": categories, + "duplicates": duplicate_report(model_context), + "card_size": card["size"], + "card_gaps": card["gaps"], + "part_b": part_b_coverage(card["card"], run["question_id"]), + "verbatim": check, + "card_dependencies": card_dependencies(run["question_id"]), + "sample_card": card["card"] if run["chart_id"] == "steve_jobs" and run["question_id"] in {"parents", "career"} else None, + }) + + timings = {} + if not args.skip_timing: + for chart in charts: + print(f"timing {chart['id']}", flush=True) + try: + timings[chart["id"]] = _time_layers(chart["body"]) + except Exception as exc: + timings[chart["id"]] = {"error": exc.__class__.__name__, "message": str(exc)[:300]} + + payload = { + "baseline": "76924e3362c0a47d9d8de896c448c66055826f70", + "reference_date": "2026-09-27", + "ayanamsa": "raman", + "node_mode": "mean", + "pythonhashseed": "0", + "external_vedastro": "not_called", + "token_method": estimate_tokens("")["token_method"], + "charts": [ + {"id": chart["id"], "label": chart["label"], "source": chart["source"], "case_id": chart["case_id"], "rodden_rating": chart["rodden_rating"]} + for chart in load_public_charts(ROOT) + ], + "source_matrix": source_matrix(ROOT), + "runs": inventory, + "layer_timings_seconds": timings, + } + out = Path(args.out) + out.parent.mkdir(parents=True, exist_ok=True) + out.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") + print(f"wrote {out}", flush=True) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/research/consult_evidence_card_time.py b/scripts/research/consult_evidence_card_time.py new file mode 100644 index 00000000..829b4483 --- /dev/null +++ b/scripts/research/consult_evidence_card_time.py @@ -0,0 +1,88 @@ +"""Time local consultation layers on the real workflow path. No VedAstro network.""" + +from __future__ import annotations + +import json +import os +import sys +import time +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +sys.path[:0] = [str(ROOT), str(ROOT / "scripts"), str(ROOT / "scripts" / "research")] + +from consult_evidence_card_lib import QUESTIONS, load_public_charts # noqa: E402 +import consult_evidence_card_run as runner # noqa: E402 +import jyotish_api_server as api # noqa: E402 + + +def _wrap(bucket: dict[str, float], name: str, fn): + def inner(*args, **kwargs): + started = time.perf_counter() + try: + return fn(*args, **kwargs) + finally: + bucket[name] = round(bucket.get(name, 0.0) + time.perf_counter() - started, 4) + return inner + + +def main() -> int: + if os.environ.get("PYTHONHASHSEED") != "0": + raise SystemExit("Set PYTHONHASHSEED=0") + runner._block_external_vedastro() + charts = load_public_charts(ROOT) + question = QUESTIONS[0] + results = {} + originals = { + "compute_chart": api.JyotishAPIHandler._compute_chart, + "thematic": api.JyotishAPIHandler._compute_thematic_report, + "rectification": api.JyotishAPIHandler._compute_rectification_gate, + "attach": api._attach_local_consultation_layers, + "varga_spectrum": api._build_consultation_varga_spectrum, + "research_chart": api._custom_research_dn_chart, + "varga_full": api.JyotishAPIHandler._compute_varga_full, + } + for chart in charts: + bucket: dict[str, float] = {} + calls = {"research_chart": 0} + + def counting_research(*args, **kwargs): + calls["research_chart"] += 1 + return originals["research_chart"](*args, **kwargs) + + api.JyotishAPIHandler._compute_chart = _wrap(bucket, "compute_chart", originals["compute_chart"]) + api.JyotishAPIHandler._compute_thematic_report = _wrap(bucket, "thematic_report", originals["thematic"]) + api.JyotishAPIHandler._compute_rectification_gate = _wrap(bucket, "rectification_gate", originals["rectification"]) + api._attach_local_consultation_layers = _wrap(bucket, "attach_local_layers", originals["attach"]) + api._build_consultation_varga_spectrum = _wrap(bucket, "varga_spectrum", originals["varga_spectrum"]) + api._custom_research_dn_chart = _wrap(bucket, "research_dn_loop", counting_research) + api.JyotishAPIHandler._compute_varga_full = _wrap(bucket, "varga_full", originals["varga_full"]) + started = time.perf_counter() + runner._run_workflow(runner._workflow_body(chart, question)) + bucket["workflow_wall"] = round(time.perf_counter() - started, 4) + bucket["research_dn_calls"] = calls["research_chart"] + results[chart["id"]] = bucket + print(chart["id"], bucket, flush=True) + for name, fn in originals.items(): + if name == "compute_chart": + api.JyotishAPIHandler._compute_chart = fn + elif name == "thematic": + api.JyotishAPIHandler._compute_thematic_report = fn + elif name == "rectification": + api.JyotishAPIHandler._compute_rectification_gate = fn + elif name == "attach": + api._attach_local_consultation_layers = fn + elif name == "varga_spectrum": + api._build_consultation_varga_spectrum = fn + elif name == "research_chart": + api._custom_research_dn_chart = fn + elif name == "varga_full": + api.JyotishAPIHandler._compute_varga_full = fn + out = ROOT / "docs" / "research" / "consult_evidence_card_timings_2026_09_27.json" + out.write_text(json.dumps(results, indent=2), encoding="utf-8") + print(f"wrote {out}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/research/project_consult_model_context.ts b/scripts/research/project_consult_model_context.ts new file mode 100644 index 00000000..888eb68a --- /dev/null +++ b/scripts/research/project_consult_model_context.ts @@ -0,0 +1,107 @@ +/** + * Read-only projection of a consultation workflow payload into the text the + * answer model sees. Does not modify frontend runtime files. + * + * The single-domain wrap matches consultation-tools.ts toModelDomainPlanContext + * when consultations.length === 1 and omittedDomains.length === 0: + * return { ...consultations[0], ...plan, consultations }; + */ +import { readFileSync, writeFileSync } from "node:fs"; +import { createConsultationPlan } from "../../frontend/src/lib/consultation-plan.ts"; +import { consultationMethodologyForDomains } from "../../frontend/src/lib/consultation-methodology.ts"; +import type { ConsultationDomain } from "../../frontend/src/lib/consultation-domain-registry.ts"; +import { + consultationWorkflowResponseSchema, + toAgentConsultationContext, + toModelOutput, +} from "../../frontend/src/mastra/consultation-workflow.ts"; + +type JsonRecord = Record; + +function readJson(path: string): JsonRecord { + return JSON.parse(readFileSync(path, "utf8")) as JsonRecord; +} + +function planFields(domain: ConsultationDomain, question: string) { + const plan = createConsultationPlan({ + userIntent: question, + theme: domain, + consultationMode: "verified_chart", + }); + return { + plan_version: plan.plan_version, + depth: plan.depth, + requested_domains: plan.requestedDomains, + timing_horizon: plan.timingHorizon, + precision_boundary: plan.precisionBoundary, + required_evidence_categories: plan.requiredEvidenceCategories, + birthTimeMode: plan.birthTimeMode, + }; +} + +function projectOne(workflow: JsonRecord, domain: ConsultationDomain, question: string) { + const parsed = consultationWorkflowResponseSchema.safeParse(workflow); + const agentContext = toAgentConsultationContext(parsed.success ? parsed.data : workflow); + const consultationPlan = createConsultationPlan({ + userIntent: question, + theme: domain, + consultationMode: "verified_chart", + }); + const modelOutput = toModelOutput(agentContext, consultationPlan); + const consultation = { domain, ...modelOutput }; + const methodology = consultationMethodologyForDomains([domain]); + const plan = { + success: agentContext.success === true, + domains: [domain], + omitted_domains: [] as ConsultationDomain[], + ...(methodology ? { methodology } : {}), + }; + const modelContext = { ...consultation, ...plan, consultations: [consultation] }; + return { + schema_ok: parsed.success, + schema_error: parsed.success ? null : parsed.error.issues.slice(0, 8).map((issue) => ({ + path: issue.path.join("."), + code: issue.code, + })), + methodology_sections: methodology?.sections.length ?? 0, + methodology_chars: methodology + ? JSON.stringify(methodology).length + : 0, + model_context: modelContext, + }; +} + +const [mode, ...rest] = process.argv.slice(2); + +if (mode === "plans") { + const spec = readJson(rest[0]); + const questions = spec.questions as Array<{ id: string; domain: ConsultationDomain; question: string }>; + const plans: JsonRecord = {}; + for (const item of questions) { + plans[item.id] = planFields(item.domain, item.question); + } + writeFileSync(rest[1], JSON.stringify(plans)); +} else if (mode === "project") { + const jobs = readJson(rest[0]) as { + items: Array<{ id: string; domain: ConsultationDomain; question: string; workflow_path: string; out_path: string }>; + }; + const summary: JsonRecord[] = []; + for (const item of jobs.items) { + const workflow = readJson(item.workflow_path); + const projected = projectOne(workflow, item.domain, item.question); + const text = JSON.stringify(projected.model_context); + writeFileSync(item.out_path, text); + summary.push({ + id: item.id, + schema_ok: projected.schema_ok, + schema_error: projected.schema_error, + methodology_sections: projected.methodology_sections, + methodology_chars: projected.methodology_chars, + model_chars: text.length, + }); + } + writeFileSync(rest[1], JSON.stringify(summary)); +} else { + process.stderr.write("usage: plans | project \n"); + process.exit(2); +} diff --git a/tests/test_consult_evidence_card_research.py b/tests/test_consult_evidence_card_research.py new file mode 100644 index 00000000..f2c895df --- /dev/null +++ b/tests/test_consult_evidence_card_research.py @@ -0,0 +1,127 @@ +"""Pure-function checks for the consultation evidence-card research scripts.""" + +from __future__ import annotations + +import sys +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +sys.path.insert(0, str(ROOT / "scripts" / "research")) + +from consult_evidence_card_lib import ( # noqa: E402 + CARD_SPECS, + CATEGORIES, + TELEMETRY_SPEC, + account, + category_report, + cut_evidence_card, + dumps, + parse_methodology_routes, + parse_must_use_layers, + parse_registry_layers, + verbatim_check, +) + + +def test_category_partition_sums_exactly(): + payload = { + "ascendant": {"sign": "Leo", "degree": 12.5}, + "methodology": {"sections": ["checklist"]}, + "western_spectrum": {"zodiac": "tropical", "natal": {"sun": "Aries"}}, + "varga_spectrum": { + "formal": {"D1": {"lagna": "Leo"}}, + "research_dn": {"D3": {"lagna": "Virgo"}}, + "extended": {"D81": {"lagna": "Cancer"}}, + }, + "technique_audit_table": [ + {"technique": "Functional Benefic/Malefic", "status": "executed"}, + {"technique": "MEVG / Global Web Evidence", "status": "blocked"}, + {"technique": "Prashna chart", "status": "not_applicable"}, + {"technique": "Research D-N through D60", "status": "executed"}, + {"technique": "Western natal (tropical)", "status": "executed", "system": "western"}, + ], + } + report = category_report(payload) + assert report["sum_error_ratio"] == 0.0 + assert report["category_sum"] == report["total_chars"] == len(dumps(payload)) + assert set(report["categories"]) == set(CATEGORIES) + assert report["categories"]["western"] > 0 + assert report["categories"]["research"] > 0 + assert report["categories"]["status"] > 0 + assert report["categories"]["not_applicable"] > 0 + assert report["categories"]["core"] > 0 + assert sum(account(payload).values()) == len(dumps(payload)) + + +def test_card_copies_projection_values_without_rewriting(): + model = { + "question": "我和父母关系如何", + "route": "family", + "claim_cards": [ + { + "category": "natal_foundation", + "evidence": { + "ascendant": {"sign": "Capricorn", "degree": 3.25}, + "houses": [{"number": 4, "sign": "Aries", "lord": "Mars"}], + "planets": {"sun": {"sign": "Aquarius", "house": 2}, "moon": {"sign": "Cancer", "house": 7}}, + "functional_benefic_malefic": {"functional_benefics": ["Venus"], "functional_malefics": ["Mars"]}, + "varga_spectrum": {"formal": {"D12": {"lagna": "Pisces", "planets": {"moon": "Leo"}}}}, + }, + }, + { + "category": "timing", + "evidence": { + "dasha_sub_periods": { + "current": { + "mahadasha": {"lord": "Saturn", "start": "2020-01-01", "end": "2026-12-31"}, + "antardasha": {"lord": "Mercury", "start": "2024-01-01", "end": "2025-01-01"}, + }, + }, + "narayana_dasha": {"current_dasha": {"md": {"sign": "Scorpio"}}}, + }, + }, + ], + } + cut = cut_evidence_card(model, "parents") + assert cut["card"]["domain"]["vargas"]["D12"]["lagna"] == "Pisces" + assert cut["card"]["base"]["ascendant"]["degree"] == 3.25 + assert "D7" not in cut["card"]["domain"]["vargas"] + check = verbatim_check(cut["card"], { + "ascendant_sign": "Capricorn", + "d12_lagna": "Pisces", + "d12_moon": "Leo", + "vimshottari_start": "2020-01-01", + "vimshottari_end": "2026-12-31", + "moon_sign": "Cancer", + "moon_house": 7, + }) + assert check["ok"] is True + assert check["checks"]["vimshottari_start"]["status"] == "match" + + +def test_source_parsers_keep_family_split_gap(): + registry = (ROOT / "frontend/src/lib/consultation-domain-registry.ts").read_text(encoding="utf-8") + methodology = (ROOT / "frontend/src/lib/consultation-methodology.ts").read_text(encoding="utf-8") + workflow = (ROOT / "frontend/src/mastra/consultation-workflow.ts").read_text(encoding="utf-8") + layers = parse_registry_layers(registry) + routes = parse_methodology_routes(methodology) + must_use = parse_must_use_layers(workflow) + assert "D12" in layers["family"] and "D7" in layers["family"] + assert "父母" not in "".join(layers["family"]) + assert routes["family"] is None + assert "family" not in must_use + assert CARD_SPECS["parents"]["vargas"] == ["D12"] + assert CARD_SPECS["children"]["vargas"] == ["D7"] + + +def test_telemetry_spec_stores_no_user_text(): + banned = {"question text", "answer text", "birth date", "name", "email", "user id"} + assert banned <= set(TELEMETRY_SPEC["does_not_store"]) + stored = {field["name"] for field in TELEMETRY_SPEC["fields"]} + assert stored == {"domain", "card_version", "card_chars", "card_token_estimate", "cited_field_ids", "feedback"} + assert "matched substring" in TELEMETRY_SPEC["does_not_store"] + + +def test_single_domain_wrap_source_still_matches_projector(): + source = (ROOT / "frontend/src/mastra/consultation-tools.ts").read_text(encoding="utf-8") + assert "return { ...consultations[0], ...plan, consultations };" in source