feat: align commercial chart calculation contract
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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"]
|
||||
Reference in New Issue
Block a user