/* Pure-text source-scanning primitives shared by checks.commands.generate (werkstatt-site) and werkstatt.commands.validate (werkstatt-engine): masked scanning with template-depth tracking, definition anchors for both `: KernelCommandDefinition` and `… satisfies KernelCommandDefinition`, the suspect-file signal, and the forbidden invisible-codepoint gate (RFC-1304). Does not read the filesystem — every function operates on already-loaded source text; consumers own IO. Does not extract definition fields beyond anchors — the site generator keeps its own name/execute/contract extraction. Does not produce diagnostics — callers map scan results to their own rule ids (CMDGEN-04/05). The suspect-file signal is anchored to definition shape Masked source keeps braces outside strings/comments visible so literalEnd can pair them; template ${ } regions are masked opaque. NON_COMMAND_ALLOWLIST lives here so the generator RFC-1321: isStringLiteralSource — shared raw-text literal check for definition name fields (CMDGEN-06), consumed by checks.commands.generate and werkstatt.commands.validate. RFC-1304: initial implementation — maskSource lifted from checks/commands-generate.ts and extended with template-depth tracking; new findDefinitionAnchors (satisfies form), fileHasCommandSignal, scanForbiddenCodepoints; NON_COMMAND_ALLOWLIST moved here for consumer parity. RFC-1304 review r1: positional signal pairing (unpairedCommandSignals) — an anchor consumes the annotation/shaped signal at its index and the satisfies tail after its literal end, so hybrid `: T = {…} satisfies KCD` counts once while literal-less `factory() satisfies KCD` stays suspect; CMDGEN_IGNORE_RE is line-anchored and tested against the keepComments mask so pragma text inside string literals cannot suppress; definition-field probe requires field position (prev char `{`/`,`) so ternary branches do not shape a literal. RFC-1321: review-r2: stringLiteralValue — comment-aware literal extractor keys COMMAND_PROVENANCE cleanly (adjacent comments no longer corrupt the key or evade CMDGEN-03); (?!\d) boundary in commitCarriesGovernanceProvenance; non-string --id guard */ /** * Invisible/control codepoints forbidden in command sources (RFC-1304 CMDGEN-05): * Unicode category Cc minus the source whitelist (tab, LF, CR), category Cf * (format characters: soft hyphen, ZWSP/ZWNJ/ZWJ, bidi controls, tag chars, …), * plus the invisible Zs separators NBSP, FIGURE/THIN/HAIR SPACE, and NNBSP. * Printable non-ASCII (umlauts, Cyrillic, CJK, typographic punctuation) is not * covered — the gate is codepoint-class based, not ASCII-only. */ const FORBIDDEN_CODEPOINT_RANGES: readonly (readonly [number, number])[] = [ [0x0000, 0x0008], // C0 minus tab (0x09) [0x000b, 0x000c], // VT, FF — LF (0x0a) and CR (0x0d) stay whitelisted [0x000e, 0x001f], // C0 remainder [0x007f, 0x009f], // DEL + C1 [0x00ad, 0x00ad], // SOFT HYPHEN [0x0600, 0x0605], // Arabic format controls [0x061c, 0x061c], // ARABIC LETTER MARK [0x06dd, 0x06dd], // ARABIC END OF AYAH [0x070f, 0x070f], // SYRIAC ABBREVIATION MARK [0x0890, 0x0891], // ARABIC POUND/PIASTRE MARK ABOVE [0x08e2, 0x08e2], // ARABIC DISPUTED END OF AYAH [0x180e, 0x180e], // MONGOLIAN VOWEL SEPARATOR [0x200b, 0x200f], // ZWSP, ZWNJ, ZWJ, LRM, RLM [0x202a, 0x202e], // bidi embeddings and overrides [0x2060, 0x2064], // WORD JOINER + invisible operators [0x2066, 0x206f], // bidi isolates + deprecated format controls [0xfeff, 0xfeff], // ZWNBSP / mid-file BOM (leading BOM exempted at scan time) [0xfff9, 0xfffb], // interlinear annotation controls [0x110bd, 0x110bd], // KAITHI NUMBER SIGN [0x110cd, 0x110cd], // KAITHI NUMBER SIGN ABOVE [0x13430, 0x13455], // Egyptian hieroglyph format controls [0x1bca0, 0x1bca3], // shorthand format controls [0x1d173, 0x1d17a], // musical format controls [0xe0001, 0xe0001], // LANGUAGE TAG [0xe0020, 0xe007f], // tag characters ]; /** Invisible space separators (Zs) that pass the Cf sweep — named in RFC-1304. */ const FORBIDDEN_SPACE_CODEPOINTS: readonly number[] = [ 0x00a0, // NBSP 0x2007, // FIGURE SPACE 0x2009, // THIN SPACE 0x200a, // HAIR SPACE 0x202f, // NNBSP ]; const CODEPOINT_NAMES: ReadonlyMap = new Map([ [0x0000, "NUL"], [0x0007, "BEL"], [0x0008, "BACKSPACE"], [0x000b, "VERTICAL TAB"], [0x000c, "FORM FEED"], [0x001b, "ESCAPE"], [0x007f, "DEL"], [0x00a0, "NBSP"], [0x00ad, "SOFT HYPHEN"], [0x061c, "ARABIC LETTER MARK"], [0x180e, "MONGOLIAN VOWEL SEPARATOR"], [0x2007, "FIGURE SPACE"], [0x2009, "THIN SPACE"], [0x200a, "HAIR SPACE"], [0x200b, "ZERO WIDTH SPACE"], [0x200c, "ZERO WIDTH NON-JOINER"], [0x200d, "ZERO WIDTH JOINER"], [0x200e, "LEFT-TO-RIGHT MARK"], [0x200f, "RIGHT-TO-LEFT MARK"], [0x202a, "LEFT-TO-RIGHT EMBEDDING"], [0x202b, "RIGHT-TO-LEFT EMBEDDING"], [0x202c, "POP DIRECTIONAL FORMATTING"], [0x202d, "LEFT-TO-RIGHT OVERRIDE"], [0x202e, "RIGHT-TO-LEFT OVERRIDE"], [0x202f, "NNBSP"], [0x2060, "WORD JOINER"], [0x2061, "FUNCTION APPLICATION"], [0x2062, "INVISIBLE TIMES"], [0x2063, "INVISIBLE SEPARATOR"], [0x2064, "INVISIBLE PLUS"], [0x2066, "LEFT-TO-RIGHT ISOLATE"], [0x2067, "RIGHT-TO-LEFT ISOLATE"], [0x2068, "FIRST STRONG ISOLATE"], [0x2069, "POP DIRECTIONAL ISOLATE"], [0xfeff, "BOM/ZWNBSP"], [0xe0001, "LANGUAGE TAG"], ]); function codepointName(cp: number): string { return CODEPOINT_NAMES.get(cp) ?? `U+${cp.toString(16).toUpperCase().padStart(4, "0")}`; } function buildForbiddenSet(): Set { const set = new Set(); for (const [lo, hi] of FORBIDDEN_CODEPOINT_RANGES) { for (let cp = lo; cp <= hi; cp++) set.add(cp); } for (const cp of FORBIDDEN_SPACE_CODEPOINTS) set.add(cp); return set; } const FORBIDDEN_SET = buildForbiddenSet(); /** * Exported constant view of the forbidden set — the single source of truth for * both consumers (RFC-1304: "the forbidden-codepoint list lives in one exported * constant shared by the generator and the validator"). */ export const FORBIDDEN_SOURCE_CODEPOINTS: ReadonlySet = FORBIDDEN_SET; export interface ForbiddenCodepointHit { /** UTF-16 index into the source string. */ offset: number; /** Unicode codepoint value. */ codepoint: number; /** Human-readable name or `U+XXXX` fallback. */ name: string; /** 1-based source line at the hit position. */ line: number; } /** * Scan raw source for forbidden invisible/control codepoints. Runs before * masking — a NUL or zero-width byte must be reported as itself, not as a * scanner artifact. A leading BOM (offset 0) is a legitimate file prologue * and is exempt; every other occurrence is a hit. Never suppressible. */ export function scanForbiddenCodepoints(source: string): ForbiddenCodepointHit[] { const hits: ForbiddenCodepointHit[] = []; let line = 1; for (let i = 0; i < source.length; i++) { const offset = i; const cp = source.codePointAt(i)!; if (cp > 0xffff) i++; // astral codepoints occupy a surrogate pair if (cp === 0x0a) { line++; continue; } if (cp === 0xfeff && offset === 0) continue; if (FORBIDDEN_SET.has(cp)) { hits.push({ offset, codepoint: cp, name: codepointName(cp), line }); } } return hits; } /** * Mask strings/comments/regex literals to spaces so brace matching and token * scans are not fooled. Newlines are preserved so diagnostics can still map * offsets to lines. * * Template literals are depth-tracked: `${ … }` regions re-enter code mode on a * mode stack, so a nested `` ` `` inside an interpolation opens a nested * template instead of terminating the outer one (RFC-1304 — the desync that * silently dropped definitions). `${` and its closing `}` are masked as * template syntax; the expression inside is masked as ordinary code content. * * `opts.keepComments` leaves `//`/`/*` comment text visible (strings and * templates still mask) — for pragma checks that must see real comments but * never tokens carried inside string literals. */ export function maskSource(src: string, opts?: { keepComments?: boolean }): string { const keepComments = opts?.keepComments === true; let out = ""; let i = 0; const n = src.length; // chars after which "/" opens a regex literal rather than division const REGEX_PREFIX_CHARS = new Set("(=,[!&|?:;{}+-*%^~<>".split("")); const REGEX_PREFIX_WORDS = new Set([ "return", "typeof", "case", "in", "of", "new", "delete", "void", "instanceof", "yield", "await", "do", "else", "throw", ]); const lastWord = () => { const m = /([A-Za-z_$][\w$]*)[^\w$]*$/.exec(out); return m?.[1] ?? ""; }; const lastSigChar = () => { const m = /(\S)\s*$/.exec(out); return m?.[1] ?? ""; }; // modeStack: "code" = ordinary scanning; "template" = inside a `…` body. // texprStack records the braceDepth at each `${` — a `}` at that depth is // the expression closer (template syntax, masked), not a literal brace. const modeStack: ("code" | "template")[] = ["code"]; const texprStack: number[] = []; let braceDepth = 0; while (i < n) { const c = src[i]; if (modeStack[modeStack.length - 1] === "template") { if (c === "\\") { out += " "; i += 2; continue; } if (c === "`") { out += " "; i++; modeStack.pop(); continue; } if (c === "$" && src[i + 1] === "{") { out += " "; i += 2; texprStack.push(braceDepth); modeStack.push("code"); continue; } out += c === "\n" ? "\n" : " "; i++; continue; } // code mode if (c === "/" && src[i + 1] === "/") { while (i < n && src[i] !== "\n") { out += keepComments ? src[i] : " "; i++; } } else if (c === "/" && src[i + 1] === "*") { out += keepComments ? "/*" : " "; i += 2; while (i < n && !(src[i] === "*" && src[i + 1] === "/")) { out += src[i] === "\n" || keepComments ? src[i] : " "; i++; } out += keepComments && i < n ? "*/" : " "; i += 2; } else if ( c === "/" && src[i + 1] !== "=" && (REGEX_PREFIX_CHARS.has(lastSigChar()) || REGEX_PREFIX_WORDS.has(lastWord()) || lastSigChar() === "") ) { // regex literal — mask until unescaped / outside a [...] class out += " "; i++; let inClass = false; while (i < n) { const ch = src[i]; if (ch === "\\") { out += " "; i += 2; continue; } if (ch === "[") inClass = true; else if (ch === "]") inClass = false; else if (ch === "/" && !inClass) break; else if (ch === "\n") break; // unterminated — bail as division fallback out += " "; i++; } if (i < n && src[i] === "/") { out += " "; i++; while (i < n && /[a-z]/.test(src[i])) { out += " "; i++; } } } else if (c === '"' || c === "'") { const q = c; out += " "; i++; while (i < n && src[i] !== q) { if (src[i] === "\\") { out += " "; i += 2; continue; } out += src[i] === "\n" ? "\n" : " "; i++; } out += " "; i++; } else if (c === "`") { out += " "; i++; modeStack.push("template"); } else if (c === "{") { braceDepth++; out += c; i++; } else if (c === "}") { if (texprStack.length > 0 && braceDepth === texprStack[texprStack.length - 1]) { // closes a ${ expression — template syntax, not a literal brace texprStack.pop(); modeStack.pop(); out += " "; i++; } else { if (braceDepth > 0) braceDepth--; out += c; i++; } } else { out += c; i++; } } return out; } /** Extract the balanced {...} literal starting at `openIdx` in masked source. */ export function literalEnd(masked: string, openIdx: number): number { let depth = 0; for (let i = openIdx; i < masked.length; i++) { if (masked[i] === "{") depth++; else if (masked[i] === "}") { depth--; if (depth === 0) return i + 1; } } return -1; } /** * Return [start,end) offsets of a TOP-LEVEL field's value inside a masked * literal whose opening brace sits at index 0. A field name counts only in * field position (preceding significant char `{` or `,`) at literal depth 1 — * a nested `name:` (a flag key, a nested object field) ahead of the real * top-level field must not shadow it (RFC-1321 review: the depth-blind * first-match both false-positived on `flags: { name: {…} }` and let a real * non-literal `name:` hide behind a nested literal). */ export function fieldOffsets(litMasked: string, field: string): [number, number] | undefined { let depth = 1; for (let i = 1; i < litMasked.length; i++) { const c = litMasked[i]; if (c === "{" || c === "[" || c === "(") { depth++; continue; } if (c === "}" || c === "]" || c === ")") { depth--; if (depth < 1) return undefined; // literal closed before the field continue; } if (depth !== 1) continue; const fm = /^[A-Za-z_$][\w$]*\s*:/.exec(litMasked.slice(i, i + 64)); if (!fm) continue; const prev = prevSigChar(litMasked, i); if (prev !== "{" && prev !== ",") { i += fm[0].length - 1; // ternary branch / label — not a field name continue; } const name = /^[A-Za-z_$][\w$]*/.exec(fm[0])![0]; // Do NOT skip whitespace here — masked string values are spaces, so // skipping would overshoot to the next comma. Slice raw and trim instead. const start = i + fm[0].length; i = start - 1; if (name !== field) continue; let vdepth = 1; for (let j = start; j < litMasked.length; j++) { const v = litMasked[j]; if (v === "{" || v === "[" || v === "(") vdepth++; else if (v === "}" || v === "]" || v === ")") { if (vdepth === 1) return [start, j]; vdepth--; } else if (v === "," && vdepth === 1) return [start, j]; } return undefined; } return undefined; } export interface DefinitionAnchor { /** The `export const ` identifier. */ exportName: string; /** Index of the `export` keyword in masked source. */ index: number; /** Index of the definition object's opening `{` in masked source. */ openIdx: number; /** * `annotated`: `export const x: KernelCommandDefinition = {`. * `satisfies`: `export const x = { … } satisfies KernelCommandDefinition` — * the annotation sits behind the literal, so the anchor is proven only after * the literal balances. */ kind: "annotated" | "satisfies"; } const ANNOTATED_DEF_RE = /export\s+const\s+([A-Za-z_$][\w$]*)\s*:\s*KernelCommandDefinition\s*=\s*\{/g; // Satisfies form: `export const x(: OtherType)? = { … } satisfies KernelCommandDefinition` // — the literal precedes the annotation, so the anchor is proven by the tail. const SATISFIES_HEAD_RE = /export\s+const\s+([A-Za-z_$][\w$]*)\s*(?::[^{=]+)?=\s*\{/g; const SATISFIES_TAIL_RE = /\s*satisfies\s+KernelCommandDefinition\b(?![\w$.])/y; /** * Find `KernelCommandDefinition` object literals in masked source. Accepts the * colon-annotated form and the postfix `satisfies` form (RFC-1304). Anchors are * sorted by source position. Convention-bound to `export const` — `export let` * and `export { x }` barreled forms are not anchors (the corpus is uniform). */ export function findDefinitionAnchors(masked: string): DefinitionAnchor[] { const anchors: DefinitionAnchor[] = []; const annotatedIdx = new Set(); for (const m of masked.matchAll(ANNOTATED_DEF_RE)) { annotatedIdx.add(m.index); anchors.push({ exportName: m[1], index: m.index, openIdx: m.index + m[0].length - 1, kind: "annotated", }); } for (const m of masked.matchAll(SATISFIES_HEAD_RE)) { if (annotatedIdx.has(m.index)) continue; // colon-annotated def already anchored const openIdx = m.index + m[0].length - 1; const end = literalEnd(masked, openIdx); if (end === -1) continue; // unbalanced — the suspect-file signal reports it SATISFIES_TAIL_RE.lastIndex = end; if (SATISFIES_TAIL_RE.test(masked)) { anchors.push({ exportName: m[1], index: m.index, openIdx, kind: "satisfies" }); } SATISFIES_TAIL_RE.lastIndex = 0; } return anchors.sort((a, b) => a.index - b.index); } // Annotation-position tokens: an `export const x: KernelCommandDefinition =` // (any initializer) — the `=` requirement excludes type usages like // `KernelCommandDefinition[]` arrays. Counted per occurrence so a file can // pair each token with its anchor (REVIEW-CODE-2026-10-16-03 finding 01). const ANNOTATION_SIGNAL_RE = /export\s+const\s+[A-Za-z_$][\w$]*\s*:\s*KernelCommandDefinition\s*=/g; // Postfix `satisfies` tokens anywhere — covers `= f() satisfies KCD` factory // forms that carry no object literal at all. const SATISFIES_SIGNAL_RE = /\bsatisfies\s+KernelCommandDefinition\b(?![\w$.])/g; // Top-level object literals — `export const x = {`, `export const x: T = {`, // `export default {`. A depth-1 `execute:`/`command:` field makes the literal // definition-shaped; deeper fields (pipeline step `command:` props, interface // members) do not count. const TOP_LITERAL_HEAD_RE = /export\s+(?:const\s+[A-Za-z_$][\w$]*\s*(?::[^={]*)?=\s*|default\s*)\{/g; /** Last significant (non-space) char before `idx`, or "" at file start. */ function prevSigChar(masked: string, idx: number): string { for (let j = idx - 1; j >= 0; j--) { const ch = masked[j]; if (ch !== " " && ch !== "\n" && ch !== "\t" && ch !== "\r") return ch; } return ""; } function literalHasDefinitionField(masked: string, openIdx: number): boolean { let depth = 1; for (let i = openIdx + 1; i < masked.length && depth >= 1; i++) { const ch = masked[i]; if (ch === "{" || ch === "[" || ch === "(") depth++; else if (ch === "}" || ch === "]" || ch === ")") { depth--; if (depth < 1) break; } else if (depth === 1) { const fm = /^[A-Za-z_$][\w$]*\s*:/.exec(masked.slice(i, i + 64)); if (fm) { // Field names must sit in field position — after `{` or `,`. A `?`/`:` // predecessor means a ternary branch or label, not a property. const prev = prevSigChar(masked, i); if (prev === "{" || prev === ",") { const field = /^[A-Za-z_$][\w$]*/.exec(fm[0])![0]; if (field === "execute" || field === "command") return true; } i += fm[0].length - 1; } } } return false; } export interface CommandSignalReport { /** Definition evidence that did not resolve to an extracted anchor. */ unpaired: number; /** Breakdown of the unpaired evidence, for diagnostic detail. */ unpairedAnnotated: number; unpairedSatisfies: number; unpairedShaped: number; /** Offset of the first unpaired signal, or -1 when fully paired. */ firstOffset: number; } /** * Pair definition-shaped evidence against extracted anchors (RFC-1304 * CMDGEN-04). Pairing is positional: an anchor consumes the annotation or * shaped-literal signal at its own `index` and the `satisfies` token directly * following its literal's end — so a hybrid `: T = {…} satisfies KCD` def * counts once, while `export const x = factory() satisfies KCD` (no literal at * all) stays unpaired and suspect. */ export function unpairedCommandSignals( masked: string, anchors: readonly DefinitionAnchor[], ): CommandSignalReport { const annotatedAt = new Set(); const satisfiesAt: number[] = []; const shapedAt = new Set(); for (const m of masked.matchAll(ANNOTATION_SIGNAL_RE)) { annotatedAt.add(m.index); } for (const m of masked.matchAll(SATISFIES_SIGNAL_RE)) { satisfiesAt.push(m.index); } for (const m of masked.matchAll(TOP_LITERAL_HEAD_RE)) { if (literalHasDefinitionField(masked, m.index + m[0].length - 1)) { shapedAt.add(m.index); } } const pairedSatisfies = new Set(); for (const anchor of anchors) { annotatedAt.delete(anchor.index); shapedAt.delete(anchor.index); const end = literalEnd(masked, anchor.openIdx); if (end === -1) continue; SATISFIES_TAIL_RE.lastIndex = end; const tm = SATISFIES_TAIL_RE.exec(masked); SATISFIES_TAIL_RE.lastIndex = 0; if (tm) pairedSatisfies.add(end + tm[0].indexOf("satisfies")); } const unpairedSatisfiesAt = satisfiesAt.filter((o) => !pairedSatisfies.has(o)); const report: CommandSignalReport = { unpairedAnnotated: annotatedAt.size, unpairedSatisfies: unpairedSatisfiesAt.length, unpairedShaped: shapedAt.size, unpaired: annotatedAt.size + unpairedSatisfiesAt.length + shapedAt.size, firstOffset: -1, }; for (const off of [...annotatedAt, ...unpairedSatisfiesAt, ...shapedAt]) { if (report.firstOffset === -1 || off < report.firstOffset) { report.firstOffset = off; } } return report; } /** * Heuristic probe (RFC-1304 CMDGEN-04): does the masked source carry any * command-definition evidence — annotation-position token, postfix satisfies, * or a definition-shaped top-level literal — regardless of pairing. Used by * the site-exports seam so a suspect (unextractable) definition still keeps * its file out of the exports map. */ export function fileHasCommandSignal(masked: string): boolean { ANNOTATION_SIGNAL_RE.lastIndex = 0; if (ANNOTATION_SIGNAL_RE.test(masked)) return true; SATISFIES_SIGNAL_RE.lastIndex = 0; if (SATISFIES_SIGNAL_RE.test(masked)) return true; for (const m of masked.matchAll(TOP_LITERAL_HEAD_RE)) { if (literalHasDefinitionField(masked, m.index + m[0].length - 1)) { return true; } } return false; } /** * RFC-1321 CMDGEN-06: extract the string-literal content of a definition * field's value, or `undefined` when the value is not a pure literal. * Receives BOTH slices fieldOffsets returned — raw text and its masked form. * The masked slice must be whitespace-only (one string token plus optional * comments — comments mask to spaces, so a leading or trailing comment stays * a literal); any visible code (`name: CONST`, `"a" + b`, `("a")`, * `"a" as const`) rejects. Bare template literals are rejected by the * quote requirement. The first quote outside comments is the token's open — * quotes inside comment text cannot mislead the extractor. */ export function stringLiteralValue( rawFieldText: string, maskedFieldText: string, ): string | undefined { if (maskedFieldText.trim().length !== 0) return undefined; let i = 0; let q = ""; let open = -1; while (i < rawFieldText.length) { const c = rawFieldText[i]; if (c === "/" && rawFieldText[i + 1] === "/") { const nl = rawFieldText.indexOf("\n", i + 2); i = nl === -1 ? rawFieldText.length : nl + 1; continue; } if (c === "/" && rawFieldText[i + 1] === "*") { const e = rawFieldText.indexOf("*" + "/", i + 2); i = e === -1 ? rawFieldText.length : e + 2; continue; } if (c === '"' || c === "'") { q = c; open = i; break; } i++; } if (open === -1) return undefined; for (let j = open + 1; j < rawFieldText.length; j++) { const c = rawFieldText[j]; if (c === "\\") { j++; continue; } if (c === q) return rawFieldText.slice(open + 1, j); if (c === "\n") return undefined; // unterminated } return undefined; } /** * RFC-1321 CMDGEN-06: is a definition field's source text a complete quoted * string literal? Shared by both enforcement points * (checks.commands.generate and werkstatt.commands.validate) so a lint pass * and a generate pass cannot disagree. */ export function isStringLiteralSource(rawFieldText: string, maskedFieldText: string): boolean { return stringLiteralValue(rawFieldText, maskedFieldText) !== undefined; } /** * File-level pragma exempting a file from the CMDGEN-04 suspect net — must be * a line comment at line start (`// cmdgen-ignore`); a string literal carrying * the token does not suppress. Never suppresses CMDGEN-05. */ export const CMDGEN_IGNORE_RE = /^[ \t]*\/\/[ \t]*cmdgen-ignore/m; /** * Files under src/checks that export run* handlers or carry command-shaped * literals but legitimately hold no KernelCommandDefinition (module entry, * shared helpers, non-command runners). Shared by checks.commands.generate * (CMDGEN-01/04) and werkstatt.commands.validate (CMDGEN-04) so both scanners * exempt the identical set — keys are paths relative to src/checks/. */ export const NON_COMMAND_ALLOWLIST: ReadonlySet = new Set([ "module.ts", "structure/naming-convention.ts", "semantic-mirror.ts", "content-idempotency.ts", "checks/mirroring.ts", "check-warpgogol/commands/flag-schema-helpers.ts", "check-warpgogol/commands/evidence-readers.ts", ]);