diff --git a/docs/research/gender_interpretation_contract_2026_07_19.md b/docs/research/gender_interpretation_contract_2026_07_19.md new file mode 100644 index 00000000..b6413f1d --- /dev/null +++ b/docs/research/gender_interpretation_contract_2026_07_19.md @@ -0,0 +1,72 @@ +# Gender interpretation contract — 2026-07-19 + +本合同只管解释层;不改变星盘计算。 + +## 总原则 + +- 性别不改变 D1、分盘、Dasha、Shadbala、Ashtakavarga、Yoga、Ayanamsa、Node mode。 +- 性别只能在婚恋/配偶/婚姻应期加权、生育语境表达里作为辅助层。 +- 不能只靠“男金女木”下婚恋结论。 + +## 婚恋/配偶 + +基础栈性别中立: + +- 7宫 +- 7宫主 +- D9 +- UL +- Darakaraka + +性别辅助层: + +- 男命增强 Venus。 +- 女命增强 Jupiter/Mars。 +- `nonbinary`、`prefer_not_to_say` 或缺失时,使用性别中立栈,不强行套二元规则。 + +## 婚姻应期 + +基础仍需: + +- 7宫主周期 +- D9 激活 +- UL 激活 +- DK 周期 +- Vimshottari + Narayana 交叉 + +性别只能增加权重: + +- 男命:Venus 周期/过境激活可作为补充证据。 +- 女命:Jupiter/Mars 周期/过境激活可作为补充证据。 + +禁止说:只因某个性别象征星激活,所以应期已验证。 + +## 子女/生育语境 + +基础仍是: + +- 5宫 +- 5宫主 +- Jupiter +- D7 +- Putrakaraka + +性别只用于语言和现实语境;不得给医疗、生育、怀孕保证结论。 + +## 产品字段建议 + +```ts +gender: "male" | "female" | "nonbinary" | "prefer_not_to_say" | null +``` + +文案建议: + +> 该信息仅用于传统婚恋/配偶象征星的解释加权,不改变星盘计算。 + +## 产品回答边界 + +如果 gender 缺失,不阻塞回答。只在婚恋/配偶问题里可轻问: + +> 如果你愿意,也可以补充性别;我会用传统配偶象征星再校正一次。 + +若使用 gender,必须说明它只是传统辅助象征层,不是唯一判断。 diff --git a/frontend/src/mastra/index.ts b/frontend/src/mastra/index.ts index 6b6531e7..5809eba1 100644 --- a/frontend/src/mastra/index.ts +++ b/frontend/src/mastra/index.ts @@ -174,6 +174,7 @@ When reference_transparency is present: - When similar_public_cases.coverage.requested_uncovered_domains is non-empty, say the current public-case catalog does not yet cover those themes; do not infer that no comparable real-world case exists. - When method_variants applies, present parallel methods and their source paths rather than silently picking one result as the only truth. - Treat Shadbala/Ashtakavarga component differences under production_tuning_allowed=false as method boundaries, not absolute calculation errors. Use no_majority_vote and method_variant_not_majority_vote: do not decide truth by engine count, and do not say one school is wrong unless a pinned authoritative worked example is present. +- If gender or sex is present in future profile context, use it only for relationship/spouse interpretation language and weighting: gender-specific spouse significators are supplements, not chart-calculation switches. For relationship questions, keep the core stack gender-neutral (7th house, 7th lord, D9, UL, Darakaraka); male charts may supplement Venus, female charts may supplement Jupiter/Mars, and unknown/nonbinary/prefer-not-to-say uses the gender-neutral stack. - If should_lead_with_limitations is false, do not lead with limitations. If a limitation is relevant, put it in one short sentence at the end. - Only say the chart calculation failed when hard_blockers is non-empty. - Never claim D2, D11, D9, D10, A10, UL, or Narayana Dasha is missing when it appears in available_layers, chart, or local_layers. diff --git a/frontend/tests/consultation-context.test.ts b/frontend/tests/consultation-context.test.ts index 591b6845..20d55084 100644 --- a/frontend/tests/consultation-context.test.ts +++ b/frontend/tests/consultation-context.test.ts @@ -22,6 +22,9 @@ test("passes transparent public-case references into the agent context", () => { assert.match(source, /method_variant_not_majority_vote/); assert.match(source, /Shadbala\/Ashtakavarga component differences/); assert.match(source, /D2, D11/); + assert.match(source, /gender-specific spouse significators are supplements/); + assert.match(source, /male.*Venus/); + assert.match(source, /female.*Jupiter\/Mars/); }); test("keeps strength, Ashtakavarga, and timing evidence available to the answer model", () => { diff --git a/references/oracle/gender_interpretation_contract_2026_07_19.json b/references/oracle/gender_interpretation_contract_2026_07_19.json new file mode 100644 index 00000000..e51500d6 --- /dev/null +++ b/references/oracle/gender_interpretation_contract_2026_07_19.json @@ -0,0 +1,83 @@ +{ + "contract_id": "gender_interpretation_contract_2026_07_19", + "status": "interpretation_boundary_registry", + "purpose": "Define where user gender may affect Vedic astrology interpretation without changing chart mathematics.", + "recommended_profile_field": { + "name": "gender", + "allowed_values": ["male", "female", "nonbinary", "prefer_not_to_say", null], + "product_copy": "Only used for traditional relationship/spouse significator weighting; it does not change the chart calculation." + }, + "calculation_layer_policy": { + "changes_chart_math": false, + "gender_neutral_calculations": [ + "rasi_chart", + "divisional_charts", + "vimshottari_dasha", + "narayana_dasha", + "ayanamsa", + "node_mode", + "shadbala", + "ashtakavarga", + "yoga_detection", + "functional_benefic_malefic" + ] + }, + "allowed_use_domains": [ + "relationship_spouse_interpretation", + "marriage_timing_weighting", + "children_birth_context_language" + ], + "forbidden_use_domains": [ + "career", + "wealth", + "core_personality", + "dasha_boundary_calculation", + "shadbala_component_calculation", + "ashtakavarga_bindu_calculation", + "absolute_prediction_confidence" + ], + "relationship_spouse_interpretation": { + "core_stack_gender_neutral": ["7th_house", "7th_lord", "D9", "UL", "Darakaraka"], + "gender_specific_supplements": { + "male": { + "spouse_karaka_focus": ["Venus"], + "language": "Male-chart traditional spouse significator weighting may emphasize Venus." + }, + "female": { + "spouse_karaka_focus": ["Jupiter", "Mars"], + "language": "Female-chart traditional spouse/husband significator weighting may emphasize Jupiter, with Mars used by some lineages for partner dynamics." + }, + "unknown_or_not_binary": { + "spouse_karaka_focus": [ + "7th_lord", + "D9", + "UL", + "Darakaraka", + "Venus_as_general_relationship_karaka" + ], + "language": "Use the gender-neutral relationship stack; do not force binary spouse significators." + } + }, + "hard_boundary": "gender_specific_karakas_are_supplements_not_single_factor_truth" + }, + "marriage_timing_weighting": { + "base_required": ["7th_lord_periods", "D9_activation", "UL_activation", "Darakaraka_periods", "Vimshottari_Narayana_crosscheck"], + "male_optional_weight": ["Venus_period_or_transit_activation"], + "female_optional_weight": ["Jupiter_or_Mars_period_or_transit_activation"], + "forbidden_claim": "Do not claim a marriage window is verified solely because a gender-specific karaka is active." + }, + "children_birth_context_language": { + "base_required": ["5th_house", "5th_lord", "Jupiter", "D7", "Putrakaraka"], + "safety_boundary": "Use gender only for context language. Do not make medical, pregnancy, fertility, or guaranteed child-birth claims." + }, + "answer_policy": { + "if_gender_missing": "Do not block. Answer from gender-neutral stack and optionally ask for gender only when relationship/spouse interpretation materially depends on traditional significator weighting.", + "if_nonbinary_or_prefer_not_to_say": "Do not force binary rules. Use gender-neutral relationship stack.", + "disclosure": "If used, say it is a traditional supplementary significator layer, not the only basis of judgment." + }, + "evidence_status": { + "source_type": "traditional_rule_registry_plus_local_methodology", + "normative_strength": "medium", + "requires_lineage_disclosure": true + } +} diff --git a/references/relationship_gender_role_technique_registry_2026_07_19.json b/references/relationship_gender_role_technique_registry_2026_07_19.json new file mode 100644 index 00000000..2fc3423a --- /dev/null +++ b/references/relationship_gender_role_technique_registry_2026_07_19.json @@ -0,0 +1,158 @@ +{ + "scope": "relationship_gender_role_technique_registry", + "created_at": "2026-07-19", + "default_profile_policy": "neutral_partner_a_b", + "base_chart_requires_gender": false, + "production_tuning_allowed": false, + "truth_policy": "technique_registry_not_prediction_truth", + "boundary": "Gender/role fields may change relationship interpretation, role weighting, or traditional marriage-rule variants; they must not change core D1/D9/Dasha/Shadbala/AV calculation.", + "recommended_optional_fields": { + "gender": "female|male|nonbinary|unspecified", + "relationship_role_mode": "neutral_partner_a_b|traditional_gendered", + "partner_interest": "male|female|any|unspecified" + }, + "web_oss_scan": [ + { + "name": "Kerykeion", + "url": "https://github.com/g-battaglia/kerykeion", + "license": "AGPL-3.0", + "usable_boundary": "oracle/reference only unless AGPL obligations are acceptable; useful for western natal/synastry/transits/returns and relationship score surface comparison." + }, + { + "name": "Astrologer-API", + "url": "https://github.com/g-battaglia/Astrologer-API", + "license": "repository license must be checked before reuse", + "usable_boundary": "hosted/API reference for western chart/synastry/composite/returns; do not copy code without license confirmation." + }, + { + "name": "Amber-bisht/astro", + "url": "https://github.com/Amber-bisht/astro", + "license": "repository license must be checked before reuse", + "usable_boundary": "Vedic compatibility output-schema reference only until license and formula sources are verified." + }, + { + "name": "RaviKarrii/Marriage-Compatibility-Asthakoot", + "url": "https://github.com/RaviKarrii/Marriage-Compatibility-Asthakoot", + "license": "MIT", + "usable_boundary": "possible permissive Ashtakoot comparison reference after formula/source audit." + }, + { + "name": "VedAstro/VedAstro", + "url": "https://github.com/VedAstro/VedAstro", + "license": "MIT", + "usable_boundary": "Vedic API/oracle reference; hosted identity remains blocked separately." + } + ], + "techniques": [ + { + "id": "vedic_venus_jupiter_spouse_significators", + "system": "vedic", + "domain": "relationship", + "gender_dependency": "interpretation_only", + "what_changes": "Traditional readings often emphasize Venus as wife/relationship desire in male charts and Jupiter as husband/protective spouse factor in female charts; neutral mode treats Venus/Jupiter as partner-quality indicators without assigning gender.", + "local_status": "partially_present", + "integration_action": "add_interpretation_layer", + "license_boundary": "use local calculations; cite formula/source notes, do not copy AGPL prose/code.", + "claim_boundary": "interpretive weighting only; not a deterministic marriage outcome." + }, + { + "id": "vedic_kuja_manglik_role_weighting", + "system": "vedic", + "domain": "relationship", + "gender_dependency": "role_weighting", + "what_changes": "Mangal/Kuja Dosha can be judged from Lagna/Moon/Venus and compared between partners; some traditional variants weight bride/groom roles differently, while neutral mode compares both charts symmetrically.", + "local_status": "partially_present", + "integration_action": "add_interpretation_layer", + "license_boundary": "local calculation preferred; external APIs only oracle/reference.", + "claim_boundary": "dosha compatibility signal, not a standalone marriage denial." + }, + { + "id": "ashtakoot_yoni_energy_not_user_gender", + "system": "vedic", + "domain": "matching", + "gender_dependency": "traditional_rule_variant", + "what_changes": "Yoni Kuta contains male/female animal-energy assignments by nakshatra; this is not the user's biological gender and must not be mapped directly to profile gender.", + "local_status": "present", + "integration_action": "use_existing_local", + "license_boundary": "existing local Ashtakoot path; external articles only explanatory source evidence.", + "claim_boundary": "matching subscore only; do not infer gender identity." + }, + { + "id": "ashtakoot_nadi_rajju_reproductive_safety", + "system": "vedic", + "domain": "matching", + "gender_dependency": "traditional_rule_variant", + "what_changes": "Nadi/Rajju are traditionally framed around health, longevity, and childbearing risk; modern neutral mode should describe them as traditional compatibility flags.", + "local_status": "present", + "integration_action": "use_existing_local", + "license_boundary": "existing local Ashtakoot path.", + "claim_boundary": "traditional risk flag, not medical advice." + }, + { + "id": "jaimini_darakaraka_upapada_spouse_role", + "system": "vedic", + "domain": "relationship", + "gender_dependency": "interpretation_only", + "what_changes": "Darakaraka and Upapada calculations are gender-neutral; interpretive language can shift between spouse/partner role modes.", + "local_status": "present", + "integration_action": "add_interpretation_layer", + "license_boundary": "use local Jaimini implementation.", + "claim_boundary": "spouse/partner evidence layer, not exact event proof." + }, + { + "id": "d9_navamsa_gendered_interpretation_layer", + "system": "vedic", + "domain": "relationship", + "gender_dependency": "interpretation_only", + "what_changes": "D9 calculation is identical for all users; relationship interpretation may emphasize partner significators differently under traditional_gendered mode.", + "local_status": "present", + "integration_action": "add_interpretation_layer", + "license_boundary": "use local varga calculation.", + "claim_boundary": "quality/structure signal; timing still needs Dasha/transit/holdout support." + }, + { + "id": "adhana_conception_gender_sensitive_scaffold", + "system": "vedic", + "domain": "conception", + "gender_dependency": "traditional_rule_variant", + "what_changes": "Adhana/conception rules can involve gendered fertility and conception assumptions; current local module is scaffold only.", + "local_status": "scaffold", + "integration_action": "blocked_until_source_verified", + "license_boundary": "must verify classical source and avoid medical claims.", + "claim_boundary": "blocked for product interpretation; research-only." + }, + { + "id": "western_venus_mars_sun_moon_partner_projection", + "system": "western", + "domain": "relationship", + "gender_dependency": "interpretation_only", + "what_changes": "Traditional western readings may map Venus/Moon or Mars/Sun to partner preference by gender; modern neutral mode treats them as affection, desire, identity, and safety signatures.", + "local_status": "not_integrated", + "integration_action": "oracle_only", + "license_boundary": "Kerykeion is AGPL-3.0; use as oracle/reference, not copied dependency for closed commercial runtime.", + "claim_boundary": "interpretive layer only; no deterministic compatibility claim." + }, + { + "id": "western_synastry_composite_role_neutral_mode", + "system": "western", + "domain": "relationship", + "gender_dependency": "none", + "what_changes": "Synastry/composite math does not require gender; relationship role labels should be A/B unless user chooses traditional wording.", + "local_status": "partial", + "integration_action": "oracle_only", + "license_boundary": "Kerykeion/Astrologer API can guide schema; license/API boundaries required.", + "claim_boundary": "relationship dynamics map, not event proof." + }, + { + "id": "western_progressed_angles_relationship_timing", + "system": "western", + "domain": "timing", + "gender_dependency": "none", + "what_changes": "Progressed angles and returns do not need gender; only interpretation voice changes.", + "local_status": "partial", + "integration_action": "add_interpretation_layer", + "license_boundary": "use local ephemeris where available; OSS only reference unless permissive.", + "claim_boundary": "candidate timing trigger; not a verified day/month prediction until holdout passes." + } + ] +} diff --git a/tests/test_gender_interpretation_contract.py b/tests/test_gender_interpretation_contract.py new file mode 100644 index 00000000..118d01a8 --- /dev/null +++ b/tests/test_gender_interpretation_contract.py @@ -0,0 +1,57 @@ +import json +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +CONTRACT = ROOT / "references" / "oracle" / "gender_interpretation_contract_2026_07_19.json" +REPORT = ROOT / "docs" / "research" / "gender_interpretation_contract_2026_07_19.md" + + +def test_gender_contract_exists_and_is_not_a_chart_calculation_switch() -> None: + data = json.loads(CONTRACT.read_text(encoding="utf-8")) + + assert data["contract_id"] == "gender_interpretation_contract_2026_07_19" + assert data["calculation_layer_policy"]["changes_chart_math"] is False + assert "vimshottari_dasha" in data["calculation_layer_policy"]["gender_neutral_calculations"] + assert "shadbala" in data["calculation_layer_policy"]["gender_neutral_calculations"] + assert "ashtakavarga" in data["calculation_layer_policy"]["gender_neutral_calculations"] + + +def test_gender_contract_limits_gender_use_to_relationship_and_birth_contexts() -> None: + data = json.loads(CONTRACT.read_text(encoding="utf-8")) + + assert data["allowed_use_domains"] == [ + "relationship_spouse_interpretation", + "marriage_timing_weighting", + "children_birth_context_language", + ] + assert "career" in data["forbidden_use_domains"] + assert "wealth" in data["forbidden_use_domains"] + assert "core_personality" in data["forbidden_use_domains"] + + +def test_gender_contract_keeps_core_marriage_stack_gender_neutral() -> None: + data = json.loads(CONTRACT.read_text(encoding="utf-8")) + marriage = data["relationship_spouse_interpretation"] + + assert marriage["core_stack_gender_neutral"] == ["7th_house", "7th_lord", "D9", "UL", "Darakaraka"] + assert marriage["gender_specific_supplements"]["male"]["spouse_karaka_focus"] == ["Venus"] + assert marriage["gender_specific_supplements"]["female"]["spouse_karaka_focus"] == ["Jupiter", "Mars"] + assert marriage["gender_specific_supplements"]["unknown_or_not_binary"]["spouse_karaka_focus"] == [ + "7th_lord", + "D9", + "UL", + "Darakaraka", + "Venus_as_general_relationship_karaka", + ] + assert marriage["hard_boundary"] == "gender_specific_karakas_are_supplements_not_single_factor_truth" + + +def test_gender_contract_report_is_readable_and_product_safe() -> None: + text = REPORT.read_text(encoding="utf-8") + + assert "不改变星盘计算" in text + assert "男命增强 Venus" in text + assert "女命增强 Jupiter/Mars" in text + assert "不能只靠“男金女木”" in text + assert "prefer_not_to_say" in text diff --git a/tests/test_relationship_gender_role_technique_registry.py b/tests/test_relationship_gender_role_technique_registry.py new file mode 100644 index 00000000..bc9c9894 --- /dev/null +++ b/tests/test_relationship_gender_role_technique_registry.py @@ -0,0 +1,54 @@ +from __future__ import annotations + +import json +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +REGISTRY = ROOT / "references/relationship_gender_role_technique_registry_2026_07_19.json" + + +def test_relationship_gender_role_registry_keeps_gender_out_of_base_chart() -> None: + data = json.loads(REGISTRY.read_text(encoding="utf-8")) + assert data["scope"] == "relationship_gender_role_technique_registry" + assert data["default_profile_policy"] == "neutral_partner_a_b" + assert data["base_chart_requires_gender"] is False + assert data["production_tuning_allowed"] is False + assert data["truth_policy"] == "technique_registry_not_prediction_truth" + + +def test_relationship_gender_role_registry_covers_core_indian_and_western_methods() -> None: + data = json.loads(REGISTRY.read_text(encoding="utf-8")) + ids = {row["id"] for row in data["techniques"]} + for required in { + "vedic_venus_jupiter_spouse_significators", + "vedic_kuja_manglik_role_weighting", + "ashtakoot_yoni_energy_not_user_gender", + "ashtakoot_nadi_rajju_reproductive_safety", + "jaimini_darakaraka_upapada_spouse_role", + "d9_navamsa_gendered_interpretation_layer", + "adhana_conception_gender_sensitive_scaffold", + "western_venus_mars_sun_moon_partner_projection", + "western_synastry_composite_role_neutral_mode", + "western_progressed_angles_relationship_timing", + }: + assert required in ids + + +def test_relationship_gender_role_registry_marks_license_and_integration_boundaries() -> None: + data = json.loads(REGISTRY.read_text(encoding="utf-8")) + for row in data["techniques"]: + assert row["integration_action"] in { + "use_existing_local", + "add_interpretation_layer", + "oracle_only", + "blocked_until_source_verified", + } + assert row["gender_dependency"] in { + "none", + "interpretation_only", + "role_weighting", + "traditional_rule_variant", + } + assert row["license_boundary"] + assert row["claim_boundary"] +