Bind renewal dates to renewal clauses

This commit is contained in:
2026-07-18 05:00:29 -03:00
parent e88577c90d
commit 11e097a1a5
3 changed files with 32 additions and 7 deletions

View File

@@ -44,8 +44,8 @@ ALLOWED_BROWSER_MEDIA_TYPES = (
)
DATE_RE = re.compile(r"\b(20\d{2}-\d{2}-\d{2})\b")
RENEWAL_DATE_RE = re.compile(
r"\brenew(?:s|al|ed|ing)?\b[^.\n;]{0,160}\b(?:on|as\s+of|effective|date|until|through)\s+"
r"(20\d{2}-\d{2}-\d{2})\b",
r"\brenew(?:s|al|ed|ing)?\b[^.\n;]{0,160}?\b(?:on|as\s+of|effective(?:\s+on)?|"
r"date(?:\s+is)?|until|through)\b\s*:?\s*(20\d{2}-\d{2}-\d{2})\b",
re.IGNORECASE,
)
RENEWAL_RE = re.compile(r"\brenew(?:s|al|ed|ing)?\b", re.IGNORECASE)
@@ -76,7 +76,7 @@ class ContractClockStudioV1(A2AAgent[ContractClockStudioV1Config, PlatformUserAu
"contracts, saves user-scoped timelines, and reopens them in a packed "
"one-page studio."
)
version = "0.1.4"
version = "0.1.5"
config_model = ContractClockStudioV1Config
auth_model = PlatformUserAuth
@@ -277,8 +277,9 @@ def _analyze_text(*, contract_id: str, title: str, text: str) -> dict[str, Any]:
return {"ok": False, "code": code, "contract_id": contract_id}
deadlines: list[dict[str, str]] = []
if RENEWAL_RE.search(clean_text):
renewal_date = explicit_dates[0]
renewal_match = RENEWAL_DATE_RE.search(clean_text)
if renewal_match:
renewal_date = date.fromisoformat(renewal_match.group(1))
deadlines.append({"kind": "renewal", "date": renewal_date.isoformat()})
notice_match = NOTICE_RE.search(clean_text)
if notice_match:
@@ -287,6 +288,12 @@ def _analyze_text(*, contract_id: str, title: str, text: str) -> dict[str, Any]:
deadlines.append(
{"kind": "notice", "date": (renewal_date - timedelta(days=notice_days)).isoformat()}
)
elif RENEWAL_RE.search(clean_text):
return {
"ok": False,
"code": "ambiguous_renewal_date",
"contract_id": contract_id,
}
else:
# Explicit dates outside a renewal clause are kept as dated obligations;
# relative invoice terms without a concrete anchor are intentionally not guessed.