colregs 0.3.1 → 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.
@@ -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
@@ -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.
@@ -297,27 +297,27 @@ towards, not because the shape is settled.
297
297
  two-subject entries and defaulted for the rest; no record in `rules.json`
298
298
  carries one, so a paragraph with no entry is uncategorised)** —
299
299
  Every rule paragraph record MUST carry exactly one `category` from the
300
- closed set `scope`, `definition`, `standard`, `display`,
301
- `classification`, `precedence`, `conduct`, `care`, `meta`. The field
302
- 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
303
303
  fail on a value outside the set. Where a paragraph plays a second role,
304
304
  that role MUST be expressed as a relation (REQ-CAT-3), never as a second
305
305
  category.
306
- - **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
307
307
  be applicability entries. They MUST be recorded in a registry sibling to
308
308
  `known_omissions`, stating that the package represents them and evaluates
309
- 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
310
310
  entry.
311
- - **REQ-CAT-3** **(unimplemented in part — `shall-not` has no entry yet)** —
312
- The modality vocabulary MUST admit `shall-not` and `shall-not-impede`
313
- alongside `shall`, `may`, `shall-if-practicable`, `conditional` and
314
- `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
315
315
  sixth verb beside REQ-MODEL-7's five. Both remain closed sets; CI MUST
316
316
  fail on a value outside them, and on a cycle in `rel:overrides`.
317
317
  - **REQ-CAT-4** — A two-subject rule MUST read a **situation record**:
318
318
  two per-vessel fact records, a kinematic state per vessel, relative
319
319
  geometry, and history. The per-vessel fact record MUST NOT change to accommodate it, and kinematic
320
- 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`
321
321
  entries MUST NOT be required to supply one. Adding the situation record
322
322
  MUST leave every existing fixture valid unedited.
323
323
  - **REQ-CAT-5** — A situation MUST NOT be expressible in the current
@@ -328,10 +328,10 @@ towards, not because the shape is settled.
328
328
  - **REQ-CAT-6** — The situation record MUST be declared in
329
329
  `data/facts.json` under `situation`, and MUST address each vessel's facts
330
330
  through the subject namespace of `docs/identifiers.md`:
331
- `<subject>:<class>:<key>`, subject from `own`/`other`/`pair`, class from
332
- `fact`/`kin`/`geo`/`hist`/`env`. A key with no subject segment MUST mean `own:`,
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:`,
333
333
  so that every predicate and fixture published today is a valid situation
334
- predicate unedited. `own:fact:*` and `other:fact:*` MUST resolve to the
334
+ predicate unedited. `self:fact:*` and `other:fact:*` MUST resolve to the
335
335
  per-vessel fact record key for key, with no key renamed or copied.
336
336
  `pair` MUST carry only classes whose facts are symmetric between the two
337
337
  vessels; `env` — where the encounter is happening — is `pair`-only for that
@@ -350,27 +350,27 @@ towards, not because the shape is settled.
350
350
  `expect` MUST be either a bare entry id — the published one-subject form,
351
351
  asserting nothing about modality — or `{entry, modality}` naming the
352
352
  modality that entry is expected to carry, which is what Q-5 needs. A case
353
- whose `status` is `illustrative` MUST assert no entries and MUST NOT join
354
- the fixture replay; it fixes the shape and the namespace before the
355
- entries exist. CI MUST fail on an undeclared fact, an unresolvable key, an
356
- unknown entry id, an unknown modality, and on an `illustrative` case that
357
- 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.
358
358
 
359
359
  - **REQ-CAT-8** — A two-subject entry MUST state an `effect` and MUST NOT
360
- state `lights`. For a `precedence` entry the effect MUST be a role per
361
- subject, `{own, other}`, from the closed set `give-way`, `stand-on`,
362
- `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
363
363
  the part, the section and the rules that section governs; for a
364
- `classification` entry it MUST carry exactly one key, either `encounter`
365
- from the closed set `head-on`, `crossing`, `overtaking`, `none`, or
366
- `risk_of_collision`, whose only value is `true`. `stand-on` MUST
367
- appear only as the counterpart of `give-way`, and the counterpart of
368
- `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
369
369
  role or an encounter outside its set, on an effect whose shape does not match
370
370
  its category, and on a `rel:overrides` that resolves to no entry, points at an
371
371
  entry of a different category, or closes a cycle. `✎` pencil, with the rest of
372
372
  §4.1.
373
- - **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
374
374
  **partition** the pair's relative geometry: for any situation those entries
375
375
  all reach, exactly one encounter type MUST apply — never two, never none.
376
376
  The crossing sector MUST NOT be enumerated; it MUST be derived, as the
@@ -447,7 +447,7 @@ See ADR 0003.
447
447
  from the other, and no property beyond the language of the text — not
448
448
  source, audience, nor legal applicability — MUST be inferred from a tag.
449
449
  - **REQ-LANG-2** — Identifiers — entry ids, fact values, light ids,
450
- 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
451
451
  be localized. Translations attach to identifiers; they never replace them.
452
452
  Identifiers are schema keywords, not display strings: each vocabulary
453
453
  distinguishes machine identifier, display label (catalog), and definition,
@@ -805,7 +805,7 @@ Tracked here until resolved; each becomes an ADR.
805
805
  this package: a making-way indicator, and `design.maxSpeed`.
806
806
  - **Q-5** — REQ-VERIFY-5 asks for boundary fixtures on every numeric gate.
807
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 `shall` to `may`, not
808
+ `modality_by`, not in the entry's `when` — they flip `modality:shall` to `modality:may`, not
809
809
  which entries apply. The fixture format only asserts applying entry ids, not
810
810
  expected modality, so there is no way to fixture these three without
811
811
  extending the schema to carry expected modality per entry. Not done
@@ -956,7 +956,7 @@ listed here, one line each, because the ADR is what makes them live. Most are
956
956
  - **Q-14** — Which category does each paragraph take? The proposal's table is
957
957
  a first cut; settled paragraph by paragraph as Rules 1–19 are transcribed.
958
958
  PR #24 settles the first sixteen and departs from the table once: 13(a) is
959
- `precedence`, not `classification` (`Q-37`).
959
+ `category:precedence`, not `category:classification` (`Q-37`).
960
960
  - **Q-15** — Which verification tool discharges each category (Alloy, Z3, TLA+,
961
961
  STL, Rocq)? Settled by building one proof per category, not by argument.
962
962
  *(engine)*
@@ -1004,38 +1004,38 @@ listed here, one line each, because the ADR is what makes them live. Most are
1004
1004
  - **Q-26** — How large is the relative-frame state space? The 10⁴–10⁶ figure
1005
1005
  is a back-of-envelope guess; settled by a worksheet. *(engine)*
1006
1006
  - **Q-27** — What are the field names for `category`, `subjects`, `when`,
1007
- `effect` and the widened `modality`? Settled when the first non-`display`
1007
+ `effect` and the widened `modality`? Settled when the first non-`category:display`
1008
1008
  entry lands, and cheap to change until then.
1009
1009
  Unchanged by PR #22, which names none of those five. The names it
1010
1010
  does fix — `situation`, the four classes, the three subjects — are
1011
1011
  REQ-CAT-6's and are equally pencil.
1012
1012
  - **Q-28** — What namespace distinguishes the two subjects of a two-subject
1013
- entry (`own:` / `other:` is the working proposal)? No such segment exists in
1013
+ entry (`self:` / `other:` is the working proposal)? No such segment exists in
1014
1014
  `docs/identifiers.md`; settled before Rule 18 lands, and it is an
1015
1015
  identifier decision under REQ-MODEL-10.
1016
1016
  **Decided in pencil 2026-09-04** (PR #22): `<subject>:<class>:<key>`
1017
- with subject `own`/`other`/`pair` and class `fact`/`kin`/`geo`/`hist`, and a
1018
- bare key meaning `own:`. Written up in `docs/identifiers.md` §"Two
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
1019
1019
  subjects", required by REQ-CAT-6, and exercised by
1020
1020
  `fixtures/situation-fixtures.json`. Three things the working proposal did
1021
1021
  not have: a third subject, because range and in-sight belong to the
1022
1022
  encounter and not to either vessel; a class segment, so kinematics and
1023
1023
  history are new classes rather than new fact keys; and the bare-key default,
1024
1024
  which is what makes the whole thing additive under REQ-MODEL-10 — no
1025
- existing identifier is renamed or repointed, and `own`/`other`/`pair` become
1025
+ existing identifier is renamed or repointed, and `self`/`other`/`pair` become
1026
1026
  reserved at the head of the identifier space, which is the only cost.
1027
1027
  Settled for good by Rule 18 being written against it.
1028
1028
  - **Q-29** — What are the file names and schemas for the invariants file and
1029
1029
  the region grid, and how does a level-3 invariant carry `jurisdiction`?
1030
1030
  Settled when the first invariant is written down.
1031
- - **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
1032
1032
  name, its schema, and its relationship to `known_omissions`? Settled by
1033
1033
  REQ-CAT-2's implementation, which is the next data change after this ADR.
1034
1034
 
1035
1035
  **Decided in pencil, PR #23.** The registry is `represented_paragraphs`,
1036
1036
  a sibling array to `known_omissions` in `data/applicability.json`. Each
1037
1037
  record: `id` (paragraph-derived, e.g. `2a`), `jurisdiction`, `cite`,
1038
- `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
1039
1039
  `lights` — a registry record states that the paragraph is represented
1040
1040
  and evaluated by nothing here, never a predicate. Holds the `2(a)` and
1041
1041
  `2(b)` records this PR adds. `✎` under `docs/conventions.md`: the file
@@ -1049,8 +1049,8 @@ here rather than in a commit message. All pencil.
1049
1049
 
1050
1050
  **Decided in pencil 2026-09-04 (PR #24)**, answering the data half of `Q-27`:
1051
1051
  the field names are `category`, `subjects` and `effect`, and `effect` is
1052
- `{own, other}` roles for a `precedence` entry and `{part, section,
1053
- 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`
1054
1054
  §"Effects", required by `REQ-CAT-8`, and exercised by
1055
1055
  `fixtures/situation-fixtures.json`. `Q-28`'s namespace is settled for good by
1056
1056
  the same PR — Rule 18 is written against it and it held, with one addition:
@@ -1062,13 +1062,13 @@ named that gap before the class existed.
1062
1062
  - **Q-31** — `modality` is a single closed value, and 18(c), 18(d)(i) and 9(a)
1063
1063
  each carry two deontic qualifications at once: a practicability caveat
1064
1064
  ("so far as possible", "if the circumstances of the case admit") *and* the
1065
- duty itself. 18(c) is expressible because `shall-if-practicable` already
1065
+ duty itself. 18(c) is expressible because `modality:shall-if-practicable` already
1066
1066
  exists; 18(d)(i) is not, and its caveat is dropped with a `gap` note on the
1067
1067
  entry. Settled by deciding whether practicability is a second field beside
1068
1068
  `modality` rather than a value inside it — which is the same question
1069
1069
  `modality_by` answers for the light rules, and should probably be answered
1070
1070
  the same way. **Narrowed, not settled, 2026-09-04 (PR #25):** 18(d)(i) is now
1071
- `shall-if-practicable` with `effect.own: shall-not-impede`, so the two
1071
+ `modality:shall-if-practicable` with `effect.self: role:shall-not-impede`, so the two
1072
1072
  qualifications sit in two fields and neither is dropped. That works only
1073
1073
  because this duty happens to be a *role*, which `effect` already carries;
1074
1074
  9(a)'s "if the circumstances of the case admit" has no second field to move
@@ -1086,7 +1086,7 @@ named that gap before the class existed.
1086
1086
  `rule18_class:fishing` by 3(d), and the 27(c) tow that severely restricts the
1087
1087
  pair — the one the old predicates could not catch at all — to
1088
1088
  `rule18_class:ram`, via a new boolean `fact:tow_restricts_deviation`. Every
1089
- 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
1090
1090
  `fact:activity` any more, and a test enforces that. `fact:activity` itself is
1091
1091
  unchanged and no entry that reads it was touched. What is *not* settled: the
1092
1092
  eighth rank Rule 18 distinguishes is the seaplane of 3(e), and it has no
@@ -1116,7 +1116,7 @@ named that gap before the class existed.
1116
1116
  alternative was declined: it would have produced a predicate no reader could
1117
1117
  check against the rule text, to avoid a language feature the rules themselves
1118
1118
  use in plain words.
1119
- - **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
1120
1120
  paragraphs identify the protected vessel by a property this package does not
1121
1121
  carry: "a vessel which can safely navigate only within a narrow channel"
1122
1122
  (9(b), 9(d)), "any vessel following a traffic lane" (10(i), 10(j)), and a
@@ -1142,37 +1142,37 @@ named that gap before the class existed.
1142
1142
  predicate reads only facts, so entry `rule:8f_iii` reads the risk-of-collision half
1143
1143
  alone and applies to every pair with risk of collision. Settled by deciding
1144
1144
  whether a norm may read another norm's effect, which is the same question a
1145
- `conduct` monitor will ask about role and phase.
1145
+ `category:conduct` monitor will ask about role and phase.
1146
1146
  - **Q-36** — Rule 18(a)(iv) and 18(d)(i) are both in force between a sailing
1147
1147
  vessel and a vessel constrained by her draught: the CBD vessel gives way, and
1148
1148
  the sailing vessel must not impede her. Neither overrides the other and the
1149
- 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`
1150
1150
  at once. The test suite pins it as a finding rather than asserting it away.
1151
1151
  Settled by reading 8(f)(ii) against the cases, not by picking a role.
1152
- - **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
1153
1153
  first-cut table, but it is the one paragraph of Rule 13 that assigns a role
1154
- and a `classification` entry has nowhere to put one. Entry `rule:13a` is
1155
- `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`
1156
1156
  entry that would set the `hist:was_overtaking` latch. Settled with the rest
1157
1157
  of `Q-14`, paragraph by paragraph.
1158
1158
 
1159
1159
  **Closed in pencil 2026-09-04 (PR #26).** 13(b) is now written, as *two*
1160
- `classification` entries rather than one — one per subject — because the
1160
+ `category:classification` entries rather than one — one per subject — because the
1161
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 `precedence`, and its predicate now carries both
1162
+ overtaken vessel's side of the same encounter as a crossing. 13(a) stays `category:precedence`, and its predicate now carries both
1163
1163
  halves of "any vessel overtaking any other": the 13(b) sector and the 13(d)
1164
1164
  latch, as an `any_of`, which closes the gap the entry recorded. 13(d) is a
1165
- third `classification` entry, reading history and no geometry at all. The
1165
+ third `category:classification` entry, reading history and no geometry at all. The
1166
1166
  split confirms the thing ADR 0005 §1 was really defending — one category per
1167
1167
  paragraph. **Reversed in part, 2026-09-16:** ADR 0015 as rewritten makes
1168
1168
  13(b) one symmetric entry, `rule:13b`, reading the same sector object on
1169
- either subject under `any_of`. 13(a) staying `precedence` is untouched.
1169
+ either subject under `any_of`. 13(a) staying `category:precedence` is untouched.
1170
1170
  - **Q-38** — 9(d), 18(d)(ii), 18(e), 18(f)(ii), 1(a)–(e) and 20(b)–(c) are
1171
1171
  recorded in `known_omissions` rather than modelled: 9(d) needs the channel's
1172
1172
  axis, 18(e) needs a fact for being a seaplane, 20(b)–(c) need time of day,
1173
1173
  and 1(a)–(e) are addressed to an authority rather than to a vessel. Settled
1174
1174
  one at a time as the facts they need land; none blocks the rest of Part B.
1175
- - **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
1176
1176
  of visibility" is the absence of a condition. That makes it unfalsifiable —
1177
1177
  `REQ-VERIFY-3`'s "excluded by at least one fixture" half cannot be satisfied
1178
1178
  and the test exempts it explicitly. Settled by deciding whether an ungated
@@ -1181,17 +1181,17 @@ named that gap before the class existed.
1181
1181
 
1182
1182
  ### From the classification norms (PR #26)
1183
1183
 
1184
- Rules 7(d), 12, 13(b)–(d), 14 and 15 are the first `classification` entries and
1185
- 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
1186
1186
  written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1187
1187
 
1188
- - **Q-40** — **Rule 12 is `precedence`, not `classification`.** ADR 0005 §1 and
1189
- 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
1190
1190
  — "one of them shall keep out of the way of the other" — and a
1191
1191
  classification effect has nowhere to put one, which is `Q-37`'s argument
1192
1192
  applied a second time. Two sailing vessels are still in a head-on, a crossing
1193
1193
  or an overtaking; Rule 12 says which of them gives way, not what kind of
1194
- 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`
1195
1195
  rather than an entry. The second half of the question is narrower and worse:
1196
1196
  12(a) says "two sailing vessels", which is 3(c), but entries the three Rule 12 entries
1197
1197
  read `rule18_class:sail` instead, so a vessel engaged in fishing under sail
@@ -1255,7 +1255,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1255
1255
  which is still how the fixtures are written and is what makes these six
1256
1256
  overrides observable rather than invisible.
1257
1257
 
1258
- 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
1259
1259
  `Q-14`.
1260
1260
  - **Q-41** — **13(c) and 14(c) invert the absent-fact rule.** "When a vessel is
1261
1261
  in any doubt as to whether she is overtaking, she shall assume that this is
@@ -1316,14 +1316,14 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1316
1316
  the same question `Q-39` asks about an ungated norm, from the other end.
1317
1317
 
1318
1318
  **Decided in pencil 2026-09-05 (PR #36): the head-on classification cites
1319
- 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
1320
1320
  effect of its own. It produces the only effect the entry has: "such a
1321
1321
  situation shall be deemed to exist when…" is the deeming test, and
1322
- `{"encounter": "head-on"}` is what a deeming test yields — exactly as
1322
+ `{"encounter": "encounter:head-on"}` is what a deeming test yields — exactly as
1323
1323
  `rule:13b` cites 13(b), the deeming paragraph,
1324
1324
  and not 13(a). 14(a) states the situation in words ("reciprocal or nearly
1325
1325
  reciprocal courses") and imposes the duty ("each shall alter her course to
1326
- starboard"); the duty is `conduct`, and the words are what 14(b) makes
1326
+ starboard"); the duty is `category:conduct`, and the words are what 14(b) makes
1327
1327
  checkable. So the entry is `rule:14b`, cites 14(b), and reads nothing 14(b) does
1328
1328
  not fix; 14(a) joins `known_omissions` as conduct beside 18(d)(ii), and
1329
1329
  the `14a` id it displaced is gone with the rest of the citation-derived ids
@@ -1333,7 +1333,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1333
1333
  instance of it.
1334
1334
  - **Q-46** — **"Coming up with" is a comparison of two facts.** 13(b) deems a
1335
1335
  vessel to be overtaking when *coming up with* another from more than 22.5°
1336
- abaft her beam. That is `own:kin:sog_kn` against `other:kin:sog_kn`, and the
1336
+ abaft her beam. That is `self:kin:sog_kn` against `other:kin:sog_kn`, and the
1337
1337
  predicate language compares a fact to a constant and never one fact to
1338
1338
  another — the same wall `rule:12a_ii` hits on "both have the wind on the same side",
1339
1339
  which it gets over only because that comparison has two values to enumerate
@@ -1351,7 +1351,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1351
1351
  Not approximated with a range or a bearing: past and clear is a seamanship
1352
1352
  judgement of the same kind as risk of collision, and a threshold for it would
1353
1353
  be a number invented rather than declared. Settled by whatever settles the
1354
- `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
1355
1355
  begin.
1356
1356
 
1357
1357
  **Ruled 2026-09-08:** while one vessel holds the latch, 13(a)'s sector
@@ -1364,7 +1364,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1364
1364
  drops back onto the latch-holder's own stern, and only the latch-holder
1365
1365
  gives way.
1366
1366
  - **Q-48** — **Nothing checks that a situation is geometrically possible.**
1367
- `own:geo:rel_bearing_deg`, `other:geo:rel_bearing_deg`, the two
1367
+ `self:geo:rel_bearing_deg`, `other:geo:rel_bearing_deg`, the two
1368
1368
  `kin:heading_deg` and the two `kin:sog_kn` are six facts related by two
1369
1369
  equations, and the situation record enforces neither. A consumer — or a
1370
1370
  fixture — can state a pair of bearings that no two headings produce, and the
@@ -1381,7 +1381,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1381
1381
  **Decided in pencil 2026-09-05: the record gains a consistency check,
1382
1382
  declared in data and enforced in the suite.** `data/facts.json` declares the
1383
1383
  equations under `situation.geometry.consistency` — the two relative bearings
1384
- are two readings of one line of sight (`own + own heading + 180 ≡ aspect +
1384
+ are two readings of one line of sight (`self + self heading + 180 ≡ aspect +
1385
1385
  other heading`), positions reproduce range and both bearings, and the two
1386
1386
  headings and speeds reproduce CPA, TCPA and bearing rate — with tolerances,
1387
1387
  and `REQ-VERIFY-8` requires the suite to apply them. A quantity a record does
@@ -1398,7 +1398,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1398
1398
  "never both give-way" property is asserted over a sweep of steady-bearing
1399
1399
  geometries — every relative bearing, several speed pairs, both intercept
1400
1400
  solutions — where it is a theorem rather than an observation:
1401
- `u·sin(own bearing) = −v·sin(aspect)`, so the two bearings lie on opposite
1401
+ `u·sin(self bearing) = −v·sin(aspect)`, so the two bearings lie on opposite
1402
1402
  sides and 15(a) can name only one vessel. The both-starboard counterexample
1403
1403
  is pinned as a record the check rejects. What is *not* settled, and is
1404
1404
  pinned too: the theorem is exact only at a bearing rate of zero, and
@@ -1412,7 +1412,7 @@ written up in `docs/identifiers.md` §"Effects"; what it could not is here.
1412
1412
 
1413
1413
  - **Q-49** — **Must `rule:13d`'s effect cross the Section II/III boundary for Rule 19(d)(i) to be expressible?**
1414
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 `own:hist:was_overtaking`/`other:hist:was_overtaking` directly, as `rule:14b` and `rule:15a:crossing` already do.
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.
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`).