feat: make birth-time rectification conversational

This commit is contained in:
Jesse_Chen
2026-07-23 13:12:09 +08:00
parent 200c39d22b
commit f9010c8797
34 changed files with 1720 additions and 177 deletions
+8 -1
View File
@@ -431,7 +431,13 @@ def test_high_rigor_event_rectification_queues_vedastro_packet(monkeypatch) -> N
"tz": 8,
"high_rigor": True,
"events": [
{"id": "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5", "domain": "education", "date": "2011-09", "precision": "month"},
{
"id": "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5",
"domain": "education",
"date": "2011-09",
"precision": "month",
"summary": "2011 年 9 月离开家乡开始大学生活",
},
{"id": "0790866c-ad5e-4a45-b2b4-a5c73f6be6ea", "domain": "career", "date": "2019-07-01", "precision": "day"},
{"id": "0ef52e51-ab5f-453b-81e5-adb44a929224", "domain": "relationship", "date": "2021", "precision": "year"},
],
@@ -447,3 +453,4 @@ def test_high_rigor_event_rectification_queues_vedastro_packet(monkeypatch) -> N
assert contract["decision"] == "continue_rectification"
assert contract["canonical_input_hash"]
assert contract["gates"]["public_holdout_release"]["status"] == "blocked"
assert result["calculation_contract"]["events"][0]["summary"] == "2011 年 9 月离开家乡开始大学生活"
+39
View File
@@ -177,6 +177,45 @@ def test_real_local_scoring_uses_dated_events_and_actual_candidate_minutes() ->
assert len(result["stability_diagnostics"]["leave_one_event_out"]["runs"]) == 3
def test_event_summary_is_fingerprinted_without_unlocking_minute_application() -> None:
base_request = {
"birth_date": "1993-04-17",
"start_time": "14:29",
"end_time": "14:30",
"lat": 36.683333,
"lon": 114.35,
"tz": 8.0,
"events": [{
"id": "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5",
"domain": "career",
"date": "2019-07",
"precision": "month",
"summary": "2019 年 7 月第一次承担团队管理职责",
}],
}
changed_request = {
**base_request,
"events": [{
**base_request["events"][0],
"summary": "2019 年 7 月离开原公司并开始独立创业",
}],
}
contract, input_hash = event_engine._canonical_input_contract(base_request)
_, changed_hash = event_engine._canonical_input_contract(changed_request)
result = event_engine.adjudicate_event_candidate_rows(
base_request,
[_row("14:29", 10), _row("14:30", 8)],
)
assert contract["schema_version"] == "rectification-candidate-input-v2"
assert contract["events"][0]["summary"] == "2019 年 7 月第一次承担团队管理职责"
assert changed_hash != input_hash
assert result["canonical_input_hash"] == input_hash
assert result["can_apply"] is False
assert "minute_holdout_not_ready" in result["reasons"]
def test_finance_events_use_d2_d11_and_recompute_both_dashas_per_minute(monkeypatch) -> None:
calls = {"vimshottari": 0, "narayana": 0, "varga_counts": []}
original_score_event = event_engine._score_event
@@ -7,6 +7,7 @@ SCHEMA = MIGRATIONS / "20260720010000_conversational_rectification_schema.sql"
BILLING = MIGRATIONS / "20260720020000_conversational_rectification_billing.sql"
TRANSITIONS = MIGRATIONS / "20260720030000_conversational_rectification_transitions.sql"
LEGACY_IMPORT = MIGRATIONS / "20260721010000_conversational_legacy_import_projection.sql"
UNCONFIRMED_REFUND = MIGRATIONS / "20260722190000_refund_unconfirmed_rectification.sql"
def _normalized(path: Path) -> str:
@@ -117,6 +118,28 @@ def test_complete_never_debits_and_release_refunds_at_most_once() -> None:
assert "'already_charged'" in release
def test_range_only_completion_and_abandonment_refund_in_the_terminal_transaction() -> None:
sql = _normalized(UNCONFIRMED_REFUND)
refund = _function(sql, "conversational_rectification_refund_unconfirmed_case")
completion = _function(sql, "complete_conversational_rectification_with_range")
abandonment = _function(sql, "abandon_conversational_rectification_without_result")
for invariant in (
"v_case.status not in ('completed', 'abandoned')",
"v_case.turn_state #>> '{candidate,status}' = 'confirmed'",
"v_billing.state = 'charged'",
"set credits = profile.credits + v_billing.price",
"'refund', v_billing.price",
"set state = 'released'",
):
assert invariant in refund
assert "save_conversational_rectification_turn" in completion
assert "conversational_rectification_refund_unconfirmed_case" in completion
assert "abandon_conversational_rectification_case" in abandonment
assert "conversational_rectification_refund_unconfirmed_case" in abandonment
assert "active_birth_time" not in sql
def test_release_terminalizes_a_created_reserved_case() -> None:
release = _function(_normalized(BILLING), "release_conversational_rectification_fee")