19569d8f | docs: map defensible Canadian citator architecture | Eli Ziff | 2026-07-27 | ↗ GitHub |
31b2ed86 | feat: add project-scoped legal knowledge graph | Eli Ziff | 2026-07-27 | ↗ GitHub |
ebc07ca4 | Citator stage 1: exact note-up graph over the local case corpus | Eli Ziff | 2026-07-28 | ↗ GitHub |
commit body build_citator_graph.py scans corpus cases (import_a2aj_hansard pattern:
atomic replace, meta table) and writes edges = literal citation
occurrences with paragraph anchors, cited-side pinpoints, and bounded
excerpts; anchor regexes, case-name bounds, pinpoint grammar, and
paragraph indexing are faithful ports from the read-only reference
implementations, proven by a differential oracle (232/232 texts across
29 court families; 3,243 spans). Distinct citation forms stay distinct
keys and union only on unambiguous corpus resolution evidence - never
inferred. caselawCitator.ts is a thin reader mirroring a2ajHansard:
noteUpCitations/graphStats, typed null when no graph is installed.
Measured on the full SCC family and reproduced via the reader before
commit: 10,889 cases, 279,803 edges, 90,602 distinct cited keys, ~200s
build; Vavilov 2019 SCC 65 notes up to 43 citing cases / 253
occurrences, identical set via the French twin.
Also consolidates citation identity: citationKey.ts is now the single
Beaver port of the reference normalizer (sharp-s casefold divergence
included); retrievalGate re-exports it, caselawCitator wraps it with a
typed refusal, and a2ajLocalBulk's private twin is replaced - three
drifting copies become one differential-tested function.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018bhP89cYSdEEjHNPnxacns
|
453c14eb | Wire grep-mode find, note-up, and compare-versions chat tools | Eli Ziff | 2026-07-28 | ↗ GitHub |
commit body library_find gains regex:true - patterns run line-by-line over the
original text (grep semantics: ^/$ anchor to lines, backtracking
bounded by line length), typed errors for invalid or oversized
patterns, hits keep the offset+section composition. caselaw_note_up
joins the research-gated group (hansardTools pattern): exact note-up
from the local citator graph, typed citator_not_installed, no treatment
labels implied. library_compare_versions redlines two versions of a
Library DOCX, saves the tracked-changes document to the Library, and
returns counts plus typed abstentions - the model never sees diff text.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018bhP89cYSdEEjHNPnxacns
|
26e3c03e | Note-up reports how often a case was cited, not its page size | Eli Ziff | 2026-07-28 | ↗ GitHub |
commit body Full-corpus graph built: 224,970 cases, 2,541,822 edges, 540,948 distinct
cited keys. Probing it exposed a reporting bug the small graph had hidden:
caselaw_note_up returned `citing_cases: entries.length`, which is the
page, so a model asking about Vavilov would have been told 10.
noteUpCitations now returns { total, entries }, where total is
COUNT(DISTINCT case_id) over the alias-closed key set, and the tool reports
citing_cases_total / returned / truncated the way library_find already
reports total_matches / returned / truncated.
Measured on the full graph (was 43 within the SCC-only build):
2019 SCC 65 8,929 citing cases
2008 SCC 9 11,094
[1999] 2 SCR 817 3,935
2016 SCC 27 572
2015 SCC 5 342
The probe also asserts the thing most likely to rot silently - the alias
closure. Citation forms are distinct keys by design and are unioned only
on unambiguous corpus resolution evidence, so if that union broke, every
note-up would undercount and still look plausible. It holds:
UNIONED 2019 SCC 65=8929 2019 CSC 65=8929
[2019] 4 SCR 653=8929 [2019] 4 RCS 653=8929
That union comes from the corpus lookup index (cases/lookup.duckdb, built
by the ALR Quote Verifier app), attached READ_ONLY at build time and never
rebuilt or modified - 170,728 alias-closure keys at revision 41a23437.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018bhP89cYSdEEjHNPnxacns
|
c9d21066 | citator: consume the corpus's curated citation graph; miner becomes differential | Eli Ziff | 2026-07-30 | ↗ GitHub |
commit body The A2AJ case rows carry a curated citation graph (cases_cited_en/_fr,
cases_citing_en/_fr - lists of neutral citations; 64.2% of the 225,017
case rows have a non-empty cited list, 1.02M cited + 935K citing edges,
probed 2026-07-30). Until now every consumer dropped these columns at
ingest and re-mined citations by regex - the survey's finding #1.
- import_a2aj_bulk.py: the five graph columns (cases_cited_*,
cases_citing_*, citing_cases_count) join the document schema as JSON
text; schema_version 2. The reader SELECTs document.* by name, so
existing databases keep working.
- build_citator_graph.py: curated lists land verbatim in provider_edge
(case_id, direction, citation, citation_key) in the shared key space,
plus case_key mapping each case to its own citation keys. The regex
miner is demoted to what only it can supply - paragraph anchors,
offsets, pinpoints, excerpts - and is measured against the provider
lists per doc (provider_keys_mined_confirmed / provider_keys_unmined /
mined_keys_unlisted in meta), never reconciled.
- caselawCitator.ts: NoteUpResult gains provider {citingInCorpus,
citingReported}; citingReported reaches the decision's citing list
through ANY of its own keys (French twin included). graphStats gains
provider_edges. Both are null on a schema-1 graph.
- citatorTools.ts: provider surface exposed to the model.
Real-data smoke (1,000 SCC cases, 16.6s): 327 curated cited edges over
35 docs, ALL 327 confirmed by the miner (0 provider-only), 761
mined-only keys the lists omit; 7,225 citing edges. The demonstrating
query: noteUp("2011 SCC 62") has 0 mined citing cases in the slice but
50 provider-reported citing citations (lower courts outside the slice).
Suites: caselawCitator (extended fixture: curated citing list, verbatim
provider_edge rows, case_key closure, differential counters),
a2ajLocalBulk; tsc clean.
Integration plan item 2 (task #28).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
|
3734db88 | citator: deterministic prose-vs-authority-list excerpt classifier | Eli Ziff | 2026-07-30 | ↗ GitHub |
commit body First link of the H12 stands-for chain (research plan D1). Pure
regex/counting with receipts and typed insufficient refusal; boundaries
measured on 3,000 random full-build edges; unit-tested on real corpus
examples. Full-build distribution (5k sample): 45% prose / 45% mixed
(prose window extracted) / 10% authority_list / 0.1% insufficient.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
|
cc2dedf7 | citator: standsForProfile - ranked attested characterizations (H12) | Eli Ziff | 2026-07-30 | ↗ GitHub |
commit body Full-build-backed stands-for profiles: citing-prose excerpts pass the
deterministic classifier (lowercase-word window selection so
space-joined document headers never beat sentence prose), rank by
citing-court level (new courtLevels map, all 28 A2AJ codes) then
occurrences then recency, carry sha256 receipts, and tier rich/thin/
none with typed refusal semantics downstream. Real-graph smoke: Jordan
572 citers/rich with SCC characterizations; a 2-citer BCSC decision
profiles thin.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012AgUm5EcRKbT3duVFMbrQD
|
7da4f03d | perf(citator): batch alias expansion so one query opens the graph once | Eli Ziff | 2026-07-31 | ↗ GitHub |
commit body `citationAliasKeys` wraps `withReadonlySqlite`, which opens and closes
the note-up graph per call. The product passage lane asks it about every
citation-shaped fragment of a query - the whole query, each comma /
semicolon split, and each detected citation - so a single citing query
reopened the 2.3 GB noteup.sqlite about seven times and recompiled two
statements each time, to run seven indexed lookups.
Added `citationAliasKeysBatch` beside it in the shared citation module
(the doctrine: expand the shared surface, never hand-roll a second one
in a consumer), and pointed `citationKeys` at it. Element i is exactly
what the single-citation call returns for citations[i], including the
degrade-to-literal-key behaviour when no graph is installed, so the
pinned-citation set and its order are unchanged.
Measured against the real 2.3 GB graph:
one citing query, 7 keyed fragments 4.77 -> 1.35 ms (3.5x)
200 real cited keys 137 -> 20 ms (6.9x)
Output identity checked both ways: the 200-key expansions are
JSON-identical, and a new test asserts batch == per-citation over the
built fixture graph and over an absent graph.
26 tests pass across caselawCitator, a2ajPassageSearch, a2ajPassageWiring,
citationKey, citatorExcerpts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9ToHYJVDxfeJcJwdzrP2H
|
2f8968af | docs: record the standsForProfile fix, citator negatives, and the corrected citer distribution | Eli Ziff | 2026-07-31 | ↗ GitHub |
commit body The standsForProfile change was measured in this session but landed inside
7da4f03d, whose message describes only the alias batching - so the perf
ledger had no row for it. Adds that row with the before/after numbers and
the identical-output proof.
Also records three citator measurements so they are not re-opened:
noteUpCitations does not need the same fix (its page caps at 50 groups, so
the loop is not the cost), commentaryCandidates is already single-query,
and the covering-index lever was measured but deliberately not applied.
Discharges P1.5: the "93% of cited keys have one citer" figure is a
smoke-citator artifact. On the full 2.54M-edge graph it is 62.16% of
540,948 keys, with 95.21% at 12 citers or fewer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9ToHYJVDxfeJcJwdzrP2H
|
14b7b376 | Research becomes a tree, and the citator says what it is | Eli Ziff | 2026-07-31 | ↗ GitHub |
commit body SHAPE, from the progressive-disclosure literature: a flat catalogue wins
while it is small -- no navigation hop, no semantic noise -- but its token
cost grows near-linearly and its accuracy degrades as the catalogue grows,
where a hierarchy stays flat on both. Research is where that bites here, at
half the deferred tools, so research is a tree and every other domain stays
one level.
research -> opens onto its children, not onto tools
research.cases -> the case tools + the citator
research.legislation -> the statute tools + Hansard
research.commentary -> journals, secondary sources, citation verification
Opening a parent returns `open_next` with each child and what it covers, so
the model narrows in one cheap turn. The A2AJ tools serve both halves of
primary law and appear under either leaf.
THE CITATOR NOW DESCRIBES ITSELF. It said "Note up a Canadian case citation
against the locally built citator graph" -- a verb the model has to already
know to want. It now states the capability: a local graph over 224,970
Canadian decisions, 2,541,822 citation edges naming 540,948 distinct cited
decisions, built offline with no network call, returning the decisions that
cite a given one with the citing court's own words, the paragraph the
citation appears at, and the pinpoints it cited into -- and stating plainly
that it records citation OCCURRENCE, not editorial treatment, so there are no
followed/overruled labels to mistake it for.
The reason to describe rather than instruct: the edit benchmark measured the
`amendment` domain being opened five times and called from zero, because its
blurb attracted renumbering tasks it could not do. Blurbs are doing routing
work, and a verb-shaped one routes on the wrong thing.
1,251 tests pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01H9ToHYJVDxfeJcJwdzrP2H
|
e2be4570 | feat: add legalProvisionGraph - provision relationship SVG renderer | Eli Ziff | 2026-08-03 | ↗ GitHub |
commit body Composes crossReferenceGraph (legalCrossReference.ts) and AgreementSkeleton
(legalTextSkeleton.ts) to extract parent-child hierarchy and resolved
internal cross-reference edges, then renders a layered left-to-right
digraph as standalone SVG with dark-mode support, tooltips, and a legend.
Co-Authored-By: Claude <noreply@anthropic.com>
|
fe46a53b | checkpoint: worktree broad commit - in-flight citator/evidence changes | Eli Ziff | 2026-08-04 | ↗ GitHub |
commit body Commits the concurrent citator/evidence session's continued work on the
attested-characterization / citeable journal-articles feature (journalArticles
tests, legalEvidenceExperiment, publicLegalSourceState). Not authored in this
session; captured per broad worktree-commit instruction so the tree is clean.
Untracked scratch (backend/.tmp-*.ts probes, provision/taxonomy .html/.svg
artifacts, .csv dumps) intentionally left out of the commit.
Co-Authored-By: Claude <noreply@anthropic.com>
|