# Reuse and dependencies ## Task and place Real canons borrow: calendars, tariff schedules, shared definitions, readings of neighboring acts. This stage decides what the package imports, what it restates in its own words, and what it merely cites — then writes the boundary down so later change arrives as a named event, not silent drift. It sits at both ends of the pipeline: scope names candidate sources up front, and release freezes the chosen versions; review checks the boundary between. ## Inputs - The candidate source: package name, version, and the exact content to borrow. - Its provenance: which act, which edition, which materialization the content was pinned to. - Its assumptions: the readings, policies, and limits its own decision records state. - The [review record template](/handbook/files/templates/review-record.md) and the [filled EAI review record](/handbook/files/filled/eai-review-agent.md), which carries finding EAI-R1 and shows the record shape borrowings are checked against. ## Actions - Check semantic identity before borrowing: same act, same edition window, same reading of the shared passage. A matching title is not identity; read the pinned bytes and the source's decision records. - Restate rather than import when the reading differs: a borrowed rule you would amend is a fork wearing an import's clothes — copy the content, cite the origin, and own the divergence in a decision record. - Pin versions exactly: the manifest names each source with the version reviewed, and an upstream amendment reopens the boundary instead of flowing in silently. - Record provenance per borrowed item: origin package and version, edition, and the assumption the borrower relies on. - Keep local imports explicit: every name used across files in the package is listed where it is used, so the boundary reader sees the full surface without guessing. ## Decisions - Import, restate, or cite: import when identity holds and the source is maintained; restate when the reading differs or the source may lapse; cite without borrowing when the act merely points outward. - Pin or track: released canon pins; only a live draft tracks a moving source, and it says so in the boundary record. ## Artifact The artifact is the dependency boundary: one entry per borrowed item with source, pinned version, borrowed content, provenance, relied-upon assumptions, and the revisit trigger. An empty boundary is a valid artifact — it states the package stands alone — but it must be written, not assumed: an unwritten boundary cannot distinguish "no dependencies" from "never checked." ## EAI example The running example stands alone: package kz.corpus.employee_accident_insurance, version 0.1.0, language 0.2, carries no dependency entries in its manifest, so the boundary record is an explicit empty list with the check run as evidence. Local names cross files through explicit imports, so the boundary reader sees the full internal surface. *Runnable shape of the boundary record for a package with no outside sources; the check below is the evidence.* ```text dependency boundary for kz.corpus.employee_accident_insurance 0.1.0: outside sources: none (manifest carries no dependency entries) local imports: explicit, listed at each use site revisit trigger: any future manifest entry reopens this record ``` The running example proves the empty boundary; it cannot prove that borrowing works. The executable half of this stage is the [payroll drill](/handbook/files/fixtures/reuse-payroll/README.md): borrower `demo.handbook.payroll` computes a premium from a rate schedule borrowed from `demo.handbook.rates`, pinned to 1.0.0, with a file registry publishing both 1.0.0 and 1.0.1. Its boundary record, with values taken from the shipped lock: ```text borrowed item: class rates class_rate/2 with inputs risk_class/2 source: demo.handbook.rates, pinned version 1.0.0, contentHash sha256:51f4da7c9ee041e09244ea33449af619ba0b8aa3e9515dd48e2dfa2c572b521c content: two rate rules over the synthetic RATE_SCHEDULE source provenance: synthetic schedule authored for this drill; identity by exact version plus content hash, not by title assumption relied upon: class-2 rate is 0.012 per unit of payroll transfer mode: import of pub declarations (Employer, risk_class, class_rate) revisit trigger: any new published version reopens this entry ``` ## Pitfall Silent drift: an unpinned source amends, the borrower's suite stays green, and answers change meaning without any test noticing — because the suite pins behavior, not the source bytes. The twin failure is borrowing a reading sight unseen: importing a rule without reading its decision records inherits someone else's close calls as your silent premises. Both are cured the same way: pins plus per-item provenance, checked at review. ## Verify The stage is done when the manifest and the boundary record agree item by item and the check passes. Observed with tool version `law` 0.1.0, semantics law.core/0.2: ```text $ law engine check corpus/laws/kz/laws/employee-accident-insurance check OK: corpus/laws/kz/laws/employee-accident-insurance ``` Criterion: compare the manifest's dependency entries against the boundary record line by line — for the running example both are empty — and confirm the check passes on that closed content. Any entry on one side missing from the other fails the stage. The drill's own criterion is stricter: the pin must hold while a new version exists, and the update must fail loudly. Observed with the same tool version: ```text $ law test docs/handbook/files/fixtures/reuse-payroll/payroll law test demo.handbook.payroll: world demo.handbook.payroll, demo.handbook.rates ok [demo.handbook.payroll#authored] tests/premium.lawtest / premium uses the borrowed class-2 rate total: 1 checked, 1 passed, 0 failed, 0 not run; code 0 ``` Version 1.0.1 sits in the shipped registry and changes the borrowed class-2 rate from 0.012 to 0.015, yet the borrower above stays green: the import line, the manifest entry, the lock's contentHash, and the vendored `deps/` IR all name 1.0.0, and nothing flows in silently. Moving the pin on a scratch copy of the borrower is a named event across five artifacts — and the suite trips on the changed assumption: ```text $ law update 'demo.handbook.rates@1.0.1' --registry file=../registry ~ demo.handbook.rates 1.0.0 -> 1.0.1 changed: .law/transport.json changed: deps/demo.handbook.rates.lawir.json changed: law.lock changed: law.toml changed: package.law $ law test . FAIL [demo.handbook.payroll#authored] tests/premium.lawtest / premium uses the borrowed class-2 rate truth_status == TRUE_ONLY: in the document NEITHER total: 1 checked, 0 passed, 1 failed, 0 not run; code 1 ``` The 12000 KZT expectation pins the relied-upon 0.012 behaviorally: after the update it no longer derives, which is the boundary working as designed — the borrower meets the upstream change as a failing check, not as drift. (Observed on a scratch copy; the shipped borrower stays pinned to 1.0.0.) ## Limits The running example has no cross-act borrowing: no calendar, no shared schedule, no reading inherited from a neighbor package. Multi-act bridges — one package's conclusions feeding another's premises — are maintainer work beyond the solo lane: they need aligned law dates, matched versions, and a joint review the single-package boundary record only points to. A boundary record proves the borrower looked, not that the source is right; criticism of the source stays with the source's own review. ## Next step Continue with [Writing scenarios](/handbook/scenarios/), which turns the model and its decisions into planned checks with fixed expectations. ## Sources - [Language](/language/) — packages, versions, and imports. - [Tutorials](/tutorials/) — the drill track behind this handbook. - [Command line](/cli/) — the check command used above. - [Recording decisions](/handbook/decisions/) — where divergences from borrowed readings earn records. For a collection of packages, continue with [shared vocabularies](/corpus/vocabulary/local-and-shared/) and [dependency contracts](/corpus/dependencies/).