nb-08 — Which edition applies and when the term expires
Northbridge course, intermediate (nb-05 →
nb-06 → nb-07 →
nb-08). All law
is fictional; every act, edition, fragment and calendar is synthetic and
unofficial. Engine law 0.1.0, semantics law.core/0.2, std 0.2.0.
Situation
Section titled “Situation”On 6 March 2026 the permits office sends Ann a notice: confirm your address within two working days. Ann replies on 11 March — is she still on time? Meanwhile a clerk re-opens a June 2025 file: residency alone sufficed then, but since 1 January 2026 a registered vehicle is also required.
Northbridge is a synthetic training town: none of this happened, no office runs this code, and nothing here is valid law anywhere. Two modeling questions carry the article: which edition’s text governs and when exactly a term expires. The answers use pinned editions and anchored rules, three time axes, a deadline policy over a training calendar, and a reusable term.
Prerequisites
Section titled “Prerequisites”nb-01: First permit: facts, a rule and a question:
facts, one rule, one question, and law test as the way to check a
claim. nb-03: Exceptions and conflicting rules:
strict versus defeasible rules and defeat.
This article adds time — validity windows on editions, effective windows on rules, achievement windows on duties — over the same firing logic.
Example
Section titled “Example”Eight terms, each explained next to its first use. Start with the clerk’s first question: which text governs the file on her desk? The source is the act itself (here, the training act “Northbridge Residential Parking Rules”). An edition is one dated, frozen version of that act. The 2025 and 2026 editions sit side by side; their validity windows touch but do not overlap:
Excerpt from demo.northbridge.sources,
packs/examples/language-demo/sources/package.law (lines 19–33;
the source block above is cut):
edition RULES_2025 of PARKING_RULES { language en; officiality unofficial; adopted @2024-12-01; in_force [@2025-01-01, @2026-01-01); materialization_status PINNED_OFFICIAL_BYTES;}
edition RULES_2026_EN of PARKING_RULES { language en; officiality unofficial; adopted @2025-12-01; in_force [@2026-01-01, infinity); materialization_status PINNED_OFFICIAL_BYTES;}Within an edition, the clerk points at one sentence. A fragment is
a named slice of an edition’s text — here Article 2 (article/2)
with a quoted sentence and a content hash; the 2025 sentence asks only
for residency, the 2026 one adds the registered vehicle. (A Russian
2026 edition exists, aligned as a reviewed translation.) An anchor
is the @source(…) line tying a rule to its fragment, so the reader
can walk from a firing rule back to its sentence:
Excerpt from the same package (lines 114–128; both rules in full):
@source(PARKING_RULES_2025_ART2)rule OldResidencyNotice strict { effective [@2025-01-01, @2026-01-01); for a: Applicant; when demo.northbridge.vocabulary::resident(a); then residency_notice(a);}
@source(PARKING_RULES_2026_ART2_EN)rule NewEligibilityNotice defeasible { effective [@2026-01-01, infinity); for a: Applicant; when demo.northbridge.vocabulary::resident(a) and demo.northbridge.vocabulary::vehicle_registered(a); then eligibility_notice(a);}Look at what each rule carries: two windows. The fragment says what
the text is; the effective window says when the rule may fire.
Their agreement here is the modeler’s responsibility, not an engine
inference. The old rule is strict, the new one defeasible — the firing
logic from earlier lessons, now with dates attached.
The time axes decide which window matters. Every evaluation runs at
three moments — legal_time (whose law governs), decision_time
(when deciding), knowledge_time (what is known). The test profile
fixes all three plus timezone and counting policy:
Excerpt from demo.northbridge.sources,
packs/examples/language-demo/sources/tests/sources.lawtest
(lines 5–8; profile only):
context profile CaseAxes { timezone "Asia/Almaty"; deadline_policy WORKING_DAYS;}Ann’s notice raises the second question: when does her two-day term expire? A deadline policy names how day-counting works: when counting starts, whether the window end is included, and where a term landing on a day off rolls. A calendar supplies the working-day facts the policy counts over. Northbridge’s training calendar is thin — weekdays, one conventional day off (9 March 2026), bounded to 2026 — and its metadata says it is not an official calendar:
Excerpt from demo.northbridge.sources,
packs/examples/language-demo/sources/package.law (lines 130–144;
calendar and policy in full):
calendar NorthbridgeCalendar { timezone "Asia/Almaty"; timezone_db "iana-tzdb@2026a"; period [@2026-01-01, @2027-01-01); source PARKING_RULES; resource "resources/northbridge-calendar-2026.json"; format "law.calendar/0.1"; content_hash "sha256:344b43d6a1060fe139378ab2de8d30a85abab0d1584891c93cd8f38713ccd6ee";}
deadline policy WORKING_DAYS { start_count next_day; include_end true; roll next_working_day;}Read the policy line by line. Counting starts the day after the
triggering event (start_count next_day), the window end counts as
inside (include_end true), and a term landing on a day off rolls
forward (roll next_working_day). The reply duty uses exactly this
arithmetic — two business days from receipt:
Excerpt from the same package (lines 152–155; goal block only — surrounding rule lines cut):
goal achievement { condition reply_filed(a); window [on, add_business_days(on, 2 business_day)];}Finally, the office reuses the same “due by when” shape for every appeal. A term packages that shape into a reusable norm: from which event the clock runs, what performance is due, the default length, and named special cases that defeat the default. The boundaries package teaches the same idea in calendar days, where no policy or calendar is needed:
Excerpt from demo.northbridge.boundaries,
packs/examples/language-demo/boundaries/package.law (lines 17–22):
term AppealWindow(a: Applicant, filed_on: Date) { from demo.northbridge.vocabulary::application_filed(a, filed_on); due appeal_decided(a); default 30 calendar_day; case FastTrack when urgent_appeal(a): 10 calendar_day;}The clock runs from the filing event, the due performance is the
appeal decision, the default length is 30 calendar days — and an
urgent appeal takes the named FastTrack case of 10 days instead.
Command and result
Section titled “Command and result”The sources package is self-contained, so one command checks all six claims:
law test packs/examples/language-demo/sourcesObserved result (engine law 0.1.0):
law test demo.northbridge.sources: мир demo.northbridge.sources, demo.northbridge.vocabulary ok [demo.northbridge.sources] tests/sources.lawtest / 2026 edition: the rule is in force ok [demo.northbridge.sources] tests/sources.lawtest / before entry into force the 2026 rule is silent ok [demo.northbridge.sources] tests/sources.lawtest / 2025 edition: the old reading holds in its window ok [demo.northbridge.sources] tests/sources.lawtest / working days: the term includes the window end ok [demo.northbridge.sources] tests/sources.lawtest / working days: overdue without performance ok [demo.northbridge.sources] tests/sources.lawtest / without a policy working days are not countedитого: 6 проверено, 6 прошли, 0 не прошли, 0 не исполнены; код 0What each test pins:
| Test | Setup | Expects |
|---|---|---|
2026 edition: the rule is in force | legal_time @2026-03-01, resident + vehicle | TRUE_ONLY, applied(NewEligibilityNotice) |
before entry into force the 2026 rule is silent | legal_time @2025-06-01, same facts | NEITHER — the rule exists but is not yet law |
2025 edition: the old reading holds in its window | legal_time @2025-06-01, resident only | TRUE_ONLY, applied(OldResidencyNotice) |
working days: the term includes the window end | notice received @2026-03-06, judged @2026-03-11 | position(ReplyOnTime, ACTIVE) — the end day counts |
working days: overdue without performance | same receipt, judged @2026-03-12, not reply_filed | position(ReplyOnTime, VIOLATED) |
without a policy working days are not counted | same receipt, context without deadline_policy | NON_EXECUTABLE + issue(MISSING_POLICY) |
All six tests pass: each answer matched its expectation. A passing
test is not a ruling in anyone’s favour — it only says the engine’s
answer agreed with the test’s expect line. The summary is in
Russian: итого: 6 проверено, 6 прошли, 0 не прошли, 0 не исполнены; код 0 — 6 checked, 6 passed, 0 failed, 0 skipped, exit code 0.
The term machinery, in calendar days:
law test packs/examples/language-demo/boundariesObserved result (engine law 0.1.0):
law test demo.northbridge.boundaries: мир demo.northbridge.boundaries, demo.northbridge.calculations, demo.northbridge.vocabulary ok [demo.northbridge.boundaries] tests/boundaries.lawtest / default term — 30 calendar days ok [demo.northbridge.boundaries] tests/boundaries.lawtest / special case defeats the general term ok [demo.northbridge.boundaries] tests/boundaries.lawtest / defeated general term does not hold ok [demo.northbridge.boundaries] tests/boundaries.lawtest / timeless support under governs is no support ok [demo.northbridge.boundaries] tests/boundaries.lawtest / same fact without governs is support ok [demo.northbridge.boundaries] tests/boundaries.lawtest / facts group visible to the package world ok [demo.northbridge.boundaries] tests/boundaries.lawtest / duration step — exactly one day ok [demo.northbridge.boundaries] tests/boundaries.lawtest / declared unit tag resolves ok [demo.northbridge.boundaries] tests/boundaries.lawtest / derived tag resolves ok [demo.northbridge.boundaries] tests/boundaries.lawtest / snapshot without provisioning — loud refusal ok [demo.northbridge.boundaries] tests/boundaries.lawtest / add_legal_term steps over calendar working days ok [demo.northbridge.boundaries] tests/boundaries.lawtest / map leads the central zone to the high fee ok [demo.northbridge.boundaries] tests/boundaries.lawtest / map does not lead the outer zone to the high fee ok [demo.northbridge.boundaries] tests/boundaries.lawtest / record field projection opens the rule ok [demo.northbridge.boundaries] tests/boundaries.lawtest / small record yields nothing ok [demo.northbridge.boundaries] tests/boundaries.lawtest / role membership opens the rule ok [demo.northbridge.boundaries] tests/boundaries.lawtest / filing without role membership yields nothing ok [demo.northbridge.boundaries] tests/boundaries.lawtest / qualified call of an imported function ok [demo.northbridge.boundaries] tests/boundaries.lawtest / applicant fee check over two imports ok [demo.northbridge.boundaries] tests/boundaries.lawtest / urgent flag routes review past the queue ok [demo.northbridge.boundaries] tests/boundaries.lawtest / non-urgent flag accelerates nothingитого: 21 проверено, 21 прошли, 0 не прошли, 0 не исполнены; код 0This article owns three of those twenty-one: the default term (filed
@2026-02-01, due @2026-03-03, TRUE_ONLY), the urgent special
case (same filing with urgent_appeal, due @2026-02-11), and the
defeated general term (for the urgent filing, @2026-03-03 is
FALSE_ONLY: the special case refutes the default, it does not add a
second answer). The rest belong to other lessons; they are shown only
to prove the suite is green as a whole.
Why this shape
Section titled “Why this shape”The task is to decide under which text a case falls and whether a term has expired — reproducibly, from pinned bytes and named counting rules, not from a sense of “current law”.
The source/edition/fragment/anchor chain makes the text behind every firing rule inspectable. The time axes separate “which law governs” from “when we decide”. The policy plus calendar makes day-counting explicit (start, inclusion, roll) instead of habit.
The six sources tests are the proof (windows select the rule; the end
counts; expiry flips ACTIVE to VIOLATED), plus the three term
tests (default 30 days, urgent 10, defeated default refuted) — all
executed by law test, not asserted in prose.
What is not proven: that two working days is the right reply term, or that the 2026 vehicle requirement is good policy. The tests prove the machine counts the declared term. Texts and terms are fictional data, not legal advice.
Why not dates in conditions, or counting by hand?
Stuffing dates into rule conditions computes the same answers here but scatters the edition boundary across every rule and leaves no text to point at. Counting working days by hand in a function (nb-04: The permit fee style) hides the choices the policy declares. Conditions for case facts, editions for text versions, policies for counting.
Changed condition
Section titled “Changed condition”Change one input: legal_time @2026-03-01 → @2025-06-01, keeping
the same person and facts (resident, vehicle registered).
In March 2026 eligibility_notice is TRUE_ONLY via
NewEligibilityNotice. In June 2025 the same question is NEITHER —
the 2026 rule is silent before entry into force, and the engine says so
instead of borrowing tomorrow’s law.
The old file is not empty, though: with residency alone,
residency_notice is TRUE_ONLY via OldResidencyNotice in its
[@2025-01-01, @2026-01-01) window. One date, three outcomes, and the
legal_time axis — not the reader’s “now” — picks between them:
edition windows filter the rules before any fact is even read.
Typical mistake
Section titled “Typical mistake”The mistake is keeping the business-day window but dropping the
deadline_policy from the context — “the calendar is right there in
the package, so counting should just work”.
It does not. The last sources test does exactly this and gets
NON_EXECUTABLE with issue(MISSING_POLICY) instead of any position.
Without start_count, include_end and roll the window end is
undefined — 11 March could fall inside or outside the term depending on
unspoken habit — so the engine forces the missing choice into the
open.
The fix: legal_time without an edition window gives silence
(NEITHER); a business-day window without a policy gives refusal
(MISSING_POLICY). Both diagnose your model, not Ann: add the window,
or add the policy, and the real question becomes answerable.
Limits
Section titled “Limits”- Refusals are profile facts, not language gaps.
MISSING_POLICYwithNON_EXECUTABLEis whatlaw 0.1.0/law.core/0.2do when working-day counting is asked for without a policy. The refusal is the specified behavior. - The calendar is a toy, honestly labeled. One timezone, one
bounded year, weekdays plus a single override (
2026-03-09off), pinned by hash — and its own metadata says it is not an official calendar. Outside[@2026-01-01, @2027-01-01)there is nothing to count over. - Policies differ per package on purpose. Sources count working
days (
WORKING_DAYS: next-day start, inclusive end, roll forward); boundaries count plain calendar days (CALENDAR_COUNT: no roll). A term incalendar_dayneeds no calendar at all — which is why theAppealWindowtests carry no policy drama. - Anchors do not verify text.
@source(…)records which fragment a rule claims to formalize; nothing checks the rule against the sentence. A misformalized rule would still fire — the anchor makes the mismatch findable, not impossible.
Three levels
Section titled “Three levels”- Northbridge use (this article): two editions, Article 2 fragments, anchored rules, three-axis contexts, a working-day policy over a toy calendar, a two-business-day reply duty — verified by the six sources tests.
- Domain template: freeze each text version as an edition with
a touching-but-disjoint validity window, slice citable units as
fragments, anchor every time-sensitive rule, drive applicability
from
legal_timealone, and count every term under a named policy (start, inclusion, roll) over a pinned calendar. Never let “now” leak into applicability; never count working days without a policy. - Confirmed example elsewhere: the reusable
termindemo.northbridge.boundaries—AppealWindow, 30-day default defeated by a 10-day urgent case — verified bylaw test packs/examples/language-demo/boundaries(21 checked, 21 passed, 0 failed). The special case refutes the default (FALSE_ONLYat the default date), exactly as the 2026 edition supersedes the 2025 reading. Confirmed external formalization: five-year prescription deadline (French Civil Code, prescription title) — packagefr.code_civil,corpus/laws/fr/code-civil/20-prescription-extinctive.law:122-129, constructadd_calendar_periodstep for year/month periods (EcheanceCinqAns:add_calendar_period(depart, 5 calendar_year)). Why this form fits: the period is built by calendar step, not measured in days, with the deadline policy carried alongside — the same “never count without a policy” template as this article. Evidence:docs/research/constructs/20-deadline-calendar/corpus-forms.en.mdsection 1 (rated exemplary there). Limit of verification: presence of the named construct at the cited lines only, confirmed by direct source read; no claim about deployment, runtime behavior, or legal correctness.
Exercise
Section titled “Exercise”Without running the engine, predict, then check with law test:
legal_time @2025-06-01, Ann resident with a registered vehicle: what iseligibility_notice(ann), and which rule fires, if any?- Notice received
@2026-03-06, nothing filed, judged@2026-03-11versus@2026-03-12: which position forReplyOnTimeon each date, and why does one day change it? - Filed
@2026-02-01, applicant urgent: what isappeal_decided(ann, date)on@2026-02-11and on@2026-03-03— and what defeats what? - Delete
deadline_policy WORKING_DAYS;fromCaseAxesand re-run the sources suite: which test changes status, to what, with which issue?
Predict first; run both suites; explain any miss in one sentence. Checkable solution: solutions/nb-08-solutions.md.
- Sources:
packs/examples/language-demo/sources/package.law(editions, fragments, anchored rules, calendar, policy, reply duty) - Texts:
packs/examples/language-demo/sources/sources/northbridge-rules-2025.txt,northbridge-rules-2026-en.txt,northbridge-rules-2026-ru.txt - Tests:
packs/examples/language-demo/sources/tests/sources.lawtest - Term source:
packs/examples/language-demo/boundaries/package.law(AppealWindow,CALENDAR_COUNT) - Term tests:
packs/examples/language-demo/boundaries/tests/boundaries.lawtest - Suite tour:
packs/examples/language-demo/README.md - Prerequisites: nb-01: First permit: facts, a rule and a question; nb-03: Exceptions and conflicting rules; next: nb-09: From permit to duties and powers
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.