feat: align commercial chart calculation contract

This commit is contained in:
732642856
2026-07-17 11:21:14 +08:00
parent 155ad047dc
commit 167934bfe9
10 changed files with 937 additions and 65 deletions
@@ -0,0 +1,64 @@
from __future__ import annotations
import sys
from pathlib import Path
import pytest
SCRIPTS = Path(__file__).resolve().parents[1] / "scripts"
if str(SCRIPTS) not in sys.path:
sys.path.insert(0, str(SCRIPTS))
BIRTH = {
"year": 1990,
"month": 1,
"day": 1,
"hour": 12,
"minute": 0,
"second": 0,
"lat": 28.6139,
"lon": 77.2090,
"tz": 5.5,
"ayanamsa": "lahiri",
"node_mode": "true",
}
def test_domain_chart_exposes_effective_parameters_and_result_hash() -> None:
from domain_calculation_service import compute_chart
result = compute_chart(BIRTH)
assert result["calculation_contract"]["effective"]["node_mode"] == "true"
assert result["calculation_contract"]["effective"]["ayanamsa"] == "lahiri"
assert result["result_hash"]
def test_api_chart_uses_same_domain_contract_and_preserves_shape(
monkeypatch: pytest.MonkeyPatch,
) -> None:
import domain_calculation_service
import jyotish_api_server
from jyotish_api_server import JyotishAPIHandler
monkeypatch.setenv("JYOTISH_API_CHART_CACHE_TTL_SECONDS", "0")
monkeypatch.setenv("VEDASTRO_ENABLE_NETWORK", "0")
monkeypatch.setattr(
jyotish_api_server,
"_attach_vedastro_main_entry_overview",
lambda result, _birth: result,
)
expected = domain_calculation_service.compute_chart(BIRTH)
result = JyotishAPIHandler.__new__(JyotishAPIHandler)._compute_chart_sync(
{**BIRTH, "transit_date": "2026-07-11"}
)
assert result["result_hash"] == expected["result_hash"]
assert result["calculation_contract"] == expected["calculation_contract"]
assert result["birth"]["node_mode"] == "true"
assert result["planets"]
assert result["ascendant"]
assert "houses" in result
+77
View File
@@ -0,0 +1,77 @@
"""Public synthetic-fixture contract shared with the commercial repository."""
from __future__ import annotations
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "scripts"
if str(SCRIPTS) not in sys.path:
sys.path.insert(0, str(SCRIPTS))
import cross_project_contract as contract # noqa: E402
MANIFEST = ROOT / "references" / "cross_project_contract" / "fixture_manifest.v1.json"
LEDGER = ROOT / "references" / "cross_project_contract" / "sync_ledger.json"
def test_public_fixture_manifest_has_complete_effective_settings() -> None:
manifest = contract.load_manifest(MANIFEST)
assert manifest["schema_version"] == 1
assert manifest["privacy_scope"] == "public_synthetic_only"
fixture = manifest["fixtures"][0]
assert fixture["birth"]["synthetic"] is True
assert fixture["effective"] == {"ayanamsa": "lahiri", "node_mode": "mean", "timezone_offset": 5.5}
def test_local_calculation_matches_public_compatibility_hash() -> None:
report = contract.evaluate_manifest(MANIFEST)
assert report["matches"] is True
assert report["fixtures"][0]["matches"] is True
def test_comparator_reports_tampered_expected_hash(tmp_path: Path) -> None:
manifest = json.loads(MANIFEST.read_text(encoding="utf-8"))
manifest["fixtures"][0]["compatibility_hash"] = "0" * 64
changed = tmp_path / "fixture_manifest.v1.json"
changed.write_text(json.dumps(manifest), encoding="utf-8")
report = contract.evaluate_manifest(changed)
assert report["matches"] is False
assert report["fixtures"][0]["matches"] is False
def test_compatibility_payload_normalizes_engine_degree_field() -> None:
fixture = contract.load_manifest(MANIFEST)["fixtures"][0]
chart = {
"ascendant": {"sign": "Aries", "degree": 1.25},
"planets": {
planet: {"sign": "Aries", "degree": float(index)}
for index, planet in enumerate(contract.PLANETS)
},
}
payload = contract.compatibility_payload(chart, fixture)
assert payload["ascendant"]["lon"] == 1.25
assert payload["planets"]["Sun"]["lon"] == 0.0
def test_sync_ledger_requires_provenance_privacy_tests_hash_and_rollback() -> None:
ledger = contract.load_ledger(LEDGER)
assert ledger["schema_version"] == 1
assert len(ledger["entries"]) >= 1
for entry in ledger["entries"]:
assert contract.validate_ledger_entry(entry) == []
assert entry["privacy_review"].startswith("pass:")
missing = contract.validate_ledger_entry({"source_repository": "x"})
assert "target_commit" in missing
assert "privacy_review" in missing
assert "rollback" in missing
+64
View File
@@ -0,0 +1,64 @@
"""Cross-repository sync status checks for the research/commercial pair."""
from __future__ import annotations
import json
import shutil
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SCRIPTS = ROOT / "scripts"
if str(SCRIPTS) not in sys.path:
sys.path.insert(0, str(SCRIPTS))
import cross_project_sync_status as sync_status # noqa: E402
POLICY = ROOT / "references" / "cross_project_contract" / "sync_policy.v1.json"
def _make_peer_copy(tmp_path: Path) -> Path:
peer = tmp_path / "peer"
policy = sync_status.load_policy(POLICY)
for rel_path in policy["shared_files"]:
source = ROOT / rel_path
target = peer / rel_path
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, target)
return peer
def test_sync_policy_encodes_research_first_commercial_mature_rule() -> None:
policy = sync_status.load_policy(POLICY)
assert policy["schema_version"] == 1
assert policy["sync_model"] == "research_validates_commercial_receives_mature"
assert policy["directional_gates"]["research_to_commercial"]["source_required"] == "validated_in_research"
assert policy["directional_gates"]["research_to_commercial"]["target_required"] == "commercial_safe"
assert "references/cross_project_contract/fixture_manifest.v1.json" in policy["shared_files"]
def test_sync_status_passes_when_shared_files_match(tmp_path: Path) -> None:
peer = _make_peer_copy(tmp_path)
report = sync_status.compare_peer(peer, policy_path=POLICY, root=ROOT)
assert report["status"] == "pass"
assert report["missing"] == []
assert report["mismatched"] == []
assert report["checked_count"] == len(sync_status.load_policy(POLICY)["shared_files"])
def test_sync_status_reports_mismatched_shared_file(tmp_path: Path) -> None:
peer = _make_peer_copy(tmp_path)
changed = peer / "references" / "cross_project_contract" / "fixture_manifest.v1.json"
data = json.loads(changed.read_text(encoding="utf-8"))
data["fixtures"][0]["compatibility_hash"] = "0" * 64
changed.write_text(json.dumps(data, sort_keys=True), encoding="utf-8")
report = sync_status.compare_peer(peer, policy_path=POLICY, root=ROOT)
assert report["status"] == "fail"
assert report["missing"] == []
assert report["mismatched"] == ["references/cross_project_contract/fixture_manifest.v1.json"]