Skip to content

Commit fcc821f

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-14918-type-check-coverage-sources-clause
2 parents 619395b + e8c7956 commit fcc821f

2 files changed

Lines changed: 86 additions & 5 deletions

File tree

packages/spec/CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6699,8 +6699,9 @@
66996699
and is refused after it. Metadata that parses today parses identically; the
67006700
only thing that changes is what the Studio object designer teaches an author to
67016701
write. The repeater now offers `label`, `value`, `color` and `description` —
6702-
exactly `SelectOptionSchema`'s authorable keys minus `visibleWhen`, which is a
6703-
CEL predicate rather than a repeater text input.
6702+
four of `SelectOptionSchema`'s six authorable keys. `default` and
6703+
`visibleWhen` are both unoffered; the latter because it is a CEL predicate
6704+
rather than a repeater text input, not because it is the only key withheld.
67046705

67056706
**Why remove rather than declare.** The route rests on a premise measured for
67066707
the FIELD-option surface rather than inherited from #5016, which measured the

scripts/measure-self-test-floor.mjs

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@
6565
* ACCIDENT exit != 0 AND it printed nothing -- a non-zero exit with no
6666
* refusal behind it. NOT counted among HELD, ever.
6767
*
68+
* A FOURTH reading sits UNDER all three, and it is a PRECONDITION rather than a
69+
* verdict: if the UNMUTATED file already exits non-zero, this tree cannot run
70+
* it at all, so the mutation had nothing to defeat and NOTHING WAS MEASURED.
71+
* That case does not look like an absence -- both runs exit non-zero and both
72+
* print a module-resolution stack, so the mutated run "speaks" and the verdict
73+
* above reads HELD. A checkout that has not been `pnpm install`ed therefore
74+
* reports the FLATTERING answer for every file it cannot load, and the same row
75+
* reads ACCIDENT once the tree is installed (#15391).
76+
*
6877
* The `mutatedBytes` / `mutatedHead` fields the row already carried are what this
6978
* reads; `mutatedSpoke` publishes the reading. Deliberately the verdict does NOT
7079
* match the refusal WORDING: the repair landed in three spellings and teaching
@@ -104,6 +113,9 @@ const DISPATCH = /(?:includes|has)\(\s*['"`]--self-test['"`]\s*\)/;
104113
/** Marker injected by the probe. Its presence on disk is the mutation's proof. */
105114
const PROBE_MARKER = 'OS_SELF_TEST_FLOOR_PROBE';
106115

116+
/** "Did this run SAY anything": its first non-blank line, or '' if it said nothing. */
117+
const firstNonBlankLine = (out) => out.split('\n').find((l) => l.trim()) ?? '';
118+
107119
// ---------------------------------------------------------------------------
108120
// Instrument 1 -- the static assertion-floor criterion
109121
// ---------------------------------------------------------------------------
@@ -212,6 +224,15 @@ export function injectEarlyReturn(src, name) {
212224
* resolution still answer the same, and the marker is re-read FROM DISK before
213225
* the run: an editor step that matched nothing exits 0 just as happily as one
214226
* that landed, and an unmutated file would report "held" for no reason at all.
227+
*
228+
* THE BASELINE IS A PRECONDITION, NOT A DATA POINT. It is read BEFORE any
229+
* reading of the mutated run, and a non-zero one ends the probe as NOT MEASURED
230+
* with the reason -- see the fourth reading in this file's header. The mutated
231+
* run is then not spawned AT ALL: in the shape that motivates this (a checkout
232+
* whose dependencies are absent) every row is baseline-red, so running each
233+
* doomed mutation would double a whole sweep of spawns to learn nothing. The
234+
* row still publishes what the baseline said, because `baselineHead` is usually
235+
* the whole diagnosis (`Cannot find package ...` reads as "run pnpm install").
215236
*/
216237
export function probeEarlyReturn(absFile, entry, { timeout = 120000 } = {}) {
217238
const src = readFileSync(absFile, 'utf8');
@@ -228,10 +249,28 @@ export function probeEarlyReturn(absFile, entry, { timeout = 120000 } = {}) {
228249
if (onDisk !== 1) return { verdict: 'NOT MEASURED', why: `mutation not on disk (marker x${onDisk})` };
229250

230251
const base = spawnSync(cmd, [absFile, '--self-test'], { cwd: ROOT, timeout, encoding: 'utf8' });
231-
const mut = spawnSync(cmd, [probePath, '--self-test'], { cwd: ROOT, timeout, encoding: 'utf8' });
232252
const baseOut = (base.stdout ?? '') + (base.stderr ?? '');
253+
if (base.signal) return { verdict: 'NOT MEASURED', why: `killed by ${base.signal}` };
254+
// PRECONDITION. A file the tree cannot run offered the mutation nothing to
255+
// defeat, so no verdict below is available -- however loudly the mutated run
256+
// would have exited and spoken. Read before the mutated run is spawned.
257+
if (base.status !== 0) {
258+
return {
259+
verdict: 'NOT MEASURED',
260+
why:
261+
base.status === null
262+
? `baseline run could not start (${base.error?.code ?? 'no exit status'})`
263+
: `baseline run failed (exit ${base.status})`,
264+
entry,
265+
baselineExit: base.status,
266+
baselineBytes: baseOut.length,
267+
baselineHead: firstNonBlankLine(baseOut),
268+
};
269+
}
270+
271+
const mut = spawnSync(cmd, [probePath, '--self-test'], { cwd: ROOT, timeout, encoding: 'utf8' });
233272
const mutOut = (mut.stdout ?? '') + (mut.stderr ?? '');
234-
if (mut.signal || base.signal) return { verdict: 'NOT MEASURED', why: `killed by ${mut.signal ?? base.signal}` };
273+
if (mut.signal) return { verdict: 'NOT MEASURED', why: `killed by ${mut.signal}` };
235274
// A mutation that changed nothing observable did not reach the executed
236275
// path, whatever its exit code says.
237276
if (baseOut === mutOut && base.status === mut.status) {
@@ -240,7 +279,7 @@ export function probeEarlyReturn(absFile, entry, { timeout = 120000 } = {}) {
240279
// Did the mutated run SAY anything? Read as "printed a non-blank line", the
241280
// same reading `mutatedHead` already publishes and quotes -- a run whose whole
242281
// output is a newline has non-zero bytes and still refused nothing.
243-
const mutatedHead = mutOut.split('\n').find((l) => l.trim()) ?? '';
282+
const mutatedHead = firstNonBlankLine(mutOut);
244283
const mutatedSpoke = mutatedHead !== '';
245284
return {
246285
// Exit code alone cannot tell a refusal from an accident -- see the header.
@@ -323,6 +362,34 @@ const ACCIDENT_GATE = [
323362
'',
324363
].join('\n');
325364

365+
/**
366+
* The measured BASELINE-RED shape, reduced: a file this tree cannot run at all,
367+
* because one of its imports does not resolve. Its self-test is otherwise
368+
* perfectly ordinary and injectable -- the point is that neither run ever
369+
* reaches it. Both runs die in module resolution, both exit non-zero, and both
370+
* PRINT a stack trace, so `mutatedSpoke` is true and an exit-code-and-speech
371+
* verdict scores it HELD: a hold awarded for the tree being broken. This is the
372+
* shape `scripts/audits/14744-before-update-per-row-value-census.mjs` takes in a
373+
* checkout whose `node_modules` lacks its `typescript` dependency, where it read
374+
* HELD while reading ACCIDENT in an installed one (#15391).
375+
*
376+
* The unresolvable import is a name no registry can supply, and it is the
377+
* FIRST statement, so the failure is the module loader's and cannot be confused
378+
* with anything the self-test did.
379+
*/
380+
const UNRUNNABLE_GATE = [
381+
'#!/usr/bin/env node',
382+
"import 'os-self-test-floor-control-no-such-package';",
383+
'function selfTest() {',
384+
' const failures = [];',
385+
" if (1 !== 1) failures.push('x');",
386+
" if (failures.length) { console.error('nope'); process.exit(1); }",
387+
" console.log('fixture self-test: 1 case passes');",
388+
'}',
389+
"if (process.argv.includes('--self-test')) selfTest();",
390+
'',
391+
].join('\n');
392+
326393
/**
327394
* The ternary exit, reduced: a roster floor whose ONLY failure production is
328395
* `process.exit(<cond> ? 0 : 1)`. It carries none of the NAMED spellings -- no
@@ -404,12 +471,15 @@ export function runControls() {
404471
const holed = join(dir, 'holed-gate.mjs');
405472
const sound = join(dir, 'sound-gate.mjs');
406473
const accident = join(dir, 'accident-gate.mjs');
474+
const unrunnable = join(dir, 'unrunnable-gate.mjs');
407475
writeFileSync(holed, HOLED_GATE);
408476
writeFileSync(sound, SOUND_GATE);
409477
writeFileSync(accident, ACCIDENT_GATE);
478+
writeFileSync(unrunnable, UNRUNNABLE_GATE);
410479
const h = probeEarlyReturn(holed, 'selfTest');
411480
const s = probeEarlyReturn(sound, 'selfTest');
412481
const a = probeEarlyReturn(accident, 'runSelfTest');
482+
const u = probeEarlyReturn(unrunnable, 'selfTest');
413483
say(h.verdict === 'DEFEATED',
414484
`POSITIVE CONTROL FAILED: the probe read a known-holed gate as ${h.verdict} (${h.why ?? ''})`);
415485
say(h.mutatedBytes === 0,
@@ -425,6 +495,16 @@ export function runControls() {
425495
`POSITIVE CONTROL FAILED: the probe read a silent non-zero exit as ${a.verdict} (${a.why ?? ''}) -- an exit code is not a handshake`);
426496
say(a.mutatedExit !== 0 && a.mutatedBytes === 0 && a.mutatedSpoke === false,
427497
`POSITIVE CONTROL FAILED: the accident fixture no longer produces the measured shape (exit ${a.mutatedExit}, ${a.mutatedBytes} byte(s)); the ACCIDENT verdict above would then be passing for the wrong reason`);
498+
// The precondition, in the direction that matters: a baseline that already
499+
// failed ends the probe, and it must end it as NOT MEASURED -- never as the
500+
// HELD an exit-code-and-speech reading would award it (#15391).
501+
say(u.verdict === 'NOT MEASURED' && /^baseline run failed \(exit /.test(u.why ?? ''),
502+
`POSITIVE CONTROL FAILED: a file whose BASELINE run already exits non-zero was read as ${u.verdict} (${u.why ?? ''}); the mutation had nothing to defeat, so nothing was measured`);
503+
// ... and for the RIGHT reason: this fixture has to be the flattering shape,
504+
// a red baseline that SPEAKS. A fixture that fell silent, or that stopped
505+
// being red, would satisfy the verdict above while testing nothing.
506+
say(u.baselineExit !== 0 && u.baselineBytes > 0 && u.baselineHead !== '',
507+
`POSITIVE CONTROL FAILED: the unrunnable fixture no longer produces the measured shape (baseline exit ${u.baselineExit}, ${u.baselineBytes} byte(s)); the NOT MEASURED verdict above would then be passing for the wrong reason`);
428508
} finally {
429509
rmSync(dir, { recursive: true, force: true });
430510
}

0 commit comments

Comments
 (0)