// Build-time regression gate for the job-log line-concatenation bug. // // THE BUG // // pixl-json-stream 1.0.9 emitted the last complete line of each read chunk // WITHOUT a trailing newline: // // var text = record + ((idx < len - 1) ? self.EOL : ''); // // Cronicle's bin/shell-plugin.js appends whatever the 'text' event hands it, // verbatim, and relies on the library to supply the terminator: // // fs.appendFileSync(job.log_file, line); // // So whenever a chunk boundary landed mid-line, the preceding complete line // lost its newline and the next line was glued onto it. Output arriving over a // pipe -- e.g. a job running `docker exec ` -- splits mid-line // constantly, so in practice most of the log ran together: // // [2026/08/11 14:00:02] EDGAR company ticker map okinfo(...): provider ... // // 1.0.10 restored the unconditional `record + self.EOL`. // // WHY THIS FILE EXISTS // // This was not a build-time resolution accident that "npm ci" alone prevents. // Upstream's own package-lock.json pinned the broken version: // // Cronicle v0.9.74 -> pixl-json-stream 1.0.9 (broken) // Cronicle v0.9.126 -> pixl-json-stream 1.0.10 (fixed) // // A lockfile delivered the bug, so a lockfile can deliver it again. The failure // mode is silent: jobs still succeed, logs are just quietly unreadable. Running // this during `docker build` converts that into a hard build failure. const JSONStream = require('pixl-json-stream'); const { PassThrough } = require('stream'); const input = new PassThrough(); const stream = new JSONStream(input, new PassThrough()); let log = ''; stream.on('text', (line) => { log += line; }); // Chunk boundaries deliberately fall mid-line ("tw" + "o"), reproducing what a // real pipe does. A library that only terminates non-final records will drop // the newline after "one" and after "three". input.write('one\ntw'); input.write('o\nthree\nfou'); input.write('r\n'); // 'text' is emitted from the stream's 'data' handler, so let the event loop // drain before asserting. setTimeout(() => { const want = 'one\ntwo\nthree\nfour\n'; if (log !== want) { console.error('FAIL: pixl-json-stream is dropping line terminators.'); console.error(' got: ' + JSON.stringify(log)); console.error(' want: ' + JSON.stringify(want)); console.error(''); console.error('Cronicle job logs would silently concatenate lines.'); console.error('See the comment at the top of this file. Refusing to build.'); process.exit(1); } const version = require('pixl-json-stream/package.json').version; console.log('OK: job log line terminators intact (pixl-json-stream ' + version + ')'); }, 200);