Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion packages/cli/test/build-json-failure-conversions.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import { mkdtempSync, rmSync, writeFileSync, mkdirSync, readFileSync } from 'nod
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -407,7 +408,14 @@ function payloadLiterals(src: string): string[] {
}

describe('#12125 — the contract is exhaustive over `compile.ts`, not just over the exits pinned above', () => {
const SRC = readFileSync(COMPILE_TS, 'utf8');
// Comments are masked before a single thing is read off this file. A raw
// read cannot tell CODE from PROSE, and this package has been bitten in both
// directions: a docblock quoting a shape has satisfied a pin with no code
// behind it, and a docblock quoting one 281 lines above the code has broken a
// pin whose code never moved. `maskComments` BLANKS comment spans in place —
// spaces for text, newlines kept — so every byte offset, every line number and
// every brace-matching walk below reads exactly as it did on raw text (#18520).
const SRC = maskComments(readFileSync(COMPILE_TS, 'utf8'));

it('the extractor produces a POSITIVE before its negative is trusted', () => {
const SYNTHETIC = [
Expand Down
10 changes: 9 additions & 1 deletion packages/cli/test/build-json-failure-warnings.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import { mkdtempSync, rmSync, writeFileSync, mkdirSync, readFileSync } from 'nod
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -482,7 +483,14 @@ function payloadLiterals(src: string): string[] {
}

describe('#11772 — the contract is exhaustive over `compile.ts`, not just over the exits pinned above', () => {
const SRC = readFileSync(COMPILE_TS, 'utf8');
// Comments are masked before a single thing is read off this file. A raw
// read cannot tell CODE from PROSE, and this package has been bitten in both
// directions: a docblock quoting a shape has satisfied a pin with no code
// behind it, and a docblock quoting one 281 lines above the code has broken a
// pin whose code never moved. `maskComments` BLANKS comment spans in place —
// spaces for text, newlines kept — so every byte offset, every line number and
// every brace-matching walk below reads exactly as it did on raw text (#18520).
const SRC = maskComments(readFileSync(COMPILE_TS, 'utf8'));

it('the extractor produces a POSITIVE before its negative is trusted', () => {
// ⭐ A "no payload lacks `warnings`" pass is worthless from an instrument
Expand Down
73 changes: 65 additions & 8 deletions packages/cli/test/cloud-login-json-ndjson.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import { mkdtempSync, rmSync, readFileSync, existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -440,25 +441,81 @@ describe('os cloud login --json — the declared NDJSON stream (#6730)', () => {
});
});

/**
* The `{ … }` body of a declaration, brace-matched from its own `(`, as a span
* in the MASKED source — so a `{` inside a comment cannot close it early and
* the offsets are still the file's own line numbers.
*/
function bodySpan(src: string, declaration: RegExp): { start: number; end: number } | null {
const m = declaration.exec(src);
if (!m) return null;
let i = src.indexOf('(', m.index);
let depth = 0;
for (; i < src.length; i++) {
if (src[i] === '(') depth++;
else if (src[i] === ')') {
depth--;
if (depth === 0) break;
}
}
const open = src.indexOf('{', i);
if (open === -1) return null;
depth = 0;
for (let j = open; j < src.length; j++) {
if (src[j] === '{') depth++;
else if (src[j] === '}') {
depth--;
if (depth === 0) return { start: open, end: j };
}
}
return null;
}

describe('the exception stays declared, not just implemented (#6730 ruling)', () => {
const cloudLoginSrc = () => readFileSync(CLOUD_LOGIN_SRC, 'utf-8');
// Masked before anything is read: every case in this describe decides from
// the TEXT of `cloud/login.ts`, and a docblock that quotes `emitJson(` — the natural
// way to explain why one emitter exists — is indistinguishable from a call to
// it in a raw read (#18520).
const cloudLoginSrc = () => maskComments(readFileSync(CLOUD_LOGIN_SRC, 'utf-8'));

it('routes every --json write through the single compact emitter', () => {
// The contract is "one document per line" for the WHOLE command, so a new
// write that called `emitJson` directly could reintroduce a multi-line
// record on a path the e2e above does not drive. One emitter is what makes
// that structurally impossible; this is the guard on the emitter.
const src = cloudLoginSrc();
const direct = src
.split('\n')
.map((line, i) => ({ line, n: i + 1 }))
.filter(({ line }) => /\bemitJson\s*\(/.test(line))
.filter(({ line }) => !/^\s*await emitJson\(payload, exitCode, \{ compact: true \}\);$/.test(line));

// ⛔ This used to subtract ONE BYTE-EXACT LINE — `await emitJson(payload,
// exitCode, { compact: true });` — from the `emitJson(` line hits, and call
// anything left an offender. That binds the argument LIST, and binding an
// argument list is the defect this file's own tier cannot survive: a pull
// request that adds a parameter, renames `payload`, or simply wraps the call
// over two lines moves the spelling, the per-PR run never collects this file
// to say so, and the red arrives on `main` days later under whatever card
// happens to be open. Bind the PROPERTY the ruling actually made instead —
// ONE emitter — by partitioning the call sites against the emitter's own
// brace-matched body: outside must be empty, inside must not be, so neither
// half can pass by finding nothing (#18520).
const emitter = bodySpan(src, /async function emitRecord\s*\(/);
expect(emitter, '`cloud/login.ts` no longer declares the single `emitRecord` emitter').not.toBeNull();

const sites = [...src.matchAll(/\bemitJson\s*\(/g)];
const lineOf = (at: number): number => src.slice(0, at).split('\n').length;
const outside = sites
.filter((m) => m.index < emitter!.start || m.index > emitter!.end)
.map((m) => {
const eol = src.indexOf('\n', m.index);
return `${lineOf(m.index)}: ${src.slice(m.index, eol === -1 ? undefined : eol).trim()}`;
});

expect(
direct.map(({ n, line }) => `${n}: ${line.trim()}`),
outside,
'every --json write in cloud/login.ts must go through emitRecord()',
).toEqual([]);
expect(/async function emitRecord\(/.test(src)).toBe(true);
expect(
sites.length - outside.length,
'the emitter itself no longer calls `emitJson`, so the partition above is vacuous',
).toBeGreaterThanOrEqual(1);
});

it('declares NDJSON in the --json flag help text', () => {
Expand Down
12 changes: 10 additions & 2 deletions packages/cli/test/diff-usage-error-stream.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import { mkdtempSync, rmSync, existsSync, readFileSync, readdirSync, statSync }
import { tmpdir } from 'node:os';
import { join, resolve, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -227,10 +228,17 @@ describe('no new command has grown a stdout write above its --json guard', () =>
const WRITES_TO_STDOUT =
/\b(?:console\.log|printHeader|printStep|printInfo|printSuccess|printWarning|printError)\(/;

// ⛔ Every read below is MASKED. This scan is the exact shape that has already
// reported a change that never happened: it decides by LINE POSITION — `run()`
// above the first `flags.json` read — and a raw read cannot tell a docblock
// quoting `printSuccess(` from a call to it. A comment is enough to invent an
// offender here, and enough to hide one by pushing the guard's line above a
// write's. `maskComments` blanks spans in place, so the indices stay the
// file's own (#18520).
function offenders(): string[] {
const found: string[] = [];
for (const abs of commandFiles(COMMANDS_DIR)) {
const lines = readFileSync(abs, 'utf-8').split('\n');
const lines = maskComments(readFileSync(abs, 'utf-8')).split('\n');
if (!lines.some((l) => /\bjson:\s*Flags\.boolean\(/.test(l))) continue;
const runIdx = lines.findIndex((l) => /async run\s*\(/.test(l));
if (runIdx < 0) continue;
Expand All @@ -250,7 +258,7 @@ describe('no new command has grown a stdout write above its --json guard', () =>
// moved or renamed the commands directory would otherwise report "no
// offenders" from an empty sweep.
const withJson = commandFiles(COMMANDS_DIR).filter((abs) =>
/\bjson:\s*Flags\.boolean\(/.test(readFileSync(abs, 'utf-8')),
/\bjson:\s*Flags\.boolean\(/.test(maskComments(readFileSync(abs, 'utf-8'))),
);
expect(withJson.length).toBeGreaterThan(10);
});
Expand Down
9 changes: 8 additions & 1 deletion packages/cli/test/helpers/config-miss-family.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import { readFileSync, readdirSync, statSync } from 'node:fs';
import { join, resolve, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../../scripts/js-comment-mask.mjs';

const HERE = resolve(fileURLToPath(import.meta.url), '..');

Expand Down Expand Up @@ -135,7 +136,13 @@ function commandId(abs: string): string {
*/
export function discoverConfigMissFamily(): string[] {
const files = commandFiles(COMMANDS_DIR);
const sources = new Map(files.map((abs) => [abs, readFileSync(abs, 'utf-8')]));
// Masked. Both halves below are regexes over command SOURCE, and both are
// satisfiable by prose: a docblock naming `json: Flags.boolean(` beside an
// import of `utils/config.js` invents a direct member, and a commented-out
// `export default class X extends Y` invents an alias. The discovery feeds a
// `toEqual` in two nightly-tier files, where a phantom member is a red no
// pull request can be shown (#18520).
const sources = new Map(files.map((abs) => [abs, maskComments(readFileSync(abs, 'utf-8'))]));

const direct = new Set<string>();
for (const [abs, src] of sources) {
Expand Down
24 changes: 22 additions & 2 deletions packages/cli/test/json-stdout-purity.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { mkdtempSync, rmSync, writeFileSync, readFileSync, readdirSync, statSync
import { tmpdir } from 'node:os';
import { join, resolve, relative, sep } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';
import { CONFIG_MISS_FAMILY, discoverConfigMissFamily } from './helpers/config-miss-family.js';

Expand Down Expand Up @@ -137,7 +138,12 @@ function commandFiles(dir: string): string[] {
function discoverFamily(): string[] {
const ids: string[] = [];
for (const abs of commandFiles(COMMANDS_DIR)) {
const src = readFileSync(abs, 'utf-8');
// Masked: both halves are text probes, and both are satisfiable by prose. A
// command whose only `bootSchemaStack(` is inside a docblock explaining that
// it does NOT boot one would join this family and be driven against boot
// diagnostics it never writes — a red in a tier no pull request collects,
// wearing this file's title rather than the docblock's (#18520).
const src = maskComments(readFileSync(abs, 'utf-8'));
if (!src.includes('bootSchemaStack(')) continue;
if (!/\bjson:\s*Flags\.boolean\(/.test(src)) continue;
const rel = relative(COMMANDS_DIR, abs).replace(/\.ts$/, '');
Expand Down Expand Up @@ -233,7 +239,21 @@ describe('the family this contract has to hold across', () => {
// assertion goes red.
const preBoot = discoverConfigMissFamily();
expect(preBoot).toEqual(Object.keys(CONFIG_MISS_FAMILY).sort());
expect(preBoot).toHaveLength(10);

// ⛔ Not `toHaveLength(10)`. The line above already binds the SET, against a
// map a sibling nightly file drives member by member — that equality IS the
// contract, and a new member reddening it until it is driven is the point.
// The integer bound nothing that equality did not, and it bound it in a
// SECOND place that has to be hand-edited: two frozen numbers over one fact,
// in a tier where the author who moves the fact is never shown the failure.
// What it was load-bearing for is the vacuum the pair shares — a discovery
// that stops matching returns `[]`, and an emptied map would agree with it —
// so it stays as a FLOOR. Ten is the population the pre-boot family was
// measured over, not a count of today (#18520).
expect(
preBoot.length,
'the pre-boot `--json` discovery reports fewer faces than the family was measured over',
).toBeGreaterThanOrEqual(10);

// The two families are NOT disjoint, and measuring that was worth more
// than assuming it: `os migrate meta` is in both, legitimately and by
Expand Down
73 changes: 65 additions & 8 deletions packages/cli/test/login-json-ndjson.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import { mkdtempSync, rmSync, readFileSync, existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -388,25 +389,81 @@ describe('os login --json — the declared NDJSON stream (#6531)', () => {
});
});

/**
* The `{ … }` body of a declaration, brace-matched from its own `(`, as a span
* in the MASKED source — so a `{` inside a comment cannot close it early and
* the offsets are still the file's own line numbers.
*/
function bodySpan(src: string, declaration: RegExp): { start: number; end: number } | null {
const m = declaration.exec(src);
if (!m) return null;
let i = src.indexOf('(', m.index);
let depth = 0;
for (; i < src.length; i++) {
if (src[i] === '(') depth++;
else if (src[i] === ')') {
depth--;
if (depth === 0) break;
}
}
const open = src.indexOf('{', i);
if (open === -1) return null;
depth = 0;
for (let j = open; j < src.length; j++) {
if (src[j] === '{') depth++;
else if (src[j] === '}') {
depth--;
if (depth === 0) return { start: open, end: j };
}
}
return null;
}

describe('the exception stays declared, not just implemented (#6531 ruling)', () => {
const loginSrc = () => readFileSync(LOGIN_SRC, 'utf-8');
// Masked before anything is read: every case in this describe decides from
// the TEXT of `login.ts`, and a docblock that quotes `emitJson(` — the natural
// way to explain why one emitter exists — is indistinguishable from a call to
// it in a raw read (#18520).
const loginSrc = () => maskComments(readFileSync(LOGIN_SRC, 'utf-8'));

it('routes every --json write through the single compact emitter', () => {
// The contract is "one document per line" for the WHOLE command, so a new
// write that called `emitJson` directly could reintroduce a multi-line
// record on a path the e2e above does not drive. One emitter is what makes
// that structurally impossible; this is the guard on the emitter.
const src = loginSrc();
const direct = src
.split('\n')
.map((line, i) => ({ line, n: i + 1 }))
.filter(({ line }) => /\bemitJson\s*\(/.test(line))
.filter(({ line }) => !/^\s*await emitJson\(payload, exitCode, \{ compact: true \}\);$/.test(line));

// ⛔ This used to subtract ONE BYTE-EXACT LINE — `await emitJson(payload,
// exitCode, { compact: true });` — from the `emitJson(` line hits, and call
// anything left an offender. That binds the argument LIST, and binding an
// argument list is the defect this file's own tier cannot survive: a pull
// request that adds a parameter, renames `payload`, or simply wraps the call
// over two lines moves the spelling, the per-PR run never collects this file
// to say so, and the red arrives on `main` days later under whatever card
// happens to be open. Bind the PROPERTY the ruling actually made instead —
// ONE emitter — by partitioning the call sites against the emitter's own
// brace-matched body: outside must be empty, inside must not be, so neither
// half can pass by finding nothing (#18520).
const emitter = bodySpan(src, /async function emitRecord\s*\(/);
expect(emitter, '`login.ts` no longer declares the single `emitRecord` emitter').not.toBeNull();

const sites = [...src.matchAll(/\bemitJson\s*\(/g)];
const lineOf = (at: number): number => src.slice(0, at).split('\n').length;
const outside = sites
.filter((m) => m.index < emitter!.start || m.index > emitter!.end)
.map((m) => {
const eol = src.indexOf('\n', m.index);
return `${lineOf(m.index)}: ${src.slice(m.index, eol === -1 ? undefined : eol).trim()}`;
});

expect(
direct.map(({ n, line }) => `${n}: ${line.trim()}`),
outside,
'every --json write in login.ts must go through emitRecord()',
).toEqual([]);
expect(/async function emitRecord\(/.test(src)).toBe(true);
expect(
sites.length - outside.length,
'the emitter itself no longer calls `emitJson`, so the partition above is vacuous',
).toBeGreaterThanOrEqual(1);
});

it('declares NDJSON in the --json flag help text', () => {
Expand Down
8 changes: 7 additions & 1 deletion packages/cli/test/login-json-noninteractive.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ import { mkdtempSync, rmSync, readFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { maskComments } from '../../../scripts/js-comment-mask.mjs';
import { childEnv } from './helpers/serve-process.js';

const HERE = resolve(fileURLToPath(import.meta.url), '..');
Expand Down Expand Up @@ -316,7 +317,12 @@ describe('the paths that must keep working (#6728 did not narrow them)', () => {
});

describe('the refusal stays structural, not one call site (#6728)', () => {
const loginSrc = () => readFileSync(LOGIN_SRC, 'utf-8');
// Masked: both cases below decide from the TEXT of `login.ts`. A docblock
// that quotes `rl.question(` without the abort signal — which is exactly what
// a comment explaining `askOrFailAtEof` would carry — reads as a live
// unsettleable prompt, and the flag-help extractor's non-greedy `})` stops at
// a `})` inside a comment. Neither failure is about the product (#18520).
const loginSrc = () => maskComments(readFileSync(LOGIN_SRC, 'utf-8'));

it('asks no question that can outlive its input', () => {
// `rl.question(...)` without the abort signal is the unsettleable form —
Expand Down
Loading
Loading