@tangle-network/agent-app 0.45.26 → 0.45.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/assistant/index.d.ts +1 -0
  2. package/dist/assistant/index.js +5 -5
  3. package/dist/chat-routes/index.js +21 -21
  4. package/dist/chat-store/index.js +2 -2
  5. package/dist/{chunk-B2UEW62O.js → chunk-5ZTFZBS6.js} +4 -4
  6. package/dist/{chunk-AGCRCOQH.js → chunk-AWPK7ZDS.js} +1 -1
  7. package/dist/chunk-C3CAYGGQ.js +18 -0
  8. package/dist/chunk-C3CAYGGQ.js.map +1 -0
  9. package/dist/chunk-EMLGWEHV.js +33 -0
  10. package/dist/chunk-EMLGWEHV.js.map +1 -0
  11. package/dist/{chunk-XEA5EG6P.js → chunk-EPZYYWCT.js} +8 -30
  12. package/dist/chunk-EPZYYWCT.js.map +1 -0
  13. package/dist/{chunk-WD2B6HGY.js → chunk-K4RA5T3A.js} +11 -32
  14. package/dist/chunk-K4RA5T3A.js.map +1 -0
  15. package/dist/chunk-NEJ7OMQS.js +351 -0
  16. package/dist/chunk-NEJ7OMQS.js.map +1 -0
  17. package/dist/{chunk-7V2I3JGZ.js → chunk-OTLEYHOG.js} +50 -12
  18. package/dist/chunk-OTLEYHOG.js.map +1 -0
  19. package/dist/{chunk-RT5RKAFX.js → chunk-QGSVF6DZ.js} +8 -18
  20. package/dist/chunk-QGSVF6DZ.js.map +1 -0
  21. package/dist/{chunk-KOMP6NDW.js → chunk-WC43OQMR.js} +45 -34
  22. package/dist/chunk-WC43OQMR.js.map +1 -0
  23. package/dist/{chunk-N3G3FSM4.js → chunk-YXA3U4JZ.js} +9 -47
  24. package/dist/chunk-YXA3U4JZ.js.map +1 -0
  25. package/dist/design-canvas-react/index.js +4 -4
  26. package/dist/design-canvas-react/lazy.js +1 -1
  27. package/dist/legibility/cli.js +14 -8
  28. package/dist/legibility/cli.js.map +1 -1
  29. package/dist/legibility/index.js +2 -1
  30. package/dist/peer-floors/cli.js +14 -8
  31. package/dist/peer-floors/cli.js.map +1 -1
  32. package/dist/preflight/cli.js +4 -2
  33. package/dist/preflight/cli.js.map +1 -1
  34. package/dist/{run-tEsZUhAf.d.ts → run-D80hoLKh.d.ts} +1 -1
  35. package/dist/sandbox/index.d.ts +53 -1
  36. package/dist/sandbox/index.js +1 -1
  37. package/dist/signoff/cli.d.ts +2 -2
  38. package/dist/signoff/cli.js +6 -18
  39. package/dist/signoff/cli.js.map +1 -1
  40. package/dist/signoff/index.d.ts +4 -420
  41. package/dist/signoff/index.js +3 -55
  42. package/dist/signoff/proof-cli.js +11 -6
  43. package/dist/signoff/proof-cli.js.map +1 -1
  44. package/dist/signoff/proof.d.ts +70 -271
  45. package/dist/signoff/proof.js +3 -73
  46. package/dist/signoff/proof.js.map +1 -1
  47. package/dist/spend/cli.d.ts +1 -0
  48. package/dist/spend/cli.js +119 -0
  49. package/dist/spend/cli.js.map +1 -0
  50. package/dist/spend/index.d.ts +640 -0
  51. package/dist/spend/index.js +196 -0
  52. package/dist/spend/index.js.map +1 -0
  53. package/dist/stream/index.js +14 -14
  54. package/dist/teams/index.js +9 -9
  55. package/dist/teams/invitations-api.js +7 -7
  56. package/dist/theme-contract/cli.js +6 -2
  57. package/dist/theme-contract/cli.js.map +1 -1
  58. package/dist/theme-contract/index.js +2 -1
  59. package/dist/{types-U7Nz-txa.d.ts → types-Bd6uW9vQ.d.ts} +1 -1
  60. package/dist/web-react/index.d.ts +28 -40
  61. package/dist/web-react/index.js +11 -11
  62. package/package.json +7 -1
  63. package/dist/chunk-7V2I3JGZ.js.map +0 -1
  64. package/dist/chunk-KOMP6NDW.js.map +0 -1
  65. package/dist/chunk-N3G3FSM4.js.map +0 -1
  66. package/dist/chunk-RT5RKAFX.js.map +0 -1
  67. package/dist/chunk-WD2B6HGY.js.map +0 -1
  68. package/dist/chunk-XEA5EG6P.js.map +0 -1
  69. /package/dist/{chunk-B2UEW62O.js.map → chunk-5ZTFZBS6.js.map} +0 -0
  70. /package/dist/{chunk-AGCRCOQH.js.map → chunk-AWPK7ZDS.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/legibility/source.ts","../src/legibility/checks/empty-state.ts","../src/legibility/scan.ts","../src/legibility/checks/reachability.ts","../src/legibility/checks/silent-failure.ts","../src/legibility/checks/success.ts","../src/legibility/checks/vocabulary.ts","../src/legibility/types.ts","../src/legibility/suppress.ts","../src/legibility/report.ts","../src/legibility/index.ts"],"sourcesContent":["/**\n * A purpose-built TS/TSX scanner: the one place this subpath decides what part\n * of a file is CODE and what part is COPY A HUMAN READS.\n *\n * Every legibility check needs the same distinction, and getting it from\n * per-check regexes is what makes a lint gate imprecise enough to be turned off.\n * `grep -i artifact` over one product's `apps/web/src` returns 11 hits and every\n * single one is an import specifier, a prop name, or a doc comment — zero are on\n * screen. A checker that reports those 11 is deleted within a week, and then it\n * guards nothing.\n *\n * So this module lexes instead: one pass produces (a) classified SEGMENTS —\n * comments, string literals, template chunks, JSX text, JSX attribute values —\n * and (b) a JSX ELEMENT TREE with spans, attributes, and the enclosing\n * expression container. Checks read those, never the raw bytes.\n *\n * It is a lexer, not a type-aware parser, and that boundary is deliberate: this\n * package ships one runtime dependency and adding `typescript` to every\n * consumer's install to lint copy is the wrong trade. What a lexer cannot do —\n * resolve a string through a variable, follow a component's props to its render\n * — is out of scope by construction and documented per check.\n *\n * Node-agnostic: pure string in, data out. The `fs` walking lives in `scan.ts`.\n */\n\n/** What a stretch of source is, once the lexer has decided. */\nexport type SegmentKind =\n /** `//…` or `/*…*​/` — never user-visible; every check skips these. */\n | 'comment'\n /** A `'…'` / `\"…\"` literal in code position. Visible only in some contexts. */\n | 'string'\n /** One literal chunk of a template literal (the `${…}` holes are code). */\n | 'template'\n /** Text between JSX tags. The highest-confidence user-visible signal there is. */\n | 'jsx-text'\n /** A `name=\"…\"` attribute value on a JSX element. */\n | 'jsx-attribute'\n\n/** One classified stretch of source. */\nexport interface SourceSegment {\n readonly kind: SegmentKind\n /** Offset of the first character of the segment's VALUE (inside the quotes). */\n readonly start: number\n /** Offset just past the segment's value. */\n readonly end: number\n /** The value text, quotes stripped, escapes left as written. */\n readonly value: string\n /** For `jsx-attribute`: the attribute name. For `jsx-text`: absent. */\n readonly attribute?: string\n /** For `jsx-attribute` / `jsx-text`: the owning element's tag name. */\n readonly tag?: string\n}\n\n/** One attribute on a JSX element. */\nexport interface JsxAttribute {\n readonly name: string\n readonly start: number\n /** The literal value when written `name=\"…\"`; null when `name={…}` or bare. */\n readonly value: string | null\n /** True when written `name={…}` — the value is code, not copy. */\n readonly expression: boolean\n}\n\n/** One JSX element, with the span every subtree question needs. */\nexport interface JsxElement {\n /** Tag as written (`div`, `Button`, `Card.Header`); `''` for a fragment. */\n readonly tag: string\n readonly attributes: JsxAttribute[]\n readonly children: JsxElement[]\n parent: JsxElement | null\n /** Offset of the opening `<`. */\n readonly start: number\n /** Offset just past the opening tag's `>`. */\n openEnd: number\n /** Offset just past the element's end (`/>` or `</tag>`). */\n end: number\n /**\n * Offset of the `{` of the nearest enclosing JSX expression container, or\n * null at the top of a return/assignment. This is what scopes an empty state\n * to its own conditional branch instead of to the whole page.\n */\n readonly containerStart: number | null\n}\n\n/** Everything one pass over a file produces. */\nexport interface ScannedSource {\n readonly text: string\n readonly segments: readonly SourceSegment[]\n /** Every element, in document (open-tag) order. */\n readonly elements: readonly JsxElement[]\n /**\n * `text` with every comment, string body and template body replaced by\n * spaces, offsets preserved. Structural regexes (catch bodies, fetch calls)\n * run over this so a `catch` inside a string can never be a finding.\n */\n readonly masked: string\n}\n\n/** 1-based line/column for a byte offset. */\nexport interface SourcePosition {\n readonly line: number\n readonly column: number\n}\n\nconst IDENT_START = /[A-Za-z_$]/\nconst IDENT_PART = /[A-Za-z0-9_$.:-]/\n\n/**\n * Characters that can legally precede a JSX element in an expression position.\n * `a < b` and `Array<Foo>` both fail this test (they follow an identifier or a\n * closing paren), which is the whole reason it exists.\n */\nconst JSX_PRECEDERS = new Set(['(', '{', '}', '=', ',', ';', ':', '?', '&', '|', '!', '+', '>', '[', '\\n'])\n\n/** Keywords after which a `<` starts JSX rather than a comparison. */\nconst JSX_PRECEDING_WORDS = new Set(['return', 'yield', 'case', 'default', 'in', 'of', 'typeof', 'await'])\n\ninterface Frame {\n kind: 'code' | 'template' | 'jsx-tag' | 'jsx-children'\n /** `{` depth inside a code frame; the frame pops when it would go negative. */\n depth: number\n element: JsxElement | null\n /** For a code frame opened by a JSX `{`: the offset of that brace. */\n containerStart: number | null\n /**\n * For a template frame: the attribute or key the whole literal fills, resolved\n * ONCE at the opening backtick and carried by every chunk.\n *\n * Resolving per chunk instead was a measured defect: in\n * ``to={`${base}/contracts/redline`}`` only the first chunk sits next to\n * `to=`, so the segment naming the destination arrived attribute-less and the\n * reachability check reported a route that a link on screen plainly reaches.\n * Four such false positives in one product — the kind that gets a gate turned\n * off in a week.\n */\n templateAttribute?: string | null\n}\n\n/**\n * Lex one TS/TSX source.\n *\n * The loop keeps a frame stack. A code frame pops back to its JSX parent when\n * an unmatched `}` closes the expression container that opened it; a JSX tag\n * frame becomes a children frame at `>` and pops at `/>`.\n */\nexport function scanSource(text: string): ScannedSource {\n const segments: SourceSegment[] = []\n const elements: JsxElement[] = []\n const mask = new Array<string>(text.length)\n for (let i = 0; i < text.length; i++) mask[i] = text[i] as string\n\n /** Blank a range in the mask, keeping newlines so line numbers survive. */\n const blank = (from: number, to: number): void => {\n for (let i = from; i < to && i < text.length; i++) mask[i] = text[i] === '\\n' ? '\\n' : ' '\n }\n\n const stack: Frame[] = [{ kind: 'code', depth: 0, element: null, containerStart: null }]\n const top = (): Frame => stack[stack.length - 1] as Frame\n\n /** The element whose children (or tag) we are currently inside, if any. */\n const openElement = (): JsxElement | null => {\n for (let i = stack.length - 1; i >= 0; i--) {\n const frame = stack[i] as Frame\n if (frame.kind === 'jsx-children' || frame.kind === 'jsx-tag') return frame.element\n }\n return null\n }\n\n /**\n * Offset of the `{` opening the innermost JSX expression container, or null\n * at the top of a return/assignment. Elements sharing a container are one\n * conditional branch — which is exactly the scope an empty state occupies.\n */\n const containerOf = (): number | null => {\n for (let i = stack.length - 1; i >= 0; i--) {\n const frame = stack[i] as Frame\n if (frame.kind === 'code') return frame.containerStart\n if (frame.kind === 'jsx-children' || frame.kind === 'jsx-tag') return frame.element?.containerStart ?? null\n }\n return null\n }\n\n let i = 0\n while (i < text.length) {\n const frame = top()\n\n if (frame.kind === 'jsx-children') {\n i = readJsxChildren(i, frame)\n continue\n }\n if (frame.kind === 'jsx-tag') {\n i = readJsxTag(i, frame)\n continue\n }\n if (frame.kind === 'template') {\n i = readTemplateChunk(i)\n continue\n }\n i = readCode(i, frame)\n }\n\n return { text, segments, elements, masked: mask.join('') }\n\n // ── readers ────────────────────────────────────────────────────────────────\n\n function readCode(at: number, frame: Frame): number {\n const ch = text[at] as string\n\n if (ch === '/' && text[at + 1] === '/') {\n const end = indexOrEnd(text, '\\n', at)\n segments.push({ kind: 'comment', start: at + 2, end, value: text.slice(at + 2, end) })\n blank(at, end)\n return end\n }\n if (ch === '/' && text[at + 1] === '*') {\n const close = text.indexOf('*/', at + 2)\n const end = close === -1 ? text.length : close + 2\n segments.push({ kind: 'comment', start: at + 2, end: end - 2, value: text.slice(at + 2, end - 2) })\n blank(at, end)\n return end\n }\n if (ch === '\"' || ch === \"'\") {\n const end = readQuoted(text, at, ch)\n segments.push({ kind: 'string', start: at + 1, end: end - 1, value: text.slice(at + 1, end - 1) })\n blank(at + 1, end - 1)\n return end\n }\n if (ch === '`') {\n stack.push({\n kind: 'template',\n depth: 0,\n element: null,\n containerStart: containerOf(),\n templateAttribute: attributeOfTemplate(at + 1),\n })\n return at + 1\n }\n if (ch === '/' && isRegexStart(text, at)) {\n return skipRegex(text, at)\n }\n if (ch === '{') {\n frame.depth++\n return at + 1\n }\n if (ch === '}') {\n // Closing the expression container that opened this frame: pop back to JSX.\n if (frame.depth === 0 && stack.length > 1) {\n stack.pop()\n return at + 1\n }\n frame.depth--\n return at + 1\n }\n if (ch === '<' && startsJsx(text, at)) {\n return openTag(at)\n }\n return at + 1\n }\n\n function readTemplateChunk(at: number): number {\n let cursor = at\n while (cursor < text.length) {\n const ch = text[cursor] as string\n if (ch === '\\\\') {\n cursor += 2\n continue\n }\n if (ch === '`') {\n pushTemplate(at, cursor)\n stack.pop()\n return cursor + 1\n }\n if (ch === '$' && text[cursor + 1] === '{') {\n pushTemplate(at, cursor)\n stack.push({ kind: 'code', depth: 0, element: null, containerStart: containerOf() })\n return cursor + 2\n }\n cursor++\n }\n pushTemplate(at, cursor)\n stack.pop()\n return cursor\n }\n\n function pushTemplate(from: number, to: number): void {\n if (to <= from) return\n const owner = openElement()\n let attribute: string | null = null\n for (let i = stack.length - 1; i >= 0; i--) {\n const entry = stack[i] as Frame\n if (entry.kind === 'template') {\n attribute = entry.templateAttribute ?? null\n break\n }\n }\n segments.push({\n kind: 'template',\n start: from,\n end: to,\n value: text.slice(from, to),\n ...(attribute === null ? {} : { attribute }),\n ...(owner === null ? {} : { tag: owner.tag }),\n })\n blank(from, to)\n }\n\n /**\n * When a template literal is a JSX attribute value (`title={`…`}` or\n * `title=` + backtick), report the attribute so the vocabulary check can\n * treat it as copy. Resolved by looking back for `name=` immediately before\n * the frame that opened this template.\n */\n function attributeOfTemplate(from: number): string | null {\n let cursor = from - 1\n if (text[cursor] === '`') cursor--\n while (cursor >= 0 && /\\s/.test(text[cursor] as string)) cursor--\n if (text[cursor] === '{') cursor--\n while (cursor >= 0 && /\\s/.test(text[cursor] as string)) cursor--\n if (text[cursor] !== '=') return null\n cursor--\n const nameEnd = cursor + 1\n while (cursor >= 0 && IDENT_PART.test(text[cursor] as string)) cursor--\n const name = text.slice(cursor + 1, nameEnd)\n return name.length > 0 && IDENT_START.test(name[0] as string) ? name : null\n }\n\n function openTag(at: number): number {\n let cursor = at + 1\n let tag = ''\n if (text[cursor] === '>') {\n // Fragment `<>`.\n const element = makeElement('', at)\n stack.push({ kind: 'jsx-children', depth: 0, element, containerStart: null })\n element.openEnd = cursor + 1\n return cursor + 1\n }\n while (cursor < text.length && IDENT_PART.test(text[cursor] as string)) {\n tag += text[cursor] as string\n cursor++\n }\n const element = makeElement(tag, at)\n stack.push({ kind: 'jsx-tag', depth: 0, element, containerStart: null })\n return cursor\n }\n\n function makeElement(tag: string, at: number): JsxElement {\n const parent = openElement()\n const element: JsxElement = {\n tag,\n attributes: [],\n children: [],\n parent,\n start: at,\n openEnd: at,\n end: at,\n containerStart: containerOf(),\n }\n if (parent) parent.children.push(element)\n elements.push(element)\n return element\n }\n\n function readJsxTag(at: number, frame: Frame): number {\n const ch = text[at] as string\n if (/\\s/.test(ch)) return at + 1\n const element = frame.element\n if (element === null) {\n stack.pop()\n return at + 1\n }\n if (ch === '/' && text[at + 1] === '>') {\n element.openEnd = at + 2\n element.end = at + 2\n stack.pop()\n return at + 2\n }\n if (ch === '>') {\n element.openEnd = at + 1\n stack.pop()\n stack.push({ kind: 'jsx-children', depth: 0, element, containerStart: null })\n return at + 1\n }\n if (ch === '{') {\n // Spread attribute `{...props}` or an expression value.\n stack.push({ kind: 'code', depth: 0, element, containerStart: at })\n return at + 1\n }\n if (!IDENT_START.test(ch)) return at + 1\n\n let cursor = at\n let name = ''\n while (cursor < text.length && IDENT_PART.test(text[cursor] as string)) {\n name += text[cursor] as string\n cursor++\n }\n let probe = cursor\n while (probe < text.length && /\\s/.test(text[probe] as string)) probe++\n if (text[probe] !== '=') {\n element.attributes.push({ name, start: at, value: null, expression: false })\n return cursor\n }\n probe++\n while (probe < text.length && /\\s/.test(text[probe] as string)) probe++\n const valueChar = text[probe]\n if (valueChar === '\"' || valueChar === \"'\") {\n const end = readQuoted(text, probe, valueChar)\n const value = text.slice(probe + 1, end - 1)\n element.attributes.push({ name, start: at, value, expression: false })\n segments.push({\n kind: 'jsx-attribute',\n start: probe + 1,\n end: end - 1,\n value,\n attribute: name,\n tag: element.tag,\n })\n blank(probe + 1, end - 1)\n return end\n }\n element.attributes.push({ name, start: at, value: null, expression: true })\n return probe\n }\n\n function readJsxChildren(at: number, frame: Frame): number {\n let cursor = at\n while (cursor < text.length) {\n const ch = text[cursor] as string\n if (ch === '{') {\n pushJsxText(at, cursor, frame.element)\n stack.push({ kind: 'code', depth: 0, element: frame.element, containerStart: cursor })\n return cursor + 1\n }\n if (ch === '<') {\n pushJsxText(at, cursor, frame.element)\n if (text[cursor + 1] === '/') {\n const close = indexOrEnd(text, '>', cursor)\n const element = frame.element\n if (element) element.end = Math.min(close + 1, text.length)\n stack.pop()\n return Math.min(close + 1, text.length)\n }\n return openTag(cursor)\n }\n cursor++\n }\n pushJsxText(at, cursor, frame.element)\n stack.pop()\n return cursor\n }\n\n function pushJsxText(from: number, to: number, owner: JsxElement | null): void {\n if (to <= from) return\n const value = text.slice(from, to)\n if (value.trim().length === 0) return\n segments.push({\n kind: 'jsx-text',\n start: from,\n end: to,\n value,\n ...(owner === null ? {} : { tag: owner.tag }),\n })\n blank(from, to)\n }\n}\n\n/** Offset just past the closing quote of the literal starting at `at`. */\nfunction readQuoted(text: string, at: number, quote: string): number {\n let cursor = at + 1\n while (cursor < text.length) {\n const ch = text[cursor]\n if (ch === '\\\\') {\n cursor += 2\n continue\n }\n if (ch === quote || ch === '\\n') return cursor + 1\n cursor++\n }\n return text.length\n}\n\nfunction indexOrEnd(text: string, needle: string, from: number): number {\n const idx = text.indexOf(needle, from)\n return idx === -1 ? text.length : idx\n}\n\n/**\n * Does the `<` at `at` open JSX rather than a comparison or a type argument?\n *\n * The rule: JSX only appears in expression position, so the previous\n * non-whitespace character must be an operator/opener, or the previous word\n * must be one of a few keywords. `a < b` (identifier before) and\n * `useState<string>(…)` (identifier before) are both rejected by the same test.\n */\nfunction startsJsx(text: string, at: number): boolean {\n const next = text[at + 1]\n if (next === undefined) return false\n if (next !== '>' && !IDENT_START.test(next)) return false\n\n let cursor = at - 1\n while (cursor >= 0 && /\\s/.test(text[cursor] as string)) cursor--\n if (cursor < 0) return true\n const prev = text[cursor] as string\n if (JSX_PRECEDERS.has(prev)) return true\n if (!IDENT_PART.test(prev)) return false\n\n let wordEnd = cursor + 1\n while (cursor >= 0 && IDENT_PART.test(text[cursor] as string)) cursor--\n return JSX_PRECEDING_WORDS.has(text.slice(cursor + 1, wordEnd))\n}\n\n/** Is the `/` at `at` the start of a regex literal rather than a division? */\nfunction isRegexStart(text: string, at: number): boolean {\n let cursor = at - 1\n while (cursor >= 0 && /\\s/.test(text[cursor] as string)) cursor--\n if (cursor < 0) return true\n const prev = text[cursor] as string\n return '([{=,;:?&|!+*%<>~^'.includes(prev)\n}\n\n/** Offset just past a regex literal (body plus flags). */\nfunction skipRegex(text: string, at: number): number {\n let cursor = at + 1\n let inClass = false\n while (cursor < text.length) {\n const ch = text[cursor]\n if (ch === '\\\\') {\n cursor += 2\n continue\n }\n if (ch === '[') inClass = true\n else if (ch === ']') inClass = false\n else if (ch === '/' && !inClass) {\n cursor++\n while (cursor < text.length && /[a-z]/.test(text[cursor] as string)) cursor++\n return cursor\n } else if (ch === '\\n') return cursor\n cursor++\n }\n return cursor\n}\n\n/** Line-start offsets, for `positionAt`. */\nexport function lineIndex(text: string): number[] {\n const starts = [0]\n for (let i = 0; i < text.length; i++) if (text[i] === '\\n') starts.push(i + 1)\n return starts\n}\n\n/** 1-based line/column of `offset`, given a `lineIndex` result. */\nexport function positionAt(starts: readonly number[], offset: number): SourcePosition {\n let lo = 0\n let hi = starts.length - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1\n if ((starts[mid] as number) <= offset) lo = mid\n else hi = mid - 1\n }\n return { line: lo + 1, column: offset - (starts[lo] as number) + 1 }\n}\n\n/** The innermost element whose span contains `offset`. */\nexport function elementAt(elements: readonly JsxElement[], offset: number): JsxElement | null {\n let best: JsxElement | null = null\n for (const element of elements) {\n if (element.start > offset) break\n const end = element.end > element.start ? element.end : element.openEnd\n if (offset < end && (best === null || element.start >= best.start)) best = element\n }\n return best\n}\n\n/**\n * The nearest enclosing FUNCTION body containing `offset`, over MASKED text.\n *\n * Walks outward from the innermost block until one is introduced by `)` +\n * optional `=>`, `function …`, or a method head — the scope a handler occupies.\n * This is what keeps a check from joining a request in one handler to a success\n * message in another, which is the difference between a report worth reading\n * and one that gets the gate switched off.\n */\nexport function enclosingFunctionBlock(masked: string, offset: number): { start: number; end: number } | null {\n let block = enclosingBlock(masked, offset)\n while (block !== null) {\n const head = masked.slice(Math.max(0, block.start - 60), block.start)\n if (/(=>|\\)|\\bfunction\\b|\\bdo\\b)\\s*$/.test(head) && !/\\b(if|for|while|switch|catch|try|else)\\s*\\)?\\s*$/.test(head)) {\n return block\n }\n const outer = enclosingBlock(masked, block.start)\n if (outer === null || outer.start === block.start) return block\n block = outer\n }\n return null\n}\n\n/**\n * The innermost `{ … }` block containing `offset`, over MASKED text.\n * Returns null when `offset` sits at top level.\n */\nexport function enclosingBlock(masked: string, offset: number): { start: number; end: number } | null {\n let depth = 0\n let start = -1\n for (let i = offset - 1; i >= 0; i--) {\n const ch = masked[i]\n if (ch === '}') depth++\n else if (ch === '{') {\n if (depth === 0) {\n start = i\n break\n }\n depth--\n }\n }\n if (start === -1) return null\n\n depth = 0\n for (let i = start; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '{') depth++\n else if (ch === '}') {\n depth--\n if (depth === 0) return { start, end: i + 1 }\n }\n }\n return { start, end: masked.length }\n}\n","/**\n * Check 2 — dead-end empty states.\n *\n * The defect, measured on one vertical: 21 empty states, 11 of them offering no\n * next action. A screen that says \"No deadlines tracked yet\" and nothing else\n * has told the reader they are in the right place and stranded them there. It\n * is the cheapest, most repeated legibility failure in the fleet, and it is\n * mechanically detectable: the empty branch renders no button, no link, no form\n * control.\n *\n * ── How the empty branch is scoped ───────────────────────────────────────────\n *\n * The interesting part is not finding the words, it is deciding what subtree\n * \"the empty state\" means. Walking up to the page root would find some button\n * somewhere and never report anything; stopping at the `<p>` would report every\n * empty state, action or not.\n *\n * The lexer records, for each element, the `{` of its enclosing JSX expression\n * container. Elements sharing a container are one conditional branch — exactly\n * how empty states are written:\n *\n * {rows.length === 0 && ( ← container\n * <div className=\"empty\"> ← branch root, same container\n * <p>No deadlines tracked yet</p>\n * </div>\n * )}\n *\n * So the branch root is the outermost ancestor sharing the text's container,\n * and the subtree searched for an action is exactly that branch. A component\n * that takes its empty copy as props (`emptyTitle=\"No sessions yet\"`) is its own\n * root, and its action props are read the same way.\n *\n * Recall limit: copy held in a variable or returned from a helper is invisible\n * to a lexer, and an \"action\" reached only through a child component's internals\n * is assumed present when that component takes an action-shaped prop.\n *\n * ── A titled section's zero-state is not a dead end ──────────────────────────\n *\n * The one measured false-positive class, and the one that decides whether this\n * check survives contact with a team. A contract detail screen carries four\n * zero-states — \"No parties recorded.\", \"No open findings.\", \"No resolved\n * findings yet.\", \"No renewal alerts configured.\" — one under each `<h2>`. None\n * of them strands anybody: the screen is full, the reader is oriented, and the\n * line is the honest label for a section that is empty. Reporting all four (and\n * a table's \"No findings.\" beside its own Run button, and a kanban column's \"No\n * filings\") buries the defect this check exists for — the screen whose ENTIRE\n * body is \"No deadlines tracked yet\".\n *\n * So a branch whose nearest preceding SIBLING is a heading is a section label\n * and is not reported. Measured over two production verticals: 21 findings → 12,\n * removing 8 section labels and 1 success state, and keeping every page-level\n * dead end. The recall cost is a real one — a screen whose whole body is one\n * titled, actionless section reads as a section here — and `emptyState:\n * { reportSectionZeroStates: true }` turns it back on.\n */\n\nimport { elementAt, type JsxElement } from '../source'\nimport type { ScannedFile } from '../scan'\nimport type { EmptyStateOptions, RawFinding } from '../types'\n\n/**\n * Copy that means \"there is nothing here\". Anchored at the start of the text\n * for the \"No …\" family so a sentence merely containing \"no\" is not a match.\n */\nconst EMPTY_PATTERNS: readonly RegExp[] = [\n /^no\\b/i,\n /^none\\b/i,\n /^nothing\\b/i,\n /^0\\s+\\w+\\s+(found|yet)/i,\n /\\bnothing (here|yet|to show|to do|to review)\\b/i,\n /\\bnot(hing)? found\\b/i,\n /\\bis empty\\b/i,\n /\\bno (results|items|data|matches|records|files|entries)\\b/i,\n /\\byou (have|haven't|don't have) (no|any)\\b/i,\n]\n\n/** Tags that are an action on their own. */\nconst ACTION_TAGS = new Set(['button', 'a', 'input', 'select', 'textarea', 'form', 'link', 'navlink'])\n\n/** Props that make any element an action. */\nconst ACTION_PROPS = new Set([\n 'onclick',\n 'onsubmit',\n 'onchange',\n 'onselect',\n 'onpress',\n 'ontoggle',\n 'href',\n 'to',\n 'action',\n 'onaction',\n 'oncta',\n 'emptyaction',\n 'emptycta',\n 'onemptyaction',\n 'primaryaction',\n])\n\n/**\n * A prop is also an action when its NAME ends like one. A component that takes\n * its empty copy as props takes its next action the same way, and the names are\n * the product's: `newSessionHref`, `onCreateClick`, `uploadAction`, `primaryCta`.\n * Measured: the exact-name list alone reported a history panel that ships a\n * \"New chat\" button, because the button arrives as `newSessionHref`.\n */\nconst ACTION_PROP_SUFFIX = /(href|action|cta|click|submit|press|link)$/i\n\n/** Props whose value is empty-state copy on a component that renders it. */\nconst EMPTY_COPY_PROPS = /^empty[A-Z]/\n\n/** `h1`–`h6`, and the component libraries' spelling of the same thing. */\nconst HEADING_TAG = /^h[1-6]$/i\nconst HEADING_SUFFIX = /(heading|title)$/i\n\n/** Run the dead-end empty-state check over one lexed file. */\nexport function checkEmptyStates(file: ScannedFile, options: EmptyStateOptions = {}): RawFinding[] {\n const actionTags = new Set([...ACTION_TAGS, ...(options.extraActionTags ?? []).map((tag) => tag.toLowerCase())])\n const actionProps = new Set([...ACTION_PROPS, ...(options.extraActionProps ?? []).map((prop) => prop.toLowerCase())])\n const patterns = [...EMPTY_PATTERNS, ...(options.extraEmptyPatterns ?? []).map((source) => new RegExp(source, 'i'))]\n\n const findings: RawFinding[] = []\n const reported = new Set<number>()\n\n const iterations = options.reportSectionZeroStates === true ? [] : listIterations(file.scan.masked)\n\n const report = (root: JsxElement, offset: number, copy: string, viaProp: string | null): void => {\n if (reported.has(root.start)) return\n reported.add(root.start)\n if (hasAction(file, root, actionTags, actionProps)) return\n if (options.reportSectionZeroStates !== true && labelsATitledSection(file, root)) return\n if (iterations.some((span) => root.start > span.start && root.start < span.end)) return\n findings.push({\n check: 'dead-end-empty-state',\n offset,\n message: `Empty state \"${clip(copy)}\" offers no next action${viaProp === null ? '' : ` (${viaProp})`}.`,\n remedy:\n 'Put the one thing the reader should do next inside this branch — a button, a link, or the control that creates the first item. If nothing can be done here, say why in the copy.',\n evidence: clip(copy),\n })\n }\n\n // Empty copy rendered as JSX text.\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'jsx-text') continue\n const text = segment.value.trim()\n if (!patterns.some((pattern) => pattern.test(text))) continue\n const element = elementAt(file.scan.elements, segment.start)\n if (element === null) continue\n report(branchRoot(element), segment.start, text, null)\n }\n\n // Empty copy handed to a component as props.\n for (const element of file.scan.elements) {\n const copyProp = element.attributes.find(\n (attribute) => EMPTY_COPY_PROPS.test(attribute.name) && attribute.value !== null,\n )\n if (!copyProp?.value) continue\n report(element, copyProp.start, copyProp.value, `via ${copyProp.name}`)\n }\n\n return findings.sort((left, right) => left.offset - right.offset)\n}\n\n/**\n * The outermost ancestor that shares this element's expression container — the\n * whole conditional branch, and nothing outside it.\n */\nfunction branchRoot(element: JsxElement): JsxElement {\n let root = element\n while (root.parent !== null && root.parent.containerStart === element.containerStart) root = root.parent\n return root\n}\n\n/**\n * The spans of every `.map(…)` callback in the file. A zero-state rendered\n * INSIDE one is a per-item placeholder — an empty kanban column, a deal with no\n * documents yet, a compliance row reading \"No findings.\" beside its own Run\n * button — and the screen around it is full. The screen-level empty state this\n * check exists for is never rendered once per row.\n */\nfunction listIterations(masked: string): { start: number; end: number }[] {\n const spans: { start: number; end: number }[] = []\n for (const match of masked.matchAll(/\\.\\s*map\\s*\\(/g)) {\n const open = (match.index ?? 0) + (match[0]?.length ?? 1) - 1\n const end = matchingParen(masked, open)\n if (end !== -1) spans.push({ start: open, end })\n }\n return spans\n}\n\nfunction matchingParen(masked: string, open: number): number {\n let depth = 0\n for (let i = open; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '(') depth++\n else if (ch === ')') {\n depth--\n if (depth === 0) return i + 1\n }\n }\n return -1\n}\n\n/**\n * Is this branch the zero-state of a titled section — a heading, then the\n * conditional that renders either the section's rows or the line saying there\n * are none? The heading is what makes it a section of a screen rather than the\n * screen, and a reader looking at a headed, empty section is oriented.\n */\nfunction labelsATitledSection(file: ScannedFile, root: JsxElement): boolean {\n let previous: JsxElement | null = null\n for (const element of file.scan.elements) {\n if (element.start >= root.start) break\n if (element.parent !== root.parent) continue\n previous = element\n }\n if (previous === null) return false\n const tag = previous.tag.split('.').pop() ?? previous.tag\n return HEADING_TAG.test(tag) || HEADING_SUFFIX.test(tag)\n}\n\n/** Does anything in this subtree let the reader act? */\nfunction hasAction(\n file: ScannedFile,\n root: JsxElement,\n actionTags: ReadonlySet<string>,\n actionProps: ReadonlySet<string>,\n): boolean {\n const end = root.end > root.start ? root.end : root.openEnd\n for (const element of file.scan.elements) {\n if (element.start < root.start) continue\n if (element.start >= end) break\n if (isActionTag(element.tag, actionTags)) return true\n if (\n element.attributes.some(\n (attribute) =>\n actionProps.has(attribute.name.toLowerCase()) || ACTION_PROP_SUFFIX.test(attribute.name),\n )\n ) {\n return true\n }\n }\n return false\n}\n\n/**\n * `button`/`a`/`Link`, anything named `…Button` / `…Link` / `…Cta`, and any\n * member expression ending in one (`Card.Button`). Component libraries rename\n * constantly; the suffix rule keeps the check from needing their catalogue.\n */\nfunction isActionTag(tag: string, actionTags: ReadonlySet<string>): boolean {\n const base = (tag.split('.').pop() ?? tag).toLowerCase()\n if (actionTags.has(base)) return true\n return /(button|link|cta|anchor|action)$/.test(base)\n}\n\nfunction clip(value: string, max = 72): string {\n const flat = value.replace(/\\s+/g, ' ').trim()\n return flat.length > max ? `${flat.slice(0, max - 1)}…` : flat\n}\n","/**\n * Filesystem side of the gate: walk a product's source, lex each file once, and\n * hand every check the same `ScannedFile`.\n *\n * Test files are excluded by default and that exclusion is load-bearing, not\n * tidiness: a test fixture deliberately contains the copy and the shapes the\n * checks hunt for (\"No results\", a silent catch, the word `payload`), so\n * scanning tests would make the gate loudest exactly where nothing ships.\n */\n\nimport { type Dirent, readFileSync, readdirSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { lineIndex, positionAt, scanSource, type ScannedSource, type SourcePosition } from './source'\n\n/** One file, lexed once, with its line index ready. */\nexport interface ScannedFile {\n /** Absolute path as walked. */\n readonly path: string\n /** Path as reported in findings — relative to cwd when it is inside it. */\n readonly display: string\n readonly text: string\n readonly scan: ScannedSource\n readonly lineStarts: readonly number[]\n positionAt(offset: number): SourcePosition\n}\n\nconst SOURCE_RE = /\\.(tsx?|jsx?|mjs|cjs)$/\nconst SKIP_DIRS = new Set([\n 'node_modules',\n '.git',\n 'dist',\n 'build',\n '.next',\n '.react-router',\n 'coverage',\n '.wrangler',\n '.turbo',\n])\n\n/**\n * Paths never scanned. Tests and fixtures contain the defects on purpose;\n * `.d.ts` files carry no copy; generated route types are not authored.\n */\nconst DEFAULT_IGNORE = [\n '.test.',\n '.spec.',\n '__tests__',\n '__fixtures__',\n '/fixtures/',\n '/tests/',\n '/test/',\n '.d.ts',\n '.stories.',\n '/+types/',\n]\n\n/** Recursively collect scannable files under `dir`. */\nfunction walkSources(dir: string, ignore: readonly string[] = []): string[] {\n let entries: Dirent[]\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n return []\n }\n const skip = [...DEFAULT_IGNORE, ...ignore]\n return entries\n .flatMap((entry) => {\n const full = join(dir, entry.name)\n if (entry.isDirectory()) return SKIP_DIRS.has(entry.name) ? [] : walkSources(full, ignore)\n return SOURCE_RE.test(entry.name) ? [full] : []\n })\n .filter((file) => !skip.some((needle) => file.includes(needle)))\n}\n\n/** Read and lex one file. Returns null when it cannot be read. */\nexport function scanFile(path: string): ScannedFile | null {\n let text: string\n try {\n text = readFileSync(path, 'utf8')\n } catch {\n return null\n }\n return buildScannedFile(path, text)\n}\n\n/** Lex an in-memory source — the shape every check test uses. */\nexport function buildScannedFile(path: string, text: string): ScannedFile {\n const scan = scanSource(text)\n const lineStarts = lineIndex(text)\n return {\n path,\n display: displayPath(path),\n text,\n scan,\n lineStarts,\n positionAt: (offset: number) => positionAt(lineStarts, offset),\n }\n}\n\n/** Lex every scannable file under `srcDirs`. */\nexport function scanSources(srcDirs: readonly string[], ignore: readonly string[] = []): ScannedFile[] {\n const files = srcDirs.flatMap((dir) => walkSources(dir, ignore))\n const unique = [...new Set(files)].sort()\n return unique.flatMap((path) => {\n const scanned = scanFile(path)\n return scanned ? [scanned] : []\n })\n}\n\n/** Path relative to cwd when it stays inside it, else the path as given. */\nfunction displayPath(file: string): string {\n const rel = relative(process.cwd(), file)\n return rel && !rel.startsWith('..') ? rel : file\n}\n\n/** One readable line of evidence: collapsed whitespace, clipped. */\nexport function evidenceOf(text: string, start: number, end: number, max = 100): string {\n const raw = text.slice(start, Math.min(end, start + max * 3)).replace(/\\s+/g, ' ').trim()\n return raw.length > max ? `${raw.slice(0, max - 1)}…` : raw\n}\n","/**\n * Check 5 — a capability with no door.\n *\n * Two deterministic engines shipped in this fleet with no way to reach them: a\n * contract redline that cites statutes, and a court-deadline calculator with 59\n * golden tests. Both correct, both routed, neither in the navigation and\n * neither linked from any screen. The only way to open them was to type the URL.\n * No test failed, because every test was about the engine.\n *\n * This check joins two things a product already has — its route table and its\n * navigation definition — and reports the routes that neither the navigation\n * nor any link in the source reaches.\n *\n * ── Matching, and why it is by STATIC SEGMENTS ───────────────────────────────\n *\n * Links are written against a base that is computed at runtime:\n *\n * route('contracts/redline', …) under route(':workspaceId', …) under route('app', …)\n * <Link to={`${base}/contracts/redline`}> base = `/app/${workspaceId}`\n *\n * Comparing strings finds nothing. So both sides are reduced to their STATIC\n * segments — parameters and `${…}` holes drop out — and a link reaches a route\n * when the link's segments are a suffix of the route's:\n *\n * route app/:workspaceId/contracts/redline → [app, contracts, redline]\n * link `${base}/contracts/redline` → [contracts, redline] ✓ suffix\n * link `${base}/contracts` → [contracts] ✗ (matches the parent, not this)\n *\n * The suffix rule is what makes the check usable without resolving `base`, and\n * the cost is a known blind spot: a detail route (`reviews/:id`) has the same\n * static segments as its list route, so a link to the list marks the detail\n * reachable. That is a missed defect, never a false alarm — the deliberate\n * direction for a gate that only survives if its reports are all real.\n *\n * ── Reachable FROM THE NAVIGATION, not merely linked ─────────────────────────\n *\n * A link is only a door if the screen holding it can itself be opened. The\n * shipped defect is an ISLAND: a contract list, a contract detail page and a\n * statute-citing redline engine, each linking the other two, and no navigation\n * entry pointing at any of them. Every route in it has an inbound link, so a\n * check that asks \"does a link exist?\" reports nothing at all — which is what\n * happened, and the redline shipped unreachable.\n *\n * So doors are resolved transitively from the navigation:\n *\n * - a nav file's path literals are roots;\n * - so is a link in a file that is NOT a route module (a shared component, a\n * header, an index route) — it could be rendered anywhere, and assuming it\n * is always available is the direction that removes findings rather than\n * inventing them;\n * - a link inside a ROUTE module counts only once that route is itself\n * reachable, and the pass repeats to a fixpoint.\n *\n * An island therefore reports every route in it, which is right: one nav entry\n * clears them all, and naming only the entry route would hide how much shipped\n * behind it.\n *\n * ── What is not a screen ─────────────────────────────────────────────────────\n *\n * `index()` and `layout()` add no path of their own. A route whose module is\n * not `.tsx` is a resource endpoint (the react-router convention) and is\n * skipped by default, as is anything under `ignore` (default `api/*`).\n */\n\nimport { buildScannedFile, evidenceOf, type ScannedFile } from '../scan'\nimport { readFileSync } from 'node:fs'\nimport type { RawFinding, ReachabilityOptions } from '../types'\n\n/** One route as declared, with its composed path. */\nexport interface RouteEntry {\n /** Full path from the root of the route table, no leading slash. */\n readonly path: string\n /** The route module, when the declaration names one. */\n readonly module: string | null\n /** Offset of the path literal in the route config, for file:line. */\n readonly offset: number\n /**\n * True when the declaration nests children. Such a route renders an Outlet\n * shell; the destination is its index child, whose path is the same string.\n * Asking a layout for its own door reports every product's `app` wrapper.\n */\n readonly isLayout: boolean\n}\n\n/** A path literal found in the source, reduced to what can be compared. */\ninterface LinkTarget {\n readonly raw: string\n readonly segments: readonly string[]\n}\n\nconst ROUTE_CALL_RE = /(?<![\\w$.])(route|index|layout|prefix)\\s*\\(/g\n\n/** A route MODULE, not a path — `routes/app.settings.tsx`. */\nconst MODULE_LITERAL = /\\.(tsx?|jsx?)$/\n\n/**\n * Attributes whose value navigates. The suffix rule matters: a shared shell\n * takes the destination as a PROP (`settingsHref={…}`), so an exact list would\n * miss every door a layout component opens — measured, on the one attribute\n * that made a product's Settings screen look orphaned.\n */\nconst LINK_ATTRIBUTES = new Set(['to', 'href', 'action', 'redirect'])\nconst LINK_ATTRIBUTE_SUFFIX = /(href|url|link|route|path)$/i\n\n/**\n * Calls whose first string argument is a destination. Matched on the full\n * dotted name OR its last segment, because the same navigation is written\n * `navigate(…)`, `router.push(…)` and `window.location.assign(…)`.\n */\nconst LINK_CALLS = new Set(['navigate', 'redirect', 'redirectdocument'])\nconst LINK_CALL_TAIL = new Set(['push', 'replace', 'assign', 'navigate', 'redirect'])\n\n/** `location.href = '/app/settings'` — navigation without a call or a prop. */\nconst LOCATION_ASSIGN_RE = /\\blocation\\s*\\.\\s*href\\s*=\\s*/g\n\n/**\n * Parse a `@react-router/dev/routes` config into composed route paths.\n *\n * Nesting is read from offset containment rather than from a grammar: a call\n * whose parentheses sit inside another call's is that call's child, which is\n * true of `route(p, m, [ route(…) ])` and needs no array bookkeeping.\n */\nexport function parseRouteConfig(file: ScannedFile): RouteEntry[] {\n const masked = file.scan.masked\n interface Call {\n readonly kind: string\n readonly start: number\n readonly end: number\n readonly args: readonly { value: string; start: number }[]\n }\n\n const calls: Call[] = []\n ROUTE_CALL_RE.lastIndex = 0\n for (const match of masked.matchAll(ROUTE_CALL_RE)) {\n const parenStart = (match.index ?? 0) + (match[0]?.length ?? 1) - 1\n const end = matchingParen(masked, parenStart)\n if (end === -1) continue\n const args = file.scan.segments\n .filter((segment) => segment.kind === 'string' && segment.start > parenStart && segment.end < end)\n .filter((segment) => topLevelArgument(masked, parenStart, segment.start))\n .map((segment) => ({ value: segment.value, start: segment.start }))\n calls.push({ kind: match[1] ?? '', start: match.index ?? 0, end, args })\n }\n\n const ancestorsOf = (call: Call): Call[] =>\n calls.filter((other) => other !== call && other.start < call.start && other.end > call.end)\n\n const entries: RouteEntry[] = []\n for (const call of calls) {\n if (call.kind !== 'route' && call.kind !== 'prefix') continue\n const own = call.args[0]\n if (own === undefined) continue\n // `route(pattern, 'routes/x.ts', …)` with a COMPUTED pattern puts the module\n // in first place. Its path is not in the source, so nothing here can decide\n // whether a door reaches it — reporting it would be a guess.\n if (MODULE_LITERAL.test(own.value)) continue\n const prefixParts = ancestorsOf(call)\n .filter((ancestor) => ancestor.kind === 'route' || ancestor.kind === 'prefix')\n .sort((left, right) => left.start - right.start)\n .map((ancestor) => ancestor.args[0]?.value ?? '')\n if (call.kind === 'prefix') continue\n entries.push({\n path: joinPath([...prefixParts, own.value]),\n module: call.args[1]?.value ?? null,\n offset: own.start,\n isLayout: calls.some((other) => other !== call && other.start > call.start && other.end < call.end),\n })\n }\n return entries\n}\n\n/**\n * Is this literal a top-level argument of the call, rather than a string nested\n * inside a child call or an object literal? Read by depth over the masked text.\n */\nfunction topLevelArgument(masked: string, parenStart: number, at: number): boolean {\n let depth = 0\n for (let i = parenStart; i < at; i++) {\n const ch = masked[i]\n if (ch === '(' || ch === '[' || ch === '{') depth++\n else if (ch === ')' || ch === ']' || ch === '}') depth--\n }\n return depth === 1\n}\n\n/** End of the statement starting at `from` — the next `;` or line break. */\nfunction endOfStatement(masked: string, from: number): number {\n for (let i = from; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === ';' || ch === '\\n') return i\n }\n return masked.length\n}\n\nfunction matchingParen(masked: string, open: number): number {\n let depth = 0\n for (let i = open; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '(') depth++\n else if (ch === ')') {\n depth--\n if (depth === 0) return i + 1\n }\n }\n return -1\n}\n\nfunction joinPath(parts: readonly string[]): string {\n return parts\n .flatMap((part) => part.split('/'))\n .map((part) => part.trim())\n .filter((part) => part.length > 0)\n .join('/')\n}\n\n/** The comparable segments of a path: statics only, params and holes dropped. */\nexport function staticSegments(path: string): string[] {\n return path\n .replace(/\\$\\{[^}]*\\}/g, '/*/')\n .split(/[/?#]/)\n .map((segment) => segment.trim())\n .filter((segment) => segment.length > 0 && !segment.startsWith(':') && segment !== '*' && !segment.startsWith('$'))\n}\n\n/**\n * Does this literal look like a destination? Leading `/`, no whitespace, at\n * least one separator.\n *\n * ── Why ANY path literal counts as a door ────────────────────────────────────\n *\n * A destination is often assembled before it is used:\n *\n * const tangleAuthUrl = hasRedirect ? `/auth/tangle/start?next=…` : '/auth/tangle/start'\n * <AuthPage tangleAuthUrl={tangleAuthUrl} />\n *\n * No attribute holds the literal and no call takes it, so an attribute-and-call\n * rule reports a route the sign-in page plainly links. Counting every path\n * literal makes the claim stronger, not weaker: \"no nav entry, no link, and no\n * literal in the whole source even names this path.\"\n *\n * Measured over two products at the moment this rule was adopted: it removed\n * the one remaining false positive and left all eight true positives standing\n * — the `/api/members` fetch does not mask the unreachable `app/:id/members`\n * screen, because a door must match the route's trailing segments and `api` is\n * not `app`.\n */\nfunction pathLike(value: string): boolean {\n const trimmed = value.trim()\n return trimmed.length > 1 && trimmed.startsWith('/') && /^\\/[\\w:$@.{}\\-/[\\]]+$/.test(trimmed)\n}\n\n/** Every path literal in one file that could navigate somewhere. */\nfunction linkTargets(file: ScannedFile): LinkTarget[] {\n const targets: LinkTarget[] = []\n const push = (raw: string): void => {\n const segments = staticSegments(raw)\n if (segments.length > 0) targets.push({ raw, segments })\n }\n\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'jsx-attribute' && segment.kind !== 'template') continue\n const attribute = segment.attribute\n if (attribute === undefined) continue\n if (LINK_ATTRIBUTES.has(attribute.toLowerCase()) || LINK_ATTRIBUTE_SUFFIX.test(attribute)) push(segment.value)\n }\n\n const masked = file.scan.masked\n const callRe = /(?<![\\w$.])([A-Za-z_$][\\w$.]*)\\s*\\(/g\n for (const match of masked.matchAll(callRe)) {\n const name = (match[1] ?? '').toLowerCase()\n const tail = name.split('.').pop() ?? name\n if (!LINK_CALLS.has(name) && !LINK_CALL_TAIL.has(tail)) continue\n const parenStart = (match.index ?? 0) + (match[0]?.length ?? 1) - 1\n const end = matchingParen(masked, parenStart)\n // Every chunk of the argument, not just the first: a destination is written\n // `\\`${base}/contracts/redline\\`` and the naming half comes after the hole.\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'string' && segment.kind !== 'template') continue\n if (segment.start < parenStart || (end !== -1 && segment.end > end)) continue\n push(segment.value)\n }\n }\n\n LOCATION_ASSIGN_RE.lastIndex = 0\n for (const match of masked.matchAll(LOCATION_ASSIGN_RE)) {\n const after = (match.index ?? 0) + (match[0]?.length ?? 0)\n const statementEnd = endOfStatement(masked, after)\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'string' && segment.kind !== 'template') continue\n if (segment.start < after || segment.start >= statementEnd) continue\n push(segment.value)\n }\n }\n\n for (const segment of file.scan.segments) {\n if (segment.kind === 'comment') continue\n if (pathLike(segment.value)) push(segment.value)\n }\n return targets\n}\n\n/**\n * Every path-shaped literal in a navigation definition. A nav file is named by\n * the product and is small, so every string that looks like a path counts —\n * being generous here can only REMOVE findings, and a nav entry written as\n * `path: '/filings'` or `href=\"/filings\"` must read the same way.\n */\nfunction navTargets(file: ScannedFile): LinkTarget[] {\n const targets: LinkTarget[] = [...linkTargets(file)]\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'string' && segment.kind !== 'template') continue\n const value = segment.value.trim()\n if (value.length === 0 || /\\s/.test(value)) continue\n if (!/^[/$]/.test(value) && !value.includes('/')) continue\n const segments = staticSegments(value)\n if (segments.length > 0) targets.push({ raw: value, segments })\n }\n return targets\n}\n\nexport interface ReachabilityInput {\n /** Every scanned product file — the source of in-source links. */\n readonly files: readonly ScannedFile[]\n readonly options: ReachabilityOptions\n}\n\nexport interface ReachabilityResult {\n readonly findings: readonly RawFinding[]\n /** The route config, lexed — so the runner can apply its suppressions. */\n readonly routeFile: ScannedFile | null\n readonly routeCount: number\n}\n\n/** Run the unreachable-capability check over a whole product. */\nexport function checkReachability({ files, options }: ReachabilityInput): ReachabilityResult {\n const routeFile = options.routeConfigFile ? readScanned(options.routeConfigFile) : null\n const declared: RouteEntry[] = routeFile\n ? parseRouteConfig(routeFile)\n : (options.routePaths ?? []).map((path) => ({ path, module: null, offset: 0, isLayout: false }))\n if (declared.length === 0) return { findings: [], routeFile, routeCount: 0 }\n\n const navFiles = (options.navFiles ?? []).map((path) => readScanned(path)).filter(isScanned)\n const navPaths = navFiles.flatMap((file) => navTargets(file))\n const navSet = new Set(navFiles.map((file) => file.path))\n\n const product = files.filter((file) => !navSet.has(file.path) && file.path !== routeFile?.path)\n const routeModules = indexRouteModules(declared, product)\n const freeDoors = product\n .filter((file) => !routeModules.has(file.path))\n .flatMap((file) => linkTargets(file))\n\n const doors = reachableDoors({ files: product, navPaths, freeDoors, routeModules })\n const ignore = options.ignore ?? ['api/*']\n const ignoreNonTsx = options.ignoreNonTsxRoutes ?? true\n\n const findings: RawFinding[] = []\n for (const entry of declared) {\n if (entry.path.length === 0) continue\n if (entry.isLayout) continue\n if (ignore.some((pattern) => matchesIgnore(entry.path, pattern))) continue\n if (ignoreNonTsx && entry.module !== null && !entry.module.endsWith('.tsx')) continue\n\n const target = staticSegments(entry.path)\n if (target.length === 0) continue\n if (doors.some((door) => isSuffix(target, door.segments))) continue\n\n findings.push({\n check: 'unreachable-capability',\n offset: entry.offset,\n message: `Route \"${entry.path}\" is reachable by neither the navigation nor any link in the source — only by typing the URL.`,\n remedy:\n 'Add it to the navigation, or link it from the screen a reader would look for it on. If it is deliberately unlisted (an internal tool, a deep link sent by email), suppress it with that reason.',\n evidence: routeFile ? evidenceOf(routeFile.text, entry.offset - 1, entry.offset + entry.path.length + 60, 90) : entry.path,\n })\n }\n\n return { findings, routeFile, routeCount: declared.length }\n}\n\nfunction isScanned(file: ScannedFile | null): file is ScannedFile {\n return file !== null\n}\n\n/**\n * Which scanned file implements which declared route. The route config names a\n * module relative to the app directory (`routes/app.workspace.contracts.tsx`)\n * and the scan walks from the product's source root, so the join is a path\n * suffix — no knowledge of the product's `appDirectory` needed.\n */\nfunction indexRouteModules(\n declared: readonly RouteEntry[],\n files: readonly ScannedFile[],\n): Map<string, RouteEntry[]> {\n const byFile = new Map<string, RouteEntry[]>()\n for (const entry of declared) {\n const module = entry.module\n if (module === null) continue\n const owner = files.find((file) => file.path === module || file.path.endsWith(`/${module}`))\n if (owner === undefined) continue\n const existing = byFile.get(owner.path)\n if (existing) existing.push(entry)\n else byFile.set(owner.path, [entry])\n }\n return byFile\n}\n\ninterface ReachabilityWalk {\n readonly files: readonly ScannedFile[]\n readonly navPaths: readonly LinkTarget[]\n readonly freeDoors: readonly LinkTarget[]\n readonly routeModules: ReadonlyMap<string, RouteEntry[]>\n}\n\n/**\n * Every door the reader can actually arrive at, walked out from the navigation.\n * A route module's links join the set only after something already in the set\n * reaches that route — which is what makes an island of mutually-linked screens\n * report instead of vouching for itself.\n */\nfunction reachableDoors({ files, navPaths, freeDoors, routeModules }: ReachabilityWalk): LinkTarget[] {\n const doors: LinkTarget[] = [...navPaths, ...freeDoors]\n const pending = files\n .filter((file) => routeModules.has(file.path))\n .map((file) => ({\n file,\n // A layout adds no path of its own and renders around every child, so it\n // opens as soon as anything is open at all.\n targets: (routeModules.get(file.path) ?? [])\n .filter((entry) => !entry.isLayout)\n .map((entry) => staticSegments(entry.path))\n .filter((parts) => parts.length > 0),\n }))\n\n let open = true\n while (open) {\n open = false\n for (let i = pending.length - 1; i >= 0; i--) {\n const candidate = pending[i]\n if (candidate === undefined) continue\n const reached =\n candidate.targets.length === 0 ||\n candidate.targets.some((target) => doors.some((door) => isSuffix(target, door.segments)))\n if (!reached) continue\n pending.splice(i, 1)\n doors.push(...linkTargets(candidate.file))\n open = true\n }\n }\n\n return doors\n}\n\nfunction readScanned(path: string): ScannedFile | null {\n try {\n return buildScannedFile(path, readFileSync(path, 'utf8'))\n } catch {\n return null\n }\n}\n\n/** Does the door's segment list end the route's? */\nfunction isSuffix(route: readonly string[], door: readonly string[]): boolean {\n if (door.length === 0 || door.length > route.length) return false\n const offset = route.length - door.length\n return door.every((segment, index) => segment.toLowerCase() === (route[offset + index] ?? '').toLowerCase())\n}\n\n/** `api/*` matches `api/anything`; an exact string matches itself. */\nfunction matchesIgnore(path: string, pattern: string): boolean {\n if (pattern.endsWith('/*')) return path === pattern.slice(0, -2) || path.startsWith(pattern.slice(0, -1))\n return path === pattern\n}\n","/**\n * Check 4 — a failure the reader never learns about.\n *\n * The shape: a `catch` that clears a loading flag, or returns a fallback, and\n * tells nobody. The request failed; the screen renders the empty state. The\n * reader is shown \"No documents yet\" for a network error, believes the answer,\n * and acts on it. That is worse than an error message, because it is a\n * confident wrong answer rather than a visible problem.\n *\n * ── What passes ──────────────────────────────────────────────────────────────\n *\n * The handler surfaces the failure (an error/notice state setter, a toast, an\n * injected `onError`), or rethrows / rejects so a boundary above can. Anything\n * else — an empty body, `setLoading(false)`, `return []`, a lone\n * `console.error` — is a finding. `console.error` is deliberately NOT a sink:\n * it writes to a console the reader does not have.\n *\n * ── Precision ────────────────────────────────────────────────────────────────\n *\n * Only handlers around I/O are read. A `try { JSON.parse(raw) } catch { return\n * {} }` is a legitimate fallback over a value already in hand, and reporting it\n * is exactly the noise that gets a gate switched off — so a `try` block with no\n * `await`, no request call and no `.then` is skipped entirely. A `.catch(…)`\n * handler is always on a promise, so it needs no such test.\n *\n * Three narrowings were MEASURED against two production verticals, where the\n * unnarrowed check reported 52 handlers of which 14 were real (27%) — a rate\n * that gets a check deleted, not fixed:\n *\n * 1. Only modules that can reach a browser are read ({@link READERLESS_PATHS}).\n * 31 of the 52 sat in `.server/` service modules and resource routes, where\n * the failure IS reported — to the operator's log — and the question of what\n * the reader is told belongs to the caller that renders. This is the single\n * largest noise class and it is a react-router CONVENTION, not a guess:\n * `.server` modules are compiled out of the client bundle.\n * 2. A handler that RESTORES the prior value has surfaced the failure: the\n * control the reader just moved visibly snaps back.\n * 3. A handler that RETURNS words — `return 'unknown'`, `new Response('Invalid\n * JSON', …)` — hands a distinguishable outcome to a caller that renders it.\n * Words inside a `console` call do not count, for the reason above.\n *\n * The cost is stated rather than hidden: narrowing 1 gives up the real\n * one-hop defect (a service returning `[]` on a network error, which a screen\n * then renders as \"nothing here\"). That is a caller-side finding this check\n * cannot see from the callee, and a product that wants it back passes\n * `readerlessPaths: []`.\n */\n\nimport { enclosingBlock } from '../source'\nimport type { ScannedFile } from '../scan'\nimport { evidenceOf } from '../scan'\nimport type { RawFinding, SilentFailureOptions } from '../types'\n\n/**\n * The catch body does something the reader can perceive: rethrows, rejects,\n * toasts, sets an error-shaped state, or RETURNS a failure value\n * (`fail(…)` / `failOutcome(…)` / `{ error: … }`) for a caller to render.\n */\nconst ERROR_SINK =\n /\\bthrow\\b|\\breject\\s*\\(|\\btoast\\b|\\bfail[A-Za-z]*\\s*\\(|\\b(set|show|render|display|report|surface|push|add|emit|on)[A-Za-z]*(error|failure|failed|problem|issue|notice|warning|message|banner|alert|toast)\\s*\\(|\\b(error|failure|message|notice)\\s*[:=][^=]/i\n\n/** `console.log/warn/error(…)` — writes to a console the reader does not have. */\nconst CONSOLE_CALL = /\\bconsole\\s*\\.\\s*[a-z]+\\s*\\([^()]*(\\([^()]*\\)[^()]*)*\\)/g\n\n/**\n * The handler put the value the reader was looking at back. The control snaps\n * back on screen, which IS the failure being reported — measured on a plan-mode\n * toggle and a settings switch in two products.\n */\nconst RESTORES_STATE = /\\b(set|restore|revert|roll)[A-Za-z]*\\s*\\(\\s*(prev|previous|original|before|last|old)[A-Za-z]*\\s*[,)]/i\n\n/**\n * The handler returns something with WORDS in it — `return 'unknown'`,\n * `return new Response('Invalid JSON', { status: 400 })`, a result object\n * carrying a summary — which is a distinguishable outcome for a caller to\n * render, not a silent one. Run over a body whose `console` calls have already\n * been removed, so words written to a log never count.\n */\nfunction returnsWords(bodyWithoutConsole: string): boolean {\n const at = bodyWithoutConsole.search(/\\breturn\\b/)\n return at !== -1 && /['\"`]/.test(bodyWithoutConsole.slice(at))\n}\n\n/**\n * I/O in the guarded block — what makes a failure worth surfacing.\n *\n * `localStorage` and `navigator` are deliberately NOT here. A storage write\n * that fails in private mode loses a preference, not an answer; the shipped\n * instance is a theme toggle whose choice applies immediately and only fails to\n * persist, and reporting it teaches a team that this check does not know what a\n * failure is.\n */\nconst IO_IN_TRY = /\\bawait\\b|\\.\\s*then\\s*\\(|\\bfetch\\s*\\(|\\bXMLHttpRequest\\b/\n\n/** Reading a body off something already in hand: `res.json()`, `req.text()`. */\nconst BODY_READ_AFTER_AWAIT = /^[\\s(]*[\\w$.\\s()]*?\\.\\s*(json|text|formData|arrayBuffer|blob)\\s*\\(\\s*\\)/\n\n/**\n * Is the guarded block ONLY a body parse? That is a fallback over bytes already\n * in hand, not a request that failed — the same rule {@link isRequestChain}\n * applies to `.catch`, applied to `try`/`catch`, because\n * `try { body = await request.clone().json() } catch { body = {} }` is the\n * shipped shape four times across two products and none of them is a defect.\n */\nfunction parseOnlyTry(tryBody: string): boolean {\n if (/\\bfetch\\s*\\(|\\.\\s*then\\s*\\(|\\bXMLHttpRequest\\b/.test(tryBody)) return false\n const awaits = [...tryBody.matchAll(/\\bawait\\b/g)]\n if (awaits.length === 0) return false\n return awaits.every((match) => BODY_READ_AFTER_AWAIT.test(tryBody.slice((match.index ?? 0) + 'await'.length)))\n}\n\n/**\n * Paths whose modules cannot render. `.server` is react-router's server-only\n * convention (compiled out of the client bundle) and `routes/api.` its resource\n * -route naming; a `catch` in either reports to an operator, not to a reader.\n */\nexport const READERLESS_PATHS: readonly string[] = ['/.server/', '/routes/api.']\n\nconst CATCH_RE = /\\bcatch\\s*(?:\\(([^)]*)\\)\\s*)?\\{/g\nconst PROMISE_CATCH_RE = /\\.\\s*catch\\s*\\(/g\n\n/** Run the silent-failure check over one lexed file. */\nexport function checkSilentFailure(file: ScannedFile, options: SilentFailureOptions = {}): RawFinding[] {\n const extraSinks = (options.extraErrorSinks ?? []).map((sink) => sink.toLowerCase())\n const readerless = options.readerlessPaths ?? READERLESS_PATHS\n if (readerless.some((marker) => file.path.includes(marker))) return []\n\n const masked = file.scan.masked\n const findings: RawFinding[] = []\n\n const surfaced = (body: string): boolean => {\n if (ERROR_SINK.test(body) || RESTORES_STATE.test(body)) return true\n if (returnsWords(body.replace(CONSOLE_CALL, ' '))) return true\n return extraSinks.some((sink) => body.toLowerCase().includes(sink))\n }\n\n CATCH_RE.lastIndex = 0\n for (const match of masked.matchAll(CATCH_RE)) {\n const braceAt = (match.index ?? 0) + (match[0]?.length ?? 1) - 1\n const block = blockFrom(masked, braceAt)\n if (block === null) continue\n const body = masked.slice(block.start + 1, block.end - 1)\n if (surfaced(body)) continue\n // The caught error carried outward — `return failOutcome(err(e))` — is\n // surfacing it through a value this check cannot follow, so it passes.\n // Carrying it into `console.warn(e)` and nowhere else is not.\n if (carriesError(body, match[1])) continue\n\n const guarded = tryBlockBefore(masked, match.index ?? 0)\n if (guarded === null || !IO_IN_TRY.test(guarded)) continue\n if (parseOnlyTry(guarded)) continue\n\n findings.push({\n check: 'silent-failure',\n offset: match.index ?? 0,\n message:\n body.trim().length === 0\n ? 'This catch swallows the failure entirely — the request failed and the screen will render as if it returned nothing.'\n : 'This catch never surfaces the failure — the reader sees an empty result, not a problem they can act on.',\n remedy:\n 'Set an error state this screen renders (with a retry), or rethrow so a boundary above can. A console line is not a sink — the reader has no console.',\n evidence: evidenceOf(file.text, match.index ?? 0, block.end, 80),\n })\n }\n\n PROMISE_CATCH_RE.lastIndex = 0\n for (const match of masked.matchAll(PROMISE_CATCH_RE)) {\n const parenAt = (match.index ?? 0) + (match[0]?.length ?? 1) - 1\n const end = matchingParen(masked, parenAt)\n if (end === -1) continue\n const body = masked.slice(parenAt + 1, end - 1)\n if (body.trim().length === 0) continue\n if (surfaced(body)) continue\n if (!isRequestChain(masked, match.index ?? 0)) continue\n // `.catch(handleFailure)` hands the failure to a named function this check\n // cannot follow; only an inline handler is read.\n if (!/=>|\\bfunction\\b/.test(body)) continue\n\n findings.push({\n check: 'silent-failure',\n offset: match.index ?? 0,\n message: 'This .catch() handler discards the failure — the promise rejects and nothing on screen changes.',\n remedy:\n 'Surface it: set the error state this view renders, or rethrow. If the failure is genuinely ignorable, suppress with a reason saying why.',\n evidence: evidenceOf(file.text, match.index ?? 0, end, 80),\n })\n }\n\n return findings.sort((left, right) => left.offset - right.offset)\n}\n\n/**\n * Is the promise this `.catch` is attached to a REQUEST?\n *\n * The dominant `.catch` in this fleet is `await res.json().catch(() => ({}))` —\n * 31 of 39 in one product — and it is not a legibility defect: it is a fallback\n * for a body that may not be JSON, on a response whose status the caller\n * already read. Reporting those buries the ones that matter. So the chain must\n * start at a request: `fetch(url).then(…).catch(() => null)` hides a network\n * failure and is reported; a parse fallback is not.\n *\n * The chain is walked BACKWARDS as an expression, not scanned back to the\n * nearest line break. That is the difference between finding the defect and\n * not: the shipped shape is written one call per line —\n *\n * fetch('/api/templates')\n * .then((r) => r.json())\n * .then((data) => { setTemplates(data.templates ?? []); setLoading(false) })\n * .catch(() => setLoading(false))\n *\n * — so a line-anchored scan sees only whitespace before `.catch`, finds no\n * `fetch`, and reports nothing. Two production screens (a template library and\n * a billing page) render a network failure as an empty list for exactly that\n * reason, and both were invisible to the line-anchored rule.\n */\nfunction isRequestChain(masked: string, catchAt: number): boolean {\n const chain = masked.slice(chainStart(masked, catchAt), catchAt)\n if (!/\\bfetch\\s*\\(/.test(chain)) return false\n return !/\\.\\s*(json|text|blob|arrayBuffer|formData)\\s*\\(\\s*\\)\\s*$/.test(chain)\n}\n\n/**\n * Walk backwards over a member/call chain to the identifier it starts at,\n * jumping over balanced `(…)` / `[…]` so arguments, arrow bodies and line\n * breaks inside the chain are stepped over rather than terminating the walk.\n */\nfunction chainStart(masked: string, from: number): number {\n let at = from\n for (;;) {\n // Trim at the TOP of every step, not once at the start: a fluent chain puts\n // a line break between `)` and the next `.`, and a walk that only trims on\n // entry stops at the first of them.\n at = trimmedEnd(masked, at)\n if (at <= 0) return 0\n const ch = masked[at - 1]\n if (ch === ')' || ch === ']') {\n const open = matchingOpenBefore(masked, at - 1)\n if (open === -1) return at\n at = trimmedEnd(masked, open)\n continue\n }\n if (ch !== undefined && /[\\w$]/.test(ch)) {\n let start = at - 1\n while (start > 0 && /[\\w$]/.test(masked[start - 1] ?? '')) start--\n const beforeIdent = trimmedEnd(masked, start)\n if (beforeIdent > 0 && masked[beforeIdent - 1] === '.') {\n at = beforeIdent - 1\n continue\n }\n return start\n }\n return at\n }\n}\n\n/** The largest index `i <= from` whose preceding character is not whitespace. */\nfunction trimmedEnd(masked: string, from: number): number {\n let at = from\n while (at > 0 && /\\s/.test(masked[at - 1] ?? '')) at--\n return at\n}\n\n/** Index of the `(` or `[` matching the closer at `close`, or -1. */\nfunction matchingOpenBefore(masked: string, close: number): number {\n const closer = masked[close]\n const opener = closer === ')' ? '(' : '['\n let depth = 0\n for (let i = close; i >= 0; i--) {\n const ch = masked[i]\n if (ch === closer) depth++\n else if (ch === opener) {\n depth--\n if (depth === 0) return i\n }\n }\n return -1\n}\n\n/**\n * Does the body use the caught binding somewhere other than a console call?\n * A destructuring or typed binding (`catch (e: unknown)`) reduces to its name.\n */\nfunction carriesError(body: string, binding: string | undefined): boolean {\n const name = /^[A-Za-z_$][\\w$]*/.exec((binding ?? '').trim())?.[0]\n if (name === undefined) return false\n const withoutConsole = body.replace(CONSOLE_CALL, ' ')\n return new RegExp(`(?<![\\\\w$])${name}(?![\\\\w$])`).test(withoutConsole)\n}\n\n/** The `{ … }` block whose opening brace is at `braceAt`. */\nfunction blockFrom(masked: string, braceAt: number): { start: number; end: number } | null {\n let depth = 0\n for (let i = braceAt; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '{') depth++\n else if (ch === '}') {\n depth--\n if (depth === 0) return { start: braceAt, end: i + 1 }\n }\n }\n return null\n}\n\nfunction matchingParen(masked: string, open: number): number {\n let depth = 0\n for (let i = open; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '(') depth++\n else if (ch === ')') {\n depth--\n if (depth === 0) return i + 1\n }\n }\n return -1\n}\n\n/**\n * The body of the `try` this `catch` belongs to. Returns null when the catch is\n * not preceded by a try block (a `.catch` was matched, or the source is\n * malformed) — the caller treats that as \"not I/O\" and skips.\n */\nfunction tryBlockBefore(masked: string, catchAt: number): string | null {\n const before = masked.slice(0, catchAt).trimEnd()\n if (!before.endsWith('}')) return null\n const block = enclosingBlock(masked, before.length - 1)\n if (block === null) return null\n const head = masked.slice(Math.max(0, block.start - 8), block.start)\n if (!/\\btry\\s*$/.test(head)) return null\n return masked.slice(block.start, block.end)\n}\n","/**\n * Check 3 — success reported before the response was read.\n *\n * The shipped defect: a Settings page that answered \"Saved\" to a 404. `fetch`\n * resolves on 404 — it only rejects on a transport failure — so a handler that\n * awaits it and then celebrates has not checked anything. The reader is told\n * their change is stored; it is not; nothing in the UI ever says otherwise.\n *\n * ── What is required for a pass ──────────────────────────────────────────────\n *\n * Somewhere in the same function body, the response is INSPECTED: `res.ok`,\n * `res.status`, a destructured `{ ok }`, or a guard call the product names in\n * `success.okGuards`. Reading `await res.json()` is not inspection — a 404 body\n * parses fine.\n *\n * Two failing shapes, reported with different messages because the fixes\n * differ:\n *\n * 1. awaited but unchecked — `await fetch(url, {…}); toast.success('Saved')`\n * 2. never awaited — `fetch(url, {…}); setSaved(true)`\n *\n * ── Precision ────────────────────────────────────────────────────────────────\n *\n * Scope is the enclosing FUNCTION body, not the file: a component with a fetch\n * in one handler and a success in another must not report. The trigger is\n * narrow on both ends — only calls the product declares as HTTP (default:\n * `fetch`, which is the only one in the standard library that resolves on a\n * failed request), and only success signals that are unambiguous: `toast.success`,\n * a `set…Saved/Success/Done/Sent/Submitted(true)` setter, or a status setter\n * given a success word. A wrapper that throws on a bad status is correct by\n * construction and is not a default trigger; a wrapper that does NOT throw is\n * the same bug one level down, so a product wraps `fetch` by adding its wrapper\n * to `httpCalls`.\n */\n\nimport { enclosingFunctionBlock } from '../source'\nimport type { ScannedFile } from '../scan'\nimport { evidenceOf } from '../scan'\nimport type { RawFinding, SuccessOptions } from '../types'\n\n/** Callees that resolve on a failed request instead of throwing. */\nconst DEFAULT_HTTP_CALLS: readonly string[] = ['fetch']\n\n/** `toast.success(…)` and friends: the reader has been told it worked. */\nconst SUCCESS_CALLS = new Set(['toast.success', 'toast.ok', 'notifySuccess'])\n\n/** `setSaved(true)`, `setSubmitted(true)`, `setIsDone(true)` … */\nconst SUCCESS_SETTER = /^set[A-Za-z]*(saved|success|succeeded|done|complete|completed|sent|submitted|confirmed)$/i\n\n/** A status setter is a success signal only when its argument says so. */\nconst STATUS_SETTER = /^set[A-Za-z]*(status|state|phase|stage|message|notice)$/i\nconst SUCCESS_WORD = /^(saved|success|succeeded|done|sent|complete|completed|updated|created|ok)\\b/i\n\n/** The response was read for its outcome, not just its body. */\nconst INSPECTS_RESPONSE = /\\.\\s*(ok|status|statusText)\\b|\\{[^}\\n]*\\b(ok|status)\\b[^}\\n]*\\}\\s*=/\n\nconst CALL_RE = /(?<![\\w$.])((?:new\\s+)?[A-Za-z_$][\\w$.]*)\\s*\\(/g\n\ninterface CallSite {\n readonly name: string\n /** Offset of the callee's first character. */\n readonly start: number\n /** Offset of the `(`. */\n readonly parenStart: number\n /** Offset just past the matching `)`, or -1 when unbalanced. */\n readonly parenEnd: number\n}\n\n/** Every call site in one file, read off the MASKED text so strings can't match. */\nfunction callSites(masked: string): CallSite[] {\n const sites: CallSite[] = []\n CALL_RE.lastIndex = 0\n for (const match of masked.matchAll(CALL_RE)) {\n const name = (match[1] ?? '').replace(/^new\\s+/, '')\n const start = match.index ?? 0\n const parenStart = start + (match[0]?.length ?? 1) - 1\n sites.push({ name, start, parenStart, parenEnd: matchingParen(masked, parenStart) })\n }\n return sites\n}\n\nfunction matchingParen(masked: string, open: number): number {\n let depth = 0\n for (let i = open; i < masked.length; i++) {\n const ch = masked[i]\n if (ch === '(') depth++\n else if (ch === ')') {\n depth--\n if (depth === 0) return i + 1\n }\n }\n return -1\n}\n\n/** Run the unchecked-success check over one lexed file. */\nexport function checkUncheckedSuccess(file: ScannedFile, options: SuccessOptions = {}): RawFinding[] {\n const httpCalls = new Set([...DEFAULT_HTTP_CALLS, ...(options.httpCalls ?? [])].map((call) => call.toLowerCase()))\n const okGuards = new Set((options.okGuards ?? []).map((guard) => guard.toLowerCase()))\n const extraSignals = new Set((options.extraSuccessSignals ?? []).map((signal) => signal.toLowerCase()))\n const masked = file.scan.masked\n\n const sites = callSites(masked)\n const requests = sites.filter((site) => httpCalls.has(site.name.toLowerCase()))\n if (requests.length === 0) return []\n\n const findings: RawFinding[] = []\n const reported = new Set<number>()\n\n for (const request of requests) {\n const scope = enclosingFunctionBlock(masked, request.start) ?? { start: 0, end: masked.length }\n if (reported.has(scope.start)) continue\n\n const body = masked.slice(scope.start, scope.end)\n if (INSPECTS_RESPONSE.test(body)) continue\n if (sites.some((site) => okGuards.has(site.name.toLowerCase()) && within(site.start, scope))) continue\n\n const signal = sites.find((site) => within(site.start, scope) && isSuccessSignal(file, site, extraSignals))\n if (!signal) continue\n\n reported.add(scope.start)\n const awaited = isAwaited(masked, request.start) || isChained(masked, request.parenEnd)\n findings.push({\n check: 'unchecked-success',\n offset: signal.start,\n message: awaited\n ? `\"${signal.name}(…)\" reports success, but nothing in this function reads the response's ok/status — ${request.name} resolves on a 404 as happily as on a 200.`\n : `\"${signal.name}(…)\" reports success before ${request.name}(…) has settled — the request is not awaited, so the outcome cannot be known yet.`,\n remedy: awaited\n ? `Check the response first: const res = await ${request.name}(…); if (!res.ok) { show the failure } else { ${signal.name}(…) }.`\n : `Await the request, then branch on res.ok. If it is deliberately fire-and-forget, say \"sending\" rather than \"sent\".`,\n evidence: evidenceOf(file.text, lineStart(file, signal.start), signal.parenEnd > 0 ? signal.parenEnd : signal.start),\n })\n }\n\n return findings\n}\n\nfunction within(offset: number, scope: { start: number; end: number }): boolean {\n return offset >= scope.start && offset < scope.end\n}\n\nfunction lineStart(file: ScannedFile, offset: number): number {\n const { line } = file.positionAt(offset)\n return file.lineStarts[line - 1] ?? offset\n}\n\n/** Is this call one that tells the reader the operation worked? */\nfunction isSuccessSignal(file: ScannedFile, site: CallSite, extraSignals: ReadonlySet<string>): boolean {\n const name = site.name\n if (SUCCESS_CALLS.has(name) || extraSignals.has(name.toLowerCase())) return true\n const argument = firstArgument(file, site)\n if (SUCCESS_SETTER.test(name)) return argument.literal === null ? argument.code === 'true' : true\n if (STATUS_SETTER.test(name)) return argument.literal !== null && SUCCESS_WORD.test(argument.literal.trim())\n return false\n}\n\n/** The first argument as written: its string value when literal, else its code. */\nfunction firstArgument(file: ScannedFile, site: CallSite): { literal: string | null; code: string } {\n const literal = file.scan.segments.find(\n (segment) =>\n (segment.kind === 'string' || segment.kind === 'template') &&\n segment.start > site.parenStart &&\n (site.parenEnd === -1 || segment.end <= site.parenEnd),\n )\n const code = file.scan.masked\n .slice(site.parenStart + 1, site.parenEnd > 0 ? site.parenEnd - 1 : site.parenStart + 40)\n .trim()\n // A literal only counts as THE first argument when no code precedes it. The\n // quote or backtick opening it is not code — the lexer blanks a literal's\n // VALUE and leaves its delimiter standing.\n const literalIsFirst =\n literal !== undefined &&\n file.scan.masked\n .slice(site.parenStart + 1, literal.start)\n .replace(/['\"`]/g, '')\n .trim() === ''\n return { literal: literalIsFirst && literal ? literal.value : null, code }\n}\n\nfunction isAwaited(masked: string, callStart: number): boolean {\n return /\\bawait\\s*$/.test(masked.slice(Math.max(0, callStart - 12), callStart))\n}\n\nfunction isChained(masked: string, parenEnd: number): boolean {\n if (parenEnd <= 0) return false\n return /^\\s*\\.\\s*(then|catch|finally)\\b/.test(masked.slice(parenEnd, parenEnd + 24))\n}\n","/**\n * Check 1 — engineering vocabulary on screen.\n *\n * The defect: a word from the codebase reaches the reader. Shipped instances\n * include \"materialized\" inside a user-facing error, a column of `sourceKind`,\n * and a chip reading `undefined`. Nobody decided to say those words; they leaked\n * because the label and the field name were the same string.\n *\n * ── Precision over recall, deliberately ──────────────────────────────────────\n *\n * A vocabulary gate lives or dies on false positives: one bad report and the\n * check is disabled, after which it guards nothing. `grep -i artifact` over one\n * product's `apps/web/src` returns 11 hits, all of them imports, prop names or\n * doc comments — a checker that reports those is deleted in a week.\n *\n * So this check only reads positions the lexer PROVES are copy, in two tiers\n * that are ON by default:\n *\n * 1. JSX text — `<p>No artifact yet</p>`. Unambiguous.\n * 2. A JSX attribute value, when the attribute is in {@link COPY_KEYS}. An\n * allowlist, so `className`, `data-*`, `aria-*`, `id`, `href` and every\n * other internal attribute are excluded by construction rather than by a\n * denylist that goes stale.\n * 3. The first argument of a call in {@link COPY_CALLS} — `toast.error('…')`,\n * `new Error('…')`, `setError('…')`. This is the tier that catches the\n * flagship defect: \"materialization\" reached a reader from a `new Error`\n * in a server module, not from a component.\n *\n * And ONE tier that is off by default, `includeObjectCopy`:\n *\n * 4. A string or template filling an object key named in {@link COPY_KEYS}\n * (`emptyTitle: '…'`, `description: '…'`).\n *\n * Tier 4 is off because it was MEASURED as the false-positive tier. Over two\n * production verticals it produced findings on a system prompt (`prompt:` in an\n * agent profile), an MCP tool description the model reads, and the body of a\n * legal document template where \"Records\" is a term of the drafted document —\n * none of them on any screen. A key named `description` is model-facing about\n * as often as it is reader-facing, and a checker that cannot tell them apart\n * must not be the one that fails the build. Products whose data modules really\n * do hold UI copy turn it on.\n *\n * Everything else — a bare string in code, an import specifier, a comment, an\n * identifier, a test file — is not read at all. The cost is real recall: copy\n * assembled through a variable (`const msg = base + suffix`) is invisible here,\n * and no lexer can see it. That is the trade this check makes on purpose.\n */\n\nimport type { ScannedFile } from '../scan'\nimport type { SourceSegment } from '../source'\nimport type { BannedTerm, RawFinding, VocabularyOptions } from '../types'\n\n/**\n * The default list. Every entry has shipped to a real screen in this fleet or\n * its verticals, and every one carries the sentence that replaces it — a gate\n * that only says \"don't\" leaves the author to guess.\n */\nexport const DEFAULT_BANNED_TERMS: readonly BannedTerm[] = [\n { term: 'materialize', instead: 'say what the reader gets: \"your documents are ready\"' },\n { term: 'materialized', instead: 'say what the reader gets: \"your documents are ready\"' },\n { term: 'materializing', instead: 'say what is happening: \"getting your documents ready\"' },\n { term: 'materialization', instead: 'say what is happening: \"getting your documents ready\"' },\n { term: 'fact', instead: 'name the thing: \"the figure we found\", \"the wage entry\"' },\n { term: 'facts', instead: 'name the things: \"the figures we found\", \"wage entries\"' },\n { term: 'conflict', instead: 'say what disagrees: \"two documents report different wages\"' },\n { term: 'conflicts', instead: 'say what disagrees: \"two documents report different wages\"' },\n { term: 'proposed', instead: 'say who acts next: \"needs your approval\"' },\n { term: 'workspace', instead: 'name the container the reader recognises: \"account\", \"client\", \"matter\"' },\n { term: 'record', instead: 'name the domain object: \"return\", \"matter\", \"contact\"' },\n { term: 'records', instead: 'name the domain objects: \"returns\", \"matters\", \"contacts\"' },\n { term: 'artifact', instead: 'name the deliverable: \"return\", \"redline\", \"brief\"' },\n { term: 'artifacts', instead: 'name the deliverables: \"returns\", \"redlines\", \"briefs\"' },\n { term: 'work product', instead: 'name the deliverable the reader asked for' },\n { term: 'OCR', instead: 'say what happened: \"we read your scan\"' },\n { term: 'extraction', instead: 'say what happened: \"what we found in your documents\"' },\n { term: 'superseded', instead: '\"replaced by a newer version\"' },\n { term: 'sourceKind', instead: 'an internal field name — write the label the reader reads' },\n { term: 'itemKey', instead: 'an internal field name — write the label the reader reads' },\n { term: 'payload', instead: 'name what was sent: \"your answers\", \"the document\"' },\n { term: 'null', instead: 'a value the code failed to fill — render the real value or written fallback copy' },\n { term: 'undefined', instead: 'a value the code failed to fill — render the real value or written fallback copy' },\n]\n\n/**\n * Attributes and object keys whose string value is copy. An allowlist: an\n * attribute that is not here is never read, which is how `aria-label`,\n * `className`, `data-testid` and `href` stay out without being enumerated.\n */\nexport const COPY_KEYS: readonly string[] = [\n 'title',\n 'label',\n 'placeholder',\n 'alt',\n 'description',\n 'heading',\n 'subheading',\n 'subtitle',\n 'message',\n 'tooltip',\n 'caption',\n 'summary',\n 'hint',\n 'helper',\n 'helperText',\n 'error',\n 'errorMessage',\n 'emptyTitle',\n 'emptyDescription',\n 'emptyLabel',\n 'emptyMessage',\n 'emptyText',\n 'cta',\n 'ctaLabel',\n 'confirmLabel',\n 'cancelLabel',\n 'submitLabel',\n 'actionLabel',\n 'buttonLabel',\n 'headline',\n 'copy',\n 'note',\n 'notice',\n 'warning',\n 'question',\n]\n\n/** Calls whose first string argument reaches the reader. */\nexport const COPY_CALLS: readonly string[] = [\n 'toast',\n 'toast.success',\n 'toast.error',\n 'toast.info',\n 'toast.warning',\n 'toast.message',\n 'alert',\n 'confirm',\n 'notify',\n 'Error',\n 'setError',\n 'setErrorMessage',\n 'setMessage',\n 'setNotice',\n 'setWarning',\n]\n\ninterface CompiledTerm {\n readonly term: BannedTerm\n readonly re: RegExp\n}\n\nfunction compile(terms: readonly BannedTerm[]): CompiledTerm[] {\n return terms.map((term) => ({\n term,\n // Whitespace in a term matches any run of whitespace, so \"work product\"\n // still matches across a wrapped line of JSX text.\n re: new RegExp(`(?<![\\\\w-])${escape(term.term).replace(/\\\\?\\s+/g, '\\\\s+')}(?![\\\\w-])`, 'gi'),\n }))\n}\n\nfunction escape(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n\n/** Run the vocabulary check over one lexed file. */\nexport function checkVocabulary(file: ScannedFile, options: VocabularyOptions = {}): RawFinding[] {\n const allow = new Set((options.allowTerms ?? []).map((term) => term.toLowerCase()))\n const base = options.terms ?? DEFAULT_BANNED_TERMS\n const terms = compile(\n [...base, ...(options.extraTerms ?? [])].filter((entry) => !allow.has(entry.term.toLowerCase())),\n )\n const copyKeys = new Set([...COPY_KEYS, ...(options.extraCopyKeys ?? [])].map((key) => key.toLowerCase()))\n const copyCalls = new Set([...COPY_CALLS, ...(options.extraCopyCalls ?? [])].map((call) => call.toLowerCase()))\n\n const findings: RawFinding[] = []\n for (const segment of file.scan.segments) {\n const visible = visibleCopy(file, segment, {\n copyKeys,\n copyCalls,\n includeObjectCopy: options.includeObjectCopy === true,\n })\n if (visible === null) continue\n\n for (const { term, re } of terms) {\n re.lastIndex = 0\n for (const match of segment.value.matchAll(re)) {\n const offset = segment.start + (match.index ?? 0)\n findings.push({\n check: 'engineering-vocabulary',\n offset,\n message: `\"${match[0]}\" is a word from the codebase, on screen in ${visible}.`,\n remedy: `Write what the reader needs: ${term.instead}.`,\n evidence: segment.value.replace(/\\s+/g, ' ').trim().slice(0, 100),\n })\n }\n }\n }\n return findings\n}\n\ninterface VisibilityContext {\n readonly copyKeys: ReadonlySet<string>\n readonly copyCalls: ReadonlySet<string>\n readonly includeObjectCopy: boolean\n}\n\n/**\n * Is this segment copy, and if so what kind? Returns a short description used\n * in the message, or null when the segment is code the reader never sees.\n */\nfunction visibleCopy(file: ScannedFile, segment: SourceSegment, context: VisibilityContext): string | null {\n const { kind, attribute, start } = segment\n if (kind === 'comment') return null\n if (kind === 'jsx-text') return 'rendered text'\n\n const named = attribute !== undefined && context.copyKeys.has(attribute.toLowerCase())\n // A JSX attribute — including one filled by a template literal — is copy only\n // when the attribute itself is on the allowlist.\n if (kind === 'jsx-attribute') return named ? `the ${attribute} attribute` : null\n if (named && segment.tag !== undefined) return `the ${attribute} attribute`\n\n return codeContext(file, start, context)\n}\n\n/**\n * Classify a string/template literal by the code immediately before it, read\n * off the MASKED source so a lookalike inside another string cannot match.\n */\nfunction codeContext(file: ScannedFile, start: number, context: VisibilityContext): string | null {\n const from = Math.max(0, start - 90)\n const before = file.scan.masked.slice(from, Math.max(from, start - 1))\n\n const call = /(?:new\\s+)?([A-Za-z_$][\\w$.]*)\\s*\\(\\s*$/.exec(before)\n if (call?.[1] && context.copyCalls.has(call[1].toLowerCase())) return `${call[1]}(…)`\n\n if (!context.includeObjectCopy) return null\n const key = /([A-Za-z_$][\\w$]*)\\s*[:=]\\s*$/.exec(before)\n if (key?.[1] && context.copyKeys.has(key[1].toLowerCase())) return `the ${key[1]} value`\n\n return null\n}\n","/**\n * The vocabulary of the legibility gate: what a finding is, what a suppression\n * is, and what a product configures.\n *\n * Kept in its own module so the checks, the report formatter and the bin all\n * agree on one shape, and so a consumer can import the types without pulling in\n * `node:fs`.\n */\n\n/** The checks this gate runs. Each is individually suppressible, by name. */\nexport type LegibilityCheckId =\n /** Words on screen that belong to the codebase, not to the reader. */\n | 'engineering-vocabulary'\n /** An empty/zero state whose subtree offers no next action. */\n | 'dead-end-empty-state'\n /** A success state set without inspecting the response that would deny it. */\n | 'unchecked-success'\n /** A `catch` that neither surfaces the failure nor rethrows it. */\n | 'silent-failure'\n /** A route no navigation entry and no in-source link can reach. */\n | 'unreachable-capability'\n /** A suppression comment that names a check but gives no reason. */\n | 'suppression-without-reason'\n\nexport const LEGIBILITY_CHECKS: readonly LegibilityCheckId[] = [\n 'engineering-vocabulary',\n 'dead-end-empty-state',\n 'unchecked-success',\n 'silent-failure',\n 'unreachable-capability',\n 'suppression-without-reason',\n]\n\n/** One defect, at one place, with the fix named. */\nexport interface LegibilityFinding {\n readonly check: LegibilityCheckId\n /** Path as reported — relative to the working directory when it is inside it. */\n readonly file: string\n /** 1-based. */\n readonly line: number\n /** 1-based. */\n readonly column: number\n /** What is wrong, in one sentence a reviewer can act on. */\n readonly message: string\n /** What to do about it. Every finding carries one; a finding without a fix is a complaint. */\n readonly remedy: string\n /** The offending source, trimmed to one readable line. */\n readonly evidence: string\n}\n\n/** A suppression that was honoured, with the reason its author wrote. */\nexport interface LegibilitySuppression {\n readonly check: LegibilityCheckId\n readonly reason: string\n readonly file: string\n readonly line: number\n}\n\nexport interface LegibilityReport {\n readonly ok: boolean\n readonly findings: readonly LegibilityFinding[]\n /** Honoured suppressions — printed, never silent. */\n readonly suppressed: readonly LegibilitySuppression[]\n readonly filesScanned: number\n readonly checksRun: readonly LegibilityCheckId[]\n}\n\n/** A banned term plus the sentence that replaces it. */\nexport interface BannedTerm {\n /** Matched case-insensitively at word boundaries against visible copy. */\n readonly term: string\n /** What to write instead — printed with the finding. */\n readonly instead: string\n}\n\nexport interface VocabularyOptions {\n /** Replaces the default list outright. */\n readonly terms?: readonly BannedTerm[]\n /** Added to the default list — the common case for a product's own jargon. */\n readonly extraTerms?: readonly BannedTerm[]\n /** Removed from the default list, for a word that is genuinely the reader's. */\n readonly allowTerms?: readonly string[]\n /**\n * Additional JSX attributes / object keys whose string value is user-visible\n * copy (the defaults cover `title`, `label`, `placeholder`, `empty*`, …).\n */\n readonly extraCopyKeys?: readonly string[]\n /**\n * Additional call names whose first string argument is user-visible copy\n * (defaults cover `toast*`, `alert`, `setError`, `new Error`).\n */\n readonly extraCopyCalls?: readonly string[]\n /**\n * Also read strings filling an object key named like copy\n * (`description: '…'`). OFF by default: measured as the tier that reports\n * system prompts, MCP tool descriptions and document templates — text no\n * reader ever sees. Turn it on when your data modules really do hold UI copy.\n */\n readonly includeObjectCopy?: boolean\n}\n\nexport interface EmptyStateOptions {\n /** Extra tags that count as an action (defaults: button, a, input, form, *Button, *Link, …). */\n readonly extraActionTags?: readonly string[]\n /** Extra props that count as an action (defaults: onClick, onSubmit, href, to, action, …). */\n readonly extraActionProps?: readonly string[]\n /** Extra regexes (as source strings) that identify empty-state copy. */\n readonly extraEmptyPatterns?: readonly string[]\n /**\n * Also report a zero-state that sits directly under a heading. OFF by\n * default: measured as the largest false-positive class — a titled section\n * with nothing in it labels a screen the reader is already oriented on, and a\n * detail page carrying four of them buries the one screen that is entirely\n * empty.\n */\n readonly reportSectionZeroStates?: boolean\n}\n\nexport interface SuccessOptions {\n /**\n * Callees that resolve on a failed request instead of throwing. `fetch` is the\n * default and the reason this check exists; add your own thin wrapper here.\n */\n readonly httpCalls?: readonly string[]\n /** Extra identifiers that mean \"the user has been told it worked\". */\n readonly extraSuccessSignals?: readonly string[]\n /**\n * Calls that inspect a response and throw on a bad status\n * (`assertOk(res)`). Their presence in the same function counts as checking.\n */\n readonly okGuards?: readonly string[]\n}\n\nexport interface SilentFailureOptions {\n /** Extra identifiers that count as surfacing a failure to the user. */\n readonly extraErrorSinks?: readonly string[]\n /**\n * Path substrings whose modules cannot reach a browser, and whose handlers\n * are therefore not this check's business. Defaults to react-router's\n * server-only conventions (`/.server/`, `/routes/api.`); pass `[]` to read\n * every module, at the measured cost of a large false-positive class\n * (best-effort telemetry, audit writes and cache fallbacks).\n */\n readonly readerlessPaths?: readonly string[]\n}\n\nexport interface ReachabilityOptions {\n /**\n * A react-router `routes.ts` (the `@react-router/dev/routes` shape:\n * `route()` / `index()` / `layout()` / `prefix()`).\n */\n readonly routeConfigFile?: string\n /** Route paths supplied directly, for a product on another router. */\n readonly routePaths?: readonly string[]\n /** Files that define navigation. Their path literals are the nav entries. */\n readonly navFiles?: readonly string[]\n /** Route paths (or prefixes ending in `/*`) that need no door — defaults to `api/*`. */\n readonly ignore?: readonly string[]\n /**\n * Treat a route whose module is not a `.tsx` file as a resource endpoint\n * rather than a screen. Default true — react-router resource routes are `.ts`.\n */\n readonly ignoreNonTsxRoutes?: boolean\n}\n\n/** What a product writes in `legibility.config.mjs`. */\nexport interface LegibilityConfig {\n /** Source directories to scan, recursively. At least one. */\n readonly srcDirs: readonly string[]\n /** Turn a check off wholesale. Prefer a per-line suppression with a reason. */\n readonly checks?: Partial<Record<LegibilityCheckId, boolean>>\n readonly vocabulary?: VocabularyOptions\n readonly emptyState?: EmptyStateOptions\n readonly success?: SuccessOptions\n readonly silentFailure?: SilentFailureOptions\n readonly reachability?: ReachabilityOptions\n /** Path substrings to skip, added to the defaults (tests, fixtures, generated). */\n readonly ignorePaths?: readonly string[]\n}\n\n/** A finding before file/line resolution — what a check returns. */\nexport interface RawFinding {\n readonly check: LegibilityCheckId\n readonly offset: number\n readonly message: string\n readonly remedy: string\n readonly evidence: string\n}\n","/**\n * Suppression: how a product says \"this one is deliberate\" without switching\n * the gate off.\n *\n * The design constraint is the whole reason this gate exists at all. A checker\n * that cannot be silenced per-line gets silenced per-repo — the config flag is\n * flipped once, in a rush, and nobody ever flips it back. So every finding is\n * individually suppressible; and because a silent suppression is\n * indistinguishable from a disabled check six months later, a suppression\n * without a written reason is ITSELF a finding, and does not suppress.\n *\n * // legibility-ignore engineering-vocabulary — \"conflict\" is the term of art\n * // a litigator uses; renaming it would make the screen less clear, not more\n * <p>Conflict check cleared</p>\n *\n * Forms:\n * - a comment on its own line suppresses the NEXT line that has content\n * - a trailing comment suppresses ITS OWN line\n * - `legibility-ignore-file <check>` suppresses the check for the whole file\n * - several checks may be named, comma-separated\n * - JSX comments (`{​/* … *​/}`) work, since they lex as comments too\n *\n * Honoured suppressions are returned, not swallowed: the report prints the\n * count and `--list-suppressions` prints every one with its reason, so the\n * exemptions stay as visible as the failures.\n */\n\nimport type { ScannedFile } from './scan'\nimport { LEGIBILITY_CHECKS, type LegibilityCheckId, type RawFinding } from './types'\n\n/** Minimum characters of prose after the separator for a reason to count. */\nconst MIN_REASON = 12\n\nconst DIRECTIVE_RE = /legibility-ignore(-file)?\\s+([^\\n]*)/\n\n/** One parsed directive. */\ninterface Directive {\n readonly checks: readonly LegibilityCheckId[]\n readonly reason: string\n /** Line the directive applies to; null for a whole-file directive. */\n readonly appliesToLine: number | null\n /** Line the directive itself is written on. */\n readonly line: number\n /** Named a check id that does not exist. */\n readonly unknownChecks: readonly string[]\n readonly hasReason: boolean\n}\n\nexport interface SuppressionIndex {\n /** Decide a finding: honoured suppression, or not. */\n reasonFor(check: LegibilityCheckId, line: number): string | null\n /** Findings the suppression syntax itself produced (missing reason, unknown check). */\n readonly selfFindings: readonly RawFinding[]\n}\n\nconst KNOWN = new Set<string>(LEGIBILITY_CHECKS)\n\n/** Parse every `legibility-ignore` directive in one lexed file. */\nexport function buildSuppressionIndex(file: ScannedFile): SuppressionIndex {\n const directives: Directive[] = []\n const selfFindings: RawFinding[] = []\n\n for (const segment of file.scan.segments) {\n if (segment.kind !== 'comment') continue\n const match = DIRECTIVE_RE.exec(segment.value)\n if (!match) continue\n\n const wholeFile = match[1] === '-file'\n const rest = (match[2] ?? '').trim()\n const { names, reason } = splitDirective(rest)\n const known = names.filter((name): name is LegibilityCheckId => KNOWN.has(name))\n const unknownChecks = names.filter((name) => !KNOWN.has(name))\n const directiveLine = file.positionAt(segment.start + match.index).line\n const hasReason = reason.length >= MIN_REASON\n\n const offset = segment.start + match.index\n if (names.length === 0) {\n selfFindings.push({\n check: 'suppression-without-reason',\n offset,\n message: 'legibility-ignore names no check, so it is unclear what it excuses.',\n remedy: `Name the check and give a reason: legibility-ignore <${LEGIBILITY_CHECKS.slice(0, 2).join('|')}|…> — why this one is right.`,\n evidence: `legibility-ignore ${rest}`.trim(),\n })\n continue\n }\n for (const unknown of unknownChecks) {\n selfFindings.push({\n check: 'suppression-without-reason',\n offset,\n message: `legibility-ignore names \"${unknown}\", which is not a check — it suppresses nothing.`,\n remedy: `Use one of: ${LEGIBILITY_CHECKS.join(', ')}.`,\n evidence: `legibility-ignore ${rest}`.trim(),\n })\n }\n if (!hasReason && known.length > 0) {\n selfFindings.push({\n check: 'suppression-without-reason',\n offset,\n message: `legibility-ignore ${known.join(', ')} gives no reason, so it does not suppress anything.`,\n remedy: `Write why this instance is right after a dash: legibility-ignore ${known[0]} — <reason, ${MIN_REASON}+ characters>.`,\n evidence: `legibility-ignore ${rest}`.trim(),\n })\n }\n if (known.length === 0) continue\n\n directives.push({\n checks: known,\n reason,\n hasReason,\n unknownChecks,\n line: directiveLine,\n appliesToLine: wholeFile ? null : targetLine(file, segment.start, directiveLine),\n })\n }\n\n const honoured = directives.filter((directive) => directive.hasReason)\n\n return {\n selfFindings,\n reasonFor(check: LegibilityCheckId, line: number): string | null {\n for (const directive of honoured) {\n if (!directive.checks.includes(check)) continue\n if (directive.appliesToLine === null || directive.appliesToLine === line) return directive.reason\n }\n return null\n },\n }\n}\n\n/**\n * Split `engineering-vocabulary, silent-failure — because …` into names and\n * reason. The separator is an em dash, `--`, `-` or `:`; anything before the\n * first separator is the (comma- or space-separated) check list.\n */\nfunction splitDirective(rest: string): { names: string[]; reason: string } {\n // The separator may open the directive (`legibility-ignore — because …`),\n // which names no check at all and must be reported as such rather than read\n // as a check called \"—\".\n const separator = /(?:^|\\s)(?:—|–|--|-|:)\\s|:\\s/.exec(rest)\n const head = separator ? rest.slice(0, separator.index) : rest\n const reason = separator ? rest.slice(separator.index + separator[0].length).trim() : ''\n const names = head\n .split(/[,\\s]+/)\n .map((name) => name.trim())\n .filter((name) => name.length > 0)\n return { names, reason }\n}\n\n/**\n * The line a non-file directive governs: its own line when code precedes it\n * (a trailing comment), otherwise the next line that has content.\n */\nfunction targetLine(file: ScannedFile, commentStart: number, commentLine: number): number {\n const lineStart = file.lineStarts[commentLine - 1] ?? 0\n const before = file.text.slice(lineStart, commentStart).replace(/[{/*]/g, '').trim()\n if (before.length > 0) return commentLine\n\n for (let line = commentLine + 1; line <= file.lineStarts.length; line++) {\n const start = file.lineStarts[line - 1]\n if (start === undefined) break\n const end = file.lineStarts[line] ?? file.text.length\n const content = file.text.slice(start, end).trim()\n if (content.length === 0) continue\n // Walk past a stacked continuation of the directive itself.\n if (/^(\\/\\/|\\*|\\{?\\/\\*)/.test(content) && !/legibility-ignore/.test(content)) continue\n if (/legibility-ignore/.test(content)) continue\n return line\n }\n return commentLine + 1\n}\n","/**\n * The report a product reads in its CI log.\n *\n * A gate is only as good as the sentence a developer reads at 6pm with a red\n * build. So every finding prints three things and never fewer: WHERE\n * (`file:line:col`, clickable in every terminal and editor), WHAT is wrong in\n * the reader's terms, and WHAT TO DO about it. A finding without a remedy is a\n * complaint, and complaints get suppressed rather than fixed.\n *\n * Honoured suppressions are counted in the summary and listed on request. A\n * suppression that nobody can see is a disabled check with extra steps.\n */\n\nimport { LEGIBILITY_CHECKS, type LegibilityCheckId, type LegibilityFinding, type LegibilityReport } from './types'\n\nexport interface FormatOptions {\n /** Print every honoured suppression with its reason. */\n readonly listSuppressions?: boolean\n /** Wrap check names in ANSI colour. Off by default — CI logs keep the bytes. */\n readonly colour?: boolean\n}\n\n/** One line per check, in the order they are declared. */\nconst CHECK_TITLES: Record<LegibilityCheckId, string> = {\n 'engineering-vocabulary': 'Engineering vocabulary on screen',\n 'dead-end-empty-state': 'Empty states with no next action',\n 'unchecked-success': 'Success reported without reading the response',\n 'silent-failure': 'Failures the reader never learns about',\n 'unreachable-capability': 'Capabilities with no door',\n 'suppression-without-reason': 'Suppressions that suppress nothing',\n}\n\nexport function formatLegibilityReport(report: LegibilityReport, options: FormatOptions = {}): string {\n const lines: string[] = []\n const bold = (text: string): string => (options.colour ? `\u001b[1m${text}\u001b[0m` : text)\n\n if (report.ok) {\n lines.push(\n `legibility OK — ${report.filesScanned} file(s), ${report.checksRun.length} check(s), no findings` +\n (report.suppressed.length > 0 ? ` (${report.suppressed.length} suppressed with a reason)` : ''),\n )\n if (options.listSuppressions) lines.push('', ...suppressionLines(report))\n return lines.join('\\n')\n }\n\n lines.push(\n `legibility FAILED — ${report.findings.length} finding(s) across ${report.filesScanned} file(s).`,\n 'Each one is a place a reader is left guessing. Fix it, or suppress that line with a written reason.',\n '',\n )\n\n for (const check of LEGIBILITY_CHECKS) {\n const findings = report.findings.filter((finding) => finding.check === check)\n if (findings.length === 0) continue\n lines.push(`${bold(CHECK_TITLES[check])} [${check}] ${findings.length}`)\n for (const finding of findings) lines.push(...findingLines(finding))\n lines.push('')\n }\n\n if (report.suppressed.length > 0) {\n lines.push(\n `${report.suppressed.length} finding(s) suppressed with a written reason` +\n (options.listSuppressions ? ':' : ' — run with --list-suppressions to read them.'),\n )\n if (options.listSuppressions) lines.push(...suppressionLines(report))\n lines.push('')\n }\n\n lines.push('Suppress one deliberate instance with a reason on the line above it:')\n lines.push(' // legibility-ignore <check> — why this instance is right')\n return lines.join('\\n')\n}\n\nfunction findingLines(finding: LegibilityFinding): string[] {\n return [\n ` ${finding.file}:${finding.line}:${finding.column}`,\n ` ${finding.message}`,\n ` → ${finding.remedy}`,\n ...(finding.evidence ? [` ${finding.evidence}`] : []),\n ]\n}\n\nfunction suppressionLines(report: LegibilityReport): string[] {\n return report.suppressed.map(\n (suppression) => ` ${suppression.file}:${suppression.line} ${suppression.check} — ${suppression.reason}`,\n )\n}\n\n/** The machine-readable form, for a product that posts findings somewhere. */\nexport function legibilityReportToJson(report: LegibilityReport): string {\n return JSON.stringify(report, null, 2)\n}\n","/**\n * `@tangle-network/agent-app/legibility` — the understandability gate a product\n * runs over its OWN source, in its OWN CI.\n *\n * ── Why this is code and not a document ──────────────────────────────────────\n *\n * `docs/product-surfaces.md` opened by reporting an audit that scored product\n * clarity 2-4/10 and concluded \"mechanism is not the gap; meaning is\". It was\n * well argued and it changed nothing: the verticals then shipped 11 of 21 empty\n * states with no next action, the word \"materialized\" in user-facing error copy,\n * a Settings page that answered \"Saved\" to a 404, and two correct deterministic\n * engines — a statute-citing contract redline and a court-deadline calculator\n * with 59 golden tests — that no navigation entry or link reached.\n *\n * Every one of those is mechanically detectable from source. So they are checks,\n * they name `file:line`, and they fail a build. The same shape as `/peer-floors`\n * and `/theme-contract`: a node-only checker the CONSUMER runs against its own\n * tree, because that is the only place the defect exists.\n *\n * ── The rule that keeps it alive ─────────────────────────────────────────────\n *\n * A gate that cannot be silenced per-instance gets silenced per-repo. So every\n * finding is individually suppressible — and a suppression with no written\n * reason is itself a finding, and suppresses nothing. Exemptions stay as visible\n * as failures; that is the whole difference between a gate and a flag someone\n * flipped in a rush.\n *\n * ── Usage ────────────────────────────────────────────────────────────────────\n *\n * import { checkLegibility, formatLegibilityReport } from '@tangle-network/agent-app/legibility'\n * const report = checkLegibility({ srcDirs: ['src'], reachability: { routeConfigFile: 'src/routes.ts', navFiles: ['src/components/sidebar.tsx'] } })\n * console.log(formatLegibilityReport(report))\n *\n * or, in CI, the bin: `agent-app-legibility-check --src src --routes src/routes.ts --nav src/components/sidebar.tsx`.\n */\n\nimport { checkEmptyStates } from './checks/empty-state'\nimport { checkReachability } from './checks/reachability'\nimport { checkSilentFailure } from './checks/silent-failure'\nimport { checkUncheckedSuccess } from './checks/success'\nimport { checkVocabulary } from './checks/vocabulary'\nimport { scanSources, type ScannedFile } from './scan'\nimport { buildSuppressionIndex } from './suppress'\nimport {\n LEGIBILITY_CHECKS,\n type LegibilityCheckId,\n type LegibilityConfig,\n type LegibilityFinding,\n type LegibilityReport,\n type LegibilitySuppression,\n type RawFinding,\n} from './types'\n\nexport { LEGIBILITY_CHECKS } from './types'\nexport type {\n BannedTerm,\n EmptyStateOptions,\n LegibilityCheckId,\n LegibilityConfig,\n LegibilityFinding,\n LegibilityReport,\n LegibilitySuppression,\n ReachabilityOptions,\n SilentFailureOptions,\n SuccessOptions,\n VocabularyOptions,\n} from './types'\nexport { formatLegibilityReport, legibilityReportToJson, type FormatOptions } from './report'\nexport { DEFAULT_BANNED_TERMS, COPY_KEYS, COPY_CALLS } from './checks/vocabulary'\n// `readerlessPaths` REPLACES this default rather than extending it, so a\n// consumer adding one server path needs the default to spread.\nexport { READERLESS_PATHS } from './checks/silent-failure'\nexport { parseRouteConfig, staticSegments, type RouteEntry } from './checks/reachability'\nexport { scanSources, scanFile, buildScannedFile, type ScannedFile } from './scan'\nexport {\n scanSource,\n type JsxAttribute,\n type JsxElement,\n type ScannedSource,\n type SegmentKind,\n type SourceSegment,\n} from './source'\n\n/** Is a check switched on? Every check is on unless the config turns it off. */\nfunction enabled(config: LegibilityConfig, check: LegibilityCheckId): boolean {\n return config.checks?.[check] !== false\n}\n\n/**\n * Run the gate over a product's source.\n *\n * Pure of process state apart from reading files: no `process.exit`, no logging.\n * The bin decides what to do with the report; a product embedding this in its\n * own tooling decides something else.\n */\nexport function checkLegibility(config: LegibilityConfig): LegibilityReport {\n if (config.srcDirs.length === 0) throw new Error('checkLegibility: srcDirs must name at least one directory')\n\n const files = scanSources(config.srcDirs, config.ignorePaths ?? [])\n const findings: LegibilityFinding[] = []\n const suppressed: LegibilitySuppression[] = []\n\n const collect = (file: ScannedFile, raw: readonly RawFinding[]): void => {\n const index = buildSuppressionIndex(file)\n for (const finding of [...raw, ...index.selfFindings]) {\n if (!enabled(config, finding.check)) continue\n const { line, column } = file.positionAt(finding.offset)\n const reason = finding.check === 'suppression-without-reason' ? null : index.reasonFor(finding.check, line)\n if (reason !== null) {\n suppressed.push({ check: finding.check, reason, file: file.display, line })\n continue\n }\n findings.push({\n check: finding.check,\n file: file.display,\n line,\n column,\n message: finding.message,\n remedy: finding.remedy,\n evidence: finding.evidence,\n })\n }\n }\n\n for (const file of files) {\n const raw: RawFinding[] = []\n if (enabled(config, 'engineering-vocabulary')) raw.push(...checkVocabulary(file, config.vocabulary))\n if (enabled(config, 'dead-end-empty-state')) raw.push(...checkEmptyStates(file, config.emptyState))\n if (enabled(config, 'unchecked-success')) raw.push(...checkUncheckedSuccess(file, config.success))\n if (enabled(config, 'silent-failure')) raw.push(...checkSilentFailure(file, config.silentFailure))\n collect(file, raw)\n }\n\n if (enabled(config, 'unreachable-capability') && config.reachability) {\n const result = checkReachability({ files, options: config.reachability })\n // The route config is the file the findings point INTO, so its own\n // suppression comments are the ones that govern them.\n if (result.routeFile) collect(result.routeFile, result.findings)\n else for (const finding of result.findings) findings.push(withoutFile(finding))\n }\n\n findings.sort(\n (left, right) => left.file.localeCompare(right.file) || left.line - right.line || left.column - right.column,\n )\n\n return {\n ok: findings.length === 0,\n findings,\n suppressed,\n filesScanned: files.length,\n checksRun: LEGIBILITY_CHECKS.filter((check) => enabled(config, check)),\n }\n}\n\n/** A finding with no file behind it — only possible for `routePaths` input. */\nfunction withoutFile(finding: RawFinding): LegibilityFinding {\n return {\n check: finding.check,\n file: '(routePaths)',\n line: 0,\n column: 0,\n message: finding.message,\n remedy: finding.remedy,\n evidence: finding.evidence,\n }\n}\n"],"mappings":"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","names":["i","element","readFileSync","matchingParen","matchingParen","matchingParen","lineStart"]}