21 KiB
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.xnetwork. There is no external hostname or reverse proxy for this deployment. Traefik is not in use here. All access is direct to192.168.2.9:8069. Do not reference CT 112,192.168.1.53, oravc.activeblue.netfor 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
holidayslibrary, 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.timesheetfor 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 3–5 applicable FL statutes identified and linked to
fl.statuterecords - Top 3–5 relevant case law entries linked to
fl.caselawrecords - 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|paternitystage_id: Many2onefl.case.stage— drives Kanban and Paralegal agent task batchescomplexity:low|medium|high|extreme(set by Attorney agent or rule-based fallback)issue_tag_ids: Many2manyfl.issue.tag— used by both agents and discovery suggestion wizarddomestic_violence_flag,respondent_has_counsel,income_imputation_concern: boolean flags that affect discovery templates and Attorney agent promptconflict_check_passed: Boolean — case cannot move past Intake stage until Trueattorney_memo_id: Many2onefl.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:
- Collect
namefrom allfl.partyrecords on the new case (petitioner + respondent). - Query all active
fl.partyrecords on other open cases. - Check for name overlap (exact + fuzzy — use
difflib.SequenceMatcher, threshold 0.85). - If a match is found: create a
fl.conflict.checkrecord withstatus = 'conflict', log to chatter with matched case reference, and setfl.case.conflict_check_passed = False. - If no match: set
status = 'clear'andconflict_check_passed = Trueautomatically. - A user with group
fl_group_managercan manually override a conflict with a written justification stored on thefl.conflict.checkrecord.
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.requestlinks to onefl.documentand oneres.partner(signer).- On creation, generate the QWeb PDF, flatten form fields except the signature block,
and store as
ir.attachmentwithmimetype = 'application/pdf'. - The signature block coordinates are document-type-specific — define them in a
_SIGNATURE_COORDSdict keyed by report template XML ID:_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 tofl.document, and log to chatter. - For documents going to the FL e-Filing Portal, the signed PDF must pass:
pikepdfvalidation 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.pywalks the user through preparation steps.- Auto-generate the court-compliant filename per 11th Circuit convention:
{LastName}_{CaseNumber}_{DocumentType}_{YYYYMMDD}.pdfExample:Smith_2024-DR-012345_MotionToModify_20240915.pdf - Validate PDF/A compliance via
pikepdfbefore allowing submission. - One-click button opens
eportal.flcourts.orgdeep-linked to the correct case (append?caseNumber={fl.case.court_case_number}if available). - Store
fl.efiling.submissionrecord with statuspending_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
holidayslibrary withholidays.US(state='FL')plus 11th Circuit judicial holidays (hardcode the annual list infl_deadline_rules.xmland 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.eventfor everyfl.deadline— use_sync_to_calendar()called increateandwrite.
Time Tracking + Billing (fl_timesheet.py)
fl.timesheet wraps account.analytic.line and adds case context.
Key fields:
case_id: Many2onefl.case(required)employee_id: Many2onehr.employeeis_billable: Boolean (default True; False for AI audit entries)ai_agent: Selectionparalegal|attorney| None — set when the Paralegal or Attorney agent auto-logs timeduration_hours: Float (maps tounit_amountonaccount.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_hoursandtotal_billable_amount(rate fromhr.employeeor a default firm rate inir.config_parameter). - Invoicing flows through standard Odoo Accounting —
account.analytic.lineentries are picked up byaccount.movegeneration as usual.
Odoo Dependencies
Declared in __manifest__.py:
'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.Htmlfor rich text,fields.Textfor plain @api.dependsfor computed fields; always setstore=Trueif used in search/group- Use
_inheritnot_namefor extending existing Odoo models - All new models need entries in
ir.model.access.csvANDfl_security.xml - XML IDs must be unique across the module — prefix everything with
fl_
Views
- Actions must be declared before
<menuitem>references inmenu_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.casemust show: case number, case type, complexity badge, next deadline, and conflict check status badge
Claude API (fl_ai_engine.py)
- Use the
anthropicPython library —pip install anthropic - API key stored in
ir.config_parameterkeyfl_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()infl_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_selectedposts a chatter summary — keep it
Reports (QWeb)
- Court form dimensions: US Letter (8.5×11 in) — set
paperformat_idappropriately - 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
pikepdfin 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.1network for this module
Running / Testing
# 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
# In Odoo shell (Settings → Technical → Parameters → System Parameters)
# Key: fl_ai.claude_api_key
# Value: sk-ant-...