paperhawk / domain_checks /check_03_contract_completeness.py
Nándorfi Vince
Initial paperhawk push to HF Space (LFS for binaries)
7ff7119
raw
history blame
3.52 kB
"""03: Contract completeness — A/B level, universal best practice.
Universal contract-completeness checks (not jurisdiction-specific):
* termination terms (high) — required for predictability
* governing law (medium) — required for dispute resolution
* penalty for high-value contracts (>1M) — uses a parity threshold
* confidentiality clause (low) — only flagged when explicitly False
"""
from __future__ import annotations
from domain_checks.base import is_empty, make_risk
from graph.states.pipeline_state import Risk
from utils.numbers import coerce_number
_REGULATION = "Universal contract completeness"
_CONTRACT_CRITICAL_FIELDS = [
("termination_terms", "Termination terms", "high",
"Without termination terms, the contract carries unpredictable risk."),
("governing_law", "Governing law", "medium",
"Missing governing law creates uncertainty in any dispute."),
]
class ContractCompletenessCheck:
check_id = "check_03_contract_completeness"
regulation = _REGULATION
is_hu_specific = False
applies_to = {"contract"}
def apply(self, extracted: dict) -> list[Risk]:
risks: list[Risk] = []
# Critical fields (termination, governing law)
for field, label, sev, explanation in _CONTRACT_CRITICAL_FIELDS:
if is_empty(extracted.get(field)):
risks.append(make_risk(
description=f"Missing contract element: {label}",
severity=sev,
rationale=explanation,
regulation=_REGULATION,
source_check_id=self.check_id,
))
# Penalty: should be present in writing for high-value contracts.
# Two shapes supported: ``total_value`` (top-level) or legacy
# ``value`` dict ({"amount": X, "currency": "USD"}).
value_dict = extracted.get("value") or {}
if isinstance(value_dict, dict) and value_dict:
total = coerce_number(value_dict.get("amount"))
currency = value_dict.get("currency", "")
else:
total = coerce_number(extracted.get("total_value"))
currency = extracted.get("currency", "")
if is_empty(extracted.get("penalty")) and total is not None and total > 1_000_000:
risks.append(make_risk(
description="No penalty clause defined in a high-value contract",
severity="medium",
rationale=(
f"Contract value is {total:,.0f} {currency} but no penalty "
f"clause is present. For high-value contracts, a penalty "
f"clause is best practice for predictable enforcement."
),
regulation="Universal contract proportionality",
source_check_id=self.check_id,
))
# Confidentiality: critical for B2B. Flag ONLY when explicitly False
# (not when missing/null) — mirrors the parity behavior.
if extracted.get("confidentiality_clause") is False:
risks.append(make_risk(
description="Confidentiality clause missing",
severity="low",
rationale=(
"The contract has no confidentiality clause. In B2B "
"relationships, protecting business information is recommended."
),
regulation=_REGULATION,
source_check_id=self.check_id,
))
return risks