Files
famlaw/activeblue_familylaw/CLAUDE.md

451 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md — activeblue_familylaw
This file gives Claude Code the context it needs to work effectively on this project.
Read this before making any changes.
---
## What This Is
**ActiveBlue Family Law** (`activeblue_familylaw`) is a custom Odoo 18 Community module for
Florida family law case management targeting **pro se litigants and full law firm operations**
in Miami-Dade County (11th Circuit).
The module runs an entire law firm within Odoo: intake, case tracking, AI-assisted legal
research, paralegal task management, discovery, court document generation, billing, and
case closure. It is not a lightweight helper — it is the primary practice management system.
Repo: `https://git.activeblue.net/tocmo0nlord/famlaw`
Module root: `activeblue_familylaw/`
Author: Active Blue LLC — `https://avc.activeblue.net`
Odoo version: **18.0**
License: LGPL-3
---
## Deployment Context
| Item | Value |
|---|---|
| Odoo instance | `192.168.2.9:8069` (Docker, local network only) |
| Target database | `db1` (accessed at `192.168.2.9:8069` — no public hostname) |
| Odoo version | 18.0 Community |
| AI inference | Claude API — `claude-sonnet-4-20250514` |
| Git remote | `https://git.activeblue.net/tocmo0nlord/famlaw` |
> **Note:** This instance is local-only on the `192.168.2.x` network. There is no external
> hostname or reverse proxy for this deployment. Traefik is not in use here. All access is
> direct to `192.168.2.9:8069`. Do not reference CT 112, `192.168.1.53`, or `avc.activeblue.net`
> for this module.
---
## AI Agent Architecture
This module uses **two distinct AI agents** backed by the Claude API (`claude-sonnet-4-20250514`).
Both agents write to the `fl.case` chatter for full auditability. All API calls must handle
`anthropic.APIError` and `anthropic.APIConnectionError` gracefully — never let AI failures
block user workflow. Log failures to chatter as a warning.
### Paralegal Agent (`fl_paralegal_agent.py`)
Handles procedural intelligence. Runs automatically on case stage transitions and can be
triggered manually from any case.
Responsibilities:
- Florida Rules of Civil Procedure deadline calculation (service by mail +5 days, holidays
excluded via Python `holidays` library, judicial holidays for 11th Circuit)
- Task batch generation per stage (see Stage Machine below)
- Statute cross-reference for active issue tags on the case
- Mandatory disclosure checklist generation (FL-12.932)
- Chatter summary after every bulk action
- Non-billable AI time logging to `fl.timesheet` for audit trail
Prompt strategy: always include `case_type`, `complexity`, `issue_tag_ids`, active deadlines,
and current stage. Keep system prompt under 800 tokens — pass case context as user message.
### Attorney Agent (`fl_attorney_agent.py`)
Handles substantive legal reasoning. Fires on demand (button on AI tab of `fl.case`).
Never runs automatically — always a deliberate user action.
Responsibilities:
- Full case questionnaire analysis → strategy memo stored in `fl.analysis`
- Top 35 applicable FL statutes identified and linked to `fl.statute` records
- Top 35 relevant case law entries linked to `fl.caselaw` records
- Argument drafting for the case's primary issue tags
- Risk flag narrative (DV, hidden assets, income imputation, unrepresented respondent)
- Child support modification: auto-detect substantial change of circumstances (§61.30(1)(b)),
pull last 3 years of support schedule from case history
Prompt strategy: include full intake questionnaire responses, parties, children, financial
data summary, and any prior `fl.analysis` records so the agent builds on prior work.
### Rule-Based Fallback
Both agents fall back to rule-based logic when the Claude API is unavailable. The fallback
must cover: complexity scoring, basic deadline calculation, and a minimal task batch.
Never surface a raw API error to the user.
---
## Module Structure
```
activeblue_familylaw/
├── __manifest__.py
├── __init__.py
├── models/
│ ├── fl_ai_engine.py ← Shared Claude API client + retry logic
│ ├── fl_paralegal_agent.py ← Paralegal AI agent (procedural)
│ ├── fl_attorney_agent.py ← Attorney AI agent (substantive)
│ ├── fl_analysis.py ← AI analysis records
│ ├── fl_argument.py ← Legal argument tracking
│ ├── fl_case.py ← Core case model (fl.case) + stage machine
│ ├── fl_caselaw.py ← FL case law library
│ ├── fl_child.py ← Minor children records
│ ├── fl_conflict_check.py ← Conflict of interest check engine
│ ├── fl_deadline.py ← Procedural deadline tracking + auto-calc
│ ├── fl_deposition.py ← Deposition scheduling
│ ├── fl_discovery.py ← Discovery requests/responses
│ ├── fl_document.py ← Court document management
│ ├── fl_efiling.py ← FL 11th Circuit e-filing portal integration
│ ├── fl_expense_case.py ← Case-linked expense tracking
│ ├── fl_fee_waiver.py ← Fee waiver eligibility
│ ├── fl_hearing.py ← Hearing calendar integration
│ ├── fl_income_withholding.py ← Income withholding orders
│ ├── fl_party.py ← Petitioner/Respondent parties
│ ├── fl_signature_request.py ← E-signature workflow (external, spec-compliant)
│ ├── fl_statute.py ← FL statute reference index
│ ├── fl_support.py ← FL 61.30 child support calc
│ └── fl_timesheet.py ← Billable hours + AI audit time (wraps account.analytic.line)
├── wizard/
│ ├── fl_intake_wizard.py ← Guided case creation + fires Attorney agent on finish
│ ├── fl_analysis_wizard.py ← Trigger AI analysis
│ ├── fl_generate_packet_wizard.py ← Generate filing packet
│ ├── fl_discovery_suggest_wizard.py ← Complexity-driven discovery suggestions
│ └── fl_efiling_wizard.py ← Prepare and submit to FL e-Filing Portal
├── views/
│ ├── fl_case_views.xml ← Kanban + form + list views, stage bar
│ ├── fl_conflict_check_views.xml
│ ├── fl_discovery_suggest_views.xml
│ ├── fl_efiling_views.xml
│ ├── fl_signature_request_views.xml
│ ├── fl_timesheet_views.xml
│ ├── menu_views.xml
│ ├── portal_*.xml ← Client-facing portal templates
│ └── website_intake_templates.xml
├── report/ ← 12 QWeb PDF court documents
│ ├── report_financial_affidavit_short.xml ← FL-12.902(b)
│ ├── report_financial_affidavit_long.xml ← FL-12.902(c)
│ ├── report_child_support_worksheet.xml ← FL-12.902(e)
│ ├── report_motion_to_modify.xml
│ ├── report_notice_deposition.xml
│ ├── report_motion_to_compel.xml
│ ├── report_income_withholding.xml
│ ├── report_fee_waiver.xml
│ ├── report_notice_ssn.xml ← FL-12.930(a)
│ ├── report_mandatory_disclosure.xml ← FL-12.932
│ ├── report_default_motion.xml
│ └── report_parenting_plan.xml
├── data/
│ ├── fl_support_schedule.xml ← Basic Support Obligation table
│ ├── fl_statute_data.xml ← FL statute index seeds
│ ├── fl_caselaw_data.xml ← 23 pre-loaded FL cases
│ ├── fl_deadline_rules.xml ← Procedural deadline rules
│ ├── fl_issue_tags.xml ← Issue taxonomy
│ ├── fl_stage_data.xml ← Case stage records (Kanban)
│ ├── ir_sequence.xml ← Case number sequences
│ ├── mail_templates.xml
│ └── case_task_templates.xml
├── security/
│ ├── fl_security.xml
│ └── ir.model.access.csv
├── controllers/ ← Portal + website intake + e-filing webhook routes
└── static/src/
├── css/familylaw_portal.css
└── js/
├── fl_calculator.js ← Interactive FL 61.30 widget
└── fl_timeline.js ← Visual case timeline
```
---
## Core Domain Models
All models use the `fl.` prefix.
| Model | Description |
|---|---|
| `fl.case` | Root entity — case type, parties, status, stage, AI complexity score |
| `fl.party` | Petitioner or Respondent (links to `res.partner`) |
| `fl.child` | Minor children on the case |
| `fl.support` | FL 61.30 child support calculation |
| `fl.deadline` | Procedural deadlines with calendar sync + auto-calculation |
| `fl.hearing` | Scheduled hearings |
| `fl.discovery` | Individual discovery requests/responses |
| `fl.discovery.suggest.wizard` | Complexity-driven discovery suggestion engine |
| `fl.discovery.suggest.line` | One suggested discovery item |
| `fl.deposition` | Deposition scheduling and tracking |
| `fl.document` | Court-filed documents (linked to reports) |
| `fl.analysis` | AI case analysis records (both agents write here) |
| `fl.caselaw` | Florida case law library entries |
| `fl.statute` | FL statute reference index |
| `fl.fee.waiver` | Fee waiver eligibility and form data |
| `fl.income.withholding` | Income withholding order records |
| `fl.argument` | Legal argument tracking (linked to case law) |
| `fl.conflict.check` | Conflict of interest check result per intake |
| `fl.signature.request` | E-signature request linked to a court document |
| `fl.efiling.submission` | FL e-Filing Portal submission record |
| `fl.timesheet` | Billable hours + AI audit entries (wraps `account.analytic.line`) |
### Key Fields on `fl.case`
- `case_type`: `modification` | `dissolution` | `paternity`
- `stage_id`: Many2one `fl.case.stage` — drives Kanban and Paralegal agent task batches
- `complexity`: `low` | `medium` | `high` | `extreme` (set by Attorney agent or rule-based fallback)
- `issue_tag_ids`: Many2many `fl.issue.tag` — used by both agents and discovery suggestion wizard
- `domestic_violence_flag`, `respondent_has_counsel`, `income_imputation_concern`: boolean flags
that affect discovery templates and Attorney agent prompt
- `conflict_check_passed`: Boolean — case cannot move past Intake stage until True
- `attorney_memo_id`: Many2one `fl.analysis` — current Attorney agent strategy memo
---
## Case Stage Machine
Stages are defined in `fl_stage_data.xml` and drive the Kanban view on `fl.case`.
Each stage transition triggers the **Paralegal agent** to generate the next task batch.
| Stage | Trigger | Paralegal Task Batch Generated |
|---|---|---|
| `Intake` | Case created | Conflict check, questionnaire completion, fee waiver assessment |
| `Active` | Intake complete + conflict check passed | Service of process, mandatory disclosure (FL-12.932), initial hearings |
| `Discovery` | Attorney fires analysis; complexity ≥ medium | Interrogatories, production requests, depositions per discovery suggest wizard |
| `Pre-Trial` | Discovery closed | Pretrial statement, exhibit list, witness list, mediation scheduling |
| `Closed` | Final order filed | Archive checklist, billing reconciliation, file retention notice |
Stage transitions validate preconditions (e.g., cannot enter `Active` without `conflict_check_passed`).
Use `_check_stage_transition()` on `fl.case` — raise `UserError` with a clear message, never silent.
---
## Conflict of Interest Check (`fl_conflict_check.py`)
Run automatically on `fl.case` creation before any other action.
Logic:
1. Collect `name` from all `fl.party` records on the new case (petitioner + respondent).
2. Query all active `fl.party` records on other open cases.
3. Check for name overlap (exact + fuzzy — use `difflib.SequenceMatcher`, threshold 0.85).
4. If a match is found: create a `fl.conflict.check` record with `status = 'conflict'`,
log to chatter with matched case reference, and set `fl.case.conflict_check_passed = False`.
5. If no match: set `status = 'clear'` and `conflict_check_passed = True` automatically.
6. A user with group `fl_group_manager` can manually override a conflict with a written
justification stored on the `fl.conflict.check` record.
Never silently pass a conflict. Always surface it to the user.
---
## E-Signature Workflow (`fl_signature_request.py`)
> **Important:** Odoo Sign is **not within spec** for Florida court document e-signatures.
> Florida courts require specific PDF/A-compliant documents with court-approved signature
> fields per the FL Supreme Court Administrative Order AOSC09-30 (amended). Do not use
> Odoo Sign for court filings.
Architecture:
- `fl.signature.request` links to one `fl.document` and one `res.partner` (signer).
- On creation, generate the QWeb PDF, flatten form fields except the signature block,
and store as `ir.attachment` with `mimetype = 'application/pdf'`.
- The signature block coordinates are document-type-specific — define them in a
`_SIGNATURE_COORDS` dict keyed by report template XML ID:
```python
_SIGNATURE_COORDS = {
'activeblue_familylaw.report_financial_affidavit_short': {'page': 1, 'x': 72, 'y': 680, 'w': 200, 'h': 30},
# ... one entry per report
}
```
- Delivery: email the PDF to the signer via Odoo mail with a portal link.
The portal page (`/familylaw/sign/<token>`) uses an HTML5 canvas signature pad
(no external JS dependency — draw to canvas, export as PNG, embed via PyMuPDF into
the PDF at the defined coordinates).
- On completion: write signature PNG into the PDF at correct coordinates, update
`fl.signature.request.state = 'signed'`, attach the signed PDF to `fl.document`,
and log to chatter.
- For documents going to the FL e-Filing Portal, the signed PDF must pass:
`pikepdf` validation for PDF/A compliance before submission is allowed.
Never use DocuSign, HelloSign, or any external e-signature SaaS — all processing
must be self-hosted per HIPAA and data sovereignty requirements.
---
## FL 11th Circuit E-Filing Integration (`fl_efiling.py`)
The Florida Courts e-Filing Portal (`eportal.flcourts.org`) exposes a REST API.
Full programmatic filing is the target; the current phase implements preparation and
assisted submission.
### Phase 1 (current): Assisted submission
- `fl_efiling_wizard.py` walks the user through preparation steps.
- Auto-generate the court-compliant filename per 11th Circuit convention:
`{LastName}_{CaseNumber}_{DocumentType}_{YYYYMMDD}.pdf`
Example: `Smith_2024-DR-012345_MotionToModify_20240915.pdf`
- Validate PDF/A compliance via `pikepdf` before allowing submission.
- One-click button opens `eportal.flcourts.org` deep-linked to the correct case
(append `?caseNumber={fl.case.court_case_number}` if available).
- Store `fl.efiling.submission` record with status `pending_manual`.
### Phase 2 (planned): API submission
- FL e-Filing Portal API endpoint: `https://api.eportal.flcourts.org/` (confirm current
base URL from portal documentation before implementing).
- Authentication: username/password token exchange stored in `ir.config_parameter`
(keys: `fl_efiling.username`, `fl_efiling.password`) — never hardcoded.
- On successful API submission: update `fl.efiling.submission.status = 'submitted'`,
store the portal confirmation number, log to chatter.
- On failure: log full error to chatter, set status `failed`, surface error message
to user — never silent failure.
---
## Deadline Engine (`fl_deadline.py`)
`_compute_due_date()` must handle:
- Florida Rules of Civil Procedure Part II service windows:
- 20-day answer period after service
- 45-day mandatory disclosure window (FL-12.932)
- 30-day response to interrogatories
- Service by mail: add 5 days (Fla. R. Civ. P. 1.090(e))
- Holiday exclusion: use Python `holidays` library with `holidays.US(state='FL')` plus
11th Circuit judicial holidays (hardcode the annual list in `fl_deadline_rules.xml`
and merge at runtime).
- `_recalculate_all(case_id)`: callable by Paralegal agent — recalculates all open
deadlines on a case when a new event is logged (hearing date set, service confirmed, etc.).
- Calendar sync: write to `calendar.event` for every `fl.deadline` — use `_sync_to_calendar()`
called in `create` and `write`.
---
## Time Tracking + Billing (`fl_timesheet.py`)
`fl.timesheet` wraps `account.analytic.line` and adds case context.
Key fields:
- `case_id`: Many2one `fl.case` (required)
- `employee_id`: Many2one `hr.employee`
- `is_billable`: Boolean (default True; False for AI audit entries)
- `ai_agent`: Selection `paralegal` | `attorney` | None — set when the Paralegal or
Attorney agent auto-logs time
- `duration_hours`: Float (maps to `unit_amount` on `account.analytic.line`)
Usage:
- Attorneys and paralegals log time manually from the case form (Timesheet tab).
- Both AI agents log non-billable entries automatically for audit trail.
- The case form shows a computed `total_billable_hours` and `total_billable_amount`
(rate from `hr.employee` or a default firm rate in `ir.config_parameter`).
- Invoicing flows through standard Odoo Accounting — `account.analytic.line` entries
are picked up by `account.move` generation as usual.
---
## Odoo Dependencies
Declared in `__manifest__.py`:
```python
'depends': [
'base', 'mail', 'portal', 'website',
'contacts', 'calendar', 'project',
'crm', 'account', 'hr_expense', 'analytic',
# 'sign' — DO NOT enable: not within FL court e-signature spec
# 'queue_job' — OCA, install separately if needed for async AI calls
]
```
`sign` is intentionally excluded — Florida court e-signatures require custom PDF handling
outside Odoo Sign's capabilities. `queue_job` is optional for async Claude API calls.
---
## Development Conventions
### Odoo 18 Patterns
- Use `fields.Html` for rich text, `fields.Text` for plain
- `@api.depends` for computed fields; always set `store=True` if used in search/group
- Use `_inherit` not `_name` for extending existing Odoo models
- All new models need entries in `ir.model.access.csv` AND `fl_security.xml`
- XML IDs must be unique across the module — prefix everything with `fl_`
### Views
- Actions must be declared before `<menuitem>` references in `menu_views.xml`
- Portal templates go in `views/portal_*.xml`
- Website intake templates go in `views/website_intake_templates.xml`
- Always test QWeb reports with `wkhtmltopdf` — paper sizes matter for court forms
- Kanban view on `fl.case` must show: case number, case type, complexity badge,
next deadline, and conflict check status badge
### Claude API (`fl_ai_engine.py`)
- Use the `anthropic` Python library — `pip install anthropic`
- API key stored in `ir.config_parameter` key `fl_ai.claude_api_key` — never hardcoded
- Model: always `claude-sonnet-4-20250514` — do not make this a user-configurable field
- Always handle `anthropic.APIError`, `anthropic.APIConnectionError`, `anthropic.RateLimitError`
- Log all AI calls (model, tokens used, latency) to chatter as an internal note
- Use the rule-based fallback in `fl_ai_engine._fallback_complexity()` when API unavailable
- Never block user workflow on AI failure
### Discovery Suggest Wizard
- Add new discovery templates to `_get_templates()` in `fl_discovery_suggest_wizard.py`
- Each template: `type`, `directed_to`, `description`, `rationale`, `trigger`, `min_complexity`
- Triggers are string labels — keep consistent with existing ones
- `action_create_selected` posts a chatter summary — keep it
### Reports (QWeb)
- Court form dimensions: US Letter (8.5×11 in) — set `paperformat_id` appropriately
- Florida court forms reference: FL Supreme Court forms at `www.flcourts.gov`
- Field labels must match official form labels exactly
- All reports used for e-filing must be PDF/A compliant — validate with `pikepdf` in CI
### Security Groups
| Group | Access |
|---|---|
| `fl_group_user` | Create/edit own cases, read all |
| `fl_group_paralegal` | All of above + manage deadlines, tasks, discovery |
| `fl_group_attorney` | All of above + fire Attorney agent, manage arguments |
| `fl_group_manager` | Full access + conflict override + billing |
---
## Out of Scope for This Repo
- Odoo AI agent / Master AI system → `tocmo0nlord/odoo-ai` (separate repo)
- IRC bot → `tocmo0nlord/irc-bot`
- Infrastructure config → handled at Docker/network layer, not this module
- HIPAA training eLearning module → different Odoo addon
- Traefik configuration → not in use on `.2.1` network for this module
---
## Running / Testing
```bash
# Restart Odoo to pick up module changes
docker compose restart odoo
# Update module (from Odoo container or Settings → Apps)
# Technical → Update Apps List first if adding new files
# Check logs
docker compose logs -f odoo | grep activeblue_familylaw
# Validate PDF/A compliance on a generated report (requires pikepdf)
python3 -c "import pikepdf; pdf = pikepdf.open('/tmp/test.pdf'); print(pdf.docinfo)"
```
Module installs via **Apps → Upload a Module** or by placing it in the addons path.
After any model change: **Settings → Activate Developer Mode → Technical → Update Apps List → Upgrade**.
### Claude API key setup
```bash
# In Odoo shell (Settings → Technical → Parameters → System Parameters)
# Key: fl_ai.claude_api_key
# Value: sk-ant-...
```