Corpus/Temporal

From Dura Lex Wiki
Jump to navigation Jump to search

Temporal Model

[edit | edit source]

Overview

[edit | edit source]

Legal documents exist in time. Articles are versioned (valid_from/valid_until). Decisions are point-in-time events. The schema handles both with the same promoted columns.

date and date_end semantics by kind

[edit | edit source]
kind date = date_end =
legislation (statute, versioned article) valid_from (entry into force) valid_until (repeal, amendment)
legislation (decree, regulation) publication_date or entry_into_force expiration (if any)
legislation (collective agreement) filing_date or effective_date expiration_date
legislation (guidance, circular) publication_date NULL (until superseded)
legislation (bill, debate) publication_date NULL
decision decision_date NULL
record (company) creation_date closure_date
record (person) NULL NULL
notice publication_date NULL
section NULL NULL
chunk (inherited from parent) NULL

Article versioning

[edit | edit source]

Multiple versions of the same article = multiple documents with the same tags.cid (permanent article identity) and different date/date_end ranges.

<syntaxhighlight lang="sql"> -- Get the version of article 1147 CC in force on 2015-06-15 SELECT * FROM corpus.documents WHERE tags->>'cid' = 'LEGISCTA000006136353'

 AND date <= '2015-06-15'
 AND (date_end IS NULL OR date_end > '2015-06-15')

ORDER BY date DESC LIMIT 1; </syntaxhighlight>

tags.cid is the permanent identity (CID from LEGI XML, or equivalent). It survives renumbering. Article 1382 and article 1240 have different id values but the relationship is captured in corpus.edges kind=replaces.

at_date in TagQuery

[edit | edit source]

The reference resolver supports temporal queries via at_date:

<syntaxhighlight lang="python"> TagQuery(

   language="fr",
   kind="legislation",
   tag_filters=TagFilterSet.from_tags({"article_number": "1147", "code": "Code civil"}),
   at_date=date(2015, 6, 15),

) </syntaxhighlight>

Translated to SQL: <syntaxhighlight lang="sql"> WHERE language = 'fr'

 AND kind = 'legislation'
 AND tags @> '{"article_number": "1147", "code": "Code civil"}'
 AND date <= '2015-06-15'
 AND (date_end IS NULL OR date_end > '2015-06-15')

ORDER BY date DESC LIMIT 1 </syntaxhighlight>

Non-Gregorian calendars

[edit | edit source]

The date column always stores ISO/Gregorian dates. The original calendar representation is preserved in tags:

Calendar Tag Example Used by
Islamic (Hijri) tags.date_hijri "1445-08-15" SA, AE, other ME
Japanese imperial era tags.date_era_jp "R06" (Reiwa 6 = 2024) JP
Taiwan ROC (Minguo) tags.date_roc_tw "112" (= 2023) TW

Conversion is done at ingestion time. The trigger and all queries use the ISO date column.

Enforcement status

[edit | edit source]

For versioned text documents, tags.enforcement_status tracks the legal force:

Status Meaning
in_force Currently applicable
deferred_enforcement Not yet in force, will be on a future date
deferred_repeal Currently in force, repeal scheduled for a future date
repealed Explicitly repealed by a subsequent act
superseded Historical version — a newer version of the same article exists
never_in_force Modified before its effective date, never applied
expired Lapsed by its own terms (sunset clause, fixed-duration text)
annulled Struck down by a court (e.g. constitutional review) — typically retroactive
transferred Content moved to a different article or location (renumbering)
denounced Collective agreement repudiated by one of the parties
disjoined Version split into multiple separate articles
conditional In force only under a specific interpretation (constitutional reservation)
pending Emergency decree or provisional measure awaiting ratification

The boolean shortcut tags.in_force (true/false) enables simple filtering. Unlike enforcement_status, which is set once at ingest from the source data, in_force is dynamically recomputed by the refresh_in_force post-ingest job from the article's date and date_end columns. The two tags can therefore diverge over time:

  • An article tagged deferred_enforcement becomes in_force=true once its effective date is in the past (the tag is not rewritten — only the boolean).
  • An article tagged deferred_repeal becomes in_force=false once its date_end is in the past.
  • An article tagged in_force becomes in_force=false if its date is in the future (rare — late-published versions).
  • All other "not in force" states (repealed, superseded, expired, annulled, transferred, denounced, never_in_force, disjoined) are always in_force=false.

In short: enforcement_status answers "what is the legal lifecycle state of this version?", while in_force answers "is this version currently legally applicable?". Use in_force for filter queries, enforcement_status for display and warnings.

Transitional provisions

[edit | edit source]

When a reform includes transitional rules (e.g., the 2016 French contract law reform: contracts signed before Oct 1, 2016 governed by old law), these are modeled as:

  • A separate document (the transitional provision article)
  • With edges to both the old and new versions
  • The knowledge graph (future) encodes transitional provisions as QUALIFY nodes that route to the correct version based on temporal context