Skip to content

Commit 164dfad

Browse files
committed
fix(pm): resolve a FILE-LOCAL declaring factory through its own definition
T1 read a property's value with a NAMED list of shared, exported helpers (`SCHEMA_PROPERTY_FORMS`, #18560) and stayed blind to a factory declared inside the one file that uses it: `memberTellKind` answered `null`, the row neither fired nor spent the #16943 budget, and nothing in the output said a thing. The repair is structural, never name-shaped: when a key line's value opens with an identifier call the shared list has no row for, the factory's own definition is resolved out of the judged file's HEAD BLOB (`index <old>..<new>` on the local path, `sha` on an API row; `git cat-file blob`, falling back to the working tree only after `git hash-object` proves it IS that blob) and classified by what its body returns at the body's own top level. Two boundaries, both a STATED silence the reader now prints with the file:line, the factory and the reason: an imported factory (imports are not chased) and a body this reader cannot classify. Claude-Session: https://claude.ai/code/session_01Gqi43smmqjJ5sUrhfoPeKu Co-authored-by: Claude <noreply@anthropic.com>
1 parent 36b2d38 commit 164dfad

1 file changed

Lines changed: 242 additions & 0 deletions

File tree

‎scripts/pm/check-widening-tells.mjs‎

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,6 +1115,7 @@ const SELF_TEST_BATTERIES = Object.freeze({
11151115
'#17217 — the CLI can be told which board it judges': 22,
11161116
'#18560 — the declaring vocabulary is a NAMED list, every form pinned by a counterfactual fixture': 30,
11171117
'#18640 — an inline closed set RE-SPELLED at the same binding is not a set that gained a value': 20,
1118+
'#18702 — a declaring factory PRIVATE to one file, resolved through its own DEFINITION': 50,
11181119
});
11191120

11201121
// DELETING an entry silences that battery's floor exactly as effectively as
@@ -4895,6 +4896,246 @@ export function selfTest() {
48954896
t('⛔ a removal in a DIFFERENT change block buys nothing — the block is the unit, as it is for #16943 and #17618', respellsExistingClosedSetBinding("const C = z.enum(['a']);", []) === false);
48964897
t('⛔ CONTROL — the identical specimen with `Clause-②: yes` is not refused either way: this file never blocks the honest declaration', wideningRefusal({ declaration: 'yes', files: [ARM_ADDED_BESIDE_OPTIONS] }).state !== 'refused');
48974898

4899+
4900+
// -- #18702 ----------------------------------------------------------------
4901+
//
4902+
// The counterfactual pin, in #18560's shape and for the same reason: the unit
4903+
// is the FACTORY, and a frozen fixture roster is asserted EQUAL to the set of
4904+
// factories the filing card names, so a factory dropped from the roster reds
4905+
// here rather than going quiet.
4906+
//
4907+
// ⭐ Each fixture carries that factory's REAL definition from the tip —
4908+
// signature verbatim, return expression verbatim at its opener, prose
4909+
// truncated — and its `returns` field is asserted to be text the definition
4910+
// actually contains, so a fixture cannot drift into describing a definition
4911+
// it does not carry. ⛔ The fixtures are NOT read off the tree: a generated
4912+
// fixture makes every future factory pass by construction, which is the shape
4913+
// this card exists because of.
4914+
battery('#18702 — a declaring factory PRIVATE to one file, resolved through its own DEFINITION');
4915+
const DRIVER_COMMON = 'packages/spec/src/data/driver/common.zod.ts';
4916+
const BLUEPRINT = 'packages/spec/src/ai/solution-blueprint.zod.ts';
4917+
const COMPONENT = 'packages/spec/src/ui/component.zod.ts';
4918+
const DATASOURCE = 'packages/spec/src/data/datasource.zod.ts';
4919+
const FILTER_RULE_ARRAY = 'packages/spec/src/ui/filter-rule-array.ts';
4920+
const MEMORY_DRIVER = 'packages/spec/src/data/driver/memory.zod.ts';
4921+
// The eight the card names, and nothing else — the roster this battery is
4922+
// held equal to.
4923+
const CARD_FACTORIES = Object.freeze([
4924+
'placeholderFree', 'strictIdent', 'strictIdentOrNull', 'emptyProps',
4925+
'objectBlockHistory', 'belongsInConfig', 'INLINE_CREDENTIAL_REFUSED', 'ruleArrayFilterError',
4926+
]);
4927+
const FACTORY_FIXTURES = Object.freeze({
4928+
placeholderFree: {
4929+
where: DRIVER_COMMON,
4930+
measured: '23 key lines at objectstack 30bac2880, 0 of them file-local',
4931+
arm: 'writable',
4932+
returns: 'return schema.superRefine((value, ctx) => {',
4933+
definition:
4934+
'export function placeholderFree<S extends z.ZodString>(schema: S, key: string) {\n'
4935+
+ ' return schema.superRefine((value, ctx) => {\n'
4936+
+ " if (typeof value !== 'string') return;\n"
4937+
+ ' });\n}\n',
4938+
line: "+ snapshotPath: placeholderFree(z.string(), 'persistence.snapshotPath').optional(),",
4939+
},
4940+
strictIdent: {
4941+
where: BLUEPRINT,
4942+
measured: '12 key lines at objectstack 30bac2880, all 12 file-local',
4943+
arm: 'writable',
4944+
returns: 'z.string().regex(SNAKE_CASE).describe(description)',
4945+
definition: 'const strictIdent = (description: string) => z.string().regex(SNAKE_CASE).describe(description);\n',
4946+
line: "+ snapshotObject: strictIdent('Object whose snapshot is taken (snake_case)'),",
4947+
},
4948+
strictIdentOrNull: {
4949+
where: BLUEPRINT,
4950+
measured: '8 key lines at objectstack 30bac2880, all 8 file-local',
4951+
arm: 'writable',
4952+
returns: 'z.string().regex(SNAKE_CASE).nullable().describe(description)',
4953+
definition:
4954+
'const strictIdentOrNull = (description: string) =>\n'
4955+
+ ' z.string().regex(SNAKE_CASE).nullable().describe(description);\n',
4956+
line: "+ snapshotField: strictIdentOrNull('Numeric field to snapshot, or null'),",
4957+
},
4958+
emptyProps: {
4959+
where: COMPONENT,
4960+
measured: '9 key lines at objectstack 30bac2880, all 9 file-local',
4961+
arm: 'writable',
4962+
returns: 'strictObject(',
4963+
definition:
4964+
'const emptyProps = (type: string) =>\n'
4965+
+ ' strictObject(\n'
4966+
+ ' {\n'
4967+
+ ' guidanceSets: COMPONENT_LEVEL_GUIDANCE,\n'
4968+
+ ' },\n'
4969+
+ ' {},\n'
4970+
+ ' );\n',
4971+
line: "+ 'nav:launcher': emptyProps('nav:launcher'),",
4972+
},
4973+
objectBlockHistory: {
4974+
where: COMPONENT,
4975+
measured: '9 key lines at objectstack 30bac2880, all 9 file-local',
4976+
arm: null,
4977+
returns: '`Until this type was added to ComponentPropsMap',
4978+
definition:
4979+
'const objectBlockHistory = (type: string) =>\n'
4980+
+ ' `Until this type was added to ComponentPropsMap, it had no entry there at all, so `\n'
4981+
+ " + 'the authoring gate skipped it.';\n",
4982+
line: "+ history: objectBlockHistory('object-grid'),",
4983+
},
4984+
belongsInConfig: {
4985+
where: DATASOURCE,
4986+
measured: '8 key lines at objectstack 30bac2880, all 8 file-local',
4987+
arm: null,
4988+
returns: '`is a driver connection detail',
4989+
definition:
4990+
'const belongsInConfig = (key: string, canonical: string = key) =>\n'
4991+
+ ' `is a driver connection detail — it belongs inside config, not at the top level.`;\n',
4992+
line: "+ host: belongsInConfig('host'),",
4993+
},
4994+
INLINE_CREDENTIAL_REFUSED: {
4995+
where: DRIVER_COMMON,
4996+
measured: '10 key lines at objectstack 30bac2880, 0 of them file-local',
4997+
arm: null,
4998+
returns: '`is a credential and is not accepted inline',
4999+
definition:
5000+
'export const INLINE_CREDENTIAL_REFUSED = (key: string): string =>\n'
5001+
+ ' `is a credential and is not accepted inline in driver config: the `\n'
5002+
+ " + 'datasource is persisted whole into sys_metadata.';\n",
5003+
line: "+ passwd: INLINE_CREDENTIAL_REFUSED('passwd'),",
5004+
},
5005+
ruleArrayFilterError: {
5006+
where: FILTER_RULE_ARRAY,
5007+
measured: '11 key lines at objectstack 30bac2880, 0 of them file-local',
5008+
arm: null,
5009+
returns: 'return (issue) => {',
5010+
definition:
5011+
'export function ruleArrayFilterError(options: RuleArrayFilterErrorOptions): z.core.$ZodErrorMap {\n'
5012+
+ ' const { surface, migration } = options;\n\n'
5013+
+ ' return (issue) => {\n'
5014+
+ " if (issue.code !== 'invalid_type') return undefined;\n"
5015+
+ ' };\n}\n',
5016+
line: '+ error: ruleArrayFilterError({',
5017+
},
5018+
});
5019+
const rosterMissing = CARD_FACTORIES.filter((n) => FACTORY_FIXTURES[n] === undefined);
5020+
const rosterOrphan = Object.keys(FACTORY_FIXTURES).filter((n) => !CARD_FACTORIES.includes(n));
5021+
t(
5022+
`⭐ every factory the card names has a fixture — a new one with no fixture reds HERE${rosterMissing.length ? ` (missing: ${rosterMissing.join(', ')})` : ''}`,
5023+
rosterMissing.length === 0,
5024+
);
5025+
t(
5026+
`⭐ …and every fixture names a factory still on that roster — one silently dropped reds HERE${rosterOrphan.length ? ` (orphaned: ${rosterOrphan.join(', ')})` : ''}`,
5027+
rosterOrphan.length === 0,
5028+
);
5029+
t(
5030+
'⛔ …and every fixture QUOTES a return its own definition really carries — a fixture describing a definition it does not hold pins nothing',
5031+
Object.values(FACTORY_FIXTURES).every((fx) => fx.definition.includes(fx.returns.replace(/^return /, ''))),
5032+
);
5033+
t('…each carrying its measurement WITH the tree it was taken against — a count with no tree is not a reading', Object.values(FACTORY_FIXTURES).every((fx) => /\bobjectstack [0-9a-f]{7,}/.test(fx.measured)));
5034+
5035+
const localRun = (where, line, source, opts = {}) => {
5036+
const unresolved = [];
5037+
const file = { filename: where, status: 'modified', patch: patchOf(30, line) };
5038+
const rows = tellsInFile(file, {
5039+
repo: opts.repo ?? THIS_REPO,
5040+
readSource: opts.blind === true ? () => null : () => source,
5041+
unresolved,
5042+
});
5043+
return { rows, unresolved, file };
5044+
};
5045+
5046+
// RESOLUTION is the first half, asserted for every fixture against its own
5047+
// arm — a writable factory, and one whose body mints prose or an error map
5048+
// rather than a schema. ⛔ `null` is a THIRD state and never rounded to
5049+
// either: it is what a name-shaped heuristic would have guessed at.
5050+
for (const name of CARD_FACTORIES) {
5051+
const fx = FACTORY_FIXTURES[name];
5052+
const read = resolveDeclaringFactory(fx.definition, name);
5053+
t(
5054+
fx.arm === 'writable'
5055+
? `⭐ \`${name}(\` returns \`${fx.returns}\` ⇒ a WRITABLE key`
5056+
: `⭐ \`${name}(\` returns \`${fx.returns}\` ⇒ NOT a schema this reader classifies — a named silence, never a guess`,
5057+
read.verdict === fx.arm,
5058+
`verdict ${JSON.stringify(read.verdict)} — ${read.reason}`,
5059+
);
5060+
}
5061+
// The VERDICT is the second half, each fixture against its own arm.
5062+
for (const name of CARD_FACTORIES) {
5063+
const fx = FACTORY_FIXTURES[name];
5064+
const { rows, unresolved } = localRun(fx.where, fx.line, fx.definition);
5065+
if (fx.arm === 'writable') {
5066+
t(
5067+
`⭐ \`${name}(\` declares a WRITABLE key, so a \`Clause-②: no\` diff carrying it FIRES — with its own file:line`,
5068+
rows.length === 1 && rows[0]?.tell === 'T1' && rows[0]?.line === 30 && unresolved.length === 0,
5069+
);
5070+
} else {
5071+
t(
5072+
`⭐ \`${name}(\` is unclassifiable, so nothing fires — and the line is REPORTED by name rather than swallowed`,
5073+
rows.length === 0 && unresolved.length === 1 && unresolved[0]?.name === name && unresolved[0]?.line === 30,
5074+
);
5075+
}
5076+
}
5077+
5078+
// -- the REFUSING arm, read off a definition rather than off a name --------
5079+
const REFUSAL_DEFINITION =
5080+
'export function refusedInlineCredentialKey(key: string, formTitle: string) {\n'
5081+
+ ' return z.never({ error: () => INLINE_CREDENTIAL_REFUSED(key) }).optional()\n'
5082+
+ " .describe('Set through the connection form secret field');\n}\n";
5083+
const REFUSAL_LINE = "+ password: refusedInlineCredentialKey('password', 'Password'),";
5084+
t('⭐ a file-local factory whose body returns `z.never(…)` declares the key UNWRITABLE — the same primitive `retiredKey(` carries, read off the DEFINITION', resolveDeclaringFactory(REFUSAL_DEFINITION, 'refusedInlineCredentialKey').verdict === 'refusing');
5085+
t('…so it is RECOGNISED and DECLINES — a stated silence, and NOT an unresolved line either', localRun(DRIVER_COMMON, REFUSAL_LINE, REFUSAL_DEFINITION).rows.length === 0 && localRun(DRIVER_COMMON, REFUSAL_LINE, REFUSAL_DEFINITION).unresolved.length === 0);
5086+
t('⛔ …and a live arm CHAINED onto it leaves the key writable, so it FIRES — the decline is bound to the line\'s own evidence, never to the factory', localRun(DRIVER_COMMON, `${REFUSAL_LINE.replace(/,$/, '')}.or(z.string()),`, REFUSAL_DEFINITION).rows[0]?.tell === 'T1');
5087+
5088+
// -- THE COUNTERFACTUAL ----------------------------------------------------
5089+
//
5090+
// ⭐ The card's own probe LINE, on the file where its factory is DECLARED. It
5091+
// is silent before and fires after, and the "before" is taken by disabling the
5092+
// resolver — ⛔ never by editing the fixture, which would prove nothing about
5093+
// the reading.
5094+
const PROBE = FACTORY_FIXTURES.placeholderFree;
5095+
t('⭐ THE FINDING: a new key added through a file-local declaring factory FIRES — the row that was silent at 6dfa3ea77', localRun(PROBE.where, PROBE.line, PROBE.definition).rows[0]?.tell === 'T1');
5096+
t('…at the line the author can open', localRun(PROBE.where, PROBE.line, PROBE.definition).rows[0]?.line === 30);
5097+
t('⭐ CONTROL — the SAME fixture with the resolver blind is silent, which is the state this card measured', localRun(PROBE.where, PROBE.line, PROBE.definition, { blind: true }).rows.length === 0);
5098+
t('…and the whole verdict is a REFUSAL, not a clean reading', wideningRefusal({ declaration: 'no', files: [localRun(PROBE.where, PROBE.line, PROBE.definition).file], readSource: () => PROBE.definition }).state === 'refused');
5099+
t('⛔ CONTROL — the identical diff with `Clause-②: yes` is not refused: this file never blocks the honest declaration', wideningRefusal({ declaration: 'yes', files: [localRun(PROBE.where, PROBE.line, PROBE.definition).file], readSource: () => PROBE.definition }).state !== 'refused');
5100+
t('⛔ CONTROL — the same widening judged on the objectui board is not judged at all, so the board resolution still decides it', wideningRefusal({ declaration: 'no', files: [localRun(PROBE.where, PROBE.line, PROBE.definition).file], repo: UI_BOARD, readSource: () => PROBE.definition }).state !== 'refused');
5101+
5102+
// -- BOUNDARY ONE: an IMPORTED factory ------------------------------------
5103+
//
5104+
// ⚠️ The card's LITERAL probe is one of these, measured rather than argued:
5105+
// `placeholderFree` is declared in `common.zod.ts` and imported at all 23 of
5106+
// its key positions, `memory.zod.ts` included. It exits 0 still — but the
5107+
// line is now NAMED.
5108+
const importedRun = localRun(MEMORY_DRIVER, PROBE.line, "import { placeholderFree } from './common.zod';\n");
5109+
t('⛔ BOUNDARY ONE — a factory defined in ANOTHER file stays unrecognised: imports are not chased', importedRun.rows.length === 0);
5110+
t('⭐ …but the silence is STATED — the line is reported with its file:line, the factory and the reason', importedRun.unresolved.length === 1 && importedRun.unresolved[0]?.name === 'placeholderFree' && importedRun.unresolved[0]?.reason.includes('IMPORTED'));
5111+
t('…and the reader PRINTS it, so exit 0 is no longer evidence about that line', unresolvedLines(importedRun.unresolved).some((l) => l.includes(`${MEMORY_DRIVER}:30`)));
5112+
t('⛔ …while an empty list prints NOTHING — a heading with no rows would read as a finding', unresolvedLines([]).length === 0 && unresolvedLines(null).length === 0);
5113+
5114+
// -- BOUNDARY TWO: a body this reader cannot read -------------------------
5115+
t('⛔ BOUNDARY TWO — two definitions of one name in a file are AMBIGUOUS, never "the first one"', resolveDeclaringFactory('const dup = (a: string) => z.string();\nconst dup = (a: string) => z.never();\n', 'dup').verdict === null);
5116+
t('⛔ …a body with no `return` this reader can find stays unresolved', resolveDeclaringFactory('function opaque(a) {\n doSomething(a);\n}\n', 'opaque').verdict === null);
5117+
t('⭐ …and a `return` belonging to a NESTED callback is not read as the factory\'s own — the quiet direction, refused by brace depth', resolveDeclaringFactory('function live(schema) {\n const g = () => {\n return z.never();\n };\n return schema;\n}\n', 'live').verdict === 'writable');
5118+
t('⛔ …a factory named in a COMMENT is no definition — the declaration must follow the line\'s indentation and nothing else', resolveDeclaringFactory('// const ghost = (a: string) => z.string();\n * const ghost = (a: string) => z.string();\n', 'ghost').verdict === null);
5119+
5120+
// -- the head BLOB, which is what makes this reading legal after #17300 ----
5121+
t('the API row carries the head blob as `sha`', headBlobId({ filename: 'x.ts', sha: 'a'.repeat(40) }) === 'a'.repeat(40));
5122+
t('…and the local path carries the same fact in its `index <old>..<new>` line', headBlobId({ filename: 'x.ts', patch: 'index eb82214af9..34232a3ac5 100644\n@@ -1,0 +1,1 @@\n+x' }) === '34232a3ac5');
5123+
t('⛔ …an all-zero id is no blob — a deleted side names nothing to read', headBlobId({ filename: 'x.ts', patch: 'index eb82214af9..0000000 100644\n@@ -1,1 +1,0 @@\n-x' }) === null);
5124+
t('⭐ ⛔ …and a patch that names NEITHER answers null, which is why every other fixture in this file never touches an object store', headBlobId({ filename: 'x.ts', patch: patchOf(30, '+ a: z.string(),') }) === null);
5125+
t('⛔ …a path that climbs out of the tree is never read, whatever id it carries', headBlobSource({ filename: '../elsewhere/x.ts', sha: 'a'.repeat(40) }) === null);
5126+
5127+
// -- the direction: the resolver only ever ADDS ----------------------------
5128+
t('⭐ the shared vocabulary is the FAST PATH — a line `SCHEMA_PROPERTY` already reads is never re-judged here', keyValueFactoryName(' window: strictObject({ from: z.string() }),') === null && keyValueFactoryName(" legacy: retiredKey('gone'),") === null);
5129+
t('…and a line it does not read hands over its identifier', keyValueFactoryName(" snapshotObject: strictIdent('x'),") === 'strictIdent');
5130+
t('⛔ a line that fires WITHOUT the resolver still fires with it — the `no` criterion is untouched', localRun(BLUEPRINT, '+ cursor: z.string().optional(),', FACTORY_FIXTURES.strictIdent.definition).rows[0]?.tell === 'T1');
5131+
t('⭐ ⛔ the resolver is read on the ADDED side ONLY: a REMOVED local-factory key buys nothing, so a `z.` key added beside it STILL fires', tellsInFile({ filename: BLUEPRINT, status: 'modified', patch: "@@ -30,1 +30,1 @@\n- gone: strictIdent('x'),\n+ cursor: z.string().optional()," }, { readSource: () => FACTORY_FIXTURES.strictIdent.definition }).length === 1);
5132+
t('⚠️ …and the PRICE of that asymmetry, pinned rather than discovered: a block REPLACING one local-factory key with another fires on the added one', tellsInFile({ filename: BLUEPRINT, status: 'modified', patch: "@@ -30,1 +30,1 @@\n- gone: strictIdent('x'),\n+ fresh: strictIdent('y')," }, { readSource: () => FACTORY_FIXTURES.strictIdent.definition }).length === 1);
5133+
5134+
// -- the readings this round must NOT disturb ------------------------------
5135+
t('⛔ #17618 — a typed PARAMETER is still not a key, and the resolver never sees one: its value opens no CALL', keyValueFactoryName(' ctx: z.RefinementCtx,') === null && tellsInFile({ filename: BLUEPRINT, status: 'modified', patch: '@@ -30,0 +30,3 @@\n+export const refine = (\n+ ctx: z.RefinementCtx,\n+) => ctx;' }).length === 0);
5136+
t('⛔ …a COMMENT carrying a local-factory key line is still not a key line', localRun(BLUEPRINT, "+ // snapshotObject: strictIdent('x'),", FACTORY_FIXTURES.strictIdent.definition).rows.length === 0);
5137+
t('⛔ …and a file OFF the contract source surface reads no blob at all, whatever its lines say', localRun('README.md', FACTORY_FIXTURES.strictIdent.line, FACTORY_FIXTURES.strictIdent.definition).unresolved.length === 0);
5138+
48985139
// -- the floor -------------------------------------------------------------
48995140
const floorFailures = [];
49005141
const floorFailure = (text) => {
@@ -4949,6 +5190,7 @@ export function selfTest() {
49495190
"#17848's re-declared key with a zod `error` param — declined by #16943's budget, bracketed by the dark control that fires when nothing paid and the surplus control that fires on a real new key beside it, " +
49505191
"#18234's key narrowed out of a universal acceptor — certified by the REMOVED value's own semantics rather than by the added value's spelling, with the dark, different-key, never-universal, narrowing-step and surplus controls that still fire, " +
49515192
"#18640's inline closed set re-spelled at the same binding — bounded by the control set that IS the finding, the same edit spelled one member per line and at a keyed property, with the added-arm, different-binding, brand-new, widened-enum and new-key controls that still fire, " +
5193+
"#18702's FILE-LOCAL declaring factory, resolved through its own definition at the head BLOB and classified by what its body returns — every factory the filing card names pinned against its own arm, the refusal arm read off a `z.never` definition rather than a name with its chained-arm control, the counterfactual bracketed by the same fixture with the resolver blind, and both boundaries (an imported factory, an unclassifiable body) pinned as a STATED silence the reader prints, " +
49525194
"#16448's four positive controls each with its file:line, its negative controls — " +
49535195
'the same diffs with `yes`, and a removal-only diff with `no` — the local path composed end ' +
49545196
'to end so a binary change to a tell surface cannot read as clean, #17112\'s split count with ' +

0 commit comments

Comments
 (0)