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.
Files changed (37) hide show
  1. package/LICENSE +194 -26
  2. package/PROVENANCE.md +45 -12
  3. package/README.md +222 -23
  4. package/data/applicability.json +1252 -190
  5. package/data/deprecated-identifiers.json +7 -0
  6. package/data/facts.json +556 -113
  7. package/data/geometry.json +33 -33
  8. package/data/images.json +51 -25
  9. package/data/lights.json +35 -35
  10. package/data/rules.json +787 -3
  11. package/docs/adr/0001-name-and-jurisdiction-model.md +119 -1
  12. package/docs/adr/0003-language-as-a-dimension.md +220 -0
  13. package/docs/adr/0004-licence-layering.md +78 -0
  14. package/docs/adr/0005-rule-categories-and-the-situation-record.md +323 -0
  15. package/docs/adr/0006-json-schema-and-identifier-diff.md +95 -0
  16. package/docs/adr/0007-rule26-overrides-and-aground.md +68 -0
  17. package/docs/adr/0008-mooring-buoy-modifier.md +87 -0
  18. package/docs/budgets.json +162 -0
  19. package/docs/conventions.md +27 -0
  20. package/docs/gates.json +84 -0
  21. package/docs/identifiers.md +435 -0
  22. package/docs/part-b-invariants.md +922 -0
  23. package/docs/requirements.md +1251 -23
  24. package/docs/verification/2026-08-30-q6-q8.md +278 -0
  25. package/docs/verification/2026-09-05-rule27f-rule28-anchor-scenarios.md +330 -0
  26. package/fixtures/applicability-fixtures.json +361 -227
  27. package/fixtures/situation-fixtures.json +3673 -0
  28. package/package.json +16 -4
  29. package/schema/applicability-fixtures.schema.json +49 -0
  30. package/schema/applicability.schema.json +401 -0
  31. package/schema/deprecated-identifiers.schema.json +29 -0
  32. package/schema/facts.schema.json +793 -0
  33. package/schema/geometry.schema.json +239 -0
  34. package/schema/images.schema.json +53 -0
  35. package/schema/lights.schema.json +131 -0
  36. package/schema/rules.schema.json +50 -0
  37. 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.