colregs 0.3.0 → 0.3.2
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/README.md +13 -11
- package/data/applicability.json +478 -503
- package/data/facts.json +22 -22
- package/data/geometry.json +8 -8
- package/data/i18n/en.json +27 -0
- package/data/i18n/fi.json +25 -0
- package/data/images.json +32 -32
- package/data/operations.json +79 -0
- package/data/rules.json +5 -0
- package/data/version.json +1 -1
- package/docs/adr/0006-json-schema-and-identifier-diff.md +2 -0
- package/docs/adr/0011-api-shape.md +7 -7
- package/docs/adr/0012-trace-and-rule2-departure-api.md +2 -2
- package/docs/adr/0014-engine-interface-owned-by-colregs.md +103 -0
- package/docs/adr/0015-rule-ids-are-paragraph-keys.md +191 -0
- package/docs/adr/0016-encounter-roles-are-pooled-across-frames.md +82 -0
- package/docs/adr/0017-closed-vocabularies-are-prefixed-identifiers.md +105 -0
- package/docs/budgets.json +8 -15
- package/docs/decisions.md +6 -0
- package/docs/identifiers.md +121 -109
- package/docs/maritime-sources.md +58 -0
- package/docs/normative-language.md +103 -0
- package/docs/part-b-invariants.md +48 -45
- package/docs/requirements.md +147 -138
- package/fixtures/applicability-fixtures.json +190 -190
- package/fixtures/situation-fixtures.json +870 -599
- package/package.json +1 -1
- package/schema/applicability-fixtures.schema.json +4 -13
- package/schema/applicability.schema.json +77 -77
- package/schema/conduct-evaluation.schema.json +135 -0
- package/schema/display-evaluation.schema.json +146 -0
- package/schema/encounter-evaluation.schema.json +109 -0
- package/schema/evaluation.schema.json +149 -0
- package/schema/fact-record.schema.json +30 -0
- package/schema/facts.schema.json +4 -4
- package/schema/i18n-catalog.schema.json +47 -0
- package/schema/operations.schema.json +124 -0
- package/schema/rule2-departure-finding.schema.json +72 -0
- package/schema/rule2-departure-model.schema.json +159 -0
- package/schema/situation-fixtures.schema.json +30 -127
- package/schema/situation.schema.json +72 -0
- package/schema/trace.schema.json +33 -0
- package/data/deprecated-identifiers.json +0 -7
- package/schema/deprecated-identifiers.schema.json +0 -29
package/docs/requirements.md
CHANGED
|
@@ -53,10 +53,10 @@ Neither consumer lives in this repo.
|
|
|
53
53
|
| **paragraph path** | The citation unit: `27(a)(i)`, `25(d)(ii)`. Not the rule number. |
|
|
54
54
|
| **fact record** | A set of facts about one vessel at one moment; the input. |
|
|
55
55
|
| **entry** | One applicability record: predicate → lights/refs → modality → citation. |
|
|
56
|
-
| **modality** | `shall` / `may` / `shall-if-practicable`. |
|
|
56
|
+
| **modality** | `modality:shall` / `modality:may` / `modality:shall-if-practicable`. |
|
|
57
57
|
| **jurisdiction** | A body of rules: `intl`, `us/inland`, `ca/inland`, … |
|
|
58
58
|
| **delta** | A jurisdiction's departures from the international text. |
|
|
59
|
-
| **identifier** | Any name the data is addressed by: entry id, paragraph path, light id, fact key, fact value, relation name. |
|
|
59
|
+
| **identifier** | Any name the data is addressed by: entry id, paragraph path, light id, fact key, fact value, relation name, modality/role/encounter/category value, jurisdiction value. |
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
@@ -68,7 +68,7 @@ Neither consumer lives in this repo.
|
|
|
68
68
|
applicability entry and every rule-text record, expressed as
|
|
69
69
|
`<country-or-body>/<waters>` with `intl` as the reserved base value.
|
|
70
70
|
Examples: `intl`, `us/inland`, `us/great-lakes`, `us/western-rivers`,
|
|
71
|
-
`ca/inland`, `de/binnen`, `eu/cevni`.
|
|
71
|
+
`ca/inland`, `de/binnen`, `eu/cevni`. The jurisdiction value is itself an identifier, unprefixed and immutable under REQ-MODEL-10 (ADR 0017).
|
|
72
72
|
- **REQ-SCOPE-3** — A jurisdiction MUST be expressible as a *delta*: entries
|
|
73
73
|
absent from a jurisdiction's data inherit from `intl`. A jurisdiction MUST
|
|
74
74
|
NOT require restating the whole body of rules. Inheritance is "unless
|
|
@@ -79,7 +79,7 @@ Neither consumer lives in this repo.
|
|
|
79
79
|
exists. That bar is about suppression, not licensing: it is independent of
|
|
80
80
|
REQ-PROV-2 and ADR 0010, and it binds whether a jurisdiction's text ships or
|
|
81
81
|
is withheld. A delta that only *adds* entries is exempt: it suppresses nothing,
|
|
82
|
-
so the Q-11 hazard cannot arise from it (ADR 0008, `30a
|
|
82
|
+
so the Q-11 hazard cannot arise from it (ADR 0008, `rule:30a:mooring_buoy`/`rule:30b:mooring_buoy`).
|
|
83
83
|
A delta that suppresses or replaces an `intl` entry still waits.
|
|
84
84
|
- **REQ-SCOPE-4** — Adding a jurisdiction MUST be additive. It MUST NOT require
|
|
85
85
|
a schema change or edits to existing `intl` entries.
|
|
@@ -156,7 +156,7 @@ Four layers, each independently addressable.
|
|
|
156
156
|
identifiers do not.
|
|
157
157
|
- **REQ-MODEL-4** — **Applicability entries**: `when` (predicate over facts) →
|
|
158
158
|
lights or refs → modality → citation → jurisdiction. Every entry MUST have a
|
|
159
|
-
stable id
|
|
159
|
+
stable id, a paragraph key in the `rule:` namespace (`rule:25d_i`; ADR 0015).
|
|
160
160
|
- **REQ-MODEL-5** — Gates MUST be expressed as predicates over facts
|
|
161
161
|
(`fact:length_m < 7`), never as pre-enumerated tuples or configuration counts. Any
|
|
162
162
|
count of "configurations" is an output of evaluation, never an input to the
|
|
@@ -168,7 +168,7 @@ Four layers, each independently addressable.
|
|
|
168
168
|
- `rel:in_lieu_of` — legal alternatives for the same fact record;
|
|
169
169
|
- `rel:excludes` — mutual exclusion, including across rules; symmetric
|
|
170
170
|
(A excludes B implies B excludes A), and no participating entry MAY be
|
|
171
|
-
forceful (`shall`/`shall-if-practicable`) — a directed "this one
|
|
171
|
+
forceful (`modality:shall`/`modality:shall-if-practicable`) — a directed "this one
|
|
172
172
|
prevails" is `rel:overrides` (ADR 0007), not `rel:excludes`;
|
|
173
173
|
- `rel:exempts` — one entry lifting another's obligation;
|
|
174
174
|
- `rel:conditional_includes` — import or alternatives, gated on a predicate.
|
|
@@ -187,8 +187,8 @@ Four layers, each independently addressable.
|
|
|
187
187
|
ADR 0005 §4.
|
|
188
188
|
- **REQ-MODEL-12** — `rel:conditional_includes` currently carries three
|
|
189
189
|
distinct shapes under one relation name: a bare `one_of` alternative set
|
|
190
|
-
(`
|
|
191
|
-
import with its own citation (`when` + `rel:includes` + `cite`, `29a`). Which
|
|
190
|
+
(`rule:25d_ii`), a gated alternative set (`when` + `one_of`, `rule:27f`), and a gated
|
|
191
|
+
import with its own citation (`when` + `rel:includes` + `cite`, `rule:29a`). Which
|
|
192
192
|
behaviour applies is inferred from which keys are present. This is a
|
|
193
193
|
**soft** requirement — the data is correct today and the tests cover it,
|
|
194
194
|
so nothing is broken. It is recorded because a third jurisdiction adding
|
|
@@ -211,7 +211,7 @@ Four layers, each independently addressable.
|
|
|
211
211
|
denoted, MUST be marked deprecated in data with the version that
|
|
212
212
|
deprecated it, and MUST NOT be removed in the same major version.
|
|
213
213
|
- **Mutating** one is forbidden. This covers the obvious case (renaming
|
|
214
|
-
`25b`) and the dangerous quiet one: an identifier keeping its spelling
|
|
214
|
+
`rule:25b`) and the dangerous quiet one: an identifier keeping its spelling
|
|
215
215
|
while changing what it denotes — a paragraph path repointed at
|
|
216
216
|
different text, a fact value narrowed, a light id reassigned. A
|
|
217
217
|
consumer cannot detect this, and every stored citation becomes silently
|
|
@@ -225,29 +225,28 @@ Four layers, each independently addressable.
|
|
|
225
225
|
removing an identifier is a major version (REQ-PKG-4); repointing one is
|
|
226
226
|
not a version event at all, because it is not permitted.
|
|
227
227
|
|
|
228
|
-
**Immutability baseline: `0.
|
|
229
|
-
identifier present in
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
2026-08-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
re-stated in a later version, or joined by a second baseline clause. This
|
|
243
|
-
clause is the whole of the exception; there is no mechanism for granting
|
|
244
|
-
another. Without that, "move the baseline" is a silent escape hatch from
|
|
228
|
+
**Immutability baseline: `1.0.0`.** The prohibitions above bind every
|
|
229
|
+
identifier present in `colregs@1.0.0` and every identifier introduced
|
|
230
|
+
from then on. Identifiers as they stood before `1.0.0` are outside the
|
|
231
|
+
baseline: while the package is pre-1.0 the schema is being designed, and
|
|
232
|
+
an identifier may be renamed or discarded without a deprecation record.
|
|
233
|
+
The baseline was first set at `0.1.1` on 2026-08-30, the day after the
|
|
234
|
+
package was seeded, so that the identifier review this requirement calls
|
|
235
|
+
for could happen at all. It was moved to `1.0.0` by Solace's ruling on
|
|
236
|
+
#121 (ADR 0015, 2026-09-16), which reshaped every entry id into a
|
|
237
|
+
paragraph key in the `rule:` namespace.
|
|
238
|
+
|
|
239
|
+
From `1.0.0` the baseline is **fixed**. It MUST NOT be moved, raised,
|
|
240
|
+
re-stated in a later version, or joined by a second baseline clause.
|
|
241
|
+
Without that, "move the baseline" is a silent escape hatch from
|
|
245
242
|
REQ-MODEL-10 and the exception becomes the pattern — a specification that
|
|
246
243
|
can suspend its own prohibition by editing one number is advisory, not
|
|
247
|
-
normative.
|
|
244
|
+
normative.
|
|
248
245
|
|
|
249
246
|
`test/data.test.mjs` pins the baseline literal and asserts it is stated
|
|
250
|
-
exactly once.
|
|
247
|
+
exactly once. There is no identifier diff against the last release: ADR 0006
|
|
248
|
+
proposed one, ADR 0015 removed it pre-1.0, and it returns with the baseline
|
|
249
|
+
tag if at all. A build has no access to git history, so it cannot see the
|
|
251
250
|
number being *edited* in place; a test that reconstructed history to
|
|
252
251
|
check would cost more than it is worth and would still pass on a rewritten
|
|
253
252
|
history. What it can refuse is a **second** baseline clause, which is the
|
|
@@ -274,14 +273,18 @@ Four layers, each independently addressable.
|
|
|
274
273
|
names, not a modelling convenience of this package.
|
|
275
274
|
- **`nuc`, `cbd`, `ram`, `ram_underwater`** — kept unspelled as terms of
|
|
276
275
|
art; see `docs/identifiers.md` for the reasoning and the trap in `ram`.
|
|
276
|
+
|
|
277
|
+
ADR 0015 (Solace's ruling on #121, 2026-09-16) reopened the first two
|
|
278
|
+
bullets: an entry id is a paragraph key in the `rule:` namespace now, and
|
|
279
|
+
the suffix taxonomy went with it. They stand as the audit's record.
|
|
277
280
|
- **REQ-MODEL-11** — Deprecated identifiers MUST be recorded as data — a
|
|
278
281
|
registry naming each retired identifier, what it denoted, the version that
|
|
279
282
|
deprecated it, and its replacement where one exists. Prose in a changelog
|
|
280
283
|
MUST NOT stand in for it: a consumer pinned to an old version needs to
|
|
281
|
-
resolve a stale identifier mechanically. The registry is
|
|
282
|
-
`
|
|
283
|
-
|
|
284
|
-
|
|
284
|
+
resolve a stale identifier mechanically. **The registry is absent until
|
|
285
|
+
`1.0.0`.** ADR 0015 deleted it, and the diff that read it: nothing before
|
|
286
|
+
the baseline is immutable, so nothing before it can be retired, and an
|
|
287
|
+
empty file with a dormant test is a mechanism that cannot fire.
|
|
285
288
|
|
|
286
289
|
### 4.1 Rule categories and the situation record
|
|
287
290
|
|
|
@@ -294,27 +297,27 @@ towards, not because the shape is settled.
|
|
|
294
297
|
two-subject entries and defaulted for the rest; no record in `rules.json`
|
|
295
298
|
carries one, so a paragraph with no entry is uncategorised)** —
|
|
296
299
|
Every rule paragraph record MUST carry exactly one `category` from the
|
|
297
|
-
closed set `scope`, `definition`, `standard`, `display`,
|
|
298
|
-
`classification`, `precedence`, `conduct`, `care`, `meta`. The field
|
|
299
|
-
defaults to `display`, so existing entries are correct unedited. CI MUST
|
|
300
|
+
closed set `category:scope`, `category:definition`, `category:standard`, `category:display`,
|
|
301
|
+
`category:classification`, `category:precedence`, `category:conduct`, `category:care`, `category:meta`. The field
|
|
302
|
+
defaults to `category:display`, so existing entries are correct unedited. CI MUST
|
|
300
303
|
fail on a value outside the set. Where a paragraph plays a second role,
|
|
301
304
|
that role MUST be expressed as a relation (REQ-CAT-3), never as a second
|
|
302
305
|
category.
|
|
303
|
-
- **REQ-CAT-2** — `care` and `meta` paragraphs (Rules 2(a) and 2(b)) MUST NOT
|
|
306
|
+
- **REQ-CAT-2** — `category:care` and `category:meta` paragraphs (Rules 2(a) and 2(b)) MUST NOT
|
|
304
307
|
be applicability entries. They MUST be recorded in a registry sibling to
|
|
305
308
|
`known_omissions`, stating that the package represents them and evaluates
|
|
306
|
-
neither. CI MUST fail on a `care` or `meta` paragraph that appears as an
|
|
309
|
+
neither. CI MUST fail on a `category:care` or `category:meta` paragraph that appears as an
|
|
307
310
|
entry.
|
|
308
|
-
- **REQ-CAT-3** **(unimplemented in part — `shall-not` has no entry yet)** —
|
|
309
|
-
The modality vocabulary MUST admit `shall-not` and `shall-not-impede`
|
|
310
|
-
alongside `shall`, `may`, `shall-if-practicable`, `conditional` and
|
|
311
|
-
`exempt`, and the relation vocabulary MUST admit `rel:overrides` as a
|
|
311
|
+
- **REQ-CAT-3** **(unimplemented in part — `modality:shall-not` has no entry yet)** —
|
|
312
|
+
The modality vocabulary MUST admit `modality:shall-not` and `modality:shall-not-impede`
|
|
313
|
+
alongside `modality:shall`, `modality:may`, `modality:shall-if-practicable`, `modality:conditional` and
|
|
314
|
+
`modality:exempt`, and the relation vocabulary MUST admit `rel:overrides` as a
|
|
312
315
|
sixth verb beside REQ-MODEL-7's five. Both remain closed sets; CI MUST
|
|
313
316
|
fail on a value outside them, and on a cycle in `rel:overrides`.
|
|
314
317
|
- **REQ-CAT-4** — A two-subject rule MUST read a **situation record**:
|
|
315
318
|
two per-vessel fact records, a kinematic state per vessel, relative
|
|
316
319
|
geometry, and history. The per-vessel fact record MUST NOT change to accommodate it, and kinematic
|
|
317
|
-
state MUST be a distinct fact class — a consumer that reads only `display`
|
|
320
|
+
state MUST be a distinct fact class — a consumer that reads only `category:display`
|
|
318
321
|
entries MUST NOT be required to supply one. Adding the situation record
|
|
319
322
|
MUST leave every existing fixture valid unedited.
|
|
320
323
|
- **REQ-CAT-5** — A situation MUST NOT be expressible in the current
|
|
@@ -325,10 +328,10 @@ towards, not because the shape is settled.
|
|
|
325
328
|
- **REQ-CAT-6** — The situation record MUST be declared in
|
|
326
329
|
`data/facts.json` under `situation`, and MUST address each vessel's facts
|
|
327
330
|
through the subject namespace of `docs/identifiers.md`:
|
|
328
|
-
`<subject>:<class>:<key>`, subject from `
|
|
329
|
-
`fact`/`kin`/`geo`/`hist`/`env`. A key with no subject segment MUST mean `
|
|
331
|
+
`<subject>:<class>:<key>`, subject from `self`/`other`/`pair`, class from
|
|
332
|
+
`fact`/`kin`/`geo`/`hist`/`env`. A key with no subject segment MUST mean `self:`,
|
|
330
333
|
so that every predicate and fixture published today is a valid situation
|
|
331
|
-
predicate unedited. `
|
|
334
|
+
predicate unedited. `self:fact:*` and `other:fact:*` MUST resolve to the
|
|
332
335
|
per-vessel fact record key for key, with no key renamed or copied.
|
|
333
336
|
`pair` MUST carry only classes whose facts are symmetric between the two
|
|
334
337
|
vessels; `env` — where the encounter is happening — is `pair`-only for that
|
|
@@ -347,27 +350,27 @@ towards, not because the shape is settled.
|
|
|
347
350
|
`expect` MUST be either a bare entry id — the published one-subject form,
|
|
348
351
|
asserting nothing about modality — or `{entry, modality}` naming the
|
|
349
352
|
modality that entry is expected to carry, which is what Q-5 needs. A case
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
names an entry.
|
|
353
|
+
MAY state `roles`, the pooled two-frame answer for both subjects (ADR
|
|
354
|
+
0016). An `illustrative` case MUST assert no entries and MUST NOT join the
|
|
355
|
+
replay. CI MUST fail on an undeclared fact, an unresolvable key, an unknown
|
|
356
|
+
entry id or modality, a stated role the pooled read does not yield, and on
|
|
357
|
+
an `illustrative` case that names an entry.
|
|
355
358
|
|
|
356
359
|
- **REQ-CAT-8** — A two-subject entry MUST state an `effect` and MUST NOT
|
|
357
|
-
state `lights`. For a `precedence` entry the effect MUST be a role per
|
|
358
|
-
subject, `{
|
|
359
|
-
`shall-not-impede`, `keep-clear`, `none`; for a `scope` entry it MUST name
|
|
360
|
+
state `lights`. For a `category:precedence` entry the effect MUST be a role per
|
|
361
|
+
subject, `{self, other}`, from the closed set `role:give-way`, `role:stand-on`,
|
|
362
|
+
`role:shall-not-impede`, `role:keep-clear`, `role:none`; for a `category:scope` entry it MUST name
|
|
360
363
|
the part, the section and the rules that section governs; for a
|
|
361
|
-
`classification` entry it MUST carry exactly one key, either `encounter`
|
|
362
|
-
from the closed set `head-on`, `crossing`, `overtaking`, `none`, or
|
|
363
|
-
`risk_of_collision`, whose only value is `true`. `stand-on` MUST
|
|
364
|
-
appear only as the counterpart of `give-way`, and the counterpart of
|
|
365
|
-
`shall-not-impede` MUST be `none` — Rule 8(f)(iii) is why. CI MUST fail on a
|
|
364
|
+
`category:classification` entry it MUST carry exactly one key, either `encounter`
|
|
365
|
+
from the closed set `encounter:head-on`, `encounter:crossing`, `encounter:overtaking`, `encounter:none`, or
|
|
366
|
+
`risk_of_collision`, whose only value is `true`. `role:stand-on` MUST
|
|
367
|
+
appear only as the counterpart of `role:give-way`, and the counterpart of
|
|
368
|
+
`role:shall-not-impede` MUST be `role:none` — Rule 8(f)(iii) is why. CI MUST fail on a
|
|
366
369
|
role or an encounter outside its set, on an effect whose shape does not match
|
|
367
370
|
its category, and on a `rel:overrides` that resolves to no entry, points at an
|
|
368
371
|
entry of a different category, or closes a cycle. `✎` pencil, with the rest of
|
|
369
372
|
§4.1.
|
|
370
|
-
- **REQ-CAT-9** — The `classification` entries for Rules 13, 14 and 15 MUST
|
|
373
|
+
- **REQ-CAT-9** — The `category:classification` entries for Rules 13, 14 and 15 MUST
|
|
371
374
|
**partition** the pair's relative geometry: for any situation those entries
|
|
372
375
|
all reach, exactly one encounter type MUST apply — never two, never none.
|
|
373
376
|
The crossing sector MUST NOT be enumerated; it MUST be derived, as the
|
|
@@ -444,7 +447,7 @@ See ADR 0003.
|
|
|
444
447
|
from the other, and no property beyond the language of the text — not
|
|
445
448
|
source, audience, nor legal applicability — MUST be inferred from a tag.
|
|
446
449
|
- **REQ-LANG-2** — Identifiers — entry ids, fact values, light ids,
|
|
447
|
-
paragraph paths, relation names — MUST be language-neutral and MUST NOT
|
|
450
|
+
paragraph paths, relation names, modality/role/encounter/category values — MUST be language-neutral and MUST NOT
|
|
448
451
|
be localized. Translations attach to identifiers; they never replace them.
|
|
449
452
|
Identifiers are schema keywords, not display strings: each vocabulary
|
|
450
453
|
distinguishes machine identifier, display label (catalog), and definition,
|
|
@@ -801,8 +804,8 @@ Tracked here until resolved; each becomes an ADR.
|
|
|
801
804
|
- **Q-4** — Two upstream SignalK spec asks are outstanding and independent of
|
|
802
805
|
this package: a making-way indicator, and `design.maxSpeed`.
|
|
803
806
|
- **Q-5** — REQ-VERIFY-5 asks for boundary fixtures on every numeric gate.
|
|
804
|
-
Three gates (`
|
|
805
|
-
`modality_by`, not in the entry's `when` — they flip `shall` to `may`, not
|
|
807
|
+
Three gates (`rule:23a_ii`, `rule:26b_ii`, `rule:30c`'s `fact:length_m` thresholds) live only in
|
|
808
|
+
`modality_by`, not in the entry's `when` — they flip `modality:shall` to `modality:may`, not
|
|
806
809
|
which entries apply. The fixture format only asserts applying entry ids, not
|
|
807
810
|
expected modality, so there is no way to fixture these three without
|
|
808
811
|
extending the schema to carry expected modality per entry. Not done
|
|
@@ -814,8 +817,8 @@ Tracked here until resolved; each becomes an ADR.
|
|
|
814
817
|
id asserts nothing, so `applicability-fixtures.json` stays byte-identical
|
|
815
818
|
and needs no migration; REQ-CAT-7 states the rule and
|
|
816
819
|
`fixtures/situation-fixtures.json` carries the worked example. What is left
|
|
817
|
-
is not a decision but the work: writing the boundary fixtures for `
|
|
818
|
-
`
|
|
820
|
+
is not a decision but the work: writing the boundary fixtures for `rule:23a_ii`,
|
|
821
|
+
`rule:26b_ii` and `rule:30c` in the new form. Pencil, so a session that finds a
|
|
819
822
|
better shape may change it, logging the change; settled for good by those
|
|
820
823
|
three fixtures actually landing.
|
|
821
824
|
- **Q-6** — The treaty-language facts behind §5 (en/fr authentic, es/ru
|
|
@@ -873,7 +876,7 @@ Tracked here until resolved; each becomes an ADR.
|
|
|
873
876
|
`24(d)`, `24(f)`, `24(g)`, `24(i)`, `25(d)(i)`, `25(d)(ii)`, `25(e)`,
|
|
874
877
|
`26(d)`, `30(e)`), plus one structural path-mismatch (`23(d)(i)` — the
|
|
875
878
|
Inland equivalent sits at bare `23(d)`, not `23(d)(i)`), one whole-rule
|
|
876
|
-
clean absence (`28`, "[Reserved]" in Inland), and two clean intl-only
|
|
879
|
+
clean absence (`rule:28`, "[Reserved]" in Inland), and two clean intl-only
|
|
877
880
|
absences. Secondary claim (amendment history): also refuted — the WIG
|
|
878
881
|
amendment (A.910(22), 2001) explicitly renumbers, displacing the
|
|
879
882
|
pre-existing `23(c)` (small-vessel alternative lights) to `23(d)`; a 1981
|
|
@@ -953,7 +956,7 @@ listed here, one line each, because the ADR is what makes them live. Most are
|
|
|
953
956
|
- **Q-14** — Which category does each paragraph take? The proposal's table is
|
|
954
957
|
a first cut; settled paragraph by paragraph as Rules 1–19 are transcribed.
|
|
955
958
|
PR #24 settles the first sixteen and departs from the table once: 13(a) is
|
|
956
|
-
`precedence`, not `classification` (`Q-37`).
|
|
959
|
+
`category:precedence`, not `category:classification` (`Q-37`).
|
|
957
960
|
- **Q-15** — Which verification tool discharges each category (Alloy, Z3, TLA+,
|
|
958
961
|
STL, Rocq)? Settled by building one proof per category, not by argument.
|
|
959
962
|
*(engine)*
|
|
@@ -962,6 +965,11 @@ listed here, one line each, because the ADR is what makes them live. Most are
|
|
|
962
965
|
invariant that does not fit. *(engine)*
|
|
963
966
|
- **Q-17** — What separation distance *d* defines the "safe" level? Fixed to
|
|
964
967
|
one value to start; settled by the sensitivity matrix of Q-22. *(engine)*
|
|
968
|
+
One data point: `docs/maritime-sources.md`'s MAIB *Polesie*/*Verity* report
|
|
969
|
+
cites UK case law putting close-quarters at a ~12-minute TCPA and adapts a
|
|
970
|
+
suggested-TCPA table (its Figure 16) from *A Guide to the Collision
|
|
971
|
+
Avoidance Rules* — not a d in metres, but a real-world anchor for the
|
|
972
|
+
sensitivity matrix.
|
|
965
973
|
- **Q-18** — What is the dynamics model, and what is the list of dynamics
|
|
966
974
|
classes (tanker, ferry, yacht, …)? Settled by the first two-vessel
|
|
967
975
|
computation; the class list is a data question once it stabilises.
|
|
@@ -983,8 +991,10 @@ listed here, one line each, because the ADR is what makes them live. Most are
|
|
|
983
991
|
it have to be computed at runtime? Settled by the first two-vessel
|
|
984
992
|
computation's cost. *(engine)*
|
|
985
993
|
- **Q-23** — Is Rule 2(b) a duty where departure is necessary, and does the
|
|
986
|
-
departing vessel bear the burden?
|
|
987
|
-
|
|
994
|
+
departing vessel bear the burden? Partly settled — yes and yes — by
|
|
995
|
+
`docs/maritime-sources.md`'s *Ever Smart* and *Crowley* entries; the
|
|
996
|
+
taxonomy of qualifying circumstances, and *The Bywell Castle* and *Boy
|
|
997
|
+
Andrew v St Rognvald*, are still unread. *colregs-engine* issue #83.
|
|
988
998
|
- **Q-24** — Are the four worked illustrations (R0, R1, R2,
|
|
989
999
|
`inconclusive-in-model`) actually in the regions they are said to be in?
|
|
990
1000
|
They fix meanings, not numbers; settled by computing them. *(engine)*
|
|
@@ -994,38 +1004,38 @@ listed here, one line each, because the ADR is what makes them live. Most are
|
|
|
994
1004
|
- **Q-26** — How large is the relative-frame state space? The 10⁴–10⁶ figure
|
|
995
1005
|
is a back-of-envelope guess; settled by a worksheet. *(engine)*
|
|
996
1006
|
- **Q-27** — What are the field names for `category`, `subjects`, `when`,
|
|
997
|
-
`effect` and the widened `modality`? Settled when the first non-`display`
|
|
1007
|
+
`effect` and the widened `modality`? Settled when the first non-`category:display`
|
|
998
1008
|
entry lands, and cheap to change until then.
|
|
999
1009
|
Unchanged by PR #22, which names none of those five. The names it
|
|
1000
1010
|
does fix — `situation`, the four classes, the three subjects — are
|
|
1001
1011
|
REQ-CAT-6's and are equally pencil.
|
|
1002
1012
|
- **Q-28** — What namespace distinguishes the two subjects of a two-subject
|
|
1003
|
-
entry (`
|
|
1013
|
+
entry (`self:` / `other:` is the working proposal)? No such segment exists in
|
|
1004
1014
|
`docs/identifiers.md`; settled before Rule 18 lands, and it is an
|
|
1005
1015
|
identifier decision under REQ-MODEL-10.
|
|
1006
1016
|
**Decided in pencil 2026-09-04** (PR #22): `<subject>:<class>:<key>`
|
|
1007
|
-
with subject `
|
|
1008
|
-
bare key meaning `
|
|
1017
|
+
with subject `self`/`other`/`pair` and class `fact`/`kin`/`geo`/`hist`, and a
|
|
1018
|
+
bare key meaning `self:`. Written up in `docs/identifiers.md` §"Two
|
|
1009
1019
|
subjects", required by REQ-CAT-6, and exercised by
|
|
1010
1020
|
`fixtures/situation-fixtures.json`. Three things the working proposal did
|
|
1011
1021
|
not have: a third subject, because range and in-sight belong to the
|
|
1012
1022
|
encounter and not to either vessel; a class segment, so kinematics and
|
|
1013
1023
|
history are new classes rather than new fact keys; and the bare-key default,
|
|
1014
1024
|
which is what makes the whole thing additive under REQ-MODEL-10 — no
|
|
1015
|
-
existing identifier is renamed or repointed, and `
|
|
1025
|
+
existing identifier is renamed or repointed, and `self`/`other`/`pair` become
|
|
1016
1026
|
reserved at the head of the identifier space, which is the only cost.
|
|
1017
1027
|
Settled for good by Rule 18 being written against it.
|
|
1018
1028
|
- **Q-29** — What are the file names and schemas for the invariants file and
|
|
1019
1029
|
the region grid, and how does a level-3 invariant carry `jurisdiction`?
|
|
1020
1030
|
Settled when the first invariant is written down.
|
|
1021
|
-
- **Q-30** — What does the `care`/`meta` registry look like as a file — its
|
|
1031
|
+
- **Q-30** — What does the `category:care`/`category:meta` registry look like as a file — its
|
|
1022
1032
|
name, its schema, and its relationship to `known_omissions`? Settled by
|
|
1023
1033
|
REQ-CAT-2's implementation, which is the next data change after this ADR.
|
|
1024
1034
|
|
|
1025
1035
|
**Decided in pencil, PR #23.** The registry is `represented_paragraphs`,
|
|
1026
1036
|
a sibling array to `known_omissions` in `data/applicability.json`. Each
|
|
1027
1037
|
record: `id` (paragraph-derived, e.g. `2a`), `jurisdiction`, `cite`,
|
|
1028
|
-
`category` (`care` or `meta`), and a one-sentence `note`; no `when`, no
|
|
1038
|
+
`category` (`category:care` or `category:meta`), and a one-sentence `note`; no `when`, no
|
|
1029
1039
|
`lights` — a registry record states that the paragraph is represented
|
|
1030
1040
|
and evaluated by nothing here, never a predicate. Holds the `2(a)` and
|
|
1031
1041
|
`2(b)` records this PR adds. `✎` under `docs/conventions.md`: the file
|
|
@@ -1039,8 +1049,8 @@ here rather than in a commit message. All pencil.
|
|
|
1039
1049
|
|
|
1040
1050
|
**Decided in pencil 2026-09-04 (PR #24)**, answering the data half of `Q-27`:
|
|
1041
1051
|
the field names are `category`, `subjects` and `effect`, and `effect` is
|
|
1042
|
-
`{
|
|
1043
|
-
applies_rules}` for a `scope` one. Written up in `docs/identifiers.md`
|
|
1052
|
+
`{self, other}` roles for a `category:precedence` entry and `{part, section,
|
|
1053
|
+
applies_rules}` for a `category:scope` one. Written up in `docs/identifiers.md`
|
|
1044
1054
|
§"Effects", required by `REQ-CAT-8`, and exercised by
|
|
1045
1055
|
`fixtures/situation-fixtures.json`. `Q-28`'s namespace is settled for good by
|
|
1046
1056
|
the same PR — Rule 18 is written against it and it held, with one addition:
|
|
@@ -1052,13 +1062,13 @@ named that gap before the class existed.
|
|
|
1052
1062
|
- **Q-31** — `modality` is a single closed value, and 18(c), 18(d)(i) and 9(a)
|
|
1053
1063
|
each carry two deontic qualifications at once: a practicability caveat
|
|
1054
1064
|
("so far as possible", "if the circumstances of the case admit") *and* the
|
|
1055
|
-
duty itself. 18(c) is expressible because `shall-if-practicable` already
|
|
1065
|
+
duty itself. 18(c) is expressible because `modality:shall-if-practicable` already
|
|
1056
1066
|
exists; 18(d)(i) is not, and its caveat is dropped with a `gap` note on the
|
|
1057
1067
|
entry. Settled by deciding whether practicability is a second field beside
|
|
1058
1068
|
`modality` rather than a value inside it — which is the same question
|
|
1059
1069
|
`modality_by` answers for the light rules, and should probably be answered
|
|
1060
1070
|
the same way. **Narrowed, not settled, 2026-09-04 (PR #25):** 18(d)(i) is now
|
|
1061
|
-
`shall-if-practicable` with `effect.
|
|
1071
|
+
`modality:shall-if-practicable` with `effect.self: role:shall-not-impede`, so the two
|
|
1062
1072
|
qualifications sit in two fields and neither is dropped. That works only
|
|
1063
1073
|
because this duty happens to be a *role*, which `effect` already carries;
|
|
1064
1074
|
9(a)'s "if the circumstances of the case admit" has no second field to move
|
|
@@ -1076,7 +1086,7 @@ named that gap before the class existed.
|
|
|
1076
1086
|
`rule18_class:fishing` by 3(d), and the 27(c) tow that severely restricts the
|
|
1077
1087
|
pair — the one the old predicates could not catch at all — to
|
|
1078
1088
|
`rule18_class:ram`, via a new boolean `fact:tow_restricts_deviation`. Every
|
|
1079
|
-
Rule 18, 9 and 10 entry reads the class; no `precedence` entry reads
|
|
1089
|
+
Rule 18, 9 and 10 entry reads the class; no `category:precedence` entry reads
|
|
1080
1090
|
`fact:activity` any more, and a test enforces that. `fact:activity` itself is
|
|
1081
1091
|
unchanged and no entry that reads it was touched. What is *not* settled: the
|
|
1082
1092
|
eighth rank Rule 18 distinguishes is the seaplane of 3(e), and it has no
|
|
@@ -1106,7 +1116,7 @@ named that gap before the class existed.
|
|
|
1106
1116
|
alternative was declined: it would have produced a predicate no reader could
|
|
1107
1117
|
check against the rule text, to avoid a language feature the rules themselves
|
|
1108
1118
|
use in plain words.
|
|
1109
|
-
- **Q-34** — A `shall-not-impede` entry names a duty toward `other`, but the
|
|
1119
|
+
- **Q-34** — A `modality:shall-not-impede` entry names a duty toward `other`, but the
|
|
1110
1120
|
paragraphs identify the protected vessel by a property this package does not
|
|
1111
1121
|
carry: "a vessel which can safely navigate only within a narrow channel"
|
|
1112
1122
|
(9(b), 9(d)), "any vessel following a traffic lane" (10(i), 10(j)), and a
|
|
@@ -1120,8 +1130,8 @@ named that gap before the class existed.
|
|
|
1120
1130
|
protected-vessel property is a per-vessel fact, consumer-supplied like
|
|
1121
1131
|
`pair:env:narrow_channel` and `pair:env:traffic_lane` are.** `fact:confined_to_channel`
|
|
1122
1132
|
and `fact:following_traffic_lane` name it, in the same shape as the existing
|
|
1123
|
-
`fact:near_channel` and `fact:obstruction_exists`; entries `9b`, `10i` and
|
|
1124
|
-
`10j` now read `other:fact:confined_to_channel`/`other:fact:following_traffic_lane`
|
|
1133
|
+
`fact:near_channel` and `fact:obstruction_exists`; entries `rule:9b`, `rule:10i` and
|
|
1134
|
+
`rule:10j` now read `other:fact:confined_to_channel`/`other:fact:following_traffic_lane`
|
|
1125
1135
|
and their `gap` fields are closed. `9(d)` has no entry yet, so it inherits
|
|
1126
1136
|
the same fact when one is written. **18(d)(i) is deliberately left open**:
|
|
1127
1137
|
"exhibiting the signals in Rule 28" is a display-compliance fact rather than
|
|
@@ -1129,40 +1139,40 @@ named that gap before the class existed.
|
|
|
1129
1139
|
CLAUDE.md "Coverage") — settling it is a narrower, separate decision.
|
|
1130
1140
|
- **Q-35** — 8(f)(iii)'s antecedent is "a vessel, the passage of which is not to
|
|
1131
1141
|
be impeded" — the *output* of another norm, not a fact. A precedence
|
|
1132
|
-
predicate reads only facts, so entry `
|
|
1142
|
+
predicate reads only facts, so entry `rule:8f_iii` reads the risk-of-collision half
|
|
1133
1143
|
alone and applies to every pair with risk of collision. Settled by deciding
|
|
1134
1144
|
whether a norm may read another norm's effect, which is the same question a
|
|
1135
|
-
`conduct` monitor will ask about role and phase.
|
|
1145
|
+
`category:conduct` monitor will ask about role and phase.
|
|
1136
1146
|
- **Q-36** — Rule 18(a)(iv) and 18(d)(i) are both in force between a sailing
|
|
1137
1147
|
vessel and a vessel constrained by her draught: the CBD vessel gives way, and
|
|
1138
1148
|
the sailing vessel must not impede her. Neither overrides the other and the
|
|
1139
|
-
model records both, so one subject holds `stand-on` and `shall-not-impede`
|
|
1149
|
+
model records both, so one subject holds `role:stand-on` and `role:shall-not-impede`
|
|
1140
1150
|
at once. The test suite pins it as a finding rather than asserting it away.
|
|
1141
1151
|
Settled by reading 8(f)(ii) against the cases, not by picking a role.
|
|
1142
|
-
- **Q-37** — 13(a) is `classification` in ADR 0005 §1 and in the proposal's
|
|
1152
|
+
- **Q-37** — 13(a) is `category:classification` in ADR 0005 §1 and in the proposal's
|
|
1143
1153
|
first-cut table, but it is the one paragraph of Rule 13 that assigns a role
|
|
1144
|
-
and a `classification` entry has nowhere to put one. Entry `13a` is
|
|
1145
|
-
`precedence` here, with 13(b)'s sector test left for the `classification`
|
|
1154
|
+
and a `category:classification` entry has nowhere to put one. Entry `rule:13a` is
|
|
1155
|
+
`category:precedence` here, with 13(b)'s sector test left for the `category:classification`
|
|
1146
1156
|
entry that would set the `hist:was_overtaking` latch. Settled with the rest
|
|
1147
1157
|
of `Q-14`, paragraph by paragraph.
|
|
1148
1158
|
|
|
1149
1159
|
**Closed in pencil 2026-09-04 (PR #26).** 13(b) is now written, as *two*
|
|
1150
|
-
`classification` entries rather than one —
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
a crossing. 13(a) stays `precedence`, and its predicate now carries both
|
|
1160
|
+
`category:classification` entries rather than one — one per subject — because the
|
|
1161
|
+
encounter type belongs to the pair and reading aspect alone classified the
|
|
1162
|
+
overtaken vessel's side of the same encounter as a crossing. 13(a) stays `category:precedence`, and its predicate now carries both
|
|
1154
1163
|
halves of "any vessel overtaking any other": the 13(b) sector and the 13(d)
|
|
1155
1164
|
latch, as an `any_of`, which closes the gap the entry recorded. 13(d) is a
|
|
1156
|
-
third `classification` entry, reading history and no geometry at all. The
|
|
1165
|
+
third `category:classification` entry, reading history and no geometry at all. The
|
|
1157
1166
|
split confirms the thing ADR 0005 §1 was really defending — one category per
|
|
1158
|
-
paragraph
|
|
1159
|
-
|
|
1167
|
+
paragraph. **Reversed in part, 2026-09-16:** ADR 0015 as rewritten makes
|
|
1168
|
+
13(b) one symmetric entry, `rule:13b`, reading the same sector object on
|
|
1169
|
+
either subject under `any_of`. 13(a) staying `category:precedence` is untouched.
|
|
1160
1170
|
- **Q-38** — 9(d), 18(d)(ii), 18(e), 18(f)(ii), 1(a)–(e) and 20(b)–(c) are
|
|
1161
1171
|
recorded in `known_omissions` rather than modelled: 9(d) needs the channel's
|
|
1162
1172
|
axis, 18(e) needs a fact for being a seaplane, 20(b)–(c) need time of day,
|
|
1163
1173
|
and 1(a)–(e) are addressed to an authority rather than to a vessel. Settled
|
|
1164
1174
|
one at a time as the facts they need land; none blocks the rest of Part B.
|
|
1165
|
-
- **Q-39** — Rule 4's `scope` entry has an empty `when`, because "any condition
|
|
1175
|
+
- **Q-39** — Rule 4's `category:scope` entry has an empty `when`, because "any condition
|
|
1166
1176
|
of visibility" is the absence of a condition. That makes it unfalsifiable —
|
|
1167
1177
|
`REQ-VERIFY-3`'s "excluded by at least one fixture" half cannot be satisfied
|
|
1168
1178
|
and the test exempts it explicitly. Settled by deciding whether an ungated
|
|
@@ -1171,19 +1181,19 @@ named that gap before the class existed.
|
|
|
1171
1181
|
|
|
1172
1182
|
### From the classification norms (PR #26)
|
|
1173
1183
|
|
|
1174
|
-
Rules 7(d), 12, 13(b)–(d), 14 and 15 are the first `classification` entries and
|
|
1175
|
-
the second family of `precedence` ones. All pencil. What the model expressed is
|
|
1184
|
+
Rules 7(d), 12, 13(b)–(d), 14 and 15 are the first `category:classification` entries and
|
|
1185
|
+
the second family of `category:precedence` ones. All pencil. What the model expressed is
|
|
1176
1186
|
written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
1177
1187
|
|
|
1178
|
-
- **Q-40** — **Rule 12 is `precedence`, not `classification`.** ADR 0005 §1 and
|
|
1179
|
-
the proposal's table both file it under `classification`; it produces a role
|
|
1188
|
+
- **Q-40** — **Rule 12 is `category:precedence`, not `category:classification`.** ADR 0005 §1 and
|
|
1189
|
+
the proposal's table both file it under `category:classification`; it produces a role
|
|
1180
1190
|
— "one of them shall keep out of the way of the other" — and a
|
|
1181
1191
|
classification effect has nowhere to put one, which is `Q-37`'s argument
|
|
1182
1192
|
applied a second time. Two sailing vessels are still in a head-on, a crossing
|
|
1183
1193
|
or an overtaking; Rule 12 says which of them gives way, not what kind of
|
|
1184
|
-
meeting it is. 12(b) is a `definition` and is the cite on `kin:wind_side`
|
|
1194
|
+
meeting it is. 12(b) is a `category:definition` and is the cite on `kin:wind_side`
|
|
1185
1195
|
rather than an entry. The second half of the question is narrower and worse:
|
|
1186
|
-
12(a) says "two sailing vessels", which is 3(c), but entries
|
|
1196
|
+
12(a) says "two sailing vessels", which is 3(c), but entries the three Rule 12 entries
|
|
1187
1197
|
read `rule18_class:sail` instead, so a vessel engaged in fishing under sail
|
|
1188
1198
|
falls out of Rule 12 — because letting her in would have given her a give-way
|
|
1189
1199
|
duty under 12(a) and a stand-on role under 18(b)(iii) with no override
|
|
@@ -1203,7 +1213,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1203
1213
|
it: Rule 18's chapeau excepts Rules 9, 10 and 13 and no others, so every
|
|
1204
1214
|
Rule 18 norm that can be in force between two sailing vessels — 18(b)(i)–(iii)
|
|
1205
1215
|
from the ordinary sailing vessel's side, 18(c)(i)–(ii) from the fishing
|
|
1206
|
-
vessel's — carries `rel:overrides` against
|
|
1216
|
+
vessel's — carries `rel:overrides` against the three Rule 12 entries. 13(a), being
|
|
1207
1217
|
"notwithstanding" the whole of Sections I and II, overrides them too, which
|
|
1208
1218
|
it had to: two sailing vessels in an overtaking held 13(a)'s and 12(a)(ii)'s
|
|
1209
1219
|
roles at once and nothing had noticed. Two fixtures and a sweep over sailing
|
|
@@ -1217,21 +1227,21 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1217
1227
|
|
|
1218
1228
|
**Decided in pencil 2026-09-05 (PR #46): Rule 15 reads 3(b), and Rule 18
|
|
1219
1229
|
overrides it too.** The same question answered the other way for Rule 15.
|
|
1220
|
-
`15a
|
|
1230
|
+
`rule:15a:keep_out_of_the_way` kept the four Rule 18 ranks — NUC, RAM, fishing and WIG —
|
|
1221
1231
|
out of Rule 15 by negating them on both subjects in its own predicate; the
|
|
1222
1232
|
negation is gone, both subjects gate on `fact:propulsion: propulsion:power`
|
|
1223
|
-
which is 3(b), and
|
|
1233
|
+
which is 3(b), and the 18(a)(i)–(iii) entries, the two 18(c) entries and `rule:18f_i` carry
|
|
1224
1234
|
`rel:overrides` against it. The gate was not merely the relation said in
|
|
1225
1235
|
the wrong place. It produced the right roles wherever Rule 18 speaks and
|
|
1226
1236
|
*no* role at all where Rule 18 is silent: two vessels engaged in fishing
|
|
1227
1237
|
under power, and a vessel not under command crossing one restricted in her
|
|
1228
1238
|
ability to manoeuvre under power, are pairs Rule 18 does not order, and
|
|
1229
1239
|
neither vessel took a helm role from any entry. Both are fixtures now, and
|
|
1230
|
-
both failed on the data before the change — `15a
|
|
1240
|
+
both failed on the data before the change — `rule:15a:crossing` classified the
|
|
1231
1241
|
encounter and nothing assigned a role. What it leaves is Rule 12's residue
|
|
1232
1242
|
again: on those unordered pairs Rule 15 lays a give-way duty on a vessel
|
|
1233
1243
|
that may be unable to discharge it, which is Rule 2's region and is
|
|
1234
|
-
recorded, not gated. `13a` needs no override against `15a
|
|
1244
|
+
recorded, not gated. `rule:13a` needs no override against `rule:15a:keep_out_of_the_way` — the
|
|
1235
1245
|
entry excludes every overtaking by the `hist:was_overtaking` latch and by
|
|
1236
1246
|
13(b)'s sector — and a test pins that absence so it stays a reason rather
|
|
1237
1247
|
than an oversight. The hand-list of six is asserted complete by a derived
|
|
@@ -1245,7 +1255,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1245
1255
|
which is still how the fixtures are written and is what makes these six
|
|
1246
1256
|
overrides observable rather than invisible.
|
|
1247
1257
|
|
|
1248
|
-
The category half — Rule 12 as `precedence` — is unchanged and stays with
|
|
1258
|
+
The category half — Rule 12 as `category:precedence` — is unchanged and stays with
|
|
1249
1259
|
`Q-14`.
|
|
1250
1260
|
- **Q-41** — **13(c) and 14(c) invert the absent-fact rule.** "When a vessel is
|
|
1251
1261
|
in any doubt as to whether she is overtaking, she shall assume that this is
|
|
@@ -1272,7 +1282,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1272
1282
|
judgement. Settled by deciding whether the vocabulary gains one — `Q-31`'s
|
|
1273
1283
|
neighbour, not its duplicate.
|
|
1274
1284
|
- **Q-43** — **The partition needs history to be present, and says nothing when
|
|
1275
|
-
it is absent.** `14b` and `15a
|
|
1285
|
+
it is absent.** `rule:14b` and `rule:15a:crossing` are gated on `hist:was_overtaking`
|
|
1276
1286
|
being `false` on both subjects, which is 13(d)'s requirement and the only way
|
|
1277
1287
|
the three encounter types stay disjoint once the latch is set. Because absent
|
|
1278
1288
|
is absent, a situation that omits the fact is classified as *no encounter at
|
|
@@ -1306,27 +1316,26 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1306
1316
|
the same question `Q-39` asks about an ungated norm, from the other end.
|
|
1307
1317
|
|
|
1308
1318
|
**Decided in pencil 2026-09-05 (PR #36): the head-on classification cites
|
|
1309
|
-
14(b), and 14(a) is `conduct`.** The question assumed 14(b) produced no
|
|
1319
|
+
14(b), and 14(a) is `category:conduct`.** The question assumed 14(b) produced no
|
|
1310
1320
|
effect of its own. It produces the only effect the entry has: "such a
|
|
1311
1321
|
situation shall be deemed to exist when…" is the deeming test, and
|
|
1312
|
-
`{"encounter": "head-on"}` is what a deeming test yields — exactly as
|
|
1313
|
-
`13b
|
|
1322
|
+
`{"encounter": "encounter:head-on"}` is what a deeming test yields — exactly as
|
|
1323
|
+
`rule:13b` cites 13(b), the deeming paragraph,
|
|
1314
1324
|
and not 13(a). 14(a) states the situation in words ("reciprocal or nearly
|
|
1315
1325
|
reciprocal courses") and imposes the duty ("each shall alter her course to
|
|
1316
|
-
starboard"); the duty is `conduct`, and the words are what 14(b) makes
|
|
1317
|
-
checkable. So the entry is `14b`, cites 14(b), and reads nothing 14(b) does
|
|
1326
|
+
starboard"); the duty is `category:conduct`, and the words are what 14(b) makes
|
|
1327
|
+
checkable. So the entry is `rule:14b`, cites 14(b), and reads nothing 14(b) does
|
|
1318
1328
|
not fix; 14(a) joins `known_omissions` as conduct beside 18(d)(ii), and
|
|
1319
|
-
`14a` is
|
|
1320
|
-
|
|
1321
|
-
replacement — the registry's first record (REQ-MODEL-11). The
|
|
1329
|
+
the `14a` id it displaced is gone with the rest of the citation-derived ids
|
|
1330
|
+
and leaves no record behind it (ADR 0015). The
|
|
1322
1331
|
general question — whether a paragraph with no effect of its own gets an
|
|
1323
1332
|
entry — is `Q-39`'s and is untouched; this paragraph turned out not to be an
|
|
1324
1333
|
instance of it.
|
|
1325
1334
|
- **Q-46** — **"Coming up with" is a comparison of two facts.** 13(b) deems a
|
|
1326
1335
|
vessel to be overtaking when *coming up with* another from more than 22.5°
|
|
1327
|
-
abaft her beam. That is `
|
|
1336
|
+
abaft her beam. That is `self:kin:sog_kn` against `other:kin:sog_kn`, and the
|
|
1328
1337
|
predicate language compares a fact to a constant and never one fact to
|
|
1329
|
-
another — the same wall `
|
|
1338
|
+
another — the same wall `rule:12a_ii` hits on "both have the wind on the same side",
|
|
1330
1339
|
which it gets over only because that comparison has two values to enumerate
|
|
1331
1340
|
and this one has infinitely many. `pair:geo:tcpa_s > 0` stands in: the pair
|
|
1332
1341
|
is closing, and closing from abaft the beam is coming up. It excludes the
|
|
@@ -1338,30 +1347,30 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1338
1347
|
- **Q-47** — **13(d)'s latch never clears.** The paragraph runs "until she is
|
|
1339
1348
|
finally past and clear", nothing in the fact vocabulary carries that, and so
|
|
1340
1349
|
in this model `hist:was_overtaking` is set by a consumer and cleared by a
|
|
1341
|
-
consumer while entry `13d` classifies an overtaking for as long as it stands.
|
|
1350
|
+
consumer while entry `rule:13d` classifies an overtaking for as long as it stands.
|
|
1342
1351
|
Not approximated with a range or a bearing: past and clear is a seamanship
|
|
1343
1352
|
judgement of the same kind as risk of collision, and a threshold for it would
|
|
1344
1353
|
be a number invented rather than declared. Settled by whatever settles the
|
|
1345
|
-
`conduct` monitors, which are the things that watch a duty end rather than
|
|
1354
|
+
`category:conduct` monitors, which are the things that watch a duty end rather than
|
|
1346
1355
|
begin.
|
|
1347
1356
|
|
|
1348
1357
|
**Ruled 2026-09-08:** while one vessel holds the latch, 13(a)'s sector
|
|
1349
1358
|
test is suppressed on the other, newly-gaining vessel — once overtaking,
|
|
1350
1359
|
always overtaking, per 13(d)'s own text, so a geometry test that would
|
|
1351
1360
|
newly name a second give-way vessel must not fire while the first still
|
|
1352
|
-
holds the role by history alone. `13a`'s sector branch now also reads
|
|
1361
|
+
holds the role by history alone. `rule:13a`'s sector branch now also reads
|
|
1353
1362
|
`other:hist:was_overtaking: false`; the closing fixture in
|
|
1354
1363
|
`fixtures/situation-fixtures.json` is the case this closes — a vessel
|
|
1355
1364
|
drops back onto the latch-holder's own stern, and only the latch-holder
|
|
1356
1365
|
gives way.
|
|
1357
1366
|
- **Q-48** — **Nothing checks that a situation is geometrically possible.**
|
|
1358
|
-
`
|
|
1367
|
+
`self:geo:rel_bearing_deg`, `other:geo:rel_bearing_deg`, the two
|
|
1359
1368
|
`kin:heading_deg` and the two `kin:sog_kn` are six facts related by two
|
|
1360
1369
|
equations, and the situation record enforces neither. A consumer — or a
|
|
1361
1370
|
fixture — can state a pair of bearings that no two headings produce, and the
|
|
1362
1371
|
entries will classify it without complaint. It bites in one visible place:
|
|
1363
1372
|
where both vessels have the other on the starboard side, which cannot happen
|
|
1364
|
-
on a collision course, `15a
|
|
1373
|
+
on a collision course, `rule:15a:keep_out_of_the_way` applies to both of them and the "never
|
|
1365
1374
|
both give-way" property fails. The fixtures added here are built from a
|
|
1366
1375
|
heading and a bearing so that they are consistent by construction, and the
|
|
1367
1376
|
file says so; the model is not. Settled by deciding whether the record gains
|
|
@@ -1372,7 +1381,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1372
1381
|
**Decided in pencil 2026-09-05: the record gains a consistency check,
|
|
1373
1382
|
declared in data and enforced in the suite.** `data/facts.json` declares the
|
|
1374
1383
|
equations under `situation.geometry.consistency` — the two relative bearings
|
|
1375
|
-
are two readings of one line of sight (`
|
|
1384
|
+
are two readings of one line of sight (`self + self heading + 180 ≡ aspect +
|
|
1376
1385
|
other heading`), positions reproduce range and both bearings, and the two
|
|
1377
1386
|
headings and speeds reproduce CPA, TCPA and bearing rate — with tolerances,
|
|
1378
1387
|
and `REQ-VERIFY-8` requires the suite to apply them. A quantity a record does
|
|
@@ -1384,12 +1393,12 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1384
1393
|
and speeds. Two cases could not keep their story: the R1 head-on had both
|
|
1385
1394
|
vessels with the other to starboard, which no speeds make a steady bearing,
|
|
1386
1395
|
and is recast as one; the 13(d) latch case is 400 m abeam with the CPA
|
|
1387
|
-
already past, and lost `
|
|
1396
|
+
already past, and lost `rule:7d_i`. The partition sweep now constructs positions
|
|
1388
1397
|
and headings for every bearing pair and is consistent at every point. The
|
|
1389
1398
|
"never both give-way" property is asserted over a sweep of steady-bearing
|
|
1390
1399
|
geometries — every relative bearing, several speed pairs, both intercept
|
|
1391
1400
|
solutions — where it is a theorem rather than an observation:
|
|
1392
|
-
`u·sin(
|
|
1401
|
+
`u·sin(self bearing) = −v·sin(aspect)`, so the two bearings lie on opposite
|
|
1393
1402
|
sides and 15(a) can name only one vessel. The both-starboard counterexample
|
|
1394
1403
|
is pinned as a record the check rejects. What is *not* settled, and is
|
|
1395
1404
|
pinned too: the theorem is exact only at a bearing rate of zero, and
|
|
@@ -1401,12 +1410,12 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
|
|
|
1401
1410
|
the relative quantities as derived facts stays open in the block's
|
|
1402
1411
|
`settled_by`.
|
|
1403
1412
|
|
|
1404
|
-
- **Q-49** — **Must `13d`'s effect cross the Section II/III boundary for Rule 19(d)(i) to be expressible?**
|
|
1405
|
-
- *broad* — drop `13d`'s `pair:geo:in_sight` gate so `encounter: overtaking` is visible in Section III; breaks the scope invariant.
|
|
1406
|
-
- *narrow* — `13d` stays gated; a 19(d)(i) entry reads `
|
|
1413
|
+
- **Q-49** — **Must `rule:13d`'s effect cross the Section II/III boundary for Rule 19(d)(i) to be expressible?**
|
|
1414
|
+
- *broad* — drop `rule:13d`'s `pair:geo:in_sight` gate so `encounter: overtaking` is visible in Section III; breaks the scope invariant.
|
|
1415
|
+
- *narrow* — `rule:13d` stays gated; a 19(d)(i) entry reads `self:hist:was_overtaking`/`other:hist:was_overtaking` directly, as `rule:14b` and `rule:15a:crossing` already do.
|
|
1407
1416
|
- Default: narrow (nothing changes).
|
|
1408
1417
|
- Recommendation: narrow — the test named below shows the fact resolves out of sight
|
|
1409
|
-
(`Q-49: hist:was_overtaking resolves out of sight; 13d does not fire`, `test/data.test.mjs`).
|
|
1418
|
+
(`Q-49: hist:was_overtaking resolves out of sight; rule:13d does not fire`, `test/data.test.mjs`).
|
|
1410
1419
|
|
|
1411
1420
|
### From the Part B invariants (P4.1)
|
|
1412
1421
|
|
|
@@ -1419,8 +1428,8 @@ nothing is blocked while open.
|
|
|
1419
1428
|
*Wide:* they attach whenever in sight and the geometry holds — Rule 11 is the
|
|
1420
1429
|
only gate Section II states — so a vessel overtaking a mile clear abeam is
|
|
1421
1430
|
give-way and Rule 16 binds her. *Narrow:* Section II's duties attach only with
|
|
1422
|
-
risk of collision; 14 and 15 are emphasis. Default **wide**: `13a`, `13b
|
|
1423
|
-
`13d` and every Rule 18 entry read `in_sight` only. No recommendation.
|
|
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.
|
|
1424
1433
|
- **Q-51** — **What arms 13(d)'s latch?** *A:* 13(b)'s deeming, at the first
|
|
1425
1434
|
state the geometry holds. *B:* 13(a)'s duty actually attaching. They differ
|
|
1426
1435
|
where the geometry holds but a condition on 13(a) does not — `Q-50`'s
|
|
@@ -1428,7 +1437,7 @@ nothing is blocked while open.
|
|
|
1428
1437
|
duty attaches. KIVELI [2025] EWHC 1185 (Admlty) holds the analogous Rule 14
|
|
1429
1438
|
latch arms on risk of collision and then persists; no authority was found on
|
|
1430
1439
|
overtaking geometry with no risk of collision. Free to reverse: four entries
|
|
1431
|
-
(`13a`, `13b
|
|
1440
|
+
(`rule:13a`, `rule:13b`, `rule:13d`) and their fixtures, and nothing consumes the one
|
|
1432
1441
|
state this changes the answer for. Settled by: a decision on Rule 13 itself,
|
|
1433
1442
|
or Cockcroft & Lameijer on whether overtaking status needs risk of
|
|
1434
1443
|
collision.
|
|
@@ -1438,8 +1447,8 @@ nothing is blocked while open.
|
|
|
1438
1447
|
other Section II classification attaches. Both preserve the duty; they differ
|
|
1439
1448
|
on encounter type, which Rule 17's phases and 14(a) hang off.
|
|
1440
1449
|
Pencilled **broad** ✎ (Solace, 2026-09-14), which is also the data's
|
|
1441
|
-
default: `13d` yields `encounter: overtaking` from history alone, `14b` and
|
|
1442
|
-
`15a
|
|
1450
|
+
default: `rule:13d` yields `encounter: overtaking` from history alone, `rule:14b` and
|
|
1451
|
+
`rule:15a:crossing` gate on `was_overtaking: false`. 13(a)'s "notwithstanding"
|
|
1443
1452
|
already displaces Rule 14; eCOLREGs states the broad reading as conventional.
|
|
1444
1453
|
Settled by: a case or commentary on an overtaking becoming a head-on; none
|
|
1445
1454
|
found.
|
|
@@ -1468,7 +1477,7 @@ nothing is blocked while open.
|
|
|
1468
1477
|
Not in sight *and* not in or near restricted visibility (clear weather, beyond
|
|
1469
1478
|
visual range, radar contact) is outside Rule 11 and 19(a): Section I only.
|
|
1470
1479
|
*Hole:* represent it; a fact for "in or near restricted visibility" is owed.
|
|
1471
|
-
*Closed:* treat not-in-sight as Section III. Default **closed**: `19a` drops
|
|
1480
|
+
*Closed:* treat not-in-sight as Section III. Default **closed**: `rule:19a` drops
|
|
1472
1481
|
the second conjunct, recorded as a `gap`. Recommend **hole**: the default is
|
|
1473
1482
|
safe for a switching consumer and unsafe for a traceability claim.
|
|
1474
1483
|
- **Q-57** — **The baseline for "keep her course and speed"?** 17(a)(i) fixes
|