@bitmagic/cli 0.1.53-dev.3 → 0.1.53-dev.5

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.
@@ -0,0 +1,516 @@
1
+ /**
2
+ * A QR encoder, so `bitmagic publish` can hand the creator's phone the URL it just printed.
3
+ *
4
+ * The Creator does this server-side already — `PublishController.generateQRCode` calls the `qrcode`
5
+ * package and the publish dialog shows the PNG. The CLI cannot follow it there: `qrcode` drags in
6
+ * `dijkstrajs`, `pngjs` and `yargs@15`, and `@bitmagic/cli` is a published package with four
7
+ * deliberately-chosen runtime dependencies. So the encoder lives here instead, cut down to exactly
8
+ * what a published-game URL needs:
9
+ *
10
+ * - **Byte mode only.** A URL is bytes. Numeric, alphanumeric and kanji modes would encode it
11
+ * smaller in theory and never in practice, because `https://` alone rules out alphanumeric.
12
+ * - **Error correction level M only**, matching the Creator's `errorCorrectionLevel: 'M'` — a code
13
+ * scanned from this terminal and one scanned from the publish dialog then behave identically.
14
+ * - **Versions 1-9 only.** The character-count indicator is 8 bits up to version 9 and 16 bits
15
+ * from version 10, so stopping here removes a branch and four tables. Version 9 holds 180 bytes;
16
+ * the longest URL this ever sees is the dev portal's, around 60. Anything longer returns null
17
+ * rather than growing the tables — see `encodeQr`.
18
+ *
19
+ * Structure follows ISO/IEC 18004. Every table below is a literal with the spec's own name for it,
20
+ * and `__tests__/qr.test.ts` checks each one against fixtures generated by the `qrcode` package, so
21
+ * a transposed digit fails loudly instead of producing a code that scans as garbage.
22
+ */
23
+ import { Buffer } from 'buffer';
24
+ /** The largest symbol version this encoder builds. Above it the count indicator widens to 16 bits. */
25
+ const MAX_VERSION = 9;
26
+ /** Byte mode's 4-bit mode indicator (ISO/IEC 18004 table 2). */
27
+ const MODE_BYTE = 0b0100;
28
+ /** The two padding codewords, applied alternately to fill the data capacity (11.2.1). */
29
+ const PAD_CODEWORDS = [0xec, 0x11];
30
+ const BLOCKS_M = [
31
+ { ecPerBlock: 10, group1Blocks: 1, group1Data: 16, group2Blocks: 0, group2Data: 0 }, // v1 = 26
32
+ { ecPerBlock: 16, group1Blocks: 1, group1Data: 28, group2Blocks: 0, group2Data: 0 }, // v2 = 44
33
+ { ecPerBlock: 26, group1Blocks: 1, group1Data: 44, group2Blocks: 0, group2Data: 0 }, // v3 = 70
34
+ { ecPerBlock: 18, group1Blocks: 2, group1Data: 32, group2Blocks: 0, group2Data: 0 }, // v4 = 100
35
+ { ecPerBlock: 24, group1Blocks: 2, group1Data: 43, group2Blocks: 0, group2Data: 0 }, // v5 = 134
36
+ { ecPerBlock: 16, group1Blocks: 4, group1Data: 27, group2Blocks: 0, group2Data: 0 }, // v6 = 172
37
+ { ecPerBlock: 18, group1Blocks: 4, group1Data: 31, group2Blocks: 0, group2Data: 0 }, // v7 = 196
38
+ { ecPerBlock: 22, group1Blocks: 2, group1Data: 38, group2Blocks: 2, group2Data: 39 }, // v8 = 242
39
+ { ecPerBlock: 22, group1Blocks: 3, group1Data: 36, group2Blocks: 2, group2Data: 37 }, // v9 = 292
40
+ ];
41
+ /**
42
+ * Alignment-pattern centre coordinates per version (ISO/IEC 18004 annex E).
43
+ *
44
+ * A pattern is drawn at every pairing of these coordinates except where it would collide with a
45
+ * finder — `drawAlignmentPatterns` skips those by checking whether the module is already set.
46
+ */
47
+ const ALIGNMENT_POSITIONS = [
48
+ [], // v1 has none
49
+ [6, 18],
50
+ [6, 22],
51
+ [6, 26],
52
+ [6, 30],
53
+ [6, 34],
54
+ [6, 22, 38],
55
+ [6, 24, 42],
56
+ [6, 26, 46],
57
+ ];
58
+ /**
59
+ * The 15-bit format-information strings for level M and mask 0-7 (ISO/IEC 18004 table C.1).
60
+ *
61
+ * Already BCH(15,5)-encoded and XORed with the 0b101010000010010 mask the spec applies, so nothing
62
+ * here has to be computed. Level M is the only row we need, which is why this is a flat array.
63
+ */
64
+ const FORMAT_INFO_M = [0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0];
65
+ /**
66
+ * The 18-bit version-information strings, which only versions 7 and up carry (table D.1).
67
+ *
68
+ * Indexed by version, so entries 1-6 are zero and never read.
69
+ */
70
+ const VERSION_INFO = { 7: 0x07c94, 8: 0x085bc, 9: 0x09a99 };
71
+ /** Penalty weights for the four mask-evaluation rules (ISO/IEC 18004 table 24). */
72
+ const PENALTY_N1 = 3;
73
+ const PENALTY_N2 = 3;
74
+ const PENALTY_N3 = 40;
75
+ const PENALTY_N4 = 10;
76
+ /**
77
+ * The eight data-mask patterns (table 23). True means "invert this module".
78
+ *
79
+ * `row`/`col` are the spec's i/j. These apply to encoding-region modules only; function patterns
80
+ * are written before masking and are never touched, which `placeData` enforces by only filling
81
+ * modules still left null.
82
+ */
83
+ const MASK_FUNCTIONS = [
84
+ (row, col) => (row + col) % 2 === 0,
85
+ (row) => row % 2 === 0,
86
+ (_row, col) => col % 3 === 0,
87
+ (row, col) => (row + col) % 3 === 0,
88
+ (row, col) => (Math.floor(row / 2) + Math.floor(col / 3)) % 2 === 0,
89
+ (row, col) => ((row * col) % 2) + ((row * col) % 3) === 0,
90
+ (row, col) => (((row * col) % 2) + ((row * col) % 3)) % 2 === 0,
91
+ (row, col) => (((row + col) % 2) + ((row * col) % 3)) % 2 === 0,
92
+ ];
93
+ // ---------------------------------------------------------------------------------------------
94
+ // GF(256) arithmetic, for Reed-Solomon
95
+ // ---------------------------------------------------------------------------------------------
96
+ /**
97
+ * Exponent and log tables over GF(256) with primitive polynomial 0x11d and generator 2 (annex B).
98
+ *
99
+ * The exponent table runs to 512 entries — a doubled copy — so `gfMul` can add two logs (each up to
100
+ * 254) and index straight in without a modulo.
101
+ */
102
+ function buildGaloisTables() {
103
+ const exp = new Uint8Array(512);
104
+ const log = new Uint8Array(256);
105
+ let value = 1;
106
+ for (let i = 0; i < 255; i += 1) {
107
+ exp[i] = value;
108
+ log[value] = i;
109
+ value <<= 1;
110
+ if ((value & 0x100) !== 0)
111
+ value ^= 0x11d;
112
+ }
113
+ for (let i = 255; i < 512; i += 1)
114
+ exp[i] = exp[i - 255];
115
+ return { exp, log };
116
+ }
117
+ const { exp: GF_EXP, log: GF_LOG } = buildGaloisTables();
118
+ function gfMultiply(a, b) {
119
+ if (a === 0 || b === 0)
120
+ return 0;
121
+ return GF_EXP[GF_LOG[a] + GF_LOG[b]];
122
+ }
123
+ /**
124
+ * The generator polynomial of the given degree, in descending coefficient order.
125
+ *
126
+ * Built as the product of (x - a^0)(x - a^1)...; subtraction is XOR in GF(2), so the sign vanishes.
127
+ */
128
+ function generatorPolynomial(degree) {
129
+ let poly = Uint8Array.from([1]);
130
+ for (let d = 0; d < degree; d += 1) {
131
+ const next = new Uint8Array(poly.length + 1);
132
+ for (let i = 0; i < poly.length; i += 1) {
133
+ next[i] ^= poly[i];
134
+ next[i + 1] ^= gfMultiply(poly[i], GF_EXP[d]);
135
+ }
136
+ poly = next;
137
+ }
138
+ return poly;
139
+ }
140
+ /** The `ecLength` error-correction codewords for one block of data codewords. */
141
+ function reedSolomon(data, ecLength) {
142
+ const generator = generatorPolynomial(ecLength);
143
+ // Long division of `data` shifted up by ecLength places; the remainder is the ECC.
144
+ const remainder = new Uint8Array(data.length + ecLength);
145
+ remainder.set(data);
146
+ for (let i = 0; i < data.length; i += 1) {
147
+ const factor = remainder[i];
148
+ if (factor === 0)
149
+ continue;
150
+ for (let j = 0; j < generator.length; j += 1) {
151
+ remainder[i + j] ^= gfMultiply(generator[j], factor);
152
+ }
153
+ }
154
+ return remainder.slice(data.length);
155
+ }
156
+ // ---------------------------------------------------------------------------------------------
157
+ // Codewords
158
+ // ---------------------------------------------------------------------------------------------
159
+ function totalDataCodewords(spec) {
160
+ return spec.group1Blocks * spec.group1Data + spec.group2Blocks * spec.group2Data;
161
+ }
162
+ /**
163
+ * How many bytes fit at this version, in byte mode at level M.
164
+ *
165
+ * The header costs 12 bits — 4 for the mode indicator plus 8 for the count — so the payload gets
166
+ * the data capacity less one and a half codewords, rounded down.
167
+ */
168
+ function byteCapacity(version) {
169
+ return Math.floor((totalDataCodewords(BLOCKS_M[version - 1]) * 8 - 12) / 8);
170
+ }
171
+ /** The smallest version that holds `byteLength` bytes, or null when even version 9 does not. */
172
+ function smallestVersion(byteLength) {
173
+ for (let version = 1; version <= MAX_VERSION; version += 1) {
174
+ if (byteLength <= byteCapacity(version))
175
+ return version;
176
+ }
177
+ return null;
178
+ }
179
+ /**
180
+ * The final codeword sequence: header, payload, padding, ECC, interleaved as the spec requires.
181
+ *
182
+ * Interleaving (8.6) is what makes a burst of damage survivable — consecutive codewords in the
183
+ * symbol come from different blocks, so a smudge spreads its errors across every block's budget
184
+ * instead of exhausting one.
185
+ */
186
+ function buildCodewords(payload, version) {
187
+ const spec = BLOCKS_M[version - 1];
188
+ const dataCodewordCount = totalDataCodewords(spec);
189
+ const capacityBits = dataCodewordCount * 8;
190
+ const bits = [];
191
+ const pushBits = (value, length) => {
192
+ for (let i = length - 1; i >= 0; i -= 1)
193
+ bits.push((value >>> i) & 1);
194
+ };
195
+ pushBits(MODE_BYTE, 4);
196
+ pushBits(payload.length, 8);
197
+ for (const byte of payload)
198
+ pushBits(byte, 8);
199
+ // Terminator: up to four zero bits, truncated if the capacity ends first (11.1).
200
+ for (let i = 0; i < 4 && bits.length < capacityBits; i += 1)
201
+ bits.push(0);
202
+ while (bits.length % 8 !== 0)
203
+ bits.push(0);
204
+ const data = new Uint8Array(dataCodewordCount);
205
+ for (let i = 0; i < bits.length; i += 1) {
206
+ if (bits[i] === 1)
207
+ data[i >> 3] |= 0x80 >> (i & 7);
208
+ }
209
+ for (let i = bits.length / 8, pad = 0; i < dataCodewordCount; i += 1, pad += 1) {
210
+ data[i] = PAD_CODEWORDS[pad % 2];
211
+ }
212
+ const blocks = [];
213
+ let offset = 0;
214
+ const groups = [
215
+ [spec.group1Blocks, spec.group1Data],
216
+ [spec.group2Blocks, spec.group2Data],
217
+ ];
218
+ for (const [count, size] of groups) {
219
+ for (let b = 0; b < count; b += 1) {
220
+ const chunk = data.slice(offset, offset + size);
221
+ offset += size;
222
+ blocks.push({ data: chunk, ec: reedSolomon(chunk, spec.ecPerBlock) });
223
+ }
224
+ }
225
+ const out = [];
226
+ const longestBlock = Math.max(spec.group1Data, spec.group2Data);
227
+ for (let i = 0; i < longestBlock; i += 1) {
228
+ for (const block of blocks) {
229
+ if (i < block.data.length)
230
+ out.push(block.data[i]);
231
+ }
232
+ }
233
+ for (let i = 0; i < spec.ecPerBlock; i += 1) {
234
+ for (const block of blocks)
235
+ out.push(block.ec[i]);
236
+ }
237
+ return Uint8Array.from(out);
238
+ }
239
+ function moduleCount(version) {
240
+ return version * 4 + 17;
241
+ }
242
+ /**
243
+ * One finder pattern with its separator, anchored at the given top-left module.
244
+ *
245
+ * The loop runs from -1 to 7 rather than 0 to 6 so the one-module separator is written in the same
246
+ * pass, as false. Out-of-range coordinates are skipped, which is what keeps the three call sites
247
+ * identical despite each finder having its separator on different sides.
248
+ */
249
+ function drawFinderPattern(grid, row, col) {
250
+ const size = grid.length;
251
+ for (let r = -1; r <= 7; r += 1) {
252
+ if (row + r < 0 || row + r >= size)
253
+ continue;
254
+ for (let c = -1; c <= 7; c += 1) {
255
+ if (col + c < 0 || col + c >= size)
256
+ continue;
257
+ const onOuterRing = (r >= 0 && r <= 6 && (c === 0 || c === 6))
258
+ || (c >= 0 && c <= 6 && (r === 0 || r === 6));
259
+ const inCore = r >= 2 && r <= 4 && c >= 2 && c <= 4;
260
+ grid[row + r][col + c] = onOuterRing || inCore;
261
+ }
262
+ }
263
+ }
264
+ function drawTimingPatterns(grid) {
265
+ const size = grid.length;
266
+ for (let i = 8; i < size - 8; i += 1) {
267
+ if (grid[i][6] === null)
268
+ grid[i][6] = i % 2 === 0;
269
+ if (grid[6][i] === null)
270
+ grid[6][i] = i % 2 === 0;
271
+ }
272
+ }
273
+ function drawAlignmentPatterns(grid, version) {
274
+ const positions = ALIGNMENT_POSITIONS[version - 1];
275
+ for (const row of positions) {
276
+ for (const col of positions) {
277
+ // Already written means a finder owns this corner; the spec omits the pattern there.
278
+ if (grid[row][col] !== null)
279
+ continue;
280
+ for (let r = -2; r <= 2; r += 1) {
281
+ for (let c = -2; c <= 2; c += 1) {
282
+ grid[row + r][col + c] = r === -2 || r === 2 || c === -2 || c === 2 || (r === 0 && c === 0);
283
+ }
284
+ }
285
+ }
286
+ }
287
+ }
288
+ /**
289
+ * The two copies of the format information, plus the always-dark module beside the bottom-left
290
+ * finder (8.9). Written before the data so `placeData` treats these positions as occupied.
291
+ */
292
+ function drawFormatInfo(grid, mask) {
293
+ const size = grid.length;
294
+ const bits = FORMAT_INFO_M[mask];
295
+ for (let i = 0; i < 15; i += 1) {
296
+ const dark = ((bits >> i) & 1) === 1;
297
+ // Copy one, running down the left of the top-left finder and skipping the timing row.
298
+ if (i < 6)
299
+ grid[i][8] = dark;
300
+ else if (i < 8)
301
+ grid[i + 1][8] = dark;
302
+ else
303
+ grid[size - 15 + i][8] = dark;
304
+ // Copy two, running left from the top-right corner and continuing under the top-left finder.
305
+ if (i < 8)
306
+ grid[8][size - i - 1] = dark;
307
+ else if (i < 9)
308
+ grid[8][15 - i] = dark;
309
+ else
310
+ grid[8][14 - i] = dark;
311
+ }
312
+ grid[size - 8][8] = true;
313
+ }
314
+ /** The two copies of the version information, for versions 7 and up only (8.10). */
315
+ function drawVersionInfo(grid, version) {
316
+ if (version < 7)
317
+ return;
318
+ const size = grid.length;
319
+ const bits = VERSION_INFO[version];
320
+ for (let i = 0; i < 18; i += 1) {
321
+ const dark = ((bits >> i) & 1) === 1;
322
+ const major = Math.floor(i / 3);
323
+ const minor = i % 3;
324
+ grid[major][size - 11 + minor] = dark;
325
+ grid[size - 11 + minor][major] = dark;
326
+ }
327
+ }
328
+ /**
329
+ * Fill the encoding region with the codeword bits, masking as we go.
330
+ *
331
+ * The walk is the spec's: two-module-wide columns from the right edge leftwards, alternating
332
+ * upward and downward, right module of the pair before the left. Column 6 is the vertical timing
333
+ * pattern and is stepped over entirely rather than skipped module by module.
334
+ *
335
+ * Running out of codewords is not an error — versions 2 to 6 have leftover remainder bits, which
336
+ * the spec fills with zeros. They still get masked, which is why this cannot just stop early.
337
+ */
338
+ function placeData(grid, codewords, mask) {
339
+ const size = grid.length;
340
+ const maskFn = MASK_FUNCTIONS[mask];
341
+ let bitIndex = 7;
342
+ let byteIndex = 0;
343
+ let row = size - 1;
344
+ let upward = true;
345
+ for (let col = size - 1; col > 0; col -= 2) {
346
+ if (col === 6)
347
+ col -= 1;
348
+ for (;;) {
349
+ for (let c = 0; c < 2; c += 1) {
350
+ if (grid[row][col - c] !== null)
351
+ continue;
352
+ let dark = false;
353
+ if (byteIndex < codewords.length) {
354
+ dark = ((codewords[byteIndex] >>> bitIndex) & 1) === 1;
355
+ }
356
+ if (maskFn(row, col - c))
357
+ dark = !dark;
358
+ grid[row][col - c] = dark;
359
+ bitIndex -= 1;
360
+ if (bitIndex === -1) {
361
+ byteIndex += 1;
362
+ bitIndex = 7;
363
+ }
364
+ }
365
+ row += upward ? -1 : 1;
366
+ if (row < 0 || row >= size) {
367
+ row -= upward ? -1 : 1;
368
+ upward = !upward;
369
+ break;
370
+ }
371
+ }
372
+ }
373
+ }
374
+ function buildSymbol(codewords, version, mask) {
375
+ const size = moduleCount(version);
376
+ const grid = Array.from({ length: size }, () => new Array(size).fill(null));
377
+ drawFinderPattern(grid, 0, 0);
378
+ drawFinderPattern(grid, size - 7, 0);
379
+ drawFinderPattern(grid, 0, size - 7);
380
+ drawAlignmentPatterns(grid, version);
381
+ drawTimingPatterns(grid);
382
+ drawFormatInfo(grid, mask);
383
+ drawVersionInfo(grid, version);
384
+ placeData(grid, codewords, mask);
385
+ // Every module is written by now: the function patterns above cover the whole reserved area, and
386
+ // placeData fills every remaining null. The cast is the only place this file assumes that.
387
+ return grid.map((row) => row.map((module) => module === true));
388
+ }
389
+ // ---------------------------------------------------------------------------------------------
390
+ // Mask selection
391
+ // ---------------------------------------------------------------------------------------------
392
+ /**
393
+ * The spec's four penalty rules (8.8.2), summed. Lower is better.
394
+ *
395
+ * Scored over the entire symbol including function patterns, as the spec requires — the finders'
396
+ * own 1:1:3:1:1 ratio is exactly what rule 3 hunts for elsewhere, and excluding them would let a
397
+ * mask hide a false finder against a real one.
398
+ */
399
+ export function maskPenalty(matrix) {
400
+ const size = matrix.length;
401
+ let points = 0;
402
+ // Rule 1: runs of five or more same-coloured modules in a row or column.
403
+ for (let a = 0; a < size; a += 1) {
404
+ let runRow = 1;
405
+ let runCol = 1;
406
+ for (let b = 1; b < size; b += 1) {
407
+ if (matrix[a][b] === matrix[a][b - 1])
408
+ runRow += 1;
409
+ else {
410
+ if (runRow >= 5)
411
+ points += PENALTY_N1 + (runRow - 5);
412
+ runRow = 1;
413
+ }
414
+ if (matrix[b][a] === matrix[b - 1][a])
415
+ runCol += 1;
416
+ else {
417
+ if (runCol >= 5)
418
+ points += PENALTY_N1 + (runCol - 5);
419
+ runCol = 1;
420
+ }
421
+ }
422
+ if (runRow >= 5)
423
+ points += PENALTY_N1 + (runRow - 5);
424
+ if (runCol >= 5)
425
+ points += PENALTY_N1 + (runCol - 5);
426
+ }
427
+ // Rule 2: every 2x2 block of one colour.
428
+ for (let row = 0; row < size - 1; row += 1) {
429
+ for (let col = 0; col < size - 1; col += 1) {
430
+ const dark = matrix[row][col];
431
+ if (matrix[row][col + 1] === dark
432
+ && matrix[row + 1][col] === dark
433
+ && matrix[row + 1][col + 1] === dark) {
434
+ points += PENALTY_N2;
435
+ }
436
+ }
437
+ }
438
+ // Rule 3: the 1:1:3:1:1 finder ratio with four light modules on one side, either orientation.
439
+ // Tracked as an 11-bit sliding window per row and per column; 0x5d0 is 10111010000 and 0x05d is
440
+ // 00001011101.
441
+ for (let a = 0; a < size; a += 1) {
442
+ let windowRow = 0;
443
+ let windowCol = 0;
444
+ for (let b = 0; b < size; b += 1) {
445
+ windowRow = ((windowRow << 1) & 0x7ff) | (matrix[a][b] ? 1 : 0);
446
+ windowCol = ((windowCol << 1) & 0x7ff) | (matrix[b][a] ? 1 : 0);
447
+ if (b < 10)
448
+ continue;
449
+ if (windowRow === 0x5d0 || windowRow === 0x05d)
450
+ points += PENALTY_N3;
451
+ if (windowCol === 0x5d0 || windowCol === 0x05d)
452
+ points += PENALTY_N3;
453
+ }
454
+ }
455
+ // Rule 4: how far the proportion of dark modules strays from half, in five-percent steps.
456
+ let dark = 0;
457
+ for (const row of matrix) {
458
+ for (const module of row) {
459
+ if (module)
460
+ dark += 1;
461
+ }
462
+ }
463
+ const percent = (dark * 100) / (size * size);
464
+ points += Math.floor(Math.abs(percent - 50) / 5) * PENALTY_N4;
465
+ return points;
466
+ }
467
+ // ---------------------------------------------------------------------------------------------
468
+ // Public surface
469
+ // ---------------------------------------------------------------------------------------------
470
+ /**
471
+ * Encode `text` with an explicitly chosen mask.
472
+ *
473
+ * Exported for the fixture tests, which pin the mask so they compare structure — codewords, ECC,
474
+ * interleaving, function patterns, format bits — rather than a mask heuristic. Callers outside the
475
+ * tests want `encodeQr`.
476
+ */
477
+ export function encodeQrWithMask(text, mask) {
478
+ if (mask < 0 || mask > 7)
479
+ return null;
480
+ const payload = Buffer.from(text, 'utf8');
481
+ const version = smallestVersion(payload.length);
482
+ if (version === null)
483
+ return null;
484
+ return buildSymbol(buildCodewords(payload, version), version, mask);
485
+ }
486
+ /**
487
+ * Encode `text` as a matrix of modules, row-major, true meaning dark. Null when it does not fit.
488
+ *
489
+ * The mask is chosen by the spec's penalty rules. That choice is a legibility heuristic and not a
490
+ * correctness property — all eight masks produce a valid, scannable symbol, and a decoder reads the
491
+ * chosen one out of the format information either way.
492
+ *
493
+ * There is no quiet zone here: it belongs to whatever draws the symbol, which knows what it is
494
+ * drawing onto. `qr-terminal.ts` paints its own.
495
+ */
496
+ export function encodeQr(text) {
497
+ const payload = Buffer.from(text, 'utf8');
498
+ const version = smallestVersion(payload.length);
499
+ if (version === null)
500
+ return null;
501
+ const codewords = buildCodewords(payload, version);
502
+ let best = null;
503
+ let bestPenalty = Number.POSITIVE_INFINITY;
504
+ for (let mask = 0; mask < 8; mask += 1) {
505
+ const candidate = buildSymbol(codewords, version, mask);
506
+ const penalty = maskPenalty(candidate);
507
+ if (penalty < bestPenalty) {
508
+ bestPenalty = penalty;
509
+ best = candidate;
510
+ }
511
+ }
512
+ return best;
513
+ }
514
+ /** The longest text this encoder can hold, in bytes. Exported so a caller can explain a refusal. */
515
+ export const MAX_BYTES = byteCapacity(MAX_VERSION);
516
+ //# sourceMappingURL=qr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"qr.js","sourceRoot":"","sources":["../../src/render/qr.ts"],"names":[],"mappings":"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"}
@@ -396,45 +396,49 @@ export function renderBitmagicJson(metadata) {
396
396
  return renderJson(metadata);
397
397
  }
398
398
  /**
399
- * The "Updating the bitmagic CLI" section, which exists because the answer is written down and was
400
- * still being asked.
399
+ * The "Updating the bitmagic CLI" section, which used to have two jobs and now has one.
401
400
  *
402
- * An agent told to update the CLI in a project directory has two published lines to choose from and,
403
- * before this, nothing in the project that named one so it asked the creator "dev or prod?", which
404
- * is a question the project already answers. The pin decides it (see `updateTagForEnvironment`), so
405
- * the section states the command outright rather than describing how to work it out.
401
+ * It began as an answer to a question the project already answered: an agent told to update the CLI
402
+ * had two published lines to choose from, nothing in the project naming one, and so asked the
403
+ * creator "dev or prod?". The section baked in the right `npm i -g` for the pin and forbade the
404
+ * question.
406
405
  *
407
- * The rule is spelled out under the command anyway, for the one case the baked value can be wrong:
408
- * this file is written at scaffold time and refreshed by `bitmagic upgrade`, so a creator who edits
409
- * `environment` in between has a project whose pin has moved and whose AGENTS.md has not.
406
+ * That instruction was right about the line and wrong about the mechanism. A printed `npm i -g` is
407
+ * run by whatever `npm` the agent's shell resolves, and a coding agent's non-interactive shell
408
+ * sources no profile under nvm it gets a different node's npm, installs into a prefix nothing on
409
+ * PATH points at, and reports success while `bitmagic --version` never moves. `bitmagic
410
+ * self-update` resolves its own install from the running process and reads the pin itself, so the
411
+ * whole two-line explanation collapses into one command that cannot be aimed at the wrong place or
412
+ * the wrong line. What remains of the old paragraph is the *why*, which an agent still needs when
413
+ * something looks wrong — not a choice for it to make.
410
414
  *
411
- * `environment` is undefined for a project scaffolded before the pin existed. That project has no
412
- * answer to bake, so the section gives it the rule and the command that produces the pin instead of
413
- * guessing a line on its behalf.
415
+ * `environment` is undefined for a project scaffolded before the pin existed. The command still
416
+ * works there (it falls back to the line the installed build is on), so that case only loses the
417
+ * sentence naming this project's environment.
414
418
  */
415
419
  function renderCliUpdateSection(environment) {
416
- const install = environment === 'prod' ? 'npm i -g @bitmagic/cli' : 'npm i -g @bitmagic/cli@dev';
417
420
  const here = environment === undefined
418
421
  ? `This project predates the \`environment\` field of \`bitmagic.json\` and so has no pin yet.
419
- Run \`bitmagic upgrade\` once to stamp one; \`bitmagic whoami\` prints what the CLI resolves in the
420
- meantime, and that environment decides the line by the rule below.`
421
- : `This project is on the **${environment}** environment (\`environment\` in
422
- \`bitmagic.json\`), so exactly one command updates the CLI here:
422
+ Run \`bitmagic upgrade\` once to stamp one, and \`bitmagic whoami\` to see what the CLI resolves in
423
+ the meantime; until there is a pin, \`self-update\` keeps you on the line your installed build is
424
+ already on.`
425
+ : `This project is on the **${environment}** environment (\`environment\` in \`bitmagic.json\`), and the command reads that pin itself.`;
426
+ return `## Updating the bitmagic CLI
423
427
 
424
428
  \`\`\`
425
- ${install}
426
- \`\`\``;
427
- return `## Updating the bitmagic CLI
429
+ bitmagic self-update
430
+ \`\`\`
428
431
 
429
432
  ${here}
430
433
 
431
- **Never ask which line to install, and never offer the choice** the environment decides it.
432
- \`dev\` and \`local\` projects take \`npm i -g @bitmagic/cli@dev\`, the prerelease line developed
433
- against the dev api-server; \`prod\` projects take the plain \`npm i -g @bitmagic/cli\`. They are not
434
- interchangeable the wrong one calls endpoints that do not exist yet, or lags the engine its
435
- environment serves, and both fail as opaque command errors rather than version warnings. Run the
436
- wrong one here and every command opens with a notice saying so. If \`bitmagic.json\` ever disagrees
437
- with this paragraph, the file is right. The engine is a separate command: \`bitmagic upgrade\`.`;
434
+ **Never ask which line to install, never offer the choice, and never update with \`npm i -g @bitmagic/cli\`** —
435
+ \`self-update\` reinstalls into the exact place this CLI lives, using the node running it, which the \`npm\` on
436
+ your PATH may not be; under nvm it usually is not, and the install lands in another prefix while
437
+ \`bitmagic --version\` never moves. The lines are not interchangeable (\`dev\` and \`local\` take the prerelease
438
+ built against the dev api-server, \`prod\` the release), and the wrong one fails as opaque command errors
439
+ rather than version warnings so run \`self-update\` before debugging a command that started failing
440
+ strangely. If \`bitmagic.json\` ever disagrees with this paragraph, the file is right. The engine is a
441
+ separate command: \`bitmagic upgrade\`.`;
438
442
  }
439
443
  export function renderAgentsMd(environment) {
440
444
  return `# Working on this Bitmagic game