colregs 0.2.3 → 0.3.0
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/PROVENANCE.md +7 -3
- package/README.md +116 -286
- package/data/applicability.json +13 -10
- package/data/corpora.json +41 -0
- package/data/editions.json +27 -0
- package/data/images.json +570 -33
- package/data/rules.json +202 -610
- package/data/text/intl/2016/en-US.uscg.json +877 -0
- package/data/text/intl/2016/es.boe.json +23 -0
- package/data/text/intl/2016/fi.finlex.json +22 -0
- package/data/text/us/inland/2014/en-US.ecfr.json +22 -0
- package/data/version.json +1 -1
- package/docs/adr/0001-name-and-jurisdiction-model.md +75 -2
- package/docs/adr/0003-language-as-a-dimension.md +9 -8
- package/docs/adr/0010-text-withheld-jurisdictions.md +123 -0
- package/docs/adr/0011-api-shape.md +173 -0
- package/docs/adr/0012-trace-and-rule2-departure-api.md +202 -0
- package/docs/adr/0013-corpus-files-with-editions.md +70 -0
- package/docs/budgets.json +16 -2
- package/docs/gates.json +3 -3
- package/docs/requirements.md +77 -35
- package/docs/timeline.md +102 -0
- package/docs/verification/2026-09-09-text-slug-straw-man.md +265 -0
- package/fixtures/situation-fixtures.json +78 -0
- package/package.json +1 -1
- package/schema/corpora.schema.json +68 -0
- package/schema/corpus.schema.json +329 -0
- package/schema/editions.schema.json +47 -0
- package/schema/images.schema.json +26 -1
- package/schema/rules.schema.json +27 -24
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "intl@2016.es.boe",
|
|
3
|
+
"edition": "intl@2016",
|
|
4
|
+
"edition_status": "claimed",
|
|
5
|
+
"language": "es",
|
|
6
|
+
"source_id": "boe",
|
|
7
|
+
"tier": "national",
|
|
8
|
+
"normalization": "NFC",
|
|
9
|
+
"source": {
|
|
10
|
+
"publisher": "Agencia Estatal Boletín Oficial del Estado",
|
|
11
|
+
"title": "Instrumento de Adhesión de España al Convenio sobre el Reglamento internacional para prevenir los abordajes, 1972",
|
|
12
|
+
"url": "https://www.boe.es/",
|
|
13
|
+
"retrieved": null
|
|
14
|
+
},
|
|
15
|
+
"rights": {
|
|
16
|
+
"source_text": "BOE aviso legal: reuse permitted, commercial and non-commercial; consolidated texts must not be represented as official",
|
|
17
|
+
"redistribution_basis": "BOE aviso legal, with attribution",
|
|
18
|
+
"attribution": "Fuente de los datos: Agencia Estatal Boletín Oficial del Estado",
|
|
19
|
+
"package_licence": "Apache-2.0"
|
|
20
|
+
},
|
|
21
|
+
"note": "Stub: the BOE instrument id is not yet located; resolve it and the retrieval date before any text lands -- Q-7.",
|
|
22
|
+
"paragraphs": {}
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "us/inland@2014.en-US.ecfr",
|
|
3
|
+
"edition": "us/inland@2014",
|
|
4
|
+
"edition_status": "claimed",
|
|
5
|
+
"language": "en-US",
|
|
6
|
+
"source_id": "ecfr",
|
|
7
|
+
"tier": "national",
|
|
8
|
+
"normalization": "NFC",
|
|
9
|
+
"source": {
|
|
10
|
+
"publisher": "Office of the Federal Register, eCFR",
|
|
11
|
+
"title": "33 CFR Part 83, Navigation Rules (Inland)",
|
|
12
|
+
"url": "https://www.ecfr.gov/current/title-33/chapter-I/subchapter-E/part-83",
|
|
13
|
+
"retrieved": null
|
|
14
|
+
},
|
|
15
|
+
"rights": {
|
|
16
|
+
"source_text": "Work of the United States Government, not subject to copyright in the United States (17 U.S.C. 105)",
|
|
17
|
+
"redistribution_basis": "17 U.S.C. 105",
|
|
18
|
+
"package_licence": "Apache-2.0"
|
|
19
|
+
},
|
|
20
|
+
"note": "Stub: a second jurisdiction, so the key shape is exercised on both axes; the delta itself waits on Q-11 -- REQ-SCOPE-3.",
|
|
21
|
+
"paragraphs": {}
|
|
22
|
+
}
|
package/data/version.json
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# ADR 0001 — Package name, and jurisdiction as a dimension
|
|
2
2
|
|
|
3
3
|
Date: 2026-08-29
|
|
4
|
-
Status: accepted; amended 2026-09-05
|
|
4
|
+
Status: accepted; amended 2026-09-05, 2026-09-09 and 2026-09-12 (licence
|
|
5
|
+
terms verified, see Amendments). CEVNI's text stays blocked; ADR 0010
|
|
6
|
+
unblocks modelling it.
|
|
5
7
|
|
|
6
8
|
## Context
|
|
7
9
|
|
|
@@ -94,7 +96,7 @@ what it implies for which instrument supplies the Rules *text*.
|
|
|
94
96
|
| Jurisdiction | Instrument (text source) | Delta | Licence, verified | Attribution to ship (REQ-PROV-3) |
|
|
95
97
|
|---|---|---|---|---|
|
|
96
98
|
| `us/inland` | 33 CFR 83, eCFR | large | 17 U.S.C. §105, public domain | none; credit USCG by custom |
|
|
97
|
-
| `eu/cevni` | CEVNI Rev.6 (UNECE) | largest | **unverified** — unece.org unreachable from the checking host; the UN default terms are personal, non-commercial only.
|
|
99
|
+
| `eu/cevni` | CEVNI Rev.6 (UNECE) | largest | **unverified** — unece.org unreachable from the checking host; the UN default terms are personal, non-commercial only. Text blocked until written permission or a national transposition; structure may be modelled now with the text withheld — ADR 0010 | — |
|
|
98
100
|
| `ca/inland` | Collision Regulations, C.R.C. c.1416, Schedule 1 | moderate | Reproduction of Federal Law Order SI/97-5 | none; accuracy diligence required, and must not be represented as an official version |
|
|
99
101
|
| `de/binnen` | SeeSchStrO (delta) + KVR, Anlage to SeeStrOV (text) | large | §5(1) UrhG, no copyright | none |
|
|
100
102
|
| `uk` | SI 1996/75 (delta) + MSN 1781 (text) | near-zero | OGL v3.0, Crown copyright | "Contains public sector information licensed under the Open Government Licence v3.0." |
|
|
@@ -141,6 +143,9 @@ what it implies for which instrument supplies the Rules *text*.
|
|
|
141
143
|
or a national transposition under an open licence (Germany's BinSchStrO
|
|
142
144
|
under §5(1) UrhG, or the Netherlands' BPR) — the same corpus by a lawful
|
|
143
145
|
route, at the cost of being a national delta rather than "CEVNI".
|
|
146
|
+
A third way opened later: ADR 0010 permits modelling CEVNI now, text
|
|
147
|
+
withheld. These two remedies restore the text; they no longer gate the
|
|
148
|
+
work.
|
|
144
149
|
8. **IMO's own text is closed to this package.** The IMO website terms
|
|
145
150
|
permit copying and adaptation "for the User's personal, non-commercial
|
|
146
151
|
purposes" and state that "Reuse of the Materials for commercial purposes
|
|
@@ -192,3 +197,71 @@ is not made here.
|
|
|
192
197
|
<https://www.un.org/en/about-us/terms-of-use>.
|
|
193
198
|
- IMO: <https://www.imo.org/en/About/Conventions/Pages/COLREG.aspx>;
|
|
194
199
|
<https://www.imo.org/en/About/Pages/IMO-Website-Terms-and-conditions-of-use.aspx>.
|
|
200
|
+
|
|
201
|
+
### 2026-09-09 — Independent re-check (issue #75), plus per-language corpus sources (Q-7)
|
|
202
|
+
|
|
203
|
+
Re-fetched issue #75's primary sources; checked Q-7's three per-language
|
|
204
|
+
corpus candidates, previously unchecked. Q-6 (authenticity) verified
|
|
205
|
+
2026-08-30.
|
|
206
|
+
|
|
207
|
+
#### Six jurisdictions — confirms 2026-09-05 verbatim, nothing changed
|
|
208
|
+
|
|
209
|
+
| Jurisdiction | Re-checked against | Result |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| `us` | [17 U.S.C. §105](https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title17-section105&num=0&edition=prelim) | Confirmed: "Copyright protection under this title is not available for any work of the United States Government." Public domain, as recorded. |
|
|
212
|
+
| `uk` | [OGL v3.0](https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/) | Confirmed: copy/adapt/exploit commercially permitted; required attribution string matches; excludes third-party rights. As recorded. |
|
|
213
|
+
| `au` | [legislation.gov.au terms-of-use](https://www.legislation.gov.au/terms-of-use) | Confirmed CC BY 4.0; both attribution strings (unchanged/adapted) match verbatim. As recorded. |
|
|
214
|
+
| `de` | [§5 UrhG](https://www.gesetze-im-internet.de/urhg/__5.html) | Confirmed: §5(1) excludes Gesetze, Verordnungen, amtliche Erlasse und Bekanntmachungen from copyright outright; §5(2)'s conditions apply only to the other class of official works. As recorded. |
|
|
215
|
+
| `ca` | [Reproduction of Federal Law Order, SI/97-5](https://laws-lois.justice.gc.ca/eng/regulations/SI-97-5/page-1.html) | Confirmed: reproduction permitted "provided due diligence is exercised... and the reproduction is not represented as an official version." As recorded. |
|
|
216
|
+
| `eu/cevni` | [unece.org/copyright](https://unece.org/copyright) (403), [unece.org/general/copyright-notice](https://unece.org/general/copyright-notice) (403); [un.org copyright](https://www.un.org/en/about-us/copyright), [un.org terms-of-use](https://www.un.org/en/about-us/terms-of-use) | Both unece.org paths 403 again — independently reproduces "unreachable" rather than assuming it. UN default terms confirmed restrictive: "personal, non-commercial use... no right to resell, redistribute... or create derivative works." Still blocked, not merely unclear — no change. |
|
|
217
|
+
|
|
218
|
+
#### Per-language corpus sources (Q-7) — new ground, mixed result
|
|
219
|
+
|
|
220
|
+
| Source | Checked against | Verdict |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| BOE (`es`) | [boe.es/informacion/aviso_legal](https://www.boe.es/informacion/aviso_legal/index.php) (the path Q-7 guessed, `boe.es/aviso_legal/`, 404s) | Clean — permits the reuse REQ-PROV-2 needs. Commercial + non-commercial reuse; required attribution ("Fuente de los datos: Agencia Estatal Boletín Oficial del Estado", or "Basado en datos de..." for derivatives); consolidated texts must not be represented as official. Matches Q-7's guess; cheapest language to unblock. |
|
|
223
|
+
| UNTS (`en`/`fr`) | [un.org terms-of-use](https://www.un.org/en/about-us/terms-of-use), [un.org copyright](https://www.un.org/en/about-us/copyright), [treaties.un.org FAQ](https://treaties.un.org/pages/Overview.aspx?path=overview%2Ffaq%2Fpage1_en.xml) (no copyright content) | Ambiguous, new concern — no UNTS-specific rights page found; the only primary terms reachable were the UN's general "personal, non-commercial... no derivative works" terms, the same ones blocking CEVNI. Weakens rather than confirms Q-7's "UNTS deposit is likely lawful" assumption. Resolves via a UNTS-specific rights statement, written UN permission, or a national republication (the `de`/`uk`/`ca`/`us` pattern already used for `intl`). |
|
|
224
|
+
| Finlex (`fi`) | [finlex.fi](https://www.finlex.fi/en/), [finlex.fi/en/legislation](https://www.finlex.fi/en/legislation/), [Tekijänoikeuslaki 404/1961](https://www.finlex.fi/fi/laki/ajantasa/1961/19610404) | Inconclusive — no terms/copyright text was present in the fetched HTML (JS-rendered shells); §9's carve-out for *säädökset* could not be confirmed from primary text. A secondary source (Electronic Frontier Finland) reports a live, contested Finlex copyright claim over compiled statute text. Resolves via a JS-capable fetch of §9 and Finlex's actual ToS page. |
|
|
225
|
+
|
|
226
|
+
`es` clears REQ-PROV-2; `fi` and `en`/`fr` via UNTS stay open. Updating
|
|
227
|
+
`docs/requirements.md` Q-7 for this is left as a follow-up (concurrent
|
|
228
|
+
edits to that file are in flight elsewhere).
|
|
229
|
+
|
|
230
|
+
### 2026-09-12 — UNTS and Finlex resolved (issue #81, Q-7)
|
|
231
|
+
|
|
232
|
+
Re-ran both 2026-09-09 checks with a fetch that renders what looked like a
|
|
233
|
+
JS-only shell. Finlex turned out not to need a browser: its Next.js page
|
|
234
|
+
ships the article text inline in a React Server Components payload that a
|
|
235
|
+
plain fetch already receives, just not as visible HTML.
|
|
236
|
+
|
|
237
|
+
**Finlex (`fi`) — resolved clean.** §9, Tekijänoikeuslaki 404/1961: no
|
|
238
|
+
copyright in laws and decrees; in other documents enacted via the Statutes
|
|
239
|
+
Collection and in treaties and similar instruments containing international
|
|
240
|
+
obligations; in the decisions and statements of an authority or other public
|
|
241
|
+
body; or in official translations of the above. Finlex's own FAQ
|
|
242
|
+
(`finlex.fi/fi/ukk`, Ministry of Justice) states published materials carry
|
|
243
|
+
no usage restrictions, and machine-readable open data is licensed CC BY 4.0.
|
|
244
|
+
EFFI's contested claim concerns the compiled database, not the statute text
|
|
245
|
+
§9 already excludes; Finlex's current primary statement outranks that
|
|
246
|
+
secondary source.
|
|
247
|
+
|
|
248
|
+
**UNTS (`en`/`fr`) — resolved, and it does not clear.** Checked the UNTS
|
|
249
|
+
intro and FAQ pages on treaties.un.org and the copyright and terms-of-use
|
|
250
|
+
pages on un.org directly; none needed a browser. No UNTS-specific rights
|
|
251
|
+
page exists anywhere in that set — every path leads to the same general UN
|
|
252
|
+
terms already found blocking CEVNI: personal, non-commercial use, with no
|
|
253
|
+
right to resell, redistribute or create derivative works. Confirmed
|
|
254
|
+
blocked, not merely ambiguous.
|
|
255
|
+
|
|
256
|
+
Per Q-7's per-language routing, `es` (BOE, cleared 2026-09-09) is the
|
|
257
|
+
corpus that unblocks the first non-`intl` text; `fi` is now open alongside
|
|
258
|
+
it. UNTS stays closed pending written UN permission or a national
|
|
259
|
+
republication of the authentic `en`/`fr` text.
|
|
260
|
+
|
|
261
|
+
Sources: `fi` —
|
|
262
|
+
<https://www.finlex.fi/fi/laki/ajantasa/1961/19610404> (§9);
|
|
263
|
+
<https://www.finlex.fi/fi/ukk> (usage terms, CC BY 4.0). UNTS —
|
|
264
|
+
<https://treaties.un.org/Pages/Content.aspx?path=DB/UNTS/pageIntro_en.xml>;
|
|
265
|
+
<https://treaties.un.org/Pages/Overview.aspx?path=overview/faq/page1_en.xml>;
|
|
266
|
+
<https://www.un.org/en/about-us/copyright>;
|
|
267
|
+
<https://www.un.org/en/about-us/terms-of-use>.
|
|
@@ -79,8 +79,10 @@ with BCP 47 codes, structured as three layers:
|
|
|
79
79
|
consolidated state*: the skeleton declares, as data, the amendment state
|
|
80
80
|
it consolidates, and every corpus declares the amendment state its
|
|
81
81
|
source reflects (REQ-LANG-10). A mismatch is legitimate but
|
|
82
|
-
machine-visible — declared staleness, never silence.
|
|
83
|
-
|
|
82
|
+
machine-visible — declared staleness, never silence. (GATE-2 adopted in
|
|
83
|
+
ADR 0013: `data/editions.json` now registers editions in force
|
|
84
|
+
*concurrently*, so "historical states are prior package versions" holds
|
|
85
|
+
only for a fully superseded edition, not one still in transition.) A
|
|
84
86
|
renumbering amendment is a major version under REQ-PKG-4 — but it is
|
|
85
87
|
resolved by *issuing new paragraph paths and deprecating the old ones*
|
|
86
88
|
(REQ-MODEL-10/11), never by repointing an existing path at different
|
|
@@ -124,7 +126,7 @@ consumer's call (the spirit of REQ-CONS-3).
|
|
|
124
126
|
### Sketch (illustrative, not binding on filenames)
|
|
125
127
|
|
|
126
128
|
```text
|
|
127
|
-
data/rules.json # skeleton: paths,
|
|
129
|
+
data/rules.json # skeleton: paths, numbers, gaps, text_status
|
|
128
130
|
data/text/intl.en-US.uscg.json # today's text, relabeled for what it is
|
|
129
131
|
data/text/intl.fr.unts.json # authentic French, when licensed+landed
|
|
130
132
|
data/text/intl.fi.finlex.json # Finnish national text, contributable
|
|
@@ -204,11 +206,10 @@ check. What was declined, and why — recorded so it isn't re-argued:
|
|
|
204
206
|
renumbering lands — or when Q-8's check of the first national
|
|
205
207
|
amalgamation shows paragraph paths do not survive it.
|
|
206
208
|
- **A full temporal/legal-version model** (instrument → edition → corpus as
|
|
207
|
-
first-class layers; GATE-2).
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
that is a new ADR.
|
|
209
|
+
first-class layers; GATE-2). Declined *here*; the cheap 80% (declared
|
|
210
|
+
amendment state, machine-visible mismatch) was adopted instead. **Re-taken
|
|
211
|
+
and adopted in ADR 0013**, on the trigger this bullet named: a
|
|
212
|
+
jurisdiction requiring multiple concurrent editions.
|
|
212
213
|
- **`dir: ltr|rtl` metadata per language.** Derivable from the language
|
|
213
214
|
tag via CLDR by any consumer that needs it; storing it invites drift.
|
|
214
215
|
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# ADR 0010 — A jurisdiction may ship without its rule text
|
|
2
|
+
|
|
3
|
+
Date: 2026-09-09
|
|
4
|
+
Status: accepted
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
REQ-PROV-2 blocks a jurisdiction until its reproduction terms are checked
|
|
9
|
+
against the primary source. Three passes have now checked CEVNI's and come
|
|
10
|
+
back the same way: unece.org is unreachable from the checking hosts (403,
|
|
11
|
+
reproduced independently), and the UN's default terms grant personal,
|
|
12
|
+
non-commercial use with "no right to resell, redistribute, or create
|
|
13
|
+
derivative works" — see ADR 0001's 2026-09-05 and 2026-09-09 amendments. The
|
|
14
|
+
remedies named there — written permission from UN Publications, or a national
|
|
15
|
+
transposition such as Germany's BinSchStrO — are both slow, and one of them
|
|
16
|
+
is somebody else's decision.
|
|
17
|
+
|
|
18
|
+
Meanwhile `eu/cevni` has sat in the jurisdiction vocabulary
|
|
19
|
+
(requirements.md §2) as a value nothing may populate, and every session that
|
|
20
|
+
has looked at it has read "licence blocked" as "jurisdiction blocked" and
|
|
21
|
+
stopped.
|
|
22
|
+
|
|
23
|
+
That reading is wrong, and it is the cost here. What this package is for is
|
|
24
|
+
**evaluating rules correctly**: which entries apply, what modality they
|
|
25
|
+
carry, which gates they turn on. None of that needs a word of the rule text.
|
|
26
|
+
A licence forbidding reproduction of an expression does not forbid modelling
|
|
27
|
+
what the expression provides, any more than a copyright in a timetable
|
|
28
|
+
forbids knowing when the train leaves.
|
|
29
|
+
|
|
30
|
+
## Decision
|
|
31
|
+
|
|
32
|
+
**A jurisdiction whose reproduction terms fail or cannot be verified MAY be
|
|
33
|
+
implemented as structure, with its text withheld.** REQ-PROV-2 continues to
|
|
34
|
+
govern *reproducing text*; it does not govern *modelling rules*. Structure
|
|
35
|
+
here means everything except the words: paragraph paths, rule numbers,
|
|
36
|
+
applicability entries, facts, gates, geometry, modality, and the relations
|
|
37
|
+
between a jurisdiction's paragraphs and the international ones.
|
|
38
|
+
|
|
39
|
+
Referencing a rule by number is not reproduction: a citation is a fact about
|
|
40
|
+
which provision is invoked, not its protected expression, and the package
|
|
41
|
+
needs nothing more than that to be correct.
|
|
42
|
+
|
|
43
|
+
**Mechanism.** `data/rules.json` gains a per-paragraph `text_status`:
|
|
44
|
+
|
|
45
|
+
| `text_status` | `text` | meaning |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| `verbatim` (default when absent) | required | today's state: the source's own words |
|
|
48
|
+
| `withheld` | MUST be absent | the paragraph is modelled; its text is not ours to ship |
|
|
49
|
+
|
|
50
|
+
A `withheld` paragraph carries a `withheld_reason` naming the licence
|
|
51
|
+
barrier, and its `rule_title` MUST be a neutral label written for this
|
|
52
|
+
package — "Overtaking", "Sound signals in reduced visibility" — never a
|
|
53
|
+
heading copied from the source. Where a withheld paragraph is substantively
|
|
54
|
+
the same provision as an international one, it carries `mirrors`, a path
|
|
55
|
+
into the `intl` ruleset; a consumer may then display the international text
|
|
56
|
+
**labelled as the international equivalent**, never as that jurisdiction's
|
|
57
|
+
text. CEVNI is largely a restatement of the Rules for inland waters, so
|
|
58
|
+
`mirrors` should cover most of it, leaving the genuine CEVNI-only provisions
|
|
59
|
+
as the short list that shows a placeholder.
|
|
60
|
+
|
|
61
|
+
### ✎ What a withheld paragraph carries in place of text — pencil
|
|
62
|
+
|
|
63
|
+
**Ink is only that the text is withheld and the structure ships.** What
|
|
64
|
+
stands in for the text is deliberately *not* settled here, and this ADR does
|
|
65
|
+
not license a later session to settle it by inference. Any of the following
|
|
66
|
+
may be adopted, dropped or combined before a general release without another
|
|
67
|
+
ADR, and more than one may ship at once — they occupy different keys:
|
|
68
|
+
|
|
69
|
+
| option | key | note |
|
|
70
|
+
|---|---|---|
|
|
71
|
+
| **Redaction** — the citation alone | — | the floor; ships today, needs no decision |
|
|
72
|
+
| **Digest** — a hash of the normalised text, algorithm-qualified | `text_digest` | lets a holder of a lawful copy bind it to our structure, and catches a silent upstream amendment |
|
|
73
|
+
| **Slug** — key nouns and verbs lifted from the paragraph, lemmatised, English counterparts where the source is another language | `text_slug` | the straw man below |
|
|
74
|
+
| **`mirrors`** — the `intl` equivalent | `mirrors` | real, lawful text for the majority of CEVNI; silent exactly where CEVNI differs |
|
|
75
|
+
|
|
76
|
+
**Straw man for the slug**, so the option is designed against something
|
|
77
|
+
rather than argued about in the abstract: take the paragraph, keep the key
|
|
78
|
+
nouns and verbs, drop everything else, lemmatise, emit a sorted set —
|
|
79
|
+
`blue-board`, `overtake`, `sound-signal`. Deterministic, reproducible from
|
|
80
|
+
the same input, no word order, no syntax, no prose. Where the source is not
|
|
81
|
+
English, the terms map to their English counterparts, which is the same
|
|
82
|
+
vocabulary the applicability entries already use. Build it and judge it; it
|
|
83
|
+
may be replaced or dropped. See the research issue.
|
|
84
|
+
|
|
85
|
+
Nothing here turns on where the line between indexing and a derivative work
|
|
86
|
+
falls. That question is not this ADR's to answer and does not gate the work:
|
|
87
|
+
redaction ships today whatever the answer, and the slug is a straw man to be
|
|
88
|
+
built, investigated or thrown away later.
|
|
89
|
+
|
|
90
|
+
How a withheld paragraph reads on screen is likewise a display choice, not a
|
|
91
|
+
data one.
|
|
92
|
+
|
|
93
|
+
## Consequences
|
|
94
|
+
|
|
95
|
+
- **No future session may record CEVNI as blocked.** It is unblocked for
|
|
96
|
+
structure as of this ADR, blocked for text until ADR 0001's licence
|
|
97
|
+
question is answered. The same route is open to any jurisdiction that
|
|
98
|
+
fails REQ-PROV-2 later; nothing here is CEVNI-specific.
|
|
99
|
+
- **A different bar still stands, and it is not this one.** REQ-SCOPE-3 and
|
|
100
|
+
Q-11 hold that no non-`intl` jurisdiction lands until an explicit
|
|
101
|
+
suppression mechanism exists, because silence-means-inherit would apply
|
|
102
|
+
international law where a national body deliberately has none. That is
|
|
103
|
+
about deltas, not licences; it survives this ADR untouched and is the live
|
|
104
|
+
blocker on CEVNI. Read the two together or the wrong one gets blamed.
|
|
105
|
+
- `schema/rules.schema.json` carries the conditional: `text` required unless
|
|
106
|
+
`text_status` is `withheld`, in which case it is forbidden and
|
|
107
|
+
`withheld_reason` is required. Only `withheld_reason` is refused on a
|
|
108
|
+
verbatim paragraph; `mirrors`, `text_digest` and `text_slug` are open to
|
|
109
|
+
any paragraph, defined but unwritten, so the pencil options above cannot be
|
|
110
|
+
foreclosed by `additionalProperties: false`. Additive under ADR 0006. Since
|
|
111
|
+
`data/rules.json` is entirely verbatim `intl`, nothing in the data
|
|
112
|
+
exercises that branch — the cases are asserted in `test/data.test.mjs`.
|
|
113
|
+
- **Nothing in evaluation may read `text`.** That is the invariant this
|
|
114
|
+
decision rests on, so it wants a test rather than a promise: fixtures and
|
|
115
|
+
the evaluator output envelope must stay green over a ruleset with every
|
|
116
|
+
`text` stripped.
|
|
117
|
+
- REQ-PROV-1 still binds: a withheld paragraph records its source, its
|
|
118
|
+
retrieval date and why the text is absent. Withholding is a provenance
|
|
119
|
+
record, not a gap in one — and not a `gaps` entry either, which keeps its
|
|
120
|
+
meaning of a paragraph we could not obtain at all.
|
|
121
|
+
- The licence question stays open where it already is. If permission or a
|
|
122
|
+
national transposition arrives, `withheld` paragraphs gain their text and
|
|
123
|
+
drop the key; no modelling is redone.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# ADR 0011 — The public API: one verb per input
|
|
2
|
+
|
|
3
|
+
Date: 2026-09-07
|
|
4
|
+
Origin: colregs-engine, where it was ADR 0001 until 2026-09-09. The
|
|
5
|
+
decision is about colregs-engine's public API; "this package" below is
|
|
6
|
+
colregs-engine. ADRs for the whole family live here (AGENTS.md).
|
|
7
|
+
Status: accepted. Ink and pencil are marked per item in the register at the
|
|
8
|
+
end, under colregs' `docs/conventions.md`.
|
|
9
|
+
|
|
10
|
+
## Context
|
|
11
|
+
|
|
12
|
+
The engine shipped one entry point, `evaluateDisplay`, and its README promised
|
|
13
|
+
that colregs' `classification` and `precedence` categories would "get their own
|
|
14
|
+
entry points" — a promise made in passing while renaming, with no target to
|
|
15
|
+
build to. Meanwhile colregs' ADR 0005 (pencil, all of it) fixed the *input*
|
|
16
|
+
those categories read: a situation record in `data/facts.json` §`situation`,
|
|
17
|
+
exercised by `fixtures/situation-fixtures.json`, with some twenty two-subject
|
|
18
|
+
entries written against it. The data side exists; the engine side has no shape.
|
|
19
|
+
|
|
20
|
+
This ADR fixes the shape. It does not build it.
|
|
21
|
+
|
|
22
|
+
## Decision
|
|
23
|
+
|
|
24
|
+
### 1. Two inputs, two verbs
|
|
25
|
+
|
|
26
|
+
| input | verb | result | status |
|
|
27
|
+
|---|---|---|---|
|
|
28
|
+
| `FactRecord` — one vessel | `evaluateDisplay` | `DisplayEvaluation` | built |
|
|
29
|
+
| `Situation` — two vessels and the encounter | `evaluateEncounter` | `EncounterEvaluation` | target |
|
|
30
|
+
|
|
31
|
+
A verb is named for the thing it evaluates, in colregs' own vocabulary: a
|
|
32
|
+
*display* is what one vessel shows, an *encounter* is what colregs calls the
|
|
33
|
+
`pair` subject. The proposed pair `classifyEncounter` / `resolvePrecedence`
|
|
34
|
+
is **not** built, for three reasons that are about the data, not taste:
|
|
35
|
+
|
|
36
|
+
- **One predicate pass.** Every `scope`, `classification` and `precedence`
|
|
37
|
+
entry matches the same situation by the same walker, as colregs' reference
|
|
38
|
+
evaluator does; two verbs run it twice or make the caller carry the type on.
|
|
39
|
+
- **Relations cross categories.** Rule 18's precedence entries override Rule
|
|
40
|
+
15's; entry `13a` overrides every Rule 18 entry. `rel:overrides` can only be
|
|
41
|
+
resolved with both sides applied in the same result.
|
|
42
|
+
- **Q-35 is open.** Whether a norm may read another norm's *effect* (8(f)(iii)
|
|
43
|
+
reads "a vessel whose passage is not to be impeded") is unsettled in colregs.
|
|
44
|
+
An API seam here would settle it by accident, in the wrong repository.
|
|
45
|
+
|
|
46
|
+
Each verb has a companion that returns only the matched entry ids —
|
|
47
|
+
`appliedDisplayEntries` today, `appliedEncounterEntries` to come — because
|
|
48
|
+
that is the fixture contract: both fixture files `expect` entry ids.
|
|
49
|
+
|
|
50
|
+
### 2. `FactRecord` keeps its name
|
|
51
|
+
|
|
52
|
+
It is colregs' name for the per-vessel record (`own.fact` is "exactly the
|
|
53
|
+
record above, key for key"). ADR 0005 §2 has the situation wrap two fact
|
|
54
|
+
records; the fact record itself does not widen, and a display consumer never
|
|
55
|
+
sees a situation. A name that hinted at two vessels would describe the wrapper,
|
|
56
|
+
not the thing.
|
|
57
|
+
|
|
58
|
+
### 3. The `Situation` type mirrors the fixture, not the predicate
|
|
59
|
+
|
|
60
|
+
colregs states the situation twice: nested by subject and class in
|
|
61
|
+
`facts.json` §`situation.record` and in every fixture case, and flat as
|
|
62
|
+
`own:fact:activity` inside predicates. The engine's public type is the
|
|
63
|
+
**nested** form. The flat form is the predicate namespace and stays internal
|
|
64
|
+
to the walker.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
interface Situation {
|
|
68
|
+
own: Subject;
|
|
69
|
+
other?: Subject;
|
|
70
|
+
pair?: Pair;
|
|
71
|
+
}
|
|
72
|
+
interface Subject { fact: FactRecord; kin?: Kinematics; geo?: DirectionalGeometry; hist?: History; }
|
|
73
|
+
interface Pair { geo?: PairGeometry; env?: Environment; }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- `own` is required; `other`/`Subject.fact` follow colregs' own fixture schema
|
|
77
|
+
(`situation-fixtures.schema.json`, `0.2.0`) — `other` optional (Rule 19's
|
|
78
|
+
single-vessel scope needs no synthesized one), `fact` required. Every other
|
|
79
|
+
class, and every key inside a class, is optional — absent is absent.
|
|
80
|
+
- Keys keep their full colregs identifier (`'kin:heading_deg'`, not
|
|
81
|
+
`heading_deg`), as `FactRecord` keeps `'fact:length_m'`. A fixture's
|
|
82
|
+
`situation` object is then assignable to `Situation` unedited.
|
|
83
|
+
- `Kinematics`, `History`, the two geometries and `Environment` are
|
|
84
|
+
**generated** from `facts.json` §`situation` by the generator that produces
|
|
85
|
+
`FactRecord`, and checked by the same validator: a situation arriving as
|
|
86
|
+
JSON is rejected on the same terms as a fact record.
|
|
87
|
+
- `FactRecord` is reused, not copied, as `Subject.fact`.
|
|
88
|
+
|
|
89
|
+
### 4. `EncounterEvaluation`, the target result
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
type EntryId = string; // a colregs entry id: '13a', '18b'
|
|
93
|
+
type ParagraphCite = string; // a Rules paragraph cite: '17(c)'
|
|
94
|
+
|
|
95
|
+
interface EncounterEvaluation {
|
|
96
|
+
colregs: { version: string; source: 'resolved' | 'caller' };
|
|
97
|
+
applied: EntryId[];
|
|
98
|
+
scope: EntryId[];
|
|
99
|
+
encounter?: 'head-on' | 'crossing' | 'overtaking' | 'none';
|
|
100
|
+
risk_of_collision: { asserted: boolean; by: EntryId[] };
|
|
101
|
+
roles: { own: SubjectRole[]; other: SubjectRole[] };
|
|
102
|
+
overridden: { id: EntryId; by: EntryId }[];
|
|
103
|
+
modalities: Record<EntryId, Modality>;
|
|
104
|
+
}
|
|
105
|
+
interface SubjectRole { role: Role; by: EntryId; }
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`EntryId` and `ParagraphCite` are both `string`, marking which vocabulary a
|
|
109
|
+
field holds: `applied` and `overridden` cite entries, ADR 0012's `phase` and
|
|
110
|
+
`breaches` cite paragraphs. Field names are snake_case with unit suffixes
|
|
111
|
+
throughout, as colregs' own keys are (`kin:heading_deg`).
|
|
112
|
+
|
|
113
|
+
`colregs` and `applied` mean what they mean on `DisplayEvaluation`. Roles are
|
|
114
|
+
a *set* per subject, each citing the entry that assigned it: colregs' own
|
|
115
|
+
suite pins a sailing vessel meeting a CBD vessel as holding `stand-on` and
|
|
116
|
+
`shall-not-impede` at once (Q-36), and a result type that could hold one role
|
|
117
|
+
would have to lie. `risk_of_collision` carries its grounds because 7(a) lets an
|
|
118
|
+
entry add a ground and never deny one. `encounter` is absent when no
|
|
119
|
+
classification entry fired, conflating "no encounter" with "cannot say" (Q-43);
|
|
120
|
+
ADR 0005 §5's status alphabet is the fix, and is not part of this shape yet.
|
|
121
|
+
|
|
122
|
+
### 5. What this shape does not evaluate
|
|
123
|
+
|
|
124
|
+
Scoped to `evaluateDisplay`/`evaluateEncounter` as defined here, not a ceiling
|
|
125
|
+
on the package; kinematic and temporal evaluation gets two verbs in ADR 0012.
|
|
126
|
+
|
|
127
|
+
- **`conduct`.** Rules 8, 13(a)'s action, 14(a), 16, 17: what a vessel shall
|
|
128
|
+
*do*. Their predicates read a trace — 8(b)'s "readily apparent" alteration,
|
|
129
|
+
17(a)(ii)'s "as soon as it becomes apparent" — and colregs declares
|
|
130
|
+
`kin:rot_deg_min` read "by a conduct monitor, not by a predicate at a point".
|
|
131
|
+
A different input (a trace: a sequence of situations) and a different tool
|
|
132
|
+
(STL/TLA+): `evaluateConduct`, ADR 0012.
|
|
133
|
+
- **`care` and `meta`.** Rules 2(a) and 2(b) are in colregs'
|
|
134
|
+
`represented_paragraphs` registry precisely so nothing computes them.
|
|
135
|
+
- **The Rule 2 region solver** (R0/R1/R2, research-ontology labels, not API).
|
|
136
|
+
Research under `research/`; its runtime face is `evaluateRule2Departure`,
|
|
137
|
+
ADR 0012.
|
|
138
|
+
- **Time.** Freshness, hysteresis and the 13(d) latch's clock are the caller's;
|
|
139
|
+
the engine receives `hist:*` as facts and does not maintain them.
|
|
140
|
+
- **Choosing.** No verb picks a display or a role; every lawful answer is
|
|
141
|
+
returned (REQ-MODEL-8).
|
|
142
|
+
|
|
143
|
+
In scope and expected of `evaluateEncounter`: derived facts (`fact:rule18_class`
|
|
144
|
+
is computed before matching, as colregs specifies), `rel:overrides`
|
|
145
|
+
resolution, and validation of the situation record.
|
|
146
|
+
|
|
147
|
+
## Consequences
|
|
148
|
+
|
|
149
|
+
- The README paragraph promising separate classification and precedence
|
|
150
|
+
entry points is replaced by a pointer here.
|
|
151
|
+
- The next PR builds `Situation` generation and validation; the one after
|
|
152
|
+
`appliedEncounterEntries` against `situation-fixtures.json`; only then
|
|
153
|
+
`evaluateEncounter`. Composition decisions the data leaves open go in
|
|
154
|
+
`docs/engine-notes.md`, as the display ones did.
|
|
155
|
+
- `colregs-engine/schema` stays the home of mirrored colregs shapes; `Situation`
|
|
156
|
+
and `EncounterEvaluation` are engine vocabulary, exported from the root.
|
|
157
|
+
|
|
158
|
+
## Register
|
|
159
|
+
|
|
160
|
+
| item | level | what would settle it |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| Two verbs, one per input; no `classifyEncounter` / `resolvePrecedence` | ink | — |
|
|
163
|
+
| `evaluateDisplay`, `appliedDisplayEntries`, `DisplayEvaluation`, `opts.data`, `colregs.source` | ink | — |
|
|
164
|
+
| `FactRecord` keeps its name | ink | — |
|
|
165
|
+
| `Situation` nested by subject and class, generated from `facts.json` | ink | — |
|
|
166
|
+
| Verb name `evaluateEncounter`; result name `EncounterEvaluation` | ✎ | colregs renaming the `pair` subject or the `encounter` effect |
|
|
167
|
+
| `own` required, `other`/`Subject.fact` per colregs 0.2.0's fixture schema | ✎ | revised 2026-09-07 from "own/other both required"; Mark to confirm before ink |
|
|
168
|
+
| `appliedEncounterEntries` as the fixture-replay companion | ✎ | the situation-fixture replay being written |
|
|
169
|
+
| Field names snake_case with unit suffixes across both ADRs; `EntryId`/`ParagraphCite` alias `string` for ids and cites | ✎ | the rename's alias window closing; a consumer arguing the compiler should enforce the two apart |
|
|
170
|
+
| `EncounterEvaluation` field set (§4) | ✎ | building it; Q-35, Q-36, Q-43 in colregs |
|
|
171
|
+
| `encounter` absent vs the ADR 0005 §5 status alphabet | ✎ | Q-43 |
|
|
172
|
+
| `conduct` is a separate package, not a third verb | ✎ | superseded by ADR 0012: a third and fourth verb, in this package |
|
|
173
|
+
| Geometry-consistency validation (REQ-VERIFY-8) in the engine's validator | ? | deciding whether it is data-suite-only |
|