colregs 0.1.1 → 0.2.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/LICENSE +194 -26
- package/PROVENANCE.md +45 -12
- package/README.md +222 -23
- package/data/applicability.json +1252 -190
- package/data/deprecated-identifiers.json +7 -0
- package/data/facts.json +556 -113
- package/data/geometry.json +33 -33
- package/data/images.json +51 -25
- package/data/lights.json +35 -35
- package/data/rules.json +787 -3
- package/docs/adr/0001-name-and-jurisdiction-model.md +119 -1
- package/docs/adr/0003-language-as-a-dimension.md +220 -0
- package/docs/adr/0004-licence-layering.md +78 -0
- package/docs/adr/0005-rule-categories-and-the-situation-record.md +323 -0
- package/docs/adr/0006-json-schema-and-identifier-diff.md +95 -0
- package/docs/adr/0007-rule26-overrides-and-aground.md +68 -0
- package/docs/adr/0008-mooring-buoy-modifier.md +87 -0
- package/docs/budgets.json +162 -0
- package/docs/conventions.md +27 -0
- package/docs/gates.json +84 -0
- package/docs/identifiers.md +435 -0
- package/docs/part-b-invariants.md +922 -0
- package/docs/requirements.md +1251 -23
- package/docs/verification/2026-08-30-q6-q8.md +278 -0
- package/docs/verification/2026-09-05-rule27f-rule28-anchor-scenarios.md +330 -0
- package/fixtures/applicability-fixtures.json +361 -227
- package/fixtures/situation-fixtures.json +3673 -0
- package/package.json +16 -4
- package/schema/applicability-fixtures.schema.json +49 -0
- package/schema/applicability.schema.json +401 -0
- package/schema/deprecated-identifiers.schema.json +29 -0
- package/schema/facts.schema.json +793 -0
- package/schema/geometry.schema.json +239 -0
- package/schema/images.schema.json +53 -0
- package/schema/lights.schema.json +131 -0
- package/schema/rules.schema.json +50 -0
- package/schema/situation-fixtures.schema.json +325 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# ADR 0001 — Package name, and jurisdiction as a dimension
|
|
2
2
|
|
|
3
3
|
Date: 2026-08-29
|
|
4
|
-
Status: accepted
|
|
4
|
+
Status: accepted; amended 2026-09-05 (licence terms verified, see Amendments)
|
|
5
5
|
|
|
6
6
|
## Context
|
|
7
7
|
|
|
@@ -69,8 +69,126 @@ been too narrow. Neither failure was about taste.
|
|
|
69
69
|
configurations, no prior art as structured data, and the only licence on the
|
|
70
70
|
list that might block outright.
|
|
71
71
|
|
|
72
|
+
*Superseded 2026-09-05: the table above is the recalled state and is kept
|
|
73
|
+
as the record of what was assumed. The verified terms are in Amendments
|
|
74
|
+
below.*
|
|
75
|
+
|
|
72
76
|
## Not decided here
|
|
73
77
|
|
|
74
78
|
The switching plugin's name and the renderer's name. The plugin needs a
|
|
75
79
|
`signalk-` prefix for app-store discovery regardless; `lamp-wright` and
|
|
76
80
|
`fanali` are both available and both fit the family for the renderer.
|
|
81
|
+
|
|
82
|
+
## Amendments
|
|
83
|
+
|
|
84
|
+
### 2026-09-05 — Licence terms verified against the primary sources (Q-3, REQ-PROV-2)
|
|
85
|
+
|
|
86
|
+
The table in Consequences was recalled, not checked, and said so. Every
|
|
87
|
+
term below except CEVNI was read from the live primary source on
|
|
88
|
+
2026-09-05; CEVNI remains unresolved (item 7). The fetch-by-fetch evidence is in the private state log of that date
|
|
89
|
+
(`state/global/log/2026-09-05-colregs-jurisdiction-licences.md`). This
|
|
90
|
+
amendment supersedes that table. It does not change the decision — name,
|
|
91
|
+
jurisdiction-as-dimension, the work queue — only the licence column and
|
|
92
|
+
what it implies for which instrument supplies the Rules *text*.
|
|
93
|
+
|
|
94
|
+
| Jurisdiction | Instrument (text source) | Delta | Licence, verified | Attribution to ship (REQ-PROV-3) |
|
|
95
|
+
|---|---|---|---|---|
|
|
96
|
+
| `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. Blocked until written permission is obtained or a national transposition is chosen instead | — |
|
|
98
|
+
| `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
|
+
| `de/binnen` | SeeSchStrO (delta) + KVR, Anlage to SeeStrOV (text) | large | §5(1) UrhG, no copyright | none |
|
|
100
|
+
| `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." |
|
|
101
|
+
| `au` | Marine Order 30 (Prevention of collisions) 2016, F2016L01187 (delta only; text inherited from `intl`) | near-zero | CC BY 4.0 | "Based on content from the Federal Register of Legislation at [full date of download — filled in when the `au` corpus is retrieved]. For the latest information on Australian Government legislation please go to https://www.legislation.gov.au." |
|
|
102
|
+
|
|
103
|
+
**What the recall got wrong.** Recorded so the errors are not re-recalled:
|
|
104
|
+
|
|
105
|
+
1. **AU instrument id.** Marine Order 30 (Prevention of collisions) 2016 is
|
|
106
|
+
F2016L01187. C2016L01175, the id carried on the board, is a different
|
|
107
|
+
instrument (a VET provider revocation).
|
|
108
|
+
2. **AU reproduces no Rules text.** The Order "gives effect to" the
|
|
109
|
+
Convention and defines the International Regulations as the Rules and
|
|
110
|
+
Annexes "as in force from time to time". CC BY 4.0 clears the Australian
|
|
111
|
+
delta only; there is no Australian government publication of the Rules
|
|
112
|
+
to lean on, so `au` inherits its text from `intl` — which the
|
|
113
|
+
jurisdiction-as-delta model already assumes.
|
|
114
|
+
3. **UK: the SI carries no Rules text either.** Regulation 4(1) of SI
|
|
115
|
+
1996/75 incorporates Rules 1–36 and Annexes I–III by reference. The text
|
|
116
|
+
is MSN 1781 (M+F), Crown copyright 2004, published on gov.uk under OGL
|
|
117
|
+
v3.0. OGL is the right licence; MSN 1781 is the source to cite.
|
|
118
|
+
4. **DE: §5(1) UrhG, not the §5(2) *amtliche Werke* limb.** Both SeeSchStrO
|
|
119
|
+
and the KVR Anlage are Verordnungen, which §5(1) excludes from copyright
|
|
120
|
+
outright. The Quellenangabe and Änderungsverbot conditions attach only to
|
|
121
|
+
§5(2) works and so do not apply. The German Rules text also lives in a
|
|
122
|
+
separate instrument from SeeSchStrO: the Anlage to §1 SeeStrOV.
|
|
123
|
+
5. **CA carries two conditions** the recall did not: due diligence as to
|
|
124
|
+
accuracy, and the reproduction "not represented as an official version".
|
|
125
|
+
The README's not-the-law disclaimer should say so explicitly for `ca`.
|
|
126
|
+
The canada.ca general terms (non-commercial only) govern non-enactment
|
|
127
|
+
Crown material and do not displace SI/97-5 for Schedule 1 — but they do
|
|
128
|
+
mean Transport Canada explanatory prose cannot be lifted on the same
|
|
129
|
+
footing.
|
|
130
|
+
6. **US: no page states "public domain".** Neither eCFR nor the USCG
|
|
131
|
+
amalgamated page carries a licence statement, and the Navigation Rules
|
|
132
|
+
Handbook PDF does not say it despite web summaries claiming so. The basis
|
|
133
|
+
is 17 U.S.C. §105(a): "Copyright protection under this title is not
|
|
134
|
+
available for any work of the United States Government".
|
|
135
|
+
7. **CEVNI is unverified, not "unclear".** unece.org, the UN Digital
|
|
136
|
+
Library and UN iLibrary all refused the checking host, so nothing
|
|
137
|
+
UNECE-specific was read. What was read is the UN's default position:
|
|
138
|
+
"All rights reserved", with web-site use limited to "personal,
|
|
139
|
+
non-commercial use, without any right to resell or redistribute". Ways
|
|
140
|
+
through: a written permission from UN Publications Rights & Permissions,
|
|
141
|
+
or a national transposition under an open licence (Germany's BinSchStrO
|
|
142
|
+
under §5(1) UrhG, or the Netherlands' BPR) — the same corpus by a lawful
|
|
143
|
+
route, at the cost of being a national delta rather than "CEVNI".
|
|
144
|
+
8. **IMO's own text is closed to this package.** The IMO website terms
|
|
145
|
+
permit copying and adaptation "for the User's personal, non-commercial
|
|
146
|
+
purposes" and state that "Reuse of the Materials for commercial purposes
|
|
147
|
+
is expressly prohibited", with derivatives bound to the same terms. That
|
|
148
|
+
is incompatible with Apache-2.0 (ADR 0004). The package does not take
|
|
149
|
+
its text from IMO website materials and must not; the US route it
|
|
150
|
+
already takes, and the UK, CA and DE routes above, all reach the same
|
|
151
|
+
Rules text lawfully. Whether IMO holds a copyright in the treaty text
|
|
152
|
+
itself is the separate, open question below.
|
|
153
|
+
|
|
154
|
+
**Accepted risk: IMO copyright in the enacted treaty text.** The `intl`
|
|
155
|
+
text is taken from a US Government publication, and §105 covers that
|
|
156
|
+
publication. It does not, by itself, answer whether IMO holds a copyright
|
|
157
|
+
in the underlying 1972 Convention text that survives national enactment.
|
|
158
|
+
The GPO's own caveat — "Government publications may contain copyrighted
|
|
159
|
+
material which was used with permission of the copyright owner" — and
|
|
160
|
+
OGL's exclusion of "third party rights the Information Provider is not
|
|
161
|
+
authorised to license" are exactly that question. No source checked
|
|
162
|
+
answers it; there is no IMO statement either way. The evidence in
|
|
163
|
+
mitigation is practice: four governments publish the full Rules under
|
|
164
|
+
their own terms — the US as a §105 work, the UK as Crown copyright (MSN
|
|
165
|
+
1781, 2004) under OGL, Canada as an enactment under SI/97-5, and Germany
|
|
166
|
+
as an official translation that §5(1) UrhG makes copyright-free. Each of
|
|
167
|
+
those is a state treating the enacted text as its own official work. This
|
|
168
|
+
is recorded as an **accepted risk**, not as settled. Whether to carry it,
|
|
169
|
+
seek an IMO statement, or narrow the package is the maintainer's call and
|
|
170
|
+
is not made here.
|
|
171
|
+
|
|
172
|
+
**Sources read, 2026-09-05.**
|
|
173
|
+
|
|
174
|
+
- US: <https://www.ecfr.gov/current/title-33/chapter-I/subchapter-E/part-83>;
|
|
175
|
+
<https://www.navcen.uscg.gov/navigation-rules-amalgamated>;
|
|
176
|
+
<https://uscode.house.gov/view.xhtml?req=granuleid:USC-prelim-title17-section105&num=0&edition=prelim>;
|
|
177
|
+
<https://www.govinfo.gov/about/policies>.
|
|
178
|
+
- UK: <https://www.legislation.gov.uk/uksi/1996/75/contents/made>;
|
|
179
|
+
<https://assets.publishing.service.gov.uk/government/uploads/system/uploads/attachment_data/file/281965/msn1781.pdf>;
|
|
180
|
+
<https://www.gov.uk/government/publications/msn-1781-mf-amendment-3-the-merchant-shipping-regulations-1996-colreg>;
|
|
181
|
+
<https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/>.
|
|
182
|
+
- AU: <https://www.legislation.gov.au/F2016L01187/latest/text>;
|
|
183
|
+
<https://www.legislation.gov.au/terms-of-use>.
|
|
184
|
+
- DE: <https://www.gesetze-im-internet.de/seeschstro_1971/BJNR006410971.html>;
|
|
185
|
+
<https://www.gesetze-im-internet.de/seestro_1972/BJNR008160977.html>;
|
|
186
|
+
<https://www.gesetze-im-internet.de/urhg/__5.html>.
|
|
187
|
+
- CA: <https://laws-lois.justice.gc.ca/eng/regulations/C.R.C.,_c._1416/FullText.html>;
|
|
188
|
+
<https://laws-lois.justice.gc.ca/eng/regulations/SI-97-5/page-1.html>;
|
|
189
|
+
<https://www.canada.ca/en/transparency/terms.html>.
|
|
190
|
+
- UN (CEVNI parent terms; UNECE itself unreachable):
|
|
191
|
+
<https://www.un.org/en/about-us/copyright>;
|
|
192
|
+
<https://www.un.org/en/about-us/terms-of-use>.
|
|
193
|
+
- IMO: <https://www.imo.org/en/About/Conventions/Pages/COLREG.aspx>;
|
|
194
|
+
<https://www.imo.org/en/About/Pages/IMO-Website-Terms-and-conditions-of-use.aspx>.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# ADR 0003 — Language as a dimension, text corpora, and display catalogs
|
|
2
|
+
|
|
3
|
+
Date: 2026-08-29
|
|
4
|
+
Status: proposed
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
COLREGS is not an English-language document with translations. The 1972
|
|
9
|
+
Convention was done in English and French, **both texts equally authentic**,
|
|
10
|
+
with official Spanish and Russian translations deposited alongside the
|
|
11
|
+
original; Arabic and Chinese texts exist because they are IMO official
|
|
12
|
+
languages and the consolidated editions are published in all six. On top of
|
|
13
|
+
that, many states gazette their own translation as legally binding national
|
|
14
|
+
law (Finland via Finlex, Germany, Spain via the BOE, …). A package that
|
|
15
|
+
treats English as the text and everything else as decoration has the legal
|
|
16
|
+
reality backwards. (Each of these claims must still be verified against the
|
|
17
|
+
primary source before the corresponding text lands — REQ-PROV-2 applies to
|
|
18
|
+
languages exactly as it does to jurisdictions; see Q-6/Q-7.)
|
|
19
|
+
|
|
20
|
+
The current `data/rules.json` already demonstrates the problem. Its text is
|
|
21
|
+
the **USCG amalgamated rendition** of the international rules, with US
|
|
22
|
+
spelling — "maneuver" where the authentic treaty English reads "manoeuvre".
|
|
23
|
+
So the repo today holds a *national-tier, en-US* corpus of the *intl*
|
|
24
|
+
jurisdiction's rules. "Which jurisdiction's rules" and "which text of them"
|
|
25
|
+
are demonstrably independent questions, and the file-format conflates them:
|
|
26
|
+
`text` is a bare string with one file-level source.
|
|
27
|
+
|
|
28
|
+
Non-legal strings have the same problem one layer down: light names,
|
|
29
|
+
placement prose, and fact-axis labels are inline English inside files the
|
|
30
|
+
requirements call language-neutral.
|
|
31
|
+
|
|
32
|
+
There is also a downstream motive: SignalK's contributor base is heavily
|
|
33
|
+
non-US (Finland especially), and consumers of this package — the educational
|
|
34
|
+
app in particular — will want localized UI in markets that are maritime
|
|
35
|
+
nations first and English-speaking second. The data model should make a
|
|
36
|
+
community-contributed language a single additive pull request.
|
|
37
|
+
|
|
38
|
+
## Decision
|
|
39
|
+
|
|
40
|
+
**Language is a first-class dimension orthogonal to jurisdiction**, tagged
|
|
41
|
+
with BCP 47 codes, structured as three layers:
|
|
42
|
+
|
|
43
|
+
1. **Structural skeleton (language-neutral).** Paragraph paths, rule
|
|
44
|
+
numbers, jurisdictions, entry ids, fact values, light ids, relations,
|
|
45
|
+
predicates, fixtures. None of this ever translates. Translations attach
|
|
46
|
+
to identifiers; they never replace them.
|
|
47
|
+
|
|
48
|
+
2. **Rule-text corpora (legal text).** One corpus per
|
|
49
|
+
(jurisdiction × language × source), keyed by the same paragraph paths as
|
|
50
|
+
the skeleton, carrying `text` and `rule_title` plus corpus-level
|
|
51
|
+
provenance. "Corpus" is the term, not "translation": a corpus may be an
|
|
52
|
+
original text, an official translation, or an independently promulgated
|
|
53
|
+
national instrument — where one is in fact a translation of another,
|
|
54
|
+
that is recorded as explicit `translation_of` metadata. `rule_title` is
|
|
55
|
+
verbatim source material like `text`, not a UI string. Every corpus declares a **status tier**:
|
|
56
|
+
|
|
57
|
+
| tier | meaning | examples |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `authentic` | identified by the governing instrument *itself* as an equally authentic text — the instrument's claim, never this repo's assessment | en and fr per the Convention |
|
|
60
|
+
| `official` | official translation published or deposited through the instrument's depositary organization | es, ru, ar, zh |
|
|
61
|
+
| `national` | a state's legally binding published text | USCG amalgamation, Finlex, BOE |
|
|
62
|
+
| `community` | informational translation, no legal standing | contributed |
|
|
63
|
+
|
|
64
|
+
Tier is a property of the *source*, not the language — today's English
|
|
65
|
+
text is `national` (USCG), and an `authentic` English corpus from the
|
|
66
|
+
UNTS original can be added later beside it. The tier deliberately ranks
|
|
67
|
+
*legal authority*; translation provenance (who translated, reviewed,
|
|
68
|
+
from what) is separate structured metadata on the corpus, not folded
|
|
69
|
+
into the tier. A corpus holds at most one text per paragraph path.
|
|
70
|
+
REQ-MODEL-1's verbatim rule applies per corpus: text is verbatim from
|
|
71
|
+
*its* source at the Unicode level (declared normalization form, no bidi
|
|
72
|
+
control insertion, no localized numerals or punctuation — REQ-LANG-9);
|
|
73
|
+
a `community` corpus must record who produced and reviewed it, and
|
|
74
|
+
machine output without named human review is not accepted.
|
|
75
|
+
|
|
76
|
+
**Amendment state, not a temporal model.** COLREGS has been amended
|
|
77
|
+
repeatedly (Rule 23(c)'s WIG craft arrived in 2001), and national texts
|
|
78
|
+
consolidate on their own schedules. The package models the *current
|
|
79
|
+
consolidated state*: the skeleton declares, as data, the amendment state
|
|
80
|
+
it consolidates, and every corpus declares the amendment state its
|
|
81
|
+
source reflects (REQ-LANG-10). A mismatch is legitimate but
|
|
82
|
+
machine-visible — declared staleness, never silence. Historical states
|
|
83
|
+
are prior package versions, not an in-data version dimension. A
|
|
84
|
+
renumbering amendment is a major version under REQ-PKG-4 — but it is
|
|
85
|
+
resolved by *issuing new paragraph paths and deprecating the old ones*
|
|
86
|
+
(REQ-MODEL-10/11), never by repointing an existing path at different
|
|
87
|
+
text. Repointing is forbidden outright: no version signal expresses it,
|
|
88
|
+
so a consumer cannot detect it.
|
|
89
|
+
|
|
90
|
+
3. **Display catalogs (UI strings, not law).** Per-language message
|
|
91
|
+
catalogs keyed by stable string keys for the identifier vocabularies:
|
|
92
|
+
light names, fact-axis value labels, modality labels, image captions.
|
|
93
|
+
These are what a demo app renders in its UI; they deliberately do *not*
|
|
94
|
+
share a file with legal corpora, because a UI label needs review for
|
|
95
|
+
idiom, while legal text needs provenance and verbatimness. Catalog
|
|
96
|
+
entries are **static strings** — no interpolation, plurals or gender
|
|
97
|
+
grammar; message composition belongs to the consumer's i18n system
|
|
98
|
+
(ICU, gettext, whatever), and this package will not grow a homemade
|
|
99
|
+
one. Catalogs carry lightweight provenance (contributors, reviewers,
|
|
100
|
+
review date, licence): maritime terminology is load-bearing even in a
|
|
101
|
+
UI label, and a translation of a public-domain instrument still has a
|
|
102
|
+
translator holding rights. Maintainer `note` fields inside structural
|
|
103
|
+
files remain untranslated working documentation — not display strings,
|
|
104
|
+
not part of the localization surface.
|
|
105
|
+
|
|
106
|
+
Corpora and catalogs are **additive**: adding a language changes no schema
|
|
107
|
+
and does not edit existing corpora or catalogs (the mirror of REQ-SCOPE-4
|
|
108
|
+
for jurisdictions); required coverage manifests and release documentation
|
|
109
|
+
update as needed.
|
|
110
|
+
Coverage is declared machine-readably — a manifest of which paragraph paths
|
|
111
|
+
each corpus contains — and CI checks every corpus key resolves to a
|
|
112
|
+
skeleton path. Partial corpora are legal and expected; silence never implies
|
|
113
|
+
coverage (the language analogue of REQ-SCOPE-6).
|
|
114
|
+
|
|
115
|
+
The package declares what exists and **never encodes a fallback policy,
|
|
116
|
+
and never silently substitutes one corpus for another**. Text is only
|
|
117
|
+
addressable inside a corpus, so anything a consumer retrieves is
|
|
118
|
+
attributable; a consumer may assemble a mixed-corpus view (Finnish where it
|
|
119
|
+
exists, English where it doesn't), but a mixed view is never a single
|
|
120
|
+
authoritative edition, and the docs say so. Which language to show, and
|
|
121
|
+
what to do when a paragraph is missing from the chosen corpus, is the
|
|
122
|
+
consumer's call (the spirit of REQ-CONS-3).
|
|
123
|
+
|
|
124
|
+
### Sketch (illustrative, not binding on filenames)
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
data/rules.json # skeleton: paths, rule numbers, gaps
|
|
128
|
+
data/text/intl.en-US.uscg.json # today's text, relabeled for what it is
|
|
129
|
+
data/text/intl.fr.unts.json # authentic French, when licensed+landed
|
|
130
|
+
data/text/intl.fi.finlex.json # Finnish national text, contributable
|
|
131
|
+
data/i18n/en.json # display catalog
|
|
132
|
+
data/i18n/fi.json
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Authoritative metadata lives *inside* each corpus file; the filename is a
|
|
136
|
+
convenience, and CI checks the two agree. Source identity is structured
|
|
137
|
+
(publisher, title, edition, publication/effective dates, URL, retrieved —
|
|
138
|
+
REQ-PROV-6), with rights recorded separately for the source text, the basis
|
|
139
|
+
for redistribution, and the package's own distribution licence. The BCP 47
|
|
140
|
+
tag carries the language of the text and nothing else — `en-US` on the
|
|
141
|
+
USCG corpus means US-spelled English, not "US law" and not "for US users";
|
|
142
|
+
provenance and legal applicability live in the metadata, never in the tag.
|
|
143
|
+
|
|
144
|
+
## Sequencing
|
|
145
|
+
|
|
146
|
+
Nothing lands with this ADR. The order later:
|
|
147
|
+
|
|
148
|
+
1. Split `data/rules.json` into skeleton + the existing text as an
|
|
149
|
+
`intl / en-US / uscg / national` corpus. Pure refactor, fixtures
|
|
150
|
+
untouched (they never contained text).
|
|
151
|
+
2. Extract display catalogs for the existing identifier vocabularies (en).
|
|
152
|
+
3. First non-English corpus — chosen by which licence check under Q-6/Q-7
|
|
153
|
+
clears first, not by market size. French (authentic, UNTS) and Finnish
|
|
154
|
+
(national, Finlex) are the likely front of the queue.
|
|
155
|
+
4. Community-contribution path documented in README (one corpus file + one
|
|
156
|
+
catalog file per PR).
|
|
157
|
+
|
|
158
|
+
## Consequences
|
|
159
|
+
|
|
160
|
+
- REQ-PROV-2's licence gate applies per corpus. The IMO consolidated
|
|
161
|
+
six-language editions are sold publications and likely **not**
|
|
162
|
+
reproducible; national gazettes and the UNTS deposit are the probable
|
|
163
|
+
lawful sources. This — not translation effort — is the sequencing
|
|
164
|
+
constraint, recorded as Q-6/Q-7.
|
|
165
|
+
- The README coverage statement (REQ-SCOPE-6) gains a language column:
|
|
166
|
+
jurisdictions × parts × languages, each with its tier.
|
|
167
|
+
- `data/rules.json` as published today is unaffected until step 1 of the
|
|
168
|
+
sequencing lands; the split is a breaking change to the published file
|
|
169
|
+
layout and versions accordingly (REQ-PKG-4).
|
|
170
|
+
- Arabic makes the corpora bidirectional-text-bearing. Plain JSON strings
|
|
171
|
+
carry RTL text fine; the data layer never inserts or strips bidi control
|
|
172
|
+
characters (REQ-LANG-9), and rendering direction is a consumer concern
|
|
173
|
+
that stays out of the data.
|
|
174
|
+
|
|
175
|
+
## Considered and declined (external review, 2026-08-29)
|
|
176
|
+
|
|
177
|
+
Two external reviews (PR #4 comments) shaped the revision above. What they
|
|
178
|
+
changed: tag-carries-language-only, tier definitions as legal claims,
|
|
179
|
+
amendment-state declaration, one-text-per-path, static catalogs with
|
|
180
|
+
provenance, Unicode-level verbatimness, structured source identity with the
|
|
181
|
+
three-rights split, no-silent-substitution phrasing, filename/metadata CI
|
|
182
|
+
check. What was declined, and why — recorded so it isn't re-argued:
|
|
183
|
+
|
|
184
|
+
- **A CI-enforced terminology glossary for translations.** (GATE-5) For legal
|
|
185
|
+
corpora it contradicts verbatimness: the source says what it says, and
|
|
186
|
+
if a national text uses inconsistent terms, so does our copy. A glossary
|
|
187
|
+
as *contributor guidance* for display catalogs may come with the
|
|
188
|
+
contribution docs; it is not schema and not CI.
|
|
189
|
+
- **ICU MessageFormat / interpolation in catalogs.** This is a data
|
|
190
|
+
package, not an i18n runtime. Static labels only; a homegrown message
|
|
191
|
+
system incompatible with real i18n libraries is the failure mode, not
|
|
192
|
+
the feature.
|
|
193
|
+
- **A package-encoded fallback chain** (e.g. `es-MX → es → en`; GATE-4).
|
|
194
|
+
Encoding a preferred substitute for legal text is exactly the
|
|
195
|
+
preference-taking REQ-CONS-3 forbids elsewhere. The stronger, narrower
|
|
196
|
+
rule replaced it: no silent substitution, full attributability, consumer
|
|
197
|
+
decides.
|
|
198
|
+
- **Splitting `paragraph_id` from `citation_path`.** (GATE-1) The paragraph
|
|
199
|
+
path *is* the shared citation across the treaty languages and the
|
|
200
|
+
harmonised national texts (ADR 0001); a second synthetic id would double
|
|
201
|
+
every cross-reference for a renumbering event that is rare, already a
|
|
202
|
+
major version under REQ-PKG-4, and resolvable by deprecation rather than
|
|
203
|
+
repointing (REQ-MODEL-10). Accepted risk, revisit only when a real
|
|
204
|
+
renumbering lands — or when Q-8's check of the first national
|
|
205
|
+
amalgamation shows paragraph paths do not survive it.
|
|
206
|
+
- **A full temporal/legal-version model** (instrument → edition → corpus as
|
|
207
|
+
first-class layers; GATE-2). The package models current consolidated law;
|
|
208
|
+
history lives in package versions. The cheap 80% — declared amendment
|
|
209
|
+
state on skeleton and corpus, machine-visible mismatch — is adopted
|
|
210
|
+
instead. If a jurisdiction ever requires multiple concurrent editions,
|
|
211
|
+
that is a new ADR.
|
|
212
|
+
- **`dir: ltr|rtl` metadata per language.** Derivable from the language
|
|
213
|
+
tag via CLDR by any consumer that needs it; storing it invites drift.
|
|
214
|
+
|
|
215
|
+
Four of these are declined *for now* rather than on principle, and the
|
|
216
|
+
difference matters: each is recorded in requirements §10 as a timed gate,
|
|
217
|
+
with the event that ends its cheap reversibility and the fact that would
|
|
218
|
+
reopen it. GATE-1 (the `paragraph_id` split) is the one that must be
|
|
219
|
+
re-taken deliberately before 1.0; GATE-3 covers the half-adopted
|
|
220
|
+
legal-status × translation-status split.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# ADR 0004 — Licence layering across the family, and Apache-2.0 here
|
|
2
|
+
|
|
3
|
+
Date: 2026-08-29
|
|
4
|
+
Status: accepted
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
|
|
8
|
+
`colregs` shipped 0.1.1 under MIT. `2669e2a` changed the compilation to
|
|
9
|
+
Apache-2.0 with the rationale in the commit body and nowhere else. The
|
|
10
|
+
external review of PR #4 flagged this as the most irreversible change in
|
|
11
|
+
flight and the only one with no record: relicensing is cheap while the
|
|
12
|
+
copyright holder is one person, and stops being cheap at the first merged
|
|
13
|
+
external contribution — which is precisely what the language work exists
|
|
14
|
+
to invite.
|
|
15
|
+
|
|
16
|
+
This ADR records the decision taken in the 2026-08-29 naming/branding
|
|
17
|
+
session. It is a record of a ruling already made, not a re-argument.
|
|
18
|
+
|
|
19
|
+
## Decision
|
|
20
|
+
|
|
21
|
+
Licensing is **layered across the product family**, matched to where the
|
|
22
|
+
novel work lives:
|
|
23
|
+
|
|
24
|
+
| package | licence | status |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `colregs` | Apache-2.0 | landed on `main`, `2669e2a` |
|
|
27
|
+
| `colregs-engine` | Apache-2.0 | repo staked, pre-code |
|
|
28
|
+
| `nav-wright` | AGPL-3.0 | repo staked, pre-code |
|
|
29
|
+
| `searoom` (the app) | AGPL-3.0 | repo seeded |
|
|
30
|
+
|
|
31
|
+
**Why permissive at the data layer.** The rule text is public law and
|
|
32
|
+
carries no copyright claim here. The fixture file is deliberately a
|
|
33
|
+
cross-implementation contract (REQ-VERIFY-1), so the evaluation logic is
|
|
34
|
+
reimplementable by anyone whatever the engine is licensed as — restricting
|
|
35
|
+
the data or the engine protects almost nothing. Adoption is the point: the
|
|
36
|
+
data package sells the ecosystem. Protection of the novel work — renderer,
|
|
37
|
+
app — lives one layer up under AGPL-3.0, where a sole copyright holder can
|
|
38
|
+
still dual-license store builds.
|
|
39
|
+
|
|
40
|
+
**Why Apache-2.0 rather than MIT.** Two reasons. The explicit patent grant,
|
|
41
|
+
where MIT's is ambiguous. And ecosystem fit: signalk-server and the
|
|
42
|
+
prominent community plugins are Apache-2.0, and the planned switching
|
|
43
|
+
plugin loads in-process into that Apache-2.0 host, so every layer it
|
|
44
|
+
consumes has to stay permissive regardless. Sampled 2026-08-30, 19 of the
|
|
45
|
+
top 20 SignalK-ecosystem projects by stars are Apache-2.0 — table in
|
|
46
|
+
<https://github.com/mark-brannan/colregs/pull/4#issuecomment-5467185331>.
|
|
47
|
+
|
|
48
|
+
**npm timing is deliberate.** The change was committed as `chore:` so
|
|
49
|
+
release-please cuts no discrete version for it. npm stays `colregs@0.1.1`
|
|
50
|
+
under MIT until the next release — the i18n work — ships. Published
|
|
51
|
+
artifacts keep the licence they shipped with permanently; the switch
|
|
52
|
+
applies from the next release forward, never retroactively.
|
|
53
|
+
|
|
54
|
+
## Consequences
|
|
55
|
+
|
|
56
|
+
- Recorded as **GATE-6** (requirements §10). Closing event: the first
|
|
57
|
+
merged external contribution. After it, any relicense needs every
|
|
58
|
+
contributor's consent.
|
|
59
|
+
- Already-published npm versions are irreversibly under their shipped
|
|
60
|
+
licence. The gate governs future releases only.
|
|
61
|
+
- The gate is **held open deliberately**, by REQ-PROV-7: `CONTRIBUTING.md`
|
|
62
|
+
states that opening a pull request agrees to a DCO-style certification
|
|
63
|
+
*and* a licence grant to the maintainer sufficient to relicense. The
|
|
64
|
+
grant is the part that holds the gate open; a bare DCO certifies origin
|
|
65
|
+
and grants nothing, so it would not.
|
|
66
|
+
- Honestly: implied assent is weaker than recorded assent. Nothing records
|
|
67
|
+
that a given contributor read the terms — only that they opened a PR
|
|
68
|
+
against a repo containing them. That is the cost of keeping the
|
|
69
|
+
contribution path frictionless while contributors are hypothetical. The
|
|
70
|
+
upgrade path, if they actually arrive, is a CLA-assistant bot that takes
|
|
71
|
+
and stores an explicit per-contributor signature.
|
|
72
|
+
- The data-side question is *not* settled by this ADR. REQ-PROV-4 holds
|
|
73
|
+
code licence and data licence apart, and whether the data wants CC0 or
|
|
74
|
+
CC BY 4.0 separately is GATE-6's trigger, tracked as Q-9.
|
|
75
|
+
- Maintainer position, on record: external contributors are unlikely short
|
|
76
|
+
of major success, so this gate is expected to stay open indefinitely. It
|
|
77
|
+
is recorded anyway — REQ-GATE-1 makes a decline without a named closing
|
|
78
|
+
event incomplete, and "unlikely" is not a closing event.
|