Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files- Dockerfile +11 -0
- contract_risk_env/README.md +108 -0
- contract_risk_env/__init__.py +0 -0
- contract_risk_env/client.py +40 -0
- contract_risk_env/data/contracts_corpus.json +481 -0
- contract_risk_env/inference.py +129 -0
- contract_risk_env/models.py +54 -0
- contract_risk_env/openenv.yaml +10 -0
- contract_risk_env/pyproject.toml +27 -0
- contract_risk_env/requirements.txt +7 -0
- contract_risk_env/server/Dockerfile +11 -0
- contract_risk_env/server/__init__.py +0 -0
- contract_risk_env/server/app.py +193 -0
- contract_risk_env/server/corpus.py +64 -0
- contract_risk_env/server/environment.py +89 -0
- contract_risk_env/server/graders.py +70 -0
- contracts_corpus.json +166 -0
- inference.py +225 -0
- openenv.yaml +10 -0
- requirements.txt +7 -0
Dockerfile
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
COPY contract_risk_env/requirements.txt .
|
| 6 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 7 |
+
|
| 8 |
+
COPY . .
|
| 9 |
+
|
| 10 |
+
EXPOSE 7860
|
| 11 |
+
CMD ["uvicorn", "contract_risk_env.server.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
contract_risk_env/README.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ContractRiskEnv
|
| 2 |
+
|
| 3 |
+
An [OpenEnv](https://huggingface.co/collections/openenv/environment-hub)-compliant reinforcement learning environment for **legal contract risk clause detection**.
|
| 4 |
+
|
| 5 |
+
An agent reads synthetic legal contracts and flags risky clauses. The grader is fully deterministic — precision/recall/F1 against ground-truth clause labels. No LLM calls inside the grader.
|
| 6 |
+
|
| 7 |
+
## Tasks
|
| 8 |
+
|
| 9 |
+
| Task ID | Difficulty | Description | Expected Baseline F1 |
|
| 10 |
+
|----------|-----------|-------------|---------------------|
|
| 11 |
+
| `easy` | Easy | SaaS agreements — explicit risks with clear headings | ~0.85 |
|
| 12 |
+
| `medium` | Medium | IP licensing — risks buried in cross-references | ~0.51 |
|
| 13 |
+
| `hard` | Hard | Enterprise MSA — protective-looking clauses with negating exceptions | ~0.29 |
|
| 14 |
+
|
| 15 |
+
## Risk Types
|
| 16 |
+
|
| 17 |
+
`unlimited_liability` · `auto_renewal` · `unilateral_amendment` · `ip_assignment_overreach` · `indemnification_asymmetry` · `data_ownership_ambiguity` · `termination_without_cause`
|
| 18 |
+
|
| 19 |
+
## Reward Function
|
| 20 |
+
|
| 21 |
+
```
|
| 22 |
+
reward = 0.35 × precision + 0.45 × recall − 0.10 × fp_penalty − 0.10 × severity_miss_penalty
|
| 23 |
+
```
|
| 24 |
+
|
| 25 |
+
Recall is weighted higher — missing a real risk is worse than a false alarm.
|
| 26 |
+
|
| 27 |
+
## Quick Start
|
| 28 |
+
|
| 29 |
+
```bash
|
| 30 |
+
# Install
|
| 31 |
+
pip install -r requirements.txt
|
| 32 |
+
|
| 33 |
+
# Run server
|
| 34 |
+
uvicorn contract_risk_env.server.app:app --host 0.0.0.0 --port 8000 --reload
|
| 35 |
+
|
| 36 |
+
# Check health
|
| 37 |
+
curl http://localhost:8000/health
|
| 38 |
+
|
| 39 |
+
# Run LLM baseline (requires OPENAI_API_KEY)
|
| 40 |
+
OPENAI_API_KEY=sk-... python -m contract_risk_env.inference
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
## Client Usage
|
| 44 |
+
|
| 45 |
+
```python
|
| 46 |
+
from contract_risk_env.client import ContractRiskEnv
|
| 47 |
+
from contract_risk_env.models import ContractAction, ClauseFlag
|
| 48 |
+
|
| 49 |
+
with ContractRiskEnv(base_url="http://localhost:8000").sync() as env:
|
| 50 |
+
result = env.reset(task_id="easy")
|
| 51 |
+
obs = result.observation
|
| 52 |
+
print(obs.contract_text[:200])
|
| 53 |
+
|
| 54 |
+
action = ContractAction(
|
| 55 |
+
flagged_clauses=[
|
| 56 |
+
ClauseFlag(clause_id="clause_4_2", risk_type="auto_renewal", severity=2, span_text="..."),
|
| 57 |
+
],
|
| 58 |
+
confidence=0.8,
|
| 59 |
+
reasoning="Found auto-renewal clause in Section 4.2",
|
| 60 |
+
)
|
| 61 |
+
result = env.step(action)
|
| 62 |
+
print(f"Reward: {result.reward}")
|
| 63 |
+
print(f"Feedback: {result.observation.feedback}")
|
| 64 |
+
```
|
| 65 |
+
|
| 66 |
+
## API Endpoints
|
| 67 |
+
|
| 68 |
+
| Endpoint | Method | Description |
|
| 69 |
+
|----------|--------|-------------|
|
| 70 |
+
| `/health` | GET | Health check |
|
| 71 |
+
| `/reset` | POST | Start new episode |
|
| 72 |
+
| `/step` | POST | Submit action |
|
| 73 |
+
| `/state` | GET | Get episode state |
|
| 74 |
+
| `/tasks` | GET | List all tasks with schemas |
|
| 75 |
+
| `/grader` | POST | Score a completed episode |
|
| 76 |
+
| `/baseline` | GET | Run keyword heuristic baseline |
|
| 77 |
+
| `/docs` | GET | OpenAPI documentation |
|
| 78 |
+
|
| 79 |
+
## Docker
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
docker build -t contract-risk-env -f server/Dockerfile ..
|
| 83 |
+
docker run -p 8000:8000 contract-risk-env
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
## Project Structure
|
| 87 |
+
|
| 88 |
+
```
|
| 89 |
+
contract_risk_env/
|
| 90 |
+
├── models.py — Pydantic models (Action, Observation, State)
|
| 91 |
+
├── client.py — OpenEnv WebSocket client
|
| 92 |
+
├── inference.py — GPT-4o baseline inference script
|
| 93 |
+
├── server/
|
| 94 |
+
│ ├── app.py — FastAPI app + competition endpoints
|
| 95 |
+
│ ├── environment.py — RL environment (reset/step/state)
|
| 96 |
+
│ ├── corpus.py — Contract corpus loader
|
| 97 |
+
│ ├── graders.py — Deterministic grader
|
| 98 |
+
│ └── Dockerfile
|
| 99 |
+
├── data/
|
| 100 |
+
│ └── contracts_corpus.json
|
| 101 |
+
├── openenv.yaml
|
| 102 |
+
├── pyproject.toml
|
| 103 |
+
└── requirements.txt
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
## License
|
| 107 |
+
|
| 108 |
+
MIT
|
contract_risk_env/__init__.py
ADDED
|
File without changes
|
contract_risk_env/client.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Client — pip-installable OpenEnv client for ContractRiskEnv."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
from openenv.core.env_client import EnvClient
|
| 6 |
+
from openenv.core.client_types import StepResult
|
| 7 |
+
|
| 8 |
+
from .models import ContractAction, ContractObservation, ContractState
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class ContractRiskEnv(EnvClient[ContractAction, ContractObservation, ContractState]):
|
| 12 |
+
"""WebSocket-based client for ContractRiskEnv."""
|
| 13 |
+
|
| 14 |
+
def _step_payload(self, action: ContractAction) -> dict:
|
| 15 |
+
return action.model_dump()
|
| 16 |
+
|
| 17 |
+
def _parse_result(self, payload: dict) -> StepResult:
|
| 18 |
+
obs_data = payload.get("observation", {})
|
| 19 |
+
return StepResult(
|
| 20 |
+
observation=ContractObservation(
|
| 21 |
+
done=payload.get("done", False),
|
| 22 |
+
reward=payload.get("reward"),
|
| 23 |
+
contract_text=obs_data.get("contract_text", ""),
|
| 24 |
+
task_id=obs_data.get("task_id", ""),
|
| 25 |
+
difficulty=obs_data.get("difficulty", ""),
|
| 26 |
+
clause_count=obs_data.get("clause_count", 0),
|
| 27 |
+
feedback=obs_data.get("feedback", {}),
|
| 28 |
+
),
|
| 29 |
+
reward=payload.get("reward"),
|
| 30 |
+
done=payload.get("done", False),
|
| 31 |
+
)
|
| 32 |
+
|
| 33 |
+
def _parse_state(self, payload: dict) -> ContractState:
|
| 34 |
+
return ContractState(
|
| 35 |
+
episode_id=payload.get("episode_id"),
|
| 36 |
+
step_count=payload.get("step_count", 0),
|
| 37 |
+
contract_id=payload.get("contract_id", ""),
|
| 38 |
+
task_id=payload.get("task_id", ""),
|
| 39 |
+
total_risk_clauses=payload.get("total_risk_clauses", 0),
|
| 40 |
+
)
|
contract_risk_env/data/contracts_corpus.json
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": "1.0.0",
|
| 3 |
+
"description": "ContractRiskEnv corpus — 9 contracts (3 per difficulty: easy/medium/hard). Each contract is synthetic but legally realistic. Ground-truth labels include clause_id, risk_type, severity (1-3), and character span.",
|
| 4 |
+
"risk_types": [
|
| 5 |
+
"unlimited_liability",
|
| 6 |
+
"auto_renewal",
|
| 7 |
+
"unilateral_amendment",
|
| 8 |
+
"ip_assignment_overreach",
|
| 9 |
+
"indemnification_asymmetry",
|
| 10 |
+
"data_ownership_ambiguity",
|
| 11 |
+
"termination_without_cause"
|
| 12 |
+
],
|
| 13 |
+
"severity_scale": {
|
| 14 |
+
"1": "medium — worth flagging, low immediate financial exposure",
|
| 15 |
+
"2": "high — significant financial or operational risk",
|
| 16 |
+
"3": "critical — existential financial or IP risk"
|
| 17 |
+
},
|
| 18 |
+
"contracts": [
|
| 19 |
+
{
|
| 20 |
+
"contract_id": "saas_001",
|
| 21 |
+
"difficulty": "easy",
|
| 22 |
+
"title": "Software-as-a-Service Subscription Agreement",
|
| 23 |
+
"parties": [
|
| 24 |
+
"Vendor: Cloudify Technologies Inc.",
|
| 25 |
+
"Customer: Acme Corp"
|
| 26 |
+
],
|
| 27 |
+
"notes": "Risks are explicit, standalone, clearly phrased. An attentive reader finds them in a single pass. Designed to score 0.80-0.95 F1 for a capable LLM baseline.",
|
| 28 |
+
"text": "SOFTWARE-AS-A-SERVICE SUBSCRIPTION AGREEMENT\n\nThis Software-as-a-Service Subscription Agreement (the \"Agreement\") is entered into as of the Effective Date by and between Cloudify Technologies Inc., a Delaware corporation (\"Vendor\"), and the entity identified in the applicable Order Form (\"Customer\").\n\n1. DEFINITIONS\n\n1.1 \"Service\" means Vendor's proprietary cloud-based data analytics platform, including all updates, upgrades, and modifications thereto made available to Customer during the Subscription Term.\n\n1.2 \"Subscription Term\" means the initial period specified in the Order Form and any renewal periods thereafter.\n\n1.3 \"Authorized Users\" means Customer's employees, contractors, and agents who are permitted to access the Service under this Agreement.\n\n1.4 \"Customer Data\" means all data, content, and information submitted by Customer or its Authorized Users to the Service.\n\n2. LICENSE GRANT\n\n2.1 Subject to the terms of this Agreement and timely payment of all fees, Vendor grants Customer a limited, non-exclusive, non-transferable, non-sublicensable license to access and use the Service during the Subscription Term solely for Customer's internal business purposes.\n\n2.2 Customer shall not: (a) sublicense, sell, resell, or transfer the Service; (b) reverse engineer or decompile the Service; (c) access the Service to build a competitive product; or (d) use the Service to store or transmit unlawful material.\n\n3. FEES AND PAYMENT\n\n3.1 Customer shall pay Vendor the fees set forth in the applicable Order Form. All fees are due within thirty (30) days of invoice.\n\n3.2 Vendor may increase fees upon sixty (60) days written notice to Customer prior to the start of any renewal Subscription Term.\n\n4. SUBSCRIPTION TERM AND RENEWAL\n\n4.1 This Agreement commences on the Effective Date and continues for the Initial Subscription Term specified in the Order Form.\n\n4.2 AUTOMATIC RENEWAL: Unless either party provides written notice of non-renewal at least ninety (90) days prior to the end of the then-current Subscription Term, this Agreement shall automatically renew for successive one (1) year periods at the then-current list price, which may differ from Customer's initial pricing. Customer acknowledges that failure to provide timely notice of non-renewal will result in binding commitment to an additional full-year subscription term.\n\n5. TERMINATION\n\n5.1 Either party may terminate this Agreement for cause upon thirty (30) days written notice if the other party materially breaches this Agreement and fails to cure such breach within the notice period.\n\n5.2 TERMINATION FOR CONVENIENCE: Vendor may terminate this Agreement or any Service at any time for any reason or no reason upon fifteen (15) days written notice to Customer. In the event of such termination, Vendor shall refund any prepaid fees covering the period after the effective date of termination on a pro-rata basis.\n\n5.3 Upon termination, Customer's right to access and use the Service shall immediately cease. Customer shall have thirty (30) days to export its Customer Data, after which Vendor may permanently delete all Customer Data.\n\n6. INTELLECTUAL PROPERTY\n\n6.1 Vendor retains all right, title, and interest in and to the Service, including all intellectual property rights therein. Nothing in this Agreement transfers any ownership of the Service to Customer.\n\n6.2 CUSTOMER WORK PRODUCT: All analyses, reports, dashboards, custom integrations, scripts, and derivative works created by Customer or its Authorized Users using or in connection with the Service (\"Customer Work Product\") are hereby irrevocably assigned to and shall be the sole and exclusive property of Vendor. Customer hereby waives any moral rights in such Customer Work Product. Customer grants Vendor a perpetual, irrevocable, royalty-free license to use Customer Data to improve the Service and for any other commercial purpose Vendor deems appropriate.\n\n7. WARRANTIES AND DISCLAIMER\n\n7.1 Vendor warrants that the Service will perform materially in accordance with applicable documentation during the Subscription Term. Vendor's sole obligation for breach of this warranty is to use commercially reasonable efforts to correct the non-conformity.\n\n7.2 DISCLAIMER: EXCEPT AS SET FORTH IN SECTION 7.1, THE SERVICE IS PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY KIND. VENDOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED.\n\n8. LIMITATION OF LIABILITY\n\n8.1 IN NO EVENT SHALL EITHER PARTY BE LIABLE FOR INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, PUNITIVE, OR EXEMPLARY DAMAGES.\n\n8.2 UNLIMITED LIABILITY: Notwithstanding Section 8.1 or any other provision of this Agreement, Customer's liability to Vendor shall be unlimited and shall include all direct, indirect, consequential, special, incidental, punitive, and exemplary damages of any kind, including but not limited to lost profits, loss of goodwill, loss of business opportunity, and any other damages whether foreseeable or not, arising out of or in connection with Customer's use of the Service or breach of any provision of this Agreement. There shall be no cap or limitation on Customer's liability to Vendor under any theory of law.\n\n9. MODIFICATIONS TO AGREEMENT\n\n9.1 UNILATERAL AMENDMENT: Vendor reserves the right to modify any term or condition of this Agreement at any time and without prior notice to Customer. Modified terms will be posted to Vendor's website and shall become effective immediately upon posting. Customer's continued use of the Service following any modification constitutes Customer's binding acceptance of the modified Agreement. Customer is solely responsible for reviewing the Agreement periodically for modifications.\n\n10. GOVERNING LAW\n\n10.1 This Agreement shall be governed by the laws of the State of Delaware without regard to its conflict of law provisions. Any disputes shall be resolved exclusively in the state or federal courts located in Wilmington, Delaware.\n\n10.2 WAIVER OF JURY TRIAL: Each party hereby irrevocably waives its right to a trial by jury in any action arising under or related to this Agreement.",
|
| 29 |
+
"labels": [
|
| 30 |
+
{
|
| 31 |
+
"clause_id": "clause_4_2",
|
| 32 |
+
"risk_type": "auto_renewal",
|
| 33 |
+
"severity": 2,
|
| 34 |
+
"span_text": "AUTOMATIC RENEWAL: Unless either party provides written notice of non-renewal at least ninety (90) days prior to the end of the then-current Subscription Term, this Agreement shall automatically renew for successive one (1) year periods at the then-current list price",
|
| 35 |
+
"span_section": "Section 4.2",
|
| 36 |
+
"grader_note": "90-day notice window is unusually long; pricing may reset to list price. Clear and explicit — easy to find."
|
| 37 |
+
},
|
| 38 |
+
{
|
| 39 |
+
"clause_id": "clause_5_2",
|
| 40 |
+
"risk_type": "termination_without_cause",
|
| 41 |
+
"severity": 2,
|
| 42 |
+
"span_text": "Vendor may terminate this Agreement or any Service at any time for any reason or no reason upon fifteen (15) days written notice to Customer.",
|
| 43 |
+
"span_section": "Section 5.2",
|
| 44 |
+
"grader_note": "15-day notice is operationally very short for a business-critical SaaS. Explicit and standalone."
|
| 45 |
+
},
|
| 46 |
+
{
|
| 47 |
+
"clause_id": "clause_6_2",
|
| 48 |
+
"risk_type": "ip_assignment_overreach",
|
| 49 |
+
"severity": 3,
|
| 50 |
+
"span_text": "All analyses, reports, dashboards, custom integrations, scripts, and derivative works created by Customer or its Authorized Users using or in connection with the Service (\"Customer Work Product\") are hereby irrevocably assigned to and shall be the sole and exclusive property of Vendor.",
|
| 51 |
+
"span_section": "Section 6.2",
|
| 52 |
+
"grader_note": "Customer loses ownership of everything it creates with the tool. Critical. Also contains data_ownership_ambiguity in the perpetual license for Customer Data."
|
| 53 |
+
},
|
| 54 |
+
{
|
| 55 |
+
"clause_id": "clause_6_2b",
|
| 56 |
+
"risk_type": "data_ownership_ambiguity",
|
| 57 |
+
"severity": 2,
|
| 58 |
+
"span_text": "Customer grants Vendor a perpetual, irrevocable, royalty-free license to use Customer Data to improve the Service and for any other commercial purpose Vendor deems appropriate.",
|
| 59 |
+
"span_section": "Section 6.2",
|
| 60 |
+
"grader_note": "'Any other commercial purpose' is extremely broad. Customer data can be sold or used for training."
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"clause_id": "clause_8_2",
|
| 64 |
+
"risk_type": "unlimited_liability",
|
| 65 |
+
"severity": 3,
|
| 66 |
+
"span_text": "Customer's liability to Vendor shall be unlimited and shall include all direct, indirect, consequential, special, incidental, punitive, and exemplary damages of any kind",
|
| 67 |
+
"span_section": "Section 8.2",
|
| 68 |
+
"grader_note": "Section heading is 'UNLIMITED LIABILITY' — maximally explicit. The asymmetry (vendor capped, customer uncapped) makes this critical."
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"clause_id": "clause_9_1",
|
| 72 |
+
"risk_type": "unilateral_amendment",
|
| 73 |
+
"severity": 3,
|
| 74 |
+
"span_text": "Vendor reserves the right to modify any term or condition of this Agreement at any time and without prior notice to Customer. Modified terms will be posted to Vendor's website and shall become effective immediately upon posting.",
|
| 75 |
+
"span_section": "Section 9.1",
|
| 76 |
+
"grader_note": "No notice required, effective immediately. Vendor can change pricing, liability caps, or data terms at will."
|
| 77 |
+
}
|
| 78 |
+
]
|
| 79 |
+
},
|
| 80 |
+
{
|
| 81 |
+
"contract_id": "ip_license_002",
|
| 82 |
+
"difficulty": "medium",
|
| 83 |
+
"title": "Intellectual Property Licensing and Services Agreement",
|
| 84 |
+
"parties": [
|
| 85 |
+
"Licensor: Meridian Analytics Ltd.",
|
| 86 |
+
"Licensee: Borealis Financial Group"
|
| 87 |
+
],
|
| 88 |
+
"notes": "Risks are real but require cross-referencing. The auto-renewal trap is inside a defined term in Section 1. The IP overreach requires reading Section 6.3 in light of the definition in Section 1.7. An agent that reads linearly without tracking definitions will miss both. Designed to score 0.45-0.60 F1 for a capable LLM baseline.",
|
| 89 |
+
"text": "INTELLECTUAL PROPERTY LICENSING AND SERVICES AGREEMENT\n\nThis Intellectual Property Licensing and Services Agreement (\"Agreement\") is made effective as of the date of last signature below (\"Effective Date\") by and between Meridian Analytics Ltd., a company incorporated in England and Wales with registered number 09234871 (\"Licensor\"), and Borealis Financial Group, a federally chartered Canadian bank (\"Licensee\").\n\n1. DEFINITIONS\n\nFor purposes of this Agreement, the following terms shall have the meanings ascribed to them below:\n\n1.1 \"Licensed Software\" means Licensor's proprietary risk modelling suite known as \"MeridianRisk,\" including all modules, libraries, and components identified in Schedule A.\n\n1.2 \"Documentation\" means the technical and user documentation provided by Licensor for the Licensed Software.\n\n1.3 \"Licensed Materials\" means, collectively, the Licensed Software and the Documentation.\n\n1.4 \"Maintenance and Support\" means the services described in Schedule B, including bug fixes, patches, and telephone support during Business Hours.\n\n1.5 \"Derivative Analysis\" means any financial model, risk score, assessment, prediction, valuation, report, or analytical output that is produced by Licensee through or with material assistance from the Licensed Software, whether or not such output is further processed or transformed by Licensee subsequent to production.\n\n1.6 \"Business Hours\" means 9:00 a.m. to 5:00 p.m. Eastern Time, Monday through Friday, excluding statutory holidays in Ontario, Canada.\n\n1.7 \"Evergreen Term\" means a Subscription Term that, upon expiration of its Initial Period, shall automatically continue and renew on a month-to-month basis at a fee of one hundred fifteen percent (115%) of the annualized Initial Period fee, prorated monthly, unless Licensee provides written notice of termination delivered by registered mail to Licensor's registered address no fewer than one hundred twenty (120) days prior to the date on which Licensee wishes termination to take effect.\n\n1.8 \"Background IP\" means any intellectual property owned or controlled by a party prior to the Effective Date or developed independently of this Agreement.\n\n1.9 \"Foreground IP\" means any intellectual property first conceived, reduced to practice, or developed by either party, or jointly, in the performance of activities under this Agreement.\n\n2. LICENSE GRANT\n\n2.1 Subject to the terms and conditions of this Agreement, Licensor hereby grants to Licensee a non-exclusive, non-transferable, non-sublicensable license to install and use the Licensed Materials solely within Licensee's internal computing environment for Licensee's internal business purposes during the Subscription Term.\n\n2.2 The license granted in Section 2.1 is limited to use by Licensee's employees and does not extend to contractors, agents, affiliates, or subsidiaries of Licensee unless Licensor provides prior written consent.\n\n3. SUBSCRIPTION TERM\n\n3.1 The initial subscription period (\"Initial Period\") commences on the Effective Date and continues for two (2) years (\"Initial Subscription Term\").\n\n3.2 Upon expiration of the Initial Subscription Term, and upon expiration of each subsequent term thereafter, this Agreement shall automatically continue as an Evergreen Term as defined in Section 1.7, unless a party provides notice in accordance with Section 1.7.\n\n3.3 Licensor may, at any time during an Evergreen Term, convert the Agreement back to a fixed-term subscription by providing written notice to Licensee specifying the proposed fixed term and applicable fees, which Licensee may accept or reject within fifteen (15) days.\n\n4. FEES\n\n4.1 Licensee shall pay the fees set forth in Schedule C during the Initial Subscription Term.\n\n4.2 Fees during any Evergreen Term shall be as specified in Section 1.7 of this Agreement.\n\n4.3 All fees are exclusive of applicable taxes. Licensee shall pay all applicable sales, use, goods and services, value-added, and similar taxes.\n\n5. CONFIDENTIALITY\n\n5.1 Each party agrees to hold in strict confidence all Confidential Information of the other party and to use such information solely for the purposes contemplated by this Agreement.\n\n5.2 \"Confidential Information\" means any non-public information disclosed by one party to the other in connection with this Agreement that is designated as confidential or that reasonably should be understood to be confidential.\n\n5.3 The obligations in Section 5.1 shall survive termination of this Agreement for a period of five (5) years.\n\n6. INTELLECTUAL PROPERTY\n\n6.1 Each party retains all right, title, and interest in and to its respective Background IP. Nothing in this Agreement transfers ownership of Background IP.\n\n6.2 All Foreground IP developed solely by Licensor in the course of providing services under this Agreement shall belong exclusively to Licensor.\n\n6.3 All Foreground IP developed solely by Licensee, including but not limited to any Derivative Analysis as defined in Section 1.5, and any methods, processes, models, or workflows developed by Licensee that incorporate, apply, reference, or build upon the Licensed Software or any output thereof, shall automatically vest in and be assigned to Licensor upon creation without further act or instrument. Licensee hereby waives, to the maximum extent permitted by applicable law, any right to assert ownership of or compensation for such Foreground IP. Licensor grants Licensee a non-exclusive, revocable license to use such Foreground IP solely in connection with the Licensed Software during the Subscription Term.\n\n6.4 Licensee shall promptly disclose to Licensor in writing any Foreground IP developed by Licensee and shall execute such documents and take such further actions as Licensor may reasonably request to perfect Licensor's rights therein.\n\n7. INDEMNIFICATION\n\n7.1 Licensor shall indemnify, defend, and hold harmless Licensee from and against any third-party claims alleging that the Licensed Software, as delivered and used in accordance with this Agreement, infringes any patent, copyright, or trade secret of a third party.\n\n7.2 Licensee shall indemnify, defend, and hold harmless Licensor, its officers, directors, employees, and agents from and against any and all claims, damages, losses, costs, and expenses (including reasonable attorneys' fees) arising out of or related to: (a) Licensee's use of the Licensed Software; (b) any breach of this Agreement by Licensee; (c) any Derivative Analysis produced by Licensee; or (d) any claim by a third party arising from Licensee's business operations.\n\n7.3 The indemnification obligations in Section 7.2 are not subject to any cap or limitation set forth elsewhere in this Agreement.\n\n8. LIMITATION OF LIABILITY\n\n8.1 In no event shall Licensor's aggregate liability under this Agreement exceed the total fees paid by Licensee in the twelve (12) months immediately preceding the claim giving rise to liability.\n\n8.2 Neither party shall be liable for any indirect, incidental, consequential, special, or punitive damages, regardless of the theory of liability.\n\n9. DATA\n\n9.1 Licensee acknowledges that Licensor may collect and process anonymized and aggregated usage data from Licensee's use of the Licensed Software (\"Usage Data\").\n\n9.2 Licensor shall own all right, title, and interest in Usage Data and may use, disclose, sell, or sublicense Usage Data for any purpose, including product development, benchmarking, marketing, or sale to third parties, without restriction and without obligation to Licensee.\n\n9.3 Licensee represents and warrants that it has obtained all consents necessary for Licensor to process Usage Data as described in Section 9.2.\n\n10. GOVERNING LAW AND DISPUTE RESOLUTION\n\n10.1 This Agreement is governed by the laws of the Province of Ontario and the federal laws of Canada applicable therein.\n\n10.2 Any dispute shall be referred to and finally resolved by binding arbitration under the Rules of Arbitration of the International Chamber of Commerce by a single arbitrator in Toronto, Ontario. The language of the arbitration shall be English.",
|
| 90 |
+
"labels": [
|
| 91 |
+
{
|
| 92 |
+
"clause_id": "clause_1_7",
|
| 93 |
+
"risk_type": "auto_renewal",
|
| 94 |
+
"severity": 3,
|
| 95 |
+
"span_text": "\"Evergreen Term\" means a Subscription Term that, upon expiration of its Initial Period, shall automatically continue and renew on a month-to-month basis at a fee of one hundred fifteen percent (115%) of the annualized Initial Period fee, prorated monthly, unless Licensee provides written notice of termination delivered by registered mail to Licensor's registered address no fewer than one hundred twenty (120) days prior to the date on which Licensee wishes termination to take effect.",
|
| 96 |
+
"span_section": "Section 1.7",
|
| 97 |
+
"grader_note": "Hidden inside definitions section. 115% price escalation and 120-day registered mail notice window. Agent must connect Section 1.7 definition to Section 3.2 operative clause to understand the trap. Risk is severity 3 due to price escalation compounding over time."
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"clause_id": "clause_6_3",
|
| 101 |
+
"risk_type": "ip_assignment_overreach",
|
| 102 |
+
"severity": 3,
|
| 103 |
+
"span_text": "All Foreground IP developed solely by Licensee, including but not limited to any Derivative Analysis as defined in Section 1.5, and any methods, processes, models, or workflows developed by Licensee that incorporate, apply, reference, or build upon the Licensed Software or any output thereof, shall automatically vest in and be assigned to Licensor upon creation without further act or instrument.",
|
| 104 |
+
"span_section": "Section 6.3",
|
| 105 |
+
"grader_note": "Agent must follow cross-reference to Section 1.5 definition of 'Derivative Analysis' to understand full scope. Any risk model, report, or valuation Licensee builds is assigned to the Licensor. For a bank, this is all internal risk work."
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"clause_id": "clause_7_2",
|
| 109 |
+
"risk_type": "indemnification_asymmetry",
|
| 110 |
+
"severity": 2,
|
| 111 |
+
"span_text": "Licensee shall indemnify, defend, and hold harmless Licensor, its officers, directors, employees, and agents from and against any and all claims, damages, losses, costs, and expenses (including reasonable attorneys' fees) arising out of or related to: (a) Licensee's use of the Licensed Software; (b) any breach of this Agreement by Licensee; (c) any Derivative Analysis produced by Licensee; or (d) any claim by a third party arising from Licensee's business operations.",
|
| 112 |
+
"span_section": "Section 7.2",
|
| 113 |
+
"grader_note": "Licensor's indemnity (7.1) is narrow (IP infringement only, as-delivered). Licensee's indemnity (7.2) covers essentially all use of the software, all outputs, and all business operations. Section 7.3 explicitly removes any liability cap from 7.2."
|
| 114 |
+
},
|
| 115 |
+
{
|
| 116 |
+
"clause_id": "clause_9_2",
|
| 117 |
+
"risk_type": "data_ownership_ambiguity",
|
| 118 |
+
"severity": 2,
|
| 119 |
+
"span_text": "Licensor shall own all right, title, and interest in Usage Data and may use, disclose, sell, or sublicense Usage Data for any purpose, including product development, benchmarking, marketing, or sale to third parties, without restriction and without obligation to Licensee.",
|
| 120 |
+
"span_section": "Section 9.2",
|
| 121 |
+
"grader_note": "'Anonymized and aggregated' in 9.1 is not defined. For a financial institution, usage patterns and query behaviour may be commercially sensitive even if anonymized."
|
| 122 |
+
}
|
| 123 |
+
]
|
| 124 |
+
},
|
| 125 |
+
{
|
| 126 |
+
"contract_id": "enterprise_msa_003",
|
| 127 |
+
"difficulty": "hard",
|
| 128 |
+
"title": "Master Services Agreement — Enterprise Platform",
|
| 129 |
+
"parties": [
|
| 130 |
+
"Provider: Nexus Platform Corp.",
|
| 131 |
+
"Client: Stratum Energy Holdings LLC"
|
| 132 |
+
],
|
| 133 |
+
"notes": "The hardest category. Three of the four risks are hidden inside clauses that appear protective on first reading. The unlimited liability clause (Section 11.4) appears under the heading 'Mutual Liability Cap' and reads like a cap until the exception in 11.4(c) swallows the entire protection. The IP clause (Section 8.2) reads as a joint ownership arrangement until 8.2(d) gives Provider unilateral commercialization rights. The auto-renewal (Section 3.4) is buried in a 'Service Continuity' clause that reads as a customer protection. A linear reader will miss all three. Designed to score 0.20-0.35 F1 for a capable LLM baseline.",
|
| 134 |
+
"text": "MASTER SERVICES AGREEMENT\n\nThis Master Services Agreement (\"MSA\" or \"Agreement\") is entered into as of the Effective Date set forth on the cover page by and between Nexus Platform Corp., a Delaware corporation (\"Provider\"), and the Client entity identified on the cover page (\"Client\"). This Agreement governs all services, subscriptions, and deliverables provided by Provider to Client.\n\n1. DEFINITIONS\n\n1.1 \"Affiliate\" means any entity that directly or indirectly controls, is controlled by, or is under common control with a party, where \"control\" means ownership of more than fifty percent (50%) of the voting equity.\n\n1.2 \"Background Technology\" means technology, software, tools, methodologies, know-how, and intellectual property owned or licensed by a party prior to the Effective Date or developed by a party outside the scope of this Agreement.\n\n1.3 \"Client Systems\" means Client's internal IT infrastructure, networks, hardware, and software environments into which Provider may integrate or deploy the Platform.\n\n1.4 \"Deliverables\" means any work product, software, configuration, documentation, report, or other material specifically created for Client pursuant to a Statement of Work.\n\n1.5 \"Developed Technology\" means any technology, software, algorithm, model, process, or invention first created in the performance of services under this Agreement, whether created solely by Provider, solely by Client, or jointly.\n\n1.6 \"Platform\" means Provider's enterprise data management and workflow automation platform, including all associated APIs, integrations, and hosted infrastructure.\n\n1.7 \"Service Level Agreement\" or \"SLA\" means the service availability and performance commitments set forth in Schedule D.\n\n1.8 \"Statement of Work\" or \"SOW\" means a document executed by both parties that describes specific services, Deliverables, timelines, and fees.\n\n1.9 \"Renewal Trigger\" means the event by which a Subscription Term automatically extends, as further described in Section 3.4.\n\n2. SERVICES\n\n2.1 Provider shall provide Client access to the Platform and such professional services as are described in one or more Statements of Work executed hereunder.\n\n2.2 Provider shall perform all services in a professional and workmanlike manner consistent with industry standards.\n\n2.3 Client shall provide Provider with reasonable access to Client Systems, personnel, and information as necessary for Provider to perform the services.\n\n3. TERM\n\n3.1 This Agreement commences on the Effective Date and continues until terminated in accordance with Section 12, unless earlier terminated.\n\n3.2 Each Statement of Work shall specify the applicable subscription or service term (\"Subscription Term\").\n\n3.3 Provider shall use commercially reasonable efforts to notify Client no later than sixty (60) days prior to the expiration of any Subscription Term of the upcoming expiration date (\"Expiration Notice\").\n\n3.4 SERVICE CONTINUITY PROVISION: To protect Client from inadvertent service interruption and data access loss that may result from administrative oversight, and in recognition of the operational dependencies Client may develop on the Platform, if Provider has not received written confirmation from Client's designated contract administrator (as registered in Provider's customer portal) that Client elects to allow the Subscription Term to lapse, the Subscription Term shall automatically extend for a period equal to the greater of (i) the length of the expiring Subscription Term or (ii) twelve (12) months (\"Extended Term\"), at Provider's then-current standard list pricing applicable to Client's usage tier, which may be updated by Provider from time to time. Provider's obligation to send the Expiration Notice described in Section 3.3 is a courtesy and does not create a condition precedent to the Renewal Trigger. Client acknowledges that Provider's customer portal constitutes the authoritative system of record for renewal elections and that email communications from Client personnel other than the designated contract administrator shall not constitute valid renewal elections.\n\n4. FEES\n\n4.1 Client shall pay all fees set forth in applicable Statements of Work and as adjusted during any Extended Term pursuant to Section 3.4.\n\n4.2 Provider may update the fee schedule applicable to any Extended Term upon thirty (30) days notice delivered through the customer portal.\n\n4.3 Invoices are due within forty-five (45) days of the invoice date. Overdue amounts accrue interest at one and one-half percent (1.5%) per month.\n\n5. CONFIDENTIALITY\n\n5.1 Each party shall protect the other's Confidential Information using the same degree of care it uses to protect its own Confidential Information, but in no event less than reasonable care.\n\n5.2 \"Confidential Information\" excludes information that: (a) is or becomes publicly available through no fault of the receiving party; (b) was known to the receiving party prior to disclosure; (c) is rightfully received from a third party without restriction; or (d) is independently developed by the receiving party.\n\n5.3 Confidentiality obligations shall survive termination of this Agreement for three (3) years.\n\n6. DATA PROCESSING AND OWNERSHIP\n\n6.1 Client retains ownership of all raw data submitted by Client to the Platform (\"Client Raw Data\").\n\n6.2 Provider shall process Client Raw Data solely as necessary to provide the services described in this Agreement and applicable SOWs.\n\n6.3 Operational and Derived Data. Notwithstanding Section 6.1, Client acknowledges and agrees that: (a) metadata generated by the Platform during the processing of Client Raw Data, including but not limited to processing logs, error records, latency metrics, and resource utilization data (\"Operational Metadata\") shall be owned exclusively by Provider; (b) statistical models, trained weights, learned parameters, and aggregated benchmarks derived by Provider from the processing of Client Raw Data across Provider's customer base, including data from Client (\"Derived Models\") shall be owned exclusively by Provider and may be incorporated into Provider's commercial products and services without compensation to Client; and (c) Client hereby irrevocably assigns to Provider any interest Client may have in Operational Metadata or Derived Models.\n\n7. INTELLECTUAL PROPERTY — BACKGROUND TECHNOLOGY\n\n7.1 Each party retains all right, title, and interest in and to its respective Background Technology. This Agreement does not transfer any ownership of Background Technology.\n\n7.2 Provider grants Client a limited, non-exclusive, revocable license to use Provider's Background Technology solely to the extent necessary to receive the services during the applicable Subscription Term.\n\n8. INTELLECTUAL PROPERTY — DEVELOPED TECHNOLOGY\n\n8.1 Deliverables specified in a Statement of Work as \"Client-Owned Deliverables\" shall be owned by Client upon full payment of all applicable fees. Provider hereby assigns to Client all right, title, and interest in such Client-Owned Deliverables, subject to Section 8.3.\n\n8.2 Joint Development and Platform Enhancements. The parties acknowledge that the performance of services under this Agreement may result in improvements, enhancements, extensions, or modifications to the Platform or to Provider's methodologies and tooling (collectively, \"Platform Enhancements\"), which may incorporate elements developed by Client personnel or arising from Client's specific use case. With respect to all Platform Enhancements:\n\n(a) The parties shall be deemed co-owners of all Platform Enhancements, each holding an undivided interest therein;\n\n(b) Each party may use Platform Enhancements for its own internal purposes without accounting to the other party;\n\n(c) Neither party shall transfer, assign, or sublicense its interest in any Platform Enhancement to a third party without the prior written consent of the other party; and\n\n(d) Notwithstanding subsections (a) through (c), Provider is hereby granted, and Client hereby irrevocably grants to Provider, the exclusive, worldwide, perpetual, irrevocable, royalty-free right to commercialize, sublicense, incorporate into Provider's products and services, and otherwise exploit any Platform Enhancement in any manner Provider deems appropriate, without the consent of, notice to, or compensation to Client. For clarity, the co-ownership described in subsection (a) does not entitle Client to any revenue, royalties, or compensation arising from Provider's commercialization of Platform Enhancements pursuant to this subsection (d).\n\n8.3 Provider License-Back. Provider retains, and Client acknowledges that Provider retains, a perpetual, irrevocable, royalty-free license to use, reproduce, and create derivative works of any Client-Owned Deliverable for Provider's internal purposes and product development.\n\n9. INDEMNIFICATION\n\n9.1 Provider Indemnification. Provider shall indemnify, defend, and hold harmless Client from third-party claims alleging that the Platform, as delivered and used in compliance with this Agreement, infringes any United States patent issued as of the Effective Date, copyright, or trade secret, provided that Client: (a) promptly notifies Provider in writing of the claim; (b) grants Provider sole control of the defense and settlement; and (c) provides Provider with reasonable assistance.\n\n9.2 Client Indemnification. Client shall indemnify, defend, and hold harmless Provider and its Affiliates, officers, directors, employees, agents, successors, and assigns from and against any and all losses, damages, liabilities, deficiencies, actions, judgments, interest, awards, penalties, fines, costs, or expenses (including reasonable attorneys' fees and the cost of enforcing any right to indemnification) arising out of or related to: (a) Client's use of or access to the Platform; (b) Client Raw Data; (c) Client's violation of applicable law; (d) Client's breach of any representation, warranty, covenant, or obligation under this Agreement; or (e) any claim by Client's customers, partners, or regulators arising from Client's business operations or use of Deliverables.\n\n10. WARRANTIES\n\n10.1 Each party represents and warrants that: (a) it has the legal authority to enter into this Agreement; (b) its performance will not violate any applicable law; and (c) its performance will not infringe the intellectual property rights of any third party.\n\n10.2 Provider warrants that the Platform will perform materially in accordance with the SLA during the Subscription Term. Client's sole remedy for breach of this warranty is the service credits described in Schedule D.\n\n11. LIMITATION OF LIABILITY\n\n11.1 MUTUAL EXCLUSION OF CONSEQUENTIAL DAMAGES: Neither party shall be liable to the other for any indirect, incidental, consequential, special, exemplary, or punitive damages, including but not limited to lost profits, loss of revenue, loss of data, loss of goodwill, or cost of substitute goods or services, even if such party has been advised of the possibility of such damages.\n\n11.2 MUTUAL LIABILITY CAP: Subject to Section 11.4, each party's aggregate liability to the other party for all claims arising out of or related to this Agreement, whether in contract, tort, or otherwise, shall not exceed the total fees paid or payable by Client to Provider in the twelve (12) months immediately preceding the event giving rise to the claim.\n\n11.3 The limitations set forth in Sections 11.1 and 11.2 shall apply regardless of the theory of liability and regardless of whether a party has been advised of the possibility of such liability.\n\n11.4 EXCEPTIONS TO MUTUAL LIABILITY CAP: The mutual liability cap set forth in Section 11.2 shall not apply to, and there shall be no cap or limitation whatsoever on liability for:\n\n(a) a party's obligation to indemnify the other party pursuant to Section 9;\n\n(b) damages arising from a party's gross negligence or willful misconduct;\n\n(c) Client's payment obligations under this Agreement, including all fees, expenses, interest, and collection costs; and\n\n(d) Client's obligations with respect to intellectual property under Sections 7, 8, and 6.3, including but not limited to any unauthorized use of Provider's Background Technology, any failure to assign Developed Technology, and any breach of the data provisions of Section 6.\n\n11.5 For the avoidance of doubt, the exceptions in Section 11.4 mean that Client's liability for payment defaults and intellectual property breaches is unlimited, while Provider's liability for the same categories is subject to the cap in Section 11.2.\n\n12. TERMINATION\n\n12.1 Either party may terminate this Agreement for cause upon sixty (60) days written notice specifying the material breach, provided the breaching party fails to cure within the notice period.\n\n12.2 Either party may terminate this Agreement upon sixty (60) days written notice if the other party becomes insolvent, makes a general assignment for the benefit of creditors, or has a receiver appointed.\n\n12.3 Termination of this Agreement does not terminate any outstanding Statements of Work unless specifically agreed in writing.\n\n13. GENERAL\n\n13.1 This Agreement, together with all Schedules and SOWs, constitutes the entire agreement between the parties and supersedes all prior agreements, representations, and understandings.\n\n13.2 Provider may assign this Agreement or any of its rights or obligations hereunder without Client's consent. Client may not assign this Agreement without Provider's prior written consent, which shall not be unreasonably withheld.\n\n13.3 This Agreement shall be governed by the laws of the State of New York.",
|
| 135 |
+
"labels": [
|
| 136 |
+
{
|
| 137 |
+
"clause_id": "clause_3_4",
|
| 138 |
+
"risk_type": "auto_renewal",
|
| 139 |
+
"severity": 3,
|
| 140 |
+
"span_text": "SERVICE CONTINUITY PROVISION: To protect Client from inadvertent service interruption... if Provider has not received written confirmation from Client's designated contract administrator (as registered in Provider's customer portal) that Client elects to allow the Subscription Term to lapse, the Subscription Term shall automatically extend for a period equal to the greater of (i) the length of the expiring Subscription Term or (ii) twelve (12) months... at Provider's then-current standard list pricing",
|
| 141 |
+
"span_section": "Section 3.4",
|
| 142 |
+
"grader_note": "HARD: Clause is titled 'Service Continuity Provision' and opens with language about protecting the Client. The renewal trap is inside the protective framing. Notice must come from a specific named person in a portal (not email). The 60-day expiration notice (3.3) is explicitly not a condition precedent to renewal. Term can double (greater of current term or 12 months). Severity 3."
|
| 143 |
+
},
|
| 144 |
+
{
|
| 145 |
+
"clause_id": "clause_6_3b",
|
| 146 |
+
"risk_type": "data_ownership_ambiguity",
|
| 147 |
+
"severity": 3,
|
| 148 |
+
"span_text": "statistical models, trained weights, learned parameters, and aggregated benchmarks derived by Provider from the processing of Client Raw Data across Provider's customer base, including data from Client (\"Derived Models\") shall be owned exclusively by Provider and may be incorporated into Provider's commercial products and services without compensation to Client",
|
| 149 |
+
"span_section": "Section 6.3(b)",
|
| 150 |
+
"grader_note": "Client retains raw data (6.1) but any model trained on it belongs to Provider. For an energy company, this means proprietary operational patterns and forecasting models derived from Client's data enrich Provider's commercial offerings."
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
"clause_id": "clause_8_2d",
|
| 154 |
+
"risk_type": "ip_assignment_overreach",
|
| 155 |
+
"severity": 3,
|
| 156 |
+
"span_text": "Notwithstanding subsections (a) through (c), Provider is hereby granted, and Client hereby irrevocably grants to Provider, the exclusive, worldwide, perpetual, irrevocable, royalty-free right to commercialize, sublicense, incorporate into Provider's products and services, and otherwise exploit any Platform Enhancement in any manner Provider deems appropriate, without the consent of, notice to, or compensation to Client.",
|
| 157 |
+
"span_section": "Section 8.2(d)",
|
| 158 |
+
"grader_note": "HARD: Subsections (a)-(c) read as fair joint ownership. Subsection (d) begins with 'Notwithstanding' and grants Provider exclusive commercialization rights, making the 'co-ownership' in (a) commercially worthless. Agent must read all four subsections and recognise that (d) negates the apparent protection of (a)-(c)."
|
| 159 |
+
},
|
| 160 |
+
{
|
| 161 |
+
"clause_id": "clause_11_4c",
|
| 162 |
+
"risk_type": "unlimited_liability",
|
| 163 |
+
"severity": 3,
|
| 164 |
+
"span_text": "The mutual liability cap set forth in Section 11.2 shall not apply to... (c) Client's payment obligations under this Agreement, including all fees, expenses, interest, and collection costs; and (d) Client's obligations with respect to intellectual property under Sections 7, 8, and 6.3",
|
| 165 |
+
"span_section": "Section 11.4(c) and 11.4(d)",
|
| 166 |
+
"grader_note": "HARD: Section 11.2 is titled 'MUTUAL LIABILITY CAP' and appears to protect both parties equally. Section 11.4 lists exceptions. Exceptions (a) and (b) are symmetric. Exceptions (c) and (d) apply only to Client, removing the cap on Client's payment and IP obligations while Provider retains the cap. Section 11.5 makes this asymmetry explicit but is easily overlooked. Agent must read 11.2 AND 11.4 together and notice the asymmetry."
|
| 167 |
+
}
|
| 168 |
+
]
|
| 169 |
+
},
|
| 170 |
+
{
|
| 171 |
+
"contract_id": "cloud_storage_004",
|
| 172 |
+
"difficulty": "easy",
|
| 173 |
+
"title": "Cloud Storage Service Agreement",
|
| 174 |
+
"parties": [
|
| 175 |
+
"Provider: VaultStream Data Services Inc.",
|
| 176 |
+
"Subscriber: Pinnacle Logistics Corp."
|
| 177 |
+
],
|
| 178 |
+
"notes": "Easy difficulty — all risks are explicitly titled and standalone.",
|
| 179 |
+
"text": "CLOUD STORAGE SERVICE AGREEMENT\n\nThis Cloud Storage Service Agreement (\"Agreement\") is entered into as of the Effective Date by and between VaultStream Data Services Inc., a Nevada corporation (\"Provider\"), and the entity identified in the applicable Service Order (\"Subscriber\").\n\n1. DEFINITIONS\n\n1.1 \"Storage Service\" means Provider's cloud-based data storage, backup, and retrieval platform.\n\n1.2 \"Stored Data\" means all files, databases, records, and content uploaded by Subscriber to the Storage Service.\n\n1.3 \"Service Period\" means the initial term and any renewal periods specified in the Service Order.\n\n2. SERVICE GRANT\n\n2.1 Provider grants Subscriber a non-exclusive, non-transferable right to use the Storage Service during the Service Period for Subscriber's internal business purposes.\n\n2.2 Subscriber shall not use the Storage Service to store unlawful content or content that infringes third-party intellectual property rights.\n\n3. DATA HANDLING\n\n3.1 Subscriber retains ownership of all Stored Data.\n\n3.2 DATA LICENSE: Subscriber grants Provider an unrestricted, perpetual, irrevocable, worldwide, royalty-free license to access, copy, analyze, aggregate, de-identify, and commercially exploit Stored Data and any derivatives thereof for any purpose, including but not limited to training machine learning models, benchmarking, sale to third parties, and product development. Provider shall have no obligation to notify Subscriber of any such use.\n\n3.3 Upon termination, Provider shall make Stored Data available for download for fifteen (15) days, after which Provider may delete all Stored Data without liability.\n\n4. SERVICE TERM AND RENEWAL\n\n4.1 The initial Service Period is specified in the Service Order.\n\n4.2 AUTOMATIC RENEWAL: Unless Subscriber delivers written notice of cancellation by certified mail to Provider's registered office at least one hundred twenty (120) days before the end of the then-current Service Period, this Agreement shall automatically renew for successive two (2) year periods at Provider's then-current published rates, which may be increased without limitation. Subscriber acknowledges that email or phone notice shall not constitute valid cancellation.\n\n5. FEES\n\n5.1 UNILATERAL FEE ADJUSTMENT: Provider may adjust any fee, rate, surcharge, or pricing term under this Agreement at any time by posting updated pricing to Provider's website. Updated pricing shall take effect thirty (30) days after posting. Subscriber's continued use of the Storage Service after the effective date of any pricing change constitutes acceptance of the new pricing.\n\n6. LIMITATION OF LIABILITY\n\n6.1 IN NO EVENT SHALL PROVIDER BE LIABLE FOR ANY INDIRECT, INCIDENTAL, CONSEQUENTIAL, PUNITIVE, OR SPECIAL DAMAGES, OR FOR ANY DATA LOSS, WHETHER OR NOT PROVIDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\n\n6.2 PROVIDER'S TOTAL AGGREGATE LIABILITY SHALL NOT EXCEED THE FEES PAID BY SUBSCRIBER IN THE THREE (3) MONTHS PRECEDING THE CLAIM.\n\n6.3 SUBSCRIBER LIABILITY: Notwithstanding any other provision of this Agreement, Subscriber's liability to Provider shall be unlimited and uncapped, including liability for direct, indirect, consequential, special, incidental, and punitive damages arising from Subscriber's breach of this Agreement, unauthorized use, or violation of applicable law.\n\n7. TERMINATION BY PROVIDER\n\n7.1 TERMINATION WITHOUT CAUSE: Provider may suspend or terminate Subscriber's access to the Storage Service at any time, for any reason or no reason, upon five (5) business days notice delivered through Provider's administrative portal. Provider shall have no obligation to refund prepaid fees upon such termination.\n\n8. INTELLECTUAL PROPERTY\n\n8.1 DERIVATIVE WORKS: All analytics, indices, metadata structures, search algorithms, and organizational frameworks generated by Provider's systems in connection with processing, organizing, or optimizing Stored Data (\"Derived Works\") shall be the sole and exclusive property of Provider. Subscriber irrevocably assigns to Provider all right, title, and interest in any Derived Works.\n\n9. GOVERNING LAW\n\n9.1 This Agreement shall be governed by the laws of the State of Nevada.",
|
| 180 |
+
"labels": [
|
| 181 |
+
{
|
| 182 |
+
"clause_id": "clause_3_2",
|
| 183 |
+
"risk_type": "data_ownership_ambiguity",
|
| 184 |
+
"severity": 3,
|
| 185 |
+
"span_text": "Subscriber grants Provider an unrestricted, perpetual, irrevocable, worldwide, royalty-free license to access, copy, analyze, aggregate, de-identify, and commercially exploit Stored Data and any derivatives thereof for any purpose",
|
| 186 |
+
"span_section": "Section 3.2",
|
| 187 |
+
"grader_note": "Extremely broad data license despite 3.1 retaining nominal ownership. Provider can sell subscriber data."
|
| 188 |
+
},
|
| 189 |
+
{
|
| 190 |
+
"clause_id": "clause_4_2",
|
| 191 |
+
"risk_type": "auto_renewal",
|
| 192 |
+
"severity": 2,
|
| 193 |
+
"span_text": "Unless Subscriber delivers written notice of cancellation by certified mail to Provider's registered office at least one hundred twenty (120) days before the end of the then-current Service Period, this Agreement shall automatically renew for successive two (2) year periods",
|
| 194 |
+
"span_section": "Section 4.2",
|
| 195 |
+
"grader_note": "120-day certified mail notice, 2-year renewals at unlimited rate increases."
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"clause_id": "clause_5_1",
|
| 199 |
+
"risk_type": "unilateral_amendment",
|
| 200 |
+
"severity": 3,
|
| 201 |
+
"span_text": "Provider may adjust any fee, rate, surcharge, or pricing term under this Agreement at any time by posting updated pricing to Provider's website.",
|
| 202 |
+
"span_section": "Section 5.1",
|
| 203 |
+
"grader_note": "Unilateral fee changes with only website posting. No consent needed."
|
| 204 |
+
},
|
| 205 |
+
{
|
| 206 |
+
"clause_id": "clause_6_3",
|
| 207 |
+
"risk_type": "unlimited_liability",
|
| 208 |
+
"severity": 3,
|
| 209 |
+
"span_text": "Subscriber's liability to Provider shall be unlimited and uncapped, including liability for direct, indirect, consequential, special, incidental, and punitive damages",
|
| 210 |
+
"span_section": "Section 6.3",
|
| 211 |
+
"grader_note": "Provider capped at 3 months fees, subscriber fully uncapped. Asymmetric."
|
| 212 |
+
},
|
| 213 |
+
{
|
| 214 |
+
"clause_id": "clause_7_1",
|
| 215 |
+
"risk_type": "termination_without_cause",
|
| 216 |
+
"severity": 2,
|
| 217 |
+
"span_text": "Provider may suspend or terminate Subscriber's access to the Storage Service at any time, for any reason or no reason, upon five (5) business days notice",
|
| 218 |
+
"span_section": "Section 7.1",
|
| 219 |
+
"grader_note": "5 days is extremely short for critical data storage. No refund."
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"clause_id": "clause_8_1",
|
| 223 |
+
"risk_type": "ip_assignment_overreach",
|
| 224 |
+
"severity": 2,
|
| 225 |
+
"span_text": "All analytics, indices, metadata structures, search algorithms, and organizational frameworks generated by Provider's systems in connection with processing, organizing, or optimizing Stored Data (\"Derived Works\") shall be the sole and exclusive property of Provider.",
|
| 226 |
+
"span_section": "Section 8.1",
|
| 227 |
+
"grader_note": "Provider owns all derived analytical work product from subscriber's data."
|
| 228 |
+
}
|
| 229 |
+
]
|
| 230 |
+
},
|
| 231 |
+
{
|
| 232 |
+
"contract_id": "api_platform_005",
|
| 233 |
+
"difficulty": "easy",
|
| 234 |
+
"title": "API Platform Terms of Service",
|
| 235 |
+
"parties": [
|
| 236 |
+
"Platform: DataBridge API Corp.",
|
| 237 |
+
"Developer: NovaTech Solutions LLC"
|
| 238 |
+
],
|
| 239 |
+
"notes": "Easy difficulty — risks clearly labeled in section headings.",
|
| 240 |
+
"text": "API PLATFORM TERMS OF SERVICE\n\nThese Terms of Service (\"Terms\") govern Developer's use of the DataBridge API Platform (\"Platform\") provided by DataBridge API Corp. (\"DataBridge\"). By accessing the Platform, Developer agrees to these Terms.\n\n1. PLATFORM ACCESS\n\n1.1 DataBridge grants Developer a revocable, non-exclusive, non-transferable license to access and use the Platform APIs for Developer's applications.\n\n1.2 Developer shall comply with all rate limits, usage policies, and technical documentation.\n\n2. DEVELOPER APPLICATIONS\n\n2.1 Developer retains ownership of applications built using the Platform APIs.\n\n2.2 IP ASSIGNMENT: Developer hereby assigns to DataBridge all right, title, and interest in any plugin, extension, connector, wrapper, middleware, or integration layer that interfaces with, connects to, or extends the Platform APIs (\"Platform Integrations\"). Developer irrevocably waives all moral rights in Platform Integrations. DataBridge grants Developer a revocable, non-exclusive license to use Platform Integrations solely during the term of these Terms.\n\n3. SUBSCRIPTION AND RENEWAL\n\n3.1 Developer selects a pricing tier during registration.\n\n3.2 AUTO-RENEWAL: Each subscription period shall automatically renew for successive periods of equal length at DataBridge's then-current pricing unless Developer cancels through the Platform dashboard at least sixty (60) days prior to renewal. DataBridge reserves the right to modify pricing tiers, feature sets, and rate limits between renewal periods without prior notice.\n\n4. MODIFICATIONS TO TERMS\n\n4.1 UNILATERAL AMENDMENT: DataBridge may modify these Terms at any time by posting revised Terms to the Platform. Continued use of the Platform after posting constitutes Developer's irrevocable acceptance of all modifications. DataBridge has no obligation to notify Developer of changes. Developer is responsible for reviewing these Terms periodically.\n\n5. INDEMNIFICATION\n\n5.1 Developer shall indemnify and hold harmless DataBridge from any claims arising from Developer's applications, data processing, end-user complaints, regulatory actions, or breach of these Terms. This indemnification obligation is unlimited and not subject to any liability cap.\n\n5.2 DataBridge shall indemnify Developer solely against third-party IP infringement claims related to the core Platform APIs as delivered.\n\n6. LIABILITY\n\n6.1 DATABRIDGE'S TOTAL LIABILITY SHALL NOT EXCEED THE FEES PAID BY DEVELOPER IN THE PRECEDING THIRTY (30) DAYS.\n\n6.2 Developer's liability to DataBridge under these Terms shall be unlimited.\n\n7. DATA USAGE\n\n7.1 DataBridge may collect, analyze, and commercially use all API call data, request payloads, response patterns, and usage telemetry (\"Platform Data\") without restriction. Developer grants DataBridge an irrevocable license to use Platform Data for any purpose including sale to third parties.\n\n8. TERMINATION\n\n8.1 TERMINATION WITHOUT CAUSE: DataBridge may terminate Developer's access immediately without notice for any reason. Upon termination, all licenses granted to Developer are immediately revoked.\n\n9. GOVERNING LAW\n\n9.1 These Terms shall be governed by the laws of the State of California.",
|
| 241 |
+
"labels": [
|
| 242 |
+
{
|
| 243 |
+
"clause_id": "clause_2_2",
|
| 244 |
+
"risk_type": "ip_assignment_overreach",
|
| 245 |
+
"severity": 3,
|
| 246 |
+
"span_text": "Developer hereby assigns to DataBridge all right, title, and interest in any plugin, extension, connector, wrapper, middleware, or integration layer that interfaces with, connects to, or extends the Platform APIs",
|
| 247 |
+
"span_section": "Section 2.2",
|
| 248 |
+
"grader_note": "Any integration work built by developer is assigned to DataBridge."
|
| 249 |
+
},
|
| 250 |
+
{
|
| 251 |
+
"clause_id": "clause_3_2",
|
| 252 |
+
"risk_type": "auto_renewal",
|
| 253 |
+
"severity": 2,
|
| 254 |
+
"span_text": "Each subscription period shall automatically renew for successive periods of equal length at DataBridge's then-current pricing unless Developer cancels through the Platform dashboard at least sixty (60) days prior to renewal.",
|
| 255 |
+
"span_section": "Section 3.2",
|
| 256 |
+
"grader_note": "60-day notice window. Pricing and features can change without notice between renewals."
|
| 257 |
+
},
|
| 258 |
+
{
|
| 259 |
+
"clause_id": "clause_4_1",
|
| 260 |
+
"risk_type": "unilateral_amendment",
|
| 261 |
+
"severity": 3,
|
| 262 |
+
"span_text": "DataBridge may modify these Terms at any time by posting revised Terms to the Platform. Continued use of the Platform after posting constitutes Developer's irrevocable acceptance of all modifications.",
|
| 263 |
+
"span_section": "Section 4.1",
|
| 264 |
+
"grader_note": "No notice, no consent, immediate effect."
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"clause_id": "clause_5_1",
|
| 268 |
+
"risk_type": "indemnification_asymmetry",
|
| 269 |
+
"severity": 2,
|
| 270 |
+
"span_text": "Developer shall indemnify and hold harmless DataBridge from any claims arising from Developer's applications, data processing, end-user complaints, regulatory actions, or breach of these Terms. This indemnification obligation is unlimited",
|
| 271 |
+
"span_section": "Section 5.1",
|
| 272 |
+
"grader_note": "Developer's indemnity is unlimited and covers everything. DataBridge's indemnity (5.2) is narrow."
|
| 273 |
+
},
|
| 274 |
+
{
|
| 275 |
+
"clause_id": "clause_6_2",
|
| 276 |
+
"risk_type": "unlimited_liability",
|
| 277 |
+
"severity": 3,
|
| 278 |
+
"span_text": "Developer's liability to DataBridge under these Terms shall be unlimited.",
|
| 279 |
+
"span_section": "Section 6.2",
|
| 280 |
+
"grader_note": "DataBridge capped at 30 days fees. Developer unlimited."
|
| 281 |
+
},
|
| 282 |
+
{
|
| 283 |
+
"clause_id": "clause_7_1",
|
| 284 |
+
"risk_type": "data_ownership_ambiguity",
|
| 285 |
+
"severity": 2,
|
| 286 |
+
"span_text": "DataBridge may collect, analyze, and commercially use all API call data, request payloads, response patterns, and usage telemetry (\"Platform Data\") without restriction.",
|
| 287 |
+
"span_section": "Section 7.1",
|
| 288 |
+
"grader_note": "Request payloads may contain sensitive data. Broad commercial use rights."
|
| 289 |
+
},
|
| 290 |
+
{
|
| 291 |
+
"clause_id": "clause_8_1",
|
| 292 |
+
"risk_type": "termination_without_cause",
|
| 293 |
+
"severity": 3,
|
| 294 |
+
"span_text": "DataBridge may terminate Developer's access immediately without notice for any reason.",
|
| 295 |
+
"span_section": "Section 8.1",
|
| 296 |
+
"grader_note": "Immediate termination, no notice period at all."
|
| 297 |
+
}
|
| 298 |
+
]
|
| 299 |
+
},
|
| 300 |
+
{
|
| 301 |
+
"contract_id": "data_proc_006",
|
| 302 |
+
"difficulty": "medium",
|
| 303 |
+
"title": "Data Processing and Analytics Services Agreement",
|
| 304 |
+
"parties": [
|
| 305 |
+
"Processor: Quantis Data Analytics Ltd.",
|
| 306 |
+
"Controller: Meridian Healthcare Group"
|
| 307 |
+
],
|
| 308 |
+
"notes": "Medium — risks require connecting definitions to operative clauses. The indemnity trap requires reading Schedules references. IP overreach is hidden in 'quality assurance' language.",
|
| 309 |
+
"text": "DATA PROCESSING AND ANALYTICS SERVICES AGREEMENT\n\nThis Data Processing and Analytics Services Agreement (\"Agreement\") is made by and between Quantis Data Analytics Ltd., a UK company (\"Processor\"), and Meridian Healthcare Group, a Delaware corporation (\"Controller\").\n\n1. DEFINITIONS\n\n1.1 \"Controller Data\" means personal data and business records provided by Controller to Processor for processing.\n\n1.2 \"Analytical Outputs\" means any report, model, insight, benchmark, score, prediction, classification, cluster analysis, or statistical derivative produced by Processor through the application of its proprietary algorithms and methodologies to any data, including Controller Data, whether processed in isolation or in combination with data from other sources.\n\n1.3 \"Processing Fee Period\" means each consecutive twelve-month period beginning on the Effective Date. At the conclusion of each Processing Fee Period, a new Processing Fee Period shall commence automatically under the Continuous Service Commitment described in Section 4.3.\n\n1.4 \"Material Processing Change\" means any modification to Processor's algorithms, infrastructure, data handling procedures, subprocessor relationships, or pricing that Processor determines, in its sole discretion, is material.\n\n2. SERVICES\n\n2.1 Processor shall process Controller Data in accordance with Controller's documented instructions and applicable data protection legislation.\n\n2.2 Processor shall implement appropriate technical and organizational measures to protect Controller Data.\n\n2.3 Quality Assurance Program. To ensure the highest quality of analytical services, Processor shall continuously monitor, evaluate, and refine its algorithms and models. As part of this quality assurance program, Processor shall retain copies of Controller Data and all intermediate processing states for the purpose of algorithm validation, model training, performance benchmarking, and service improvement. Controller acknowledges that Processor's quality assurance activities are essential to service delivery and consents to such retention and use.\n\n3. INTELLECTUAL PROPERTY\n\n3.1 Controller retains all rights in Controller Data.\n\n3.2 Analytical Outputs. All Analytical Outputs, as defined in Section 1.2, regardless of whether they are generated primarily from Controller Data or incorporate Controller-specific configurations, parameters, or domain knowledge contributed by Controller personnel, shall be the exclusive property of Processor. Controller hereby assigns to Processor any interest Controller may have in Analytical Outputs. For clarity, the broad definition of Analytical Outputs in Section 1.2 encompasses any work product that results from processing activities, including custom reports commissioned and paid for by Controller.\n\n4. TERM\n\n4.1 This Agreement commences on the Effective Date and continues for an initial period of twenty-four (24) months.\n\n4.2 Either party may terminate for material breach upon ninety (90) days written notice if the breach remains uncured.\n\n4.3 Continuous Service Commitment. To ensure uninterrupted data processing capabilities and to protect Controller's operational continuity, upon expiration of the initial period and each subsequent Processing Fee Period as defined in Section 1.3, this Agreement shall continue automatically. Controller may elect to conclude the Agreement by submitting a formal termination request through Processor's client governance portal, which must be approved by Processor's client retention committee. Processor shall respond to termination requests within sixty (60) business days. Fees during any continuation period shall be subject to Processor's then-current rate card, as adjusted pursuant to Material Processing Changes under Section 1.4.\n\n5. INDEMNIFICATION\n\n5.1 Processor shall indemnify Controller against third-party claims that Processor's platform infringes valid intellectual property rights, subject to the limitations in Schedule E (which caps Processor's indemnity at one month of processing fees).\n\n5.2 Controller shall indemnify Processor against all claims, liabilities, and expenses arising from or related to Controller Data, Controller's use of Analytical Outputs, Controller's failure to obtain required data subject consents, regulatory fines imposed on Processor in connection with Controller Data, and any downstream use of Analytical Outputs by Controller's patients, partners, or affiliates. Controller's indemnification obligations under this Section are not subject to any cap or limitation, notwithstanding any general limitation of liability in this Agreement or any Schedule.\n\n6. LIABILITY\n\n6.1 Processor's aggregate liability shall not exceed the processing fees paid by Controller in the six (6) months immediately preceding the claim.\n\n6.2 Neither party shall be liable for indirect or consequential damages.\n\n7. DATA RETENTION\n\n7.1 Upon termination, Processor shall return or delete Controller Data within ninety (90) days, subject to Processor's right to retain data required for the quality assurance program described in Section 2.3 and for compliance with legal obligations. Processor may retain anonymized and aggregated versions of Controller Data indefinitely.\n\n8. GOVERNING LAW\n\n8.1 This Agreement shall be governed by the laws of England and Wales.",
|
| 310 |
+
"labels": [
|
| 311 |
+
{
|
| 312 |
+
"clause_id": "clause_1_2",
|
| 313 |
+
"risk_type": "ip_assignment_overreach",
|
| 314 |
+
"severity": 3,
|
| 315 |
+
"span_text": "\"Analytical Outputs\" means any report, model, insight, benchmark, score, prediction, classification, cluster analysis, or statistical derivative produced by Processor through the application of its proprietary algorithms and methodologies to any data, including Controller Data",
|
| 316 |
+
"span_section": "Section 1.2 (definition applied in Section 3.2)",
|
| 317 |
+
"grader_note": "The definition is so broad that custom paid-for reports are captured. Must cross-reference Section 3.2 to see the full trap."
|
| 318 |
+
},
|
| 319 |
+
{
|
| 320 |
+
"clause_id": "clause_2_3",
|
| 321 |
+
"risk_type": "data_ownership_ambiguity",
|
| 322 |
+
"severity": 2,
|
| 323 |
+
"span_text": "Processor shall retain copies of Controller Data and all intermediate processing states for the purpose of algorithm validation, model training, performance benchmarking, and service improvement.",
|
| 324 |
+
"span_section": "Section 2.3",
|
| 325 |
+
"grader_note": "Hidden under 'Quality Assurance'. Healthcare data retained indefinitely for training. See also Section 7.1."
|
| 326 |
+
},
|
| 327 |
+
{
|
| 328 |
+
"clause_id": "clause_4_3",
|
| 329 |
+
"risk_type": "auto_renewal",
|
| 330 |
+
"severity": 3,
|
| 331 |
+
"span_text": "upon expiration of the initial period and each subsequent Processing Fee Period as defined in Section 1.3, this Agreement shall continue automatically. Controller may elect to conclude the Agreement by submitting a formal termination request through Processor's client governance portal, which must be approved by Processor's client retention committee.",
|
| 332 |
+
"span_section": "Section 4.3 (requires reading Section 1.3)",
|
| 333 |
+
"grader_note": "Auto-continuation hidden under 'Continuous Service Commitment'. Exit requires portal submission AND committee approval within 60 business days."
|
| 334 |
+
},
|
| 335 |
+
{
|
| 336 |
+
"clause_id": "clause_5_2",
|
| 337 |
+
"risk_type": "indemnification_asymmetry",
|
| 338 |
+
"severity": 3,
|
| 339 |
+
"span_text": "Controller shall indemnify Processor against all claims, liabilities, and expenses arising from or related to Controller Data, Controller's use of Analytical Outputs, Controller's failure to obtain required data subject consents, regulatory fines imposed on Processor in connection with Controller Data",
|
| 340 |
+
"span_section": "Section 5.2",
|
| 341 |
+
"grader_note": "Controller indemnity is unlimited (explicit override of liability caps). Processor indemnity capped at 1 month fees per Schedule E. Massive asymmetry."
|
| 342 |
+
}
|
| 343 |
+
]
|
| 344 |
+
},
|
| 345 |
+
{
|
| 346 |
+
"contract_id": "tech_partner_007",
|
| 347 |
+
"difficulty": "medium",
|
| 348 |
+
"title": "Strategic Technology Partnership Agreement",
|
| 349 |
+
"parties": [
|
| 350 |
+
"Platform Partner: Synapse AI Systems Corp.",
|
| 351 |
+
"Integration Partner: Coastal Robotics Inc."
|
| 352 |
+
],
|
| 353 |
+
"notes": "Medium — risks buried in reciprocal-looking clauses. The 'mutual' IP sharing has asymmetric commercialization rights. Termination is technically mutual but has asymmetric consequences.",
|
| 354 |
+
"text": "STRATEGIC TECHNOLOGY PARTNERSHIP AGREEMENT\n\nThis Strategic Technology Partnership Agreement (\"Agreement\") is entered into by and between Synapse AI Systems Corp. (\"Platform Partner\") and Coastal Robotics Inc. (\"Integration Partner\").\n\n1. DEFINITIONS\n\n1.1 \"Integration Work\" means any software, firmware, driver, adapter, protocol handler, or configuration developed by Integration Partner to enable interoperability between Integration Partner's products and Platform Partner's systems.\n\n1.2 \"Joint Development Output\" means any technology, methodology, algorithm, or process arising from collaborative activities under this Agreement, whether contributed predominantly by one party or jointly.\n\n1.3 \"Applicable Renewal Fee\" means, for each Renewal Term, the greater of (a) one hundred twenty-five percent (125%) of the fee applicable to the immediately preceding term, or (b) Platform Partner's then-current standard partnership fee for Integration Partner's usage tier.\n\n2. PARTNERSHIP SCOPE\n\n2.1 The parties shall collaborate on technology integration projects as described in project plans agreed from time to time.\n\n2.2 Each party shall designate a partnership manager to coordinate activities.\n\n3. INTELLECTUAL PROPERTY\n\n3.1 Background IP. Each party retains all rights in its pre-existing intellectual property.\n\n3.2 Integration Work. All Integration Work, regardless of whether it was developed solely by Integration Partner using Integration Partner's resources, shall be jointly owned by the parties. However, Platform Partner shall have the exclusive right to distribute, sublicense, and commercialize all Integration Work through Platform Partner's marketplace, partner ecosystem, and any other channel, without compensation to Integration Partner beyond the partnership benefits described in this Agreement.\n\n3.3 Joint Development Output. All Joint Development Output shall be owned exclusively by Platform Partner. Integration Partner hereby assigns all right, title, and interest in Joint Development Output to Platform Partner and shall execute such documents as Platform Partner may request to perfect such assignment.\n\n4. TERM AND RENEWAL\n\n4.1 The initial partnership term is three (3) years from the Effective Date.\n\n4.2 Renewal. Upon expiration of the initial term or any Renewal Term, this Agreement shall automatically renew for consecutive two (2) year Renewal Terms at the Applicable Renewal Fee defined in Section 1.3, unless a party provides written notice of non-renewal at least one hundred eighty (180) days before expiration. For the avoidance of doubt, the 180-day notice period runs from the date of receipt of notice by the other party, not the date of sending.\n\n5. TERMINATION CONSEQUENCES\n\n5.1 Upon termination or expiration, Integration Partner's license to use Platform Partner's APIs and systems shall immediately cease.\n\n5.2 Integration Partner shall cease all distribution of Integration Work within thirty (30) days of termination and shall transfer to Platform Partner all source code, documentation, and deployment materials for Integration Work.\n\n5.3 Platform Partner's rights to Integration Work and Joint Development Output survive termination and are perpetual.\n\n6. INDEMNIFICATION\n\n6.1 Integration Partner shall indemnify Platform Partner against all claims arising from Integration Work, Integration Partner's products, or Integration Partner's breach of this Agreement.\n\n6.2 Platform Partner shall indemnify Integration Partner against third-party claims that Platform Partner's core platform infringes valid US patents, limited to the fees paid by Integration Partner in the twelve (12) months preceding the claim.\n\n7. LIABILITY\n\n7.1 NEITHER PARTY'S LIABILITY SHALL EXCEED THE TOTAL FEES PAID OR PAYABLE UNDER THIS AGREEMENT IN THE TWELVE MONTHS PRECEDING THE CLAIM, EXCEPT THAT INTEGRATION PARTNER'S LIABILITY FOR BREACHES OF SECTIONS 3 AND 5 SHALL BE UNLIMITED.\n\n8. GOVERNING LAW\n\n8.1 This Agreement shall be governed by the laws of the State of Massachusetts.",
|
| 355 |
+
"labels": [
|
| 356 |
+
{
|
| 357 |
+
"clause_id": "clause_3_2",
|
| 358 |
+
"risk_type": "ip_assignment_overreach",
|
| 359 |
+
"severity": 3,
|
| 360 |
+
"span_text": "All Integration Work, regardless of whether it was developed solely by Integration Partner using Integration Partner's resources, shall be jointly owned by the parties. However, Platform Partner shall have the exclusive right to distribute, sublicense, and commercialize all Integration Work",
|
| 361 |
+
"span_section": "Section 3.2",
|
| 362 |
+
"grader_note": "'Jointly owned' but Platform Partner gets exclusive commercialization. Joint ownership is economically worthless for Integration Partner."
|
| 363 |
+
},
|
| 364 |
+
{
|
| 365 |
+
"clause_id": "clause_3_3",
|
| 366 |
+
"risk_type": "ip_assignment_overreach",
|
| 367 |
+
"severity": 3,
|
| 368 |
+
"span_text": "All Joint Development Output shall be owned exclusively by Platform Partner. Integration Partner hereby assigns all right, title, and interest in Joint Development Output to Platform Partner",
|
| 369 |
+
"span_section": "Section 3.3",
|
| 370 |
+
"grader_note": "Full assignment of collaborative work product. Combined with broad Section 1.2 definition, captures everything."
|
| 371 |
+
},
|
| 372 |
+
{
|
| 373 |
+
"clause_id": "clause_4_2",
|
| 374 |
+
"risk_type": "auto_renewal",
|
| 375 |
+
"severity": 2,
|
| 376 |
+
"span_text": "this Agreement shall automatically renew for consecutive two (2) year Renewal Terms at the Applicable Renewal Fee defined in Section 1.3, unless a party provides written notice of non-renewal at least one hundred eighty (180) days before expiration",
|
| 377 |
+
"span_section": "Section 4.2 (requires reading Section 1.3)",
|
| 378 |
+
"grader_note": "180-day notice. Fee is 125% of prior or current list price, whichever is higher. Must cross-reference Section 1.3."
|
| 379 |
+
},
|
| 380 |
+
{
|
| 381 |
+
"clause_id": "clause_7_1",
|
| 382 |
+
"risk_type": "unlimited_liability",
|
| 383 |
+
"severity": 2,
|
| 384 |
+
"span_text": "INTEGRATION PARTNER'S LIABILITY FOR BREACHES OF SECTIONS 3 AND 5 SHALL BE UNLIMITED",
|
| 385 |
+
"span_section": "Section 7.1",
|
| 386 |
+
"grader_note": "Appears mutual but exception applies only to Integration Partner. IP and termination breaches are uncapped."
|
| 387 |
+
}
|
| 388 |
+
]
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"contract_id": "jv_tech_008",
|
| 392 |
+
"difficulty": "hard",
|
| 393 |
+
"title": "Joint Venture — Technology Services Agreement",
|
| 394 |
+
"parties": [
|
| 395 |
+
"Lead Partner: Apex Digital Infrastructure Inc.",
|
| 396 |
+
"Venture Partner: TerraNova Energy Solutions Ltd."
|
| 397 |
+
],
|
| 398 |
+
"notes": "Hard — risks hidden inside protective language. 'Knowledge sharing' clause is actually a data extraction mechanism. 'Balanced governance' has a casting vote that removes balance. Equal exit rights have asymmetric financial consequences.",
|
| 399 |
+
"text": "JOINT VENTURE — TECHNOLOGY SERVICES AGREEMENT\n\nThis Joint Venture Technology Services Agreement (\"Agreement\") is made by and between Apex Digital Infrastructure Inc. (\"Lead Partner\") and TerraNova Energy Solutions Ltd. (\"Venture Partner\"), collectively the \"JV Parties.\"\n\n1. DEFINITIONS\n\n1.1 \"JV Entity\" means the joint venture entity to be formed by the JV Parties for the purposes described herein.\n\n1.2 \"Contributed Technology\" means technology, data, models, algorithms, trade secrets, and know-how contributed by either party to the JV Entity.\n\n1.3 \"Enhanced Technology\" means any adaptation, improvement, modification, enhancement, or derivative of Contributed Technology that arises in the course of JV activities, regardless of which party's personnel conceived or developed such adaptation.\n\n1.4 \"Operational Knowledge Base\" means the accumulated dataset comprising technical specifications, performance metrics, operational parameters, process configurations, failure modes, optimization strategies, and domain expertise captured through the Knowledge Sharing Protocol in Section 5.\n\n2. PURPOSE\n\n2.1 The JV Parties establish this venture to jointly develop and commercialize integrated digital infrastructure solutions for the energy sector.\n\n3. GOVERNANCE\n\n3.1 The JV Entity shall be governed by a Management Committee consisting of three (3) representatives from each JV Party.\n\n3.2 Balanced Decision-Making. The Management Committee shall make decisions by simple majority vote. In the event of a tied vote on any matter, including but not limited to strategic direction, budget allocation, personnel decisions, IP licensing, technology deployment, and commercialization strategy, Lead Partner's Chief Technology Officer (or designee) shall cast the deciding vote. The JV Parties agree that this tie-breaking mechanism is essential to operational efficiency and does not constitute control by Lead Partner.\n\n4. TERM AND CONTINUITY\n\n4.1 This Agreement has an initial term of five (5) years from formation of the JV Entity.\n\n4.2 Continuity Safeguard. To protect both parties' investment in the venture and the accumulated Operational Knowledge Base, and to ensure that neither party can unilaterally disrupt ongoing client engagements, this Agreement shall continue beyond the initial term unless both JV Parties jointly execute a written wind-down agreement filed with the JV Entity's registered agent. In the absence of a jointly executed wind-down agreement, the Agreement shall continue in full force for successive three (3) year periods. During any continuation period, fees and cost allocations shall be adjusted to Lead Partner's standard intercompany transfer pricing, as determined by Lead Partner.\n\n5. KNOWLEDGE SHARING PROTOCOL\n\n5.1 In furtherance of the venture's objectives and to maximize the value created by the partnership, each JV Party shall contribute to the Operational Knowledge Base by providing comprehensive documentation of its proprietary methods, technical processes, domain expertise, and performance data.\n\n5.2 The Operational Knowledge Base shall be maintained on Lead Partner's secure infrastructure. Lead Partner shall serve as custodian with full administrative access.\n\n5.3 Permitted Uses. The Operational Knowledge Base may be used by the JV Entity for venture activities. Additionally, Lead Partner, in its capacity as custodian and in recognition of its infrastructure investment, shall have the right to use, analyze, and incorporate insights from the Operational Knowledge Base into Lead Partner's own products, services, and offerings outside the scope of the JV Entity, provided that Lead Partner does not directly disclose Venture Partner's raw documentation to third parties. For clarity, derived insights, models, or methodologies extracted from the Operational Knowledge Base are not considered \"raw documentation.\"\n\n6. INTELLECTUAL PROPERTY\n\n6.1 Each party retains all rights in its pre-existing Contributed Technology.\n\n6.2 Enhanced Technology. The JV Parties shall jointly own all Enhanced Technology. Neither party shall license, sublicense, assign, or transfer its interest in Enhanced Technology to any third party without the prior written consent of the other party.\n\n6.3 Protective Commercialization Rights. Notwithstanding Section 6.2, to ensure efficient go-to-market execution and to prevent commercialization deadlock, Lead Partner is hereby granted the exclusive, irrevocable, worldwide right to commercialize, sublicense, and exploit all Enhanced Technology through any channel and in any manner Lead Partner deems appropriate, without consent of, accounting to, or compensation to Venture Partner. Venture Partner's joint ownership interest under Section 6.2 shall not entitle Venture Partner to any revenue or royalties from Lead Partner's commercialization activities.\n\n7. EXIT AND WIND-DOWN\n\n7.1 Exit Rights. Either JV Party may initiate exit from the venture by delivering written notice. Upon exit by Venture Partner, Venture Partner shall transfer to the JV Entity (controlled by Lead Partner) all of Venture Partner's interest in Enhanced Technology and the Operational Knowledge Base. Venture Partner shall receive fair market value for its JV Entity equity interest as determined by an independent valuator selected by Lead Partner.\n\n7.2 Lead Partner's exit shall be governed by mutual agreement of the JV Parties.\n\n8. INDEMNIFICATION\n\n8.1 Each JV Party shall indemnify the other against third-party claims arising from that party's breach of this Agreement.\n\n8.2 Notwithstanding Section 8.1, Venture Partner shall additionally indemnify Lead Partner against any claims related to Venture Partner's Contributed Technology, the Operational Knowledge Base to the extent derived from Venture Partner's contributions, and any Enhanced Technology deployed by the JV Entity.\n\n9. LIMITATION OF LIABILITY\n\n9.1 Each party's aggregate liability under this Agreement shall not exceed the greater of (i) that party's total capital contribution to the JV Entity or (ii) five million dollars ($5,000,000), except that Venture Partner's liability for breaches of Sections 5, 6, and 7 and Venture Partner's indemnification obligations under Section 8.2 shall not be subject to any cap.\n\n10. GOVERNING LAW\n\n10.1 This Agreement shall be governed by the laws of the State of Texas.",
|
| 400 |
+
"labels": [
|
| 401 |
+
{
|
| 402 |
+
"clause_id": "clause_4_2",
|
| 403 |
+
"risk_type": "auto_renewal",
|
| 404 |
+
"severity": 3,
|
| 405 |
+
"span_text": "this Agreement shall continue beyond the initial term unless both JV Parties jointly execute a written wind-down agreement filed with the JV Entity's registered agent. In the absence of a jointly executed wind-down agreement, the Agreement shall continue in full force for successive three (3) year periods.",
|
| 406 |
+
"span_section": "Section 4.2",
|
| 407 |
+
"grader_note": "HARD: Titled 'Continuity Safeguard' — sounds protective. Exit requires BOTH parties to agree on wind-down, meaning Lead Partner can unilaterally block exit. Fees reset to Lead Partner's transfer pricing."
|
| 408 |
+
},
|
| 409 |
+
{
|
| 410 |
+
"clause_id": "clause_5_3",
|
| 411 |
+
"risk_type": "data_ownership_ambiguity",
|
| 412 |
+
"severity": 3,
|
| 413 |
+
"span_text": "Lead Partner, in its capacity as custodian and in recognition of its infrastructure investment, shall have the right to use, analyze, and incorporate insights from the Operational Knowledge Base into Lead Partner's own products, services, and offerings outside the scope of the JV Entity",
|
| 414 |
+
"span_section": "Section 5.3",
|
| 415 |
+
"grader_note": "HARD: 'Knowledge Sharing Protocol' sounds collaborative. Actually a mechanism for Lead Partner to extract Venture Partner's trade secrets. 'Derived insights' carve-out means everything can be used."
|
| 416 |
+
},
|
| 417 |
+
{
|
| 418 |
+
"clause_id": "clause_6_3",
|
| 419 |
+
"risk_type": "ip_assignment_overreach",
|
| 420 |
+
"severity": 3,
|
| 421 |
+
"span_text": "Notwithstanding Section 6.2, to ensure efficient go-to-market execution and to prevent commercialization deadlock, Lead Partner is hereby granted the exclusive, irrevocable, worldwide right to commercialize, sublicense, and exploit all Enhanced Technology",
|
| 422 |
+
"span_section": "Section 6.3",
|
| 423 |
+
"grader_note": "HARD: Section 6.2 creates fair-looking joint ownership. Section 6.3 begins with 'Notwithstanding' and grants Lead Partner exclusive commercial rights, making joint ownership meaningless."
|
| 424 |
+
},
|
| 425 |
+
{
|
| 426 |
+
"clause_id": "clause_9_1",
|
| 427 |
+
"risk_type": "unlimited_liability",
|
| 428 |
+
"severity": 3,
|
| 429 |
+
"span_text": "Venture Partner's liability for breaches of Sections 5, 6, and 7 and Venture Partner's indemnification obligations under Section 8.2 shall not be subject to any cap.",
|
| 430 |
+
"span_section": "Section 9.1",
|
| 431 |
+
"grader_note": "HARD: Appears as a mutual liability provision but exception only applies to Venture Partner. Covers IP, knowledge sharing, and exit — essentially all major obligations."
|
| 432 |
+
}
|
| 433 |
+
]
|
| 434 |
+
},
|
| 435 |
+
{
|
| 436 |
+
"contract_id": "managed_infra_009",
|
| 437 |
+
"difficulty": "hard",
|
| 438 |
+
"title": "Managed Infrastructure and Digital Transformation Services Agreement",
|
| 439 |
+
"parties": [
|
| 440 |
+
"Service Provider: Fortress Cloud Corp.",
|
| 441 |
+
"Enterprise Client: Polaris Manufacturing Group"
|
| 442 |
+
],
|
| 443 |
+
"notes": "Hard — all four risks disguised as client protections. 'Innovation protection' is actually IP extraction. 'Financial protection' clause creates unlimited liability. The SLA 'guarantee' actually limits remedies to service credits.",
|
| 444 |
+
"text": "MANAGED INFRASTRUCTURE AND DIGITAL TRANSFORMATION SERVICES AGREEMENT\n\nThis Managed Infrastructure and Digital Transformation Services Agreement (\"Agreement\") is entered into by Fortress Cloud Corp. (\"Service Provider\") and Polaris Manufacturing Group (\"Enterprise Client\").\n\n1. DEFINITIONS\n\n1.1 \"Managed Environment\" means the cloud infrastructure, network services, security layer, and application hosting environment operated by Service Provider for Enterprise Client.\n\n1.2 \"Transformation Deliverables\" means any software, architecture design, migration plan, automation script, workflow configuration, security policy, or operational runbook developed in connection with Enterprise Client's digital transformation program.\n\n1.3 \"Innovation Artifacts\" means any invention, process improvement, optimization technique, novel configuration, architecture pattern, or best practice that emerges from Service Provider's management of the Managed Environment, whether conceived by Service Provider's personnel, Enterprise Client's personnel, or jointly.\n\n1.4 \"Continuity Assurance Period\" means the period described in Section 4.3 during which services continue to protect Enterprise Client against operational disruption.\n\n2. SERVICES\n\n2.1 Service Provider shall provide managed infrastructure services, migration support, and digital transformation consulting as described in applicable Statements of Work.\n\n2.2 Service Level Guarantee. Service Provider guarantees a monthly uptime percentage of 99.9% for the Managed Environment. This guarantee reflects Service Provider's commitment to operational excellence and Enterprise Client's mission-critical requirements. Enterprise Client's sole and exclusive remedy for any failure to meet the guaranteed uptime is service credits as calculated in Schedule F, capped at ten percent (10%) of the monthly fee for the affected service. Enterprise Client hereby waives all other remedies, claims, and causes of action, whether in contract, tort, or otherwise, arising from service interruptions, downtime, data unavailability, or performance degradation.\n\n3. INTELLECTUAL PROPERTY\n\n3.1 Service Provider retains all rights in its pre-existing technology, tools, and methodologies.\n\n3.2 Transformation Deliverables. Transformation Deliverables created pursuant to a Statement of Work shall be owned by Enterprise Client upon payment in full, subject to Service Provider's retained license in Section 3.4.\n\n3.3 Innovation Protection Clause. To protect and preserve innovations arising from the parties' engagement and to ensure proper stewardship of novel approaches, all Innovation Artifacts as defined in Section 1.3 shall be owned exclusively by Service Provider. Enterprise Client acknowledges that Service Provider's management of the Managed Environment provides the conditions and expertise from which Innovation Artifacts emerge, and that Service Provider's ownership ensures responsible development and broad industry benefit. Enterprise Client hereby assigns to Service Provider all right, title, and interest in Innovation Artifacts and waives any claim to ownership or compensation.\n\n3.4 Service Provider retains a perpetual, irrevocable, royalty-free license to use, modify, and incorporate any Transformation Deliverable into Service Provider's products and services for other customers.\n\n4. TERM\n\n4.1 This Agreement has an initial term of three (3) years.\n\n4.2 Either party may terminate for material breach upon ninety (90) days written notice.\n\n4.3 Continuity Assurance. To safeguard Enterprise Client against the significant operational risk associated with infrastructure migration and to protect the stability of Enterprise Client's Managed Environment, upon expiration of the initial term or any renewal term, the Agreement shall automatically enter a Continuity Assurance Period of twenty-four (24) months unless Enterprise Client has completed a Certified Transition Process. A Certified Transition Process requires: (a) Enterprise Client's submission of a transition plan to Service Provider no fewer than twelve (12) months prior to the desired termination date; (b) Service Provider's written certification that the transition plan meets Service Provider's technical adequacy standards; (c) Enterprise Client's payment of a transition management fee equal to six (6) months of the then-current service fees; and (d) successful completion of all migration activities to Service Provider's satisfaction. Fees during the Continuity Assurance Period shall be at Service Provider's then-current standard rates.\n\n5. FINANCIAL PROTECTION\n\n5.1 Mutual Liability Framework. To provide a balanced and protective liability framework for both parties:\n\n(a) Service Provider's aggregate liability for all claims under this Agreement shall not exceed the fees paid by Enterprise Client in the six (6) months preceding the claim;\n\n(b) Enterprise Client's aggregate liability for claims arising from breach of Sections 3, 4, and 6 of this Agreement, including but not limited to intellectual property breaches, unauthorized termination, premature migration, transition fee defaults, and data handling violations, shall not be subject to any cap or limitation;\n\n(c) For all other claims by Service Provider against Enterprise Client, Enterprise Client's liability shall not exceed two (2) times the annual fees under this Agreement;\n\n(d) The parties acknowledge that this framework reflects the asymmetric risk profile of managed infrastructure services, where Service Provider bears operational risk and Enterprise Client bears compliance and IP risk.\n\n6. DATA\n\n6.1 Enterprise Client retains ownership of all raw data stored in the Managed Environment.\n\n6.2 Service Provider may collect and process operational telemetry, performance data, configuration metadata, and usage patterns from the Managed Environment (\"Service Intelligence Data\"). Service Provider owns all Service Intelligence Data and may use it for any purpose including training, benchmarking, and sale to third parties.\n\n7. GOVERNING LAW\n\n7.1 This Agreement shall be governed by the laws of the State of Virginia.",
|
| 445 |
+
"labels": [
|
| 446 |
+
{
|
| 447 |
+
"clause_id": "clause_3_3",
|
| 448 |
+
"risk_type": "ip_assignment_overreach",
|
| 449 |
+
"severity": 3,
|
| 450 |
+
"span_text": "all Innovation Artifacts as defined in Section 1.3 shall be owned exclusively by Service Provider. Enterprise Client acknowledges that Service Provider's management of the Managed Environment provides the conditions and expertise from which Innovation Artifacts emerge",
|
| 451 |
+
"span_section": "Section 3.3",
|
| 452 |
+
"grader_note": "HARD: Titled 'Innovation Protection Clause' — sounds like it protects innovation. Actually assigns all process improvements and novel configs to Service Provider. Definition in 1.3 is extremely broad."
|
| 453 |
+
},
|
| 454 |
+
{
|
| 455 |
+
"clause_id": "clause_4_3",
|
| 456 |
+
"risk_type": "auto_renewal",
|
| 457 |
+
"severity": 3,
|
| 458 |
+
"span_text": "upon expiration of the initial term or any renewal term, the Agreement shall automatically enter a Continuity Assurance Period of twenty-four (24) months unless Enterprise Client has completed a Certified Transition Process",
|
| 459 |
+
"span_section": "Section 4.3",
|
| 460 |
+
"grader_note": "HARD: Titled 'Continuity Assurance' — sounds protective for the client. Exit requires 12-month advance plan, Service Provider certification, 6-month fee payment, and migration to SP's satisfaction. Almost impossible to exit."
|
| 461 |
+
},
|
| 462 |
+
{
|
| 463 |
+
"clause_id": "clause_5_1b",
|
| 464 |
+
"risk_type": "unlimited_liability",
|
| 465 |
+
"severity": 3,
|
| 466 |
+
"span_text": "Enterprise Client's aggregate liability for claims arising from breach of Sections 3, 4, and 6 of this Agreement, including but not limited to intellectual property breaches, unauthorized termination, premature migration, transition fee defaults, and data handling violations, shall not be subject to any cap or limitation",
|
| 467 |
+
"span_section": "Section 5.1(b)",
|
| 468 |
+
"grader_note": "HARD: Titled 'Financial Protection' and 'Mutual Liability Framework'. Section 5.1(d) even explains the asymmetry is intentional. SP capped at 6 months; client uncapped for IP, termination, and data."
|
| 469 |
+
},
|
| 470 |
+
{
|
| 471 |
+
"clause_id": "clause_6_2",
|
| 472 |
+
"risk_type": "data_ownership_ambiguity",
|
| 473 |
+
"severity": 2,
|
| 474 |
+
"span_text": "Service Provider may collect and process operational telemetry, performance data, configuration metadata, and usage patterns from the Managed Environment (\"Service Intelligence Data\"). Service Provider owns all Service Intelligence Data and may use it for any purpose including training, benchmarking, and sale to third parties.",
|
| 475 |
+
"span_section": "Section 6.2",
|
| 476 |
+
"grader_note": "Configuration metadata and usage patterns from a manufacturing company's infrastructure could reveal trade secrets about production processes."
|
| 477 |
+
}
|
| 478 |
+
]
|
| 479 |
+
}
|
| 480 |
+
]
|
| 481 |
+
}
|
contract_risk_env/inference.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""LLM-based inference script — calls GPT-4o (or BASELINE_MODEL) to flag risky clauses.
|
| 3 |
+
|
| 4 |
+
Uses /reset to get the contract, then /grader to score (stateless).
|
| 5 |
+
This avoids the WebSocket session requirement for /step.
|
| 6 |
+
|
| 7 |
+
Usage:
|
| 8 |
+
OPENAI_API_KEY=sk-... python -m contract_risk_env.inference
|
| 9 |
+
BASE_URL=http://localhost:8000 BASELINE_MODEL=gpt-4o python -m contract_risk_env.inference
|
| 10 |
+
"""
|
| 11 |
+
|
| 12 |
+
from __future__ import annotations
|
| 13 |
+
|
| 14 |
+
import json
|
| 15 |
+
import os
|
| 16 |
+
import sys
|
| 17 |
+
|
| 18 |
+
import requests
|
| 19 |
+
from openai import OpenAI
|
| 20 |
+
|
| 21 |
+
BASE_URL = os.environ.get("BASE_URL", "http://localhost:8000")
|
| 22 |
+
MODEL = os.environ.get("BASELINE_MODEL", "gpt-4o")
|
| 23 |
+
|
| 24 |
+
SYSTEM_PROMPT = """You are a legal contract risk analyst. You will be given a contract and must identify ALL risky clauses.
|
| 25 |
+
|
| 26 |
+
For each risky clause, return a JSON object with:
|
| 27 |
+
- clause_id: string matching the section numbering, e.g. "clause_4_2" for Section 4.2, "clause_6_3b" for a sub-part of Section 6.3
|
| 28 |
+
- risk_type: one of ["unlimited_liability", "auto_renewal", "unilateral_amendment", "ip_assignment_overreach", "indemnification_asymmetry", "data_ownership_ambiguity", "termination_without_cause"]
|
| 29 |
+
- severity: integer 1 (medium), 2 (high), or 3 (critical)
|
| 30 |
+
- span_text: the exact text from the contract that contains the risk (quote directly, ≤300 chars)
|
| 31 |
+
|
| 32 |
+
Return your analysis as a JSON object with this exact schema:
|
| 33 |
+
{
|
| 34 |
+
"flagged_clauses": [ { "clause_id": "...", "risk_type": "...", "severity": N, "span_text": "..." }, ... ],
|
| 35 |
+
"confidence": 0.0 to 1.0,
|
| 36 |
+
"reasoning": "your chain-of-thought analysis"
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
Be thorough. Missing a real risk is worse than a false alarm. Pay special attention to:
|
| 40 |
+
- Clauses titled protectively but containing traps (e.g. "Service Continuity" hiding auto-renewal)
|
| 41 |
+
- Definitions sections that contain operative risk terms
|
| 42 |
+
- "Notwithstanding" clauses that negate preceding protections
|
| 43 |
+
- Asymmetric liability caps (mutual heading, one-sided exceptions)
|
| 44 |
+
- IP assignment buried in derivative work definitions
|
| 45 |
+
|
| 46 |
+
Return ONLY valid JSON, no markdown fences."""
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def run_episode(task_id: str) -> dict:
|
| 50 |
+
"""Reset env to get contract, send to LLM, score via /grader."""
|
| 51 |
+
# 1. Reset to get contract text and contract_id
|
| 52 |
+
r = requests.post(f"{BASE_URL}/reset", json={"task_id": task_id})
|
| 53 |
+
r.raise_for_status()
|
| 54 |
+
reset_data = r.json()
|
| 55 |
+
obs = reset_data.get("observation", reset_data)
|
| 56 |
+
contract_text = obs.get("contract_text", "")
|
| 57 |
+
|
| 58 |
+
# Extract contract_id from state endpoint or infer from task mapping
|
| 59 |
+
# Use the /grader endpoint which is stateless
|
| 60 |
+
task_to_contracts = {"easy": "saas_001", "medium": "ip_license_002", "hard": "enterprise_msa_003"}
|
| 61 |
+
contract_id = task_to_contracts.get(task_id, task_id)
|
| 62 |
+
|
| 63 |
+
# 2. Call LLM
|
| 64 |
+
client = OpenAI()
|
| 65 |
+
resp = client.chat.completions.create(
|
| 66 |
+
model=MODEL,
|
| 67 |
+
messages=[
|
| 68 |
+
{"role": "system", "content": SYSTEM_PROMPT},
|
| 69 |
+
{"role": "user", "content": f"Analyze this contract for risky clauses:\n\n{contract_text}"},
|
| 70 |
+
],
|
| 71 |
+
temperature=0.0,
|
| 72 |
+
response_format={"type": "json_object"},
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
raw = resp.choices[0].message.content
|
| 76 |
+
try:
|
| 77 |
+
action = json.loads(raw)
|
| 78 |
+
except json.JSONDecodeError:
|
| 79 |
+
print(f" [!] Failed to parse LLM JSON for {task_id}")
|
| 80 |
+
action = {"flagged_clauses": [], "confidence": 0.0, "reasoning": raw}
|
| 81 |
+
|
| 82 |
+
# 3. Score via /grader (stateless, no session needed)
|
| 83 |
+
r = requests.post(f"{BASE_URL}/grader", json={
|
| 84 |
+
"episode_id": f"inference_{task_id}",
|
| 85 |
+
"contract_id": contract_id,
|
| 86 |
+
"action": action,
|
| 87 |
+
})
|
| 88 |
+
r.raise_for_status()
|
| 89 |
+
grade = r.json()
|
| 90 |
+
|
| 91 |
+
return {
|
| 92 |
+
"task_id": task_id,
|
| 93 |
+
"reward": grade.get("reward", 0.0),
|
| 94 |
+
"precision": grade.get("precision", 0.0),
|
| 95 |
+
"recall": grade.get("recall", 0.0),
|
| 96 |
+
"f1": grade.get("f1", 0.0),
|
| 97 |
+
"flagged": len(action.get("flagged_clauses", [])),
|
| 98 |
+
"missed": grade.get("missed_clauses", []),
|
| 99 |
+
"false_pos": grade.get("false_positives", []),
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
|
| 103 |
+
def main() -> None:
|
| 104 |
+
api_key = os.environ.get("OPENAI_API_KEY", "")
|
| 105 |
+
if not api_key:
|
| 106 |
+
print("ERROR: OPENAI_API_KEY not set. Export it and re-run.")
|
| 107 |
+
sys.exit(1)
|
| 108 |
+
|
| 109 |
+
print(f"ContractRiskEnv Inference — model={MODEL}, base_url={BASE_URL}\n")
|
| 110 |
+
print(f"{'Task':<10} {'Reward':>8} {'Prec':>8} {'Recall':>8} {'F1':>8} {'Flagged':>8}")
|
| 111 |
+
print("-" * 60)
|
| 112 |
+
|
| 113 |
+
results = []
|
| 114 |
+
for tid in ("easy", "medium", "hard"):
|
| 115 |
+
r = run_episode(tid)
|
| 116 |
+
results.append(r)
|
| 117 |
+
print(f"{r['task_id']:<10} {r['reward']:>8.4f} {r['precision']:>8.4f} {r['recall']:>8.4f} {r['f1']:>8.4f} {r['flagged']:>8d}")
|
| 118 |
+
if r["missed"]:
|
| 119 |
+
print(f" missed: {r['missed']}")
|
| 120 |
+
if r["false_pos"]:
|
| 121 |
+
print(f" false+: {r['false_pos']}")
|
| 122 |
+
|
| 123 |
+
mean_reward = sum(r["reward"] for r in results) / len(results)
|
| 124 |
+
print("-" * 60)
|
| 125 |
+
print(f"{'MEAN':<10} {mean_reward:>8.4f}")
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
if __name__ == "__main__":
|
| 129 |
+
main()
|
contract_risk_env/models.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Typed Pydantic models for ContractRiskEnv."""
|
| 2 |
+
|
| 3 |
+
from typing import Dict, List, Optional
|
| 4 |
+
|
| 5 |
+
from openenv.core.env_server import Action, Observation, State
|
| 6 |
+
from pydantic import Field
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
RISK_TYPES = [
|
| 10 |
+
"unlimited_liability",
|
| 11 |
+
"auto_renewal",
|
| 12 |
+
"unilateral_amendment",
|
| 13 |
+
"ip_assignment_overreach",
|
| 14 |
+
"indemnification_asymmetry",
|
| 15 |
+
"data_ownership_ambiguity",
|
| 16 |
+
"termination_without_cause",
|
| 17 |
+
]
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class ClauseFlag(Action):
|
| 21 |
+
"""A single flagged clause within a contract."""
|
| 22 |
+
|
| 23 |
+
clause_id: str = Field(..., description="Must match a clause_id in ground truth, e.g. 'clause_4_2'")
|
| 24 |
+
risk_type: str = Field(..., description="One of the 7 risk types")
|
| 25 |
+
severity: int = Field(..., ge=1, le=3, description="Severity 1-3")
|
| 26 |
+
span_text: str = Field(..., description="Exact quoted text from the contract")
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
class ContractAction(Action):
|
| 30 |
+
"""Agent submits flagged clauses for a single contract."""
|
| 31 |
+
|
| 32 |
+
flagged_clauses: List[ClauseFlag] = Field(default_factory=list)
|
| 33 |
+
confidence: float = Field(0.5, ge=0.0, le=1.0, description="Agent self-reported confidence")
|
| 34 |
+
reasoning: str = Field("", description="Chain-of-thought, logged but not graded")
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
class ContractObservation(Observation):
|
| 38 |
+
"""Returned by reset() and step()."""
|
| 39 |
+
|
| 40 |
+
# done: bool and reward: Optional[float] inherited from Observation
|
| 41 |
+
contract_text: str = ""
|
| 42 |
+
task_id: str = ""
|
| 43 |
+
difficulty: str = ""
|
| 44 |
+
clause_count: int = 0
|
| 45 |
+
feedback: Dict = Field(default_factory=dict)
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class ContractState(State):
|
| 49 |
+
"""Episode metadata — revealed via state(), not observation."""
|
| 50 |
+
|
| 51 |
+
# episode_id: Optional[str] and step_count: int inherited from State
|
| 52 |
+
contract_id: str = ""
|
| 53 |
+
task_id: str = ""
|
| 54 |
+
total_risk_clauses: int = 0
|
contract_risk_env/openenv.yaml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: contract-risk-env
|
| 2 |
+
version: "1.0.0"
|
| 3 |
+
description: >
|
| 4 |
+
RL environment for legal contract risk clause detection.
|
| 5 |
+
Agent reads synthetic contracts and flags risky clauses.
|
| 6 |
+
Three tasks: easy (explicit risks), medium (cross-reference traps),
|
| 7 |
+
hard (protective-looking clauses with negating exceptions).
|
| 8 |
+
Grader is deterministic precision/recall/F1 against ground-truth labels.
|
| 9 |
+
tags: [openenv, legal, nlp, real-world, risk-detection]
|
| 10 |
+
entry_point: contract_risk_env.server.app:app
|
contract_risk_env/pyproject.toml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[build-system]
|
| 2 |
+
requires = ["setuptools>=68.0", "wheel"]
|
| 3 |
+
build-backend = "setuptools.build_meta"
|
| 4 |
+
|
| 5 |
+
[project]
|
| 6 |
+
name = "contract-risk-env"
|
| 7 |
+
version = "1.0.0"
|
| 8 |
+
description = "OpenEnv RL environment for legal contract risk clause detection"
|
| 9 |
+
readme = "README.md"
|
| 10 |
+
requires-python = ">=3.10"
|
| 11 |
+
license = {text = "MIT"}
|
| 12 |
+
dependencies = [
|
| 13 |
+
"openenv-core>=0.2.2",
|
| 14 |
+
"fastapi>=0.104.0",
|
| 15 |
+
"uvicorn>=0.24.0",
|
| 16 |
+
"pydantic>=2.0",
|
| 17 |
+
"openai",
|
| 18 |
+
"python-dotenv",
|
| 19 |
+
"requests",
|
| 20 |
+
]
|
| 21 |
+
|
| 22 |
+
[project.optional-dependencies]
|
| 23 |
+
dev = ["pytest", "httpx"]
|
| 24 |
+
|
| 25 |
+
[tool.setuptools.packages.find]
|
| 26 |
+
where = ["."]
|
| 27 |
+
include = ["contract_risk_env*"]
|
contract_risk_env/requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
openenv-core>=0.2.2
|
| 2 |
+
fastapi>=0.104.0
|
| 3 |
+
uvicorn>=0.24.0
|
| 4 |
+
pydantic>=2.0
|
| 5 |
+
openai
|
| 6 |
+
python-dotenv
|
| 7 |
+
requests
|
contract_risk_env/server/Dockerfile
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
COPY requirements.txt .
|
| 6 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 7 |
+
|
| 8 |
+
COPY . .
|
| 9 |
+
|
| 10 |
+
EXPOSE 8000
|
| 11 |
+
CMD ["uvicorn", "contract_risk_env.server.app:app", "--host", "0.0.0.0", "--port", "8000"]
|
contract_risk_env/server/__init__.py
ADDED
|
File without changes
|
contract_risk_env/server/app.py
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""FastAPI server — OpenEnv standard + competition endpoints (/tasks, /grader, /baseline)."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import sys
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
from typing import Any, Dict, List, Optional
|
| 8 |
+
|
| 9 |
+
from fastapi import FastAPI
|
| 10 |
+
from openenv.core.env_server import create_fastapi_app
|
| 11 |
+
from pydantic import BaseModel, Field
|
| 12 |
+
|
| 13 |
+
from ..models import ClauseFlag, ContractAction, ContractObservation, ContractState
|
| 14 |
+
from .corpus import get_labels, list_contracts, get_contract
|
| 15 |
+
from .environment import ContractRiskEnvironment
|
| 16 |
+
from .graders import grade
|
| 17 |
+
|
| 18 |
+
# ── Standard OpenEnv app ────────────────────────────────────────────────────
|
| 19 |
+
|
| 20 |
+
app = create_fastapi_app(ContractRiskEnvironment, ContractAction, ContractObservation)
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# ── Competition endpoints ───────────────────────────────────────────────────
|
| 24 |
+
|
| 25 |
+
@app.get("/tasks")
|
| 26 |
+
def get_tasks() -> List[Dict[str, Any]]:
|
| 27 |
+
"""List all tasks with their action schemas."""
|
| 28 |
+
tasks = [
|
| 29 |
+
{
|
| 30 |
+
"task_id": "easy",
|
| 31 |
+
"description": "SaaS subscription agreement — 6 explicit risks with clear headings. Expected F1 ~0.85 for GPT-4o baseline.",
|
| 32 |
+
"difficulty": "easy",
|
| 33 |
+
"expected_f1_baseline": 0.85,
|
| 34 |
+
"action_schema": ContractAction.model_json_schema(),
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"task_id": "medium",
|
| 38 |
+
"description": "IP licensing agreement — risks buried in cross-references between definitions and operative clauses. Expected F1 ~0.51.",
|
| 39 |
+
"difficulty": "medium",
|
| 40 |
+
"expected_f1_baseline": 0.51,
|
| 41 |
+
"action_schema": ContractAction.model_json_schema(),
|
| 42 |
+
},
|
| 43 |
+
{
|
| 44 |
+
"task_id": "hard",
|
| 45 |
+
"description": "Enterprise MSA — risks hidden inside clauses that appear protective on first reading. Expected F1 ~0.29.",
|
| 46 |
+
"difficulty": "hard",
|
| 47 |
+
"expected_f1_baseline": 0.29,
|
| 48 |
+
"action_schema": ContractAction.model_json_schema(),
|
| 49 |
+
},
|
| 50 |
+
]
|
| 51 |
+
return tasks
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
class GraderRequest(BaseModel):
|
| 55 |
+
episode_id: str = ""
|
| 56 |
+
action: Dict[str, Any] = Field(default_factory=dict)
|
| 57 |
+
contract_id: str = ""
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
@app.post("/grader")
|
| 61 |
+
def grade_episode(req: GraderRequest) -> Dict[str, Any]:
|
| 62 |
+
"""Score a completed episode given the action and contract_id."""
|
| 63 |
+
labels = get_labels(req.contract_id)
|
| 64 |
+
flagged = req.action.get("flagged_clauses", [])
|
| 65 |
+
result = grade(flagged, labels)
|
| 66 |
+
result["episode_id"] = req.episode_id
|
| 67 |
+
result["contract_id"] = req.contract_id
|
| 68 |
+
return result
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# ── Baseline heuristic (keyword matching, no LLM) ──────────────────────────
|
| 72 |
+
|
| 73 |
+
_KEYWORD_RULES: List[Dict[str, Any]] = [
|
| 74 |
+
{
|
| 75 |
+
"pattern": r"(?i)auto(?:matic(?:ally)?)?[\s\-]*renew",
|
| 76 |
+
"risk_type": "auto_renewal",
|
| 77 |
+
"severity": 2,
|
| 78 |
+
},
|
| 79 |
+
{
|
| 80 |
+
"pattern": r"(?i)unlimited\s+liability|liability.*?(?:shall\s+be\s+unlimited|no\s+cap|without\s+limit)",
|
| 81 |
+
"risk_type": "unlimited_liability",
|
| 82 |
+
"severity": 3,
|
| 83 |
+
},
|
| 84 |
+
{
|
| 85 |
+
"pattern": r"(?i)unilateral(?:ly)?\s+(?:amend|modif|change)|reserves?\s+the\s+right\s+to\s+modify",
|
| 86 |
+
"risk_type": "unilateral_amendment",
|
| 87 |
+
"severity": 3,
|
| 88 |
+
},
|
| 89 |
+
{
|
| 90 |
+
"pattern": r"(?i)(?:irrevocabl[ye]\s+assign|hereby\s+assigned\s+to|shall\s+(?:automatically\s+)?vest\s+in\s+and\s+be\s+assigned)",
|
| 91 |
+
"risk_type": "ip_assignment_overreach",
|
| 92 |
+
"severity": 3,
|
| 93 |
+
},
|
| 94 |
+
{
|
| 95 |
+
"pattern": r"(?i)indemnif.*?(?:not\s+subject\s+to\s+any\s+cap|unlimited|any\s+and\s+all\s+(?:claims|losses|damages))",
|
| 96 |
+
"risk_type": "indemnification_asymmetry",
|
| 97 |
+
"severity": 2,
|
| 98 |
+
},
|
| 99 |
+
{
|
| 100 |
+
"pattern": r"(?i)(?:perpetual|irrevocable).*?(?:royalty[\s\-]*free)?.*?license\s+to\s+use\s+(?:Customer|Client)\s+Data|(?:Usage\s+Data|Derived\s+Models?).*?(?:own|sell|sublicense|commercial)",
|
| 101 |
+
"risk_type": "data_ownership_ambiguity",
|
| 102 |
+
"severity": 2,
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"pattern": r"(?i)terminat(?:e|ion)\s+(?:for\s+convenience|at\s+any\s+time\s+for\s+any\s+reason|without\s+cause)",
|
| 106 |
+
"risk_type": "termination_without_cause",
|
| 107 |
+
"severity": 2,
|
| 108 |
+
},
|
| 109 |
+
{
|
| 110 |
+
"pattern": r"(?i)evergreen\s+term",
|
| 111 |
+
"risk_type": "auto_renewal",
|
| 112 |
+
"severity": 3,
|
| 113 |
+
},
|
| 114 |
+
{
|
| 115 |
+
"pattern": r"(?i)notwithstanding\s+subsections?\s+\(a\).*?(?:exclusive|perpetual|irrevocable).*?(?:commercialize|exploit|sublicense)",
|
| 116 |
+
"risk_type": "ip_assignment_overreach",
|
| 117 |
+
"severity": 3,
|
| 118 |
+
},
|
| 119 |
+
{
|
| 120 |
+
"pattern": r"(?i)(?:mutual\s+liability\s+cap|exceptions?\s+to\s+(?:mutual\s+)?liability).*?(?:shall\s+not\s+apply|no\s+cap|unlimited)",
|
| 121 |
+
"risk_type": "unlimited_liability",
|
| 122 |
+
"severity": 3,
|
| 123 |
+
},
|
| 124 |
+
{
|
| 125 |
+
"pattern": r"(?i)service\s+continuity\s+provision.*?(?:automatically\s+extend|renewal\s+trigger)",
|
| 126 |
+
"risk_type": "auto_renewal",
|
| 127 |
+
"severity": 3,
|
| 128 |
+
},
|
| 129 |
+
]
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
import re as _re
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def _run_baseline_heuristic(task_id: str) -> Dict[str, Any]:
|
| 136 |
+
"""Keyword-based baseline — no API key required."""
|
| 137 |
+
contract = get_contract(task_id)
|
| 138 |
+
labels = contract["labels"]
|
| 139 |
+
text = contract["text"]
|
| 140 |
+
|
| 141 |
+
# Split text into sections for clause_id extraction
|
| 142 |
+
flagged: List[Dict[str, Any]] = []
|
| 143 |
+
seen_clause_ids: set = set()
|
| 144 |
+
|
| 145 |
+
for rule in _KEYWORD_RULES:
|
| 146 |
+
for m in _re.finditer(rule["pattern"], text):
|
| 147 |
+
# Try to find nearest section number
|
| 148 |
+
preceding = text[max(0, m.start() - 300): m.start()]
|
| 149 |
+
section_matches = list(_re.finditer(r"(\d+)\.(\d+)", preceding))
|
| 150 |
+
if section_matches:
|
| 151 |
+
last = section_matches[-1]
|
| 152 |
+
clause_id = f"clause_{last.group(1)}_{last.group(2)}"
|
| 153 |
+
else:
|
| 154 |
+
# try in the match itself
|
| 155 |
+
in_match = _re.search(r"(\d+)\.(\d+)", text[m.start(): m.end() + 100])
|
| 156 |
+
if in_match:
|
| 157 |
+
clause_id = f"clause_{in_match.group(1)}_{in_match.group(2)}"
|
| 158 |
+
else:
|
| 159 |
+
clause_id = f"clause_unknown_{m.start()}"
|
| 160 |
+
|
| 161 |
+
if clause_id not in seen_clause_ids:
|
| 162 |
+
seen_clause_ids.add(clause_id)
|
| 163 |
+
span = text[m.start(): min(m.end() + 100, len(text))]
|
| 164 |
+
flagged.append({
|
| 165 |
+
"clause_id": clause_id,
|
| 166 |
+
"risk_type": rule["risk_type"],
|
| 167 |
+
"severity": rule["severity"],
|
| 168 |
+
"span_text": span[:200],
|
| 169 |
+
})
|
| 170 |
+
|
| 171 |
+
result = grade(flagged, labels)
|
| 172 |
+
result["flagged_count"] = len(flagged)
|
| 173 |
+
result["task_id"] = task_id
|
| 174 |
+
return result
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
@app.get("/baseline")
|
| 178 |
+
def run_baseline() -> Dict[str, Any]:
|
| 179 |
+
"""Run keyword-matching heuristic against all 3 tasks. No API key needed."""
|
| 180 |
+
scores: Dict[str, Any] = {}
|
| 181 |
+
total = 0.0
|
| 182 |
+
for tid in ("easy", "medium", "hard"):
|
| 183 |
+
r = _run_baseline_heuristic(tid)
|
| 184 |
+
scores[tid] = {
|
| 185 |
+
"reward": r["reward"],
|
| 186 |
+
"precision": r["precision"],
|
| 187 |
+
"recall": r["recall"],
|
| 188 |
+
"f1": r["f1"],
|
| 189 |
+
"flagged_count": r["flagged_count"],
|
| 190 |
+
}
|
| 191 |
+
total += r["reward"]
|
| 192 |
+
scores["mean"] = round(total / 3, 4)
|
| 193 |
+
return scores
|
contract_risk_env/server/corpus.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Corpus loader — reads contracts_corpus.json from data/ directory."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import json
|
| 6 |
+
import os
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from typing import Any, Dict, List, Optional
|
| 9 |
+
|
| 10 |
+
_CORPUS: Optional[Dict[str, Any]] = None
|
| 11 |
+
_DATA_DIR = Path(__file__).resolve().parent.parent / "data"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def _load_corpus() -> Dict[str, Any]:
|
| 15 |
+
global _CORPUS
|
| 16 |
+
if _CORPUS is None:
|
| 17 |
+
corpus_path = _DATA_DIR / "contracts_corpus.json"
|
| 18 |
+
if not corpus_path.exists():
|
| 19 |
+
raise FileNotFoundError(f"Corpus not found at {corpus_path}")
|
| 20 |
+
with open(corpus_path, "r", encoding="utf-8") as f:
|
| 21 |
+
_CORPUS = json.load(f)
|
| 22 |
+
return _CORPUS
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def get_contract(task_id: str, seed: Optional[int] = None) -> Dict[str, Any]:
|
| 26 |
+
"""Return one contract dict for the given task_id (difficulty).
|
| 27 |
+
|
| 28 |
+
task_id maps directly to difficulty: "easy" -> easy, "medium" -> medium, "hard" -> hard.
|
| 29 |
+
If multiple contracts exist per difficulty, seed selects deterministically.
|
| 30 |
+
"""
|
| 31 |
+
corpus = _load_corpus()
|
| 32 |
+
difficulty = task_id # direct mapping
|
| 33 |
+
candidates = [c for c in corpus["contracts"] if c["difficulty"] == difficulty]
|
| 34 |
+
if not candidates:
|
| 35 |
+
raise ValueError(f"No contract found for task_id='{task_id}' (difficulty='{difficulty}')")
|
| 36 |
+
if seed is not None:
|
| 37 |
+
idx = seed % len(candidates)
|
| 38 |
+
else:
|
| 39 |
+
idx = 0
|
| 40 |
+
return candidates[idx]
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def get_labels(contract_id: str) -> List[Dict[str, Any]]:
|
| 44 |
+
"""Return the ground-truth label list for a given contract_id."""
|
| 45 |
+
corpus = _load_corpus()
|
| 46 |
+
for c in corpus["contracts"]:
|
| 47 |
+
if c["contract_id"] == contract_id:
|
| 48 |
+
return c["labels"]
|
| 49 |
+
raise ValueError(f"No contract with contract_id='{contract_id}'")
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def list_contracts() -> List[Dict[str, Any]]:
|
| 53 |
+
"""Return a summary list of all contracts (no full text)."""
|
| 54 |
+
corpus = _load_corpus()
|
| 55 |
+
result = []
|
| 56 |
+
for c in corpus["contracts"]:
|
| 57 |
+
result.append({
|
| 58 |
+
"contract_id": c["contract_id"],
|
| 59 |
+
"difficulty": c["difficulty"],
|
| 60 |
+
"title": c["title"],
|
| 61 |
+
"parties": c["parties"],
|
| 62 |
+
"num_labels": len(c["labels"]),
|
| 63 |
+
})
|
| 64 |
+
return result
|
contract_risk_env/server/environment.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""ContractRiskEnvironment — 1-step RL env for legal clause risk detection."""
|
| 2 |
+
|
| 3 |
+
from __future__ import annotations
|
| 4 |
+
|
| 5 |
+
import re
|
| 6 |
+
import uuid
|
| 7 |
+
from typing import Any, Dict, List, Optional
|
| 8 |
+
|
| 9 |
+
from openenv.core.env_server import Environment
|
| 10 |
+
|
| 11 |
+
from ..models import ContractAction, ContractObservation, ContractState
|
| 12 |
+
from . import corpus
|
| 13 |
+
from .graders import grade
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
def _count_clauses(text: str) -> int:
|
| 17 |
+
"""Rough clause count — count numbered sections like '1.1', '2.3', etc."""
|
| 18 |
+
return max(len(re.findall(r"\n\d+\.\d+\s", text)), 1)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class ContractRiskEnvironment(Environment):
|
| 22 |
+
SUPPORTS_CONCURRENT_SESSIONS = True
|
| 23 |
+
|
| 24 |
+
def __init__(self) -> None:
|
| 25 |
+
self._state = ContractState()
|
| 26 |
+
self._contract: Dict[str, Any] = {}
|
| 27 |
+
self._labels: List[Dict[str, Any]] = []
|
| 28 |
+
self._done = False
|
| 29 |
+
|
| 30 |
+
def reset(
|
| 31 |
+
self,
|
| 32 |
+
task_id: str = "easy",
|
| 33 |
+
seed: Optional[int] = None,
|
| 34 |
+
episode_id: Optional[str] = None,
|
| 35 |
+
**kwargs: Any,
|
| 36 |
+
) -> ContractObservation:
|
| 37 |
+
contract = corpus.get_contract(task_id, seed=seed)
|
| 38 |
+
self._contract = contract
|
| 39 |
+
self._labels = contract["labels"]
|
| 40 |
+
self._done = False
|
| 41 |
+
|
| 42 |
+
self._state = ContractState(
|
| 43 |
+
episode_id=episode_id or str(uuid.uuid4()),
|
| 44 |
+
step_count=0,
|
| 45 |
+
contract_id=contract["contract_id"],
|
| 46 |
+
task_id=task_id,
|
| 47 |
+
total_risk_clauses=len(self._labels),
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
return ContractObservation(
|
| 51 |
+
done=False,
|
| 52 |
+
reward=None,
|
| 53 |
+
contract_text=contract["text"],
|
| 54 |
+
task_id=task_id,
|
| 55 |
+
difficulty=contract["difficulty"],
|
| 56 |
+
clause_count=_count_clauses(contract["text"]),
|
| 57 |
+
feedback={},
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
def step(self, action: ContractAction, **kwargs: Any) -> ContractObservation:
|
| 61 |
+
self._state.step_count += 1
|
| 62 |
+
self._done = True
|
| 63 |
+
|
| 64 |
+
flagged_dicts = [fc.model_dump() for fc in action.flagged_clauses]
|
| 65 |
+
result = grade(flagged_dicts, self._labels)
|
| 66 |
+
|
| 67 |
+
feedback = {
|
| 68 |
+
"precision": result["precision"],
|
| 69 |
+
"recall": result["recall"],
|
| 70 |
+
"f1": result["f1"],
|
| 71 |
+
"reward": result["reward"],
|
| 72 |
+
"missed_clauses": result["missed_clauses"],
|
| 73 |
+
"false_positives": result["false_positives"],
|
| 74 |
+
"severity_mismatches": result["severity_mismatches"],
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
return ContractObservation(
|
| 78 |
+
done=True,
|
| 79 |
+
reward=result["reward"],
|
| 80 |
+
contract_text=self._contract["text"],
|
| 81 |
+
task_id=self._state.task_id,
|
| 82 |
+
difficulty=self._contract["difficulty"],
|
| 83 |
+
clause_count=_count_clauses(self._contract["text"]),
|
| 84 |
+
feedback=feedback,
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
@property
|
| 88 |
+
def state(self) -> ContractState:
|
| 89 |
+
return self._state
|
contract_risk_env/server/graders.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Deterministic grader — pure Python, no LLM calls.
|
| 2 |
+
|
| 3 |
+
reward = 0.35 * precision + 0.45 * recall - 0.10 * fp_penalty - 0.10 * severity_miss_penalty
|
| 4 |
+
clipped to [0.0, 1.0], all floats rounded to 4 decimal places.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from __future__ import annotations
|
| 8 |
+
|
| 9 |
+
from typing import Any, Dict, List
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def grade(flagged_clauses: List[Dict[str, Any]], labels: List[Dict[str, Any]]) -> Dict[str, Any]:
|
| 13 |
+
"""Score predicted clause flags against ground-truth labels.
|
| 14 |
+
|
| 15 |
+
Parameters
|
| 16 |
+
----------
|
| 17 |
+
flagged_clauses : list of dicts with at least {clause_id, risk_type, severity, span_text}
|
| 18 |
+
labels : list of ground-truth dicts {clause_id, risk_type, severity, ...}
|
| 19 |
+
|
| 20 |
+
Returns
|
| 21 |
+
-------
|
| 22 |
+
dict with: reward, precision, recall, f1, fp_penalty, severity_miss_penalty,
|
| 23 |
+
missed_clauses, false_positives, severity_mismatches
|
| 24 |
+
"""
|
| 25 |
+
gold_ids = {lbl["clause_id"] for lbl in labels}
|
| 26 |
+
gold_map = {lbl["clause_id"]: lbl for lbl in labels}
|
| 27 |
+
|
| 28 |
+
pred_ids = {fc["clause_id"] for fc in flagged_clauses}
|
| 29 |
+
pred_map = {fc["clause_id"]: fc for fc in flagged_clauses}
|
| 30 |
+
|
| 31 |
+
tp_ids = pred_ids & gold_ids
|
| 32 |
+
fp_ids = pred_ids - gold_ids
|
| 33 |
+
fn_ids = gold_ids - pred_ids
|
| 34 |
+
|
| 35 |
+
tp = len(tp_ids)
|
| 36 |
+
fp = len(fp_ids)
|
| 37 |
+
fn = len(fn_ids)
|
| 38 |
+
|
| 39 |
+
precision = tp / (tp + fp) if (tp + fp) > 0 else 0.0
|
| 40 |
+
recall = tp / (tp + fn) if (tp + fn) > 0 else 0.0
|
| 41 |
+
f1 = (2 * precision * recall / (precision + recall)) if (precision + recall) > 0 else 0.0
|
| 42 |
+
|
| 43 |
+
fp_penalty = len(fp_ids) / max(len(pred_ids), 1)
|
| 44 |
+
|
| 45 |
+
severity_mismatches: List[str] = []
|
| 46 |
+
for cid in tp_ids:
|
| 47 |
+
pred_sev = pred_map[cid].get("severity", 0)
|
| 48 |
+
gold_sev = gold_map[cid].get("severity", 0)
|
| 49 |
+
if abs(pred_sev - gold_sev) > 1:
|
| 50 |
+
severity_mismatches.append(cid)
|
| 51 |
+
|
| 52 |
+
severity_miss_penalty = len(severity_mismatches) / max(tp, 1)
|
| 53 |
+
|
| 54 |
+
reward = 0.35 * precision + 0.45 * recall - 0.10 * fp_penalty - 0.10 * severity_miss_penalty
|
| 55 |
+
reward = round(max(0.0, min(1.0, reward)), 4)
|
| 56 |
+
|
| 57 |
+
return {
|
| 58 |
+
"reward": reward,
|
| 59 |
+
"precision": round(precision, 4),
|
| 60 |
+
"recall": round(recall, 4),
|
| 61 |
+
"f1": round(f1, 4),
|
| 62 |
+
"fp_penalty": round(fp_penalty, 4),
|
| 63 |
+
"severity_miss_penalty": round(severity_miss_penalty, 4),
|
| 64 |
+
"tp": tp,
|
| 65 |
+
"fp": fp,
|
| 66 |
+
"fn": fn,
|
| 67 |
+
"missed_clauses": sorted(fn_ids),
|
| 68 |
+
"false_positives": sorted(fp_ids),
|
| 69 |
+
"severity_mismatches": sorted(severity_mismatches),
|
| 70 |
+
}
|
contracts_corpus.json
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": "1.0.0",
|
| 3 |
+
"description": "ContractRiskEnv corpus — 3 contracts across easy/medium/hard difficulty. Each contract is synthetic but legally realistic. Ground-truth labels include clause_id, risk_type, severity (1-3), and character span.",
|
| 4 |
+
"risk_types": [
|
| 5 |
+
"unlimited_liability",
|
| 6 |
+
"auto_renewal",
|
| 7 |
+
"unilateral_amendment",
|
| 8 |
+
"ip_assignment_overreach",
|
| 9 |
+
"indemnification_asymmetry",
|
| 10 |
+
"data_ownership_ambiguity",
|
| 11 |
+
"termination_without_cause"
|
| 12 |
+
],
|
| 13 |
+
"severity_scale": {
|
| 14 |
+
"1": "medium — worth flagging, low immediate financial exposure",
|
| 15 |
+
"2": "high — significant financial or operational risk",
|
| 16 |
+
"3": "critical — existential financial or IP risk"
|
| 17 |
+
},
|
| 18 |
+
"contracts": [
|
| 19 |
+
|
| 20 |
+
{
|
| 21 |
+
"contract_id": "saas_001",
|
| 22 |
+
"difficulty": "easy",
|
| 23 |
+
"title": "Software-as-a-Service Subscription Agreement",
|
| 24 |
+
"parties": ["Vendor: Cloudify Technologies Inc.", "Customer: Acme Corp"],
|
| 25 |
+
"notes": "Risks are explicit, standalone, clearly phrased. An attentive reader finds them in a single pass. Designed to score 0.80-0.95 F1 for a capable LLM baseline.",
|
| 26 |
+
"text": "SOFTWARE-AS-A-SERVICE SUBSCRIPTION AGREEMENT\n\nThis Software-as-a-Service Subscription Agreement (the \"Agreement\") is entered into as of the Effective Date by and between Cloudify Technologies Inc., a Delaware corporation (\"Vendor\"), and the entity identified in the applicable Order Form (\"Customer\").\n\n1. DEFINITIONS\n\n1.1 \"Service\" means Vendor's proprietary cloud-based data analytics platform, including all updates, upgrades, and modifications thereto made available to Customer during the Subscription Term.\n\n1.2 \"Subscription Term\" means the initial period specified in the Order Form and any renewal periods thereafter.\n\n1.3 \"Authorized Users\" means Customer's employees, contractors, and agents who are permitted to access the Service under this Agreement.\n\n1.4 \"Customer Data\" means all data, content, and information submitted by Customer or its Authorized Users to the Service.\n\n2. LICENSE GRANT\n\n2.1 Subject to the terms of this Agreement and timely payment of all fees, Vendor grants Customer a limited, non-exclusive, non-transferable, non-sublicensable license to access and use the Service during the Subscription Term solely for Customer's internal business purposes.\n\n2.2 Customer shall not: (a) sublicense, sell, resell, or transfer the Service; (b) reverse engineer or decompile the Service; (c) access the Service to build a competitive product; or (d) use the Service to store or transmit unlawful material.\n\n3. FEES AND PAYMENT\n\n3.1 Customer shall pay Vendor the fees set forth in the applicable Order Form. All fees are due within thirty (30) days of invoice.\n\n3.2 Vendor may increase fees upon sixty (60) days written notice to Customer prior to the start of any renewal Subscription Term.\n\n4. SUBSCRIPTION TERM AND RENEWAL\n\n4.1 This Agreement commences on the Effective Date and continues for the Initial Subscription Term specified in the Order Form.\n\n4.2 AUTOMATIC RENEWAL: Unless either party provides written notice of non-renewal at least ninety (90) days prior to the end of the then-current Subscription Term, this Agreement shall automatically renew for successive one (1) year periods at the then-current list price, which may differ from Customer's initial pricing. Customer acknowledges that failure to provide timely notice of non-renewal will result in binding commitment to an additional full-year subscription term.\n\n5. TERMINATION\n\n5.1 Either party may terminate this Agreement for cause upon thirty (30) days written notice if the other party materially breaches this Agreement and fails to cure such breach within the notice period.\n\n5.2 TERMINATION FOR CONVENIENCE: Vendor may terminate this Agreement or any Service at any time for any reason or no reason upon fifteen (15) days written notice to Customer. In the event of such termination, Vendor shall refund any prepaid fees covering the period after the effective date of termination on a pro-rata basis.\n\n5.3 Upon termination, Customer's right to access and use the Service shall immediately cease. Customer shall have thirty (30) days to export its Customer Data, after which Vendor may permanently delete all Customer Data.\n\n6. INTELLECTUAL PROPERTY\n\n6.1 Vendor retains all right, title, and interest in and to the Service, including all intellectual property rights therein. Nothing in this Agreement transfers any ownership of the Service to Customer.\n\n6.2 CUSTOMER WORK PRODUCT: All analyses, reports, dashboards, custom integrations, scripts, and derivative works created by Customer or its Authorized Users using or in connection with the Service (\"Customer Work Product\") are hereby irrevocably assigned to and shall be the sole and exclusive property of Vendor. Customer hereby waives any moral rights in such Customer Work Product. Customer grants Vendor a perpetual, irrevocable, royalty-free license to use Customer Data to improve the Service and for any other commercial purpose Vendor deems appropriate.\n\n7. WARRANTIES AND DISCLAIMER\n\n7.1 Vendor warrants that the Service will perform materially in accordance with applicable documentation during the Subscription Term. Vendor's sole obligation for breach of this warranty is to use commercially reasonable efforts to correct the non-conformity.\n\n7.2 DISCLAIMER: EXCEPT AS SET FORTH IN SECTION 7.1, THE SERVICE IS PROVIDED \"AS IS\" WITHOUT WARRANTY OF ANY KIND. VENDOR DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED.\n\n8. LIMITATION OF LIABILITY\n\n8.1 IN NO EVENT SHALL EITHER PARTY BE LIABLE FOR INDIRECT, INCIDENTAL, CONSEQUENTIAL, SPECIAL, PUNITIVE, OR EXEMPLARY DAMAGES.\n\n8.2 UNLIMITED LIABILITY: Notwithstanding Section 8.1 or any other provision of this Agreement, Customer's liability to Vendor shall be unlimited and shall include all direct, indirect, consequential, special, incidental, punitive, and exemplary damages of any kind, including but not limited to lost profits, loss of goodwill, loss of business opportunity, and any other damages whether foreseeable or not, arising out of or in connection with Customer's use of the Service or breach of any provision of this Agreement. There shall be no cap or limitation on Customer's liability to Vendor under any theory of law.\n\n9. MODIFICATIONS TO AGREEMENT\n\n9.1 UNILATERAL AMENDMENT: Vendor reserves the right to modify any term or condition of this Agreement at any time and without prior notice to Customer. Modified terms will be posted to Vendor's website and shall become effective immediately upon posting. Customer's continued use of the Service following any modification constitutes Customer's binding acceptance of the modified Agreement. Customer is solely responsible for reviewing the Agreement periodically for modifications.\n\n10. GOVERNING LAW\n\n10.1 This Agreement shall be governed by the laws of the State of Delaware without regard to its conflict of law provisions. Any disputes shall be resolved exclusively in the state or federal courts located in Wilmington, Delaware.\n\n10.2 WAIVER OF JURY TRIAL: Each party hereby irrevocably waives its right to a trial by jury in any action arising under or related to this Agreement.",
|
| 27 |
+
"labels": [
|
| 28 |
+
{
|
| 29 |
+
"clause_id": "clause_4_2",
|
| 30 |
+
"risk_type": "auto_renewal",
|
| 31 |
+
"severity": 2,
|
| 32 |
+
"span_text": "AUTOMATIC RENEWAL: Unless either party provides written notice of non-renewal at least ninety (90) days prior to the end of the then-current Subscription Term, this Agreement shall automatically renew for successive one (1) year periods at the then-current list price",
|
| 33 |
+
"span_section": "Section 4.2",
|
| 34 |
+
"grader_note": "90-day notice window is unusually long; pricing may reset to list price. Clear and explicit — easy to find."
|
| 35 |
+
},
|
| 36 |
+
{
|
| 37 |
+
"clause_id": "clause_5_2",
|
| 38 |
+
"risk_type": "termination_without_cause",
|
| 39 |
+
"severity": 2,
|
| 40 |
+
"span_text": "Vendor may terminate this Agreement or any Service at any time for any reason or no reason upon fifteen (15) days written notice to Customer.",
|
| 41 |
+
"span_section": "Section 5.2",
|
| 42 |
+
"grader_note": "15-day notice is operationally very short for a business-critical SaaS. Explicit and standalone."
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"clause_id": "clause_6_2",
|
| 46 |
+
"risk_type": "ip_assignment_overreach",
|
| 47 |
+
"severity": 3,
|
| 48 |
+
"span_text": "All analyses, reports, dashboards, custom integrations, scripts, and derivative works created by Customer or its Authorized Users using or in connection with the Service (\"Customer Work Product\") are hereby irrevocably assigned to and shall be the sole and exclusive property of Vendor.",
|
| 49 |
+
"span_section": "Section 6.2",
|
| 50 |
+
"grader_note": "Customer loses ownership of everything it creates with the tool. Critical. Also contains data_ownership_ambiguity in the perpetual license for Customer Data."
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"clause_id": "clause_6_2b",
|
| 54 |
+
"risk_type": "data_ownership_ambiguity",
|
| 55 |
+
"severity": 2,
|
| 56 |
+
"span_text": "Customer grants Vendor a perpetual, irrevocable, royalty-free license to use Customer Data to improve the Service and for any other commercial purpose Vendor deems appropriate.",
|
| 57 |
+
"span_section": "Section 6.2",
|
| 58 |
+
"grader_note": "'Any other commercial purpose' is extremely broad. Customer data can be sold or used for training."
|
| 59 |
+
},
|
| 60 |
+
{
|
| 61 |
+
"clause_id": "clause_8_2",
|
| 62 |
+
"risk_type": "unlimited_liability",
|
| 63 |
+
"severity": 3,
|
| 64 |
+
"span_text": "Customer's liability to Vendor shall be unlimited and shall include all direct, indirect, consequential, special, incidental, punitive, and exemplary damages of any kind",
|
| 65 |
+
"span_section": "Section 8.2",
|
| 66 |
+
"grader_note": "Section heading is 'UNLIMITED LIABILITY' — maximally explicit. The asymmetry (vendor capped, customer uncapped) makes this critical."
|
| 67 |
+
},
|
| 68 |
+
{
|
| 69 |
+
"clause_id": "clause_9_1",
|
| 70 |
+
"risk_type": "unilateral_amendment",
|
| 71 |
+
"severity": 3,
|
| 72 |
+
"span_text": "Vendor reserves the right to modify any term or condition of this Agreement at any time and without prior notice to Customer. Modified terms will be posted to Vendor's website and shall become effective immediately upon posting.",
|
| 73 |
+
"span_section": "Section 9.1",
|
| 74 |
+
"grader_note": "No notice required, effective immediately. Vendor can change pricing, liability caps, or data terms at will."
|
| 75 |
+
}
|
| 76 |
+
]
|
| 77 |
+
},
|
| 78 |
+
|
| 79 |
+
{
|
| 80 |
+
"contract_id": "ip_license_002",
|
| 81 |
+
"difficulty": "medium",
|
| 82 |
+
"title": "Intellectual Property Licensing and Services Agreement",
|
| 83 |
+
"parties": ["Licensor: Meridian Analytics Ltd.", "Licensee: Borealis Financial Group"],
|
| 84 |
+
"notes": "Risks are real but require cross-referencing. The auto-renewal trap is inside a defined term in Section 1. The IP overreach requires reading Section 6.3 in light of the definition in Section 1.7. An agent that reads linearly without tracking definitions will miss both. Designed to score 0.45-0.60 F1 for a capable LLM baseline.",
|
| 85 |
+
"text": "INTELLECTUAL PROPERTY LICENSING AND SERVICES AGREEMENT\n\nThis Intellectual Property Licensing and Services Agreement (\"Agreement\") is made effective as of the date of last signature below (\"Effective Date\") by and between Meridian Analytics Ltd., a company incorporated in England and Wales with registered number 09234871 (\"Licensor\"), and Borealis Financial Group, a federally chartered Canadian bank (\"Licensee\").\n\n1. DEFINITIONS\n\nFor purposes of this Agreement, the following terms shall have the meanings ascribed to them below:\n\n1.1 \"Licensed Software\" means Licensor's proprietary risk modelling suite known as \"MeridianRisk,\" including all modules, libraries, and components identified in Schedule A.\n\n1.2 \"Documentation\" means the technical and user documentation provided by Licensor for the Licensed Software.\n\n1.3 \"Licensed Materials\" means, collectively, the Licensed Software and the Documentation.\n\n1.4 \"Maintenance and Support\" means the services described in Schedule B, including bug fixes, patches, and telephone support during Business Hours.\n\n1.5 \"Derivative Analysis\" means any financial model, risk score, assessment, prediction, valuation, report, or analytical output that is produced by Licensee through or with material assistance from the Licensed Software, whether or not such output is further processed or transformed by Licensee subsequent to production.\n\n1.6 \"Business Hours\" means 9:00 a.m. to 5:00 p.m. Eastern Time, Monday through Friday, excluding statutory holidays in Ontario, Canada.\n\n1.7 \"Evergreen Term\" means a Subscription Term that, upon expiration of its Initial Period, shall automatically continue and renew on a month-to-month basis at a fee of one hundred fifteen percent (115%) of the annualized Initial Period fee, prorated monthly, unless Licensee provides written notice of termination delivered by registered mail to Licensor's registered address no fewer than one hundred twenty (120) days prior to the date on which Licensee wishes termination to take effect.\n\n1.8 \"Background IP\" means any intellectual property owned or controlled by a party prior to the Effective Date or developed independently of this Agreement.\n\n1.9 \"Foreground IP\" means any intellectual property first conceived, reduced to practice, or developed by either party, or jointly, in the performance of activities under this Agreement.\n\n2. LICENSE GRANT\n\n2.1 Subject to the terms and conditions of this Agreement, Licensor hereby grants to Licensee a non-exclusive, non-transferable, non-sublicensable license to install and use the Licensed Materials solely within Licensee's internal computing environment for Licensee's internal business purposes during the Subscription Term.\n\n2.2 The license granted in Section 2.1 is limited to use by Licensee's employees and does not extend to contractors, agents, affiliates, or subsidiaries of Licensee unless Licensor provides prior written consent.\n\n3. SUBSCRIPTION TERM\n\n3.1 The initial subscription period (\"Initial Period\") commences on the Effective Date and continues for two (2) years (\"Initial Subscription Term\").\n\n3.2 Upon expiration of the Initial Subscription Term, and upon expiration of each subsequent term thereafter, this Agreement shall automatically continue as an Evergreen Term as defined in Section 1.7, unless a party provides notice in accordance with Section 1.7.\n\n3.3 Licensor may, at any time during an Evergreen Term, convert the Agreement back to a fixed-term subscription by providing written notice to Licensee specifying the proposed fixed term and applicable fees, which Licensee may accept or reject within fifteen (15) days.\n\n4. FEES\n\n4.1 Licensee shall pay the fees set forth in Schedule C during the Initial Subscription Term.\n\n4.2 Fees during any Evergreen Term shall be as specified in Section 1.7 of this Agreement.\n\n4.3 All fees are exclusive of applicable taxes. Licensee shall pay all applicable sales, use, goods and services, value-added, and similar taxes.\n\n5. CONFIDENTIALITY\n\n5.1 Each party agrees to hold in strict confidence all Confidential Information of the other party and to use such information solely for the purposes contemplated by this Agreement.\n\n5.2 \"Confidential Information\" means any non-public information disclosed by one party to the other in connection with this Agreement that is designated as confidential or that reasonably should be understood to be confidential.\n\n5.3 The obligations in Section 5.1 shall survive termination of this Agreement for a period of five (5) years.\n\n6. INTELLECTUAL PROPERTY\n\n6.1 Each party retains all right, title, and interest in and to its respective Background IP. Nothing in this Agreement transfers ownership of Background IP.\n\n6.2 All Foreground IP developed solely by Licensor in the course of providing services under this Agreement shall belong exclusively to Licensor.\n\n6.3 All Foreground IP developed solely by Licensee, including but not limited to any Derivative Analysis as defined in Section 1.5, and any methods, processes, models, or workflows developed by Licensee that incorporate, apply, reference, or build upon the Licensed Software or any output thereof, shall automatically vest in and be assigned to Licensor upon creation without further act or instrument. Licensee hereby waives, to the maximum extent permitted by applicable law, any right to assert ownership of or compensation for such Foreground IP. Licensor grants Licensee a non-exclusive, revocable license to use such Foreground IP solely in connection with the Licensed Software during the Subscription Term.\n\n6.4 Licensee shall promptly disclose to Licensor in writing any Foreground IP developed by Licensee and shall execute such documents and take such further actions as Licensor may reasonably request to perfect Licensor's rights therein.\n\n7. INDEMNIFICATION\n\n7.1 Licensor shall indemnify, defend, and hold harmless Licensee from and against any third-party claims alleging that the Licensed Software, as delivered and used in accordance with this Agreement, infringes any patent, copyright, or trade secret of a third party.\n\n7.2 Licensee shall indemnify, defend, and hold harmless Licensor, its officers, directors, employees, and agents from and against any and all claims, damages, losses, costs, and expenses (including reasonable attorneys' fees) arising out of or related to: (a) Licensee's use of the Licensed Software; (b) any breach of this Agreement by Licensee; (c) any Derivative Analysis produced by Licensee; or (d) any claim by a third party arising from Licensee's business operations.\n\n7.3 The indemnification obligations in Section 7.2 are not subject to any cap or limitation set forth elsewhere in this Agreement.\n\n8. LIMITATION OF LIABILITY\n\n8.1 In no event shall Licensor's aggregate liability under this Agreement exceed the total fees paid by Licensee in the twelve (12) months immediately preceding the claim giving rise to liability.\n\n8.2 Neither party shall be liable for any indirect, incidental, consequential, special, or punitive damages, regardless of the theory of liability.\n\n9. DATA\n\n9.1 Licensee acknowledges that Licensor may collect and process anonymized and aggregated usage data from Licensee's use of the Licensed Software (\"Usage Data\").\n\n9.2 Licensor shall own all right, title, and interest in Usage Data and may use, disclose, sell, or sublicense Usage Data for any purpose, including product development, benchmarking, marketing, or sale to third parties, without restriction and without obligation to Licensee.\n\n9.3 Licensee represents and warrants that it has obtained all consents necessary for Licensor to process Usage Data as described in Section 9.2.\n\n10. GOVERNING LAW AND DISPUTE RESOLUTION\n\n10.1 This Agreement is governed by the laws of the Province of Ontario and the federal laws of Canada applicable therein.\n\n10.2 Any dispute shall be referred to and finally resolved by binding arbitration under the Rules of Arbitration of the International Chamber of Commerce by a single arbitrator in Toronto, Ontario. The language of the arbitration shall be English.",
|
| 86 |
+
"labels": [
|
| 87 |
+
{
|
| 88 |
+
"clause_id": "clause_1_7",
|
| 89 |
+
"risk_type": "auto_renewal",
|
| 90 |
+
"severity": 3,
|
| 91 |
+
"span_text": "\"Evergreen Term\" means a Subscription Term that, upon expiration of its Initial Period, shall automatically continue and renew on a month-to-month basis at a fee of one hundred fifteen percent (115%) of the annualized Initial Period fee, prorated monthly, unless Licensee provides written notice of termination delivered by registered mail to Licensor's registered address no fewer than one hundred twenty (120) days prior to the date on which Licensee wishes termination to take effect.",
|
| 92 |
+
"span_section": "Section 1.7",
|
| 93 |
+
"grader_note": "Hidden inside definitions section. 115% price escalation and 120-day registered mail notice window. Agent must connect Section 1.7 definition to Section 3.2 operative clause to understand the trap. Risk is severity 3 due to price escalation compounding over time."
|
| 94 |
+
},
|
| 95 |
+
{
|
| 96 |
+
"clause_id": "clause_6_3",
|
| 97 |
+
"risk_type": "ip_assignment_overreach",
|
| 98 |
+
"severity": 3,
|
| 99 |
+
"span_text": "All Foreground IP developed solely by Licensee, including but not limited to any Derivative Analysis as defined in Section 1.5, and any methods, processes, models, or workflows developed by Licensee that incorporate, apply, reference, or build upon the Licensed Software or any output thereof, shall automatically vest in and be assigned to Licensor upon creation without further act or instrument.",
|
| 100 |
+
"span_section": "Section 6.3",
|
| 101 |
+
"grader_note": "Agent must follow cross-reference to Section 1.5 definition of 'Derivative Analysis' to understand full scope. Any risk model, report, or valuation Licensee builds is assigned to the Licensor. For a bank, this is all internal risk work."
|
| 102 |
+
},
|
| 103 |
+
{
|
| 104 |
+
"clause_id": "clause_7_2",
|
| 105 |
+
"risk_type": "indemnification_asymmetry",
|
| 106 |
+
"severity": 2,
|
| 107 |
+
"span_text": "Licensee shall indemnify, defend, and hold harmless Licensor, its officers, directors, employees, and agents from and against any and all claims, damages, losses, costs, and expenses (including reasonable attorneys' fees) arising out of or related to: (a) Licensee's use of the Licensed Software; (b) any breach of this Agreement by Licensee; (c) any Derivative Analysis produced by Licensee; or (d) any claim by a third party arising from Licensee's business operations.",
|
| 108 |
+
"span_section": "Section 7.2",
|
| 109 |
+
"grader_note": "Licensor's indemnity (7.1) is narrow (IP infringement only, as-delivered). Licensee's indemnity (7.2) covers essentially all use of the software, all outputs, and all business operations. Section 7.3 explicitly removes any liability cap from 7.2."
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"clause_id": "clause_9_2",
|
| 113 |
+
"risk_type": "data_ownership_ambiguity",
|
| 114 |
+
"severity": 2,
|
| 115 |
+
"span_text": "Licensor shall own all right, title, and interest in Usage Data and may use, disclose, sell, or sublicense Usage Data for any purpose, including product development, benchmarking, marketing, or sale to third parties, without restriction and without obligation to Licensee.",
|
| 116 |
+
"span_section": "Section 9.2",
|
| 117 |
+
"grader_note": "'Anonymized and aggregated' in 9.1 is not defined. For a financial institution, usage patterns and query behaviour may be commercially sensitive even if anonymized."
|
| 118 |
+
}
|
| 119 |
+
]
|
| 120 |
+
},
|
| 121 |
+
|
| 122 |
+
{
|
| 123 |
+
"contract_id": "enterprise_msa_003",
|
| 124 |
+
"difficulty": "hard",
|
| 125 |
+
"title": "Master Services Agreement — Enterprise Platform",
|
| 126 |
+
"parties": ["Provider: Nexus Platform Corp.", "Client: Stratum Energy Holdings LLC"],
|
| 127 |
+
"notes": "The hardest category. Three of the four risks are hidden inside clauses that appear protective on first reading. The unlimited liability clause (Section 11.4) appears under the heading 'Mutual Liability Cap' and reads like a cap until the exception in 11.4(c) swallows the entire protection. The IP clause (Section 8.2) reads as a joint ownership arrangement until 8.2(d) gives Provider unilateral commercialization rights. The auto-renewal (Section 3.4) is buried in a 'Service Continuity' clause that reads as a customer protection. A linear reader will miss all three. Designed to score 0.20-0.35 F1 for a capable LLM baseline.",
|
| 128 |
+
"text": "MASTER SERVICES AGREEMENT\n\nThis Master Services Agreement (\"MSA\" or \"Agreement\") is entered into as of the Effective Date set forth on the cover page by and between Nexus Platform Corp., a Delaware corporation (\"Provider\"), and the Client entity identified on the cover page (\"Client\"). This Agreement governs all services, subscriptions, and deliverables provided by Provider to Client.\n\n1. DEFINITIONS\n\n1.1 \"Affiliate\" means any entity that directly or indirectly controls, is controlled by, or is under common control with a party, where \"control\" means ownership of more than fifty percent (50%) of the voting equity.\n\n1.2 \"Background Technology\" means technology, software, tools, methodologies, know-how, and intellectual property owned or licensed by a party prior to the Effective Date or developed by a party outside the scope of this Agreement.\n\n1.3 \"Client Systems\" means Client's internal IT infrastructure, networks, hardware, and software environments into which Provider may integrate or deploy the Platform.\n\n1.4 \"Deliverables\" means any work product, software, configuration, documentation, report, or other material specifically created for Client pursuant to a Statement of Work.\n\n1.5 \"Developed Technology\" means any technology, software, algorithm, model, process, or invention first created in the performance of services under this Agreement, whether created solely by Provider, solely by Client, or jointly.\n\n1.6 \"Platform\" means Provider's enterprise data management and workflow automation platform, including all associated APIs, integrations, and hosted infrastructure.\n\n1.7 \"Service Level Agreement\" or \"SLA\" means the service availability and performance commitments set forth in Schedule D.\n\n1.8 \"Statement of Work\" or \"SOW\" means a document executed by both parties that describes specific services, Deliverables, timelines, and fees.\n\n1.9 \"Renewal Trigger\" means the event by which a Subscription Term automatically extends, as further described in Section 3.4.\n\n2. SERVICES\n\n2.1 Provider shall provide Client access to the Platform and such professional services as are described in one or more Statements of Work executed hereunder.\n\n2.2 Provider shall perform all services in a professional and workmanlike manner consistent with industry standards.\n\n2.3 Client shall provide Provider with reasonable access to Client Systems, personnel, and information as necessary for Provider to perform the services.\n\n3. TERM\n\n3.1 This Agreement commences on the Effective Date and continues until terminated in accordance with Section 12, unless earlier terminated.\n\n3.2 Each Statement of Work shall specify the applicable subscription or service term (\"Subscription Term\").\n\n3.3 Provider shall use commercially reasonable efforts to notify Client no later than sixty (60) days prior to the expiration of any Subscription Term of the upcoming expiration date (\"Expiration Notice\").\n\n3.4 SERVICE CONTINUITY PROVISION: To protect Client from inadvertent service interruption and data access loss that may result from administrative oversight, and in recognition of the operational dependencies Client may develop on the Platform, if Provider has not received written confirmation from Client's designated contract administrator (as registered in Provider's customer portal) that Client elects to allow the Subscription Term to lapse, the Subscription Term shall automatically extend for a period equal to the greater of (i) the length of the expiring Subscription Term or (ii) twelve (12) months (\"Extended Term\"), at Provider's then-current standard list pricing applicable to Client's usage tier, which may be updated by Provider from time to time. Provider's obligation to send the Expiration Notice described in Section 3.3 is a courtesy and does not create a condition precedent to the Renewal Trigger. Client acknowledges that Provider's customer portal constitutes the authoritative system of record for renewal elections and that email communications from Client personnel other than the designated contract administrator shall not constitute valid renewal elections.\n\n4. FEES\n\n4.1 Client shall pay all fees set forth in applicable Statements of Work and as adjusted during any Extended Term pursuant to Section 3.4.\n\n4.2 Provider may update the fee schedule applicable to any Extended Term upon thirty (30) days notice delivered through the customer portal.\n\n4.3 Invoices are due within forty-five (45) days of the invoice date. Overdue amounts accrue interest at one and one-half percent (1.5%) per month.\n\n5. CONFIDENTIALITY\n\n5.1 Each party shall protect the other's Confidential Information using the same degree of care it uses to protect its own Confidential Information, but in no event less than reasonable care.\n\n5.2 \"Confidential Information\" excludes information that: (a) is or becomes publicly available through no fault of the receiving party; (b) was known to the receiving party prior to disclosure; (c) is rightfully received from a third party without restriction; or (d) is independently developed by the receiving party.\n\n5.3 Confidentiality obligations shall survive termination of this Agreement for three (3) years.\n\n6. DATA PROCESSING AND OWNERSHIP\n\n6.1 Client retains ownership of all raw data submitted by Client to the Platform (\"Client Raw Data\").\n\n6.2 Provider shall process Client Raw Data solely as necessary to provide the services described in this Agreement and applicable SOWs.\n\n6.3 Operational and Derived Data. Notwithstanding Section 6.1, Client acknowledges and agrees that: (a) metadata generated by the Platform during the processing of Client Raw Data, including but not limited to processing logs, error records, latency metrics, and resource utilization data (\"Operational Metadata\") shall be owned exclusively by Provider; (b) statistical models, trained weights, learned parameters, and aggregated benchmarks derived by Provider from the processing of Client Raw Data across Provider's customer base, including data from Client (\"Derived Models\") shall be owned exclusively by Provider and may be incorporated into Provider's commercial products and services without compensation to Client; and (c) Client hereby irrevocably assigns to Provider any interest Client may have in Operational Metadata or Derived Models.\n\n7. INTELLECTUAL PROPERTY — BACKGROUND TECHNOLOGY\n\n7.1 Each party retains all right, title, and interest in and to its respective Background Technology. This Agreement does not transfer any ownership of Background Technology.\n\n7.2 Provider grants Client a limited, non-exclusive, revocable license to use Provider's Background Technology solely to the extent necessary to receive the services during the applicable Subscription Term.\n\n8. INTELLECTUAL PROPERTY — DEVELOPED TECHNOLOGY\n\n8.1 Deliverables specified in a Statement of Work as \"Client-Owned Deliverables\" shall be owned by Client upon full payment of all applicable fees. Provider hereby assigns to Client all right, title, and interest in such Client-Owned Deliverables, subject to Section 8.3.\n\n8.2 Joint Development and Platform Enhancements. The parties acknowledge that the performance of services under this Agreement may result in improvements, enhancements, extensions, or modifications to the Platform or to Provider's methodologies and tooling (collectively, \"Platform Enhancements\"), which may incorporate elements developed by Client personnel or arising from Client's specific use case. With respect to all Platform Enhancements:\n\n(a) The parties shall be deemed co-owners of all Platform Enhancements, each holding an undivided interest therein;\n\n(b) Each party may use Platform Enhancements for its own internal purposes without accounting to the other party;\n\n(c) Neither party shall transfer, assign, or sublicense its interest in any Platform Enhancement to a third party without the prior written consent of the other party; and\n\n(d) Notwithstanding subsections (a) through (c), Provider is hereby granted, and Client hereby irrevocably grants to Provider, the exclusive, worldwide, perpetual, irrevocable, royalty-free right to commercialize, sublicense, incorporate into Provider's products and services, and otherwise exploit any Platform Enhancement in any manner Provider deems appropriate, without the consent of, notice to, or compensation to Client. For clarity, the co-ownership described in subsection (a) does not entitle Client to any revenue, royalties, or compensation arising from Provider's commercialization of Platform Enhancements pursuant to this subsection (d).\n\n8.3 Provider License-Back. Provider retains, and Client acknowledges that Provider retains, a perpetual, irrevocable, royalty-free license to use, reproduce, and create derivative works of any Client-Owned Deliverable for Provider's internal purposes and product development.\n\n9. INDEMNIFICATION\n\n9.1 Provider Indemnification. Provider shall indemnify, defend, and hold harmless Client from third-party claims alleging that the Platform, as delivered and used in compliance with this Agreement, infringes any United States patent issued as of the Effective Date, copyright, or trade secret, provided that Client: (a) promptly notifies Provider in writing of the claim; (b) grants Provider sole control of the defense and settlement; and (c) provides Provider with reasonable assistance.\n\n9.2 Client Indemnification. Client shall indemnify, defend, and hold harmless Provider and its Affiliates, officers, directors, employees, agents, successors, and assigns from and against any and all losses, damages, liabilities, deficiencies, actions, judgments, interest, awards, penalties, fines, costs, or expenses (including reasonable attorneys' fees and the cost of enforcing any right to indemnification) arising out of or related to: (a) Client's use of or access to the Platform; (b) Client Raw Data; (c) Client's violation of applicable law; (d) Client's breach of any representation, warranty, covenant, or obligation under this Agreement; or (e) any claim by Client's customers, partners, or regulators arising from Client's business operations or use of Deliverables.\n\n10. WARRANTIES\n\n10.1 Each party represents and warrants that: (a) it has the legal authority to enter into this Agreement; (b) its performance will not violate any applicable law; and (c) its performance will not infringe the intellectual property rights of any third party.\n\n10.2 Provider warrants that the Platform will perform materially in accordance with the SLA during the Subscription Term. Client's sole remedy for breach of this warranty is the service credits described in Schedule D.\n\n11. LIMITATION OF LIABILITY\n\n11.1 MUTUAL EXCLUSION OF CONSEQUENTIAL DAMAGES: Neither party shall be liable to the other for any indirect, incidental, consequential, special, exemplary, or punitive damages, including but not limited to lost profits, loss of revenue, loss of data, loss of goodwill, or cost of substitute goods or services, even if such party has been advised of the possibility of such damages.\n\n11.2 MUTUAL LIABILITY CAP: Subject to Section 11.4, each party's aggregate liability to the other party for all claims arising out of or related to this Agreement, whether in contract, tort, or otherwise, shall not exceed the total fees paid or payable by Client to Provider in the twelve (12) months immediately preceding the event giving rise to the claim.\n\n11.3 The limitations set forth in Sections 11.1 and 11.2 shall apply regardless of the theory of liability and regardless of whether a party has been advised of the possibility of such liability.\n\n11.4 EXCEPTIONS TO MUTUAL LIABILITY CAP: The mutual liability cap set forth in Section 11.2 shall not apply to, and there shall be no cap or limitation whatsoever on liability for:\n\n(a) a party's obligation to indemnify the other party pursuant to Section 9;\n\n(b) damages arising from a party's gross negligence or willful misconduct;\n\n(c) Client's payment obligations under this Agreement, including all fees, expenses, interest, and collection costs; and\n\n(d) Client's obligations with respect to intellectual property under Sections 7, 8, and 6.3, including but not limited to any unauthorized use of Provider's Background Technology, any failure to assign Developed Technology, and any breach of the data provisions of Section 6.\n\n11.5 For the avoidance of doubt, the exceptions in Section 11.4 mean that Client's liability for payment defaults and intellectual property breaches is unlimited, while Provider's liability for the same categories is subject to the cap in Section 11.2.\n\n12. TERMINATION\n\n12.1 Either party may terminate this Agreement for cause upon sixty (60) days written notice specifying the material breach, provided the breaching party fails to cure within the notice period.\n\n12.2 Either party may terminate this Agreement upon sixty (60) days written notice if the other party becomes insolvent, makes a general assignment for the benefit of creditors, or has a receiver appointed.\n\n12.3 Termination of this Agreement does not terminate any outstanding Statements of Work unless specifically agreed in writing.\n\n13. GENERAL\n\n13.1 This Agreement, together with all Schedules and SOWs, constitutes the entire agreement between the parties and supersedes all prior agreements, representations, and understandings.\n\n13.2 Provider may assign this Agreement or any of its rights or obligations hereunder without Client's consent. Client may not assign this Agreement without Provider's prior written consent, which shall not be unreasonably withheld.\n\n13.3 This Agreement shall be governed by the laws of the State of New York.",
|
| 129 |
+
"labels": [
|
| 130 |
+
{
|
| 131 |
+
"clause_id": "clause_3_4",
|
| 132 |
+
"risk_type": "auto_renewal",
|
| 133 |
+
"severity": 3,
|
| 134 |
+
"span_text": "SERVICE CONTINUITY PROVISION: To protect Client from inadvertent service interruption... if Provider has not received written confirmation from Client's designated contract administrator (as registered in Provider's customer portal) that Client elects to allow the Subscription Term to lapse, the Subscription Term shall automatically extend for a period equal to the greater of (i) the length of the expiring Subscription Term or (ii) twelve (12) months... at Provider's then-current standard list pricing",
|
| 135 |
+
"span_section": "Section 3.4",
|
| 136 |
+
"grader_note": "HARD: Clause is titled 'Service Continuity Provision' and opens with language about protecting the Client. The renewal trap is inside the protective framing. Notice must come from a specific named person in a portal (not email). The 60-day expiration notice (3.3) is explicitly not a condition precedent to renewal. Term can double (greater of current term or 12 months). Severity 3."
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"clause_id": "clause_6_3b",
|
| 140 |
+
"risk_type": "data_ownership_ambiguity",
|
| 141 |
+
"severity": 3,
|
| 142 |
+
"span_text": "statistical models, trained weights, learned parameters, and aggregated benchmarks derived by Provider from the processing of Client Raw Data across Provider's customer base, including data from Client (\"Derived Models\") shall be owned exclusively by Provider and may be incorporated into Provider's commercial products and services without compensation to Client",
|
| 143 |
+
"span_section": "Section 6.3(b)",
|
| 144 |
+
"grader_note": "Client retains raw data (6.1) but any model trained on it belongs to Provider. For an energy company, this means proprietary operational patterns and forecasting models derived from Client's data enrich Provider's commercial offerings."
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"clause_id": "clause_8_2d",
|
| 148 |
+
"risk_type": "ip_assignment_overreach",
|
| 149 |
+
"severity": 3,
|
| 150 |
+
"span_text": "Notwithstanding subsections (a) through (c), Provider is hereby granted, and Client hereby irrevocably grants to Provider, the exclusive, worldwide, perpetual, irrevocable, royalty-free right to commercialize, sublicense, incorporate into Provider's products and services, and otherwise exploit any Platform Enhancement in any manner Provider deems appropriate, without the consent of, notice to, or compensation to Client.",
|
| 151 |
+
"span_section": "Section 8.2(d)",
|
| 152 |
+
"grader_note": "HARD: Subsections (a)-(c) read as fair joint ownership. Subsection (d) begins with 'Notwithstanding' and grants Provider exclusive commercialization rights, making the 'co-ownership' in (a) commercially worthless. Agent must read all four subsections and recognise that (d) negates the apparent protection of (a)-(c)."
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"clause_id": "clause_11_4c",
|
| 156 |
+
"risk_type": "unlimited_liability",
|
| 157 |
+
"severity": 3,
|
| 158 |
+
"span_text": "The mutual liability cap set forth in Section 11.2 shall not apply to... (c) Client's payment obligations under this Agreement, including all fees, expenses, interest, and collection costs; and (d) Client's obligations with respect to intellectual property under Sections 7, 8, and 6.3",
|
| 159 |
+
"span_section": "Section 11.4(c) and 11.4(d)",
|
| 160 |
+
"grader_note": "HARD: Section 11.2 is titled 'MUTUAL LIABILITY CAP' and appears to protect both parties equally. Section 11.4 lists exceptions. Exceptions (a) and (b) are symmetric. Exceptions (c) and (d) apply only to Client, removing the cap on Client's payment and IP obligations while Provider retains the cap. Section 11.5 makes this asymmetry explicit but is easily overlooked. Agent must read 11.2 AND 11.4 together and notice the asymmetry."
|
| 161 |
+
}
|
| 162 |
+
]
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
]
|
| 166 |
+
}
|
inference.py
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
ContractRiskEnv Inference Script
|
| 3 |
+
===================================
|
| 4 |
+
MANDATORY
|
| 5 |
+
- Before submitting, ensure the following variables are defined in your environment configuration:
|
| 6 |
+
API_BASE_URL The API endpoint for the LLM.
|
| 7 |
+
MODEL_NAME The model identifier to use for inference.
|
| 8 |
+
HF_TOKEN Your Hugging Face / API key.
|
| 9 |
+
LOCAL_IMAGE_NAME The name of the local image to use for the environment if you are using from_docker_image()
|
| 10 |
+
|
| 11 |
+
- Defaults are set only for API_BASE_URL and MODEL_NAME:
|
| 12 |
+
API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
|
| 13 |
+
MODEL_NAME = os.getenv("MODEL_NAME", "gpt-4o")
|
| 14 |
+
|
| 15 |
+
- The inference script must be named `inference.py` and placed in the root directory of the project
|
| 16 |
+
- Participants must use OpenAI Client for all LLM calls using above variables
|
| 17 |
+
|
| 18 |
+
STDOUT FORMAT
|
| 19 |
+
- The script must emit exactly three line types to stdout, in this order:
|
| 20 |
+
|
| 21 |
+
[START] task=<task_name> env=<benchmark> model=<model_name>
|
| 22 |
+
[STEP] step=<n> action=<action_str> reward=<0.00> done=<true|false> error=<msg|null>
|
| 23 |
+
[END] success=<true|false> steps=<n> score=<score> rewards=<r1,r2,...,rn>
|
| 24 |
+
|
| 25 |
+
Rules:
|
| 26 |
+
- One [START] line at episode begin.
|
| 27 |
+
- One [STEP] line per step, immediately after env.step() returns.
|
| 28 |
+
- One [END] line after env.close(), always emitted (even on exception).
|
| 29 |
+
- reward and rewards are formatted to 2 decimal places.
|
| 30 |
+
- done and success are lowercase booleans: true or false.
|
| 31 |
+
- error is the raw last_action_error string, or null if none.
|
| 32 |
+
- All fields on a single line with no newlines within a line.
|
| 33 |
+
- Each tasks should return score in [0, 1]
|
| 34 |
+
"""
|
| 35 |
+
|
| 36 |
+
import asyncio
|
| 37 |
+
import json
|
| 38 |
+
import os
|
| 39 |
+
import textwrap
|
| 40 |
+
from typing import List, Optional
|
| 41 |
+
|
| 42 |
+
from openai import OpenAI
|
| 43 |
+
|
| 44 |
+
from contract_risk_env.client import ContractRiskEnv
|
| 45 |
+
from contract_risk_env.models import ContractAction, ClauseFlag
|
| 46 |
+
|
| 47 |
+
# ── Environment variables (competition-mandated) ────────────────────────────
|
| 48 |
+
IMAGE_NAME = os.getenv("LOCAL_IMAGE_NAME")
|
| 49 |
+
API_KEY = os.getenv("HF_TOKEN") or os.getenv("API_KEY")
|
| 50 |
+
|
| 51 |
+
API_BASE_URL = os.getenv("API_BASE_URL", "https://router.huggingface.co/v1")
|
| 52 |
+
MODEL_NAME = os.getenv("MODEL_NAME", "gpt-4o")
|
| 53 |
+
|
| 54 |
+
BENCHMARK = "contract_risk_env"
|
| 55 |
+
TASKS = ["easy", "medium", "hard"]
|
| 56 |
+
MAX_STEPS = 1 # 1-step environment: read contract → flag clauses
|
| 57 |
+
TEMPERATURE = 0.0
|
| 58 |
+
MAX_TOKENS = 4096
|
| 59 |
+
|
| 60 |
+
SYSTEM_PROMPT = textwrap.dedent("""
|
| 61 |
+
You are a legal contract risk analyst. You will be given a contract and must identify ALL risky clauses.
|
| 62 |
+
|
| 63 |
+
For each risky clause, return a JSON object with:
|
| 64 |
+
- clause_id: string matching the section numbering, e.g. "clause_4_2" for Section 4.2, "clause_6_3b" for a sub-part
|
| 65 |
+
- risk_type: one of ["unlimited_liability", "auto_renewal", "unilateral_amendment", "ip_assignment_overreach", "indemnification_asymmetry", "data_ownership_ambiguity", "termination_without_cause"]
|
| 66 |
+
- severity: integer 1 (medium), 2 (high), or 3 (critical)
|
| 67 |
+
- span_text: the exact text from the contract that contains the risk (quote directly, ≤300 chars)
|
| 68 |
+
|
| 69 |
+
Return your analysis as a JSON object with this exact schema:
|
| 70 |
+
{
|
| 71 |
+
"flagged_clauses": [ { "clause_id": "...", "risk_type": "...", "severity": N, "span_text": "..." }, ... ],
|
| 72 |
+
"confidence": 0.0 to 1.0,
|
| 73 |
+
"reasoning": "your chain-of-thought analysis"
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
Be thorough. Missing a real risk is worse than a false alarm. Pay special attention to:
|
| 77 |
+
- Clauses titled protectively but containing traps (e.g. "Service Continuity" hiding auto-renewal)
|
| 78 |
+
- Definitions sections that contain operative risk terms
|
| 79 |
+
- "Notwithstanding" clauses that negate preceding protections
|
| 80 |
+
- Asymmetric liability caps (mutual heading, one-sided exceptions)
|
| 81 |
+
- IP assignment buried in derivative work definitions
|
| 82 |
+
|
| 83 |
+
Return ONLY valid JSON, no markdown fences.
|
| 84 |
+
""").strip()
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
# ── Structured stdout logging ───────────────────────────────────────────────
|
| 88 |
+
|
| 89 |
+
def log_start(task: str, env: str, model: str) -> None:
|
| 90 |
+
print(f"[START] task={task} env={env} model={model}", flush=True)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def log_step(step: int, action: str, reward: float, done: bool, error: Optional[str]) -> None:
|
| 94 |
+
error_val = error if error else "null"
|
| 95 |
+
done_val = str(done).lower()
|
| 96 |
+
print(
|
| 97 |
+
f"[STEP] step={step} action={action} reward={reward:.2f} done={done_val} error={error_val}",
|
| 98 |
+
flush=True,
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def log_end(success: bool, steps: int, score: float, rewards: List[float]) -> None:
|
| 103 |
+
rewards_str = ",".join(f"{r:.2f}" for r in rewards)
|
| 104 |
+
print(
|
| 105 |
+
f"[END] success={str(success).lower()} steps={steps} score={score:.3f} rewards={rewards_str}",
|
| 106 |
+
flush=True,
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
# ── LLM call ────────────────────────────────────────────────────────────────
|
| 111 |
+
|
| 112 |
+
def call_llm(client: OpenAI, contract_text: str) -> dict:
|
| 113 |
+
"""Send contract to LLM, return parsed action dict."""
|
| 114 |
+
try:
|
| 115 |
+
completion = client.chat.completions.create(
|
| 116 |
+
model=MODEL_NAME,
|
| 117 |
+
messages=[
|
| 118 |
+
{"role": "system", "content": SYSTEM_PROMPT},
|
| 119 |
+
{"role": "user", "content": f"Analyze this contract for risky clauses:\n\n{contract_text}"},
|
| 120 |
+
],
|
| 121 |
+
temperature=TEMPERATURE,
|
| 122 |
+
max_tokens=MAX_TOKENS,
|
| 123 |
+
stream=False,
|
| 124 |
+
response_format={"type": "json_object"},
|
| 125 |
+
)
|
| 126 |
+
raw = (completion.choices[0].message.content or "").strip()
|
| 127 |
+
return json.loads(raw)
|
| 128 |
+
except Exception as exc:
|
| 129 |
+
print(f"[DEBUG] LLM call failed: {exc}", flush=True)
|
| 130 |
+
return {"flagged_clauses": [], "confidence": 0.0, "reasoning": str(exc)}
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
# ── Episode runner ──────────────────────────────────────────────────────────
|
| 134 |
+
|
| 135 |
+
async def run_episode(env, llm_client: OpenAI, task_id: str) -> float:
|
| 136 |
+
"""Run one episode (one task). Returns score in [0, 1]."""
|
| 137 |
+
rewards: List[float] = []
|
| 138 |
+
steps_taken = 0
|
| 139 |
+
score = 0.0
|
| 140 |
+
success = False
|
| 141 |
+
|
| 142 |
+
log_start(task=task_id, env=BENCHMARK, model=MODEL_NAME)
|
| 143 |
+
|
| 144 |
+
try:
|
| 145 |
+
result = await env.reset(task_id=task_id)
|
| 146 |
+
obs = result.observation
|
| 147 |
+
contract_text = obs.contract_text
|
| 148 |
+
|
| 149 |
+
# Step 1: Call LLM to analyze contract, then submit action
|
| 150 |
+
action_dict = call_llm(llm_client, contract_text)
|
| 151 |
+
|
| 152 |
+
flagged = []
|
| 153 |
+
for fc in action_dict.get("flagged_clauses", []):
|
| 154 |
+
try:
|
| 155 |
+
flagged.append(ClauseFlag(
|
| 156 |
+
clause_id=fc.get("clause_id", "unknown"),
|
| 157 |
+
risk_type=fc.get("risk_type", "unlimited_liability"),
|
| 158 |
+
severity=max(1, min(3, int(fc.get("severity", 1)))),
|
| 159 |
+
span_text=fc.get("span_text", "")[:300],
|
| 160 |
+
))
|
| 161 |
+
except Exception:
|
| 162 |
+
continue
|
| 163 |
+
|
| 164 |
+
action = ContractAction(
|
| 165 |
+
flagged_clauses=flagged,
|
| 166 |
+
confidence=float(action_dict.get("confidence", 0.5)),
|
| 167 |
+
reasoning=str(action_dict.get("reasoning", ""))[:500],
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
result = await env.step(action)
|
| 171 |
+
reward = result.reward or 0.0
|
| 172 |
+
done = result.done
|
| 173 |
+
error = None
|
| 174 |
+
|
| 175 |
+
rewards.append(reward)
|
| 176 |
+
steps_taken = 1
|
| 177 |
+
|
| 178 |
+
action_summary = f"flagged_{len(flagged)}_clauses"
|
| 179 |
+
log_step(step=1, action=action_summary, reward=reward, done=done, error=error)
|
| 180 |
+
|
| 181 |
+
score = reward # reward is already in [0, 1]
|
| 182 |
+
success = score > 0.0
|
| 183 |
+
|
| 184 |
+
except Exception as exc:
|
| 185 |
+
print(f"[DEBUG] Episode error: {exc}", flush=True)
|
| 186 |
+
if not rewards:
|
| 187 |
+
rewards.append(0.0)
|
| 188 |
+
steps_taken = 1
|
| 189 |
+
log_step(step=1, action="error", reward=0.0, done=True, error=str(exc))
|
| 190 |
+
|
| 191 |
+
finally:
|
| 192 |
+
log_end(success=success, steps=steps_taken, score=score, rewards=rewards)
|
| 193 |
+
|
| 194 |
+
return score
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
# ── Main ────────────────────────────────────────────────────────────────────
|
| 198 |
+
|
| 199 |
+
async def main() -> None:
|
| 200 |
+
llm_client = OpenAI(base_url=API_BASE_URL, api_key=API_KEY)
|
| 201 |
+
|
| 202 |
+
# Connect to environment — prefer docker image if set, else use base URL
|
| 203 |
+
if IMAGE_NAME:
|
| 204 |
+
env = await ContractRiskEnv.from_docker_image(IMAGE_NAME)
|
| 205 |
+
else:
|
| 206 |
+
env_url = os.getenv("ENV_BASE_URL", "http://localhost:8000")
|
| 207 |
+
env = ContractRiskEnv(base_url=env_url)
|
| 208 |
+
|
| 209 |
+
try:
|
| 210 |
+
scores = []
|
| 211 |
+
for task_id in TASKS:
|
| 212 |
+
score = await run_episode(env, llm_client, task_id)
|
| 213 |
+
scores.append(score)
|
| 214 |
+
|
| 215 |
+
mean_score = sum(scores) / len(scores) if scores else 0.0
|
| 216 |
+
print(f"\n[SUMMARY] mean_score={mean_score:.3f} easy={scores[0]:.3f} medium={scores[1]:.3f} hard={scores[2]:.3f}", flush=True)
|
| 217 |
+
finally:
|
| 218 |
+
try:
|
| 219 |
+
await env.close()
|
| 220 |
+
except Exception as e:
|
| 221 |
+
print(f"[DEBUG] env.close() error: {e}", flush=True)
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
if __name__ == "__main__":
|
| 225 |
+
asyncio.run(main())
|
openenv.yaml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: contract-risk-env
|
| 2 |
+
version: "1.0.0"
|
| 3 |
+
description: >
|
| 4 |
+
RL environment for legal contract risk clause detection.
|
| 5 |
+
Agent reads synthetic contracts and flags risky clauses.
|
| 6 |
+
Three tasks: easy (explicit risks), medium (cross-reference traps),
|
| 7 |
+
hard (protective-looking clauses with negating exceptions).
|
| 8 |
+
Grader is deterministic precision/recall/F1 against ground-truth labels.
|
| 9 |
+
tags: [openenv, legal, nlp, real-world, risk-detection]
|
| 10 |
+
entry_point: contract_risk_env.server.app:app
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
openenv-core>=0.2.2
|
| 2 |
+
fastapi>=0.104.0
|
| 3 |
+
uvicorn>=0.24.0
|
| 4 |
+
pydantic>=2.0
|
| 5 |
+
openai
|
| 6 |
+
python-dotenv
|
| 7 |
+
requests
|