gabriel / muse public
Open #73 Enhancement
filed by gabriel human · 19 days ago

Legal Contracts Domain — implementation plan (TDD-first, comprehensive)

0 Anchors
Blast radius
Churn 30d
0 Proposals

Background

Muse treats "domain" as a first-class primitive (muse/domain.py::MuseDomainPlugin). A plugin implements six methods — snapshot, diff, merge, drift, apply, schema — and gets the full VCS engine free: commit DAG, branching, checkout, lineage, log graph, merge-base finder. The CAD (#66), 3D Scenes (#67), Video Timelines (#68), Research Papers (#69), Biological Pathways (#70), Datasets (#71), and Knowledge Graphs (#72) plans are proving the model across geometry, spatial hierarchy, temporal edits, scholarly argument, biological/general graphs, and tabular data.

Legal contracts are the tenth shape of problem, and the one whose core operation already has a name the legal profession invented independently: redlining. A contract is parties bound by obligations and rights, expressed through defined terms and clauses, subject to conditions and deadlines, negotiated across multiple rounds of concurrent counter-proposals from different parties' counsel — which is exactly the three-way merge problem this domain plugin architecture already solves for code. Today contract negotiation happens in Word documents with track-changes (word-level, meaning-blind — a redline shows that text changed, never what obligation changed) or PDF exports (fully opaque once signed). If Muse can version a contract the way it versions code — diffing obligations and defined-term references, not paragraphs; merging two counsel's concurrent redlines by clause, not by line; validating that every defined term is used and every cross-reference resolves — it proves the domain-plugin model generalizes to normative, obligation- bearing legal text, the closest structural analog yet to the Research Papers plan's claim/evidence model, but applied to enforceable commitments instead of scientific assertions. The goal is not to version contract files. It is to version legal meaning, obligations, negotiation state, provenance, and enforceable agreement structure.

This issue is the plan only. Each numbered phase in §11 becomes its own staging issue once reviewed and accepted.

Goal

Ship a muse/plugins/contract/ domain plugin, structured like muse/plugins/midi/ and the CAD/3D-Scenes/Timeline/Paper/Pathway/Dataset/KG plans, that:

  • Registers in muse domains --json alongside code, midi, identity, mist, social, and (once landed) cad/scene3d/timeline/paper/pathway/ dataset/kg.
  • Passes muse code test --json for every module it touches.
  • Snapshots, diffs, and merges a contract with clause/obligation/defined-term-level semantic awareness — never as an opaque DOCX/PDF blob, and never limited to Word's word-level track-changes model.
  • Supports a query DSL (muse contract query "...") answering the examples in §6.
  • Detects the drift/validation classes in §7 via muse status/muse check.
  • Has test coverage per §8, with test IDs (LEG_01, LEG_02, …) referenced from both this plan and the tests that satisfy them.

"Done" for the plan means: reviewed, decomposed into §11's breakdown, with acceptance criteria concrete enough for a different agent to implement test-first.


1. Domain Scope

Supported initial contract types

Bilateral and multilateral commercial agreements with standard structure — NDAs, MSAs, SOWs, licensing agreements, employment agreements — single-document contracts with defined terms, numbered clauses, and a signature block. v0 targets contracts in the tens-of-pages range with hundreds, not thousands, of defined terms/clauses. Multi-document master-agreement-plus-schedules structures are in scope for cross- reference modeling (§2) but full schedule-level semantic diffing is deferred.

Two-layer strategy, consistent with every prior plan, adapted for a domain with no existing open interchange standard as mature as glTF/SBML/OTIO:

  1. Canonical semantic layer (Muse-owned): a JSON-serializable contract IR (§2) — parties, defined terms, clauses, obligations, and cross-references as addressable elements, not paragraph text. Muse snapshots, diffs, merges, and queries this directly.
  2. Interchange boundary: DOCX with tracked changes as the primary v0 authoring/negotiation format, since it is where real-world contract negotiation actually happens — importing DOCX's own revision/comment XML (via python-docx plus OOXML's w:ins/w:del tracked-change markup) lets Muse ingest an existing redline round as a redline, not just as final text. Markdown is a secondary authoring format for born-digital, lawyer-as-engineer contracts (increasingly common for developer-facing ToS/DPA templates). PDF is import-only and lossy (final signed contracts are almost always PDF, with no further authoring expected) — flagged as lossy import (§7), never treated as equivalent to a DOCX/Markdown-sourced snapshot. No existing structured legal- document standard (Akoma Ntoso/LegalDocML is the closest, built for legislation rather than commercial contracts) is mature enough as a v0 primary target, so v0 does not adopt one — Akoma Ntoso export is named as a v1+ interop target (§10) once the canonical IR is proven, not attempted now.

Relationship to PDF, DOCX, Markdown, plain-text, and CLM exports

Format/tool Role
DOCX (with tracked changes) v0 primary interchange format — the only format among these that natively encodes what this domain most needs to ingest faithfully: an in-progress redline round, not just final text.
PDF Import-only, lossy fallback (§1, above) — text and layout extracted, clause/obligation structure inferred by heading/numbering heuristics, never guaranteed accurate; the near-universal format for executed (signed, final) contracts, where no further authoring is expected.
Markdown Secondary authoring format for born-digital contracts — direct Markdown→IR path (headings → Clause, a definitions block → DefinedTerms, no DOCX intermediate needed).
Plain text Import-only, weakest-fidelity fallback — no structure to infer beyond regex-based heading/numbering detection; useful as a last-resort adapter and a stress-test fixture for §7's validation gates, not a format anyone should author in going forward.
CLM exports (Ironclad, DocuSign CLM, ContractPodAi, etc.) Not a single format — each CLM platform exports its own JSON/XML schema plus a rendered DOCX/PDF of the actual contract text. v0 treats a CLM export's rendered document (usually DOCX or PDF) as the import source through the adapters above, and treats the platform's metadata (parties, effective date, contract type, approval status) as an optional metadata-only import into VersionMetadata/Party fields when present — CLM platforms are not treated as a fourth parallel document format, since their actual contract text still flows through DOCX/PDF/Markdown.

What is in scope for v0

  • Parties, their roles (e.g. discloser/recipient, licensor/licensee), and basic entity metadata (legal name, jurisdiction of incorporation).
  • Defined terms: capitalized terms with an explicit definition, and every place they're subsequently used — the domain's most legally load-bearing referential structure (an undefined or unused defined term is a real drafting defect, not a stylistic nit).
  • Clauses/sections in a numbered hierarchy, with stable identity independent of their current number (§3) — the single most important identity problem this domain shares with the Research Papers plan's section-pinning problem, but with higher stakes, since legal cross-references ("as defined in Section 5.2") break silently and dangerously if renumbering isn't tracked correctly.
  • Obligations and rights as explicit, extracted elements distinct from the clause text that expresses them — "Party A shall deliver X by date Y" is both prose and a structured obligation with a subject, an action, and a deadline (§2).
  • Conditions and deadlines/terms (contract duration, renewal, notice periods) as addressable, queryable elements.
  • Cross-references between clauses/defined terms, preserved as an explicit graph (not re-parsed from prose at query time), mirroring the reference-graph- preservation principle from the Research Papers and Knowledge Graphs plans.
  • Amendments and redlines as first-class, versioned lifecycle events — an amendment is a structured, attributed delta against a prior executed version, not just a new document that happens to look similar.
  • Basic lifecycle state: draftunder_negotiationexecutedamended | terminated | expired — modeled explicitly (§2), since this is the one domain plan so far where the artifact's own lifecycle stage is itself first-class committed metadata, not just a repo-level convention.

What is explicitly out of scope for v0

  • Full NLP-based obligation/right extraction with legal-entailment-level accuracy — v0's obligation extraction is structurally heuristic (modal-verb cues like "shall"/"must"/"may," subject/deadline proximity), flagged with an extraction- confidence signal, never presented as an authoritative legal reading. Mirrors the Research Papers plan's explicit stance on heuristic, non-authoritative claim extraction.
  • Automated legal-conflict detection ("does clause 5 contradict clause 12") beyond structurally-detectable cases (e.g. two clauses assigning the same deadline to incompatible obligations) — deep semantic contradiction detection requires legal reasoning this plan does not attempt to build; named as a future extension (§10).
  • Jurisdiction-specific legal validity/enforceability checking (is this clause enforceable under California law) — this domain models structure and obligations, not legal advice; explicitly, permanently out of scope, not just deferred.
  • E-signature execution and identity verification (DocuSign/Adobe Sign-style signing workflows) — this domain records that a signature block exists and whether it's populated (§2, §7), but does not implement or replace an e- signature platform.
  • Multi-jurisdiction contract translation/localization — a contract in one language is one dataset; cross-language same-contract alignment is out of scope for v0.
  • Full CLM platform feature parity (approval workflows, e-signature integration, contract repository search across thousands of contracts as a compliance tool) — this domain versions one contract's semantic structure and history; a CLM- style cross-contract portfolio view is a named future direction (§10), reached the same way every prior plan's cross-repo search is reached, not built as a first-class v0 feature.

2. Canonical Model

All elements are content-addressed (sha256:<hex>) and referenced by ID, never positional index — same identity discipline as every prior plan — so renumbering a clause or reordering party listings never produces a spurious diff.

Element Fields Notes
Contract id, title, parties: [Party.id], defined_terms: [DefinedTerm.id], clauses: [Clause.id] (ordered — see §3 pinning), lifecycle_state (draft|under_negotiation|executed|amended|terminated|expired), effective_date \| null, governing_law \| null, metadata The top-level container; lifecycle_state is committed, versioned data, not a repo-level convention.
Party id, legal_name, role (disclosing_party|receiving_party|licensor|licensee|custom), jurisdiction \| null, signature_ref: SignatureBlock.id \| null
DefinedTerm id, term (the capitalized phrase, e.g. "Confidential Information"), definition_ref: Clause.id (where it's defined), usage_refs: [Clause.id] (every clause that references it), synonyms: [string] The domain's most legally load-bearing element — usage_refs vs. definition_ref being empty each represent a distinct, real defect (§7).
Clause id, heading \| null, number \| null (current display numbering — not identity, §3), level (nesting depth), parent_ref: Clause.id \| null, text, defined_term_refs: [DefinedTerm.id] (referenced, ordered by appearance), obligation_refs: [Obligation.id], right_refs: [Right.id], condition_refs: [Condition.id] Structurally close to the Research Papers plan's Section/Paragraph, but flatter — v0 does not split clause text into sub-paragraph units the way that plan splits sections into paragraphs, since clause-level granularity is the domain's natural review unit ("redline this clause," not "redline this sentence").
Obligation id, obligor_ref: Party.id, obligee_ref: Party.id \| null, action (extracted, heuristic — see §1), deadline_ref: Deadline.id \| null, condition_refs: [Condition.id], clause_ref: Clause.id, extraction_confidence (explicit|inferred) explicit when the clause uses an unambiguous obligation modal ("shall"); inferred for weaker heuristic matches — never silently presented as equally confident.
Right id, holder_ref: Party.id, description, clause_ref: Clause.id, exercisable_condition_refs: [Condition.id] E.g. a termination right, an audit right — distinct from Obligation (someone may do something vs. someone must).
Condition id, description, clause_ref: Clause.id, kind (precedent|concurrent|subsequent) Conditions gate obligations/rights — modeled once, referenced by both, avoiding duplicate condition text scattered across obligation/right definitions.
Deadline id, kind (fixed_date|relative_period|event_triggered), value (a date, a duration, or a reference to a triggering event/clause), clause_ref: Clause.id relative_period/event_triggered deadlines are not resolved to an absolute date at snapshot time (that requires knowing when the triggering event occurs) — they're stored as their own declared structure, resolved only at query time when context is available (§6).
CrossReference id, from_clause_ref: Clause.id, to_clause_ref: Clause.id \| DefinedTerm.id, resolved: bool The explicit, preserved reference graph (§1) — resolved tracks whether the target still exists, powering §7's broken-cross-reference check.
SignatureBlock id, party_ref: Party.id, signed: bool, signed_date \| null, signatory_name \| null
Redline id, author_ref: Party.id \| string, clause_ref: Clause.id, change_kind (insertion|deletion|replacement|comment), content, round (an integer negotiation-round counter), status (proposed|accepted|rejected) A structured, attributed redline — imported from DOCX tracked-changes (§1) into this element rather than left as opaque OOXML markup, so a redline round is itself diffable/queryable content, not just a rendering artifact.
Amendment id, amends_clause_refs: [Clause.id], effective_date, description, executed_by: [SignatureBlock.id] A lifecycle event distinct from an ordinary commit — an amendment is itself a legally meaningful artifact with its own execution/signature requirement, modeled explicitly rather than left implicit in commit history.
VersionMetadata curator \| null, source_format (docx|markdown|pdf|plaintext), source_checksum, clm_platform_hint \| null, schema_version

Design invariant carried over from every prior plan: identity is content- and reference-based, never positional. Clause numbering is display metadata, never identity (§3) — renumbering an entire contract (a routine drafting operation when a clause is inserted/removed) must never itself produce a diff.


3. Snapshot Design

Deterministic document normalization

snapshot() walks the live state (a DOCX/Markdown document under state/, same "walk the format, produce the canonical IR" pattern as every prior plan) and produces the canonical IR as the SnapshotManifest:

  1. Resolve every element to a stable ID (below).
  2. Canonicalize clause text (whitespace/line-wrap normalized to a single logical string — a Word reflow is never semantic content, same principle the Research Papers plan applies to paragraph normalization).
  3. Canonicalize ordering: Clause.parent_ref/nesting preserves authored structure (semantically meaningful — clause hierarchy determines scope); defined_terms/ parties lists sorted by ID for serialization (listing order in a definitions block is cosmetic, not semantic).
  4. Extract Obligation/Right/Condition/Deadline heuristically from clause text (§1) and record extraction_confidence on every extracted Obligation.

Stable identity for clauses and defined terms

  • Clause identity is pinned the same way the Research Papers plan pins Section identity: provisionally content-derived (from heading + parent identity + a fuzzy-hash of text) at first snapshot, then explicitly carried forward across subsequent snapshots via matching against the previous snapshot's clauses, reassigned only when matching confidence is too low to reasonably carry forward (a genuine clause split/merge/rewrite). This is the load-bearing fix that makes clause renumbering — which happens on essentially every substantive edit to a numbered contract — never itself produce a diff.
  • DefinedTerm identity is derived from the term text itself (term, case- normalized) — two clauses defining "Confidential Information" identically are the same defined term by construction; a term whose definition text changes while the term name stays the same is a content change (§4), not an identity change.
  • Redline identity is derived from (author_ref, clause_ref, change_kind, round) plus a content hash — stable across re-import of the same DOCX tracked- changes revision, so re-snapshotting an unchanged redline round doesn't spuriously re-identify every proposed change.

Content-addressed schedules and exhibits

Schedules/exhibits (referenced attachments, e.g. a pricing schedule) are treated as CrossReference targets pointing at an external or content-addressed sub-document (§1's multi-document scope note) — full semantic modeling of schedule content is deferred, but the reference to a schedule and whether it resolves is tracked now, consistent with every prior plan's external-reference discipline.

Citation/reference graph preservation

CrossReference and DefinedTerm.usage_refs graphs are preserved as explicit snapshot data, not re-derived from prose at query time — the same "snapshot-time graph, not query-time inference" principle the Research Papers and Knowledge Graphs plans apply to their respective reference graphs, enabling §6's cross-reference and defined-term-usage queries to be direct lookups over committed data.

Deterministic serialization

DOCX's own OOXML round-trips are not guaranteed byte-stable across Word versions (track-changes XML in particular varies), and Markdown reflow is not canonical text — Muse never hashes DOCX/Markdown bytes directly for content-addressing; it always re-serializes through the canonical IR's fixed field order and ID scheme (§2), the same discipline as every prior plan's "never hash the interchange format's bytes directly" rule. A golden-snapshot suite (§8) locks this down.


4. Semantic Diff

diff(base, target, *, repo_root=None) returns a StructuredDelta, same contract as every prior plan — this is, in effect, semantic redlining: a diff that shows what obligation/right/deadline changed, not just what text changed.

  • Clause-level diffs: InsertOp/DeleteOp/ReplaceOp keyed on pinned clause identity (§3); a heading-only change is a RenameOp distinct from text-content changes, same distinction the Research Papers plan draws for section renames.
  • Obligation changes: a change to Obligation.obligor_ref/deadline_ref/ action is reported as a changed obligation, distinct from a clause's surrounding prose changing without altering the extracted obligation itself — this is the single most valuable diff in the domain, since "the deadline in clause 7 moved from 30 days to 60 days" is the actual negotiation-relevant fact, buried inside a paragraph a word-level diff would show as unhelpfully "changed."
  • Right changes: same treatment as obligations, applied to Right elements.
  • Defined-term changes: a DefinedTerm.definition_ref's text changing (the definition itself was reworded) is reported distinctly from a usage being added/removed (usage_refs gaining/losing a clause) — redefining a term and using it somewhere new are different kinds of change with different review weight.
  • Cross-reference changes: a CrossReference.to_clause_ref changing (a reference retargeted, e.g. because clause 5.2 became 5.3 and the reference was correctly updated) is reported distinctly from a reference becoming unresolved (resolved flipping to false, a drafting error) — same distinction every prior plan draws for external/internal reference state changes.
  • Party changes: Party add/remove/role-change reported explicitly, since a party addition/removal is almost always a substantively significant contract change (e.g. adding a guarantor), not a cosmetic edit.
  • Deadline/condition changes: field-level diffs on Deadline.value/ Condition.description, with relative_period/event_triggered deadline changes flagged distinctly from fixed_date changes, since the former's actual real-world impact depends on when the triggering event occurs (§2) — the diff can show the declared change but not necessarily its resolved real-world effect.
  • Amendment/redline diffs: an Amendment or Redline element's own fields changing (e.g. a redline's status flipping proposedaccepted) is reported as a negotiation-state change, distinct from the underlying clause content actually changing — accepting a redline and the clause text itself changing are related but separately reportable events.
  • Rename and move detection: per §3 — a clause moved to a different parent (e.g. promoted from a subsection to a top-level section during a restructuring redline) is a MoveOp, not delete+insert.

5. Merge Strategy

merge(base, left, right, *, repo_root=None) — three-way, merge_mode: three_way — and this is the domain plan where three-way merge maps most directly onto the domain's actual real-world workflow: two counsel's concurrent redlines on the same draft are a three-way merge problem, not an analogy for one.

  • Independent clause edits (the common case): edits to disjoint clauses merge automatically via the engine's default address-keyed map merge, driven by schema()'s dimensions (§9) — counsel A redlines the indemnification clause while counsel B redlines the termination clause.
  • Same-clause conflicts: both branches edit the same Clause.text differently — always a reported conflict (no auto-resolution of legal prose, consistent with every prior plan's rejection of silently picking a value neither author chose); using the Research Papers plan's edit-distance-based identity split, if the branches produced genuinely unrelated rewrites (not two edits of the same clause), both are kept as a non-conflicting insert rather than forced into a conflict — an explicit, tested boundary case (§8).
  • Conflicting obligations: both branches change the same Obligation's deadline_ref/obligor_ref differently — reported conflict with both proposed values shown in business terms (e.g. "30 days" vs. "60 days"), not just element IDs — the domain's most negotiation-relevant conflict class.
  • Defined-term conflicts: both branches redefine the same DefinedTerm differently — reported conflict (a genuine definitional disagreement); both branches independently adding new, different defined terms auto-merges (disjoint additions).
  • Cross-reference conflicts: both branches retarget the same CrossReference differently — conflict; a resolved flag change alone is not (mirrors every prior plan's state-change-vs-value-dispute distinction).
  • Party conflicts: both branches change the same Party's role/jurisdiction differently — conflict; both branches independently adding different new parties (e.g. adding different guarantors) is flagged as a review item, not a hard conflict, mirroring the Research Papers plan's concurrent-author-addition treatment, since there's no mechanically "correct" merged party list but it's not silent either.
  • Concurrent redline rounds: both branches contain Redline proposals against the same clause from the same negotiation round — auto-merges as two disjoint proposed redlines (both are visible, neither is silently dropped) unless their status is accepted on both branches with different resulting text, which escalates to a same-clause conflict (above) — this reflects the real workflow where multiple redline proposals can coexist until one is accepted.
  • Human-readable merge reports: every conflict carries both branches' values, the base value, and a plain-language cause string in contract-negotiation terms (e.g. "Both branches changed the payment deadline in Clause 4.2: left proposes 30 days, right proposes 60 days — base was 15 days"), consistent with the workspace-wide conflict-marker convention.

6. Query Support

A query DSL mirroring every prior plan's equivalent (muse contract query "<predicate>" --json), plus purpose-built subcommands scoped to contract review's actual workflow.

muse contract query "obligation.obligor == 'Acme Corp' and obligation.deadline < '2026-12-31'" --json
muse contract query "defined_term.usage_count == 0" --json
muse contract query "cross_reference.resolved == false" --json
  • Find all obligations of a party: muse contract obligations-of "Acme Corp" --json
  • Find all deadlines: muse contract deadlines --json / muse contract deadlines --before "2026-12-31" --json
  • Find undefined/orphaned terms: muse contract query "defined_term.usage_count == 0" --json (defined but never used) / muse contract undefined-terms --json (capitalized-looking term used but never defined — the more dangerous case, detected via a capitalization heuristic against the defined-terms list).
  • Find broken cross-references: muse contract query "cross_reference.resolved == false" --json / muse contract broken-refs --json
  • Find clauses referencing a right: muse contract query "clause.right_refs contains '<right_id>'" --json
  • Find termination rights: muse contract query "right.description contains 'terminate'" --json / muse contract termination-rights --json
  • Find indemnification clauses: muse contract query "clause.heading contains 'Indemnification' or clause.defined_term_refs contains 'Indemnified Party'" --json
  • Find pending redlines: muse contract query "redline.status == 'proposed'" --json / muse contract pending-redlines --json — the negotiation-tracking analog of a code review's "unresolved comments" view.
  • Find amendments affecting a clause: muse contract query "amendment.amends_clause_refs contains '<clause_id>'" --json
  • Traverse defined-term usage: muse contract term-usage "Confidential Information" --json — every clause that references a given defined term, the contract-domain analog of the Research Papers plan's citation traversal.
  • Cross-repo contract search: muse hub search contracts --party "Acme Corp" --clause-type indemnification --json, the same cross-repo search architecture every prior graph/argument-shaped plan (#69, #70, #71, #72) has required.

7. Validation and Drift Detection

Surfaces through muse status (via drift()) and muse check/muse code invariants, same pattern as every prior plan's _invariants.py.

  • Undefined term references: a capitalized term used in clause text that doesn't match any DefinedTerm.term (heuristically detected via capitalization pattern) — commit-blocking, since this is a genuine, common, and dangerous drafting defect (a term meant to carry a specific defined meaning that silently doesn't).
  • Orphaned defined terms: a DefinedTerm with usage_refs empty — flagged informational, not blocking (a defined-but-unused term is sloppy drafting, not necessarily invalid — sometimes intentional, e.g. terms defined for future amendments).
  • Broken cross-references: a CrossReference with resolved == false where the target was genuinely deleted (not just renumbered, since renumbering is handled by identity pinning, §3) — commit-blocking.
  • Missing signature blocks: a Contract.lifecycle_state == 'executed' with any Party.signature_ref unresolved or SignatureBlock.signed == false — commit- blocking, since an "executed" contract with missing signatures is a contradiction in the model's own terms.
  • Deadline inconsistencies: two Obligations with the same condition_refs but contradictory deadline_ref values (structurally detectable — not full legal-conflict detection, §1) — flagged, not necessarily blocking, since this needs human judgment about whether it's actually contradictory or just independently-scoped.
  • Governing-law/clause inconsistency: a structural check for clauses that declare a jurisdiction-specific mechanism inconsistent with Contract .governing_law (e.g. referencing a specific US state's UCC provisions while governing_law declares a different jurisdiction) — flagged informational, a narrow, cheaply-detectable case, not a substitute for legal review (§1).
  • Extraction-confidence gaps: an Obligation/Right with low extraction confidence clustered heavily in one clause — flagged informational, surfacing where the heuristic extraction (§1) is least trustworthy so a reviewer knows where to look more carefully, not because it's necessarily wrong.
  • Circular amendment references: an Amendment that (directly or transitively) amends a clause that was itself introduced by a later amendment — commit- blocking, a genuine temporal-logic error in the lifecycle model.
  • Non-deterministic imports: re-importing the same source (DOCX/Markdown) twice must produce identical canonical IR — hard-error regression gate, same treatment as every prior plan.
  • Schema migration risks: VersionMetadata.schema_version mismatches flagged before diff/merge across the boundary, never auto-migrated silently, consistent with the workspace-wide muse code migrate permission rule.

8. TDD Plan

Test IDs use the LEG_NN prefix, per the workspace convention (CAD_NN, SCN_NN, VID_NN, PAP_NN, BIO_NN, DAT_NN, KG_NN).

Tier Coverage Example test IDs
Unit Canonical model (de)serialization for every element type; clause identity pinning; defined-term identity (case-normalized); obligation extraction confidence tagging. LEG_01LEG_04
Golden snapshot Fixed fixtures (a short NDA with defined terms, an MSA with multiple obligations/deadlines, a contract with an active redline round, a multi-party agreement) snapshotted once, checked byte-for-byte against committed golden JSON. LEG_10LEG_13
Round-trip import DOCX (with tracked changes)→IR and Markdown→IR must reproduce input structure within fidelity ceiling and produce identical IR on re-import; PDF→IR must produce a valid, flagged-lossy import, never silently treated as high-fidelity. LEG_20LEG_22
Semantic diff One test per §4 category (clause, obligation, right, defined-term definition-vs-usage, cross-reference retarget-vs-broken, party, deadline/condition, amendment/redline negotiation-state). LEG_30LEG_38
Merge One test per §5 case, incl. the edit-distance-based non-conflict split, concurrent-redline auto-merge, and same-round-both-accepted-different-text escalation. LEG_50LEG_58
Obligation/cross-reference graph tests Defined-term usage traversal and cross-reference resolution correctness against a fixture with a known expected graph. LEG_60, LEG_61
Query engine One test per remaining §6 example (obligations-of, undefined-terms, broken-refs, pending-redlines, term-usage). LEG_70LEG_74
Property-based Randomized clause-renumbering generation asserting identity pinning never spuriously diffs on pure renumbering; randomized obligation-deadline generation asserting the deadline-inconsistency check fires exactly on genuinely contradictory pairs. LEG_80, LEG_81
Validation/drift One test per §7 bullet (undefined-term blocking, orphaned-term informational, missing-signature blocking on executed state, circular-amendment blocking, non-deterministic import, schema mismatch). LEG_90LEG_95

Fixture strategy using representative contracts

Fixtures use real-world-shaped, non-confidential template contracts (a standard mutual NDA template, a simple SOW/services agreement template, a short licensing agreement) — real drafting conventions (defined-term capitalization style, section- numbering schemes, boilerplate structure) are exactly what §3's identity pinning and §7's validation need to handle, same "realistic tool output" reasoning as every prior plan. A minimal library: a short NDA with 5–10 defined terms (baseline case); an MSA with several dated/conditional obligations (obligation-extraction stress test); a contract with a deliberately introduced redline round exported from a real Word tracked-changes session (DOCX import fidelity test); a multi-party agreement (party-conflict merge test); a contract with a deliberately undefined capitalized term and a deliberately broken cross-reference (validation-gate tests); a renumbered version of the baseline NDA (identity-pinning regression test). Property-based tests use synthetic clause/obligation generators, not the fixture library, for systematic renumbering and deadline-conflict coverage.


9. Backend Integration

Domain plugin implementation

muse/plugins/contract/ following the muse/plugins/midi/ layout:

muse/plugins/contract/
  __init__.py
  plugin.py             # snapshot/diff/merge/drift/apply/schema
  entity.py             # Canonical model dataclasses (§2)
  manifest.py           # SnapshotManifest (de)serialization, normalization (§3)
  contract_diff.py       # Diff algorithms (§4)
  contract_merge.py       # Merge algorithms (§5)
  extraction.py           # Heuristic obligation/right/deadline/term extraction (§1)
  _query.py              # Query DSL (§6)
  _invariants.py         # Validation/drift checks (§7)
  _import_docx.py         # DOCX (incl. tracked changes) <-> IR adapter
  _import_markdown.py     # Markdown <-> IR direct path
  _import_pdf.py           # PDF -> IR lossy fallback (import-only)

schema() declares (mirroring every prior plan's domains --json shape):

{
  "schema_version": "<muse_version>",
  "merge_mode": "three_way",
  "description": "Semantic version control for legal contracts...",
  "dimensions": [
    {"name": "structure", "description": "Clauses, hierarchy, and parties."},
    {"name": "definitions", "description": "Defined terms and their usage graph."},
    {"name": "obligations", "description": "Obligations, rights, conditions, and deadlines."},
    {"name": "references", "description": "Cross-references between clauses and terms."},
    {"name": "negotiation", "description": "Redlines, negotiation rounds, and their status."},
    {"name": "lifecycle", "description": "Amendments, signatures, and contract lifecycle state."},
    {"name": "metadata", "description": "Source format, curator, schema version."}
  ]
}

Storage implications

Snapshots are small, structured document data — no large binary payloads beyond the original DOCX/PDF source itself, which is treated as an external reference (mirrors the Video Timelines/Datasets plans' external-reference discipline for their large source artifacts), not stored bytes-for-bytes in .muse/objects/. muse count-objects/gc/prune need no contract-specific changes.

API endpoints needed (MuseHub)

  • GET /:owner/:repo/contract/:ref/structure — clause/party/defined-term listing at a ref.
  • GET /:owner/:repo/contract/:ref/diff?base=&target= — structured semantic- redline diff for proposal review rendering.
  • GET /:owner/:repo/contract/:ref/obligations?party= — obligation listing, backing §6's CLI commands for UI use.
  • GET /hub/search/contracts?party=&clause_type= — cross-repo search endpoint (§6), same architectural pattern every prior graph/argument-shaped plan required.

CLI implications

New muse contract subcommand group: muse contract query, muse contract obligations-of, muse contract deadlines, muse contract undefined-terms, muse contract broken-refs, muse contract pending-redlines, muse contract term-usage, muse contract termination-rights. All accept --json.

MuseHub UI implications

  • Proposal/diff view needs a semantic redline renderer: rendered contract prose (not raw DOCX) with changed obligations/rights/deadlines highlighted inline distinctly from ordinary prose edits, a pending-redlines panel showing proposed-but-not-yet-accepted changes by round, and a conflict panel in plain negotiation-language terms (§5).
  • Repo browse view needs a rendered-contract reading view with a clause outline sidebar and a defined-terms glossary panel (term → definition → every usage, clickable), the contract-domain analog of the Research Papers plan's claims panel.

Rich contract visualization

  • Full rendered view (typeset contract prose from the canonical IR) as the default "read this contract" experience — never raw DOCX/PDF, mirroring every prior plan's "render from canonical IR, not raw source" principle.
  • Obligation timeline view: obligations/deadlines plotted on an actual timeline (distinct from the Video Timelines plan's media-editing timeline, but a structurally similar "time-anchored elements laid out visually" view) — useful for spotting an obligation-heavy period or a deadline clustering issue at a glance.

MCP/tooling implications

Expose contract_query, contract_diff, contract_obligations_of, contract_undefined_terms as MCP tools, mirroring every prior plan's exposure pattern — lets agentception workers check "did this redline introduce an undefined term" or "what does this party still owe" before a merge or review completes.


10. Future Semantic Extensions

Named here so the v0 scope boundary (§1) is legible as a deliberate step, not a ceiling:

  • Deep legal-conflict detection: full semantic contradiction detection between clauses beyond v0's structurally-detectable deadline-inconsistency case (§7) — requires legal-domain reasoning this plan does not attempt to build.
  • Jurisdiction-aware enforceability analysis: checking clause validity against actual governing-law requirements — explicitly out of scope permanently (§1), not just deferred; would require this domain to give legal advice, which it does not.
  • Akoma Ntoso / LegalDocML export: a structured legal-XML export target for interop with legislative/regulatory tooling, once the canonical IR (§2) is proven against real contracts (§1).
  • E-signature platform integration: connecting SignatureBlock execution state to a live DocuSign/Adobe Sign workflow rather than v0's static, imported signature-block record.
  • Cross-contract portfolio analysis: CLM-style queries across an entire contract portfolio (e.g. "every contract with an auto-renewal clause expiring next quarter") — a natural extension of §6's cross-repo search once proven at scale.
  • Obligation-to-code/dataset cross-linking: linking a contractual obligation (e.g. a data-retention clause) to the actual code/dataset-domain artifacts that implement compliance with it — connecting this domain to Muse's broader code-intelligence and dataset-provenance layers.
  • AI-assisted redline drafting: suggested counter-proposals for a given redline, grounded in the contract's own defined terms and obligation structure — structurally similar to the Research Papers/Pathways plans' deferred AI- assisted-construction directions.
  • Precedent-clause library and similarity search: matching a clause against a library of prior negotiated clauses (embedding-based similarity) to surface "how did we negotiate this last time" — connects to whatever vector-search infrastructure MuseHub eventually adopts for other domains, same as the Knowledge Graphs plan's deferred embedding-search direction.
  • Full obligation lifecycle tracking: not just recording an obligation's existence, but tracking its actual real-world performance status (performed, overdue, waived) over time — a substantial extension connecting this domain to external performance-tracking data, not attempted in v0.

11. Staging Deliverables

Proposed issue breakdown

  1. LEG-1 — Canonical model + snapshot + clause identity pinning (§2, §3): entity dataclasses, clause/defined-term identity, DOCX import bridge (incl. tracked changes), golden-snapshot tests (LEG_01LEG_13). Load-bearing — nothing else starts until this lands.
  2. LEG-2 — Markdown/PDF import (§1, §3): depends on LEG-1. LEG_20LEG_22.
  3. LEG-3 — Heuristic extraction (obligations/rights/deadlines/terms) (§1): depends on LEG-1; parallel with LEG-2.
  4. LEG-4 — Semantic diff (§4): depends on LEG-1, LEG-3. LEG_30LEG_38.
  5. LEG-5 — Merge strategy (§5): depends on LEG-1, LEG-4. LEG_50LEG_58.
  6. LEG-6 — Cross-reference/defined-term graph + query DSL + CLI (§6, §9): depends on LEG-1, LEG-3. LEG_60LEG_74.
  7. LEG-7 — Property-based renumbering/deadline suite (§8): depends on LEG-1, LEG-3. LEG_80, LEG_81.
  8. LEG-8 — Remaining validation & drift checks (§7): depends on LEG-1, LEG-3; parallel with LEG-4/LEG-5/LEG-6. LEG_90LEG_95.
  9. LEG-9 — MuseHub API endpoints + cross-repo contract search (§9): depends on LEG-1, LEG-4, LEG-6.
  10. LEG-10 — MuseHub UI: semantic redline renderer, glossary panel, obligation timeline (§9): depends on LEG-9. Not scoped in detail until LEG-4/LEG-5 output shapes are proven.
  11. LEG-11 — MCP tooling exposure (§9): depends on LEG-6.

Milestones

  • M1 (Foundation): LEG-1 merged, muse domains --json lists contract as active, golden-snapshot suite green, clause renumbering verified to never spuriously diff.
  • M2 (Interop): LEG-2 merged; Markdown round-trip and PDF lossy-import fixtures pass at their fidelity ceilings.
  • M3 (Semantic core): LEG-3 + LEG-4 + LEG-5 merged; a two-branch conflict fixture (both branches change the same obligation's deadline differently) produces a correct conflict report; concurrent-redline auto-merge verified working as designed.
  • M4 (Usable): LEG-6 + LEG-7 + LEG-8 merged; muse contract obligations-of/ undefined-terms/broken-refs/pending-redlines all answer correctly against fixtures.
  • M5 (Ecosystem): LEG-9, LEG-10, LEG-11 merged; a contract proposal on staging MuseHub renders a real semantic redline with a defined-terms glossary and obligation timeline.

Acceptance criteria (whole-plan level)

  • muse domains --json shows contract with active: true and the schema in §9.
  • Renumbering the baseline NDA fixture (inserting a clause and letting every subsequent clause renumber) produces zero diffs on the unaffected clauses — verifies clause identity pinning (§3).
  • The undefined-term and broken-cross-reference fixtures are commit-blocking (§7); the orphaned-defined-term fixture is informational only; well-formed fixtures produce no false positives.
  • A merge of disjoint clause edits auto-resolves with zero conflicts; two branches both proposing (but not accepting) redlines on the same clause in the same round auto-merge as coexisting proposals; a merge where both branches change the same obligation's deadline differently reports a correctly-worded conflict in business terms.
  • muse contract obligations-of/term-usage/deadlines correctly answer against fixtures with known expected results.
  • No test depends on network access, a specific python-docx/Word version's exact tracked-changes XML, or wall-clock time (§3/§7 determinism requirement).

Risks

  • Extraction-accuracy risk: v0's heuristic obligation/right/deadline extraction (§1) will miss non-standard phrasing and may over-extract modal verbs that aren't really obligations. Mitigation: extraction_confidence is always visible, never presented as ground truth — mirrors the Research Papers plan's identical claim-extraction-accuracy risk and mitigation.
  • Clause-identity-pinning risk: the matching algorithm behind §3's pinning is a single point of failure for the domain's most important guarantee (renumbering never diffs) — a poor match on a genuinely restructured contract could either falsely merge two unrelated clauses or falsely split one edited clause into delete+insert. Mitigation: needs real-fixture calibration (open question below), not a guessed threshold, and must be tested against both a pure-renumbering fixture (must not diff) and a genuine-rewrite fixture (must diff) explicitly.
  • DOCX tracked-changes fidelity risk: OOXML's revision-tracking XML has known edge cases (nested revisions, revisions inside tables, formatting-only changes mixed with text changes) that vary across Word versions. Mitigation: LEG-2's round-trip tests should include at least one fixture with nested/complex tracked changes, not only simple insertions/deletions, to surface real gaps early.
  • Scope-creep-into-legal-advice risk: the governing-law/clause-consistency check (§7) and any future "conflict detection" work (§10) sit right at the boundary of what looks like legal analysis. Mitigation: this plan is explicit that jurisdiction-specific enforceability is permanently out of scope (§1), and any check added later must be evaluated against that boundary before implementation, not organically expanded.
  • Cross-repo search risk: same architectural risk class every prior plan with cross-repo search flagged (#69–#72) — should ideally share one implementation across all five plans rather than five independent ones.

Open questions

  • What specific matching-confidence threshold should clause identity pinning (§3) use to distinguish "same clause, edited" from "genuinely different clause"? Needs calibration against real contract-restructuring examples before LEG-1 is finalized, mirroring the identical open question the Research Papers plan raised for paragraph identity.
  • Should obligation/right extraction (§1, §3) support a pluggable extraction backend from the start (heuristic v0, NLP-based later), or is that premature abstraction until a v1 approach is actually designed? Mirrors the identical open question the Research Papers plan raised for claim extraction.
  • Should this domain's cross-repo search (§9) share one implementation with the Research Papers/Pathways/Datasets/Knowledge Graphs plans' equivalent endpoints? Worth resolving once, across all five, before any of their respective search- endpoint issues start.
  • Where exactly should CLM-platform metadata import (§1) live — a first-class, documented import path in LEG-1/LEG-2, or an explicitly out-of-scope-for-now convenience left for a future issue once a specific CLM integration is actually requested? Leaning toward the latter (avoid speculative design against a platform with no concrete integration target yet) — flagged for confirmation.
  • Should the Redline element's round counter be author-declared or Muse- computed (incrementing automatically per commit touching redlines)? Needs a decision before LEG-1, since it affects how naturally the model matches real negotiation workflows where rounds aren't always cleanly synchronized across parties' own tracking.

Implementation order

LEG-1 → (LEG-2, LEG-3 in parallel) → LEG-4 → LEG-5 → LEG-6 → LEG-7 → LEG-8 → LEG-9 → (LEG-10 and LEG-11 in parallel). Extraction (LEG-3) is pulled forward alongside import since diff/merge/query all depend on obligations/rights/terms existing as addressable elements, not just raw clause text.


Plan-only issue. Each deliverable in §11 should be filed as its own staging issue once reviewed, referencing the test IDs and criteria above.

Activity
gabriel opened this issue 19 days ago
No activity yet. Use the CLI to comment.