Initial commit — Step 1 complete: case spine, lifecycle, attorney gates
Delivers the validated Step 1 slice of the Active Blue Family Law platform (Odoo 18 Community module `activeblue_familylaw`): - familylaw.case model: identity, team, representation flag, conflict_check_cleared gate - Full lifecycle state machine (intake→engaged→disclosure→discovery→mediation→hearing→closed) - Attorney-only guards enforced in Python + view groups= - Security groups (Family Law/Staff, Family Law/Attorney), model access rules - List, form, and search views (Odoo 18 <list> syntax; no attrs=/states=) - Family Law app menu with Configuration placeholder - 10 tagged unit tests (familylaw_step1): transitions, conflict gate, attorney-only, audit - CLAUDE.md, BUILD_PLAN.md, START_HERE.md: full design brief and step contract Step 2 (parties, children, issues, proceeding model, conflict screening, intake questionnaire) is the next build target. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
*.egg-info/
|
||||
dist/
|
||||
build/
|
||||
*.egg
|
||||
|
||||
# Odoo
|
||||
*.pot
|
||||
*.mo
|
||||
*.pyc
|
||||
|
||||
# Editors
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
*.local
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Node (if any frontend tooling added later)
|
||||
node_modules/
|
||||
598
CLAUDE.md
Normal file
598
CLAUDE.md
Normal file
@@ -0,0 +1,598 @@
|
||||
# CLAUDE.md — Active Blue Family Law Platform
|
||||
|
||||
> **Handoff document for Claude Code.** This is the single source of truth for the
|
||||
> project: what it is, how it's architected, the decisions already made, what's been
|
||||
> built, and what to build next. Read this fully before writing code. Companion
|
||||
> design docs (`00`–`11`) live in the design package; this file is the operational
|
||||
> brief that ties them together.
|
||||
|
||||
---
|
||||
|
||||
## 1. What we're building (and the one rule that governs everything)
|
||||
|
||||
A **case-management platform for a Florida family-law practice** in **Miami-Dade
|
||||
(11th Judicial Circuit)**, built on **Odoo 18 Community**. A staff member with
|
||||
**little legal knowledge** enters case data through guided intake; the software
|
||||
**assembles the case** — manages it, attaches verified case law, tracks
|
||||
statutory/procedural requirements and evidence, and flags what's needed for
|
||||
success — and routes a **finished, draft case package to a licensed attorney who
|
||||
reads it, verifies it, and signs it.** The attorney owns the output.
|
||||
|
||||
**THE GOVERNING RULE — non-negotiable, enforced in code, not policy:**
|
||||
|
||||
> The software **builds, verifies, organizes, and flags.** A **licensed attorney
|
||||
> judges, decides, and signs.** Nothing reaches a client, a clerk, or a courtroom
|
||||
> without attorney approval. The AI is the paralegal who never sleeps — **it is not
|
||||
> the lawyer.**
|
||||
|
||||
**Claude's specific role = the quality-elevation layer.** Claude exists to produce
|
||||
*high-quality, verified, fully-assembled* work product — drafted documents, extracted
|
||||
facts, completeness-checked files, and **verified** case-law research — and **move it
|
||||
UP to the licensed attorney for sign-off**. The point of using a frontier model is the
|
||||
quality of what gets elevated: the attorney receives something strong enough to approve
|
||||
with minor edits, fast. Claude *intervenes* by supplying verified case law and the
|
||||
available next steps/avenues — **not** by deciding strategy or rendering the legal
|
||||
opinion. The intervention makes the attorney faster; it never replaces them.
|
||||
|
||||
This exists because the platform must **not** practice law. Two structural gates
|
||||
enforce it everywhere:
|
||||
1. **The review gate** — AI-produced work is born in a draft state; only a licensed
|
||||
attorney (group) can approve it; nothing can be filed/sent/signed unapproved.
|
||||
2. **The citation gate** — every case-law citation is born `unverified` and must
|
||||
pass verification (exists / on-point / good-law) against a real database before
|
||||
it can enter a filing. (Lawyers have been sanctioned for AI-hallucinated cites;
|
||||
this makes that mechanically impossible.)
|
||||
|
||||
**The product goal is a high attorney-approval rate achieved by producing genuinely
|
||||
good, complete, citation-verified work — NOT by making review shallow.** The win
|
||||
condition is "approve with minor edits, fast," like a senior partner redlining a
|
||||
strong associate draft.
|
||||
|
||||
**How the software improves over time — the SAFE loop (read this carefully).** The
|
||||
near-term improvement mechanism is **prompt and few-shot-example refinement plus the
|
||||
regression eval suite** — NOT model fine-tuning on live matters. Family-law work
|
||||
product is full of **confidential, privileged client data** (Bar Rule 4-1.6); feeding
|
||||
attorney-corrected drafts into model training risks leaking one client's information
|
||||
into another client's matter, which is far worse than any bad draft. Therefore:
|
||||
- The default loop is: attorney edits → those edits inform **curated, hand-written
|
||||
exemplars and prompt tweaks** + new regression test cases → output improves. No
|
||||
client data enters any training process by default.
|
||||
- **Fine-tuning is a FUTURE, GATED capability**, not part of this build, and only ever
|
||||
on a **de-identified, attorney-approved, consented** corpus held separately that
|
||||
**never auto-ingests live matters**. (See doc 09 §10 cautions.)
|
||||
The attorney is the quality bar and the source of curated examples — never an
|
||||
unwitting training-data faucet, and never a bottleneck to engineer around.
|
||||
|
||||
---
|
||||
|
||||
## 2. Capabilities the platform must deliver
|
||||
|
||||
Derived backward from the outcome: **a non-lawyer enters facts → a complete,
|
||||
verified, attorney-signable case package comes out, fast enough that the attorney's
|
||||
review is confirmatory, not corrective.** Every capability earns its place by serving
|
||||
that outcome. **Grouped by RISK, not feature area** — the tier tells you what's safe
|
||||
to build now vs. what needs attorney-validated legal content first.
|
||||
|
||||
### Tier 1 — The spine (capture & manage) — *safe to build now; data + deterministic rules*
|
||||
1. **Guided intake & fact capture** — the adaptive questionnaire (triage routes by
|
||||
case type; branches collect exactly the facts each matter needs, in plain
|
||||
language). **Highest-leverage capability in the system** — everything downstream
|
||||
is only as good as the facts captured here; bad capture is the #1 cause of a draft
|
||||
getting sent back.
|
||||
2. **Case management & system of record** — matter, parties, children, issues,
|
||||
**proceedings** (each modification/enforcement is a child `familylaw.proceeding`
|
||||
under the case — see §4), lifecycle state, team. The Odoo spine; the container
|
||||
everything fills.
|
||||
3. **Automated conflict-of-interest screening** — when intake captures the opposing
|
||||
party, the system **searches every party across every matter** and surfaces
|
||||
potential conflicts (opposing party was a past client; is adverse to a current
|
||||
client) **for the attorney to clear**. A human ticking a checkbox across hundreds
|
||||
of matters *will* miss structural conflicts; an undetected conflict can disqualify
|
||||
the firm and void work (Bar Rules 4-1.7/4-1.9). The software does the search a
|
||||
human can't do reliably; the **attorney still decides** (the Step 1
|
||||
`conflict_check_cleared` gate stays). Belongs in Step 2 (needs the party model).
|
||||
3. **Document & evidence repository** — every document on the matter, versioned,
|
||||
checksummed, with legal metadata (type, privilege, retention). The case file as
|
||||
one organized source of truth.
|
||||
4. **Deadline & calendar engine** — statutory/procedural clocks (answer, disclosure,
|
||||
discovery, objection windows) computed deterministically, surfaced on a layered,
|
||||
filterable calendar. Pure rules + date math; a real differentiator (a missed
|
||||
family-law deadline is malpractice).
|
||||
|
||||
### Tier 2 — The assembly (build the case) — *safe to build now; assembly + deterministic scoring*
|
||||
5. **Document drafting** — first drafts of pleadings/motions/forms from captured
|
||||
facts, with placeholders for unknowns, born as drafts for attorney review. Where
|
||||
the non-lawyer's facts become legal documents.
|
||||
6. **Procedural avenue mapping + decision graph** — given case type + what changed,
|
||||
surface the *available* procedural paths with their required elements and deadlines,
|
||||
rendered as a **branching decision graph** the attorney can compare at a glance. The
|
||||
menu, **not** the decision. Suggests; never strategizes. **Each path node shows a
|
||||
STRENGTH-OF-SUPPORT comparison — NOT a success percentage:**
|
||||
- procedural requirements (forms, elements, proof needed);
|
||||
- **strength factors present / missing**, drawn factually from the case data (e.g.
|
||||
"income change exceeds 15% threshold ✓; underemployment evidence not gathered ✗;
|
||||
financial affidavit on file ✓");
|
||||
- effort + timeline (deterministic: deadlines, steps, typical duration);
|
||||
- key risks / unknowns ("outcome depends on whether the court imputes income — a
|
||||
judgment call for the attorney");
|
||||
- what would strengthen the path (the gaps to close).
|
||||
**This deliberately does NOT output a win probability.** A "% chance of success" is
|
||||
fabricated precision (no honest dataset of comparable sealed/settled Miami-Dade
|
||||
outcomes exists), it is functionally the legal *opinion* only a licensed attorney may
|
||||
give, it becomes Bar-complaint/malpractice evidence if the case loses, and it anchors
|
||||
the attorney into shallow review. The graph compares **which path the facts on hand
|
||||
best support**; the attorney converts that into a probability using their own
|
||||
judgment and license. (See EXCLUDED, below.)
|
||||
7. **Requirements & completeness scoring** — the readiness engine: score the file
|
||||
against what a complete case of that type/stage needs (forms, proven facts,
|
||||
evidentiary foundations, met deadlines) and surface gaps **before** the attorney
|
||||
sees it. **The capability that most directly drives approval rate** — it catches
|
||||
the omissions that cause rejections. (Feeds the "strength factors" in capability 6.)
|
||||
|
||||
### Tier 3 — The legal support (high-risk, high-value core) — *NEEDS attorney-validated legal content before shipping*
|
||||
8. **Case-law research & verified citations** — propose authority, draft argument,
|
||||
and **verify every citation against a real reporter (CourtListener) before it can
|
||||
enter a filing**; unverified = mechanically blocked. Most valuable *and* most
|
||||
dangerous — the part that makes the software feel like it knows law, and the part
|
||||
that gets people sanctioned if built wrong.
|
||||
9. **Prior-judgment interpretation** — extract structured facts from an existing
|
||||
order, summarize it plainly, and **flag** legal-interpretation questions **without
|
||||
ruling** on them. Central to the modification/enforcement work this practice
|
||||
focuses on.
|
||||
|
||||
### Tier 4 — The output & the loop (close it safely) — *the machinery that makes all the above defensible*
|
||||
10. **Attorney review & approval workflow** — the GATE made into a workflow:
|
||||
assembled package → attorney reads, verifies, edits, signs → only then does
|
||||
anything move. **Non-negotiable; the capability that makes every other one safe.**
|
||||
11. **E-signature & filing preparation** — client-facing docs via DocuSeal; court
|
||||
filings prepared for `/s/` + Portal upload (prepare-and-upload). The last mile
|
||||
from approved draft to going out.
|
||||
12. **Audit trail** — every fact, AI action, citation verification status, and
|
||||
approval reconstructable. Protects the attorney and the practice when anyone asks
|
||||
"who did what, and was it checked."
|
||||
13. **Communications drafting** — plain-language, attorney-reviewed client updates;
|
||||
never auto-sends. Keeps clients informed without the attorney writing every email.
|
||||
14. **Nonlawyer supervision & access control** — the operator is a *low-legal-knowledge
|
||||
staffer handling privileged client data*, which triggers the attorney's duty to
|
||||
supervise nonlawyer assistants (Bar Rule 4-5.3). So: **matter-scoped access**
|
||||
(staff see only their assigned matters, not the whole client base), a nonlawyer-
|
||||
conduct acknowledgment, and the hard principle that **staff capture and assemble
|
||||
but never communicate legal positions to a client** (extends "never advises" from
|
||||
the AI to the human operator). This is a confidentiality + ethics requirement, not
|
||||
a nicety.
|
||||
15. **Data retention & destruction** — Florida imposes file-retention obligations, and
|
||||
"keep everything forever in an audit log" is itself a liability (more data = more
|
||||
breach surface; some data shouldn't be kept indefinitely). So: **attorney-configured
|
||||
retention classes**, a defined **closed-matter lifecycle** (retain → eligible for
|
||||
destruction → destroyed, with the action logged), and **client-file return at
|
||||
matter close**. The audit trail (12) records *that* destruction happened without
|
||||
retaining the destroyed content.
|
||||
|
||||
### Deliberately EXCLUDED (these cross from *assist* into *judge* → UPL/liability)
|
||||
- **Outcome / success-percentage prediction** — NO "% chance of winning" on any path,
|
||||
graph, or report. There is no honest dataset of comparable Miami-Dade family-law
|
||||
outcomes (cases are sealed, settlements private, "success" isn't binary), so any
|
||||
percentage is **fabricated precision**; it is functionally the legal *opinion* only a
|
||||
licensed attorney may give; it becomes evidence if a case loses; and it anchors the
|
||||
attorney into shallow review. **What IS allowed (capability 6): a strength-of-support
|
||||
decision graph** that compares which path the *facts on hand* best support — present/
|
||||
missing factors, requirements, effort, risks — leaving the probability judgment to the
|
||||
attorney. The distinction is load-bearing: "72% likely to win" = excluded;
|
||||
"threshold met, 4 of 5 supporting elements documented" = allowed.
|
||||
- **Evidence admissibility rulings** — admissibility is a contextual legal ruling.
|
||||
The software surfaces an evidence **completeness checklist** ("missing the
|
||||
foundation for exhibit C"); it does **not** rule the exhibit admissible.
|
||||
|
||||
**Build order implication:** Tiers 1, 2, and 4 are safe to build now (no legal
|
||||
judgment — data, assembly, deterministic rules, safety machinery). **Tier 3 is gated
|
||||
behind attorney validation of the underlying legal logic** (the requirements/
|
||||
elicitation content is the artifact to put in front of a Florida attorney). Build
|
||||
Tiers 1/2/4 first and gate Tier 3 → genuinely useful product quickly, on the right
|
||||
side of the line. This maps onto §7: capabilities 1–7 and 10–15 ride Steps 1–14
|
||||
(conflict screening 3 → Step 2; supervision/access 14 → Steps 2–3; retention 15 →
|
||||
Step 12); capabilities 8–9 are the Tier-3 pieces (Steps 6, 7, 9) the attorney
|
||||
questionnaire validates.
|
||||
|
||||
---
|
||||
|
||||
## 3. Architecture (decided)
|
||||
|
||||
- **Odoo 18 Community is the spine:** system of record, workflow/state machines,
|
||||
RBAC, audit (`mail.thread`), deadlines (`ir.cron` + `base.automation`), documents,
|
||||
calendar, UI. ~70% of needs are Odoo plumbing — **do not rebuild from scratch.**
|
||||
- **AI = Odoo's own HTTPS call to the Claude API** at `api.anthropic.com/v1/messages`.
|
||||
- **No Odoo "AI" feature is used** — Odoo Community has none; this is a plain
|
||||
outbound HTTP call from our module.
|
||||
- API key in `ir.config_parameter` (encrypted, attorney-group readable only).
|
||||
- Model **pinned in config** (`familylaw.model`), recorded per task for audit.
|
||||
- Calls run **async via `queue_job`** (OCA) so they never block the web worker.
|
||||
- **Provider is pluggable.** Local **Ollama** is a *future* routing option, not
|
||||
wired now. Build `_route_model()` so flipping high-confidentiality work to local
|
||||
is a **config change, not a redesign**.
|
||||
- **Trust/billing reconciliation NEVER reaches any model** — the routing layer
|
||||
raises before any such call. (IOTA, Bar Rule 5-1.1 — human-only.)
|
||||
- **One external service:** an optional **FastAPI orchestrator** for the multi-step
|
||||
**research loop** (search → propose citations → verify each → synthesize). Mirrors
|
||||
the owner's existing `odoo-ai` pattern. Single-shot AI tasks (drafting, summaries,
|
||||
extraction) run **from Odoo directly**; only the agentic research chain goes
|
||||
external. Running even that as sequenced `queue_job` steps inside Odoo is an
|
||||
acceptable alternative — complexity-vs-consolidation call, not correctness.
|
||||
- **Satellites:**
|
||||
- **DocuSeal** — self-hosted e-signature for *client-facing* docs (court filings use
|
||||
the `/s/` convention via the FL E-Filing Portal, **NOT** DocuSeal). **Two material
|
||||
caveats (do not bury these):** (1) the **API/embedding needed for the Odoo
|
||||
integration requires DocuSeal *Pro* (~$200/yr / ~$20-per-user-mo)** — the free tier
|
||||
does core signing but not the programmatic integration; (2) the **DocuSeal signing
|
||||
host must be internet-facing**, unlike the rest of the NetBird-internal,
|
||||
privacy-first stack — so it must be **isolated and hardened** (its Postgres not
|
||||
exposed, audit trail backed up). For a HIPAA-adjacent operator these are design
|
||||
facts, not footnotes.
|
||||
- **MinIO or Synology NAS** — file archive behind `ir.attachment`.
|
||||
- **CourtListener** — citation verification. **It is a single point of failure for
|
||||
the citation gate (capability 8 — the thing that prevents sanctions), so:**
|
||||
(1) **fail CLOSED** — if CourtListener is down, rate-limited, or has no record for a
|
||||
cite, the citation **stays `unverified` and remains blocked**; the system NEVER
|
||||
"assumes good" or waves anything through on a verification failure; (2) define at
|
||||
least **one fallback source** (e.g. Google Scholar / a secondary API) before relying
|
||||
solely on it; (3) **confirm Florida appellate (DCA + Supreme Court) coverage is
|
||||
adequate BEFORE building on it** — verify the tool actually works for FL family-law
|
||||
authority, don't assume.
|
||||
- **AI cost & latency (model this from day one):** a fully-assembled matter can mean
|
||||
*many* calls (drafting + research + per-citation verification), so a research loop can
|
||||
run minutes and cost real money per case. Set a **per-task token ceiling**, and
|
||||
**record token cost + latency on each `ai.task`** so the economics are measurable and
|
||||
capped, not discovered later. Budget the cost-per-assembled-case explicitly.
|
||||
- **Court e-filing reality:** the FL Courts E-Filing Portal has **no public push
|
||||
API**. The model is **prepare-and-upload**: software prepares, attorney signs
|
||||
`/s/`, a human uploads through the Portal, confirmation recorded back in Odoo.
|
||||
|
||||
### Tech/environment notes
|
||||
- **Odoo 18 view syntax:** use `<list>` (NOT `<tree>` — removed in 18). `attrs=`
|
||||
and `states=` are **removed**; use direct attributes (`invisible="..."`,
|
||||
`readonly="..."`, `required="..."`). Chatter: explicit `oe_chatter` div used for
|
||||
cross-release safety (v18 also supports the `<chatter/>` shorthand).
|
||||
- Owner runs Odoo 18 in production (Docker/Proxmox stack, Postgres, Traefik,
|
||||
NetBird). The orchestrator/Ollama/GPU box already exist.
|
||||
- **Verify volatile legal facts at build time.** Florida renumbers forms and amends
|
||||
rules/statutes regularly (e.g., the 2023 alimony overhaul removed permanent
|
||||
alimony; Rule 12.410 subpoena amendment effective Oct 1 2025). Never bake a
|
||||
specific statute version into code as if permanent; keep "verify current rule"
|
||||
in the flow.
|
||||
|
||||
---
|
||||
|
||||
## 4. Decisions locked (apply these — do not re-litigate)
|
||||
|
||||
| Decision | **Choice** | Consequence for the build |
|
||||
|---|---|---|
|
||||
| **Intake front door** | **Intake creates a draft case directly** | The intake questionnaire fills a `familylaw.case` that starts in `intake` state. No separate lead/convert step. |
|
||||
| **Case creation strictness** | **Conditional: strict for standard intake, FAST-PATH for emergencies** | Standard intake = **strict** (require matter name, client, case type, county/court + triage essentials before the draft case commits — the friction is fine and keeps data clean). **Emergency intake = fast-path:** if the urgency screen trips (child withheld / removal threat / violence), creation requires only the bare minimum to act (who, which child, what's happening) and **defers** the rest. Rationale: in a genuine emergency the procedural clock and the child's safety beat data completeness; a bare "strict" rule would block opening the matter exactly when speed matters most. The urgency screen runs first, so it gates which creation path applies. |
|
||||
| **Modification: how Case A is handled** | **One continuous case; each new proceeding is a child `familylaw.proceeding`** | A modification/enforcement **reopens the same `familylaw.case`** (continuity, full history in one place) **BUT** spawns a new **`familylaw.proceeding`** record under it. **Deadlines, documents, and proceeding-state attach to the PROCEEDING, not the case.** This resolves the flaw in a bare "reopen": without it, the deadline engine can't tell the 2024 dissolution's disclosure clock from a 2027 modification's, and documents/audit from distinct legal proceedings pile together. The case is the client-matter spine; the proceeding is the unit of legal action. (Reconciles with doc 03's parent/child structure — same idea, named `proceeding`.) |
|
||||
| **"Interpret the prior judgment"** | **Extraction + plain summary + legal interpretation (flagged, not concluded)** | The AI extracts structured facts, writes a plain-language summary, **and** may surface legal interpretation of provisions — but interpretation is **flagged for the attorney, never stated as a conclusion/ruling.** Born as draft; attorney decides. |
|
||||
|
||||
Other standing choices from design: **native Odoo models** for the questionnaire
|
||||
(NOT the Survey app) — answers must land as typed case data the workflow can use,
|
||||
with no survey→case mapping layer. Markdown for docs; module version-controlled in
|
||||
Gitea by the owner.
|
||||
|
||||
---
|
||||
|
||||
## 5. The build method — VERIFIABLE STEPS (follow strictly)
|
||||
|
||||
Build in small, independently verifiable slices. **Do not start step N+1 until step
|
||||
N's tests are green and its walkthrough passes.** Every step delivers, in order:
|
||||
|
||||
1. **Installable code** — installs/upgrades cleanly (`-u activeblue_familylaw`).
|
||||
2. **A walkthrough** — a UI click-path that shows the new behaviour end to end.
|
||||
3. **Tagged unit tests** — under `tests/`, tagged `familylaw_step<N>`, proving the
|
||||
step's guarantees (especially the gates).
|
||||
4. **Done-when** — explicit pass condition: green tests + clean walkthrough → ship,
|
||||
then advance.
|
||||
|
||||
### Test harness
|
||||
- Tests subclass `TransactionCase` (savepoint rollback; DB stays clean).
|
||||
- Tag: `@tagged("post_install", "-at_install", "familylaw", "familylaw_step<N>")`.
|
||||
- Group-gated actions: `new_test_user(..., groups="base.group_user,activeblue_familylaw.group_familylaw_attorney")`; call with `.with_user(attorney)` / `.with_user(paralegal)`.
|
||||
- **External APIs are ALWAYS mocked** (`unittest.mock.patch`) — Claude, DocuSeal,
|
||||
CourtListener. Tests must never hit the network. Assert on what got written to
|
||||
Odoo (e.g. "document born `ai_draft`", "citation born `unverified`").
|
||||
- **Date math tested with fixed dates**, never `today()`, for determinism.
|
||||
|
||||
Run all: `odoo -d <db> -i activeblue_familylaw --test-enable --stop-after-init`
|
||||
Run one step: `odoo -d <db> -u activeblue_familylaw --test-enable --test-tags familylaw_step1 --stop-after-init`
|
||||
|
||||
---
|
||||
|
||||
## 6. What's already built — STEP 1 ✅ (delivered, validated)
|
||||
|
||||
Module: `activeblue_familylaw` (in the Step 1 zip; layout below).
|
||||
|
||||
**`familylaw.case`** — the matter spine:
|
||||
- Identity: `name`, `client_id` (res.partner), `case_type` (selection: dissolution
|
||||
w/ & w/o children, paternity, support/parenting/alimony modification, enforcement,
|
||||
DV injunction, other).
|
||||
- Team: `attorney_id`, `paralegal_id` (res.users).
|
||||
- **`representation`** (attorney / pro_se) — drives the Step 8 subpoena branch.
|
||||
- **`conflict_check_cleared`** (attorney-only gate, readonly, tracked).
|
||||
- **`state`** lifecycle: `intake → engaged → disclosure → discovery → mediation →
|
||||
hearing → closed`, with **guarded transitions** (each checks current state, rejects
|
||||
illegal jumps) and **attorney-only** actions (`action_mark_conflict_cleared`,
|
||||
`action_close`, `action_reopen`) enforced in **Python AND** via `groups=` on buttons.
|
||||
- `mail.thread` / `mail.activity.mixin` — every transition + clearance posts to the
|
||||
chatter (the audit trail).
|
||||
|
||||
**Security:** groups `group_familylaw_user` (Staff) and `group_familylaw_attorney`
|
||||
(Attorney, implies Staff implies internal). Access rules: staff can't delete; attorney can.
|
||||
|
||||
**Views:** list (`<list>`), form (statusbar + transition buttons + chatter), search
|
||||
(filters: My Cases, Open, Awaiting Conflict Clearance; group-by: stage/attorney/type).
|
||||
**Menu:** Family Law → Cases (+ Configuration placeholder).
|
||||
|
||||
**Tests (`tests/test_case_lifecycle.py`, tag `familylaw_step1`):** 10 tests — initial
|
||||
state, conflict-clearance gate (engage blocked until cleared; only attorney clears),
|
||||
illegal-transition rejection, full forward path, attorney-only close/reopen, audit
|
||||
logging. Statically validated: Python compiles, XML well-formed, manifest is a dict,
|
||||
every button maps to a method, every view field exists on the model, zero
|
||||
Odoo-18-forbidden constructs.
|
||||
|
||||
### Module layout
|
||||
```
|
||||
activeblue_familylaw/
|
||||
__init__.py
|
||||
__manifest__.py # depends: base, mail
|
||||
models/
|
||||
__init__.py
|
||||
familylaw_case.py # the spine + state machine + gates
|
||||
security/
|
||||
familylaw_security.xml # groups + module category
|
||||
ir.model.access.csv # staff (no unlink) / attorney (full)
|
||||
views/
|
||||
familylaw_case_views.xml # list, form, search, action
|
||||
familylaw_menus.xml # app menu
|
||||
tests/
|
||||
__init__.py
|
||||
test_case_lifecycle.py # familylaw_step1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. The step sequence (roadmap)
|
||||
|
||||
| Step | Slice | Key models / files | Proves (tests) | Doc |
|
||||
|---|---|---|---|---|
|
||||
| **1 ✅** | Case spine + lifecycle + attorney gates | `familylaw.case`, security, views | transitions, conflict gate, attorney-only, audit | 02,03 |
|
||||
| **2 → NEXT** | **Parties, children, issues + `proceeding` + conflict screening + `case_number` + search + intake questionnaire** | `familylaw.party`, `.child`, `.issue`, **`familylaw.proceeding`**; indexed `case_number`; conflict-search method; intake wizard | relations, DOB constraints, **find by party/child/case number**, **conflict search surfaces a past-client opposing party**, questionnaire creates draft case (strict) / emergency fast-path, urgency flag raised, "good case?" captured not answered | 02,03 |
|
||||
| 3 | **Documents + the review gate** | `familylaw.document` (`ai_draft→attorney_review→approved`), attached to a **proceeding** | only attorney approves; can't file/send unapproved (GATE 1) | 03,04 |
|
||||
| 4 | Deadline engine | `familylaw.deadline` (**FK to `proceeding`, not case**) + `base.automation` + `ir.cron` + `calendar.event` mirror | 20/45/30-day math, weekend roll, overdue, **deadlines isolated per proceeding** | 02,11 |
|
||||
| 5 | Mandatory disclosure (Rule 12.285) | `disclosure.item`, `financial.affidavit`, `fin.line` (per proceeding) | 12.902(b) vs (c) by income, 45-day due, can't-waive | 02,11 |
|
||||
| 6 | **Claude client + `ai.task` ledger** (single-shot) | `familylaw.ai.client`, `ai.task` (**logs model + token cost + latency**), drafting agent, `queue_job` | (mocked) doc born `ai_draft`, task logged w/ cost, cites born `unverified` | 04,09 |
|
||||
| 7 | **Citation ledger + filing gate** + research loop | `familylaw.citation`, `action_request_filing`, FastAPI orchestrator; **fail-closed verification + fallback source** | filing blocked on any unverified cite (GATE 2); verification failure keeps cite blocked | 06 |
|
||||
| 8 | **Discovery + subpoena** (12.351 gate + pro-se/attorney branch) | `discovery.request`, objection-window gate | objection-window hard gate, same-day Notice of Issuance, clerk-vs-attorney routing | 11 A.6,C |
|
||||
| 9 | **Child-support modification** workflow (end to end) | wires 1–8 for `support_modification`; **new `proceeding` under the reopened case** | 15%/$50 threshold, 20-day answer, DOR-case flag, retroactivity note, **prior-judgment extraction+summary+flagged interpretation** | 11 B.2 |
|
||||
| 10 | **Emergency** workflow (12.941 pick-up/removal) | emergency motion records + required-attachment checks; **uses the intake fast-path** | have-order-vs-not fork; missing-attachment block; fast-path opens matter on minimum facts | 11 B.1 |
|
||||
| 11 | DocuSeal e-signature | `action_send_for_signature`, webhook controller (**Pro tier; isolated internet-facing host**) | (mocked) only `approved` sends; webhook → `signed` | 05 |
|
||||
| 12 | File archive + calendar layers + **retention lifecycle** | `ir.attachment` + `familylaw.archive` metadata; calendar categories; retention classes + closed-matter destruction | SHA-256 checksum, **retention class drives destruction-eligibility**, client-file-return at close, **per-layer filter toggles** | new |
|
||||
| 13 | Miami-Dade auto-seed (AO 14-13) | Status Quo Order, parenting-course + mediation obligations on case open | obligations seed on open; course-before-judgment guard | 11 D |
|
||||
| 14 | Comms agent + AI-assisted billing flag + hardening + **matter-scoped access** | `comms` drafts, `time.entry.ai_assisted`, record rules scoping staff to assigned matters, encryption/backup | (mocked) comms never auto-sends; AI ratio reportable; **staff can't see unassigned matters** | 04,08 |
|
||||
|
||||
**Intake questionnaire** (native models; intake-creates-draft-case; **conditional
|
||||
strictness — strict for standard, fast-path for emergencies**) is the high-leverage
|
||||
elicitation layer. It belongs with **Step 2** (it needs the party/child fields) and is
|
||||
built **triage section + ONE case-type branch (child-support modification first)**,
|
||||
then more branches added incrementally. The triage **urgency screen runs FIRST** and
|
||||
selects strict vs. fast-path creation. It captures facts only — it **never answers**
|
||||
"do I have a good case?" (logs that as a question for the attorney).
|
||||
|
||||
**MVP to run a solo practice:** Steps 1–6 + 8 + 11, then add 7. Steps 9/10 are the
|
||||
headline workflows; 12–14 round it out.
|
||||
|
||||
---
|
||||
|
||||
## 8. STEP 2 — the immediate task (build this next)
|
||||
|
||||
**Goal:** the related records that make a matter real, the **proceeding** layer that
|
||||
keeps modifications/enforcements cleanly separated, **automated conflict screening**,
|
||||
search the way a practice actually searches (by people + court case number), and the
|
||||
intake questionnaire front door (conditional strict / emergency fast-path).
|
||||
|
||||
**Build:**
|
||||
1. **`familylaw.party`** — a party to the matter (`res.partner` + role: client /
|
||||
opposing party / opposing counsel / other). Opposing-party capture feeds conflict
|
||||
screening (#6).
|
||||
2. **`familylaw.child`** — a minor child (name, DOB **with validation: reject future
|
||||
or implausible dates**, link to case); searchable.
|
||||
3. **`familylaw.issue`** — a contested issue (time-sharing, support, equitable
|
||||
distribution, alimony, etc.) — the spine for later requirements scoring.
|
||||
4. **`familylaw.proceeding`** — **the unit of legal action under a case.** A case can
|
||||
have many proceedings over time (original dissolution, later modification, later
|
||||
enforcement). Fields: `case_id` (FK), `proceeding_type`, `state` (its own
|
||||
lifecycle), open/close dates. **From here on, deadlines and documents attach to a
|
||||
proceeding, not directly to the case** (Steps 3–5 build on this). On case creation,
|
||||
open an initial proceeding for the originating matter.
|
||||
5. **`case_number`** on `familylaw.case` — court-assigned (e.g. 2024-DR-001234),
|
||||
**indexed + searchable**. (A proceeding may also carry its own number if the court
|
||||
assigns one.)
|
||||
6. **Automated conflict screening** — a method that, given the captured opposing
|
||||
party, **searches `familylaw.party` across ALL cases** and returns potential
|
||||
conflicts (opposing party matches a past/current client; or is already an opposing
|
||||
party elsewhere). Surface the hits **on the case for the attorney to clear** — it
|
||||
does **not** auto-clear or auto-block; the Step 1 `conflict_check_cleared` attorney
|
||||
gate remains the decision point. (Name-match can be fuzzy; flag for human review,
|
||||
never auto-resolve.)
|
||||
7. **Search-by-person / by-number:** extend case search so a matter is findable by
|
||||
party name, child name, and `case_number` — not just title/client.
|
||||
8. **Intake questionnaire (native; creates draft case; conditional strictness):** a
|
||||
guided multi-step flow that (a) runs **triage FIRST** (caller + contact, opposing
|
||||
party, minor children y/n, county/court, existing case/order, **urgency screen:
|
||||
child withheld / removal threat / violence**), (b) **branches on urgency**:
|
||||
*standard* → strict (require name, client, case type, county + triage essentials
|
||||
before commit); *emergency* → **fast-path** (commit on minimum facts: who, which
|
||||
child, what's happening; defer the rest), (c) branches into the **child-support
|
||||
modification** question set, and (d) on completion **creates a draft
|
||||
`familylaw.case` in `intake` state** (and its initial proceeding). Runs conflict
|
||||
screening (#6) as part of completion. Collects facts only.
|
||||
|
||||
**Tests (`familylaw_step2`):** relation integrity (party/child/issue/proceeding ↔
|
||||
case); DOB constraint rejects future/implausible dates; **find case by party name /
|
||||
child name / case_number** returns the right matter; **conflict screening surfaces a
|
||||
past-client opposing party** and does NOT auto-clear; a case can hold **multiple
|
||||
proceedings** and each carries its own state; questionnaire triage sets case type;
|
||||
**standard path enforces strict creation** (rejects incomplete submission);
|
||||
**emergency path commits on minimum facts** and raises the urgency flag; "do I have a
|
||||
good case?" is **captured as an attorney question, never answered**.
|
||||
|
||||
**Constraints:** Odoo 18 syntax (`<list>`, direct attributes — no `<tree>`, no
|
||||
`attrs`/`states`). **No external/network calls in Step 2** (questionnaire is pure data
|
||||
capture; AI extraction of an uploaded judgment is Step 6+; conflict screening is a
|
||||
local DB search, not an AI call). Keep the gate philosophy intact — nothing here
|
||||
advises, decides, or auto-clears a conflict.
|
||||
|
||||
**Done-when:** `familylaw_step2` tests green + a walkthrough where you (a) complete a
|
||||
*standard* modification intake and land on a new draft case with an initial
|
||||
proceeding; (b) complete an *emergency* intake and get a matter opened on minimum
|
||||
facts with the urgency flag set; (c) see a conflict flag when the opposing party
|
||||
matches an existing client; and (d) find an existing case by opposing-party name, by
|
||||
child name, and by case number.
|
||||
|
||||
---
|
||||
|
||||
## 9. Working agreements for Claude Code
|
||||
|
||||
- **Read the relevant design doc (`00`–`11`) before each step**; this file says
|
||||
*what/next*, the docs say *why/detail*.
|
||||
- **One verifiable step at a time.** Don't scaffold ahead. Deliver code + tests +
|
||||
walkthrough, stop, confirm green, then continue.
|
||||
- **The two gates are sacred.** Never add a code path that lets AI output be
|
||||
filed/sent/signed without attorney approval, or lets an unverified citation into a
|
||||
filing. If a request would breach this, flag it instead of building it.
|
||||
- **Mock all external APIs in tests.** Never hit Claude/DocuSeal/CourtListener from a
|
||||
test.
|
||||
- **Verify volatile legal facts** (forms, rules, statutes) against current sources at
|
||||
build time; keep "verify current rule" in the flow rather than hardcoding a version
|
||||
as permanent.
|
||||
- **Owner profile:** experienced infra/dev (Proxmox, Docker, Postgres, Python,
|
||||
Odoo 18 in prod). Be direct and technical; prefer CLI; the owner version-controls
|
||||
in Gitea. Plan fully, validate each stage.
|
||||
- **This is not legal advice** and the platform must not practice law; a licensed
|
||||
attorney reviews, verifies, and signs all output.
|
||||
|
||||
---
|
||||
|
||||
## 10. Design-revision changelog (audit fixes applied to this revision)
|
||||
|
||||
Nine flaws were found in a critical design review and fixed in this document:
|
||||
|
||||
1. **Training-data flywheel → safe improvement loop (§1).** The "attorney corrections
|
||||
become training data" claim risked leaking privileged client data (Rule 4-1.6) and
|
||||
assumed nonexistent fine-tuning infra. Replaced with prompt/example refinement +
|
||||
regression evals as the default; fine-tuning is future/gated on a de-identified,
|
||||
consented, separate corpus.
|
||||
2. **Bare "reopen" → `familylaw.proceeding` model (§4, §7, §8).** Reopening one case
|
||||
repeatedly would conflate deadlines/documents/audit across distinct legal
|
||||
proceedings and contradicted doc 03. Now: one continuous case, each
|
||||
modification/enforcement is a child proceeding that owns its own deadlines/docs/state.
|
||||
3. **Conflict checkbox → automated conflict screening (capability 3, Step 2).** A human
|
||||
ticking a box misses structural conflicts across many matters. Added a DB-wide
|
||||
party search that surfaces conflicts for the attorney to clear (attorney still decides).
|
||||
4. **Strict creation vs. emergencies → conditional strictness (§4, Step 2/10).** Strict
|
||||
field requirements would block opening a genuine emergency matter. Now strict for
|
||||
standard intake, fast-path (minimum facts) when the urgency screen trips.
|
||||
5. **AI cost/latency unmodeled → budgeted (§3, Step 6).** Added per-task token ceiling
|
||||
and cost+latency logging on `ai.task`; budget cost-per-assembled-case explicitly.
|
||||
6. **CourtListener single point of failure → fail-closed + fallback + FL-coverage check
|
||||
(§3, Step 7).** Verification failure now keeps a cite blocked (never "assume good"),
|
||||
a fallback source is required, and Florida appellate coverage must be confirmed first.
|
||||
7. **Non-lawyer operator confidentiality → supervision + matter-scoped access
|
||||
(capability 14, Step 14).** Added Rule 4-5.3 supervision layer, matter-scoped record
|
||||
rules, and the principle that staff never communicate legal positions to clients.
|
||||
8. **DocuSeal caveats restored (§3, Step 11).** Surfaced the Pro-tier cost (~$200/yr for
|
||||
the API) and the internet-facing/isolated-host requirement at the architecture level.
|
||||
9. **No retention policy → retention & destruction capability (capability 15, Step 12).**
|
||||
Added attorney-configured retention classes, a closed-matter destruction lifecycle,
|
||||
and client-file return at close (audit logs *that* destruction occurred, not the content).
|
||||
|
||||
**Note:** none of these were defects in the delivered Step 1 *code* — they were in the
|
||||
surrounding design. Step 1 remains valid. The structural change that most affects
|
||||
forthcoming work is the `familylaw.proceeding` model (fix 2), which Step 2 introduces
|
||||
and Steps 3–5 build on.
|
||||
|
||||
**Later additions (this revision):**
|
||||
10. **Strength-of-support decision graph, NOT a success-percentage predictor
|
||||
(capability 6, EXCLUDED).** A requested "% chance of success per path" was declined
|
||||
as fabricated precision / functional legal opinion / liability, and replaced with a
|
||||
factual path-comparison graph (present-missing factors, requirements, effort, risks)
|
||||
that leaves the probability judgment to the attorney.
|
||||
11. **Claude's role clarified as the quality-elevation layer (§1)** and a new **§11
|
||||
"Requirements for Success"** added — the non-code gaps (engaged licensed attorney,
|
||||
practice-ownership model, malpractice insurance, engagement-letter AI clause,
|
||||
security/breach plan, operator UPL guardrails, content-maintenance process, the
|
||||
elicitation content, FL-proven citation source, eval/QA, cost model). #1 (attorney)
|
||||
and #2 (ownership) gate the venture; both are non-coding and run parallel to Steps 2–5.
|
||||
|
||||
---
|
||||
|
||||
## 11. Requirements for SUCCESS (non-code gaps that must be closed)
|
||||
|
||||
The 15 capabilities make the software *function*. These items make the venture
|
||||
*succeed and stay legal*. Several are **launch-blockers**, not enhancements. They are
|
||||
not optional, and most cannot be solved by writing code.
|
||||
|
||||
### Critical — blocks the whole model
|
||||
1. **A named, engaged, licensed Florida family-law attorney — NOW, not at launch.**
|
||||
The entire architecture routes assembled cases to a reviewing/signing attorney; with
|
||||
no such attorney, there is no one to hand the case to and the product cannot legally
|
||||
operate. This attorney must (a) **validate the legal logic** in docs 02/11 (forms,
|
||||
deadlines, avenues, 11th-Circuit specifics), (b) be the **actual reviewing/signing
|
||||
attorney**, and (c) **own the malpractice and Bar exposure**. *First concrete step:
|
||||
the attorney-review questionnaire (below) — it turns the researched-but-unvalidated
|
||||
legal logic into something a Florida attorney can confirm and sign off.*
|
||||
2. **Settle "whose practice is this?" (ownership / business model).** Florida prohibits
|
||||
nonlawyer ownership of law firms and fee-splitting with nonlawyers. Clean model:
|
||||
**Active Blue builds/operates the software; a licensed firm uses it.** Problematic
|
||||
model: **Active Blue runs the practice** — no code fixes that. Resolve before
|
||||
building the Tier-3 legal-reasoning pieces, because the answer shapes how they're
|
||||
built and who the "attorney" in the workflow legally is.
|
||||
|
||||
### Launch-blockers — required before a single real client matter
|
||||
3. **Malpractice insurance that contemplates AI-assisted work**, carried by the
|
||||
responsible attorney/firm.
|
||||
4. **Engagement-letter framework with an AI-disclosure clause** — the client is told AI
|
||||
assists their matter and a licensed attorney reviews and is responsible.
|
||||
5. **Security review + breach-response plan for privileged data.** The privacy-first
|
||||
stack is a head start, but privileged legal data + a non-lawyer operator + an
|
||||
internet-facing DocuSeal host needs an actual review, encryption-at-rest for case
|
||||
data, and an incident plan — not just good instincts.
|
||||
6. **UPL guardrails for the human operator** (pairs with capability 14): the non-lawyer
|
||||
never communicates legal positions/opinions to clients; all legal questions route to
|
||||
the attorney; this is trained and enforced, not assumed.
|
||||
|
||||
### Ongoing — required to stay correct over time
|
||||
7. **A legal-content maintenance process.** Florida changed alimony (2023) and subpoena
|
||||
rules (2025); forms get renumbered. Someone must **watch for rule/form/statute
|
||||
changes and update the logic** on a schedule. A case built on a repealed form is a
|
||||
malpractice event. "Verify current rule" handles point-in-time; this handles drift.
|
||||
8. **The requirements/elicitation content itself** (unblocks capabilities 7 & 8). The
|
||||
per-case-type definition of "what a complete, winnable file requires" — elements,
|
||||
proof, forms, the strength factors the decision graph reads — **does not exist yet**.
|
||||
This is the artifact the attorney validates and the engine consumes; without it,
|
||||
completeness-scoring and research have nothing authoritative to check against.
|
||||
9. **A citation-verification source proven for Florida** (pairs with §3 architecture):
|
||||
confirm CourtListener (+ fallback) actually covers FL DCA + Supreme Court family-law
|
||||
authority adequately before relying on the citation gate in production.
|
||||
10. **A real evaluation/QA process before anything is client-facing.** The regression
|
||||
eval suite (doc 09 §9) wired to run before every prompt/model change; a defined bar
|
||||
the assembled output must clear; attorney spot-audits of approved work.
|
||||
|
||||
### Strongly recommended — for the product to actually deliver its promise
|
||||
11. **Cost-per-assembled-case model** (pairs with §3 / Step 6): know the token cost and
|
||||
latency of a full matter so pricing and the economics hold; cap per-task spend.
|
||||
12. **Client intake/consent for AI involvement** captured in the record (distinct from
|
||||
the engagement letter): the client's informed acknowledgment, logged.
|
||||
13. **A "human-in-the-loop won't be skipped" enforcement audit**: periodic proof that no
|
||||
code path and no operator habit lets unreviewed/unsigned work reach a client, clerk,
|
||||
or court — the two gates verified in practice, not just in tests.
|
||||
|
||||
**Bottom line:** of everything above, **#1 (the attorney) and #2 (the ownership model)
|
||||
gate the venture** — neither is a coding task, both should be moving in parallel with
|
||||
Steps 2–5, and #1 starts with the attorney-review questionnaire. The software can be
|
||||
~80–90% built and validated and still cannot run a real matter until #1–#6 are closed.
|
||||
60
START_HERE.md
Normal file
60
START_HERE.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# START HERE — Claude Code kickoff
|
||||
|
||||
You are picking up an in-progress build. Read in this order, then start the task at
|
||||
the bottom. Do **not** re-derive the design — it exists; follow it.
|
||||
|
||||
## Read order (do this first)
|
||||
1. **`CLAUDE.md`** — the operational brief and single source of truth. Read it fully.
|
||||
Pay special attention to:
|
||||
- §1 — the governing rule + the two gates + Claude's role as the quality-elevation layer.
|
||||
- §2 — the 15 capabilities, grouped by RISK (what's safe now vs. attorney-gated).
|
||||
- §4 — locked decisions (apply them; do not re-litigate).
|
||||
- §5 — the verifiable-step method + the test harness rules.
|
||||
- §8 — **STEP 2, your immediate task.**
|
||||
- §10 — the audit fixes already applied (esp. fix 2, the `familylaw.proceeding` model).
|
||||
- §11 — the non-code success gaps (context for why some steps are gated).
|
||||
2. **`BUILD_PLAN.md`** — the step contract and the run/test commands.
|
||||
3. **The design docs `00`–`11`** (in the separate design package) — *why/detail* behind
|
||||
each step. Read the relevant doc(s) before each step, not all at once. For Step 2:
|
||||
docs 02 (domain) and 03 (data model).
|
||||
|
||||
## Current state
|
||||
- **Step 1 is DONE and validated** — `activeblue_familylaw` module: the `familylaw.case`
|
||||
spine, the lifecycle state machine, attorney-only gates, security groups, views,
|
||||
and 10 passing tests (tag `familylaw_step1`). Module layout is in `CLAUDE.md §6`.
|
||||
- The code is Odoo 18 (uses `<list>` not `<tree>`; direct attributes, no `attrs`/`states`).
|
||||
- Nothing else is built yet. Steps 2–14 are designed, not implemented.
|
||||
|
||||
## Hard rules (from CLAUDE.md — do not violate)
|
||||
- **One verifiable step at a time.** Don't scaffold ahead. Each step = installable code
|
||||
+ a UI walkthrough + tagged unit tests + a done-when. Get green before advancing.
|
||||
- **The two gates are sacred:** no code path lets AI output be filed/sent/signed without
|
||||
attorney approval, or lets an unverified citation into a filing. If a request would
|
||||
breach this, flag it — don't build it.
|
||||
- **Mock all external APIs in tests** (Claude, DocuSeal, CourtListener). Never hit the
|
||||
network from a test. Test date math with fixed dates.
|
||||
- **No outcome/success-percentage prediction.** The decision graph compares strength of
|
||||
support, never a "% chance of winning" (CLAUDE.md §2 EXCLUDED).
|
||||
- **Tier 3 (capabilities 8–9, Steps 6–7–9) is gated** behind licensed-attorney
|
||||
validation of the legal logic. You may build the *structure/scaffolding* but flag that
|
||||
the legal content is unvalidated; do not present legal reasoning as authoritative.
|
||||
|
||||
## Your first task: STEP 2
|
||||
Build exactly what `CLAUDE.md §8` specifies:
|
||||
- Models: `familylaw.party`, `familylaw.child`, `familylaw.issue`, **`familylaw.proceeding`**.
|
||||
- Add indexed, searchable `case_number` to `familylaw.case`; open an initial proceeding
|
||||
on case creation.
|
||||
- **Automated conflict screening** — a local DB search over `familylaw.party` across all
|
||||
cases that surfaces potential conflicts for the attorney to clear (never auto-clears,
|
||||
never auto-blocks; the Step 1 `conflict_check_cleared` attorney gate remains).
|
||||
- Extend case search to find by party name, child name, and `case_number`.
|
||||
- **Intake questionnaire** (native models; creates a draft case): triage-first with the
|
||||
urgency screen, **conditional strictness** (standard = strict; emergency = fast-path on
|
||||
minimum facts), branching into the **child-support modification** question set, runs
|
||||
conflict screening on completion. Captures facts only — never answers "do I have a good
|
||||
case?" (logs it as an attorney question).
|
||||
- Tests tagged `familylaw_step2` covering everything in §8's test list.
|
||||
- **Done-when:** `familylaw_step2` green + the four-part walkthrough in §8.
|
||||
|
||||
Work in the module, keep Step 1's tests green, and deliver Step 2 as one reviewable,
|
||||
tested slice. Then stop and report before starting Step 3.
|
||||
@@ -0,0 +1,113 @@
|
||||
# Active Blue Family Law — Build Plan
|
||||
|
||||
**Module:** `activeblue_familylaw` (Odoo 18 Community)
|
||||
**Method:** build in small, independently **verifiable steps**. We do not start step *N+1* until step *N*'s tests are green and its walkthrough passes.
|
||||
**Companion design docs:** `00`–`11` (architecture → forms & litigation playbook).
|
||||
|
||||
---
|
||||
|
||||
## The verifiable-step contract
|
||||
|
||||
Every step delivers four things, in this order:
|
||||
|
||||
1. **Installable code** — the module installs/upgrades cleanly (`-u activeblue_familylaw`) with the step's new models, security, and views.
|
||||
2. **A walkthrough** — a short click-path you can follow in the UI to *see* the new behaviour end to end.
|
||||
3. **Tagged unit tests** — automated tests under `tests/`, tagged `familylaw_step<N>`, that prove the step's guarantees (especially the gates).
|
||||
4. **Done-when** — an explicit pass condition. Green tests + a clean walkthrough = ship; then advance.
|
||||
|
||||
Nothing that touches a real client matter ships until the two ethics gates (attorney review; verified citations) are implemented and tested — Steps 3 and 7.
|
||||
|
||||
---
|
||||
|
||||
## Test harness (how testing works here)
|
||||
|
||||
Odoo ships a `unittest`-based runner. Tests live in `activeblue_familylaw/tests/`, subclass `TransactionCase` (each test rolls back in a savepoint, so the DB stays clean), and carry tags so we can run one step at a time.
|
||||
|
||||
**Run all tests for the module (install + test):**
|
||||
```bash
|
||||
odoo -d <db> -i activeblue_familylaw --test-enable --stop-after-init
|
||||
```
|
||||
|
||||
**Run only one step's tests (against an already-installed module):**
|
||||
```bash
|
||||
odoo -d <db> -u activeblue_familylaw --test-enable --test-tags familylaw_step1 --stop-after-init
|
||||
```
|
||||
|
||||
**Conventions:**
|
||||
- Tag classes `@tagged("post_install", "-at_install", "familylaw", "familylaw_step<N>")`.
|
||||
- Use `new_test_user(..., groups="base.group_user,activeblue_familylaw.group_familylaw_attorney")` to test group-gated actions; call gated methods with `.with_user(attorney)` / `.with_user(paralegal)`.
|
||||
- **External APIs are always mocked** in unit tests — Claude (`/v1/messages`), DocuSeal, CourtListener. Tests must never hit a live network. From Step 6 we use `unittest.mock.patch` on the HTTP client method and assert on what got written to Odoo (e.g. "document born in `ai_draft`", "citation born `unverified`").
|
||||
- Date math (Step 4+) is tested with fixed dates, not `today()`, so results are deterministic.
|
||||
|
||||
---
|
||||
|
||||
## Architecture recap (so each step lands in the right place)
|
||||
|
||||
- **Odoo is the spine:** system of record, workflow/state machines, RBAC, audit (`mail.thread`), deadlines (`ir.cron` + `base.automation`), documents, calendar, UI.
|
||||
- **AI = Odoo's own HTTPS call to the Claude API** (`api.anthropic.com/v1/messages`), key in `ir.config_parameter`, model pinned in config, wrapped in `queue_job` so it runs async. *No Odoo-AI feature is used.*
|
||||
- **The one external service** is the optional FastAPI orchestrator for the multi-step **research** loop (Step 7); single-shot AI calls (drafting, summaries) run from Odoo directly.
|
||||
- **Satellites:** DocuSeal (e-signature, Step 11), MinIO/Synology (file archive, Step 12), CourtListener (citation verification, Step 7).
|
||||
- **Local Ollama** is a *later* routing option; `_route_model()` is built so flipping high-confidentiality work to local is a config change, not a redesign. Trust/billing reconciliation never reaches any model.
|
||||
|
||||
---
|
||||
|
||||
## The step sequence
|
||||
|
||||
| Step | Goal (vertical slice) | Key models / files | Proves (tests) | Design doc |
|
||||
|---|---|---|---|---|
|
||||
| **1 ✅** | **Case spine + lifecycle state machine + attorney gates** | `familylaw.case`, security groups, case views | state transitions, conflict-clearance gate, attorney-only actions, illegal-transition rejection, audit logging | 02, 03 |
|
||||
| 2 | Parties, children, issues | `familylaw.party`, `.child`, `.issue` | relations, DOB/constraint validation | 02, 03 |
|
||||
| 3 | **Documents + the review gate** | `familylaw.document` (`ai_draft→attorney_review→approved`) | only attorney approves; can't file/send unapproved (THE gate) | 03, 04 |
|
||||
| 4 | Deadline engine | `familylaw.deadline`, `base.automation`, `ir.cron`, `calendar.event` mirror | 20/45/30-day math, weekend roll, overdue detection | 02, 11 |
|
||||
| 5 | Mandatory disclosure (Rule 12.285) | `disclosure.item`, `financial.affidavit`, `fin.line` | 12.902(b) vs (c) by income, 45-day due date, can't-waive flags | 02, 11 |
|
||||
| 6 | **Claude client + `ai.task` ledger** (single-shot) | `familylaw.ai.client`, `ai.task`, drafting agent, `queue_job` | (mocked API) doc born `ai_draft`, task logged, citations born `unverified` | 04, 09 |
|
||||
| 7 | **Citation ledger + filing gate** + research loop | `familylaw.citation`, `action_request_filing`, FastAPI orchestrator | filing blocked on any unverified citation; allowed when all verified | 06 |
|
||||
| 8 | **Discovery + subpoena workflow** (12.351 gate + pro-se/attorney branch) | `discovery.request`, subpoena objection-window gate | objection-window hard gate, same-day Notice of Issuance, clerk-vs-attorney routing | 11 (A.6, C) |
|
||||
| 9 | Child-support **modification** workflow (Playbook Scenario 2, end to end) | wires Steps 1–8 for `support_modification` | 15%/$50 threshold, 20-day answer clock, DOR-case flag, retroactivity note | 11 (B.2) |
|
||||
| 10 | **Emergency** workflow (12.941 pick-up / removal — Scenario 1) | emergency motion records + required-attachment checks | the have-order-vs-not fork; missing-attachment block | 11 (B.1) |
|
||||
| 11 | DocuSeal e-signature | `action_send_for_signature`, webhook controller | (mocked) only `approved` can send; webhook flips to `signed` | 05 |
|
||||
| 12 | File archive + calendar layers | `ir.attachment` + `familylaw.archive` metadata; calendar categories | SHA-256 checksum, retention class, per-layer filtering | (new) |
|
||||
| 13 | Miami-Dade auto-seed (AO 14-13) | Status Quo Order, parenting-course + mediation obligations on case open | obligations seed on open; course-before-judgment guard | 11 (D) |
|
||||
| 14 | Comms agent + AI-assisted billing flag + hardening | `comms` drafts, `time.entry.ai_assisted`, encryption/backup pass | (mocked) comms never auto-sends; AI ratio reportable | 04, 08 |
|
||||
|
||||
**Suggested MVP to run a real solo practice:** Steps 1–6 + 8 + 11. Add 7 (research/verification) next. 9/10 are the headline workflows; 12–14 round it out.
|
||||
|
||||
---
|
||||
|
||||
## STEP 1 — delivered ✅
|
||||
|
||||
**What's in it**
|
||||
- `familylaw.case` — the matter record: identity (`name`, `client_id`, `case_type`), team (`attorney_id`, `paralegal_id`), the **`representation`** flag (attorney / pro_se — drives the Step 8 subpoena branch), the **`conflict_check_cleared`** gate, and the **`state`** lifecycle: `intake → engaged → disclosure → discovery → mediation → hearing → closed`.
|
||||
- A **guarded state machine**: each transition checks the current stage and refuses illegal jumps; `action_mark_conflict_cleared` and `action_close`/`action_reopen` are **attorney-only** (enforced in Python *and* hidden via `groups=` on the buttons).
|
||||
- Security groups **Family Law / Staff** and **Family Law / Attorney** (attorney implies staff implies internal user) + model access rules (staff can't delete; attorney can).
|
||||
- List, form (statusbar + transition buttons + audit chatter), and search views; a **Family Law** app menu.
|
||||
- `mail.thread` audit trail — every stage change and the conflict clearance post to the chatter.
|
||||
|
||||
**Install**
|
||||
```bash
|
||||
# copy the module into your addons path, then:
|
||||
odoo -d <db> -i activeblue_familylaw --stop-after-init
|
||||
# (or install "Active Blue Family Law" from the Apps menu)
|
||||
```
|
||||
|
||||
**Run Step 1 tests**
|
||||
```bash
|
||||
odoo -d <db> -i activeblue_familylaw --test-enable --test-tags familylaw_step1 --stop-after-init
|
||||
```
|
||||
Ten tests cover: initial state, the conflict-clearance gate (engage blocked until cleared; only an attorney can clear), illegal-transition rejection, the full forward path, attorney-only close/reopen, and audit logging.
|
||||
|
||||
**Walkthrough (click-path)**
|
||||
1. Family Law → Cases → **New**. Enter a matter name, pick Client A, set Case Type = *Child Support Modification*, assign yourself as attorney. Save. → it's in **Intake**.
|
||||
2. As a **staff** user, the *Clear Conflict Check* and *Close* buttons are hidden; try the flow and you can't engage yet.
|
||||
3. As an **attorney**, click **Clear Conflict Check** → the boolean ticks and a chatter note appears. Now **Engage** → stage moves to *Engaged*.
|
||||
4. Walk **Start Disclosure → Start Discovery → Start Mediation → Set for Hearing**; the statusbar advances and each change is logged.
|
||||
5. **Close Case** (attorney only) → *Closed*; **Reopen** sends it back to *Engaged*.
|
||||
|
||||
**Done-when:** the 10 tests pass and the walkthrough behaves as above. ✅ → ready for Step 2 (parties, children, issues).
|
||||
|
||||
---
|
||||
|
||||
## Notes / known-small-things
|
||||
- The form uses the explicit `oe_chatter` div for cross-release safety. Odoo 18 also supports the shorthand `<chatter/>` tag; swap if preferred.
|
||||
- An app icon can be added later at `static/description/icon.png` and referenced via `web_icon` on the root menu (left off now to keep install dependency-free).
|
||||
- Record-level isolation between attorneys (multi-attorney record rules) is intentionally deferred; Step 1 grants the two groups company-wide access. We tighten this when the data model warrants it.
|
||||
@@ -0,0 +1,598 @@
|
||||
# CLAUDE.md — Active Blue Family Law Platform
|
||||
|
||||
> **Handoff document for Claude Code.** This is the single source of truth for the
|
||||
> project: what it is, how it's architected, the decisions already made, what's been
|
||||
> built, and what to build next. Read this fully before writing code. Companion
|
||||
> design docs (`00`–`11`) live in the design package; this file is the operational
|
||||
> brief that ties them together.
|
||||
|
||||
---
|
||||
|
||||
## 1. What we're building (and the one rule that governs everything)
|
||||
|
||||
A **case-management platform for a Florida family-law practice** in **Miami-Dade
|
||||
(11th Judicial Circuit)**, built on **Odoo 18 Community**. A staff member with
|
||||
**little legal knowledge** enters case data through guided intake; the software
|
||||
**assembles the case** — manages it, attaches verified case law, tracks
|
||||
statutory/procedural requirements and evidence, and flags what's needed for
|
||||
success — and routes a **finished, draft case package to a licensed attorney who
|
||||
reads it, verifies it, and signs it.** The attorney owns the output.
|
||||
|
||||
**THE GOVERNING RULE — non-negotiable, enforced in code, not policy:**
|
||||
|
||||
> The software **builds, verifies, organizes, and flags.** A **licensed attorney
|
||||
> judges, decides, and signs.** Nothing reaches a client, a clerk, or a courtroom
|
||||
> without attorney approval. The AI is the paralegal who never sleeps — **it is not
|
||||
> the lawyer.**
|
||||
|
||||
**Claude's specific role = the quality-elevation layer.** Claude exists to produce
|
||||
*high-quality, verified, fully-assembled* work product — drafted documents, extracted
|
||||
facts, completeness-checked files, and **verified** case-law research — and **move it
|
||||
UP to the licensed attorney for sign-off**. The point of using a frontier model is the
|
||||
quality of what gets elevated: the attorney receives something strong enough to approve
|
||||
with minor edits, fast. Claude *intervenes* by supplying verified case law and the
|
||||
available next steps/avenues — **not** by deciding strategy or rendering the legal
|
||||
opinion. The intervention makes the attorney faster; it never replaces them.
|
||||
|
||||
This exists because the platform must **not** practice law. Two structural gates
|
||||
enforce it everywhere:
|
||||
1. **The review gate** — AI-produced work is born in a draft state; only a licensed
|
||||
attorney (group) can approve it; nothing can be filed/sent/signed unapproved.
|
||||
2. **The citation gate** — every case-law citation is born `unverified` and must
|
||||
pass verification (exists / on-point / good-law) against a real database before
|
||||
it can enter a filing. (Lawyers have been sanctioned for AI-hallucinated cites;
|
||||
this makes that mechanically impossible.)
|
||||
|
||||
**The product goal is a high attorney-approval rate achieved by producing genuinely
|
||||
good, complete, citation-verified work — NOT by making review shallow.** The win
|
||||
condition is "approve with minor edits, fast," like a senior partner redlining a
|
||||
strong associate draft.
|
||||
|
||||
**How the software improves over time — the SAFE loop (read this carefully).** The
|
||||
near-term improvement mechanism is **prompt and few-shot-example refinement plus the
|
||||
regression eval suite** — NOT model fine-tuning on live matters. Family-law work
|
||||
product is full of **confidential, privileged client data** (Bar Rule 4-1.6); feeding
|
||||
attorney-corrected drafts into model training risks leaking one client's information
|
||||
into another client's matter, which is far worse than any bad draft. Therefore:
|
||||
- The default loop is: attorney edits → those edits inform **curated, hand-written
|
||||
exemplars and prompt tweaks** + new regression test cases → output improves. No
|
||||
client data enters any training process by default.
|
||||
- **Fine-tuning is a FUTURE, GATED capability**, not part of this build, and only ever
|
||||
on a **de-identified, attorney-approved, consented** corpus held separately that
|
||||
**never auto-ingests live matters**. (See doc 09 §10 cautions.)
|
||||
The attorney is the quality bar and the source of curated examples — never an
|
||||
unwitting training-data faucet, and never a bottleneck to engineer around.
|
||||
|
||||
---
|
||||
|
||||
## 2. Capabilities the platform must deliver
|
||||
|
||||
Derived backward from the outcome: **a non-lawyer enters facts → a complete,
|
||||
verified, attorney-signable case package comes out, fast enough that the attorney's
|
||||
review is confirmatory, not corrective.** Every capability earns its place by serving
|
||||
that outcome. **Grouped by RISK, not feature area** — the tier tells you what's safe
|
||||
to build now vs. what needs attorney-validated legal content first.
|
||||
|
||||
### Tier 1 — The spine (capture & manage) — *safe to build now; data + deterministic rules*
|
||||
1. **Guided intake & fact capture** — the adaptive questionnaire (triage routes by
|
||||
case type; branches collect exactly the facts each matter needs, in plain
|
||||
language). **Highest-leverage capability in the system** — everything downstream
|
||||
is only as good as the facts captured here; bad capture is the #1 cause of a draft
|
||||
getting sent back.
|
||||
2. **Case management & system of record** — matter, parties, children, issues,
|
||||
**proceedings** (each modification/enforcement is a child `familylaw.proceeding`
|
||||
under the case — see §4), lifecycle state, team. The Odoo spine; the container
|
||||
everything fills.
|
||||
3. **Automated conflict-of-interest screening** — when intake captures the opposing
|
||||
party, the system **searches every party across every matter** and surfaces
|
||||
potential conflicts (opposing party was a past client; is adverse to a current
|
||||
client) **for the attorney to clear**. A human ticking a checkbox across hundreds
|
||||
of matters *will* miss structural conflicts; an undetected conflict can disqualify
|
||||
the firm and void work (Bar Rules 4-1.7/4-1.9). The software does the search a
|
||||
human can't do reliably; the **attorney still decides** (the Step 1
|
||||
`conflict_check_cleared` gate stays). Belongs in Step 2 (needs the party model).
|
||||
3. **Document & evidence repository** — every document on the matter, versioned,
|
||||
checksummed, with legal metadata (type, privilege, retention). The case file as
|
||||
one organized source of truth.
|
||||
4. **Deadline & calendar engine** — statutory/procedural clocks (answer, disclosure,
|
||||
discovery, objection windows) computed deterministically, surfaced on a layered,
|
||||
filterable calendar. Pure rules + date math; a real differentiator (a missed
|
||||
family-law deadline is malpractice).
|
||||
|
||||
### Tier 2 — The assembly (build the case) — *safe to build now; assembly + deterministic scoring*
|
||||
5. **Document drafting** — first drafts of pleadings/motions/forms from captured
|
||||
facts, with placeholders for unknowns, born as drafts for attorney review. Where
|
||||
the non-lawyer's facts become legal documents.
|
||||
6. **Procedural avenue mapping + decision graph** — given case type + what changed,
|
||||
surface the *available* procedural paths with their required elements and deadlines,
|
||||
rendered as a **branching decision graph** the attorney can compare at a glance. The
|
||||
menu, **not** the decision. Suggests; never strategizes. **Each path node shows a
|
||||
STRENGTH-OF-SUPPORT comparison — NOT a success percentage:**
|
||||
- procedural requirements (forms, elements, proof needed);
|
||||
- **strength factors present / missing**, drawn factually from the case data (e.g.
|
||||
"income change exceeds 15% threshold ✓; underemployment evidence not gathered ✗;
|
||||
financial affidavit on file ✓");
|
||||
- effort + timeline (deterministic: deadlines, steps, typical duration);
|
||||
- key risks / unknowns ("outcome depends on whether the court imputes income — a
|
||||
judgment call for the attorney");
|
||||
- what would strengthen the path (the gaps to close).
|
||||
**This deliberately does NOT output a win probability.** A "% chance of success" is
|
||||
fabricated precision (no honest dataset of comparable sealed/settled Miami-Dade
|
||||
outcomes exists), it is functionally the legal *opinion* only a licensed attorney may
|
||||
give, it becomes Bar-complaint/malpractice evidence if the case loses, and it anchors
|
||||
the attorney into shallow review. The graph compares **which path the facts on hand
|
||||
best support**; the attorney converts that into a probability using their own
|
||||
judgment and license. (See EXCLUDED, below.)
|
||||
7. **Requirements & completeness scoring** — the readiness engine: score the file
|
||||
against what a complete case of that type/stage needs (forms, proven facts,
|
||||
evidentiary foundations, met deadlines) and surface gaps **before** the attorney
|
||||
sees it. **The capability that most directly drives approval rate** — it catches
|
||||
the omissions that cause rejections. (Feeds the "strength factors" in capability 6.)
|
||||
|
||||
### Tier 3 — The legal support (high-risk, high-value core) — *NEEDS attorney-validated legal content before shipping*
|
||||
8. **Case-law research & verified citations** — propose authority, draft argument,
|
||||
and **verify every citation against a real reporter (CourtListener) before it can
|
||||
enter a filing**; unverified = mechanically blocked. Most valuable *and* most
|
||||
dangerous — the part that makes the software feel like it knows law, and the part
|
||||
that gets people sanctioned if built wrong.
|
||||
9. **Prior-judgment interpretation** — extract structured facts from an existing
|
||||
order, summarize it plainly, and **flag** legal-interpretation questions **without
|
||||
ruling** on them. Central to the modification/enforcement work this practice
|
||||
focuses on.
|
||||
|
||||
### Tier 4 — The output & the loop (close it safely) — *the machinery that makes all the above defensible*
|
||||
10. **Attorney review & approval workflow** — the GATE made into a workflow:
|
||||
assembled package → attorney reads, verifies, edits, signs → only then does
|
||||
anything move. **Non-negotiable; the capability that makes every other one safe.**
|
||||
11. **E-signature & filing preparation** — client-facing docs via DocuSeal; court
|
||||
filings prepared for `/s/` + Portal upload (prepare-and-upload). The last mile
|
||||
from approved draft to going out.
|
||||
12. **Audit trail** — every fact, AI action, citation verification status, and
|
||||
approval reconstructable. Protects the attorney and the practice when anyone asks
|
||||
"who did what, and was it checked."
|
||||
13. **Communications drafting** — plain-language, attorney-reviewed client updates;
|
||||
never auto-sends. Keeps clients informed without the attorney writing every email.
|
||||
14. **Nonlawyer supervision & access control** — the operator is a *low-legal-knowledge
|
||||
staffer handling privileged client data*, which triggers the attorney's duty to
|
||||
supervise nonlawyer assistants (Bar Rule 4-5.3). So: **matter-scoped access**
|
||||
(staff see only their assigned matters, not the whole client base), a nonlawyer-
|
||||
conduct acknowledgment, and the hard principle that **staff capture and assemble
|
||||
but never communicate legal positions to a client** (extends "never advises" from
|
||||
the AI to the human operator). This is a confidentiality + ethics requirement, not
|
||||
a nicety.
|
||||
15. **Data retention & destruction** — Florida imposes file-retention obligations, and
|
||||
"keep everything forever in an audit log" is itself a liability (more data = more
|
||||
breach surface; some data shouldn't be kept indefinitely). So: **attorney-configured
|
||||
retention classes**, a defined **closed-matter lifecycle** (retain → eligible for
|
||||
destruction → destroyed, with the action logged), and **client-file return at
|
||||
matter close**. The audit trail (12) records *that* destruction happened without
|
||||
retaining the destroyed content.
|
||||
|
||||
### Deliberately EXCLUDED (these cross from *assist* into *judge* → UPL/liability)
|
||||
- **Outcome / success-percentage prediction** — NO "% chance of winning" on any path,
|
||||
graph, or report. There is no honest dataset of comparable Miami-Dade family-law
|
||||
outcomes (cases are sealed, settlements private, "success" isn't binary), so any
|
||||
percentage is **fabricated precision**; it is functionally the legal *opinion* only a
|
||||
licensed attorney may give; it becomes evidence if a case loses; and it anchors the
|
||||
attorney into shallow review. **What IS allowed (capability 6): a strength-of-support
|
||||
decision graph** that compares which path the *facts on hand* best support — present/
|
||||
missing factors, requirements, effort, risks — leaving the probability judgment to the
|
||||
attorney. The distinction is load-bearing: "72% likely to win" = excluded;
|
||||
"threshold met, 4 of 5 supporting elements documented" = allowed.
|
||||
- **Evidence admissibility rulings** — admissibility is a contextual legal ruling.
|
||||
The software surfaces an evidence **completeness checklist** ("missing the
|
||||
foundation for exhibit C"); it does **not** rule the exhibit admissible.
|
||||
|
||||
**Build order implication:** Tiers 1, 2, and 4 are safe to build now (no legal
|
||||
judgment — data, assembly, deterministic rules, safety machinery). **Tier 3 is gated
|
||||
behind attorney validation of the underlying legal logic** (the requirements/
|
||||
elicitation content is the artifact to put in front of a Florida attorney). Build
|
||||
Tiers 1/2/4 first and gate Tier 3 → genuinely useful product quickly, on the right
|
||||
side of the line. This maps onto §7: capabilities 1–7 and 10–15 ride Steps 1–14
|
||||
(conflict screening 3 → Step 2; supervision/access 14 → Steps 2–3; retention 15 →
|
||||
Step 12); capabilities 8–9 are the Tier-3 pieces (Steps 6, 7, 9) the attorney
|
||||
questionnaire validates.
|
||||
|
||||
---
|
||||
|
||||
## 3. Architecture (decided)
|
||||
|
||||
- **Odoo 18 Community is the spine:** system of record, workflow/state machines,
|
||||
RBAC, audit (`mail.thread`), deadlines (`ir.cron` + `base.automation`), documents,
|
||||
calendar, UI. ~70% of needs are Odoo plumbing — **do not rebuild from scratch.**
|
||||
- **AI = Odoo's own HTTPS call to the Claude API** at `api.anthropic.com/v1/messages`.
|
||||
- **No Odoo "AI" feature is used** — Odoo Community has none; this is a plain
|
||||
outbound HTTP call from our module.
|
||||
- API key in `ir.config_parameter` (encrypted, attorney-group readable only).
|
||||
- Model **pinned in config** (`familylaw.model`), recorded per task for audit.
|
||||
- Calls run **async via `queue_job`** (OCA) so they never block the web worker.
|
||||
- **Provider is pluggable.** Local **Ollama** is a *future* routing option, not
|
||||
wired now. Build `_route_model()` so flipping high-confidentiality work to local
|
||||
is a **config change, not a redesign**.
|
||||
- **Trust/billing reconciliation NEVER reaches any model** — the routing layer
|
||||
raises before any such call. (IOTA, Bar Rule 5-1.1 — human-only.)
|
||||
- **One external service:** an optional **FastAPI orchestrator** for the multi-step
|
||||
**research loop** (search → propose citations → verify each → synthesize). Mirrors
|
||||
the owner's existing `odoo-ai` pattern. Single-shot AI tasks (drafting, summaries,
|
||||
extraction) run **from Odoo directly**; only the agentic research chain goes
|
||||
external. Running even that as sequenced `queue_job` steps inside Odoo is an
|
||||
acceptable alternative — complexity-vs-consolidation call, not correctness.
|
||||
- **Satellites:**
|
||||
- **DocuSeal** — self-hosted e-signature for *client-facing* docs (court filings use
|
||||
the `/s/` convention via the FL E-Filing Portal, **NOT** DocuSeal). **Two material
|
||||
caveats (do not bury these):** (1) the **API/embedding needed for the Odoo
|
||||
integration requires DocuSeal *Pro* (~$200/yr / ~$20-per-user-mo)** — the free tier
|
||||
does core signing but not the programmatic integration; (2) the **DocuSeal signing
|
||||
host must be internet-facing**, unlike the rest of the NetBird-internal,
|
||||
privacy-first stack — so it must be **isolated and hardened** (its Postgres not
|
||||
exposed, audit trail backed up). For a HIPAA-adjacent operator these are design
|
||||
facts, not footnotes.
|
||||
- **MinIO or Synology NAS** — file archive behind `ir.attachment`.
|
||||
- **CourtListener** — citation verification. **It is a single point of failure for
|
||||
the citation gate (capability 8 — the thing that prevents sanctions), so:**
|
||||
(1) **fail CLOSED** — if CourtListener is down, rate-limited, or has no record for a
|
||||
cite, the citation **stays `unverified` and remains blocked**; the system NEVER
|
||||
"assumes good" or waves anything through on a verification failure; (2) define at
|
||||
least **one fallback source** (e.g. Google Scholar / a secondary API) before relying
|
||||
solely on it; (3) **confirm Florida appellate (DCA + Supreme Court) coverage is
|
||||
adequate BEFORE building on it** — verify the tool actually works for FL family-law
|
||||
authority, don't assume.
|
||||
- **AI cost & latency (model this from day one):** a fully-assembled matter can mean
|
||||
*many* calls (drafting + research + per-citation verification), so a research loop can
|
||||
run minutes and cost real money per case. Set a **per-task token ceiling**, and
|
||||
**record token cost + latency on each `ai.task`** so the economics are measurable and
|
||||
capped, not discovered later. Budget the cost-per-assembled-case explicitly.
|
||||
- **Court e-filing reality:** the FL Courts E-Filing Portal has **no public push
|
||||
API**. The model is **prepare-and-upload**: software prepares, attorney signs
|
||||
`/s/`, a human uploads through the Portal, confirmation recorded back in Odoo.
|
||||
|
||||
### Tech/environment notes
|
||||
- **Odoo 18 view syntax:** use `<list>` (NOT `<tree>` — removed in 18). `attrs=`
|
||||
and `states=` are **removed**; use direct attributes (`invisible="..."`,
|
||||
`readonly="..."`, `required="..."`). Chatter: explicit `oe_chatter` div used for
|
||||
cross-release safety (v18 also supports the `<chatter/>` shorthand).
|
||||
- Owner runs Odoo 18 in production (Docker/Proxmox stack, Postgres, Traefik,
|
||||
NetBird). The orchestrator/Ollama/GPU box already exist.
|
||||
- **Verify volatile legal facts at build time.** Florida renumbers forms and amends
|
||||
rules/statutes regularly (e.g., the 2023 alimony overhaul removed permanent
|
||||
alimony; Rule 12.410 subpoena amendment effective Oct 1 2025). Never bake a
|
||||
specific statute version into code as if permanent; keep "verify current rule"
|
||||
in the flow.
|
||||
|
||||
---
|
||||
|
||||
## 4. Decisions locked (apply these — do not re-litigate)
|
||||
|
||||
| Decision | **Choice** | Consequence for the build |
|
||||
|---|---|---|
|
||||
| **Intake front door** | **Intake creates a draft case directly** | The intake questionnaire fills a `familylaw.case` that starts in `intake` state. No separate lead/convert step. |
|
||||
| **Case creation strictness** | **Conditional: strict for standard intake, FAST-PATH for emergencies** | Standard intake = **strict** (require matter name, client, case type, county/court + triage essentials before the draft case commits — the friction is fine and keeps data clean). **Emergency intake = fast-path:** if the urgency screen trips (child withheld / removal threat / violence), creation requires only the bare minimum to act (who, which child, what's happening) and **defers** the rest. Rationale: in a genuine emergency the procedural clock and the child's safety beat data completeness; a bare "strict" rule would block opening the matter exactly when speed matters most. The urgency screen runs first, so it gates which creation path applies. |
|
||||
| **Modification: how Case A is handled** | **One continuous case; each new proceeding is a child `familylaw.proceeding`** | A modification/enforcement **reopens the same `familylaw.case`** (continuity, full history in one place) **BUT** spawns a new **`familylaw.proceeding`** record under it. **Deadlines, documents, and proceeding-state attach to the PROCEEDING, not the case.** This resolves the flaw in a bare "reopen": without it, the deadline engine can't tell the 2024 dissolution's disclosure clock from a 2027 modification's, and documents/audit from distinct legal proceedings pile together. The case is the client-matter spine; the proceeding is the unit of legal action. (Reconciles with doc 03's parent/child structure — same idea, named `proceeding`.) |
|
||||
| **"Interpret the prior judgment"** | **Extraction + plain summary + legal interpretation (flagged, not concluded)** | The AI extracts structured facts, writes a plain-language summary, **and** may surface legal interpretation of provisions — but interpretation is **flagged for the attorney, never stated as a conclusion/ruling.** Born as draft; attorney decides. |
|
||||
|
||||
Other standing choices from design: **native Odoo models** for the questionnaire
|
||||
(NOT the Survey app) — answers must land as typed case data the workflow can use,
|
||||
with no survey→case mapping layer. Markdown for docs; module version-controlled in
|
||||
Gitea by the owner.
|
||||
|
||||
---
|
||||
|
||||
## 5. The build method — VERIFIABLE STEPS (follow strictly)
|
||||
|
||||
Build in small, independently verifiable slices. **Do not start step N+1 until step
|
||||
N's tests are green and its walkthrough passes.** Every step delivers, in order:
|
||||
|
||||
1. **Installable code** — installs/upgrades cleanly (`-u activeblue_familylaw`).
|
||||
2. **A walkthrough** — a UI click-path that shows the new behaviour end to end.
|
||||
3. **Tagged unit tests** — under `tests/`, tagged `familylaw_step<N>`, proving the
|
||||
step's guarantees (especially the gates).
|
||||
4. **Done-when** — explicit pass condition: green tests + clean walkthrough → ship,
|
||||
then advance.
|
||||
|
||||
### Test harness
|
||||
- Tests subclass `TransactionCase` (savepoint rollback; DB stays clean).
|
||||
- Tag: `@tagged("post_install", "-at_install", "familylaw", "familylaw_step<N>")`.
|
||||
- Group-gated actions: `new_test_user(..., groups="base.group_user,activeblue_familylaw.group_familylaw_attorney")`; call with `.with_user(attorney)` / `.with_user(paralegal)`.
|
||||
- **External APIs are ALWAYS mocked** (`unittest.mock.patch`) — Claude, DocuSeal,
|
||||
CourtListener. Tests must never hit the network. Assert on what got written to
|
||||
Odoo (e.g. "document born `ai_draft`", "citation born `unverified`").
|
||||
- **Date math tested with fixed dates**, never `today()`, for determinism.
|
||||
|
||||
Run all: `odoo -d <db> -i activeblue_familylaw --test-enable --stop-after-init`
|
||||
Run one step: `odoo -d <db> -u activeblue_familylaw --test-enable --test-tags familylaw_step1 --stop-after-init`
|
||||
|
||||
---
|
||||
|
||||
## 6. What's already built — STEP 1 ✅ (delivered, validated)
|
||||
|
||||
Module: `activeblue_familylaw` (in the Step 1 zip; layout below).
|
||||
|
||||
**`familylaw.case`** — the matter spine:
|
||||
- Identity: `name`, `client_id` (res.partner), `case_type` (selection: dissolution
|
||||
w/ & w/o children, paternity, support/parenting/alimony modification, enforcement,
|
||||
DV injunction, other).
|
||||
- Team: `attorney_id`, `paralegal_id` (res.users).
|
||||
- **`representation`** (attorney / pro_se) — drives the Step 8 subpoena branch.
|
||||
- **`conflict_check_cleared`** (attorney-only gate, readonly, tracked).
|
||||
- **`state`** lifecycle: `intake → engaged → disclosure → discovery → mediation →
|
||||
hearing → closed`, with **guarded transitions** (each checks current state, rejects
|
||||
illegal jumps) and **attorney-only** actions (`action_mark_conflict_cleared`,
|
||||
`action_close`, `action_reopen`) enforced in **Python AND** via `groups=` on buttons.
|
||||
- `mail.thread` / `mail.activity.mixin` — every transition + clearance posts to the
|
||||
chatter (the audit trail).
|
||||
|
||||
**Security:** groups `group_familylaw_user` (Staff) and `group_familylaw_attorney`
|
||||
(Attorney, implies Staff implies internal). Access rules: staff can't delete; attorney can.
|
||||
|
||||
**Views:** list (`<list>`), form (statusbar + transition buttons + chatter), search
|
||||
(filters: My Cases, Open, Awaiting Conflict Clearance; group-by: stage/attorney/type).
|
||||
**Menu:** Family Law → Cases (+ Configuration placeholder).
|
||||
|
||||
**Tests (`tests/test_case_lifecycle.py`, tag `familylaw_step1`):** 10 tests — initial
|
||||
state, conflict-clearance gate (engage blocked until cleared; only attorney clears),
|
||||
illegal-transition rejection, full forward path, attorney-only close/reopen, audit
|
||||
logging. Statically validated: Python compiles, XML well-formed, manifest is a dict,
|
||||
every button maps to a method, every view field exists on the model, zero
|
||||
Odoo-18-forbidden constructs.
|
||||
|
||||
### Module layout
|
||||
```
|
||||
activeblue_familylaw/
|
||||
__init__.py
|
||||
__manifest__.py # depends: base, mail
|
||||
models/
|
||||
__init__.py
|
||||
familylaw_case.py # the spine + state machine + gates
|
||||
security/
|
||||
familylaw_security.xml # groups + module category
|
||||
ir.model.access.csv # staff (no unlink) / attorney (full)
|
||||
views/
|
||||
familylaw_case_views.xml # list, form, search, action
|
||||
familylaw_menus.xml # app menu
|
||||
tests/
|
||||
__init__.py
|
||||
test_case_lifecycle.py # familylaw_step1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. The step sequence (roadmap)
|
||||
|
||||
| Step | Slice | Key models / files | Proves (tests) | Doc |
|
||||
|---|---|---|---|---|
|
||||
| **1 ✅** | Case spine + lifecycle + attorney gates | `familylaw.case`, security, views | transitions, conflict gate, attorney-only, audit | 02,03 |
|
||||
| **2 → NEXT** | **Parties, children, issues + `proceeding` + conflict screening + `case_number` + search + intake questionnaire** | `familylaw.party`, `.child`, `.issue`, **`familylaw.proceeding`**; indexed `case_number`; conflict-search method; intake wizard | relations, DOB constraints, **find by party/child/case number**, **conflict search surfaces a past-client opposing party**, questionnaire creates draft case (strict) / emergency fast-path, urgency flag raised, "good case?" captured not answered | 02,03 |
|
||||
| 3 | **Documents + the review gate** | `familylaw.document` (`ai_draft→attorney_review→approved`), attached to a **proceeding** | only attorney approves; can't file/send unapproved (GATE 1) | 03,04 |
|
||||
| 4 | Deadline engine | `familylaw.deadline` (**FK to `proceeding`, not case**) + `base.automation` + `ir.cron` + `calendar.event` mirror | 20/45/30-day math, weekend roll, overdue, **deadlines isolated per proceeding** | 02,11 |
|
||||
| 5 | Mandatory disclosure (Rule 12.285) | `disclosure.item`, `financial.affidavit`, `fin.line` (per proceeding) | 12.902(b) vs (c) by income, 45-day due, can't-waive | 02,11 |
|
||||
| 6 | **Claude client + `ai.task` ledger** (single-shot) | `familylaw.ai.client`, `ai.task` (**logs model + token cost + latency**), drafting agent, `queue_job` | (mocked) doc born `ai_draft`, task logged w/ cost, cites born `unverified` | 04,09 |
|
||||
| 7 | **Citation ledger + filing gate** + research loop | `familylaw.citation`, `action_request_filing`, FastAPI orchestrator; **fail-closed verification + fallback source** | filing blocked on any unverified cite (GATE 2); verification failure keeps cite blocked | 06 |
|
||||
| 8 | **Discovery + subpoena** (12.351 gate + pro-se/attorney branch) | `discovery.request`, objection-window gate | objection-window hard gate, same-day Notice of Issuance, clerk-vs-attorney routing | 11 A.6,C |
|
||||
| 9 | **Child-support modification** workflow (end to end) | wires 1–8 for `support_modification`; **new `proceeding` under the reopened case** | 15%/$50 threshold, 20-day answer, DOR-case flag, retroactivity note, **prior-judgment extraction+summary+flagged interpretation** | 11 B.2 |
|
||||
| 10 | **Emergency** workflow (12.941 pick-up/removal) | emergency motion records + required-attachment checks; **uses the intake fast-path** | have-order-vs-not fork; missing-attachment block; fast-path opens matter on minimum facts | 11 B.1 |
|
||||
| 11 | DocuSeal e-signature | `action_send_for_signature`, webhook controller (**Pro tier; isolated internet-facing host**) | (mocked) only `approved` sends; webhook → `signed` | 05 |
|
||||
| 12 | File archive + calendar layers + **retention lifecycle** | `ir.attachment` + `familylaw.archive` metadata; calendar categories; retention classes + closed-matter destruction | SHA-256 checksum, **retention class drives destruction-eligibility**, client-file-return at close, **per-layer filter toggles** | new |
|
||||
| 13 | Miami-Dade auto-seed (AO 14-13) | Status Quo Order, parenting-course + mediation obligations on case open | obligations seed on open; course-before-judgment guard | 11 D |
|
||||
| 14 | Comms agent + AI-assisted billing flag + hardening + **matter-scoped access** | `comms` drafts, `time.entry.ai_assisted`, record rules scoping staff to assigned matters, encryption/backup | (mocked) comms never auto-sends; AI ratio reportable; **staff can't see unassigned matters** | 04,08 |
|
||||
|
||||
**Intake questionnaire** (native models; intake-creates-draft-case; **conditional
|
||||
strictness — strict for standard, fast-path for emergencies**) is the high-leverage
|
||||
elicitation layer. It belongs with **Step 2** (it needs the party/child fields) and is
|
||||
built **triage section + ONE case-type branch (child-support modification first)**,
|
||||
then more branches added incrementally. The triage **urgency screen runs FIRST** and
|
||||
selects strict vs. fast-path creation. It captures facts only — it **never answers**
|
||||
"do I have a good case?" (logs that as a question for the attorney).
|
||||
|
||||
**MVP to run a solo practice:** Steps 1–6 + 8 + 11, then add 7. Steps 9/10 are the
|
||||
headline workflows; 12–14 round it out.
|
||||
|
||||
---
|
||||
|
||||
## 8. STEP 2 — the immediate task (build this next)
|
||||
|
||||
**Goal:** the related records that make a matter real, the **proceeding** layer that
|
||||
keeps modifications/enforcements cleanly separated, **automated conflict screening**,
|
||||
search the way a practice actually searches (by people + court case number), and the
|
||||
intake questionnaire front door (conditional strict / emergency fast-path).
|
||||
|
||||
**Build:**
|
||||
1. **`familylaw.party`** — a party to the matter (`res.partner` + role: client /
|
||||
opposing party / opposing counsel / other). Opposing-party capture feeds conflict
|
||||
screening (#6).
|
||||
2. **`familylaw.child`** — a minor child (name, DOB **with validation: reject future
|
||||
or implausible dates**, link to case); searchable.
|
||||
3. **`familylaw.issue`** — a contested issue (time-sharing, support, equitable
|
||||
distribution, alimony, etc.) — the spine for later requirements scoring.
|
||||
4. **`familylaw.proceeding`** — **the unit of legal action under a case.** A case can
|
||||
have many proceedings over time (original dissolution, later modification, later
|
||||
enforcement). Fields: `case_id` (FK), `proceeding_type`, `state` (its own
|
||||
lifecycle), open/close dates. **From here on, deadlines and documents attach to a
|
||||
proceeding, not directly to the case** (Steps 3–5 build on this). On case creation,
|
||||
open an initial proceeding for the originating matter.
|
||||
5. **`case_number`** on `familylaw.case` — court-assigned (e.g. 2024-DR-001234),
|
||||
**indexed + searchable**. (A proceeding may also carry its own number if the court
|
||||
assigns one.)
|
||||
6. **Automated conflict screening** — a method that, given the captured opposing
|
||||
party, **searches `familylaw.party` across ALL cases** and returns potential
|
||||
conflicts (opposing party matches a past/current client; or is already an opposing
|
||||
party elsewhere). Surface the hits **on the case for the attorney to clear** — it
|
||||
does **not** auto-clear or auto-block; the Step 1 `conflict_check_cleared` attorney
|
||||
gate remains the decision point. (Name-match can be fuzzy; flag for human review,
|
||||
never auto-resolve.)
|
||||
7. **Search-by-person / by-number:** extend case search so a matter is findable by
|
||||
party name, child name, and `case_number` — not just title/client.
|
||||
8. **Intake questionnaire (native; creates draft case; conditional strictness):** a
|
||||
guided multi-step flow that (a) runs **triage FIRST** (caller + contact, opposing
|
||||
party, minor children y/n, county/court, existing case/order, **urgency screen:
|
||||
child withheld / removal threat / violence**), (b) **branches on urgency**:
|
||||
*standard* → strict (require name, client, case type, county + triage essentials
|
||||
before commit); *emergency* → **fast-path** (commit on minimum facts: who, which
|
||||
child, what's happening; defer the rest), (c) branches into the **child-support
|
||||
modification** question set, and (d) on completion **creates a draft
|
||||
`familylaw.case` in `intake` state** (and its initial proceeding). Runs conflict
|
||||
screening (#6) as part of completion. Collects facts only.
|
||||
|
||||
**Tests (`familylaw_step2`):** relation integrity (party/child/issue/proceeding ↔
|
||||
case); DOB constraint rejects future/implausible dates; **find case by party name /
|
||||
child name / case_number** returns the right matter; **conflict screening surfaces a
|
||||
past-client opposing party** and does NOT auto-clear; a case can hold **multiple
|
||||
proceedings** and each carries its own state; questionnaire triage sets case type;
|
||||
**standard path enforces strict creation** (rejects incomplete submission);
|
||||
**emergency path commits on minimum facts** and raises the urgency flag; "do I have a
|
||||
good case?" is **captured as an attorney question, never answered**.
|
||||
|
||||
**Constraints:** Odoo 18 syntax (`<list>`, direct attributes — no `<tree>`, no
|
||||
`attrs`/`states`). **No external/network calls in Step 2** (questionnaire is pure data
|
||||
capture; AI extraction of an uploaded judgment is Step 6+; conflict screening is a
|
||||
local DB search, not an AI call). Keep the gate philosophy intact — nothing here
|
||||
advises, decides, or auto-clears a conflict.
|
||||
|
||||
**Done-when:** `familylaw_step2` tests green + a walkthrough where you (a) complete a
|
||||
*standard* modification intake and land on a new draft case with an initial
|
||||
proceeding; (b) complete an *emergency* intake and get a matter opened on minimum
|
||||
facts with the urgency flag set; (c) see a conflict flag when the opposing party
|
||||
matches an existing client; and (d) find an existing case by opposing-party name, by
|
||||
child name, and by case number.
|
||||
|
||||
---
|
||||
|
||||
## 9. Working agreements for Claude Code
|
||||
|
||||
- **Read the relevant design doc (`00`–`11`) before each step**; this file says
|
||||
*what/next*, the docs say *why/detail*.
|
||||
- **One verifiable step at a time.** Don't scaffold ahead. Deliver code + tests +
|
||||
walkthrough, stop, confirm green, then continue.
|
||||
- **The two gates are sacred.** Never add a code path that lets AI output be
|
||||
filed/sent/signed without attorney approval, or lets an unverified citation into a
|
||||
filing. If a request would breach this, flag it instead of building it.
|
||||
- **Mock all external APIs in tests.** Never hit Claude/DocuSeal/CourtListener from a
|
||||
test.
|
||||
- **Verify volatile legal facts** (forms, rules, statutes) against current sources at
|
||||
build time; keep "verify current rule" in the flow rather than hardcoding a version
|
||||
as permanent.
|
||||
- **Owner profile:** experienced infra/dev (Proxmox, Docker, Postgres, Python,
|
||||
Odoo 18 in prod). Be direct and technical; prefer CLI; the owner version-controls
|
||||
in Gitea. Plan fully, validate each stage.
|
||||
- **This is not legal advice** and the platform must not practice law; a licensed
|
||||
attorney reviews, verifies, and signs all output.
|
||||
|
||||
---
|
||||
|
||||
## 10. Design-revision changelog (audit fixes applied to this revision)
|
||||
|
||||
Nine flaws were found in a critical design review and fixed in this document:
|
||||
|
||||
1. **Training-data flywheel → safe improvement loop (§1).** The "attorney corrections
|
||||
become training data" claim risked leaking privileged client data (Rule 4-1.6) and
|
||||
assumed nonexistent fine-tuning infra. Replaced with prompt/example refinement +
|
||||
regression evals as the default; fine-tuning is future/gated on a de-identified,
|
||||
consented, separate corpus.
|
||||
2. **Bare "reopen" → `familylaw.proceeding` model (§4, §7, §8).** Reopening one case
|
||||
repeatedly would conflate deadlines/documents/audit across distinct legal
|
||||
proceedings and contradicted doc 03. Now: one continuous case, each
|
||||
modification/enforcement is a child proceeding that owns its own deadlines/docs/state.
|
||||
3. **Conflict checkbox → automated conflict screening (capability 3, Step 2).** A human
|
||||
ticking a box misses structural conflicts across many matters. Added a DB-wide
|
||||
party search that surfaces conflicts for the attorney to clear (attorney still decides).
|
||||
4. **Strict creation vs. emergencies → conditional strictness (§4, Step 2/10).** Strict
|
||||
field requirements would block opening a genuine emergency matter. Now strict for
|
||||
standard intake, fast-path (minimum facts) when the urgency screen trips.
|
||||
5. **AI cost/latency unmodeled → budgeted (§3, Step 6).** Added per-task token ceiling
|
||||
and cost+latency logging on `ai.task`; budget cost-per-assembled-case explicitly.
|
||||
6. **CourtListener single point of failure → fail-closed + fallback + FL-coverage check
|
||||
(§3, Step 7).** Verification failure now keeps a cite blocked (never "assume good"),
|
||||
a fallback source is required, and Florida appellate coverage must be confirmed first.
|
||||
7. **Non-lawyer operator confidentiality → supervision + matter-scoped access
|
||||
(capability 14, Step 14).** Added Rule 4-5.3 supervision layer, matter-scoped record
|
||||
rules, and the principle that staff never communicate legal positions to clients.
|
||||
8. **DocuSeal caveats restored (§3, Step 11).** Surfaced the Pro-tier cost (~$200/yr for
|
||||
the API) and the internet-facing/isolated-host requirement at the architecture level.
|
||||
9. **No retention policy → retention & destruction capability (capability 15, Step 12).**
|
||||
Added attorney-configured retention classes, a closed-matter destruction lifecycle,
|
||||
and client-file return at close (audit logs *that* destruction occurred, not the content).
|
||||
|
||||
**Note:** none of these were defects in the delivered Step 1 *code* — they were in the
|
||||
surrounding design. Step 1 remains valid. The structural change that most affects
|
||||
forthcoming work is the `familylaw.proceeding` model (fix 2), which Step 2 introduces
|
||||
and Steps 3–5 build on.
|
||||
|
||||
**Later additions (this revision):**
|
||||
10. **Strength-of-support decision graph, NOT a success-percentage predictor
|
||||
(capability 6, EXCLUDED).** A requested "% chance of success per path" was declined
|
||||
as fabricated precision / functional legal opinion / liability, and replaced with a
|
||||
factual path-comparison graph (present-missing factors, requirements, effort, risks)
|
||||
that leaves the probability judgment to the attorney.
|
||||
11. **Claude's role clarified as the quality-elevation layer (§1)** and a new **§11
|
||||
"Requirements for Success"** added — the non-code gaps (engaged licensed attorney,
|
||||
practice-ownership model, malpractice insurance, engagement-letter AI clause,
|
||||
security/breach plan, operator UPL guardrails, content-maintenance process, the
|
||||
elicitation content, FL-proven citation source, eval/QA, cost model). #1 (attorney)
|
||||
and #2 (ownership) gate the venture; both are non-coding and run parallel to Steps 2–5.
|
||||
|
||||
---
|
||||
|
||||
## 11. Requirements for SUCCESS (non-code gaps that must be closed)
|
||||
|
||||
The 15 capabilities make the software *function*. These items make the venture
|
||||
*succeed and stay legal*. Several are **launch-blockers**, not enhancements. They are
|
||||
not optional, and most cannot be solved by writing code.
|
||||
|
||||
### Critical — blocks the whole model
|
||||
1. **A named, engaged, licensed Florida family-law attorney — NOW, not at launch.**
|
||||
The entire architecture routes assembled cases to a reviewing/signing attorney; with
|
||||
no such attorney, there is no one to hand the case to and the product cannot legally
|
||||
operate. This attorney must (a) **validate the legal logic** in docs 02/11 (forms,
|
||||
deadlines, avenues, 11th-Circuit specifics), (b) be the **actual reviewing/signing
|
||||
attorney**, and (c) **own the malpractice and Bar exposure**. *First concrete step:
|
||||
the attorney-review questionnaire (below) — it turns the researched-but-unvalidated
|
||||
legal logic into something a Florida attorney can confirm and sign off.*
|
||||
2. **Settle "whose practice is this?" (ownership / business model).** Florida prohibits
|
||||
nonlawyer ownership of law firms and fee-splitting with nonlawyers. Clean model:
|
||||
**Active Blue builds/operates the software; a licensed firm uses it.** Problematic
|
||||
model: **Active Blue runs the practice** — no code fixes that. Resolve before
|
||||
building the Tier-3 legal-reasoning pieces, because the answer shapes how they're
|
||||
built and who the "attorney" in the workflow legally is.
|
||||
|
||||
### Launch-blockers — required before a single real client matter
|
||||
3. **Malpractice insurance that contemplates AI-assisted work**, carried by the
|
||||
responsible attorney/firm.
|
||||
4. **Engagement-letter framework with an AI-disclosure clause** — the client is told AI
|
||||
assists their matter and a licensed attorney reviews and is responsible.
|
||||
5. **Security review + breach-response plan for privileged data.** The privacy-first
|
||||
stack is a head start, but privileged legal data + a non-lawyer operator + an
|
||||
internet-facing DocuSeal host needs an actual review, encryption-at-rest for case
|
||||
data, and an incident plan — not just good instincts.
|
||||
6. **UPL guardrails for the human operator** (pairs with capability 14): the non-lawyer
|
||||
never communicates legal positions/opinions to clients; all legal questions route to
|
||||
the attorney; this is trained and enforced, not assumed.
|
||||
|
||||
### Ongoing — required to stay correct over time
|
||||
7. **A legal-content maintenance process.** Florida changed alimony (2023) and subpoena
|
||||
rules (2025); forms get renumbered. Someone must **watch for rule/form/statute
|
||||
changes and update the logic** on a schedule. A case built on a repealed form is a
|
||||
malpractice event. "Verify current rule" handles point-in-time; this handles drift.
|
||||
8. **The requirements/elicitation content itself** (unblocks capabilities 7 & 8). The
|
||||
per-case-type definition of "what a complete, winnable file requires" — elements,
|
||||
proof, forms, the strength factors the decision graph reads — **does not exist yet**.
|
||||
This is the artifact the attorney validates and the engine consumes; without it,
|
||||
completeness-scoring and research have nothing authoritative to check against.
|
||||
9. **A citation-verification source proven for Florida** (pairs with §3 architecture):
|
||||
confirm CourtListener (+ fallback) actually covers FL DCA + Supreme Court family-law
|
||||
authority adequately before relying on the citation gate in production.
|
||||
10. **A real evaluation/QA process before anything is client-facing.** The regression
|
||||
eval suite (doc 09 §9) wired to run before every prompt/model change; a defined bar
|
||||
the assembled output must clear; attorney spot-audits of approved work.
|
||||
|
||||
### Strongly recommended — for the product to actually deliver its promise
|
||||
11. **Cost-per-assembled-case model** (pairs with §3 / Step 6): know the token cost and
|
||||
latency of a full matter so pricing and the economics hold; cap per-task spend.
|
||||
12. **Client intake/consent for AI involvement** captured in the record (distinct from
|
||||
the engagement letter): the client's informed acknowledgment, logged.
|
||||
13. **A "human-in-the-loop won't be skipped" enforcement audit**: periodic proof that no
|
||||
code path and no operator habit lets unreviewed/unsigned work reach a client, clerk,
|
||||
or court — the two gates verified in practice, not just in tests.
|
||||
|
||||
**Bottom line:** of everything above, **#1 (the attorney) and #2 (the ownership model)
|
||||
gate the venture** — neither is a coding task, both should be moving in parallel with
|
||||
Steps 2–5, and #1 starts with the attorney-review questionnaire. The software can be
|
||||
~80–90% built and validated and still cannot run a real matter until #1–#6 are closed.
|
||||
@@ -0,0 +1,60 @@
|
||||
# START HERE — Claude Code kickoff
|
||||
|
||||
You are picking up an in-progress build. Read in this order, then start the task at
|
||||
the bottom. Do **not** re-derive the design — it exists; follow it.
|
||||
|
||||
## Read order (do this first)
|
||||
1. **`CLAUDE.md`** — the operational brief and single source of truth. Read it fully.
|
||||
Pay special attention to:
|
||||
- §1 — the governing rule + the two gates + Claude's role as the quality-elevation layer.
|
||||
- §2 — the 15 capabilities, grouped by RISK (what's safe now vs. attorney-gated).
|
||||
- §4 — locked decisions (apply them; do not re-litigate).
|
||||
- §5 — the verifiable-step method + the test harness rules.
|
||||
- §8 — **STEP 2, your immediate task.**
|
||||
- §10 — the audit fixes already applied (esp. fix 2, the `familylaw.proceeding` model).
|
||||
- §11 — the non-code success gaps (context for why some steps are gated).
|
||||
2. **`BUILD_PLAN.md`** — the step contract and the run/test commands.
|
||||
3. **The design docs `00`–`11`** (in the separate design package) — *why/detail* behind
|
||||
each step. Read the relevant doc(s) before each step, not all at once. For Step 2:
|
||||
docs 02 (domain) and 03 (data model).
|
||||
|
||||
## Current state
|
||||
- **Step 1 is DONE and validated** — `activeblue_familylaw` module: the `familylaw.case`
|
||||
spine, the lifecycle state machine, attorney-only gates, security groups, views,
|
||||
and 10 passing tests (tag `familylaw_step1`). Module layout is in `CLAUDE.md §6`.
|
||||
- The code is Odoo 18 (uses `<list>` not `<tree>`; direct attributes, no `attrs`/`states`).
|
||||
- Nothing else is built yet. Steps 2–14 are designed, not implemented.
|
||||
|
||||
## Hard rules (from CLAUDE.md — do not violate)
|
||||
- **One verifiable step at a time.** Don't scaffold ahead. Each step = installable code
|
||||
+ a UI walkthrough + tagged unit tests + a done-when. Get green before advancing.
|
||||
- **The two gates are sacred:** no code path lets AI output be filed/sent/signed without
|
||||
attorney approval, or lets an unverified citation into a filing. If a request would
|
||||
breach this, flag it — don't build it.
|
||||
- **Mock all external APIs in tests** (Claude, DocuSeal, CourtListener). Never hit the
|
||||
network from a test. Test date math with fixed dates.
|
||||
- **No outcome/success-percentage prediction.** The decision graph compares strength of
|
||||
support, never a "% chance of winning" (CLAUDE.md §2 EXCLUDED).
|
||||
- **Tier 3 (capabilities 8–9, Steps 6–7–9) is gated** behind licensed-attorney
|
||||
validation of the legal logic. You may build the *structure/scaffolding* but flag that
|
||||
the legal content is unvalidated; do not present legal reasoning as authoritative.
|
||||
|
||||
## Your first task: STEP 2
|
||||
Build exactly what `CLAUDE.md §8` specifies:
|
||||
- Models: `familylaw.party`, `familylaw.child`, `familylaw.issue`, **`familylaw.proceeding`**.
|
||||
- Add indexed, searchable `case_number` to `familylaw.case`; open an initial proceeding
|
||||
on case creation.
|
||||
- **Automated conflict screening** — a local DB search over `familylaw.party` across all
|
||||
cases that surfaces potential conflicts for the attorney to clear (never auto-clears,
|
||||
never auto-blocks; the Step 1 `conflict_check_cleared` attorney gate remains).
|
||||
- Extend case search to find by party name, child name, and `case_number`.
|
||||
- **Intake questionnaire** (native models; creates a draft case): triage-first with the
|
||||
urgency screen, **conditional strictness** (standard = strict; emergency = fast-path on
|
||||
minimum facts), branching into the **child-support modification** question set, runs
|
||||
conflict screening on completion. Captures facts only — never answers "do I have a good
|
||||
case?" (logs it as an attorney question).
|
||||
- Tests tagged `familylaw_step2` covering everything in §8's test list.
|
||||
- **Done-when:** `familylaw_step2` green + the four-part walkthrough in §8.
|
||||
|
||||
Work in the module, keep Step 1's tests green, and deliver Step 2 as one reviewable,
|
||||
tested slice. Then stop and report before starting Step 3.
|
||||
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
@@ -0,0 +1,35 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
{
|
||||
"name": "Active Blue Family Law",
|
||||
"version": "18.0.1.0.0",
|
||||
"category": "Services/Legal",
|
||||
"summary": "Florida family law case management (Miami-Dade / 11th Judicial Circuit)",
|
||||
"description": """
|
||||
Active Blue Family Law
|
||||
======================
|
||||
Case-management platform for a Florida family-law practice, built in verifiable
|
||||
steps. STEP 1 delivers the case spine: the familylaw.case model, its lifecycle
|
||||
state machine, security groups (attorney / staff), and the case views.
|
||||
|
||||
Each subsequent step adds one vertical, independently testable slice. See
|
||||
BUILD_PLAN.md for the full sequence and the test method.
|
||||
|
||||
Design package: docs 00-11 (architecture, domain, data model, AI agents,
|
||||
signing, citation verification, wire map, training, forms & playbook).
|
||||
""",
|
||||
"author": "Active Blue LLC",
|
||||
"website": "https://activeblue.net",
|
||||
"license": "LGPL-3",
|
||||
"depends": [
|
||||
"base",
|
||||
"mail",
|
||||
],
|
||||
"data": [
|
||||
"security/familylaw_security.xml",
|
||||
"security/ir.model.access.csv",
|
||||
"views/familylaw_case_views.xml",
|
||||
"views/familylaw_menus.xml",
|
||||
],
|
||||
"application": True,
|
||||
"installable": True,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
from . import familylaw_case
|
||||
@@ -0,0 +1,216 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""STEP 1 — The case spine.
|
||||
|
||||
familylaw.case is the system of record for a matter. This step implements:
|
||||
* the core identifying fields and the responsible-people links,
|
||||
* the pro-se / attorney representation flag (drives later workflows),
|
||||
* the lifecycle STATE MACHINE with guarded transitions, and
|
||||
* two attorney-only gates (conflict clearance, closing a case).
|
||||
|
||||
The guards are enforced in Python (server-side, testable) AND mirrored in the
|
||||
view via `groups=` on the buttons (defence in depth). Later steps add parties,
|
||||
children, documents, the review gate, deadlines, AI, discovery, etc.
|
||||
"""
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
ATTORNEY_GROUP = "activeblue_familylaw.group_familylaw_attorney"
|
||||
|
||||
# The case lifecycle. Order matters: it defines the legal "forward" path.
|
||||
STATE_SEQUENCE = [
|
||||
"intake",
|
||||
"engaged",
|
||||
"disclosure",
|
||||
"discovery",
|
||||
"mediation",
|
||||
"hearing",
|
||||
"closed",
|
||||
]
|
||||
|
||||
|
||||
class FamilyLawCase(models.Model):
|
||||
_name = "familylaw.case"
|
||||
_description = "Family Law Case"
|
||||
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||
_order = "create_date desc"
|
||||
|
||||
# --- Identity -----------------------------------------------------------
|
||||
name = fields.Char(
|
||||
string="Matter",
|
||||
required=True,
|
||||
tracking=True,
|
||||
help="Short matter title, e.g. 'In re the Marriage of Client A'.",
|
||||
)
|
||||
client_id = fields.Many2one(
|
||||
"res.partner",
|
||||
string="Client",
|
||||
required=True,
|
||||
tracking=True,
|
||||
)
|
||||
case_type = fields.Selection(
|
||||
selection=[
|
||||
("dissolution_no_children", "Dissolution — no children"),
|
||||
("dissolution_children", "Dissolution — with children"),
|
||||
("paternity", "Paternity"),
|
||||
("support_modification", "Child Support Modification"),
|
||||
("parenting_modification", "Parenting / Time-Sharing Modification"),
|
||||
("alimony_modification", "Alimony Modification"),
|
||||
("enforcement", "Enforcement / Contempt"),
|
||||
("dv_injunction", "Domestic Violence Injunction"),
|
||||
("other", "Other"),
|
||||
],
|
||||
string="Case Type",
|
||||
required=True,
|
||||
default="dissolution_children",
|
||||
tracking=True,
|
||||
)
|
||||
|
||||
# --- People -------------------------------------------------------------
|
||||
attorney_id = fields.Many2one(
|
||||
"res.users",
|
||||
string="Responsible Attorney",
|
||||
tracking=True,
|
||||
)
|
||||
paralegal_id = fields.Many2one(
|
||||
"res.users",
|
||||
string="Paralegal",
|
||||
tracking=True,
|
||||
)
|
||||
|
||||
# --- Representation (drives the subpoena workflow in a later step) ------
|
||||
representation = fields.Selection(
|
||||
selection=[
|
||||
("attorney", "Attorney of Record"),
|
||||
("pro_se", "Pro Se (self-represented)"),
|
||||
],
|
||||
string="Representation",
|
||||
default="attorney",
|
||||
required=True,
|
||||
tracking=True,
|
||||
help="Pro-se matters route subpoena issuance through the clerk of court; "
|
||||
"attorney-of-record matters issue directly. See Forms & Playbook, Part C.",
|
||||
)
|
||||
|
||||
# --- Gates / status -----------------------------------------------------
|
||||
conflict_check_cleared = fields.Boolean(
|
||||
string="Conflict Check Cleared",
|
||||
readonly=True,
|
||||
copy=False,
|
||||
tracking=True,
|
||||
help="Set by an attorney once the conflict check is documented and clear. "
|
||||
"Required before the matter can be engaged.",
|
||||
)
|
||||
state = fields.Selection(
|
||||
selection=[
|
||||
("intake", "Intake"),
|
||||
("engaged", "Engaged"),
|
||||
("disclosure", "Mandatory Disclosure"),
|
||||
("discovery", "Discovery"),
|
||||
("mediation", "Mediation"),
|
||||
("hearing", "Hearing / Trial"),
|
||||
("closed", "Closed"),
|
||||
],
|
||||
string="Stage",
|
||||
default="intake",
|
||||
required=True,
|
||||
copy=False,
|
||||
tracking=True,
|
||||
)
|
||||
|
||||
date_opened = fields.Date(
|
||||
string="Date Opened",
|
||||
default=fields.Date.context_today,
|
||||
)
|
||||
active = fields.Boolean(default=True)
|
||||
|
||||
# --- Internal helpers ---------------------------------------------------
|
||||
def _ensure_attorney(self):
|
||||
"""Raise unless the acting user is in the attorney group."""
|
||||
if not self.env.user.has_group(ATTORNEY_GROUP):
|
||||
raise UserError(
|
||||
_("Only a licensed attorney (Family Law / Attorney group) may "
|
||||
"perform this action.")
|
||||
)
|
||||
|
||||
def _require_state(self, allowed):
|
||||
"""Raise if any record is not in one of the allowed states."""
|
||||
bad = self.filtered(lambda c: c.state not in allowed)
|
||||
if bad:
|
||||
raise UserError(
|
||||
_("This action is not allowed from the current stage (%(states)s). "
|
||||
"Allowed from: %(allowed)s.",
|
||||
states=", ".join(sorted(set(bad.mapped("state")))),
|
||||
allowed=", ".join(allowed))
|
||||
)
|
||||
|
||||
def _advance_to(self, target):
|
||||
"""Write the new state and log it on the chatter."""
|
||||
for case in self:
|
||||
case.state = target
|
||||
case.message_post(
|
||||
body=_("Stage changed to: %s") % dict(
|
||||
self._fields["state"].selection).get(target, target)
|
||||
)
|
||||
|
||||
# --- Gated transitions --------------------------------------------------
|
||||
def action_mark_conflict_cleared(self):
|
||||
"""Attorney-only: record that the conflict check is clear."""
|
||||
self._ensure_attorney()
|
||||
for case in self:
|
||||
if case.conflict_check_cleared:
|
||||
continue
|
||||
case.conflict_check_cleared = True
|
||||
case.message_post(body=_("Conflict check cleared by %s.")
|
||||
% self.env.user.name)
|
||||
return True
|
||||
|
||||
def action_engage(self):
|
||||
"""intake -> engaged. Requires a cleared conflict check."""
|
||||
self._require_state(["intake"])
|
||||
not_cleared = self.filtered(lambda c: not c.conflict_check_cleared)
|
||||
if not_cleared:
|
||||
raise UserError(
|
||||
_("Cannot engage a matter before the conflict check is cleared. "
|
||||
"An attorney must clear it first.")
|
||||
)
|
||||
self._advance_to("engaged")
|
||||
return True
|
||||
|
||||
def action_start_disclosure(self):
|
||||
"""engaged -> disclosure (Rule 12.285 phase begins in a later step)."""
|
||||
self._require_state(["engaged"])
|
||||
self._advance_to("disclosure")
|
||||
return True
|
||||
|
||||
def action_start_discovery(self):
|
||||
"""disclosure -> discovery."""
|
||||
self._require_state(["disclosure"])
|
||||
self._advance_to("discovery")
|
||||
return True
|
||||
|
||||
def action_start_mediation(self):
|
||||
"""discovery -> mediation (mandatory in Miami-Dade before final hearing)."""
|
||||
self._require_state(["discovery"])
|
||||
self._advance_to("mediation")
|
||||
return True
|
||||
|
||||
def action_set_hearing(self):
|
||||
"""mediation -> hearing / trial."""
|
||||
self._require_state(["mediation"])
|
||||
self._advance_to("hearing")
|
||||
return True
|
||||
|
||||
def action_close(self):
|
||||
"""Attorney-only: close the matter from any non-closed stage."""
|
||||
self._ensure_attorney()
|
||||
self._require_state([s for s in STATE_SEQUENCE if s != "closed"])
|
||||
self._advance_to("closed")
|
||||
return True
|
||||
|
||||
def action_reopen(self):
|
||||
"""Attorney-only: reopen a closed matter back to engaged."""
|
||||
self._ensure_attorney()
|
||||
self._require_state(["closed"])
|
||||
self._advance_to("engaged")
|
||||
return True
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Application category -->
|
||||
<record id="module_category_familylaw" model="ir.module.category">
|
||||
<field name="name">Family Law</field>
|
||||
<field name="description">Access rights for the Active Blue Family Law platform.</field>
|
||||
<field name="sequence">20</field>
|
||||
</record>
|
||||
|
||||
<!-- Staff / paralegal: day-to-day work, no attorney-only gates -->
|
||||
<record id="group_familylaw_user" model="res.groups">
|
||||
<field name="name">Family Law / Staff</field>
|
||||
<field name="category_id" ref="module_category_familylaw"/>
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<!-- Attorney: everything staff can do, plus the gated actions
|
||||
(conflict clearance, approvals, filing, closing). Implies staff. -->
|
||||
<record id="group_familylaw_attorney" model="res.groups">
|
||||
<field name="name">Family Law / Attorney</field>
|
||||
<field name="category_id" ref="module_category_familylaw"/>
|
||||
<field name="implied_ids" eval="[(4, ref('group_familylaw_user'))]"/>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_familylaw_case_user,familylaw.case staff,model_familylaw_case,group_familylaw_user,1,1,1,0
|
||||
access_familylaw_case_attorney,familylaw.case attorney,model_familylaw_case,group_familylaw_attorney,1,1,1,1
|
||||
|
@@ -0,0 +1 @@
|
||||
from . import test_case_lifecycle
|
||||
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""STEP 1 tests — case lifecycle state machine + attorney-only gates.
|
||||
|
||||
Run just this step:
|
||||
odoo -d <db> -i activeblue_familylaw --test-enable --test-tags familylaw_step1 --stop-after-init
|
||||
|
||||
The tests prove the verifiable behaviour for Step 1:
|
||||
* a new case starts in 'intake' with no conflict clearance;
|
||||
* a matter cannot be engaged before an attorney clears the conflict;
|
||||
* only an attorney can clear the conflict / close the case;
|
||||
* illegal (skipping) transitions are rejected;
|
||||
* the full forward path works end to end.
|
||||
"""
|
||||
|
||||
from odoo.tests.common import TransactionCase, new_test_user, tagged
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install", "familylaw", "familylaw_step1")
|
||||
class TestCaseLifecycle(TransactionCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.partner = cls.env["res.partner"].create({"name": "Client A"})
|
||||
|
||||
# An attorney and a paralegal, each in the right group.
|
||||
cls.attorney = new_test_user(
|
||||
cls.env,
|
||||
login="fl_attorney",
|
||||
name="Test Attorney",
|
||||
email="attorney@example.com",
|
||||
groups="base.group_user,activeblue_familylaw.group_familylaw_attorney",
|
||||
)
|
||||
cls.paralegal = new_test_user(
|
||||
cls.env,
|
||||
login="fl_paralegal",
|
||||
name="Test Paralegal",
|
||||
email="paralegal@example.com",
|
||||
groups="base.group_user,activeblue_familylaw.group_familylaw_user",
|
||||
)
|
||||
|
||||
cls.Case = cls.env["familylaw.case"]
|
||||
cls.case = cls.Case.create({
|
||||
"name": "In re the Marriage of Client A",
|
||||
"client_id": cls.partner.id,
|
||||
"case_type": "support_modification",
|
||||
"attorney_id": cls.attorney.id,
|
||||
"paralegal_id": cls.paralegal.id,
|
||||
})
|
||||
|
||||
# --- defaults -----------------------------------------------------------
|
||||
def test_01_initial_state(self):
|
||||
self.assertEqual(self.case.state, "intake")
|
||||
self.assertFalse(self.case.conflict_check_cleared)
|
||||
self.assertEqual(self.case.representation, "attorney")
|
||||
|
||||
# --- conflict-clearance gate -------------------------------------------
|
||||
def test_02_engage_blocked_without_clearance(self):
|
||||
with self.assertRaises(UserError):
|
||||
self.case.action_engage()
|
||||
self.assertEqual(self.case.state, "intake")
|
||||
|
||||
def test_03_clearance_requires_attorney(self):
|
||||
with self.assertRaises(UserError):
|
||||
self.case.with_user(self.paralegal).action_mark_conflict_cleared()
|
||||
self.assertFalse(self.case.conflict_check_cleared)
|
||||
|
||||
def test_04_attorney_clears_conflict(self):
|
||||
self.case.with_user(self.attorney).action_mark_conflict_cleared()
|
||||
self.assertTrue(self.case.conflict_check_cleared)
|
||||
|
||||
def test_05_engage_after_clearance(self):
|
||||
self.case.with_user(self.attorney).action_mark_conflict_cleared()
|
||||
self.case.action_engage()
|
||||
self.assertEqual(self.case.state, "engaged")
|
||||
|
||||
# --- transition guards --------------------------------------------------
|
||||
def test_06_illegal_transition_blocked(self):
|
||||
# cannot jump straight from intake to discovery
|
||||
with self.assertRaises(UserError):
|
||||
self.case.action_start_discovery()
|
||||
self.assertEqual(self.case.state, "intake")
|
||||
|
||||
def test_07_full_forward_path(self):
|
||||
self.case.with_user(self.attorney).action_mark_conflict_cleared()
|
||||
self.case.action_engage()
|
||||
self.assertEqual(self.case.state, "engaged")
|
||||
self.case.action_start_disclosure()
|
||||
self.assertEqual(self.case.state, "disclosure")
|
||||
self.case.action_start_discovery()
|
||||
self.assertEqual(self.case.state, "discovery")
|
||||
self.case.action_start_mediation()
|
||||
self.assertEqual(self.case.state, "mediation")
|
||||
self.case.action_set_hearing()
|
||||
self.assertEqual(self.case.state, "hearing")
|
||||
self.case.with_user(self.attorney).action_close()
|
||||
self.assertEqual(self.case.state, "closed")
|
||||
|
||||
# --- closing / reopening gate ------------------------------------------
|
||||
def test_08_close_requires_attorney(self):
|
||||
with self.assertRaises(UserError):
|
||||
self.case.with_user(self.paralegal).action_close()
|
||||
self.assertNotEqual(self.case.state, "closed")
|
||||
|
||||
def test_09_reopen_requires_attorney_and_closed_state(self):
|
||||
# reopen only valid from 'closed'
|
||||
with self.assertRaises(UserError):
|
||||
self.case.action_reopen()
|
||||
# close then reopen as attorney
|
||||
self.case.with_user(self.attorney).action_mark_conflict_cleared()
|
||||
self.case.with_user(self.attorney).action_close()
|
||||
self.assertEqual(self.case.state, "closed")
|
||||
self.case.with_user(self.attorney).action_reopen()
|
||||
self.assertEqual(self.case.state, "engaged")
|
||||
|
||||
# --- audit trail (mail.thread tracking) --------------------------------
|
||||
def test_10_state_change_is_logged(self):
|
||||
before = len(self.case.message_ids)
|
||||
self.case.with_user(self.attorney).action_mark_conflict_cleared()
|
||||
self.case.action_engage()
|
||||
self.assertGreater(
|
||||
len(self.case.message_ids), before,
|
||||
"Stage changes and conflict clearance should post to the chatter "
|
||||
"(the audit trail).",
|
||||
)
|
||||
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- LIST (Odoo 18 uses <list>, not <tree>) -->
|
||||
<record id="view_familylaw_case_list" model="ir.ui.view">
|
||||
<field name="name">familylaw.case.list</field>
|
||||
<field name="model">familylaw.case</field>
|
||||
<field name="arch" type="xml">
|
||||
<list string="Cases">
|
||||
<field name="name"/>
|
||||
<field name="client_id"/>
|
||||
<field name="case_type"/>
|
||||
<field name="attorney_id"/>
|
||||
<field name="representation"/>
|
||||
<field name="conflict_check_cleared"/>
|
||||
<field name="state" widget="badge"
|
||||
decoration-success="state == 'closed'"
|
||||
decoration-info="state in ('intake','engaged')"
|
||||
decoration-warning="state in ('disclosure','discovery','mediation','hearing')"/>
|
||||
</list>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- FORM -->
|
||||
<record id="view_familylaw_case_form" model="ir.ui.view">
|
||||
<field name="name">familylaw.case.form</field>
|
||||
<field name="model">familylaw.case</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Case">
|
||||
<header>
|
||||
<!-- Attorney-only gate: clear the conflict check -->
|
||||
<button name="action_mark_conflict_cleared" type="object"
|
||||
string="Clear Conflict Check" class="btn-primary"
|
||||
invisible="conflict_check_cleared"
|
||||
groups="activeblue_familylaw.group_familylaw_attorney"/>
|
||||
<!-- Forward transitions (visible only from the valid stage) -->
|
||||
<button name="action_engage" type="object" string="Engage"
|
||||
class="btn-primary" invisible="state != 'intake'"/>
|
||||
<button name="action_start_disclosure" type="object"
|
||||
string="Start Disclosure" invisible="state != 'engaged'"/>
|
||||
<button name="action_start_discovery" type="object"
|
||||
string="Start Discovery" invisible="state != 'disclosure'"/>
|
||||
<button name="action_start_mediation" type="object"
|
||||
string="Start Mediation" invisible="state != 'discovery'"/>
|
||||
<button name="action_set_hearing" type="object"
|
||||
string="Set for Hearing" invisible="state != 'mediation'"/>
|
||||
<!-- Attorney-only: close / reopen -->
|
||||
<button name="action_close" type="object" string="Close Case"
|
||||
invisible="state == 'closed'"
|
||||
groups="activeblue_familylaw.group_familylaw_attorney"/>
|
||||
<button name="action_reopen" type="object" string="Reopen"
|
||||
invisible="state != 'closed'"
|
||||
groups="activeblue_familylaw.group_familylaw_attorney"/>
|
||||
<field name="state" widget="statusbar"
|
||||
statusbar_visible="intake,engaged,disclosure,discovery,mediation,hearing,closed"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="e.g. In re the Marriage of Client A"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group string="Matter">
|
||||
<field name="client_id"/>
|
||||
<field name="case_type"/>
|
||||
<field name="representation"/>
|
||||
<field name="date_opened"/>
|
||||
</group>
|
||||
<group string="Team & Status">
|
||||
<field name="attorney_id"/>
|
||||
<field name="paralegal_id"/>
|
||||
<field name="conflict_check_cleared" readonly="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</sheet>
|
||||
<!-- Audit trail. Odoo 18 also offers the shorthand <chatter/> tag;
|
||||
this explicit form is used for maximum cross-release safety. -->
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="activity_ids"/>
|
||||
<field name="message_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- SEARCH -->
|
||||
<record id="view_familylaw_case_search" model="ir.ui.view">
|
||||
<field name="name">familylaw.case.search</field>
|
||||
<field name="model">familylaw.case</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Cases">
|
||||
<field name="name"/>
|
||||
<field name="client_id"/>
|
||||
<field name="attorney_id"/>
|
||||
<filter name="my_cases" string="My Cases"
|
||||
domain="[('attorney_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<filter name="open_cases" string="Open"
|
||||
domain="[('state', '!=', 'closed')]"/>
|
||||
<filter name="needs_conflict_clearance" string="Awaiting Conflict Clearance"
|
||||
domain="[('conflict_check_cleared', '=', False), ('state', '=', 'intake')]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_state" string="Stage"
|
||||
context="{'group_by': 'state'}"/>
|
||||
<filter name="group_attorney" string="Attorney"
|
||||
context="{'group_by': 'attorney_id'}"/>
|
||||
<filter name="group_type" string="Case Type"
|
||||
context="{'group_by': 'case_type'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ACTION -->
|
||||
<record id="action_familylaw_case" model="ir.actions.act_window">
|
||||
<field name="name">Cases</field>
|
||||
<field name="res_model">familylaw.case</field>
|
||||
<field name="view_mode">list,form</field>
|
||||
<field name="search_view_id" ref="view_familylaw_case_search"/>
|
||||
<field name="context">{'search_default_open_cases': 1}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">Open your first matter</p>
|
||||
<p>Create a case to begin. New matters start in Intake; an attorney
|
||||
clears the conflict check, then the matter can be engaged.</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Top-level application menu -->
|
||||
<menuitem id="menu_familylaw_root"
|
||||
name="Family Law"
|
||||
sequence="50"/>
|
||||
|
||||
<!-- Cases -->
|
||||
<menuitem id="menu_familylaw_cases"
|
||||
name="Cases"
|
||||
parent="menu_familylaw_root"
|
||||
action="action_familylaw_case"
|
||||
sequence="10"/>
|
||||
|
||||
<!-- Configuration placeholder (populated in later steps) -->
|
||||
<menuitem id="menu_familylaw_config"
|
||||
name="Configuration"
|
||||
parent="menu_familylaw_root"
|
||||
sequence="90"
|
||||
groups="activeblue_familylaw.group_familylaw_attorney"/>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user