nb-09 — From permit to duties and powers
Northbridge course, intermediate (nb-05 →
nb-06 → nb-07 →
nb-08 → nb-09).
All law is fictional; every office, notice, revocation and towing rule is
synthetic and unofficial. No real municipal deployment or legal-validity
claims. Engine law 0.1.0, semantics law.core/0.2.
Situation
Section titled “Situation”Ann filed her parking-permit application on 1 March 2026. Filing is not the end of the story — it starts several directed relations at once. The permit office now owes Ann a decision within thirty days. Ann, once eligible, must not resell her permit to anyone during 2026.
If she does resell it, the office may revoke it by sending a revocation notice — and only then. If the office refuses her outright, she may object during March. And while she displays a valid permit, the office may not have her car towed.
The eligibility lessons answered “may Ann have a permit?”: nb-01: First permit: facts, a rule and a question, nb-02: Why a missing fact is not a refusal, nb-03: Exceptions and conflicting rules. This article answers what happens next: who owes what to whom, what counts as doing it or breaking it, and which acts change the legal state. Law DSL expresses those relations as five position constructs: duty, prohibition, power, liberty, and immunity, each shown with its meaning in place below.
Prerequisites
Section titled “Prerequisites”nb-01: First permit: facts, a rule and a question:
facts, strict rules, law test as the way to check a claim.
nb-02: Why a missing fact is not a refusal:
the four truth statuses — NEITHER below means “no conclusion either
way”, never a refusal.
nb-03: Exceptions and conflicting rules: strict
rules and how conflicts resolve.
nb-08: Which edition applies and when the term expires:
the CALENDAR_DAYS deadline policy — the decision duty’s window end
(due) is computed by the DecisionDeadline rule with that policy,
and the duty tests set the policy in their context.
New here: positions are not truth claims. truth(...) says whether a
proposition holds; positions() says what lifecycle state each duty,
prohibition, power, liberty and immunity is in: ACTIVE (in force,
outcome still open), SATISFIED (goal met), VIOLATED (goal failed),
UNDETERMINED (too little known to say either).
Minimal example
Section titled “Minimal example”All fragments are excerpts from
packs/examples/language-demo/permits/package.law (identifiers as
written; package header, imports and unrelated rules cut).
Excerpt 1 — the office’s duty to decide (lines 77–90). A duty names a bearer o (who owes), a beneficiary (to whom it is owed), and a goal: here an achievement goal with a condition and a window.
rule DecisionDuty strict { for a: Applicant; for o: Office; for on, due: Date; when demo.northbridge.vocabulary::application_filed(a, on) and decision_due(a, due) and demo.northbridge.vocabulary::permit_office(o); then duty NotifyDecision { bearer o; beneficiary a; goal achievement { condition demo.northbridge.vocabulary::decision_notified(a); window [on, due]; } };}One idea: an achievement goal is met when its condition becomes true at least once inside the window — notify Ann once before the due date and the duty is satisfied.
Excerpt 2 — Ann’s prohibition on resale (lines 92–102). A prohibition names a bearer a, a beneficiary, a forbidden action, and a window.
rule NoResale strict { for a: Applicant; for o: Office; when permit_eligible(a) and demo.northbridge.vocabulary::permit_office(o); then prohibition NoPermitResale { bearer a; beneficiary o; action demo.northbridge.vocabulary::resells_permit(a); window [@2026-01-01, @2026-12-31]; };}One idea: the mirror image of a duty — instead of “bring about this condition”, “do not perform this action” for the whole of 2026.
Excerpt 3 — the maintenance duty (lines 149–162). Same parties shape, a different goal kind: maintenance must hold at every point of the window, not just once.
rule MaintainEligibility strict { for a: Applicant; for o: Office; for on: Date; when demo.northbridge.vocabulary::application_filed(a, on) and demo.northbridge.vocabulary::permit_office(o); then duty MaintainConditions { bearer a; beneficiary o; goal maintenance { condition permit_eligible(a); window [@2026-01-01, @2026-12-31]; } };}One idea: staying eligible all year is a duty too — one counterexample (fines on 1 June) violates it, while one good day proves nothing.
Excerpt 4 — the revocation power (lines 164–175). A power names a
holder, the party it is over, the exercise act, the valid_when grounds,
and the effect the exercise creates.
rule RevocationPower strict { for a: Applicant; for o: Office; when demo.northbridge.vocabulary::permit_office(o) and permit_eligible(a); then power RevokePermit { holder o; over a; exercise revocation_notice(o, a); valid_when (demo.northbridge.vocabulary::resells_permit(a)); effect create(permit_revoked(a)); };}One idea: the notice is only an exercise — permit_revoked(a) appears
solely when the grounds (resells_permit) hold too.
Excerpt 5 — the liberty to object (lines 177–187). A liberty names a holder, the party it is against, a permitted action, and a window.
rule ObjectionRight strict { for a: Applicant; for o: Office; when permit_refused(a, o); then liberty MayObject { holder a; against o; action objects(a, o); window [@2026-03-01, @2026-03-31]; };}One idea: a refusal opens a one-month window in which objecting is permitted — the liberty exists only because the refusal happened.
Excerpt 6 — immunity against towing (lines 189–199). An immunity names a holder, the party it is against, a protected effect (something that must not be brought about against the holder), and a window.
rule NoTowing strict { for a: Applicant; for o: Office; when permit_displayed(a, o); then immunity NoTowingWithPermit { holder a; against o; protected_effect vehicle_towed(o, a); window [@2026-01-01, @2026-12-31]; };}One idea: displaying the permit shields Ann from one specific effect — towing — without granting anything else.
Command and result
Section titled “Command and result”law test packs/examples/language-demo/permitsObserved result (engine law 0.1.0) — the ten position, power, liberty
and immunity lines of the run plus its summary:
ok [demo.northbridge.permits] tests/permits.lawtest / positions: duty and prohibition active ok [demo.northbridge.permits] tests/permits.lawtest / duty satisfied ok [demo.northbridge.permits] tests/permits.lawtest / duty violated ok [demo.northbridge.permits] tests/permits.lawtest / outcome unknown — no violation ok [demo.northbridge.permits] tests/permits.lawtest / maintenance holds while the window is open ok [demo.northbridge.permits] tests/permits.lawtest / maintenance violated by counterexample ok [demo.northbridge.permits] tests/permits.lawtest / without a certificate the post-window outcome is unknown ok [demo.northbridge.permits] tests/permits.lawtest / power exercised lawfully ok [demo.northbridge.permits] tests/permits.lawtest / power without grounds does not operate ok [demo.northbridge.permits] tests/permits.lawtest / liberty and immunityитого: 28 проверено, 28 прошли, 0 не прошли, 0 не исполнены; код 0The package also passes the static check:
law engine check packs/examples/language-demo/permits/package.lawcheck OK: packs/examples/language-demo/permits/package.lawWhat the decisive tests assert (evaluate positions(), except the two
power tests, which ask truth(permit_revoked(ann))):
| Test | Setup | Expects |
|---|---|---|
positions: duty and prohibition active | filed 1 March, office known, judged 5 March | NotifyDecision ACTIVE, NoPermitResale ACTIVE |
duty satisfied | filed 2 March, notified, judged 10 April | NotifyDecision SATISFIED |
duty violated | filed 2 March, explicitly not notified, judged 10 April | NotifyDecision VIOLATED |
outcome unknown — no violation | filed 2 March, notification neither asserted nor denied, judged 10 April | NotifyDecision UNDETERMINED |
maintenance holds while the window is open | still eligible, judged 1 June | MaintainConditions ACTIVE |
maintenance violated by counterexample | fines recorded, judged 1 June | MaintainConditions VIOLATED |
without a certificate the post-window outcome is unknown | filed 2 March, no certificate facts either way, judged 5 January | MaintainConditions UNDETERMINED |
power exercised lawfully | notice sent and resale recorded | permit_revoked TRUE_ONLY |
power without grounds does not operate | notice sent, no resale recorded | permit_revoked NEITHER |
liberty and immunity | refused and permit displayed, judged 10 March | MayObject ACTIVE, NoTowingWithPermit ACTIVE |
All 28 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: итого: 28 проверено, 28 прошли, 0 не прошли, 0 не исполнены; код 0 — 28 checked, 28 passed, 0 failed, 0 skipped, exit code 0.
Note the dates doing work: the achievement duty is judged on 10 April, after the 30-day window from the 2 March filing has closed — so its outcome is decidable. The maintenance duty is judged on 1 June, mid-window — still open, hence ACTIVE while no counterexample exists.
Why this construct
Section titled “Why this construct”The task is to turn “the office must decide, Ann must not resell, the office may revoke on resale, Ann may object, towing is off-limits” into machine-checkable relations with named parties and observable lifecycles.
Each of the five answers a different question the desk clerk actually asks. Duty and prohibition: who owes what to whom. Power: can this act change her legal state. Liberty: may she do this. Immunity: are we barred from doing that to her. One construct per question — no overloading.
The ten tests are the proof: every lifecycle state (ACTIVE, SATISFIED,
VIOLATED, UNDETERMINED) and both power outcomes (TRUE_ONLY, NEITHER)
are executed by law test, not asserted in prose.
What is not proven: that these are the right municipal rules. The tests prove the machine tracks the declared duties and powers; no test can prove Northbridge chose wisely. All acts are fictional data, not legal advice.
Why not eligibility rules or constraints?
Eligibility rules (nb-01: First permit: facts, a rule and a question, nb-02: Why a missing fact is not a refusal, nb-03: Exceptions and conflicting rules) can label someone “revocable” but cannot name the act, the grounds, or the effect. Constraints can flag “issued without fee” but carry no parties and no lifecycle. Positions keep parties, performance, violation and effect in one named unit.
Changed condition
Section titled “Changed condition”Take the lawful revocation and remove one fact:
resells_permit(ann).
With resale asserted (office, eligibility and the notice all present),
truth(permit_revoked(ann)) is TRUE_ONLY — exercise plus grounds, so
the create(permit_revoked(a)) effect fires. Without resale, everything
else identical, the same query is NEITHER.
Why: the notice was still sent and the power still exists, but an
exercise without valid_when grounds operates nothing. One condition,
two outcomes — and the difference shows in the truth status, not in
anyone’s intention.
The same one-change logic governs duties: duty satisfied versus duty violated differ only in whether decision_notified(ann) is asserted
or explicitly denied on 10 April; assert neither and the third test
reports UNDETERMINED. The engine never invents a violation from
silence.
Typical mistake
Section titled “Typical mistake”The mistake is treating the exercise act as the effect: “the office sent the notice, so the permit is revoked.”
It is not — the groundless-power test returns NEITHER with the notice
on record. exercise names which act counts; valid_when decides
whether it operates; only an operating exercise produces the
effect.
The fix: a power needs three things at once — standing (office plus
eligibility in the when), the exercise act, and true grounds. Remove
any one and permit_revoked stays NEITHER. If you want revocation on
notice alone, write valid_when that way — but then say so, because
the test suite will hold you to it.
Limits
Section titled “Limits”- Positions are read through
positions(). Truth queries see the power’s effect (permit_revoked), never the duty or liberty itself. Askingtruth(NotifyDecision)is a category error — duties have lifecycle states, not truth values. - Windows bound everything.
MayObjectopens only for refusals inside 1–31 March;NoPermitResalecovers only 2026. Outside its window a position is not violated — it simply does not apply. - UNDETERMINED is not VIOLATED. After the window closes with the
outcome unrecorded (
without a certificate ... unknown), the engine reports UNDETERMINED rather than guessing. Violation needs a witness: an explicit denial for achievement, a counterexample for maintenance. - Verified profile: engine
law 0.1.0, semanticslaw.core/0.2. The lifecycle vocabulary (ACTIVE, SATISFIED, VIOLATED, UNDETERMINED, exercise / valid_when / effect) is a fact about this profile’s implementation, never a claim about the language in general.
Exercise
Section titled “Exercise”Without running the engine, predict, then check with law test:
- In
duty violated, which single change to the given facts flipsNotifyDecisionfrom VIOLATED to SATISFIED, and which flips it to UNDETERMINED? - In
maintenance violated by counterexample, why is the status VIOLATED rather than UNDETERMINED — what plays the witness role? - In
power without grounds does not operate, name the three ingredients (standing, exercise, grounds) and say which one is absent. - In
liberty and immunity, why isMayObjectACTIVE on 10 March but would not even apply to a refusal dated 15 April?
Write down each prediction first; run the suite; explain any miss in one sentence. Checkable solution: solutions/nb-09-solutions.md.
Sources
Section titled “Sources”- Source:
packs/examples/language-demo/permits/package.law(rulesDecisionDuty,NoResale,MaintainEligibility,RevocationPower,ObjectionRight,NoTowing) - Tests:
packs/examples/language-demo/permits/tests/permits.lawtest(the ten position, power, liberty and immunity tests) - Suite tour:
packs/examples/language-demo/README.md - Language reference:
docs/language/09-advanced-cheat-sheet.law.md(positions and advanced constructs),docs/language/06-testing-a-package.law.md(thelaw testreference) - Prerequisite: nb-01: First permit: facts, a rule and a question; next: nb-10: A procedure with parallel checks
Three levels:
- Northbridge use (this article): office decision duty, resale prohibition, eligibility maintenance, revocation power, objection liberty, towing immunity — verified by the ten tests above.
- Domain template: whenever a regime says who must do what for
whom, model each relation as one named position with explicit parties
and a window; use achievement for one-off acts, maintenance for
standing conditions; give every power named grounds plus a named
effect, and read lifecycles only through
positions(). - Confirmed example elsewhere: unit training readiness (US Army
AR 350-1, para. 1-9a) — package
us.army.training,corpus/laws/us/army-training/03-deontic.law:50-61, constructthen dutywith an addressed holder, a beneficiary, and an achieve-during window (UnitTrainingReadiness). Why this form fits: one named position with explicit parties and a window — this article’s domain template, outside civil law. Evidence:docs/research/constructs/10-duty/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.
Where an exercised objection would be heard
The appeals package takes over where positions stop: readings are
selected, judgments are rendered, precedents are followed or
distinguished — verified by
law test packs/examples/language-demo/appeals
(7 checked, 7 passed, 0 failed), including judgment rendered
(TRUE_ONLY once the hearing officer’s judgment is on record) and
precedent distinguished (FALSE_ONLY where the defendant’s facts
differ). Positions create the relations; appeals resolve what is
contested about them — exactly as the limits say.
Documentation for Arxo. Writings — blog.arxo.io.
Anonymous visit counts on stats.arxo.io, no cookies.