colregs 0.3.3 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/data/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.3.3"
2
+ "version": "0.3.4"
3
3
  }
@@ -53,6 +53,25 @@ anyone has checked, and the `us/inland@2014` edition is recalled, not
53
53
  verified, and says so. That is the honest cost of this option and the reason
54
54
  to look at both.
55
55
 
56
+ ## Considered and declined (amendment, 2026-09-16)
57
+
58
+ Four designs additive on option B, declined for now rather than on
59
+ principle — each recorded in requirements.md §10 as a timed gate, closing
60
+ event the first national text whose edition cannot be determined:
61
+
62
+ - **Validity intervals on editions (`in_force_until`).** (GATE-7)
63
+ `superseded_by` plus `in_force` already infers validity for every
64
+ edition on file; a dedicated field would duplicate that inference.
65
+ - **A per-source publication record separate from the edition, FRBR
66
+ manifestation.** (GATE-8) `source` lives on the corpus and one edition
67
+ has one source per jurisdiction today; nothing distinguishes yet.
68
+ - **A content digest per corpus for verification.** (GATE-9)
69
+ `edition_status` already flags an unchecked corpus; a digest adds
70
+ tamper/drift detection nothing on file has needed.
71
+ - **A skeleton per edition, instead of one shared skeleton.** (GATE-10)
72
+ Low risk today: no amendment has ever renumbered a rule (GATE-1's
73
+ verified history). The trigger is the first one that does.
74
+
56
75
  ## Consequences
57
76
 
58
77
  - Breaking file layout (REQ-PKG-4): `data/rules.json` no longer carries
@@ -0,0 +1,80 @@
1
+ # ADR 0020 — The skeleton is a delta too: a jurisdiction's paragraphs are a merge patch over `intl`
2
+
3
+ Date: 2026-09-17
4
+ Status: proposed — merging this PR is the ruling; a revert undoes it
5
+
6
+ ## Context
7
+
8
+ ADR 0018 made the entries table a delta over `intl`. The skeleton was not
9
+ one. `data/rules.json` keyed every paragraph by bare path, one record per
10
+ key, and every one of them was `intl`; the corpus test asserted that a
11
+ corpus paragraph's path belongs to the corpus's own jurisdiction. So a
12
+ `us/inland` corpus could not carry `21(a)`: the key existed and was
13
+ `intl`'s. The 2026-08-30 diff of 33 CFR 83 against Part C found 18 paths
14
+ where Inland spells the same path with different text, three it does not
15
+ spell at all, and a dozen it adds. None of the 18 could be stated. That,
16
+ not a licence, is why the Inland corpus stub had no paragraphs (issue
17
+ #161), and why every planning session stalled on "the second jurisdiction".
18
+
19
+ Solace ruled on issue #137 on 2026-09-17: `us/inland`, Part C, before v1.
20
+
21
+ ## Decision
22
+
23
+ 1. **`rules.json` gains `deltas`, keyed by jurisdiction.** A delta has
24
+ `paragraphs` (own rows, keyed by path, each carrying its jurisdiction)
25
+ and `suppressions` (paths the source does not spell, each with a `why`).
26
+ `paragraphs` at the top level stays the `intl` base, untouched, so every
27
+ existing consumer reads what it read.
28
+
29
+ 2. **A jurisdiction's resolved skeleton is the RFC 7396 merge patch of its
30
+ delta over the base**, the same statement ADR 0018 makes for entries: own
31
+ rows present, suppressed paths `null`, an unmentioned path inherited
32
+ whole. A restated path merges field by field, so an own row that says
33
+ nothing about `images` inherits the base figure. The test builds the
34
+ patch, applies a literal RFC 7396 implementation, and asserts the
35
+ resolved skeleton is what corpora, entries and fixtures key into.
36
+
37
+ 3. **A path is stated in a delta when its text differs from `intl` or has no
38
+ `intl` counterpart; suppressed when the source does not spell it; silent
39
+ otherwise.** A `[Reserved]` section is a spelled path with reserved text,
40
+ so it is stated, not suppressed: Inland `28` and `26(d)` are rows whose
41
+ corpus text will be `[Reserved]`.
42
+
43
+ 4. **An entry in force under a jurisdiction cites a path in that
44
+ jurisdiction's resolved skeleton.** An inherited `intl` entry whose path
45
+ the delta suppresses cannot stand by silence: it is tombstoned, and where
46
+ the norm survives under another path, replaced (ADR 0018 point 3).
47
+
48
+ 5. **`us/inland` lands with its Part C skeleton delta**, every row from
49
+ `docs/verification/2026-08-30-q6-q8.md`: 19 restated paths (the 18
50
+ differing plus `28`), 18 Inland-only paths, and `23(d)(i)`, `23(d)(ii)`,
51
+ `23(d)(iii)` suppressed. A new sub-paragraph is stated when `intl`
52
+ already carries sibling sub-rows of that parent; where `intl`'s parent is
53
+ one row, the parent is restated and the sub-paragraph waits for the
54
+ corpus. So `24(f)`'s Inland `(iii)` and `22(d)`'s Inland `(ii)` wait
55
+ (`24(f)`, `22(d)` are one row each in `intl`), while `24(g)(v)` is stated
56
+ (`intl`'s `24(g)(i)` is a sibling row). `NRHB_23_e.png` and
57
+ `NRHB_24_j.png` are mapped to `23(e)` and `24(j)` and stop being
58
+ unmapped.
59
+
60
+ 6. **The first replace lands with it.** Inland 83.23(d) is the under-12 m
61
+ provision as one paragraph; `23(d)(i)` is not a path there. Point 4
62
+ forces the branch ADR 0018 left unexercised: `rule:23d_i` is tombstoned
63
+ under `us/inland` and `rule:23d`, same predicate and lights, cites
64
+ `23(d)`. Fixtures show both sides.
65
+
66
+ ## Consequences
67
+
68
+ - The Inland corpus can now be filled: every path it will carry resolves.
69
+ Text is 17 U.S.C. 105, so REQ-PROV-2 does not gate it. That is the next PR.
70
+ - `us/inland` is now six applicability records and a skeleton delta of 40
71
+ rows. README's coverage statement says so; it is still not a model of the
72
+ Inland Rules until the entries for the restated paths land.
73
+ - The skeleton edition `us/inland@2014` is declared and still recalled, not
74
+ verified against the Federal Register (REQ-LANG-10). The corpus fetch
75
+ verifies it or corrects it.
76
+ - GATE-1 is untouched: a path that differs across jurisdictions at one time
77
+ is REQ-MODEL-1 working as designed, and this ADR gives it a home.
78
+ - **Cost to reverse.** Delete `deltas` from data and schema, the resolver and
79
+ three tests, `rule:23d` and its tombstone, two fixtures; unmap two images.
80
+ No consumer reads `deltas` yet. Pre-1.0, a revert.
package/docs/budgets.json CHANGED
@@ -27,7 +27,8 @@
27
27
  "docs/adr/0019-relation-reach-and-import-reads.md": 110,
28
28
  "docs/timeline.md": 130,
29
29
  "docs/maritime-sources.md": 130,
30
- "docs/decisions.md": 40
30
+ "docs/decisions.md": 40,
31
+ "docs/adr/0020-skeleton-is-a-delta.md": 110
31
32
  },
32
33
  "json_prose": {
33
34
  "targets": [
package/docs/decisions.md CHANGED
@@ -6,3 +6,5 @@ each: date, short name, the answer, a link to the argument.
6
6
  - 2026-09-16 — docs ownership: colregs-engine's docs are sited wrong; colregs owns docs going forward, no new doc lands in colregs-engine. `normative-language.md` was already migrated the same day (commit fe0f8c2, #125); migration of the remaining three (`formal-methods-glossary.md`, `formal-methods-reading-list.md`, `engine-notes.md`) is not yet scheduled. Argued on kanban; no public writeup to link.
7
7
  - 2026-09-16 — own vs self: rename the subject segment `own` to `self` across the situation record (fact keys, precedence effect keys, facts.json, fixtures, docs/identifiers.md). Work spawned as [colregs#138](https://github.com/mark-brannan/colregs/issues/138).
8
8
  - 2026-09-16 — Q-54, Rule 17's phases are monotone: once 17(a)(ii) permission or the 17(b) duty has arisen for the stand-on vessel, it does not fall back on belated give-way compliance. Argued in [colregs#72](https://github.com/mark-brannan/colregs/issues/72); recorded in `docs/requirements.md`.
9
+ - 2026-09-16 — Q-53, 17(a)(ii) is an exception, not a suspension: the stand-on vessel's duty stands and a departure is lawful only as action to avoid collision; a monitor flags any other alteration. Argued in [colregs#72](https://github.com/mark-brannan/colregs/issues/72); recorded in `docs/requirements.md`.
10
+ - 2026-09-17 — second jurisdiction: `us/inland`, Part C, before v1. Ruled on [colregs#137](https://github.com/mark-brannan/colregs/issues/137); skeleton delta lands under ADR 0020, text and entries follow.
package/docs/gates.json CHANGED
@@ -11,6 +11,7 @@
11
11
  "first-non-english-corpus": "the second corpus of any one jurisdiction, which in practice is the first non-English text",
12
12
  "first-community-translation-of-national-corpus": "the first `community`-tier translation of a `national`-tier corpus",
13
13
  "first-external-contribution": "the first merged contribution from someone other than the copyright holder",
14
+ "first-undated-national-edition": "the first national text whose edition cannot be determined",
14
15
  "none": "the decline does not get cheaper or dearer with time; recorded so it is not re-read as merely deferred"
15
16
  },
16
17
  "statuses": {
@@ -79,6 +80,46 @@
79
80
  "status": "open",
80
81
  "settled_by": null,
81
82
  "note": "ADR 0004 settles the code licence (MIT \u2192 Apache-2.0) and leaves the data licence open. Already-published npm versions stay under the licence they shipped with; the gate governs future releases only, and is held open deliberately by REQ-PROV-7's CONTRIBUTING.md terms (DCO-style certification plus a relicensing grant); a CLA-assistant bot is the upgrade path if contributors arrive."
83
+ },
84
+ {
85
+ "id": "GATE-7",
86
+ "title": "validity intervals on editions (`in_force_until`)",
87
+ "declined_in": "docs/adr/0013-corpus-files-with-editions.md",
88
+ "closing_event": "first-undated-national-edition",
89
+ "trigger": "an edition superseded with no successor edition registered to bound it \u2014 repeal without replacement, or two editions of one jurisdiction whose validity ranges cannot be ordered from `superseded_by` alone",
90
+ "status": "open",
91
+ "settled_by": null,
92
+ "note": "Declined alongside ADR 0013 (option B, GATE-2 adopted): `superseded_by` plus `in_force` infers validity for every edition on file today. An explicit `in_force_until` is additive, not a rewrite, so paying for it before a case needs it buys nothing."
93
+ },
94
+ {
95
+ "id": "GATE-8",
96
+ "title": "a per-source publication record separate from the edition (FRBR manifestation)",
97
+ "declined_in": "docs/adr/0013-corpus-files-with-editions.md",
98
+ "closing_event": "first-undated-national-edition",
99
+ "trigger": "two distinct published sources for the same edition that disagree \u2014 e.g. an official gazette printing and a codifier's republication of the same edition differing in errata \u2014 so \"the source\" stops being a property of the edition",
100
+ "status": "open",
101
+ "settled_by": null,
102
+ "note": "Declined alongside ADR 0013: today `source` lives on the corpus and one edition has one source per jurisdiction. A manifestation layer is additive when a second publication record is actually needed."
103
+ },
104
+ {
105
+ "id": "GATE-9",
106
+ "title": "a content digest per corpus for verification",
107
+ "declined_in": "docs/adr/0013-corpus-files-with-editions.md",
108
+ "closing_event": "first-undated-national-edition",
109
+ "trigger": "a corpus found to differ from its cited source with no accompanying edition or source change \u2014 silent drift a hash would have caught and prose review did not",
110
+ "status": "open",
111
+ "settled_by": null,
112
+ "note": "Declined alongside ADR 0013: `edition_status` (verified/claimed/unknown, this ADR's before-merge item 1) already flags an unchecked corpus. A digest adds tamper/drift detection on top, which nothing on file today has needed."
113
+ },
114
+ {
115
+ "id": "GATE-10",
116
+ "title": "a skeleton per edition",
117
+ "declined_in": "docs/adr/0013-corpus-files-with-editions.md",
118
+ "closing_event": "first-undated-national-edition",
119
+ "trigger": "the first amendment that deletes or renumbers a path",
120
+ "status": "open",
121
+ "settled_by": null,
122
+ "note": "Declined alongside ADR 0013: one shared `data/rules.json` skeleton is low risk because no amendment has ever renumbered a rule (seven IMO amendments since 1972, none doing so). A per-edition skeleton is the fallback the day one does."
82
123
  }
83
124
  ]
84
125
  }
@@ -26,6 +26,12 @@ question the rule text leaves open.
26
26
  - **Nautical Institute — *Action by the Stand-On Vessel*** (Seaways case study). The stand-on vessel's stages as taught; does not reach whether they are reversible.
27
27
  <https://www.nautinst.org/resources-page/200115-action-by-the-stand-on-vessel.html>
28
28
  - **USCG Navigation Rules (Amalgamated)**. <https://www.navcen.uscg.gov/navigation-rules-amalgamated>
29
+ - **Steamship Mutual — *Navigation in Restricted Visibility***. Confirms Section II reapplies once vessels are in sight of one another again; silent on whether status accumulated before the loss of sight (a `Q-51`/`Q-52` classification, a `Q-54` Rule 17 stage) carries forward.
30
+ <https://www.steamshipmutual.com/publications/articles/restrictedvisibility0109>
31
+ - **Britannia P&I — *Navigation in restricted visibility***. No stand-on vessel exists under Rule 19; also silent on status continuity across the transition.
32
+ <https://britanniapandi.com/en_gb/guidance/navigation-in-restricted-visibility/>
33
+ - **Professional Mariner — *Overtaking or crossing? Don't assume what other ship will do***. The Rule 13(d) bearing-shift overtaking history, discussed only within continuous visual contact.
34
+ <https://professionalmariner.com/overtaking-or-crossing-dont-assume-what-other-ship-will-do/>
29
35
 
30
36
  ## Marine incident analysis
31
37
 
@@ -47,6 +53,16 @@ ambiguous give-way/stand-on roles are what the Rules are written against.
47
53
  <https://www.bahamasmaritime.com/wp-content/uploads/2026/02/2026-5-Polesie-Verity-ReportAndAnnexes.pdf>
48
54
  - IMO GISIS Marine Casualties and Incidents module. Not a paper but a source class: the mandatory-reporting database of marine safety investigation reports. Ground truth for real COLREGS-relevant incidents.
49
55
  <https://www.imo.org/en/OurWork/IIIS/Pages/Marine-Safety-Investigation-reports.aspx>
56
+ - NTSB/MAR-16/01 — *Conti Peridot*/*Carla Maersk* collision, Houston Ship Channel. Occurred entirely within restricted visibility; no in-sight phase, no Rule 13/17 discussion. Checked for `Q-55` and found not on point.
57
+ <https://www.ntsb.gov/investigations/AccidentReports/Reports/MAR1601.pdf>
58
+ - Dutch Safety Board — *Collision in Restricted Visibility* (*VB Seal*/*Gulholmen*, Maasmond, 2026). Rules appendix cites only Rules 6 and 19; the encounter never had an in-sight phase. Checked for `Q-55` and found not on point.
59
+ <https://onderzoeksraad.nl/wp-content/uploads/2026/07/collision-in-restricted-visibility.pdf>
60
+ - TSB Canada M23C0143 — ferry *Svanoy*. Fog/lookout casualty; no Section II status question arises.
61
+ <https://www.tsb.gc.ca/eng/rapports-reports/marine/2023/m23c0143/m23c0143.html>
62
+ - SWZ Maritime on Nautical Institute MARS 202601 (near-miss in fog). Operational-failure summary only; no rule-regime discussion.
63
+ <https://swzmaritime.nl/news/2026/02/13/near-vessel-collision-in-fog/> · MARS index: <https://www.nautinst.org/technical-resources/mars.html>
64
+ - Marine Insight — fog/TSS-turn collision write-up. Overtaking occurred entirely within fog; no visibility transition at issue.
65
+ <https://www.marineinsight.com/real-life-incident-vessels-collide-in-dense-fog-during-sudden-tss-turn/>
50
66
 
51
67
  ## Known gaps
52
68
 
@@ -55,4 +71,5 @@ ambiguous give-way/stand-on roles are what the Rules are written against.
55
71
  manoeuvrability, shoal water, a lee shore, set, visibility or sea state.
56
72
  - Two standard texts — Cockcroft & Lameijer, *A Guide to the Collision Avoidance Rules*, and Farwell's *Rules of the Nautical Road* — are not online. Either may settle how the stages of a close-quarters encounter are divided, and whether they are treated as irreversible.
57
73
  - Several of the questions in `docs/requirements.md` §11 appear unlitigated: overtaking geometry with no risk of collision, an overtaking situation becoming a head-on, resumption of course by a stand-on vessel that has acted, and the fate of accumulated Section II state across a visibility transition.
74
+ - `Q-55` (visibility transition): checked casualty reports, P&I guidance and trade-press commentary beyond the sources above — no authority found in either direction on whether a `Q-51`/`Q-52` classification or a `Q-54` Rule 17 stage survives a restricted-visibility interruption or resets on regaining sight. Deferred indefinitely, 2026-09-16; Cockcroft & Lameijer and Farwell (both already listed above as unreachable) remain the most plausible sources to settle it.
58
75
  - BAILII refuses automated access. Use the National Archives Find Case Law service: <https://caselaw.nationalarchives.gov.uk/>
@@ -396,7 +396,9 @@ without further action by the give-way vessel.
396
396
  - **Formally.** Reachability over the stand-on vessel's manoeuvring envelope:
397
397
  `Safe(s, σ_own, σ_other)` of ADR 0005 §5 with the give-way strategy set
398
398
  unconstrained — the first Part B invariant needing `kin:dynamics`.
399
- - **Reading in doubt.** Suspension or exception: `Q-53`.
399
+ - **Reading ruled.** Exception, not suspension (`Q-53`, 2026-09-16): the
400
+ 17(a)(i) duty stands and the only lawful departure is action to avoid
401
+ collision; a checker flags any other alteration.
400
402
 
401
403
  ### INV-17b — phase 3: the stand-on vessel shall act
402
404
 
@@ -639,8 +639,7 @@ specification until 1.0.
639
639
 
640
640
  ### Open gates
641
641
 
642
- Each gate names the declined design, the closing event, and the trigger.
643
-
642
+ Each names the declined design, closing event, and trigger.
644
643
  - **GATE-1 — `paragraph_id` split from `citation_path`**
645
644
  (ADR 0003, declined; REQ-LANG-3, REQ-PKG-4).
646
645
  *Closing event*: the 1.0 tag. Before it, splitting the two is a
@@ -764,8 +763,9 @@ Each gate names the declined design, the closing event, and the trigger.
764
763
  unlikely short of major success. Recorded regardless: "unlikely" is not
765
764
  a closing event (REQ-GATE-1).
766
765
 
767
- Gates whose closing event is "none" are recorded because a future reader
768
- will otherwise re-ask whether they were merely deferred. They were not.
766
+ Four gates from ADR 0013 (option B), *closing event* for all four the first national text whose edition cannot be determined: **GATE-7 — validity intervals on editions (`in_force_until`)**, trigger an edition superseded with no successor to bound it; **GATE-8 — a per-source publication record separate from the edition (FRBR manifestation)**, trigger two published sources for one edition that disagree; **GATE-9 — a content digest per corpus for verification**, trigger a corpus differing from its cited source with no edition or source change; **GATE-10 — a skeleton per edition**, trigger the first amendment that deletes or renumbers a path.
767
+
768
+ Gates whose closing event is "none" are recorded because a future reader will otherwise re-ask whether they were merely deferred. They were not.
769
769
 
770
770
  ### Gate status is data
771
771
 
@@ -1416,6 +1416,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1416
1416
  - Default: narrow (nothing changes).
1417
1417
  - Recommendation: narrow — the test named below shows the fact resolves out of sight
1418
1418
  (`Q-49: hist:was_overtaking resolves out of sight; rule:13d does not fire`, `test/data.test.mjs`).
1419
+ - **Q-58** — **Do the Rule 18/12 role entries need `other:hist:was_overtaking: false`, like `rule:13a` and `rule:15a:keep_out_of_the_way` (Q-47)?** The nine `18a*`/`18b*`/`18c*` and three `12a*` entries carry no such gate, and `rule:13a` overrides them only when *self* holds the history; when the *other* holds it, self is named give-way under Rule 18 or 12 while 13(a) puts the duty on the other alone. Default **ungated** (nothing changes), recorded as a `gap` on the twelve. Recommend **gated**, in Q-47's shape: 13(a)'s 'notwithstanding' and Rule 18's own exception for Rule 13 both displace these entries, and Q-47 already ruled the history decides who holds the role. colregs-engine#75 (closed) read the table as self-centric and recommended a consumer swap subjects for the other's duty; that answers the other's role, not self's wrong one. `colregs#117`.
1419
1420
 
1420
1421
  ### From the Part B invariants (P4.1)
1421
1422
 
@@ -1426,21 +1427,19 @@ nothing is blocked while open.
1426
1427
  - **Q-50** — **Does risk of collision gate Rules 13 and 18?** 14(a) and 15(a)
1427
1428
  say "so as to involve risk of collision"; Rule 13 and Rule 18 do not.
1428
1429
  *Wide:* they attach whenever in sight and the geometry holds — Rule 11 is the
1429
- only gate Section II states — so a vessel overtaking a mile clear abeam is
1430
- give-way and Rule 16 binds her. *Narrow:* Section II's duties attach only with
1430
+ only gate Section II states. *Narrow:* Section II's duties attach only with
1431
1431
  risk of collision; 14 and 15 are emphasis. Default **wide**: `rule:13a`, `rule:13b`,
1432
- `rule:13d` and every Rule 18 entry read `in_sight` only. No recommendation.
1432
+ `rule:13d` and every Rule 18 entry read `in_sight` only. **Ruled
1433
+ 2026-09-17:** wide — the window is the encounter itself. A pair the engine is
1434
+ evaluating is an encounter, at whatever range suits the vessels; inside it 13
1435
+ and 18 attach on sight and geometry alone, and how close is clear stays a
1436
+ monitor parameter. *The Nowy Sacz* [1977] 2 Lloyd's Rep 91 (CA) holds risk
1437
+ of collision unnecessary for the overtaking rule; *Meghna Princess* [2017]
1438
+ SGHC 220 [56] restates it; nothing found on Rule 18 either way (colregs#72).
1433
1439
  - **Q-51** — **What arms 13(d)'s overtaking history?** *A:* 13(b)'s deeming, at the first
1434
1440
  state the geometry holds. *B:* 13(a)'s duty actually attaching. They differ
1435
- where the geometry holds but a condition on 13(a) does not — `Q-50`'s
1436
- surface. Pencilled **B** ✎ (Solace, 2026-09-14): the overtaking history arms when the
1437
- duty attaches. KIVELI [2025] EWHC 1185 (Admlty) holds the analogous Rule 14
1438
- history arms on risk of collision and then persists; no authority was found on
1439
- overtaking geometry with no risk of collision. Free to reverse: four entries
1440
- (`rule:13a`, `rule:13b`, `rule:13d`) and their fixtures, and nothing consumes the one
1441
- state this changes the answer for. Settled by: a decision on Rule 13 itself,
1442
- or Cockcroft & Lameijer on whether overtaking status needs risk of
1443
- collision.
1441
+ only on `Q-50`'s surface. **Ruled 2026-09-17:** B, closed by `Q-50` wide —
1442
+ with no gate between geometry and duty the two readings coincide (colregs#72).
1444
1443
  - **Q-52** — **What does 13(d)'s overtaking history forbid?** *Narrow:* reclassification to
1445
1444
  *crossing* only, as the paragraph says, leaving head-on to Rule 14 on the
1446
1445
  geometry of the moment. *Broad:* the encounter stays an overtaking and no
@@ -1456,9 +1455,10 @@ nothing is blocked while open.
1456
1455
  *Suspension:* "may, however" lifts the duty once non-compliance is apparent;
1457
1456
  a monitor then flags nothing. *Exception:* the duty stands and a departure is
1458
1457
  lawful only as action to avoid collision by her manoeuvre alone; a monitor
1459
- flags any other alteration. No default (Rule 17 has no entry). Recommend
1460
- **exception**: 17(a)(ii) describes an action, not a proviso, and leaves a
1461
- monitor something to check — a drafting argument, not a source.
1458
+ flags any other alteration. No default (Rule 17 has no entry). **Ruled
1459
+ 2026-09-16:** exception — the 17(a)(i) duty stands and a departure is lawful
1460
+ only as action to avoid collision; a monitor flags any other alteration.
1461
+ Purpose, not source (colregs#72); read with `Q-54`.
1462
1462
  - **Q-54** — **Are Rule 17's phases monotone?** *Monotone:* one three-valued
1463
1463
  marker per stand-on vessel per encounter; late compliance does not take the
1464
1464
  permission away. *Re-evaluating:* each phase is a predicate on the current
@@ -1471,8 +1471,9 @@ nothing is blocked while open.
1471
1471
  becomes of a 13(d) overtaking history or a Rule 17 phase. *Persisting:* they belong to the
1472
1472
  encounter and survive the fog. *Resetting:* Section II starts afresh on the
1473
1473
  geometry when sight is regained — the reclassification 13(d) forbids, via
1474
- visibility. No default (nothing is temporal). Recommend **persisting**, which
1475
- `INV-13d`'s "same encounter" is written for; likeliest surprising TLC trace.
1474
+ visibility. No default (nothing is temporal). **Deferred indefinitely** (Solace,
1475
+ 2026-09-16): no authority either way (colregs#72); scenario contrived. Lean, not
1476
+ ruling: **resetting** — a new encounter after the fog; persisting withdrawn.
1476
1477
  - **Q-56** — **The third visibility state: a hole, or closed by the model?**
1477
1478
  Not in sight *and* not in or near restricted visibility (clear weather, beyond
1478
1479
  visual range, radar contact) is outside Rule 11 and 19(a): Section I only.
@@ -1494,7 +1495,5 @@ module, expensive after.
1494
1495
 
1495
1496
  A third, ruled rather than pencil: **`docs/part-b-invariants.md` stays
1496
1497
  hand-written Markdown; no derived JSON registry.** Ruled 2026-09-08. Revisit
1497
- only if P4.2's TLA+ needs to cite `INV-` ids mechanically — the id scheme
1498
- just above is already the cheap-to-change half of that trigger, so the
1499
- revisit costs one file's worth of tooling, not a re-derivation of the ids
1500
- themselves.
1498
+ only if P4.2's TLA+ needs to cite `INV-` ids mechanically; the cost then is one
1499
+ file's worth of tooling, not a re-derivation of the ids.
@@ -936,7 +936,7 @@
936
936
  "expect": []
937
937
  },
938
938
  {
939
- "name": "6 m outboard, max speed 6 kn, US Inland: 23(d)(ii) has no Inland counterpart, 23(d)(i) and 23(a) are inherited",
939
+ "name": "6 m outboard, max speed 6 kn, US Inland: 23(d)(ii) has no Inland counterpart, 23(d)(i) is replaced by 23(d), 23(a) is inherited",
940
940
  "jurisdiction": "us/inland",
941
941
  "facts": {
942
942
  "fact:propulsion": "propulsion:power",
@@ -949,7 +949,7 @@
949
949
  "rule:23a_i",
950
950
  "rule:23a_ii",
951
951
  "rule:23a_iii_iv",
952
- "rule:23d_i"
952
+ "rule:23d"
953
953
  ]
954
954
  },
955
955
  {
@@ -965,6 +965,54 @@
965
965
  "rule:30a",
966
966
  "rule:30c"
967
967
  ]
968
+ },
969
+ {
970
+ "name": "same yacht motoring, US Inland: 23(d)(i) is replaced by Inland 23(d)",
971
+ "jurisdiction": "us/inland",
972
+ "facts": {
973
+ "fact:propulsion": "propulsion:power",
974
+ "fact:activity": "activity:none",
975
+ "fact:position": "position:underway",
976
+ "fact:length_m": 11.6
977
+ },
978
+ "expect": [
979
+ "rule:23a_i",
980
+ "rule:23a_ii",
981
+ "rule:23a_iii_iv",
982
+ "rule:23d"
983
+ ]
984
+ },
985
+ {
986
+ "name": "pushing ahead, not a composite unit, US Inland: 24(c)(iii) replaces the sternlight with two towing lights",
987
+ "jurisdiction": "us/inland",
988
+ "facts": {
989
+ "fact:propulsion": "propulsion:power",
990
+ "fact:activity": "activity:pushing",
991
+ "fact:position": "position:underway",
992
+ "fact:length_m": 30,
993
+ "fact:composite_unit": false
994
+ },
995
+ "expect": [
996
+ "rule:24c:towing_lights",
997
+ "rule:24c:underway_lights"
998
+ ]
999
+ },
1000
+ {
1001
+ "name": "pushing ahead, not a composite unit, at anchor, US Inland (issue #137 review: sidelights/towing lights are underway-gated, masthead only at anchor)",
1002
+ "jurisdiction": "us/inland",
1003
+ "facts": {
1004
+ "fact:propulsion": "propulsion:power",
1005
+ "fact:activity": "activity:pushing",
1006
+ "fact:position": "position:anchored",
1007
+ "fact:length_m": 30,
1008
+ "fact:composite_unit": false
1009
+ },
1010
+ "expect": [
1011
+ "rule:24c:towing_lights",
1012
+ "rule:30a",
1013
+ "rule:30b",
1014
+ "rule:30c"
1015
+ ]
968
1016
  }
969
1017
  ]
970
1018
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "colregs",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "COLREGS 72 and its national amalgamations as language-neutral JSON — rule text, light definitions, and applicability predicates — with cross-implementation fixtures",
5
5
  "license": "Apache-2.0",
6
6
  "colregs": {
@@ -9,7 +9,6 @@
9
9
  "colregs",
10
10
  "applied",
11
11
  "exempted",
12
- "excluded",
13
12
  "overridden",
14
13
  "displays",
15
14
  "optional_additions",
@@ -27,9 +26,6 @@
27
26
  "exempted": {
28
27
  "$ref": "evaluation.schema.json#/$defs/byEntryList"
29
28
  },
30
- "excluded": {
31
- "$ref": "evaluation.schema.json#/$defs/byEntryList"
32
- },
33
29
  "overridden": {
34
30
  "$ref": "evaluation.schema.json#/$defs/byEntryList"
35
31
  },
@@ -12,6 +12,54 @@
12
12
  "note": {
13
13
  "type": "string"
14
14
  },
15
+ "paragraphs": {
16
+ "$ref": "#/$defs/paragraphs"
17
+ },
18
+ "deltas": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "description": "Per-jurisdiction skeleton deltas over `paragraphs` (ADR 0020): own paragraphs by path, suppressed paths, everything else inherited.",
22
+ "patternProperties": {
23
+ "^[a-z]+(/[a-z]+)+$": {
24
+ "type": "object",
25
+ "additionalProperties": false,
26
+ "required": [
27
+ "paragraphs",
28
+ "suppressions"
29
+ ],
30
+ "properties": {
31
+ "note": {
32
+ "type": "string"
33
+ },
34
+ "paragraphs": {
35
+ "$ref": "#/$defs/paragraphs"
36
+ },
37
+ "suppressions": {
38
+ "type": "array",
39
+ "items": {
40
+ "type": "object",
41
+ "additionalProperties": false,
42
+ "required": [
43
+ "path",
44
+ "why"
45
+ ],
46
+ "properties": {
47
+ "path": {
48
+ "$ref": "evaluation.schema.json#/$defs/paragraphCite"
49
+ },
50
+ "why": {
51
+ "type": "string",
52
+ "minLength": 1
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ }
61
+ },
62
+ "$defs": {
15
63
  "paragraphs": {
16
64
  "type": "object",
17
65
  "additionalProperties": false,
@@ -1,22 +0,0 @@
1
- {
2
- "id": "intl@2016.fi.finlex",
3
- "edition": "intl@2016",
4
- "edition_status": "claimed",
5
- "language": "fi",
6
- "source_id": "finlex",
7
- "tier": "national",
8
- "normalization": "NFC",
9
- "source": {
10
- "publisher": "Finlex (Oikeusministeriö), Suomen säädöskokoelman sopimussarja",
11
- "title": "Asetus kansainvälisistä säännöistä yhteentörmäämisen ehkäisemiseksi merellä vuonna 1972 tehdyn yleissopimuksen voimaansaattamisesta, SopS 30/1977",
12
- "url": "https://www.finlex.fi/fi/sopimukset/sopsteksti/1977/19770030",
13
- "retrieved": "2026-09-12"
14
- },
15
- "rights": {
16
- "source_text": "Tekijänoikeuslaki 404/1961 §9: no copyright in treaties and their official translations",
17
- "redistribution_basis": "Finlex FAQ: published materials carry no usage restriction; open data CC BY 4.0",
18
- "package_licence": "Apache-2.0"
19
- },
20
- "note": "Stub: identity and provenance only; the Finnish text is not transcribed yet. GATE-2 is adopted in docs/gates.json, settled by ADR 0013, so nothing structural blocks it.",
21
- "paragraphs": {}
22
- }