champollion 0.3.3

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 (170) hide show
  1. package/LICENSE +133 -0
  2. package/README.md +387 -0
  3. package/bin/cli.js +278 -0
  4. package/index.js +135 -0
  5. package/lib/api-key.js +127 -0
  6. package/lib/autofix.js +432 -0
  7. package/lib/bridge/method_bridge.py +430 -0
  8. package/lib/card-source-resolution.mjs +284 -0
  9. package/lib/cards/cache.js +169 -0
  10. package/lib/cards/env.js +82 -0
  11. package/lib/cards/fetch-card-child.js +38 -0
  12. package/lib/cards/reader.js +435 -0
  13. package/lib/cards/refresh.js +111 -0
  14. package/lib/cards/remote.js +387 -0
  15. package/lib/cldf-export.mjs +540 -0
  16. package/lib/cldf-terms.mjs +62 -0
  17. package/lib/command-help.js +790 -0
  18. package/lib/commands/audit.js +49 -0
  19. package/lib/commands/card.js +454 -0
  20. package/lib/commands/doctor.js +559 -0
  21. package/lib/commands/fonts.js +489 -0
  22. package/lib/commands/help.js +91 -0
  23. package/lib/commands/init.js +1259 -0
  24. package/lib/commands/integrity.js +148 -0
  25. package/lib/commands/leaderboard.js +478 -0
  26. package/lib/commands/lint.js +30 -0
  27. package/lib/commands/models.js +177 -0
  28. package/lib/commands/plugin.js +103 -0
  29. package/lib/commands/provenance.js +45 -0
  30. package/lib/commands/recommend.js +75 -0
  31. package/lib/commands/register-corpus.js +678 -0
  32. package/lib/commands/repair-script.js +42 -0
  33. package/lib/commands/seal-corpus.js +355 -0
  34. package/lib/commands/seo.js +72 -0
  35. package/lib/commands/serve.js +147 -0
  36. package/lib/commands/status.js +265 -0
  37. package/lib/commands/submit.js +332 -0
  38. package/lib/commands/sync.js +89 -0
  39. package/lib/commands/tm.js +573 -0
  40. package/lib/commands/verify.js +39 -0
  41. package/lib/commands/watch.js +20 -0
  42. package/lib/commands/wrap.js +138 -0
  43. package/lib/commands/xliff.js +327 -0
  44. package/lib/commercial-eligibility.js +235 -0
  45. package/lib/concurrent.js +87 -0
  46. package/lib/config.js +523 -0
  47. package/lib/contamination-lane.js +76 -0
  48. package/lib/content-sync.js +731 -0
  49. package/lib/content.js +733 -0
  50. package/lib/corpus-registration.mjs +608 -0
  51. package/lib/cost-report.js +346 -0
  52. package/lib/diff.js +155 -0
  53. package/lib/docusaurus-sync.js +1256 -0
  54. package/lib/flatten.js +55 -0
  55. package/lib/format.js +954 -0
  56. package/lib/hash.js +159 -0
  57. package/lib/icu.js +473 -0
  58. package/lib/integrity.js +689 -0
  59. package/lib/license-gate.mjs +478 -0
  60. package/lib/license-identify.mjs +229 -0
  61. package/lib/lint.js +629 -0
  62. package/lib/method-manifest.js +60 -0
  63. package/lib/methods/anthropic.js +140 -0
  64. package/lib/methods/apertium.js +163 -0
  65. package/lib/methods/api.js +316 -0
  66. package/lib/methods/base.js +184 -0
  67. package/lib/methods/content-separator.js +45 -0
  68. package/lib/methods/deepl.js +426 -0
  69. package/lib/methods/direct-llm.js +586 -0
  70. package/lib/methods/external.js +332 -0
  71. package/lib/methods/fetch-with-retry.js +124 -0
  72. package/lib/methods/gemini.js +147 -0
  73. package/lib/methods/google-translate.js +402 -0
  74. package/lib/methods/http-utils.js +122 -0
  75. package/lib/methods/libretranslate.js +314 -0
  76. package/lib/methods/llm-coached.js +670 -0
  77. package/lib/methods/llm.js +592 -0
  78. package/lib/methods/local.js +76 -0
  79. package/lib/methods/microsoft-translator.js +331 -0
  80. package/lib/methods/openai.js +131 -0
  81. package/lib/methods/openrouter-client.js +327 -0
  82. package/lib/methods/openrouter-pricing.js +156 -0
  83. package/lib/methods/provider-env.js +115 -0
  84. package/lib/methods/provider-pricing.js +310 -0
  85. package/lib/methods/tilde.js +150 -0
  86. package/lib/methods/translated.js +229 -0
  87. package/lib/methods/translation-error.js +80 -0
  88. package/lib/models.js +258 -0
  89. package/lib/no-translate.js +233 -0
  90. package/lib/output.js +238 -0
  91. package/lib/pairs.js +547 -0
  92. package/lib/plugins.js +447 -0
  93. package/lib/provenance.js +323 -0
  94. package/lib/recommend.js +648 -0
  95. package/lib/registers.js +1185 -0
  96. package/lib/repair-script.js +266 -0
  97. package/lib/scripts.js +994 -0
  98. package/lib/seal.mjs +464 -0
  99. package/lib/sealed-qualifier.mjs +211 -0
  100. package/lib/security.js +59 -0
  101. package/lib/segment.js +369 -0
  102. package/lib/seo.js +275 -0
  103. package/lib/serve.js +854 -0
  104. package/lib/string-classify.js +85 -0
  105. package/lib/submit.mjs +344 -0
  106. package/lib/sync.js +969 -0
  107. package/lib/tags/bcp47.js +202 -0
  108. package/lib/tags/resolve.js +314 -0
  109. package/lib/terminology.js +111 -0
  110. package/lib/tm-seed.js +294 -0
  111. package/lib/tm.js +515 -0
  112. package/lib/translate-pair.js +197 -0
  113. package/lib/translate.js +203 -0
  114. package/lib/types.js +230 -0
  115. package/lib/validate.js +510 -0
  116. package/lib/verify.js +451 -0
  117. package/lib/watch.js +145 -0
  118. package/lib/xliff.js +184 -0
  119. package/package.json +93 -0
  120. package/shared/ATTRIBUTION.md +145 -0
  121. package/shared/CORPORA-CARDS.md +288 -0
  122. package/shared/DATA-SOVEREIGNTY.md +500 -0
  123. package/shared/LANGUAGE-CARD-FIELDS.md +532 -0
  124. package/shared/card-lint-baseline.json +3189 -0
  125. package/shared/cards-fallback.json +1 -0
  126. package/shared/catalogue/card-config.json +6091 -0
  127. package/shared/catalogue/external-results.json +3888 -0
  128. package/shared/catalogue/gender-guidance.json +1038 -0
  129. package/shared/catalogue/method-coverage.json +1751 -0
  130. package/shared/catalogue/metric-coverage.json +170 -0
  131. package/shared/catalogue/metric-reliability.json +1 -0
  132. package/shared/catalogue/register-presets.json +3180 -0
  133. package/shared/catalogue/vitality-scales.json +55 -0
  134. package/shared/cldr-index.json +1115 -0
  135. package/shared/code-bridge.json +253 -0
  136. package/shared/corpora-cards-v1-reference.md +281 -0
  137. package/shared/curated-dictionary-flags.json +35 -0
  138. package/shared/curated-endonyms.json +35 -0
  139. package/shared/curated-fsts.json +51 -0
  140. package/shared/curated-orthography-conventions.json +26 -0
  141. package/shared/curated-sil-resources.json +374 -0
  142. package/shared/curated-tools.json +41 -0
  143. package/shared/docent/corpus.json +11333 -0
  144. package/shared/docent/faq.en.json +564 -0
  145. package/shared/docent/register-blocks.json +60 -0
  146. package/shared/docent/system-prompt.md +144 -0
  147. package/shared/domain-taxonomy.json +35 -0
  148. package/shared/explainers/glossary.json +2975 -0
  149. package/shared/explainers/tc-features.json +20112 -0
  150. package/shared/explainers/term-watchlist.json +147 -0
  151. package/shared/human-services.json +59 -0
  152. package/shared/license-corrections.json +261 -0
  153. package/shared/license-evidence.json +13452 -0
  154. package/shared/licenses.json +6781 -0
  155. package/shared/method-registry.json +236 -0
  156. package/shared/metric-registry.json +620 -0
  157. package/shared/model-aliases.json +7 -0
  158. package/shared/schemas/champollion-plugin.schema.json +206 -0
  159. package/shared/schemas/corpora-card.schema.json +957 -0
  160. package/shared/schemas/domain-taxonomy.schema.json +64 -0
  161. package/shared/schemas/external-results.schema.json +314 -0
  162. package/shared/schemas/human-services.schema.json +90 -0
  163. package/shared/schemas/language-card.schema.json +1308 -0
  164. package/shared/schemas/licenses.schema.json +155 -0
  165. package/shared/schemas/method-card.schema.json +412 -0
  166. package/shared/schemas/method-registry.schema.json +85 -0
  167. package/shared/schemas/metric-registry.schema.json +96 -0
  168. package/shared/schemas/metric-reliability.schema.json +178 -0
  169. package/shared/schemas/model-aliases.schema.json +27 -0
  170. package/shared/schemas/source-snapshot.schema.json +96 -0
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Provenance & Licensing Registry — tracks resource dependencies per method.
3
+ *
4
+ * WHY: When champollion is used commercially, users need to know if
5
+ * their translation pipeline depends on proprietary datasets or tools.
6
+ * This registry makes those dependencies explicit and flaggable.
7
+ *
8
+ * Each translation method declares its resource dependencies:
9
+ * - name: Human-readable resource name
10
+ * - license: SPDX license identifier or "PROPRIETARY"
11
+ * - owner: Organization/person that owns the resource
12
+ * - status: "clear" (licensed/open), "pending-agreement", or "restricted"
13
+ * - url: Link to resource or license info (optional)
14
+ *
15
+ * The CLI surfaces provenance warnings when a pair uses a method with
16
+ * non-commercial resources: "[WARN] This pair uses PROPRIETARY resources"
17
+ *
18
+ * This module REPORTS. Enforcement — refusing to route a non-eligible method
19
+ * in a commercial lane — lives in lib/commercial-eligibility.js, which is
20
+ * also where the `commercialReady` verdict is resolved from the shared
21
+ * registry SSOT. Keep the two consistent by never re-declaring the verdict
22
+ * here; see getProvenance().
23
+ */
24
+
25
+ /**
26
+ * Registry of resource dependencies per translation method.
27
+ *
28
+ * Methods not listed here are assumed to have no external dependencies
29
+ * (i.e., they only use the LLM API, which is covered by the user's
30
+ * own API key and ToS).
31
+ */
32
+ import { resolveCommercialEligibility } from './commercial-eligibility.js';
33
+
34
+ const METHOD_PROVENANCE = {
35
+ llm: {
36
+ resources: [],
37
+ flags: [],
38
+ },
39
+
40
+ 'llm-coached': {
41
+ resources: [],
42
+ flags: [],
43
+ },
44
+
45
+ 'google-translate': {
46
+ resources: [
47
+ {
48
+ name: 'Google Cloud Translation API',
49
+ license: 'Google Cloud ToS',
50
+ owner: 'Google',
51
+ status: 'clear',
52
+ url: 'https://cloud.google.com/translate/docs',
53
+ },
54
+ ],
55
+ flags: [],
56
+ },
57
+
58
+ api: {
59
+ resources: [
60
+ {
61
+ name: 'Remote Translation API',
62
+ license: 'Provider ToS',
63
+ owner: 'API provider',
64
+ status: 'clear',
65
+ url: '',
66
+ },
67
+ ],
68
+ flags: [],
69
+ },
70
+
71
+ deepl: {
72
+ resources: [
73
+ {
74
+ name: 'DeepL Translation API',
75
+ license: 'Proprietary (DeepL ToS)',
76
+ owner: 'DeepL SE',
77
+ status: 'clear',
78
+ url: 'https://www.deepl.com/pro-api',
79
+ },
80
+ ],
81
+ flags: [],
82
+ },
83
+
84
+ 'microsoft-translator': {
85
+ resources: [
86
+ {
87
+ name: 'Microsoft Translator Text API',
88
+ license: 'Microsoft Services Agreement',
89
+ owner: 'Microsoft',
90
+ status: 'clear',
91
+ url: 'https://azure.microsoft.com/services/cognitive-services/translator/',
92
+ },
93
+ ],
94
+ flags: [],
95
+ },
96
+
97
+ libretranslate: {
98
+ resources: [
99
+ {
100
+ name: 'LibreTranslate API',
101
+ license: 'AGPL-3.0',
102
+ owner: 'LibreTranslate',
103
+ status: 'clear',
104
+ url: 'https://libretranslate.com',
105
+ },
106
+ ],
107
+ flags: ['COPYLEFT_AGPL'],
108
+ },
109
+
110
+ openai: {
111
+ resources: [
112
+ {
113
+ name: 'OpenAI Developer API',
114
+ license: 'Proprietary (OpenAI ToS)',
115
+ owner: 'OpenAI',
116
+ status: 'clear',
117
+ url: 'https://openai.com/api',
118
+ },
119
+ ],
120
+ flags: [],
121
+ },
122
+
123
+ anthropic: {
124
+ resources: [
125
+ {
126
+ name: 'Anthropic Messages API',
127
+ license: 'Proprietary (Anthropic ToS)',
128
+ owner: 'Anthropic',
129
+ status: 'clear',
130
+ url: 'https://www.anthropic.com/api',
131
+ },
132
+ ],
133
+ flags: [],
134
+ },
135
+
136
+ gemini: {
137
+ resources: [
138
+ {
139
+ name: 'Google Gemini API',
140
+ license: 'Proprietary (Google ToS)',
141
+ owner: 'Google',
142
+ status: 'clear',
143
+ url: 'https://ai.google.dev',
144
+ },
145
+ ],
146
+ flags: [],
147
+ },
148
+
149
+ 'fst-gated': {
150
+ resources: [
151
+ {
152
+ name: 'Plains Cree FST (GiellaLT)',
153
+ // Upstream LICENSE: AGPL v3 (or-later) with a §7(b) attribution rider
154
+ // — matches shared/licenses.json giellalt-lang-crk. Invoked as a
155
+ // separate tool, never bundled (CLAUDE.md AGPL boundary).
156
+ license: 'AGPL-3.0-or-later',
157
+ owner: 'ALTLab / GiellaLT',
158
+ status: 'clear',
159
+ url: 'https://github.com/giellalt/lang-crk',
160
+ },
161
+ {
162
+ name: 'Wolvengrey Cree Dictionary (nêhiyawêwin: itwêwina / Cree: Words)',
163
+ license: 'PROPRIETARY',
164
+ // Rights-holder is Arok Wolvengrey (First Nations University of
165
+ // Canada; published by University of Regina Press) — NOT UAlberta.
166
+ // ALTLab's itwêwina serves the content for runtime lookups only.
167
+ owner: 'Arok Wolvengrey (First Nations University of Canada); served via ALTLab’s itwêwina',
168
+ status: 'pending-agreement',
169
+ url: 'https://itwewina.altlab.app/',
170
+ },
171
+ ],
172
+ flags: ['PROPRIETARY_DATASET'],
173
+ },
174
+
175
+ 'human-review': {
176
+ resources: [],
177
+ flags: ['REQUIRES_HUMAN'],
178
+ },
179
+ };
180
+
181
+ /**
182
+ * Get provenance info for a translation method.
183
+ *
184
+ * `resources` and `flags` are curated here; **`commercialReady` is derived**
185
+ * from lib/commercial-eligibility.js, which reads the shared method registry
186
+ * SSOT. It is deliberately NOT stored in the table above: it used to be, the
187
+ * two copies drifted, and LibreTranslate ended up declared commercial-ready
188
+ * here while the SSOT (correctly, it is AGPL) said otherwise.
189
+ *
190
+ * Note the default for an unrecorded method is now `false`, not `true` — a
191
+ * licence boundary has to fail safe. This only affects the COMMERCIAL lane;
192
+ * the default non-commercial lane is never gated.
193
+ *
194
+ * @param {string} methodName - Method name (e.g., "llm", "fst-gated")
195
+ * @returns {{resources: Array, commercialReady: boolean, flags: string[],
196
+ * eligibility: object}} `eligibility` carries the structured verdict
197
+ * (source, license, reason) so reports can cite where the answer came from
198
+ */
199
+ function getProvenance(methodName) {
200
+ const base = METHOD_PROVENANCE[methodName] || { resources: [], flags: [] };
201
+ const eligibility = resolveCommercialEligibility(methodName);
202
+ return {
203
+ resources: base.resources,
204
+ flags: base.flags,
205
+ commercialReady: eligibility.eligible,
206
+ eligibility,
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Check if a method is cleared for commercial use.
212
+ *
213
+ * @param {string} methodName - Method name
214
+ * @returns {boolean}
215
+ */
216
+ function isCommercialReady(methodName) {
217
+ const prov = getProvenance(methodName);
218
+ return prov.commercialReady;
219
+ }
220
+
221
+ /**
222
+ * Get all provenance flags for a set of pairs.
223
+ * Aggregates flags across all methods used in the pair graph.
224
+ *
225
+ * Checks TWO sources per pair:
226
+ * 1. The static METHOD_PROVENANCE registry (by method name)
227
+ * 2. The plugin's own provenance declaration (pairConfig.pluginProvenance)
228
+ * Either source can flag a pair as non-commercial.
229
+ *
230
+ * @param {Map<string, object>} pairs - Pair graph from pairs.js
231
+ * @returns {{ flags: string[], blockedPairs: string[], allClear: boolean }}
232
+ */
233
+ function auditProvenance(pairs) {
234
+ const allFlags = new Set();
235
+ const blockedPairs = [];
236
+
237
+ for (const [pairKey, pairConfig] of pairs) {
238
+ let isBlocked = false;
239
+
240
+ // Check 1: static METHOD_PROVENANCE registry by method name
241
+ const methodProv = getProvenance(pairConfig.method);
242
+ for (const flag of methodProv.flags) {
243
+ allFlags.add(flag);
244
+ }
245
+ if (!methodProv.commercialReady) {
246
+ isBlocked = true;
247
+ }
248
+
249
+ // Check 2: plugin's own provenance declaration (from manifest)
250
+ // A plugin can carry licensing info that the static registry doesn't
251
+ // know about — e.g., a coached plugin using proprietary coaching data.
252
+ const pluginProv = pairConfig.pluginProvenance;
253
+ if (pluginProv && typeof pluginProv === 'object') {
254
+ if (Array.isArray(pluginProv.flags)) {
255
+ for (const flag of pluginProv.flags) {
256
+ allFlags.add(flag);
257
+ }
258
+ }
259
+ if (pluginProv.commercialReady === false) {
260
+ isBlocked = true;
261
+ }
262
+ }
263
+
264
+ if (isBlocked) {
265
+ blockedPairs.push(pairKey);
266
+ }
267
+ }
268
+
269
+ return {
270
+ flags: [...allFlags],
271
+ blockedPairs,
272
+ allClear: blockedPairs.length === 0,
273
+ };
274
+ }
275
+
276
+ /**
277
+ * Format a provenance report for CLI output.
278
+ *
279
+ * @param {Map<string, object>} pairs - Pair graph
280
+ * @returns {string} Formatted report
281
+ */
282
+ function formatProvenanceReport(pairs) {
283
+ const audit = auditProvenance(pairs);
284
+ const lines = [];
285
+
286
+ if (audit.allClear) {
287
+ lines.push('[OK] All translation pairs are cleared for commercial use.\n');
288
+ return lines.join('\n');
289
+ }
290
+
291
+ lines.push('[WARN] PROVENANCE WARNINGS\n');
292
+
293
+ for (const pairKey of audit.blockedPairs) {
294
+ const pairConfig = pairs.get(pairKey);
295
+ const prov = getProvenance(pairConfig.method);
296
+
297
+ lines.push(` ${pairKey} (method: ${pairConfig.method})`);
298
+ for (const resource of prov.resources) {
299
+ const statusIcon = resource.status === 'clear' ? '[OK]' : '[RESTRICTED]';
300
+ lines.push(` ${statusIcon} ${resource.name} — ${resource.license} (${resource.status})`);
301
+ if (resource.url) {
302
+ lines.push(` ${resource.url}`);
303
+ }
304
+ }
305
+ lines.push('');
306
+ }
307
+
308
+ if (audit.flags.includes('PROPRIETARY_DATASET')) {
309
+ lines.push(' [WARN] One or more pairs depend on PROPRIETARY datasets.');
310
+ lines.push(' Commercial use requires licensing agreements with the resource owners.');
311
+ lines.push('');
312
+ }
313
+
314
+ return lines.join('\n');
315
+ }
316
+
317
+ export {
318
+ METHOD_PROVENANCE,
319
+ getProvenance,
320
+ isCommercialReady,
321
+ auditProvenance,
322
+ formatProvenanceReport,
323
+ };