Merge PR #49: pass birth-time accuracy truth into consultation engine

Reviewed: tsc + consult 295 + rectification 747 + python suites green;
guard functions and window/general instructions verified unchanged.
Conflict: BUG entry renumbered 467→468 (467 taken by report-extraction).
Review fix: test_consultation_birth_accuracy.py added to CORE_PYTEST_TARGETS
(pytest-style file outside the rectification glob would never hit the auto gate).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu
This commit is contained in:
Jesse_Chen
2026-09-01 20:48:27 +00:00
15 changed files with 534 additions and 14 deletions
+128
View File
@@ -0,0 +1,128 @@
#!/usr/bin/env python3
"""Consultation birth-time accuracy truth-passing invariants."""
from __future__ import annotations
import os
import re
import sys
SCRIPTS = os.path.join(os.path.dirname(__file__), '..', 'scripts')
if SCRIPTS not in sys.path:
sys.path.insert(0, SCRIPTS)
from birth_time_rectifier import get_effective_accuracy, get_enabled_vargas # noqa: E402
from jyotish_api_server import JyotishAPIHandler, _build_consumer_context # noqa: E402
CANDIDATE_WINDOW_COPY = re.compile(
r'candidate windows|not_auto_rectified|按时间范围|建议先做事件反验',
re.I,
)
PRECISION_ANNOTATION_COPY = re.compile(r'填报时间|标注精度|precision', re.I)
def _handler() -> JyotishAPIHandler:
handler = JyotishAPIHandler.__new__(JyotishAPIHandler)
handler._compute_vedastro_gateway_run = lambda body: { # type: ignore[method-assign]
'status': 'official_blocked',
'official_closure_reason': 'accuracy_contract_probe',
}
return handler
def _gate(declared_accuracy: str, time_source: str) -> dict:
return _handler()._compute_rectification_gate({
'planets': {
'Sun': {'lon': 80.0},
'Moon': {'lon': 123.0},
'Mars': {'lon': 210.0},
'Mercury': {'lon': 75.0},
'Jupiter': {'lon': 15.0},
'Venus': {'lon': 102.0},
'Saturn': {'lon': 330.0},
'Rahu': {'lon': 5.0},
'Ketu': {'lon': 185.0},
},
'ascendant': {'lon': 15.0},
'declared_accuracy': declared_accuracy,
'time_source': time_source,
})
def _consumer(rectification: dict) -> dict:
return _build_consumer_context(
question='我的事业接下来怎么走',
route_packet={'question_type': 'career', 'primary_theme': 'career'},
chart={'success': True},
rectification=rectification,
machine_evidence_packet={'sections': {'D1': {'status': 'used'}, 'D9': {'status': 'used'}, 'D10': {'status': 'used'}}},
vedastro_official={'status': 'blocked'},
)
def _joined_boundaries(context: dict) -> str:
return ' '.join(str(value) for value in context.get('domain_boundaries', {}).values())
def test_hospital_gate_is_minute_with_d9_d10_and_no_uncertainty_boundary() -> None:
result = _gate('minute', 'hospital')
context = _consumer(result)
assert result['effective_accuracy'] == 'minute'
assert result['lagna_boundary']['is_sensitive'] is False
assert result['enabled_vargas']['D9'] == 'enabled'
assert result['enabled_vargas']['D10'] == 'enabled'
assert 'birth_time_uncertainty_boundary' not in context['domain_boundaries']
assert CANDIDATE_WINDOW_COPY.search(_joined_boundaries(context)) is None
def test_family_exact_and_approximate_use_precision_annotation_not_candidate_windows() -> None:
family = _gate('minute', 'family_clear')
approximate = _gate('15min', 'family_vague')
assert family['effective_accuracy'] == '5min'
assert approximate['effective_accuracy'] == '15min'
assert '按填报时间排盘' in family['summary']['headline']
assert '按填报时间排盘' in approximate['summary']['headline']
assert CANDIDATE_WINDOW_COPY.search(family['summary']['headline']) is None
assert CANDIDATE_WINDOW_COPY.search(approximate['summary']['headline']) is None
family_context = _consumer(family)
approximate_context = _consumer(approximate)
for context in (family_context, approximate_context):
joined = _joined_boundaries(context)
assert CANDIDATE_WINDOW_COPY.search(joined) is None
assert PRECISION_ANNOTATION_COPY.search(joined)
assert 'not_auto_rectified' not in context.get('domain_context_layers', [])
def test_five_min_and_fifteen_min_vargas_are_not_unknown() -> None:
unknown = get_enabled_vargas('unknown')
five = get_enabled_vargas('5min')
fifteen = get_enabled_vargas('15min')
assert five != unknown
assert fifteen != unknown
assert five['D1'] == 'enabled'
assert five['D9'] == 'enabled'
assert five['D10'] == 'enabled'
assert five['D5'] == 'enabled_with_warning'
assert five['D4'] == 'enabled_with_warning'
assert five['D7'] == 'enabled_with_warning'
assert five['D30'] == 'disabled'
assert five['D60'] == 'disabled'
assert fifteen['D1'] == 'enabled'
assert fifteen['D9'] == 'enabled'
def test_rectified_and_hospital_effective_accuracy_stay_precise() -> None:
assert get_effective_accuracy('rectified', 'rectified') == 'rectified'
assert get_effective_accuracy('minute', 'hospital') == 'minute'
assert get_effective_accuracy('minute', 'family_clear') == '5min'
assert get_effective_accuracy('15min', 'family_vague') == '15min'
rectified = _gate('rectified', 'rectified')
context = _consumer(rectified)
assert rectified['effective_accuracy'] == 'rectified'
assert 'birth_time_uncertainty_boundary' not in context['domain_boundaries']
assert CANDIDATE_WINDOW_COPY.search(_joined_boundaries(context)) is None