Corpus/Temporal
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_enforcementbecomesin_force=trueonce its effectivedateis in the past (the tag is not rewritten — only the boolean). - An article tagged
deferred_repealbecomesin_force=falseonce itsdate_endis in the past. - An article tagged
in_forcebecomesin_force=falseif itsdateis in the future (rare — late-published versions). - All other "not in force" states (
repealed,superseded,expired,annulled,transferred,denounced,never_in_force,disjoined) are alwaysin_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