fix(rectification): close round A/2 tail gaps in tests, CI, and stale-score reuse
Independent Staging Quality Gate / validate (pull_request) Failing after 6m13s
Independent Staging Quality Gate / publish (pull_request) Has been skipped

Window_scan assertions now match the public from_sign/to_sign contract, the
staging quick gate runs the rectification Python suite, and compare-candidates
rescores when stored policy lags the live engine identity.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-01 18:17:33 +08:00
parent 26ea3f06cb
commit c48a965640
9 changed files with 250 additions and 7 deletions
+17
View File
@@ -3019,6 +3019,7 @@ API_COMMAND_MAP = {
'rectification-v5-score': '/api/rectification/v5/score',
'rectification-v5-diagnostics': '/api/rectification/v5/diagnostics',
'rectification-v5-vedastro-validate': '/api/rectification/v5/vedastro-validate',
'rectification-v5-versions': '/api/rectification/v5/versions',
'case-validation': '/api/case_validation',
'divisional-yoga': '/api/divisional_yoga',
'deep-varga-avastha': '/api/deep_varga_avastha',
@@ -3058,6 +3059,7 @@ TECHNIQUE_EXAMPLE_ENDPOINTS = {
'/api/rectification/v5/score',
'/api/rectification/v5/diagnostics',
'/api/rectification/v5/vedastro-validate',
'/api/rectification/v5/versions',
'/api/relationship',
'/api/remedies',
'/api/sade_sati',
@@ -3293,6 +3295,8 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'async_job_runtime': async_job_runtime_status(),
'vedastro': self._vedastro_status(),
})
elif path == '/api/rectification/v5/versions':
self._json(self._compute_rectification_v5_versions())
elif path == '/api/cities':
self._json(list(CITY_DB.keys()))
elif path == '/api/capability_audit':
@@ -3518,6 +3522,8 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
self._json(self._compute_rectification_v5_diagnostics(body))
elif path == '/api/rectification/v5/vedastro-validate':
self._json(self._compute_rectification_v5_vedastro_validate(body))
elif path == '/api/rectification/v5/versions':
self._json(self._compute_rectification_v5_versions())
elif path == '/api/dynamic_rectification_opportunities':
result = self._compute_dynamic_rectification_opportunities(body)
self._json(result)
@@ -9061,6 +9067,14 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
except ValueError as exc:
raise BadRequest(str(exc)) from exc
def _compute_rectification_v5_versions(self, body=None):
from scripts.rectification.api_service import engine_scoring_versions
return {
'success': True,
'endpoint': 'rectification_v5_versions',
**engine_scoring_versions(),
}
def _compute_rectification_v5_candidate_features(self, body):
from scripts.rectification.api_service import candidate_features
return {
@@ -10111,6 +10125,7 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'/api/rectification/v5/score': self._compute_rectification_v5_score,
'/api/rectification/v5/diagnostics': self._compute_rectification_v5_diagnostics,
'/api/rectification/v5/vedastro-validate': self._compute_rectification_v5_vedastro_validate,
'/api/rectification/v5/versions': self._compute_rectification_v5_versions,
'/api/relationship': self._compute_relationship,
'/api/remedies': self._compute_remedies,
'/api/sade_sati': self._compute_sade_sati,
@@ -10241,6 +10256,7 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'/api/rectification/v5/score': 'Build the V5 event-by-candidate contribution matrix and score candidate ranges',
'/api/rectification/v5/diagnostics': 'Run V5 stability diagnostics over the server-owned contribution matrix',
'/api/rectification/v5/vedastro-validate': 'Validate one V5 primary/runner-up pair with safe official VedAstro summaries',
'/api/rectification/v5/versions': 'Return live V5 algorithm and decision-policy identity without scoring',
'/api/relationship': 'Compute relationship and spouse-status evidence',
'/api/remedies': 'Generate low-risk remedies from doshas/strength/dasha',
'/api/sade_sati': 'Compute Sade Sati status and phase',
@@ -10324,6 +10340,7 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
'candidate_times': ['05:01', '05:02'],
'events': [{'id': '00000000-0000-4000-8000-000000000001', 'domain': 'education', 'event_kind': 'education_milestone', 'date_start': '2016-09-01', 'date_end': '2016-09-30', 'precision': 'month', 'summary': '大学入学'}],
},
'/api/rectification/v5/versions': {},
'/api/relationship': {'planets': SAMPLE_PLANETS, 'asc_sign': 'Aries', 'dasha_info': {'maha_dasha': 'Venus', 'antar_dasha': 'Jupiter'}},
'/api/remedies': {'shadbala': {'Sun': {'rupas': 4.1}, 'Moon': {'rupas': 3.8}}, 'doshas': ['manglik'], 'dasha_lord': 'Venus'},
'/api/sade_sati': {'moon_degree': SAMPLE_PLANETS['Moon']['lon'], 'asc_degree': SAMPLE_ASCENDANT['lon'], 'saturn_degree': SAMPLE_PLANETS['Saturn']['lon']},
+9
View File
@@ -152,6 +152,15 @@ def _rectification_report(
}
def engine_scoring_versions() -> dict[str, str]:
"""Identity fields also returned by `/api/rectification/v5/score`, without scoring."""
return {
"algorithm_version": ALGORITHM_VERSION,
"event_contract_version": EVENT_CONTRACT_VERSION,
"decision_policy_version": POLICY_VERSION,
}
def candidate_features(request: RectificationRequest) -> dict[str, Any]:
spec = calculation_spec(request)
spec_hash = sha256(spec)
+4
View File
@@ -59,6 +59,10 @@ CORE_PYTEST_TARGETS = [
# Staging quick profile never runs `tests/` wholesale. A distinguish probe
# with empty mapping or non-positive gain must fail this gate (BUG-393).
"tests/test_candidate_discriminator_contract.py",
# Auto staging gate is `--profile quick`. `test.yml` / `ci.yml` run the
# full pytest tree but are workflow_dispatch only, so a stale window_scan
# assertion in this glob stayed red on origin/staging until listed here.
"tests/test_rectification_*.py",
]
RUNTIME_TRUTH_PYTEST_TARGETS = [