Repair ContractClock persistence and receipt safety
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import base64
|
||||
import importlib.util
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -27,7 +26,7 @@ def test_full_stack_product_contract_card_and_manifest():
|
||||
frontend = (ROOT / "frontend" / "src" / "App.jsx").read_text(encoding="utf-8")
|
||||
a2a_client = (ROOT / "frontend" / "src" / "a2a.js").read_text(encoding="utf-8")
|
||||
|
||||
assert "version: 0.1.5" in manifest
|
||||
assert "version: 0.1.6" in manifest
|
||||
assert "public: false" in manifest
|
||||
assert "frontend:" in manifest and "mount: /app" in manifest
|
||||
assert "resources:" in manifest and "databases:" in manifest
|
||||
@@ -45,7 +44,7 @@ def test_full_stack_product_contract_card_and_manifest():
|
||||
assert migrations and all(path.read_text(encoding="utf-8").strip() for path in migrations)
|
||||
|
||||
card = load_local_project(ROOT).agent_cls().card()
|
||||
assert card.version == "0.1.5"
|
||||
assert card.version == "0.1.6"
|
||||
skill_names = {skill.name for skill in card.skills}
|
||||
assert {"analyze_contract", "get_contract_deadlines", "analyze_contract_upload_base64", "analyze_contract_file"} <= skill_names
|
||||
analyze_schema = next(skill.input_schema for skill in card.skills if skill.name == "analyze_contract")
|
||||
@@ -85,6 +84,31 @@ def test_explicit_date_only_success_and_failure():
|
||||
assert bad.ok is False
|
||||
assert bad.code == "ambiguous_date"
|
||||
|
||||
multiple_dates = module._analyze_contract_text(
|
||||
contract_id="studio-contract-multiple-dates",
|
||||
title="Multiple dates",
|
||||
text=(
|
||||
"This Agreement is effective on 2025-01-01 and renews automatically "
|
||||
"on 2026-12-31 unless either party gives at least 60 days written notice."
|
||||
),
|
||||
)
|
||||
assert [d.model_dump(include={"kind", "date"}) for d in multiple_dates.deadlines] == [
|
||||
{"kind": "renewal", "date": "2026-12-31"},
|
||||
{"kind": "notice", "date": "2026-11-01"},
|
||||
]
|
||||
|
||||
separate_lines = module._analyze_contract_text(
|
||||
contract_id="studio-contract-separate-lines",
|
||||
title="Separate clauses",
|
||||
text=(
|
||||
"Agreement renews on 2026-12-31\n"
|
||||
"60 days written notice applies to another obligation"
|
||||
),
|
||||
)
|
||||
assert [d.model_dump(include={"kind", "date"}) for d in separate_lines.deadlines] == [
|
||||
{"kind": "renewal", "date": "2026-12-31"},
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_success_failure_upload_and_reload_with_fake_postgres(monkeypatch):
|
||||
@@ -106,7 +130,7 @@ async def test_success_failure_upload_and_reload_with_fake_postgres(monkeypatch)
|
||||
params = params or ()
|
||||
normalized = " ".join(sql.split())
|
||||
if normalized.startswith("SET"):
|
||||
return
|
||||
raise AssertionError("timeouts must be configured in connection options")
|
||||
if "INSERT INTO contracts" in normalized:
|
||||
tenant, contract_id, title, source_hash = params
|
||||
key = (tenant, contract_id)
|
||||
@@ -158,6 +182,7 @@ async def test_success_failure_upload_and_reload_with_fake_postgres(monkeypatch)
|
||||
class FakePsycopg:
|
||||
def connect(self, *args, **kwargs):
|
||||
assert "statement_timeout=5000" in kwargs.get("options", "")
|
||||
assert "idle_in_transaction_session_timeout=5000" in kwargs.get("options", "")
|
||||
return FakeConnection()
|
||||
|
||||
monkeypatch.setenv("DATABASE_URL", "postgresql://example.invalid/db")
|
||||
@@ -176,6 +201,9 @@ async def test_success_failure_upload_and_reload_with_fake_postgres(monkeypatch)
|
||||
assert success.ok is True
|
||||
assert success.receipt_id and success.saved_at
|
||||
assert len(store["receipts"]) == 1
|
||||
receipt_payload = __import__("json").loads(store["receipts"][0][-1])
|
||||
assert "source_text" not in str(receipt_payload)
|
||||
assert receipt_payload["result"]["deadline_count"] == 2
|
||||
|
||||
reload_result = await agent.invoke("get_contract_deadlines", ctx, contract_id="studio-contract-v1")
|
||||
assert reload_result.ok is True
|
||||
|
||||
Reference in New Issue
Block a user